Follow #29447 Fix #29454 Extract from #20549tags/v1.22.0-rc0
@@ -1480,8 +1480,9 @@ LEVEL = Info | |||
;; | |||
;; Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled | |||
;DEFAULT_EMAIL_NOTIFICATIONS = enabled | |||
;; Disabled features for users, could be "deletion", more features can be disabled in future | |||
;; Disabled features for users, could be "deletion","manage_gpg_keys" more features can be disabled in future | |||
;; - deletion: a user cannot delete their own account | |||
;; - manage_gpg_keys: a user cannot configure gpg keys | |||
;USER_DISABLED_FEATURES = | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
@@ -518,8 +518,9 @@ And the following unique queues: | |||
- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**: Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled | |||
- `DISABLE_REGULAR_ORG_CREATION`: **false**: Disallow regular (non-admin) users from creating organizations. | |||
- `USER_DISABLED_FEATURES`: **_empty_** Disabled features for users, could be `deletion` and more features can be added in future. | |||
- `USER_DISABLED_FEATURES`: **_empty_** Disabled features for users, could be `deletion`, `manage_gpg_keys` and more features can be added in future. | |||
- `deletion`: User cannot delete their own account. | |||
- `manage_gpg_keys`: User cannot configure gpg keys | |||
## Security (`security`) | |||
@@ -497,8 +497,9 @@ Gitea 创建以下非唯一队列: | |||
- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**:用户电子邮件通知的默认配置(用户可配置)。选项:enabled、onmention、disabled | |||
- `DISABLE_REGULAR_ORG_CREATION`: **false**:禁止普通(非管理员)用户创建组织。 | |||
- `USER_DISABLED_FEATURES`:**_empty_** 禁用的用户特性,当前允许为空或者 `deletion`, 未来可以增加更多设置。 | |||
- `USER_DISABLED_FEATURES`:**_empty_** 禁用的用户特性,当前允许为空或者 `deletion`,`manage_gpg_keys` 未来可以增加更多设置。 | |||
- `deletion`: 用户不能通过界面或者API删除他自己。 | |||
- `manage_gpg_keys`: 用户不能配置 GPG 密钥 | |||
## 安全性 (`security`) | |||
@@ -20,5 +20,6 @@ func loadAdminFrom(rootCfg ConfigProvider) { | |||
} | |||
const ( | |||
UserFeatureDeletion = "deletion" | |||
UserFeatureDeletion = "deletion" | |||
UserFeatureManageGPGKeys = "manage_gpg_keys" | |||
) |
@@ -10,6 +10,7 @@ import ( | |||
asymkey_model "code.gitea.io/gitea/models/asymkey" | |||
"code.gitea.io/gitea/models/db" | |||
"code.gitea.io/gitea/modules/setting" | |||
api "code.gitea.io/gitea/modules/structs" | |||
"code.gitea.io/gitea/modules/web" | |||
"code.gitea.io/gitea/routers/api/v1/utils" | |||
@@ -132,6 +133,11 @@ func GetGPGKey(ctx *context.APIContext) { | |||
// CreateUserGPGKey creates new GPG key to given user by ID. | |||
func CreateUserGPGKey(ctx *context.APIContext, form api.CreateGPGKeyOption, uid int64) { | |||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) { | |||
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited")) | |||
return | |||
} | |||
token := asymkey_model.VerificationToken(ctx.Doer, 1) | |||
lastToken := asymkey_model.VerificationToken(ctx.Doer, 0) | |||
@@ -268,6 +274,11 @@ func DeleteGPGKey(ctx *context.APIContext) { | |||
// "404": | |||
// "$ref": "#/responses/notFound" | |||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) { | |||
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited")) | |||
return | |||
} | |||
if err := asymkey_model.DeleteGPGKey(ctx, ctx.Doer, ctx.ParamsInt64(":id")); err != nil { | |||
if asymkey_model.IsErrGPGKeyAccessDenied(err) { | |||
ctx.Error(http.StatusForbidden, "", "You do not have access to this key") |
@@ -5,6 +5,7 @@ | |||
package setting | |||
import ( | |||
"fmt" | |||
"net/http" | |||
asymkey_model "code.gitea.io/gitea/models/asymkey" | |||
@@ -77,6 +78,11 @@ func KeysPost(ctx *context.Context) { | |||
ctx.Flash.Success(ctx.Tr("settings.add_principal_success", form.Content)) | |||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys") | |||
case "gpg": | |||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) { | |||
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited")) | |||
return | |||
} | |||
token := asymkey_model.VerificationToken(ctx.Doer, 1) | |||
lastToken := asymkey_model.VerificationToken(ctx.Doer, 0) | |||
@@ -224,6 +230,10 @@ func KeysPost(ctx *context.Context) { | |||
func DeleteKey(ctx *context.Context) { | |||
switch ctx.FormString("type") { | |||
case "gpg": | |||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) { | |||
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited")) | |||
return | |||
} | |||
if err := asymkey_model.DeleteGPGKey(ctx, ctx.Doer, ctx.FormInt64("id")); err != nil { | |||
ctx.Flash.Error("DeleteGPGKey: " + err.Error()) | |||
} else { |
@@ -2,6 +2,8 @@ | |||
<div class="user-setting-content"> | |||
{{template "user/settings/keys_ssh" .}} | |||
{{template "user/settings/keys_principal" .}} | |||
{{if not ($.UserDisabledFeatures.Contains "manage_gpg_keys")}} | |||
{{template "user/settings/keys_gpg" .}} | |||
{{end}} | |||
</div> | |||
{{template "user/settings/layout_footer" .}} |