Skip to content

Commit d647042

Browse files
committed
Allow disalbe part user settings
1 parent 112e425 commit d647042

File tree

8 files changed

+130
-59
lines changed

8 files changed

+130
-59
lines changed

custom/conf/app.example.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2481,3 +2481,7 @@ ROUTER = console
24812481
;PROXY_URL =
24822482
;; Comma separated list of host names requiring proxy. Glob patterns (*) are accepted; use ** to match all hosts.
24832483
;PROXY_HOSTS =
2484+
2485+
;[user]
2486+
; Disabled modules from user settings, could be passwods, suicide, security, applications, gpg keys, organiztions
2487+
;USER_SETTING_DISABLED_MODULES =

modules/setting/setting.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,8 @@ func loadFromConf(allowEmpty bool, extraConfig string) {
11281128
for _, emoji := range UI.CustomEmojis {
11291129
UI.CustomEmojisMap[emoji] = ":" + emoji + ":"
11301130
}
1131+
1132+
newUserSetting()
11311133
}
11321134

11331135
func parseAuthorizedPrincipalsAllow(values []string) ([]string, bool) {

modules/setting/user.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package setting
6+
7+
import (
8+
"strings"
9+
10+
"code.gitea.io/gitea/modules/log"
11+
)
12+
13+
// userSetting represents user settings
14+
type userSetting struct {
15+
SettingDisabledModules []string
16+
}
17+
18+
func (s *userSetting) Enabled(module string) bool {
19+
for _, m := range s.SettingDisabledModules {
20+
if strings.EqualFold(m, module) {
21+
return false
22+
}
23+
}
24+
return true
25+
}
26+
27+
var User userSetting
28+
29+
func newUserSetting() {
30+
sec := Cfg.Section("user")
31+
if err := sec.MapTo(&User); err != nil {
32+
log.Fatal("user setting mapping failed: %v", err)
33+
}
34+
}

routers/web/user/setting/keys.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package setting
66

77
import (
8+
"fmt"
89
"net/http"
910

1011
asymkey_model "code.gitea.io/gitea/models/asymkey"
@@ -77,6 +78,11 @@ func KeysPost(ctx *context.Context) {
7778
ctx.Flash.Success(ctx.Tr("settings.add_principal_success", form.Content))
7879
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
7980
case "gpg":
81+
if !setting.User.Enabled("gpg keys") {
82+
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting are not allowed"))
83+
return
84+
}
85+
8086
token := asymkey_model.VerificationToken(ctx.Doer, 1)
8187
lastToken := asymkey_model.VerificationToken(ctx.Doer, 0)
8288

@@ -216,6 +222,10 @@ func KeysPost(ctx *context.Context) {
216222
func DeleteKey(ctx *context.Context) {
217223
switch ctx.FormString("type") {
218224
case "gpg":
225+
if !setting.User.Enabled("gpg keys") {
226+
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting are not allowed"))
227+
return
228+
}
219229
if err := asymkey_model.DeleteGPGKey(ctx.Doer, ctx.FormInt64("id")); err != nil {
220230
ctx.Flash.Error("DeleteGPGKey: " + err.Error())
221231
} else {

routers/web/web.go

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,14 @@ func RegisterRoutes(m *web.Route) {
316316
}
317317
}
318318

319+
userSettingModuleEnabled := func(module string) func(ctx *context.Context) {
320+
return func(ctx *context.Context) {
321+
if !setting.User.Enabled(module) {
322+
ctx.Error(http.StatusNotFound)
323+
}
324+
}
325+
}
326+
319327
// FIXME: not all routes need go through same middleware.
320328
// Especially some AJAX requests, we can reduce middleware number to improve performance.
321329
// Routers.
@@ -406,15 +414,15 @@ func RegisterRoutes(m *web.Route) {
406414
m.Group("/user/settings", func() {
407415
m.Get("", user_setting.Profile)
408416
m.Post("", bindIgnErr(forms.UpdateProfileForm{}), user_setting.ProfilePost)
409-
m.Get("/change_password", auth.MustChangePassword)
410-
m.Post("/change_password", bindIgnErr(forms.MustChangePasswordForm{}), auth.MustChangePasswordPost)
417+
m.Get("/change_password", userSettingModuleEnabled("password"), auth.MustChangePassword)
418+
m.Post("/change_password", userSettingModuleEnabled("password"), bindIgnErr(forms.MustChangePasswordForm{}), auth.MustChangePasswordPost)
411419
m.Post("/avatar", bindIgnErr(forms.AvatarForm{}), user_setting.AvatarPost)
412420
m.Post("/avatar/delete", user_setting.DeleteAvatar)
413421
m.Group("/account", func() {
414422
m.Combo("").Get(user_setting.Account).Post(bindIgnErr(forms.ChangePasswordForm{}), user_setting.AccountPost)
415423
m.Post("/email", bindIgnErr(forms.AddEmailForm{}), user_setting.EmailPost)
416424
m.Post("/email/delete", user_setting.DeleteEmail)
417-
m.Post("/delete", user_setting.DeleteAccount)
425+
m.Post("/delete", userSettingModuleEnabled("suicide"), user_setting.DeleteAccount)
418426
})
419427
m.Group("/appearance", func() {
420428
m.Get("", user_setting.Appearance)
@@ -441,18 +449,18 @@ func RegisterRoutes(m *web.Route) {
441449
m.Post("/toggle_visibility", security.ToggleOpenIDVisibility)
442450
}, openIDSignInEnabled)
443451
m.Post("/account_link", linkAccountEnabled, security.DeleteAccountLink)
444-
})
452+
}, userSettingModuleEnabled("security"))
445453
m.Group("/applications/oauth2", func() {
446454
m.Get("/{id}", user_setting.OAuth2ApplicationShow)
447455
m.Post("/{id}", bindIgnErr(forms.EditOAuth2ApplicationForm{}), user_setting.OAuthApplicationsEdit)
448456
m.Post("/{id}/regenerate_secret", user_setting.OAuthApplicationsRegenerateSecret)
449457
m.Post("", bindIgnErr(forms.EditOAuth2ApplicationForm{}), user_setting.OAuthApplicationsPost)
450458
m.Post("/{id}/delete", user_setting.DeleteOAuth2Application)
451459
m.Post("/{id}/revoke/{grantId}", user_setting.RevokeOAuth2Grant)
452-
})
453-
m.Combo("/applications").Get(user_setting.Applications).
454-
Post(bindIgnErr(forms.NewAccessTokenForm{}), user_setting.ApplicationsPost)
455-
m.Post("/applications/delete", user_setting.DeleteApplication)
460+
}, userSettingModuleEnabled("applications"))
461+
m.Combo("/applications").Get(userSettingModuleEnabled("applications"), user_setting.Applications).
462+
Post(userSettingModuleEnabled("applications"), bindIgnErr(forms.NewAccessTokenForm{}), user_setting.ApplicationsPost)
463+
m.Post("/applications/delete", userSettingModuleEnabled("applications"), user_setting.DeleteApplication)
456464
m.Combo("/keys").Get(user_setting.Keys).
457465
Post(bindIgnErr(forms.AddKeyForm{}), user_setting.KeysPost)
458466
m.Post("/keys/delete", user_setting.DeleteKey)
@@ -470,13 +478,14 @@ func RegisterRoutes(m *web.Route) {
470478
})
471479
})
472480
}, packagesEnabled)
473-
m.Get("/organization", user_setting.Organization)
481+
m.Get("/organization", userSettingModuleEnabled("organizations"), user_setting.Organization)
474482
m.Get("/repos", user_setting.Repos)
475483
m.Post("/repos/unadopted", user_setting.AdoptOrDeleteRepository)
476484
}, reqSignIn, func(ctx *context.Context) {
477485
ctx.Data["PageIsUserSettings"] = true
478486
ctx.Data["AllThemes"] = setting.UI.Themes
479487
ctx.Data["EnablePackages"] = setting.Packages.Enabled
488+
ctx.Data["UserModules"] = &setting.User
480489
})
481490

482491
m.Group("/user", func() {

templates/user/settings/account.tmpl

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,42 @@
33
{{template "user/settings/navbar" .}}
44
<div class="ui container">
55
{{template "base/alert" .}}
6-
<h4 class="ui top attached header">
7-
{{.locale.Tr "settings.password"}}
8-
</h4>
9-
<div class="ui attached segment">
10-
{{if or (.SignedUser.IsLocal) (.SignedUser.IsOAuth2)}}
11-
<form class="ui form ignore-dirty" action="{{AppSubUrl}}/user/settings/account" method="post">
12-
{{template "base/disable_form_autofill"}}
13-
{{.CsrfTokenHtml}}
14-
{{if .SignedUser.IsPasswordSet}}
15-
<div class="required field {{if .Err_OldPassword}}error{{end}}">
16-
<label for="old_password">{{.locale.Tr "settings.old_password"}}</label>
17-
<input id="old_password" name="old_password" type="password" autocomplete="current-password" autofocus required>
18-
</div>
19-
{{end}}
20-
<div class="required field {{if .Err_Password}}error{{end}}">
21-
<label for="password">{{.locale.Tr "settings.new_password"}}</label>
22-
<input id="password" name="password" type="password" autocomplete="new-password" required>
23-
</div>
24-
<div class="required field {{if .Err_Password}}error{{end}}">
25-
<label for="retype">{{.locale.Tr "settings.retype_new_password"}}</label>
26-
<input id="retype" name="retype" type="password" autocomplete="new-password" required>
27-
</div>
6+
{{if $.UserModules.Enabled "password"}}
7+
<h4 class="ui top attached header">
8+
{{.locale.Tr "settings.password"}}
9+
</h4>
10+
<div class="ui attached segment">
11+
{{if or (.SignedUser.IsLocal) (.SignedUser.IsOAuth2)}}
12+
<form class="ui form ignore-dirty" action="{{AppSubUrl}}/user/settings/account" method="post">
13+
{{template "base/disable_form_autofill"}}
14+
{{.CsrfTokenHtml}}
15+
{{if .SignedUser.IsPasswordSet}}
16+
<div class="required field {{if .Err_OldPassword}}error{{end}}">
17+
<label for="old_password">{{.locale.Tr "settings.old_password"}}</label>
18+
<input id="old_password" name="old_password" type="password" autocomplete="current-password" autofocus required>
19+
</div>
20+
{{end}}
21+
<div class="required field {{if .Err_Password}}error{{end}}">
22+
<label for="password">{{.locale.Tr "settings.new_password"}}</label>
23+
<input id="password" name="password" type="password" autocomplete="new-password" required>
24+
</div>
25+
<div class="required field {{if .Err_Password}}error{{end}}">
26+
<label for="retype">{{.locale.Tr "settings.retype_new_password"}}</label>
27+
<input id="retype" name="retype" type="password" autocomplete="new-password" required>
28+
</div>
2829

29-
<div class="field">
30-
<button class="ui green button">{{$.locale.Tr "settings.change_password"}}</button>
31-
<a href="{{AppSubUrl}}/user/forgot_password?email={{.Email}}">{{.locale.Tr "auth.forgot_password"}}</a>
30+
<div class="field">
31+
<button class="ui green button">{{$.locale.Tr "settings.change_password"}}</button>
32+
<a href="{{AppSubUrl}}/user/forgot_password?email={{.Email}}">{{.locale.Tr "auth.forgot_password"}}</a>
33+
</div>
34+
</form>
35+
{{else}}
36+
<div class="ui info message">
37+
<p class="text left">{{$.locale.Tr "settings.password_change_disabled"}}</p>
3238
</div>
33-
</form>
34-
{{else}}
35-
<div class="ui info message">
36-
<p class="text left">{{$.locale.Tr "settings.password_change_disabled"}}</p>
39+
{{end}}
3740
</div>
38-
{{end}}
39-
</div>
41+
{{end}}
4042

4143
<h4 class="ui top attached header">
4244
{{.locale.Tr "settings.manage_emails"}}
@@ -172,15 +174,17 @@
172174
{{template "base/delete_modal_actions" .}}
173175
</div>
174176

175-
<div class="ui small basic delete modal" id="delete-account">
176-
<div class="ui icon header">
177-
{{svg "octicon-trash"}}
178-
{{.locale.Tr "settings.delete_account_title"}}
179-
</div>
180-
<div class="content">
181-
<p>{{.locale.Tr "settings.delete_account_desc"}}</p>
177+
{{if $.UserModules.Enabled "suicide"}}
178+
<div class="ui small basic delete modal" id="delete-account">
179+
<div class="ui icon header">
180+
{{svg "octicon-trash"}}
181+
{{.locale.Tr "settings.delete_account_title"}}
182+
</div>
183+
<div class="content">
184+
<p>{{.locale.Tr "settings.delete_account_desc"}}</p>
185+
</div>
186+
{{template "base/delete_modal_actions" .}}
182187
</div>
183-
{{template "base/delete_modal_actions" .}}
184-
</div>
188+
{{end}}
185189

186190
{{template "base/footer" .}}

templates/user/settings/keys.tmpl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
{{template "base/alert" .}}
66
{{template "user/settings/keys_ssh" .}}
77
{{template "user/settings/keys_principal" .}}
8-
{{template "user/settings/keys_gpg" .}}
8+
{{if $.UserModules.Enabled "gpg keys"}}
9+
{{template "user/settings/keys_gpg" .}}
10+
{{end}}
911
</div>
1012
</div>
1113

templates/user/settings/navbar.tmpl

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@
99
<a class="{{if .PageIsSettingsAppearance}}active {{end}}item" href="{{AppSubUrl}}/user/settings/appearance">
1010
{{.locale.Tr "settings.appearance"}}
1111
</a>
12-
<a class="{{if .PageIsSettingsSecurity}}active {{end}}item" href="{{AppSubUrl}}/user/settings/security">
13-
{{.locale.Tr "settings.security"}}
14-
</a>
15-
<a class="{{if .PageIsSettingsApplications}}active {{end}}item" href="{{AppSubUrl}}/user/settings/applications">
16-
{{.locale.Tr "settings.applications"}}
17-
</a>
12+
{{if $.UserModules.Enabled "security"}}
13+
<a class="{{if .PageIsSettingsSecurity}}active {{end}}item" href="{{AppSubUrl}}/user/settings/security">
14+
{{.locale.Tr "settings.security"}}
15+
</a>
16+
{{end}}
17+
{{if $.UserModules.Enabled "applications"}}
18+
<a class="{{if .PageIsSettingsApplications}}active {{end}}item" href="{{AppSubUrl}}/user/settings/applications">
19+
{{.locale.Tr "settings.applications"}}
20+
</a>
21+
{{end}}
1822
<a class="{{if .PageIsSettingsKeys}}active {{end}}item" href="{{AppSubUrl}}/user/settings/keys">
1923
{{.locale.Tr "settings.ssh_gpg_keys"}}
2024
</a>
@@ -23,9 +27,11 @@
2327
{{.locale.Tr "packages.title"}}
2428
</a>
2529
{{end}}
26-
<a class="{{if .PageIsSettingsOrganization}}active {{end}}item" href="{{AppSubUrl}}/user/settings/organization">
27-
{{.locale.Tr "settings.organization"}}
28-
</a>
30+
{{if $.UserModules.Enabled "organizations"}}
31+
<a class="{{if .PageIsSettingsOrganization}}active {{end}}item" href="{{AppSubUrl}}/user/settings/organization">
32+
{{.locale.Tr "settings.organization"}}
33+
</a>
34+
{{end}}
2935
<a class="{{if .PageIsSettingsRepos}}active {{end}}item" href="{{AppSubUrl}}/user/settings/repos">
3036
{{.locale.Tr "settings.repos"}}
3137
</a>

0 commit comments

Comments
 (0)