Skip to content

Commit b3c084c

Browse files
committed
Merge master-IB#1105051 into main-IB#1105051
2 parents b7c6457 + fe6ae27 commit b3c084c

File tree

28 files changed

+201
-44
lines changed

28 files changed

+201
-44
lines changed

cmd/admin.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ func runChangePassword(c *cli.Context) error {
471471
return err
472472
}
473473

474-
if err = user_model.UpdateUserCols(db.DefaultContext, user, "passwd", "passwd_hash_algo", "salt"); err != nil {
474+
if err = user_model.UpdateUserCols(db.DefaultContext, user, false, "passwd", "passwd_hash_algo", "salt"); err != nil {
475475
return err
476476
}
477477

custom/conf/app.example.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,9 @@ PATH =
630630
;; Allow registration only using third-party services, it works only when DISABLE_REGISTRATION is false
631631
;ALLOW_ONLY_EXTERNAL_REGISTRATION = false
632632
;;
633+
;; Disable local user management (i.e. when user data and password comes from LDAP and should not be changed locally in gitea).
634+
;DISABLE_LOCAL_USER_MANAGEMENT = false
635+
;;
633636
;; User must sign in to view anything.
634637
;REQUIRE_SIGNIN_VIEW = false
635638
;;

docs/content/doc/advanced/config-cheat-sheet.en-us.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ Certain queues have defaults that override the defaults set in `[queue]` (this o
596596
- `ALLOW_ONLY_INTERNAL_REGISTRATION`: **false** Set to true to force registration only via Gitea.
597597
- `ALLOW_ONLY_EXTERNAL_REGISTRATION`: **false** Set to true to force registration only using third-party services.
598598
- `NO_REPLY_ADDRESS`: **noreply.DOMAIN** Value for the domain part of the user's email address in the Git log if user has set KeepEmailPrivate to true. DOMAIN resolves to the value in server.DOMAIN.
599+
- `DISABLE_LOCAL_USER_MANAGEMENT`: **false** Set to true to disable local user management in gitea (i.e. when users are managed in LDAP).
599600
The user's email will be replaced with a concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS.
600601
- `USER_DELETE_WITH_COMMENTS_MAX_TIME`: **0** Minimum amount of time a user must exist before comments are kept when the user is deleted.
601602
- `VALID_SITE_URL_SCHEMES`: **http, https**: Valid site url schemes for user profiles

models/repo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ func CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_
508508

509509
// Remember visibility preference.
510510
u.LastRepoVisibility = repo.IsPrivate
511-
if err = user_model.UpdateUserColsEngine(db.GetEngine(ctx), u, "last_repo_visibility"); err != nil {
511+
if err = user_model.UpdateUserColsEngine(db.GetEngine(ctx), u, false, "last_repo_visibility"); err != nil {
512512
return fmt.Errorf("updateUser: %v", err)
513513
}
514514

models/user/email_address.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ func updateActivation(e db.Engine, email *EmailAddress, activate bool) error {
303303
if _, err := e.ID(email.ID).Cols("is_activated").Update(email); err != nil {
304304
return err
305305
}
306-
return UpdateUserColsEngine(e, user, "rands")
306+
return UpdateUserColsEngine(e, user, false, "rands")
307307
}
308308

309309
// MakeEmailPrimary sets primary email address of given user.
@@ -513,7 +513,7 @@ func ActivateUserEmail(userID int64, email string, activate bool) (err error) {
513513
if user.Rands, err = GetUserSalt(); err != nil {
514514
return fmt.Errorf("unable to generate salt: %v", err)
515515
}
516-
if err = UpdateUserColsEngine(sess, &user, "is_active", "rands"); err != nil {
516+
if err = UpdateUserColsEngine(sess, &user, false, "is_active", "rands"); err != nil {
517517
return fmt.Errorf("unable to updateUserCols() for user ID: %d: %v", userID, err)
518518
}
519519
}

models/user/user.go

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -206,13 +206,13 @@ func (u *User) SetLastLogin() {
206206
// UpdateUserDiffViewStyle updates the users diff view style
207207
func UpdateUserDiffViewStyle(u *User, style string) error {
208208
u.DiffViewStyle = style
209-
return UpdateUserCols(db.DefaultContext, u, "diff_view_style")
209+
return UpdateUserCols(db.DefaultContext, u, false, "diff_view_style")
210210
}
211211

212212
// UpdateUserTheme updates a users' theme irrespective of the site wide theme
213213
func UpdateUserTheme(u *User, themeName string) error {
214214
u.Theme = themeName
215-
return UpdateUserCols(db.DefaultContext, u, "theme")
215+
return UpdateUserCols(db.DefaultContext, u, false, "theme")
216216
}
217217

218218
// GetEmail returns an noreply email, if the user has set to keep his
@@ -502,7 +502,7 @@ func (u *User) EmailNotifications() string {
502502
// SetEmailNotifications sets the user's email notification preference
503503
func SetEmailNotifications(u *User, set string) error {
504504
u.EmailNotificationsPreference = set
505-
if err := UpdateUserCols(db.DefaultContext, u, "email_notifications_preference"); err != nil {
505+
if err := UpdateUserCols(db.DefaultContext, u, false, "email_notifications_preference"); err != nil {
506506
log.Error("SetEmailNotifications: %v", err)
507507
return err
508508
}
@@ -827,7 +827,43 @@ func validateUser(u *User) error {
827827
return ValidateEmail(u.Email)
828828
}
829829

830+
// updateUserAllowed is used to block updating selected user fields when local user managemement is disabled.
831+
func updateUserAllowed(u *User) error {
832+
// Don't allow changes of selected user fields if local user management is disabled.
833+
if setting.Service.DisableLocalUserManagement && (u.Type == UserTypeIndividual) {
834+
if currUser, err := GetUserByID(u.ID); err == nil {
835+
if currUser.Name != u.Name {
836+
return fmt.Errorf("cannot change user %s username; local user management disabled", u.Name)
837+
}
838+
if (currUser.LoginSource != u.LoginSource) || (currUser.LoginName != u.LoginName) {
839+
return fmt.Errorf("cannot change user %s login; local user management disabled", u.Name)
840+
}
841+
if currUser.FullName != u.FullName {
842+
return fmt.Errorf("cannot change user %s full name; local user management disabled", u.Name)
843+
}
844+
if currUser.Email != u.Email {
845+
return fmt.Errorf("cannot change user %s e-mail; local user management disabled", u.Name)
846+
}
847+
if (currUser.Passwd != u.Passwd) || (currUser.PasswdHashAlgo != u.PasswdHashAlgo) {
848+
return fmt.Errorf("cannot change user %s password; local user management disabled", u.Name)
849+
}
850+
if currUser.IsActive != u.IsActive {
851+
return fmt.Errorf("cannot change user %s activity; local user management disabled", u.Name)
852+
}
853+
if currUser.IsAdmin != u.IsAdmin {
854+
return fmt.Errorf("cannot change user %s admin permission; local user management disabled", u.Name)
855+
}
856+
} else {
857+
return err
858+
}
859+
}
860+
return nil
861+
}
862+
830863
func updateUser(ctx context.Context, u *User, changePrimaryEmail bool) error {
864+
if err := updateUserAllowed(u); err != nil {
865+
return err
866+
}
831867
if err := validateUser(u); err != nil {
832868
return err
833869
}
@@ -872,16 +908,21 @@ func UpdateUser(u *User, emailChanged bool) error {
872908
}
873909

874910
// UpdateUserCols update user according special columns
875-
func UpdateUserCols(ctx context.Context, u *User, cols ...string) error {
876-
return updateUserCols(db.GetEngine(ctx), u, cols...)
911+
func UpdateUserCols(ctx context.Context, u *User, force bool, cols ...string) error {
912+
return updateUserCols(db.GetEngine(ctx), u, force, cols...)
877913
}
878914

879915
// UpdateUserColsEngine update user according special columns
880-
func UpdateUserColsEngine(e db.Engine, u *User, cols ...string) error {
881-
return updateUserCols(e, u, cols...)
916+
func UpdateUserColsEngine(e db.Engine, u *User, force bool, cols ...string) error {
917+
return updateUserCols(e, u, force, cols...)
882918
}
883919

884-
func updateUserCols(e db.Engine, u *User, cols ...string) error {
920+
func updateUserCols(e db.Engine, u *User, force bool, cols ...string) error {
921+
if !force {
922+
if err := updateUserAllowed(u); err != nil {
923+
return err
924+
}
925+
}
885926
if err := validateUser(u); err != nil {
886927
return err
887928
}

modules/setting/service.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ var Service = struct {
3030
DisableRegistration bool
3131
AllowOnlyInternalRegistration bool
3232
AllowOnlyExternalRegistration bool
33+
DisableLocalUserManagement bool
3334
ShowRegistrationButton bool
3435
ShowMilestonesDashboardPage bool
3536
RequireSignInView bool
@@ -115,6 +116,7 @@ func newService() {
115116
} else {
116117
Service.RegisterManualConfirm = false
117118
}
119+
Service.DisableLocalUserManagement = sec.Key("DISABLE_LOCAL_USER_MANAGEMENT").MustBool()
118120
Service.EmailDomainWhitelist = sec.Key("EMAIL_DOMAIN_WHITELIST").Strings(",")
119121
Service.EmailDomainBlocklist = sec.Key("EMAIL_DOMAIN_BLOCKLIST").Strings(",")
120122
Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration))

modules/templates/helper.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ func NewFuncMap() []template.FuncMap {
239239
"DisableImportLocal": func() bool {
240240
return !setting.ImportLocalPaths
241241
},
242+
"DisableLocalUserManagement": func() bool {
243+
return setting.Service.DisableLocalUserManagement
244+
},
242245
"Dict": func(values ...interface{}) (map[string]interface{}, error) {
243246
if len(values)%2 != 0 {
244247
return nil, errors.New("invalid dict call")

routers/api/v1/org/org.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ func Edit(ctx *context.APIContext) {
346346
if form.RepoAdminChangeTeamAccess != nil {
347347
org.RepoAdminChangeTeamAccess = *form.RepoAdminChangeTeamAccess
348348
}
349-
if err := user_model.UpdateUserCols(db.DefaultContext, org.AsUser(),
349+
if err := user_model.UpdateUserCols(db.DefaultContext, org.AsUser(), false,
350350
"full_name", "description", "website", "location",
351351
"visibility", "repo_admin_change_team_access",
352352
); err != nil {

routers/web/admin/auths.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ func Authentications(ctx *context.Context) {
4949
ctx.Data["PageIsAdmin"] = true
5050
ctx.Data["PageIsAdminAuthentications"] = true
5151

52+
// No access to this page if local user management is disabled.
53+
if setting.Service.DisableLocalUserManagement {
54+
ctx.ServerError("Authentications", fmt.Errorf("access to Authentications function denied; local user management disabled"))
55+
return
56+
}
57+
5258
var err error
5359
ctx.Data["Sources"], err = auth.Sources()
5460
if err != nil {
@@ -111,6 +117,12 @@ func NewAuthSource(ctx *context.Context) {
111117
ctx.Data["SSPISeparatorReplacement"] = "_"
112118
ctx.Data["SSPIDefaultLanguage"] = ""
113119

120+
// No access to this page if local user management is disabled.
121+
if setting.Service.DisableLocalUserManagement {
122+
ctx.ServerError("NewAuthSource", fmt.Errorf("access to NewAuthSource function denied; local user management disabled"))
123+
return
124+
}
125+
114126
// only the first as default
115127
ctx.Data["oauth2_provider"] = oauth2providers[0]
116128

@@ -240,6 +252,12 @@ func NewAuthSourcePost(ctx *context.Context) {
240252
ctx.Data["SSPISeparatorReplacement"] = "_"
241253
ctx.Data["SSPIDefaultLanguage"] = ""
242254

255+
// Don't allow to create auth source if local user management is disabled.
256+
if setting.Service.DisableLocalUserManagement {
257+
ctx.ServerError("NewAuthSourcePost", fmt.Errorf("cannot create auth source; local user management disabled"))
258+
return
259+
}
260+
243261
hasTLS := false
244262
var config convert.Conversion
245263
switch auth.Type(form.Type) {
@@ -314,6 +332,12 @@ func EditAuthSource(ctx *context.Context) {
314332
oauth2providers := oauth2.GetOAuth2Providers()
315333
ctx.Data["OAuth2Providers"] = oauth2providers
316334

335+
// No access to this page if local user management is disabled.
336+
if setting.Service.DisableLocalUserManagement {
337+
ctx.ServerError("EditAuthSource", fmt.Errorf("access to EditAuthSource page denied; local user management disabled"))
338+
return
339+
}
340+
317341
source, err := auth.GetSourceByID(ctx.ParamsInt64(":authid"))
318342
if err != nil {
319343
ctx.ServerError("auth.GetSourceByID", err)
@@ -349,6 +373,12 @@ func EditAuthSourcePost(ctx *context.Context) {
349373
oauth2providers := oauth2.GetOAuth2Providers()
350374
ctx.Data["OAuth2Providers"] = oauth2providers
351375

376+
// Don't allow to update auth source if local user management is disabled.
377+
if setting.Service.DisableLocalUserManagement {
378+
ctx.ServerError("EditAuthSourcePost", fmt.Errorf("cannot update auth source; local user management disabled"))
379+
return
380+
}
381+
352382
source, err := auth.GetSourceByID(ctx.ParamsInt64(":authid"))
353383
if err != nil {
354384
ctx.ServerError("auth.GetSourceByID", err)

routers/web/admin/emails.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package admin
66

77
import (
88
"bytes"
9+
"fmt"
910
"net/http"
1011
"net/url"
1112

@@ -28,6 +29,12 @@ func Emails(ctx *context.Context) {
2829
ctx.Data["PageIsAdmin"] = true
2930
ctx.Data["PageIsAdminEmails"] = true
3031

32+
// No access to this page if local user management is disabled.
33+
if setting.Service.DisableLocalUserManagement {
34+
ctx.ServerError("Emails", fmt.Errorf("access to Emails function denied; local user management disabled"))
35+
return
36+
}
37+
3138
opts := &user_model.SearchEmailOptions{
3239
ListOptions: db.ListOptions{
3340
PageSize: setting.UI.Admin.UserPagingNum,
@@ -112,6 +119,12 @@ func isKeywordValid(keyword string) bool {
112119
// ActivateEmail serves a POST request for activating/deactivating a user's email
113120
func ActivateEmail(ctx *context.Context) {
114121

122+
// Don't allow to activate/deactivate emails if local user management is disabled.
123+
if setting.Service.DisableLocalUserManagement {
124+
ctx.ServerError("ActivateEmail", fmt.Errorf("cannot activate email; local user management disabled"))
125+
return
126+
}
127+
115128
truefalse := map[string]bool{"1": true, "0": false}
116129

117130
uid := ctx.FormInt64("uid")

routers/web/admin/users.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package admin
77

88
import (
9+
"fmt"
910
"net/http"
1011
"net/url"
1112
"strconv"
@@ -81,6 +82,12 @@ func NewUser(ctx *context.Context) {
8182

8283
ctx.Data["login_type"] = "0-0"
8384

85+
// No access to this page if local user management is disabled.
86+
if setting.Service.DisableLocalUserManagement {
87+
ctx.ServerError("NewUser", fmt.Errorf("access to NewUser function denied; local user management disabled"))
88+
return
89+
}
90+
8491
sources, err := auth.Sources()
8592
if err != nil {
8693
ctx.ServerError("auth.Sources", err)
@@ -100,6 +107,11 @@ func NewUserPost(ctx *context.Context) {
100107
ctx.Data["PageIsAdminUsers"] = true
101108
ctx.Data["DefaultUserVisibilityMode"] = setting.Service.DefaultUserVisibilityMode
102109

110+
if setting.Service.DisableLocalUserManagement {
111+
ctx.ServerError("NewUserPost", fmt.Errorf("cannot create new user; local user management disabled"))
112+
return
113+
}
114+
103115
sources, err := auth.Sources()
104116
if err != nil {
105117
ctx.ServerError("auth.Sources", err)
@@ -278,6 +290,13 @@ func EditUserPost(ctx *context.Context) {
278290

279291
if len(form.Password) > 0 && (u.IsLocal() || u.IsOAuth2()) {
280292
var err error
293+
294+
// Don't allow password changes if local user management is disabled.
295+
if setting.Service.DisableLocalUserManagement {
296+
ctx.ServerError("UpdateUser", fmt.Errorf("cannot change %s password; local user management disabled", u.Name))
297+
return
298+
}
299+
281300
if len(form.Password) < setting.MinPasswordLength {
282301
ctx.Data["Err_Password"] = true
283302
ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplUserEdit, &form)

routers/web/auth/auth.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func resetLocale(ctx *context.Context, u *user_model.User) error {
107107
// If the user does not have a locale set, we save the current one.
108108
if len(u.Language) == 0 {
109109
u.Language = ctx.Locale.Language()
110-
if err := user_model.UpdateUserCols(db.DefaultContext, u, "language"); err != nil {
110+
if err := user_model.UpdateUserCols(db.DefaultContext, u, false, "language"); err != nil {
111111
return err
112112
}
113113
}
@@ -333,7 +333,7 @@ func handleSignInFull(ctx *context.Context, u *user_model.User, remember bool, o
333333
// If the user does not have a locale set, we save the current one.
334334
if len(u.Language) == 0 {
335335
u.Language = ctx.Locale.Language()
336-
if err := user_model.UpdateUserCols(db.DefaultContext, u, "language"); err != nil {
336+
if err := user_model.UpdateUserCols(db.DefaultContext, u, false, "language"); err != nil {
337337
ctx.ServerError("UpdateUserCols Language", fmt.Errorf("Error updating user language [user: %d, locale: %s]", u.ID, u.Language))
338338
return setting.AppSubURL + "/"
339339
}
@@ -350,7 +350,7 @@ func handleSignInFull(ctx *context.Context, u *user_model.User, remember bool, o
350350

351351
// Register last login
352352
u.SetLastLogin()
353-
if err := user_model.UpdateUserCols(db.DefaultContext, u, "last_login_unix"); err != nil {
353+
if err := user_model.UpdateUserCols(db.DefaultContext, u, false, "last_login_unix"); err != nil {
354354
ctx.ServerError("UpdateUserCols", err)
355355
return setting.AppSubURL + "/"
356356
}
@@ -603,7 +603,7 @@ func handleUserCreated(ctx *context.Context, u *user_model.User, gothUser *goth.
603603
u.IsAdmin = true
604604
u.IsActive = true
605605
u.SetLastLogin()
606-
if err := user_model.UpdateUserCols(db.DefaultContext, u, "is_admin", "is_active", "last_login_unix"); err != nil {
606+
if err := user_model.UpdateUserCols(db.DefaultContext, u, false, "is_admin", "is_active", "last_login_unix"); err != nil {
607607
ctx.ServerError("UpdateUser", err)
608608
return
609609
}
@@ -724,7 +724,7 @@ func handleAccountActivation(ctx *context.Context, user *user_model.User) {
724724
ctx.ServerError("UpdateUser", err)
725725
return
726726
}
727-
if err := user_model.UpdateUserCols(db.DefaultContext, user, "is_active", "rands"); err != nil {
727+
if err := user_model.UpdateUserCols(db.DefaultContext, user, false, "is_active", "rands"); err != nil {
728728
if user_model.IsErrUserNotExist(err) {
729729
ctx.NotFound("UpdateUserCols", err)
730730
} else {

routers/web/auth/oauth.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,7 +1021,7 @@ func handleOAuth2SignIn(ctx *context.Context, source *auth.Source, u *user_model
10211021
cols = append(cols, "is_admin", "is_restricted")
10221022
}
10231023

1024-
if err := user_model.UpdateUserCols(db.DefaultContext, u, cols...); err != nil {
1024+
if err := user_model.UpdateUserCols(db.DefaultContext, u, false, cols...); err != nil {
10251025
ctx.ServerError("UpdateUserCols", err)
10261026
return
10271027
}
@@ -1048,7 +1048,7 @@ func handleOAuth2SignIn(ctx *context.Context, source *auth.Source, u *user_model
10481048

10491049
changed := setUserGroupClaims(source, u, &gothUser)
10501050
if changed {
1051-
if err := user_model.UpdateUserCols(db.DefaultContext, u, "is_admin", "is_restricted"); err != nil {
1051+
if err := user_model.UpdateUserCols(db.DefaultContext, u, false, "is_admin", "is_restricted"); err != nil {
10521052
ctx.ServerError("UpdateUserCols", err)
10531053
return
10541054
}

0 commit comments

Comments
 (0)