Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add setting to disable user features when user login type is not plain #29615

Merged
Merged
Show file tree
Hide file tree
Changes from 6 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
jackHay22 marked this conversation as resolved.
Show resolved Hide resolved
;;EXTERNAL_USER_DISABLE_ALL_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 {
jackHay22 marked this conversation as resolved.
Show resolved Hide resolved
// NOTE: in the long run it may be better to check the ExternalLoginUser table rather than user.LoginType
return (setting.Admin.ExternalUserDisableAllFeatures && 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.ExternalUserDisableAllFeatures && 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]
ExternalUserDisableAllFeatures 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.ExternalUserDisableAllFeatures = sec.Key("EXTERNAL_USER_DISABLE_ALL_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)
}
Loading