Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1485,6 +1485,8 @@ LEVEL = Info
;; - manage_ssh_keys: a user cannot configure ssh keys
;; - manage_gpg_keys: a user cannot configure gpg keys
;USER_DISABLED_FEATURES =
;; Whether to disable all user features if the user has an external login type
;;EXTERNAL_USER_DISABLE_FEATURES = false

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Expand Down
18 changes: 18 additions & 0 deletions models/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -1232,3 +1232,21 @@ func GetOrderByName() string {
}
return "name"
}

// FeatureDisabledWithLoginType checks if a user feature is disabled, taking into account the login type of the
// user if applicable
func FeatureDisabledWithLoginType(user *User, feature string) bool {
// NOTE: in the long run it may be better to check the ExternalLoginUser table rather than user.LoginType
return (setting.Admin.ExternalUserDisableFeatures && user != nil && user.LoginType > auth.Plain) ||
setting.Admin.UserDisabledFeatures.Contains(feature)
}

// DisabledFeaturesWithLoginType returns the set of user features disabled, taking into account the login type
// of the user if applicable
func DisabledFeaturesWithLoginType(user *User) *container.Set[string] {
// NOTE: in the long run it may be better to check the ExternalLoginUser table rather than user.LoginType
if setting.Admin.ExternalUserDisableFeatures && user != nil && user.LoginType > auth.Plain {
return &setting.DefaultUserFeatureSet
}
return &setting.Admin.UserDisabledFeatures
}
17 changes: 13 additions & 4 deletions modules/setting/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,33 @@

package setting

import "code.gitea.io/gitea/modules/container"
import (
"code.gitea.io/gitea/modules/container"
)

// Admin settings
var Admin struct {
DisableRegularOrgCreation bool
DefaultEmailNotification string
UserDisabledFeatures container.Set[string]
DisableRegularOrgCreation bool
DefaultEmailNotification string
UserDisabledFeatures container.Set[string]
ExternalUserDisableFeatures bool
}

func loadAdminFrom(rootCfg ConfigProvider) {
sec := rootCfg.Section("admin")
Admin.DisableRegularOrgCreation = sec.Key("DISABLE_REGULAR_ORG_CREATION").MustBool(false)
Admin.DefaultEmailNotification = sec.Key("DEFAULT_EMAIL_NOTIFICATIONS").MustString("enabled")
Admin.UserDisabledFeatures = container.SetOf(sec.Key("USER_DISABLED_FEATURES").Strings(",")...)
Admin.ExternalUserDisableFeatures = sec.Key("EXTERNAL_USER_DISABLE_FEATURES").MustBool(false)
}

const (
UserFeatureDeletion = "deletion"
UserFeatureManageSSHKeys = "manage_ssh_keys"
UserFeatureManageGPGKeys = "manage_gpg_keys"
)

var DefaultUserFeatureSet = container.SetOf(
UserFeatureDeletion,
UserFeatureManageSSHKeys,
UserFeatureManageGPGKeys)
5 changes: 3 additions & 2 deletions routers/api/v1/user/gpg_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
Expand Down Expand Up @@ -133,7 +134,7 @@ 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) {
if user_model.FeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageGPGKeys) {
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
return
}
Expand Down Expand Up @@ -274,7 +275,7 @@ func DeleteGPGKey(ctx *context.APIContext) {
// "404":
// "$ref": "#/responses/notFound"

if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) {
if user_model.FeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageGPGKeys) {
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
return
}
Expand Down
4 changes: 2 additions & 2 deletions routers/api/v1/user/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func GetPublicKey(ctx *context.APIContext) {

// CreateUserPublicKey creates new public key to given user by ID.
func CreateUserPublicKey(ctx *context.APIContext, form api.CreateKeyOption, uid int64) {
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageSSHKeys) {
if user_model.FeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageSSHKeys) {
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
return
}
Expand Down Expand Up @@ -269,7 +269,7 @@ func DeletePublicKey(ctx *context.APIContext) {
// "404":
// "$ref": "#/responses/notFound"

if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageSSHKeys) {
if user_model.FeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageSSHKeys) {
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
return
}
Expand Down
4 changes: 2 additions & 2 deletions routers/web/user/setting/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ func DeleteEmail(ctx *context.Context) {

// DeleteAccount render user suicide page and response for delete user himself
func DeleteAccount(ctx *context.Context) {
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureDeletion) {
if user_model.FeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureDeletion) {
ctx.Error(http.StatusNotFound)
return
}
Expand Down Expand Up @@ -304,7 +304,7 @@ func loadAccountData(ctx *context.Context) {
ctx.Data["EmailNotificationsPreference"] = ctx.Doer.EmailNotificationsPreference
ctx.Data["ActivationsPending"] = pendingActivation
ctx.Data["CanAddEmails"] = !pendingActivation || !setting.Service.RegisterEmailConfirm
ctx.Data["UserDisabledFeatures"] = &setting.Admin.UserDisabledFeatures
ctx.Data["UserDisabledFeatures"] = user_model.DisabledFeaturesWithLoginType(ctx.Doer)

if setting.Service.UserDeleteWithCommentsMaxTime != 0 {
ctx.Data["UserDeleteWithCommentsMaxTime"] = setting.Service.UserDeleteWithCommentsMaxTime.String()
Expand Down
13 changes: 7 additions & 6 deletions routers/web/user/setting/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
Expand Down Expand Up @@ -78,7 +79,7 @@ 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) {
if user_model.FeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageGPGKeys) {
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
return
}
Expand Down Expand Up @@ -159,7 +160,7 @@ func KeysPost(ctx *context.Context) {
ctx.Flash.Success(ctx.Tr("settings.verify_gpg_key_success", keyID))
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
case "ssh":
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageSSHKeys) {
if user_model.FeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageSSHKeys) {
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
return
}
Expand Down Expand Up @@ -203,7 +204,7 @@ func KeysPost(ctx *context.Context) {
ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title))
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
case "verify_ssh":
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageSSHKeys) {
if user_model.FeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageSSHKeys) {
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
return
}
Expand Down Expand Up @@ -240,7 +241,7 @@ func KeysPost(ctx *context.Context) {
func DeleteKey(ctx *context.Context) {
switch ctx.FormString("type") {
case "gpg":
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) {
if user_model.FeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageGPGKeys) {
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
return
}
Expand All @@ -250,7 +251,7 @@ func DeleteKey(ctx *context.Context) {
ctx.Flash.Success(ctx.Tr("settings.gpg_key_deletion_success"))
}
case "ssh":
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageSSHKeys) {
if user_model.FeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageSSHKeys) {
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
return
}
Expand Down Expand Up @@ -333,5 +334,5 @@ func loadKeysData(ctx *context.Context) {

ctx.Data["VerifyingID"] = ctx.FormString("verify_gpg")
ctx.Data["VerifyingFingerprint"] = ctx.FormString("verify_ssh")
ctx.Data["UserDisabledFeatures"] = &setting.Admin.UserDisabledFeatures
ctx.Data["UserDisabledFeatures"] = user_model.DisabledFeaturesWithLoginType(ctx.Doer)
}