aboutsummaryrefslogtreecommitdiffstats
path: root/routers
diff options
context:
space:
mode:
Diffstat (limited to 'routers')
-rw-r--r--routers/api/v1/api.go4
-rw-r--r--routers/api/v1/repo/fork.go2
-rw-r--r--routers/api/v1/repo/repo.go2
-rw-r--r--routers/web/admin/auths.go2
-rw-r--r--routers/web/auth/linkaccount.go7
-rw-r--r--routers/web/auth/oauth.go95
-rw-r--r--routers/web/repo/issue_label.go2
-rw-r--r--routers/web/repo/setting.go2
-rw-r--r--routers/web/web.go2
9 files changed, 81 insertions, 37 deletions
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 5f57977c29..1d2f8b18e0 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -507,7 +507,7 @@ func orgAssignment(args ...bool) func(ctx *context.APIContext) {
var err error
if assignOrg {
- ctx.Org.Organization, err = organization.GetOrgByName(ctx.Params(":org"))
+ ctx.Org.Organization, err = organization.GetOrgByName(ctx, ctx.Params(":org"))
if err != nil {
if organization.IsErrOrgNotExist(err) {
redirectUserID, err := user_model.LookupUserRedirect(ctx.Params(":org"))
@@ -687,7 +687,7 @@ func Routes(ctx gocontext.Context) *web.Route {
}
// Get user from session if logged in.
- m.Use(context.APIAuth(group))
+ m.Use(auth.APIAuth(group))
m.Use(context.ToggleAPI(&context.ToggleOptions{
SignInRequired: setting.Service.RequireSignInView,
diff --git a/routers/api/v1/repo/fork.go b/routers/api/v1/repo/fork.go
index e4c7eb7041..5b564a8066 100644
--- a/routers/api/v1/repo/fork.go
+++ b/routers/api/v1/repo/fork.go
@@ -108,7 +108,7 @@ func CreateFork(ctx *context.APIContext) {
if form.Organization == nil {
forker = ctx.Doer
} else {
- org, err := organization.GetOrgByName(*form.Organization)
+ org, err := organization.GetOrgByName(ctx, *form.Organization)
if err != nil {
if organization.IsErrOrgNotExist(err) {
ctx.Error(http.StatusUnprocessableEntity, "", err)
diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go
index e0cae5f82c..1426d1dbcc 100644
--- a/routers/api/v1/repo/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -468,7 +468,7 @@ func CreateOrgRepo(ctx *context.APIContext) {
// "403":
// "$ref": "#/responses/forbidden"
opt := web.GetForm(ctx).(*api.CreateRepoOption)
- org, err := organization.GetOrgByName(ctx.Params(":org"))
+ org, err := organization.GetOrgByName(ctx, ctx.Params(":org"))
if err != nil {
if organization.IsErrOrgNotExist(err) {
ctx.Error(http.StatusUnprocessableEntity, "", err)
diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go
index 1bc166902c..8ce45720fe 100644
--- a/routers/web/admin/auths.go
+++ b/routers/web/admin/auths.go
@@ -204,6 +204,8 @@ func parseOAuth2Config(form forms.AuthenticationForm) *oauth2.Source {
GroupClaimName: form.Oauth2GroupClaimName,
RestrictedGroup: form.Oauth2RestrictedGroup,
AdminGroup: form.Oauth2AdminGroup,
+ GroupTeamMap: form.Oauth2GroupTeamMap,
+ GroupTeamMapRemoval: form.Oauth2GroupTeamMapRemoval,
}
}
diff --git a/routers/web/auth/linkaccount.go b/routers/web/auth/linkaccount.go
index 6c409c6b9d..47a0daa06d 100644
--- a/routers/web/auth/linkaccount.go
+++ b/routers/web/auth/linkaccount.go
@@ -16,6 +16,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
auth_service "code.gitea.io/gitea/services/auth"
+ "code.gitea.io/gitea/services/auth/source/oauth2"
"code.gitea.io/gitea/services/externalaccount"
"code.gitea.io/gitea/services/forms"
@@ -267,5 +268,11 @@ func LinkAccountPostRegister(ctx *context.Context) {
return
}
+ source := authSource.Cfg.(*oauth2.Source)
+ if err := syncGroupsToTeams(ctx, source, &gothUser, u); err != nil {
+ ctx.ServerError("SyncGroupsToTeams", err)
+ return
+ }
+
handleSignIn(ctx, u, false)
}
diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go
index be60a0c73b..a11417da16 100644
--- a/routers/web/auth/oauth.go
+++ b/routers/web/auth/oauth.go
@@ -17,7 +17,9 @@ import (
"code.gitea.io/gitea/models/auth"
org_model "code.gitea.io/gitea/models/organization"
user_model "code.gitea.io/gitea/models/user"
+ auth_module "code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
@@ -27,6 +29,7 @@ import (
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/modules/web/middleware"
auth_service "code.gitea.io/gitea/services/auth"
+ source_service "code.gitea.io/gitea/services/auth/source"
"code.gitea.io/gitea/services/auth/source/oauth2"
"code.gitea.io/gitea/services/externalaccount"
"code.gitea.io/gitea/services/forms"
@@ -963,12 +966,19 @@ func SignInOAuthCallback(ctx *context.Context) {
IsActive: util.OptionalBoolOf(!setting.OAuth2Client.RegisterEmailConfirm),
}
- setUserGroupClaims(authSource, u, &gothUser)
+ source := authSource.Cfg.(*oauth2.Source)
+
+ setUserAdminAndRestrictedFromGroupClaims(source, u, &gothUser)
if !createAndHandleCreatedUser(ctx, base.TplName(""), nil, u, overwriteDefault, &gothUser, setting.OAuth2Client.AccountLinking != setting.OAuth2AccountLinkingDisabled) {
// error already handled
return
}
+
+ if err := syncGroupsToTeams(ctx, source, &gothUser, u); err != nil {
+ ctx.ServerError("SyncGroupsToTeams", err)
+ return
+ }
} else {
// no existing user is found, request attach or new account
showLinkingLogin(ctx, gothUser)
@@ -979,7 +989,7 @@ func SignInOAuthCallback(ctx *context.Context) {
handleOAuth2SignIn(ctx, authSource, u, gothUser)
}
-func claimValueToStringSlice(claimValue interface{}) []string {
+func claimValueToStringSet(claimValue interface{}) container.Set[string] {
var groups []string
switch rawGroup := claimValue.(type) {
@@ -993,37 +1003,45 @@ func claimValueToStringSlice(claimValue interface{}) []string {
str := fmt.Sprintf("%s", rawGroup)
groups = strings.Split(str, ",")
}
- return groups
+ return container.SetOf(groups...)
}
-func setUserGroupClaims(loginSource *auth.Source, u *user_model.User, gothUser *goth.User) bool {
- source := loginSource.Cfg.(*oauth2.Source)
- if source.GroupClaimName == "" || (source.AdminGroup == "" && source.RestrictedGroup == "") {
- return false
+func syncGroupsToTeams(ctx *context.Context, source *oauth2.Source, gothUser *goth.User, u *user_model.User) error {
+ if source.GroupTeamMap != "" || source.GroupTeamMapRemoval {
+ groupTeamMapping, err := auth_module.UnmarshalGroupTeamMapping(source.GroupTeamMap)
+ if err != nil {
+ return err
+ }
+
+ groups := getClaimedGroups(source, gothUser)
+
+ if err := source_service.SyncGroupsToTeams(ctx, u, groups, groupTeamMapping, source.GroupTeamMapRemoval); err != nil {
+ return err
+ }
}
+ return nil
+}
+
+func getClaimedGroups(source *oauth2.Source, gothUser *goth.User) container.Set[string] {
groupClaims, has := gothUser.RawData[source.GroupClaimName]
if !has {
- return false
+ return nil
}
- groups := claimValueToStringSlice(groupClaims)
+ return claimValueToStringSet(groupClaims)
+}
+
+func setUserAdminAndRestrictedFromGroupClaims(source *oauth2.Source, u *user_model.User, gothUser *goth.User) bool {
+ groups := getClaimedGroups(source, gothUser)
wasAdmin, wasRestricted := u.IsAdmin, u.IsRestricted
if source.AdminGroup != "" {
- u.IsAdmin = false
+ u.IsAdmin = groups.Contains(source.AdminGroup)
}
if source.RestrictedGroup != "" {
- u.IsRestricted = false
- }
-
- for _, g := range groups {
- if source.AdminGroup != "" && g == source.AdminGroup {
- u.IsAdmin = true
- } else if source.RestrictedGroup != "" && g == source.RestrictedGroup {
- u.IsRestricted = true
- }
+ u.IsRestricted = groups.Contains(source.RestrictedGroup)
}
return wasAdmin != u.IsAdmin || wasRestricted != u.IsRestricted
@@ -1070,6 +1088,15 @@ func handleOAuth2SignIn(ctx *context.Context, source *auth.Source, u *user_model
needs2FA = err == nil
}
+ oauth2Source := source.Cfg.(*oauth2.Source)
+ groupTeamMapping, err := auth_module.UnmarshalGroupTeamMapping(oauth2Source.GroupTeamMap)
+ if err != nil {
+ ctx.ServerError("UnmarshalGroupTeamMapping", err)
+ return
+ }
+
+ groups := getClaimedGroups(oauth2Source, &gothUser)
+
// If this user is enrolled in 2FA and this source doesn't override it,
// we can't sign the user in just yet. Instead, redirect them to the 2FA authentication page.
if !needs2FA {
@@ -1088,7 +1115,7 @@ func handleOAuth2SignIn(ctx *context.Context, source *auth.Source, u *user_model
u.SetLastLogin()
// Update GroupClaims
- changed := setUserGroupClaims(source, u, &gothUser)
+ changed := setUserAdminAndRestrictedFromGroupClaims(oauth2Source, u, &gothUser)
cols := []string{"last_login_unix"}
if changed {
cols = append(cols, "is_admin", "is_restricted")
@@ -1099,6 +1126,13 @@ func handleOAuth2SignIn(ctx *context.Context, source *auth.Source, u *user_model
return
}
+ if oauth2Source.GroupTeamMap != "" || oauth2Source.GroupTeamMapRemoval {
+ if err := source_service.SyncGroupsToTeams(ctx, u, groups, groupTeamMapping, oauth2Source.GroupTeamMapRemoval); err != nil {
+ ctx.ServerError("SyncGroupsToTeams", err)
+ return
+ }
+ }
+
// update external user information
if err := externalaccount.UpdateExternalUser(u, gothUser); err != nil {
if !errors.Is(err, util.ErrNotExist) {
@@ -1121,7 +1155,7 @@ func handleOAuth2SignIn(ctx *context.Context, source *auth.Source, u *user_model
return
}
- changed := setUserGroupClaims(source, u, &gothUser)
+ changed := setUserAdminAndRestrictedFromGroupClaims(oauth2Source, u, &gothUser)
if changed {
if err := user_model.UpdateUserCols(ctx, u, "is_admin", "is_restricted"); err != nil {
ctx.ServerError("UpdateUserCols", err)
@@ -1129,6 +1163,13 @@ func handleOAuth2SignIn(ctx *context.Context, source *auth.Source, u *user_model
}
}
+ if oauth2Source.GroupTeamMap != "" || oauth2Source.GroupTeamMapRemoval {
+ if err := source_service.SyncGroupsToTeams(ctx, u, groups, groupTeamMapping, oauth2Source.GroupTeamMapRemoval); err != nil {
+ ctx.ServerError("SyncGroupsToTeams", err)
+ return
+ }
+ }
+
if err := updateSession(ctx, nil, map[string]interface{}{
// User needs to use 2FA, save data and redirect to 2FA page.
"twofaUid": u.ID,
@@ -1188,15 +1229,9 @@ func oAuth2UserLoginCallback(authSource *auth.Source, request *http.Request, res
}
if oauth2Source.RequiredClaimValue != "" {
- groups := claimValueToStringSlice(claimInterface)
- found := false
- for _, group := range groups {
- if group == oauth2Source.RequiredClaimValue {
- found = true
- break
- }
- }
- if !found {
+ groups := claimValueToStringSet(claimInterface)
+
+ if !groups.Contains(oauth2Source.RequiredClaimValue) {
return nil, goth.User{}, user_model.ErrUserProhibitLogin{Name: gothUser.UserID}
}
}
diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go
index 01421dc927..66e8920bd9 100644
--- a/routers/web/repo/issue_label.go
+++ b/routers/web/repo/issue_label.go
@@ -78,7 +78,7 @@ func RetrieveLabels(ctx *context.Context) {
}
ctx.Data["OrgLabels"] = orgLabels
- org, err := organization.GetOrgByName(ctx.Repo.Owner.LowerName)
+ org, err := organization.GetOrgByName(ctx, ctx.Repo.Owner.LowerName)
if err != nil {
ctx.ServerError("GetOrgByName", err)
return
diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go
index 2cc263e5bb..5c30795f22 100644
--- a/routers/web/repo/setting.go
+++ b/routers/web/repo/setting.go
@@ -1006,7 +1006,7 @@ func AddTeamPost(ctx *context.Context) {
return
}
- team, err := organization.OrgFromUser(ctx.Repo.Owner).GetTeam(name)
+ team, err := organization.OrgFromUser(ctx.Repo.Owner).GetTeam(ctx, name)
if err != nil {
if organization.IsErrTeamNotExist(err) {
ctx.Flash.Error(ctx.Tr("form.team_not_exist"))
diff --git a/routers/web/web.go b/routers/web/web.go
index 6898956053..88e27ad678 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -203,7 +203,7 @@ func Routes(ctx gocontext.Context) *web.Route {
}
// Get user from session if logged in.
- common = append(common, context.Auth(group))
+ common = append(common, auth_service.Auth(group))
// GetHead allows a HEAD request redirect to GET if HEAD method is not defined for that route
common = append(common, middleware.GetHead)