diff --git a/cmd/admin.go b/cmd/admin.go index 9f81f5284dd6d..813b92a3d0f7a 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -283,7 +283,7 @@ func runChangePassword(c *cli.Context) error { } user.HashPassword(c.String("password")) - if err := models.UpdateUserCols(user, "passwd", "salt"); err != nil { + if err := models.UpdateUserCols(user, false, "passwd", "salt"); err != nil { return err } diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index b3b9fd96cc708..385bf6ccb02e8 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -569,6 +569,8 @@ EMAIL_DOMAIN_WHITELIST= DISABLE_REGISTRATION = false ; Allow registration only using third-party services, it works only when DISABLE_REGISTRATION is false ALLOW_ONLY_EXTERNAL_REGISTRATION = false +; Disable local user management (i.e. when user data and password comes from LDAP and should not be changed locally in gitea). +DISABLE_LOCAL_USER_MANAGEMENT = false ; User must sign in to view anything. REQUIRE_SIGNIN_VIEW = false ; Mail notification diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index 673eeac79ddae..784e15f3f84ba 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -409,6 +409,7 @@ set name for unique queues. Individual queues will default to - `DEFAULT_ORG_VISIBILITY`: **public**: Set default visibility mode for organisations, either "public", "limited" or "private". - `DEFAULT_ORG_MEMBER_VISIBLE`: **false** True will make the membership of the users visible when added to the organisation. - `ALLOW_ONLY_EXTERNAL_REGISTRATION`: **false** Set to true to force registration only using third-party services. +- `DISABLE_LOCAL_USER_MANAGEMENT`: **false** Set to true to disable local user management in gitea (i.e. when users are managed in LDAP). - `NO_REPLY_ADDRESS`: **DOMAIN** Default value for the domain part of the user's email address in the git log if he has set KeepEmailPrivate to true. The user's email will be replaced with a concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS. diff --git a/models/login_source.go b/models/login_source.go index 1de24a9cf70b5..55efa3c0c62c5 100644 --- a/models/login_source.go +++ b/models/login_source.go @@ -488,7 +488,7 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource) (*Use cols = append(cols, "is_restricted") } if len(cols) > 0 { - err = UpdateUserCols(user, cols...) + err = UpdateUserCols(user, false, cols...) if err != nil { return nil, err } @@ -768,7 +768,7 @@ func UserSignIn(username, password string) (*User, error) { // Update password hash if server password hash algorithm have changed if user.PasswdHashAlgo != setting.PasswordHashAlgo { user.HashPassword(password) - if err := UpdateUserCols(user, "passwd", "passwd_hash_algo"); err != nil { + if err := UpdateUserCols(user, false, "passwd", "passwd_hash_algo"); err != nil { return nil, err } } diff --git a/models/repo.go b/models/repo.go index 46f91fc7df658..20822ff14c405 100644 --- a/models/repo.go +++ b/models/repo.go @@ -1190,7 +1190,7 @@ func CreateRepository(ctx DBContext, doer, u *User, repo *Repository, overwriteO // Remember visibility preference. u.LastRepoVisibility = repo.IsPrivate - if err = updateUserCols(ctx.e, u, "last_repo_visibility"); err != nil { + if err = updateUserCols(ctx.e, u, false, "last_repo_visibility"); err != nil { return fmt.Errorf("updateUser: %v", err) } diff --git a/models/user.go b/models/user.go index 650d5a803aa9a..064e47b296ead 100644 --- a/models/user.go +++ b/models/user.go @@ -220,13 +220,13 @@ func (u *User) SetLastLogin() { // UpdateDiffViewStyle updates the users diff view style func (u *User) UpdateDiffViewStyle(style string) error { u.DiffViewStyle = style - return UpdateUserCols(u, "diff_view_style") + return UpdateUserCols(u, false, "diff_view_style") } // UpdateTheme updates a users' theme irrespective of the site wide theme func (u *User) UpdateTheme(themeName string) error { u.Theme = themeName - return UpdateUserCols(u, "theme") + return UpdateUserCols(u, false, "theme") } // GetEmail returns an noreply email, if the user has set to keep his @@ -824,7 +824,7 @@ func (u *User) EmailNotifications() string { // SetEmailNotifications sets the user's email notification preference func (u *User) SetEmailNotifications(set string) error { u.EmailNotificationsPreference = set - if err := UpdateUserCols(u, "email_notifications_preference"); err != nil { + if err := UpdateUserCols(u, false, "email_notifications_preference"); err != nil { log.Error("SetEmailNotifications: %v", err) return err } @@ -1126,7 +1126,43 @@ func checkDupEmail(e Engine, u *User) error { return nil } +// updateUserAllowed is used to block updating selected user fields when local user managemement is disabled. +func updateUserAllowed(u *User) error { + // Don't allow changes of selected user fields if local user management is disabled. + if setting.Service.DisableLocalUserManagement && (u.Type == UserTypeIndividual) { + if currUser, err := GetUserByID(u.ID); err == nil { + if currUser.Name != u.Name { + return fmt.Errorf("cannot change user %s username; local user management disabled", u.Name) + } + if (currUser.LoginSource != u.LoginSource) || (currUser.LoginName != u.LoginName) { + return fmt.Errorf("cannot change user %s login; local user management disabled", u.Name) + } + if currUser.FullName != u.FullName { + return fmt.Errorf("cannot change user %s full name; local user management disabled", u.Name) + } + if currUser.Email != u.Email { + return fmt.Errorf("cannot change user %s e-mail; local user management disabled", u.Name) + } + if (currUser.Passwd != u.Passwd) || (currUser.PasswdHashAlgo != u.PasswdHashAlgo) { + return fmt.Errorf("cannot change user %s password; local user management disabled", u.Name) + } + if currUser.IsActive != u.IsActive { + return fmt.Errorf("cannot change user %s activity; local user management disabled", u.Name) + } + if currUser.IsAdmin != u.IsAdmin { + return fmt.Errorf("cannot change user %s admin permission; local user management disabled", u.Name) + } + } else { + return err + } + } + return nil +} + func updateUser(e Engine, u *User) error { + if err := updateUserAllowed(u); err != nil { + return err + } _, err := e.ID(u.ID).AllCols().Update(u) return err } @@ -1137,11 +1173,16 @@ func UpdateUser(u *User) error { } // UpdateUserCols update user according special columns -func UpdateUserCols(u *User, cols ...string) error { - return updateUserCols(x, u, cols...) +func UpdateUserCols(u *User, force bool, cols ...string) error { + return updateUserCols(x, u, force, cols...) } -func updateUserCols(e Engine, u *User, cols ...string) error { +func updateUserCols(e Engine, u *User, force bool, cols ...string) error { + if !force { + if err := updateUserAllowed(u); err != nil { + return err + } + } _, err := e.ID(u.ID).Cols(cols...).Update(u) return err } @@ -1982,7 +2023,7 @@ func SyncExternalUsers(ctx context.Context, updateExisting bool) error { } usr.IsActive = true - err = UpdateUserCols(usr, "full_name", "email", "is_admin", "is_restricted", "is_active") + err = UpdateUserCols(usr, true, "full_name", "email", "is_admin", "is_restricted", "is_active") if err != nil { log.Error("SyncExternalUsers[%s]: Error updating user %s: %v", s.Name, usr.Name, err) } @@ -2019,7 +2060,7 @@ func SyncExternalUsers(ctx context.Context, updateExisting bool) error { log.Trace("SyncExternalUsers[%s]: Deactivating user %s", s.Name, usr.Name) usr.IsActive = false - err = UpdateUserCols(usr, "is_active") + err = UpdateUserCols(usr, true, "is_active") if err != nil { log.Error("SyncExternalUsers[%s]: Error deactivating user %s: %v", s.Name, usr.Name, err) } diff --git a/models/user_mail.go b/models/user_mail.go index 60354e23ffb22..390e60f9fa16d 100644 --- a/models/user_mail.go +++ b/models/user_mail.go @@ -201,7 +201,7 @@ func (email *EmailAddress) updateActivation(e Engine, activate bool) error { if _, err := e.ID(email.ID).Cols("is_activated").Update(email); err != nil { return err } - return updateUserCols(e, user, "rands") + return updateUserCols(e, user, false, "rands") } // DeleteEmailAddress deletes an email address of given user. @@ -448,7 +448,7 @@ func ActivateUserEmail(userID int64, email string, primary, activate bool) (err if user.Rands, err = GetUserSalt(); err != nil { return fmt.Errorf("generate salt: %v", err) } - if err = updateUserCols(sess, &user, "is_active", "rands"); err != nil { + if err = updateUserCols(sess, &user, false, "is_active", "rands"); err != nil { return fmt.Errorf("updateUserCols(): %v", err) } } else { diff --git a/modules/auth/sso/sso.go b/modules/auth/sso/sso.go index c2e36f3f5ebf2..f8d999ee891b7 100644 --- a/modules/auth/sso/sso.go +++ b/modules/auth/sso/sso.go @@ -133,7 +133,7 @@ func handleSignIn(ctx *macaron.Context, sess session.Store, user *models.User) { // If the user does not have a locale set, we save the current one. if len(user.Language) == 0 { user.Language = ctx.Locale.Language() - if err := models.UpdateUserCols(user, "language"); err != nil { + if err := models.UpdateUserCols(user, false, "language"); err != nil { log.Error(fmt.Sprintf("Error updating user language [user: %d, locale: %s]", user.ID, user.Language)) return } diff --git a/modules/auth/user_form.go b/modules/auth/user_form.go index 999d4cd74df69..fe9b7bfbf511d 100644 --- a/modules/auth/user_form.go +++ b/modules/auth/user_form.go @@ -51,6 +51,7 @@ type InstallForm struct { EnableOpenIDSignUp bool DisableRegistration bool AllowOnlyExternalRegistration bool + DisableLocalUserManagement bool EnableCaptcha bool RequireSignInView bool DefaultKeepEmailPrivate bool diff --git a/modules/setting/service.go b/modules/setting/service.go index c463b0a9d5d0d..5dd33ff1e4a77 100644 --- a/modules/setting/service.go +++ b/modules/setting/service.go @@ -20,6 +20,7 @@ var Service struct { EmailDomainWhitelist []string DisableRegistration bool AllowOnlyExternalRegistration bool + DisableLocalUserManagement bool ShowRegistrationButton bool ShowMilestonesDashboardPage bool RequireSignInView bool @@ -61,6 +62,7 @@ func newService() { Service.ResetPwdCodeLives = sec.Key("RESET_PASSWD_CODE_LIVE_MINUTES").MustInt(180) Service.DisableRegistration = sec.Key("DISABLE_REGISTRATION").MustBool() Service.AllowOnlyExternalRegistration = sec.Key("ALLOW_ONLY_EXTERNAL_REGISTRATION").MustBool() + Service.DisableLocalUserManagement = sec.Key("DISABLE_LOCAL_USER_MANAGEMENT").MustBool() Service.EmailDomainWhitelist = sec.Key("EMAIL_DOMAIN_WHITELIST").Strings(",") Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration)) Service.ShowMilestonesDashboardPage = sec.Key("SHOW_MILESTONES_DASHBOARD_PAGE").MustBool(true) diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 63be27d98735a..13a185eb50d40 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -228,6 +228,9 @@ func NewFuncMap() []template.FuncMap { "DisableImportLocal": func() bool { return !setting.ImportLocalPaths }, + "DisableLocalUserManagement": func() bool { + return setting.Service.DisableLocalUserManagement + }, "TrN": TrN, "Dict": func(values ...interface{}) (map[string]interface{}, error) { if len(values)%2 != 0 { diff --git a/routers/admin/auths.go b/routers/admin/auths.go index 98f6e25b1f938..e1066c90ac8e4 100644 --- a/routers/admin/auths.go +++ b/routers/admin/auths.go @@ -40,6 +40,12 @@ func Authentications(ctx *context.Context) { ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminAuthentications"] = true + // No access to this page if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("Authentications", fmt.Errorf("access to /admin/auths page denied; local user management disabled")) + return + } + var err error ctx.Data["Sources"], err = models.LoginSources() if err != nil { @@ -96,6 +102,12 @@ func NewAuthSource(ctx *context.Context) { ctx.Data["SSPISeparatorReplacement"] = "_" ctx.Data["SSPIDefaultLanguage"] = "" + // No access to this page if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("NewAuthSource", fmt.Errorf("access to /admin/auths/new page denied; local user management disabled")) + return + } + // only the first as default for key := range models.OAuth2Providers { ctx.Data["oauth2_provider"] = key @@ -218,6 +230,12 @@ func NewAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) { ctx.Data["SSPISeparatorReplacement"] = "_" ctx.Data["SSPIDefaultLanguage"] = "" + // Don't allow to create auth source if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("NewAuthSourcePost", fmt.Errorf("cannot create auth source; local user management disabled")) + return + } + hasTLS := false var config convert.Conversion switch models.LoginType(form.Type) { @@ -290,6 +308,12 @@ func EditAuthSource(ctx *context.Context) { ctx.Data["OAuth2Providers"] = models.OAuth2Providers ctx.Data["OAuth2DefaultCustomURLMappings"] = models.OAuth2DefaultCustomURLMappings + // No access to this page if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("EditAuthSource", fmt.Errorf("access to /admin/auths page denied; local user management disabled")) + return + } + source, err := models.GetLoginSourceByID(ctx.ParamsInt64(":authid")) if err != nil { ctx.ServerError("GetLoginSourceByID", err) @@ -314,6 +338,12 @@ func EditAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) { ctx.Data["OAuth2Providers"] = models.OAuth2Providers ctx.Data["OAuth2DefaultCustomURLMappings"] = models.OAuth2DefaultCustomURLMappings + // Don't allow to update auth source if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("EditAuthSourcePost", fmt.Errorf("cannot update auth source; local user management disabled")) + return + } + source, err := models.GetLoginSourceByID(ctx.ParamsInt64(":authid")) if err != nil { ctx.ServerError("GetLoginSourceByID", err) diff --git a/routers/admin/emails.go b/routers/admin/emails.go index f0b14ce5e59dc..2001f148130be 100644 --- a/routers/admin/emails.go +++ b/routers/admin/emails.go @@ -6,6 +6,7 @@ package admin import ( "bytes" + "fmt" "net/url" "code.gitea.io/gitea/models" @@ -28,6 +29,12 @@ func Emails(ctx *context.Context) { ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminEmails"] = true + // No access to this page if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("Emails", fmt.Errorf("access to /admin/emails page denied; local user management disabled")) + return + } + opts := &models.SearchEmailOptions{ ListOptions: models.ListOptions{ PageSize: setting.UI.Admin.UserPagingNum, @@ -112,6 +119,12 @@ func isKeywordValid(keyword string) bool { // ActivateEmail serves a POST request for activating/deactivating a user's email func ActivateEmail(ctx *context.Context) { + // Don't allow to activate/deactivate emails if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("ActivateEmail", fmt.Errorf("cannot activate email; local user management disabled")) + return + } + truefalse := map[string]bool{"1": true, "0": false} uid := com.StrTo(ctx.Query("uid")).MustInt64() diff --git a/routers/admin/users.go b/routers/admin/users.go index 531f81b8b51e4..dc21921da143f 100644 --- a/routers/admin/users.go +++ b/routers/admin/users.go @@ -6,6 +6,7 @@ package admin import ( + "fmt" "strings" "code.gitea.io/gitea/models" @@ -50,6 +51,12 @@ func NewUser(ctx *context.Context) { ctx.Data["login_type"] = "0-0" + // No access to this page if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("NewUser", fmt.Errorf("access to /admin/users/new page denied; local user management disabled")) + return + } + sources, err := models.LoginSources() if err != nil { ctx.ServerError("LoginSources", err) @@ -67,6 +74,12 @@ func NewUserPost(ctx *context.Context, form auth.AdminCreateUserForm) { ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminUsers"] = true + // Don't allow to create users if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("NewUserPost", fmt.Errorf("cannot create new user; local user management disabled")) + return + } + sources, err := models.LoginSources() if err != nil { ctx.ServerError("LoginSources", err) @@ -226,6 +239,11 @@ func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) { if len(form.Password) > 0 { var err error + // Don't allow password changes if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("UpdateUser", fmt.Errorf("cannot change %s password; local user management disabled", u.Name)) + return + } if len(form.Password) < setting.MinPasswordLength { ctx.Data["Err_Password"] = true ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplUserEdit, &form) diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index 987f141078088..4759c8ede1667 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -253,7 +253,7 @@ func Edit(ctx *context.APIContext, form api.EditOrgOption) { if form.Visibility != "" { org.Visibility = api.VisibilityModes[form.Visibility] } - if err := models.UpdateUserCols(org, "full_name", "description", "website", "location", "visibility"); err != nil { + if err := models.UpdateUserCols(org, false, "full_name", "description", "website", "location", "visibility"); err != nil { ctx.Error(http.StatusInternalServerError, "EditOrganization", err) return } diff --git a/routers/user/auth.go b/routers/user/auth.go index 96a73c9dd4632..9eb8cd1359454 100644 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -519,7 +519,7 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR // If the user does not have a locale set, we save the current one. if len(u.Language) == 0 { u.Language = ctx.Locale.Language() - if err := models.UpdateUserCols(u, "language"); err != nil { + if err := models.UpdateUserCols(u, false, "language"); err != nil { log.Error(fmt.Sprintf("Error updating user language [user: %d, locale: %s]", u.ID, u.Language)) return setting.AppSubURL + "/" } @@ -532,7 +532,7 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR // Register last login u.SetLastLogin() - if err := models.UpdateUserCols(u, "last_login_unix"); err != nil { + if err := models.UpdateUserCols(u, false, "last_login_unix"); err != nil { ctx.ServerError("UpdateUserCols", err) return setting.AppSubURL + "/" } @@ -639,7 +639,7 @@ func handleOAuth2SignIn(u *models.User, gothUser goth.User, ctx *context.Context // Register last login u.SetLastLogin() - if err := models.UpdateUserCols(u, "last_login_unix"); err != nil { + if err := models.UpdateUserCols(u, false, "last_login_unix"); err != nil { ctx.ServerError("UpdateUserCols", err) return } @@ -978,7 +978,7 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au u.IsAdmin = true u.IsActive = true u.SetLastLogin() - if err := models.UpdateUserCols(u, "is_admin", "is_active", "last_login_unix"); err != nil { + if err := models.UpdateUserCols(u, false, "is_admin", "is_active", "last_login_unix"); err != nil { ctx.ServerError("UpdateUser", err) return } @@ -1154,7 +1154,7 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo u.IsAdmin = true u.IsActive = true u.SetLastLogin() - if err := models.UpdateUserCols(u, "is_admin", "is_active", "last_login_unix"); err != nil { + if err := models.UpdateUserCols(u, false, "is_admin", "is_active", "last_login_unix"); err != nil { ctx.ServerError("UpdateUser", err) return } @@ -1215,7 +1215,7 @@ func Activate(ctx *context.Context) { ctx.ServerError("UpdateUser", err) return } - if err := models.UpdateUserCols(user, "is_active", "rands"); err != nil { + if err := models.UpdateUserCols(user, false, "is_active", "rands"); err != nil { if models.IsErrUserNotExist(err) { ctx.Error(404) } else { @@ -1475,7 +1475,7 @@ func ResetPasswdPost(ctx *context.Context) { } u.HashPassword(passwd) u.MustChangePassword = false - if err := models.UpdateUserCols(u, "must_change_password", "passwd", "rands", "salt"); err != nil { + if err := models.UpdateUserCols(u, false, "must_change_password", "passwd", "rands", "salt"); err != nil { ctx.ServerError("UpdateUser", err) return } @@ -1551,7 +1551,7 @@ func MustChangePasswordPost(ctx *context.Context, cpt *captcha.Captcha, form aut u.HashPassword(form.Password) u.MustChangePassword = false - if err := models.UpdateUserCols(u, "must_change_password", "passwd", "salt"); err != nil { + if err := models.UpdateUserCols(u, false, "must_change_password", "passwd", "salt"); err != nil { ctx.ServerError("UpdateUser", err) return } diff --git a/routers/user/auth_openid.go b/routers/user/auth_openid.go index ba2c8be8c24cb..258691522874a 100644 --- a/routers/user/auth_openid.go +++ b/routers/user/auth_openid.go @@ -443,7 +443,7 @@ func RegisterOpenIDPost(ctx *context.Context, cpt *captcha.Captcha, form auth.Si u.IsAdmin = true u.IsActive = true u.SetLastLogin() - if err := models.UpdateUserCols(u, "is_admin", "is_active", "last_login_unix"); err != nil { + if err := models.UpdateUserCols(u, false, "is_admin", "is_active", "last_login_unix"); err != nil { ctx.ServerError("UpdateUser", err) return } diff --git a/routers/user/setting/account.go b/routers/user/setting/account.go index 99e20177bc986..f9fe5c00fc4c6 100644 --- a/routers/user/setting/account.go +++ b/routers/user/setting/account.go @@ -7,6 +7,7 @@ package setting import ( "errors" + "fmt" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/auth" @@ -68,7 +69,7 @@ func AccountPost(ctx *context.Context, form auth.ChangePasswordForm) { return } ctx.User.HashPassword(form.Password) - if err := models.UpdateUserCols(ctx.User, "salt", "passwd"); err != nil { + if err := models.UpdateUserCols(ctx.User, false, "salt", "passwd"); err != nil { ctx.ServerError("UpdateUser", err) return } @@ -86,6 +87,12 @@ func EmailPost(ctx *context.Context, form auth.AddEmailForm) { // Make emailaddress primary. if ctx.Query("_method") == "PRIMARY" { + // No access to this function if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("MakeEmailPrimary", fmt.Errorf("access to /user/settings/account/email MakeEmailPrimary function denied; local user management disabled")) + return + } + if err := models.MakeEmailPrimary(&models.EmailAddress{ID: ctx.QueryInt64("id")}); err != nil { ctx.ServerError("MakeEmailPrimary", err) return @@ -97,6 +104,11 @@ func EmailPost(ctx *context.Context, form auth.AddEmailForm) { } // Send activation Email if ctx.Query("_method") == "SENDACTIVATION" { + // No access to this function if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("SendActivation", fmt.Errorf("access to /user/settings/account/email SendActivation function denied; local user management disabled")) + return + } var address string if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) { log.Error("Send activation: activation still pending") @@ -161,6 +173,12 @@ func EmailPost(ctx *context.Context, form auth.AddEmailForm) { return } + // No access to this function if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("AddEmailAddress", fmt.Errorf("access to /user/settings/account/email AddEmailAddress function denied; local user management disabled")) + return + } + if ctx.HasError() { loadAccountData(ctx) @@ -201,6 +219,13 @@ func EmailPost(ctx *context.Context, form auth.AddEmailForm) { // DeleteEmail response for delete user's email func DeleteEmail(ctx *context.Context) { + + // No access to this function if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("DeleteEmail", fmt.Errorf("access to /user/settings/account/email DeleteEmail function denied; local user management disabled")) + return + } + if err := models.DeleteEmailAddress(&models.EmailAddress{ID: ctx.QueryInt64("id"), UID: ctx.User.ID}); err != nil { ctx.ServerError("DeleteEmail", err) return @@ -215,6 +240,12 @@ func DeleteEmail(ctx *context.Context) { // DeleteAccount render user suicide page and response for delete user himself func DeleteAccount(ctx *context.Context) { + // No access to this page if local user management is disabled. + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("DeleteAccount", fmt.Errorf("access to /user/settings/account/delete page denied; local user management disabled")) + return + } + ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsAccount"] = true diff --git a/routers/user/setting/profile.go b/routers/user/setting/profile.go index fe0506946ad68..de80f013a62e5 100644 --- a/routers/user/setting/profile.go +++ b/routers/user/setting/profile.go @@ -46,6 +46,9 @@ func handleUsernameChange(ctx *context.Context, newName string) { // Check if user name has been changed if ctx.User.LowerName != strings.ToLower(newName) { + if setting.Service.DisableLocalUserManagement { + ctx.ServerError("ChangeUserName", fmt.Errorf("cannot change user %s username; local user management disabled", ctx.User.Name)) + } if err := models.ChangeUserName(ctx.User, newName); err != nil { switch { case models.IsErrUserAlreadyExist(err): @@ -155,7 +158,7 @@ func UpdateAvatarSetting(ctx *context.Context, form auth.AvatarForm, ctxUser *mo } } - if err := models.UpdateUserCols(ctxUser, "avatar", "avatar_email", "use_custom_avatar"); err != nil { + if err := models.UpdateUserCols(ctxUser, false, "avatar", "avatar_email", "use_custom_avatar"); err != nil { return fmt.Errorf("UpdateUser: %v", err) } diff --git a/templates/admin/navbar.tmpl b/templates/admin/navbar.tmpl index 6d81d7557f607..eba96209c0966 100644 --- a/templates/admin/navbar.tmpl +++ b/templates/admin/navbar.tmpl @@ -17,12 +17,14 @@ {{.i18n.Tr "admin.systemhooks"}} +{{if not DisableLocalUserManagement}} {{.i18n.Tr "admin.authentication"}} {{.i18n.Tr "admin.emails"}} +{{end}} {{.i18n.Tr "admin.config"}} diff --git a/templates/admin/user/edit.tmpl b/templates/admin/user/edit.tmpl index 042c09954a2c3..6031f6895098a 100644 --- a/templates/admin/user/edit.tmpl +++ b/templates/admin/user/edit.tmpl @@ -14,7 +14,7 @@ {{.User.Name}} -
+
-
+
- +
- +
-
+
- +
-
+

{{.i18n.Tr "admin.users.password_helper"}}

@@ -68,19 +68,19 @@
- +
- +
- +
diff --git a/templates/admin/user/list.tmpl b/templates/admin/user/list.tmpl index d6dd7d5c03969..0363501bbeb0f 100644 --- a/templates/admin/user/list.tmpl +++ b/templates/admin/user/list.tmpl @@ -5,9 +5,11 @@ {{template "base/alert" .}}

{{.i18n.Tr "admin.users.user_manage_panel"}} ({{.i18n.Tr "admin.total" .Total}}) +{{if not DisableLocalUserManagement}} +{{end}}

{{template "admin/base/search" .}} diff --git a/templates/user/settings/account.tmpl b/templates/user/settings/account.tmpl index b2cff8618878a..584974cc9b1bb 100644 --- a/templates/user/settings/account.tmpl +++ b/templates/user/settings/account.tmpl @@ -3,6 +3,7 @@ {{template "user/settings/navbar" .}}
{{template "base/alert" .}} +{{if not DisableLocalUserManagement}}

{{.i18n.Tr "settings.password"}}

@@ -36,7 +37,7 @@
{{end}}
- +{{end}}

{{.i18n.Tr "settings.manage_emails"}}

@@ -70,6 +71,7 @@
{{range .Emails}}
+{{if not DisableLocalUserManagement}} {{if not .IsPrimary}}
{{end}} +{{end}}
{{.Email}} +{{if not DisableLocalUserManagement}} + {{if .IsPrimary}}
{{$.i18n.Tr "settings.primary"}}
{{end}} @@ -111,11 +116,13 @@ {{else}}
{{$.i18n.Tr "settings.requires_activation"}}
{{end}} +{{end}}
{{end}}
+{{if not DisableLocalUserManagement}}
{{.CsrfTokenHtml}} @@ -128,7 +135,7 @@
- +{{end}}

{{.i18n.Tr "settings.manage_themes"}}

@@ -167,6 +174,7 @@
+{{if not DisableLocalUserManagement}}

{{.i18n.Tr "settings.delete_account"}}

@@ -189,6 +197,7 @@ +{{end}} diff --git a/templates/user/settings/profile.tmpl b/templates/user/settings/profile.tmpl index 1f34e24585d6d..2748eb45f89be 100644 --- a/templates/user/settings/profile.tmpl +++ b/templates/user/settings/profile.tmpl @@ -10,20 +10,20 @@

{{.i18n.Tr "settings.profile_desc"}}

{{.CsrfTokenHtml}} -
+
- - {{if not .SignedUser.IsLocal}} + + {{if not (or .SignedUser.IsLocal DisableLocalUserManagement)}}

{{$.i18n.Tr "settings.password_username_disabled"}}

{{end}}
- +
-
+
- +