diff --git a/routers/web/auth/linkaccount.go b/routers/web/auth/linkaccount.go index c624d896ca..36c798d4e7 100644 --- a/routers/web/auth/linkaccount.go +++ b/routers/web/auth/linkaccount.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/models/auth" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/optional" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/util" @@ -20,6 +21,7 @@ import ( "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/externalaccount" "code.gitea.io/gitea/services/forms" + user_service "code.gitea.io/gitea/services/user" ) var tplLinkAccount templates.TplName = "user/auth/link_account" @@ -310,6 +312,19 @@ func LinkAccountPostRegister(ctx *context.Context) { return } source := authSource.Cfg.(*oauth2.Source) + + isAdmin, isRestricted := getUserAdminAndRestrictedFromGroupClaims(source, &linkAccountData.GothUser) + if isAdmin.Has() || isRestricted.Has() { + opts := &user_service.UpdateOptions{ + IsAdmin: isAdmin, + IsRestricted: optional.Some(isRestricted.ValueOrDefault(setting.Service.DefaultUserIsRestricted)), + } + if err := user_service.UpdateUser(ctx, u, opts); err != nil { + ctx.ServerError("UpdateUser", err) + return + } + } + if err := syncGroupsToTeams(ctx, source, &linkAccountData.GothUser, u); err != nil { ctx.ServerError("SyncGroupsToTeams", err) return diff --git a/tests/integration/signin_test.go b/tests/integration/signin_test.go index ff35baae9d..ac90ddd363 100644 --- a/tests/integration/signin_test.go +++ b/tests/integration/signin_test.go @@ -4,6 +4,8 @@ package integration import ( + "fmt" + "hash/crc32" "net/http" "net/url" "strings" @@ -19,6 +21,7 @@ import ( "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers" "code.gitea.io/gitea/routers/web/auth" + "code.gitea.io/gitea/services/auth/source/oauth2" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/tests" @@ -199,3 +202,49 @@ func TestRequireSignInView(t *testing.T) { assert.Equal(t, "/user/login?redirect_to=%2Fuser2%2Frepo1%2Fsrc%2Fbranch%2Fmaster", resp.Header().Get("Location")) }) } + +func TestLinkAccountSignupAppliesRestrictedClaim(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + authName := fmt.Sprintf("link-account-oidc-%s", t.Name()) + addOAuth2Source(t, authName, oauth2.Source{ + Provider: "gitea", + GroupClaimName: "groups", + RestrictedGroup: "link-account-restricted", + }) + + ctx := t.Context() + authSource, err := auth_model.GetActiveOAuth2SourceByAuthName(ctx, authName) + require.NoError(t, err) + suffix := crc32.ChecksumIEEE([]byte(t.Name())) + userName := fmt.Sprintf("linkclaim%x", suffix) + userEmail := fmt.Sprintf("%s@example.com", userName) + gothUser := goth.User{ + Provider: authSource.Cfg.(*oauth2.Source).Provider, + UserID: userName, + Email: userEmail, + RawData: map[string]any{ + "groups": []string{"link-account-restricted"}, + }, + } + + defer web.RouteMockReset() + web.RouteMock(web.MockAfterMiddlewares, func(ctx *context.Context) { + _ = auth.Oauth2SetLinkAccountData(ctx, auth.LinkAccountData{ + AuthSourceID: authSource.ID, + GothUser: gothUser, + }) + }) + + session := emptyTestSession(t) + req := NewRequestWithValues(t, "POST", "/user/link_account_signup", map[string]string{ + "user_name": userName, + "email": userEmail, + "password": "pass123456", + "retype": "pass123456", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + + createdUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: userName}) + assert.True(t, createdUser.IsRestricted) +}