mirror of
https://github.com/go-gitea/gitea.git
synced 2026-03-05 23:23:10 +01:00
Use "Enable Gravatar" but not "Disable" (#36771)
* Fix #35685 * Fix #35627 * Fix #31112 Introduce "fipped" config value type, remove unused setting variables. Make DisableGravatar=true by defult, remove useless config options from the "Install" page. The legacy config options are still kept because they are still the fallback values for the system config options. --------- Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
parent
fde7f7db28
commit
ae2b19849d
@ -238,9 +238,6 @@ RUN_USER = ; git
|
||||
;; Indicate whether to check minimum key size with corresponding type
|
||||
;MINIMUM_KEY_SIZE_CHECK = false
|
||||
;;
|
||||
;; Disable CDN even in "prod" mode
|
||||
;OFFLINE_MODE = true
|
||||
;;
|
||||
;; TLS Settings: Either ACME or manual
|
||||
;; (Other common TLS configuration are found before)
|
||||
;ENABLE_ACME = false
|
||||
@ -1983,12 +1980,12 @@ LEVEL = Info
|
||||
;; or a custom avatar source, like: http://cn.gravatar.com/avatar/
|
||||
;GRAVATAR_SOURCE = gravatar
|
||||
;;
|
||||
;; This value will always be true in offline mode.
|
||||
;; Deprecated, see Web UI Admin Panel -> Config -> Settings
|
||||
;DISABLE_GRAVATAR = false
|
||||
;;
|
||||
;; Federated avatar lookup uses DNS to discover avatar associated
|
||||
;; with emails, see https://www.libravatar.org
|
||||
;; This value will always be false in offline mode or when Gravatar is disabled.
|
||||
;; Deprecated, see Web UI Admin Panel -> Config -> Settings
|
||||
;ENABLE_FEDERATED_AVATAR = false
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@ -74,7 +74,7 @@ func (u *User) AvatarLinkWithSize(ctx context.Context, size int) string {
|
||||
switch {
|
||||
case u.UseCustomAvatar:
|
||||
useLocalAvatar = true
|
||||
case disableGravatar, setting.OfflineMode:
|
||||
case disableGravatar:
|
||||
useLocalAvatar = true
|
||||
autoGenerateAvatar = true
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ func initDefaultConfig() {
|
||||
config.SetCfgSecKeyGetter(&cfgSecKeyGetter{})
|
||||
defaultConfig = &ConfigStruct{
|
||||
Picture: &PictureStruct{
|
||||
DisableGravatar: config.NewOption[bool]("picture.disable_gravatar").WithFileConfig(config.CfgSecKey{Sec: "picture", Key: "DISABLE_GRAVATAR"}),
|
||||
DisableGravatar: config.NewOption[bool]("picture.disable_gravatar").WithDefaultSimple(true).WithFileConfig(config.CfgSecKey{Sec: "picture", Key: "DISABLE_GRAVATAR"}),
|
||||
EnableFederatedAvatar: config.NewOption[bool]("picture.enable_federated_avatar").WithFileConfig(config.CfgSecKey{Sec: "picture", Key: "ENABLE_FEDERATED_AVATAR"}),
|
||||
},
|
||||
Repository: &RepositoryStruct{
|
||||
|
||||
@ -102,7 +102,7 @@ func (opt *Option[T]) ValueRevision(ctx context.Context) (v T, rev int, has bool
|
||||
var valStr *string
|
||||
if dynVal, hasDbValue := dg.GetValue(ctx, opt.dynKey); hasDbValue {
|
||||
valStr = &dynVal
|
||||
} else if cfgVal, has := GetCfgSecKeyGetter().GetValue(opt.cfgSecKey.Sec, opt.cfgSecKey.Key); has {
|
||||
} else if cfgVal, hasCfgValue := GetCfgSecKeyGetter().GetValue(opt.cfgSecKey.Sec, opt.cfgSecKey.Key); hasCfgValue {
|
||||
valStr = &cfgVal
|
||||
}
|
||||
if valStr == nil {
|
||||
|
||||
@ -22,9 +22,7 @@ var (
|
||||
RenderedSizeFactor: 2,
|
||||
}
|
||||
|
||||
GravatarSource string
|
||||
DisableGravatar bool // Depreciated: migrated to database
|
||||
EnableFederatedAvatar bool // Depreciated: migrated to database
|
||||
GravatarSource string
|
||||
|
||||
RepoAvatar = struct {
|
||||
Storage *Storage
|
||||
@ -65,29 +63,12 @@ func loadAvatarsFrom(rootCfg ConfigProvider) error {
|
||||
GravatarSource = source
|
||||
}
|
||||
|
||||
DisableGravatar = sec.Key("DISABLE_GRAVATAR").MustBool(GetDefaultDisableGravatar())
|
||||
deprecatedSettingDB(rootCfg, "", "DISABLE_GRAVATAR")
|
||||
EnableFederatedAvatar = sec.Key("ENABLE_FEDERATED_AVATAR").MustBool(GetDefaultEnableFederatedAvatar(DisableGravatar))
|
||||
deprecatedSettingDB(rootCfg, "", "ENABLE_FEDERATED_AVATAR")
|
||||
deprecatedSettingDB(rootCfg, "picture", "DISABLE_GRAVATAR")
|
||||
deprecatedSettingDB(rootCfg, "picture", "ENABLE_FEDERATED_AVATAR")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetDefaultDisableGravatar() bool {
|
||||
return OfflineMode
|
||||
}
|
||||
|
||||
func GetDefaultEnableFederatedAvatar(disableGravatar bool) bool {
|
||||
v := !InstallLock
|
||||
if OfflineMode {
|
||||
v = false
|
||||
}
|
||||
if disableGravatar {
|
||||
v = false
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func loadRepoAvatarFrom(rootCfg ConfigProvider) error {
|
||||
sec := rootCfg.Section("picture")
|
||||
|
||||
|
||||
@ -91,7 +91,6 @@ var (
|
||||
RedirectOtherPort bool
|
||||
RedirectorUseProxyProtocol bool
|
||||
PortToRedirect string
|
||||
OfflineMode bool
|
||||
CertFile string
|
||||
KeyFile string
|
||||
StaticRootPath string
|
||||
@ -346,7 +345,6 @@ func loadServerFrom(rootCfg ConfigProvider) {
|
||||
RedirectOtherPort = sec.Key("REDIRECT_OTHER_PORT").MustBool(false)
|
||||
PortToRedirect = sec.Key("PORT_TO_REDIRECT").MustString("80")
|
||||
RedirectorUseProxyProtocol = sec.Key("REDIRECTOR_USE_PROXY_PROTOCOL").MustBool(UseProxyProtocol)
|
||||
OfflineMode = sec.Key("OFFLINE_MODE").MustBool(true)
|
||||
if len(StaticRootPath) == 0 {
|
||||
StaticRootPath = AppWorkPath
|
||||
}
|
||||
|
||||
@ -285,12 +285,6 @@
|
||||
"install.register_confirm": "Require Email Confirmation to Register",
|
||||
"install.mail_notify": "Enable Email Notifications",
|
||||
"install.server_service_title": "Server and Third-Party Service Settings",
|
||||
"install.offline_mode": "Enable Local Mode",
|
||||
"install.offline_mode_popup": "Disable third-party content delivery networks and serve all resources locally.",
|
||||
"install.disable_gravatar": "Disable Gravatar",
|
||||
"install.disable_gravatar_popup": "Disable Gravatar and third-party avatar sources. A default avatar will be used unless a user locally uploads an avatar.",
|
||||
"install.federated_avatar_lookup": "Enable Federated Avatars",
|
||||
"install.federated_avatar_lookup_popup": "Enable federated avatar lookup using Libravatar.",
|
||||
"install.disable_registration": "Disable Self-Registration",
|
||||
"install.disable_registration_popup": "Disable user self-registration. Only administrators will be able to create new user accounts.",
|
||||
"install.allow_only_external_registration_popup": "Allow Registration Only Through External Services",
|
||||
@ -3193,7 +3187,6 @@
|
||||
"admin.config.custom_conf": "Configuration File Path",
|
||||
"admin.config.custom_file_root_path": "Custom File Root Path",
|
||||
"admin.config.domain": "Server Domain",
|
||||
"admin.config.offline_mode": "Local Mode",
|
||||
"admin.config.disable_router_log": "Disable Router Log",
|
||||
"admin.config.run_user": "Run As Username",
|
||||
"admin.config.run_mode": "Run Mode",
|
||||
@ -3296,7 +3289,7 @@
|
||||
"admin.config.cookie_life_time": "Cookie Life Time",
|
||||
"admin.config.picture_config": "Picture and Avatar Configuration",
|
||||
"admin.config.picture_service": "Picture Service",
|
||||
"admin.config.disable_gravatar": "Disable Gravatar",
|
||||
"admin.config.enable_gravatar": "Enable Gravatar",
|
||||
"admin.config.enable_federated_avatar": "Enable Federated Avatars",
|
||||
"admin.config.open_with_editor_app_help": "The \"Open with\" editors for the clone menu. If left empty, the default will be used. Expand to see the default.",
|
||||
"admin.config.git_guide_remote_name": "Repository remote name for git commands in the guide",
|
||||
|
||||
@ -17,7 +17,6 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
db_install "code.gitea.io/gitea/models/db/install"
|
||||
system_model "code.gitea.io/gitea/models/system"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/auth/password/hash"
|
||||
"code.gitea.io/gitea/modules/generate"
|
||||
@ -114,11 +113,6 @@ func Install(ctx *context.Context) {
|
||||
form.RegisterConfirm = setting.Service.RegisterEmailConfirm
|
||||
form.MailNotify = setting.Service.EnableNotifyMail
|
||||
|
||||
// Server and other services settings
|
||||
form.OfflineMode = setting.OfflineMode
|
||||
form.DisableGravatar = setting.DisableGravatar // when installing, there is no database connection so that given a default value
|
||||
form.EnableFederatedAvatar = setting.EnableFederatedAvatar // when installing, there is no database connection so that given a default value
|
||||
|
||||
form.EnableOpenIDSignIn = setting.Service.EnableOpenIDSignIn
|
||||
form.EnableOpenIDSignUp = setting.Service.EnableOpenIDSignUp
|
||||
form.DisableRegistration = setting.Service.DisableRegistration
|
||||
@ -405,15 +399,6 @@ func SubmitInstall(ctx *context.Context) {
|
||||
cfg.Section("service").Key("REGISTER_EMAIL_CONFIRM").SetValue(strconv.FormatBool(form.RegisterConfirm))
|
||||
cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").SetValue(strconv.FormatBool(form.MailNotify))
|
||||
|
||||
cfg.Section("server").Key("OFFLINE_MODE").SetValue(strconv.FormatBool(form.OfflineMode))
|
||||
if err := system_model.SetSettings(ctx, map[string]string{
|
||||
setting.Config().Picture.DisableGravatar.DynKey(): strconv.FormatBool(form.DisableGravatar),
|
||||
setting.Config().Picture.EnableFederatedAvatar.DynKey(): strconv.FormatBool(form.EnableFederatedAvatar),
|
||||
}); err != nil {
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
|
||||
return
|
||||
}
|
||||
|
||||
cfg.Section("openid").Key("ENABLE_OPENID_SIGNIN").SetValue(strconv.FormatBool(form.EnableOpenIDSignIn))
|
||||
cfg.Section("openid").Key("ENABLE_OPENID_SIGNUP").SetValue(strconv.FormatBool(form.EnableOpenIDSignUp))
|
||||
cfg.Section("service").Key("DISABLE_REGISTRATION").SetValue(strconv.FormatBool(form.DisableRegistration))
|
||||
|
||||
@ -126,7 +126,6 @@ func Config(ctx *context.Context) {
|
||||
ctx.Data["AppUrl"] = setting.AppURL
|
||||
ctx.Data["AppBuiltWith"] = setting.AppBuiltWith
|
||||
ctx.Data["Domain"] = setting.Domain
|
||||
ctx.Data["OfflineMode"] = setting.OfflineMode
|
||||
ctx.Data["RunUser"] = setting.RunUser
|
||||
ctx.Data["RunMode"] = util.ToTitleCase(setting.RunMode)
|
||||
ctx.Data["GitVersion"] = git.DefaultFeatures().VersionInfo()
|
||||
|
||||
@ -45,9 +45,6 @@ type InstallForm struct {
|
||||
RegisterConfirm bool
|
||||
MailNotify bool
|
||||
|
||||
OfflineMode bool
|
||||
DisableGravatar bool
|
||||
EnableFederatedAvatar bool
|
||||
EnableOpenIDSignIn bool
|
||||
EnableOpenIDSignUp bool
|
||||
DisableRegistration bool
|
||||
|
||||
@ -15,8 +15,6 @@
|
||||
<dd>{{.AppUrl}}</dd>
|
||||
<dt>{{ctx.Locale.Tr "admin.config.domain"}}</dt>
|
||||
<dd>{{.Domain}}</dd>
|
||||
<dt>{{ctx.Locale.Tr "admin.config.offline_mode"}}</dt>
|
||||
<dd>{{svg (Iif .OfflineMode "octicon-check" "octicon-x")}}</dd>
|
||||
<dt>{{ctx.Locale.Tr "admin.config.disable_router_log"}}</dt>
|
||||
<dd>{{svg (Iif .DisableRouterLog "octicon-check" "octicon-x")}}</dd>
|
||||
|
||||
|
||||
@ -3,17 +3,21 @@
|
||||
</h4>
|
||||
<div class="ui attached table segment">
|
||||
<dl class="admin-dl-horizontal">
|
||||
<dt>{{ctx.Locale.Tr "admin.config.disable_gravatar"}}</dt>
|
||||
{{$cfgOpt := .SystemConfig.Picture.DisableGravatar}}
|
||||
<dt>{{ctx.Locale.Tr "admin.config.enable_gravatar"}}</dt>
|
||||
<dd>
|
||||
<div class="ui toggle checkbox" data-tooltip-content="{{ctx.Locale.Tr "admin.config.disable_gravatar"}}">
|
||||
<input type="checkbox" data-config-dyn-key="picture.disable_gravatar" {{if .SystemConfig.Picture.DisableGravatar.Value ctx}}checked{{end}}><label></label>
|
||||
<div class="ui toggle checkbox" data-tooltip-content="{{ctx.Locale.Tr "admin.config.enable_gravatar"}}">
|
||||
<input type="checkbox" data-config-dyn-key="{{$cfgOpt.DynKey}}" data-config-value-type="flipped" {{if not ($cfgOpt.Value ctx)}}checked{{end}}><label></label>
|
||||
</div>
|
||||
</dd>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
{{$cfgOpt = .SystemConfig.Picture.EnableFederatedAvatar}}
|
||||
<dt>{{ctx.Locale.Tr "admin.config.enable_federated_avatar"}}</dt>
|
||||
<dd>
|
||||
<div class="ui toggle checkbox" data-tooltip-content="{{ctx.Locale.Tr "admin.config.enable_federated_avatar"}}">
|
||||
<input type="checkbox" data-config-dyn-key="picture.enable_federated_avatar" {{if .SystemConfig.Picture.EnableFederatedAvatar.Value ctx}}checked{{end}}><label></label>
|
||||
<input type="checkbox" data-config-dyn-key="{{$cfgOpt.DynKey}}" data-config-value-type="boolean" {{if $cfgOpt.Value ctx}}checked{{end}}><label></label>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
@ -203,24 +203,6 @@
|
||||
<summary class="right-content tw-py-2{{if .Err_Services}} tw-text-red{{end}}">
|
||||
{{ctx.Locale.Tr "install.server_service_title"}}
|
||||
</summary>
|
||||
<div class="inline field">
|
||||
<div class="ui checkbox" id="offline-mode">
|
||||
<label data-tooltip-content="{{ctx.Locale.Tr "install.offline_mode_popup"}}">{{ctx.Locale.Tr "install.offline_mode"}}</label>
|
||||
<input name="offline_mode" type="checkbox" {{if .offline_mode}}checked{{end}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<div class="ui checkbox" id="disable-gravatar">
|
||||
<label data-tooltip-content="{{ctx.Locale.Tr "install.disable_gravatar_popup"}}">{{ctx.Locale.Tr "install.disable_gravatar"}}</label>
|
||||
<input name="disable_gravatar" type="checkbox" {{if .disable_gravatar}}checked{{end}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<div class="ui checkbox" id="federated-avatar-lookup">
|
||||
<label data-tooltip-content="{{ctx.Locale.Tr "install.federated_avatar_lookup_popup"}}">{{ctx.Locale.Tr "install.federated_avatar_lookup"}}</label>
|
||||
<input name="enable_federated_avatar" type="checkbox" {{if .enable_federated_avatar}}checked{{end}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<div class="ui checkbox" id="enable-openid-signin">
|
||||
<label data-tooltip-content="{{ctx.Locale.Tr "install.openid_signin_popup"}}">{{ctx.Locale.Tr "install.openid_signin"}}</label>
|
||||
|
||||
@ -41,7 +41,6 @@ SSH_LISTEN_HOST = localhost
|
||||
SSH_PORT = 2201
|
||||
START_SSH_SERVER = true
|
||||
LFS_START_SERVER = true
|
||||
OFFLINE_MODE = false
|
||||
LFS_JWT_SECRET = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w
|
||||
BUILTIN_SSH_SERVER_USER = git
|
||||
SSH_TRUSTED_USER_CA_KEYS = ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCb4DC1dMFnJ6pXWo7GMxTchtzmJHYzfN6sZ9FAPFR4ijMLfGki+olvOMO5Fql1/yGnGfbELQa1S6y4shSvj/5K+zUFScmEXYf3Gcr87RqilLkyk16RS+cHNB1u87xTHbETaa3nyCJeGQRpd4IQ4NKob745mwDZ7jQBH8AZEng50Oh8y8fi8skBBBzaYp1ilgvzG740L7uex6fHV62myq0SXeCa+oJUjq326FU8y+Vsa32H8A3e7tOgXZPdt2TVNltx2S9H2WO8RMi7LfaSwARNfy1zu+bfR50r6ef8Yx5YKCMz4wWb1SHU1GS800mjOjlInLQORYRNMlSwR1+vLlVDciOqFapDSbj+YOVOawR0R1aqlSKpZkt33DuOBPx9qe6CVnIi7Z+Px/KqM+OLCzlLY/RS+LbxQpDWcfTVRiP+S5qRTcE3M3UioN/e0BE/1+MpX90IGpvVkA63ILYbKEa4bM3ASL7ChTCr6xN5XT+GpVJveFKK1cfNx9ExHI4rzYE=
|
||||
@ -62,10 +61,6 @@ DEFAULT_ALLOW_CREATE_ORGANIZATION = true
|
||||
NO_REPLY_ADDRESS = noreply.example.org
|
||||
ENABLE_NOTIFY_MAIL = true
|
||||
|
||||
[picture]
|
||||
DISABLE_GRAVATAR = false
|
||||
ENABLE_FEDERATED_AVATAR = false
|
||||
|
||||
[session]
|
||||
PROVIDER = file
|
||||
|
||||
|
||||
@ -43,7 +43,6 @@ SSH_LISTEN_HOST = localhost
|
||||
SSH_PORT = 2201
|
||||
BUILTIN_SSH_SERVER_USER = git
|
||||
START_SSH_SERVER = true
|
||||
OFFLINE_MODE = false
|
||||
|
||||
LFS_START_SERVER = true
|
||||
LFS_JWT_SECRET = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w
|
||||
@ -65,10 +64,6 @@ DEFAULT_ALLOW_CREATE_ORGANIZATION = true
|
||||
NO_REPLY_ADDRESS = noreply.example.org
|
||||
ENABLE_NOTIFY_MAIL = true
|
||||
|
||||
[picture]
|
||||
DISABLE_GRAVATAR = false
|
||||
ENABLE_FEDERATED_AVATAR = false
|
||||
|
||||
[session]
|
||||
PROVIDER = file
|
||||
|
||||
|
||||
@ -42,7 +42,6 @@ SSH_LISTEN_HOST = localhost
|
||||
SSH_PORT = 2202
|
||||
START_SSH_SERVER = true
|
||||
LFS_START_SERVER = true
|
||||
OFFLINE_MODE = false
|
||||
LFS_JWT_SECRET = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w
|
||||
BUILTIN_SSH_SERVER_USER = git
|
||||
SSH_TRUSTED_USER_CA_KEYS = ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCb4DC1dMFnJ6pXWo7GMxTchtzmJHYzfN6sZ9FAPFR4ijMLfGki+olvOMO5Fql1/yGnGfbELQa1S6y4shSvj/5K+zUFScmEXYf3Gcr87RqilLkyk16RS+cHNB1u87xTHbETaa3nyCJeGQRpd4IQ4NKob745mwDZ7jQBH8AZEng50Oh8y8fi8skBBBzaYp1ilgvzG740L7uex6fHV62myq0SXeCa+oJUjq326FU8y+Vsa32H8A3e7tOgXZPdt2TVNltx2S9H2WO8RMi7LfaSwARNfy1zu+bfR50r6ef8Yx5YKCMz4wWb1SHU1GS800mjOjlInLQORYRNMlSwR1+vLlVDciOqFapDSbj+YOVOawR0R1aqlSKpZkt33DuOBPx9qe6CVnIi7Z+Px/KqM+OLCzlLY/RS+LbxQpDWcfTVRiP+S5qRTcE3M3UioN/e0BE/1+MpX90IGpvVkA63ILYbKEa4bM3ASL7ChTCr6xN5XT+GpVJveFKK1cfNx9ExHI4rzYE=
|
||||
@ -63,10 +62,6 @@ DEFAULT_ALLOW_CREATE_ORGANIZATION = true
|
||||
NO_REPLY_ADDRESS = noreply.example.org
|
||||
ENABLE_NOTIFY_MAIL = true
|
||||
|
||||
[picture]
|
||||
DISABLE_GRAVATAR = false
|
||||
ENABLE_FEDERATED_AVATAR = false
|
||||
|
||||
[session]
|
||||
PROVIDER = file
|
||||
|
||||
|
||||
@ -37,7 +37,6 @@ SSH_LISTEN_HOST = localhost
|
||||
SSH_PORT = 2203
|
||||
START_SSH_SERVER = true
|
||||
LFS_START_SERVER = true
|
||||
OFFLINE_MODE = false
|
||||
LFS_JWT_SECRET = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w
|
||||
ENABLE_GZIP = true
|
||||
BUILTIN_SSH_SERVER_USER = git
|
||||
@ -59,10 +58,6 @@ DEFAULT_KEEP_EMAIL_PRIVATE = false
|
||||
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
|
||||
NO_REPLY_ADDRESS = noreply.example.org
|
||||
|
||||
[picture]
|
||||
DISABLE_GRAVATAR = false
|
||||
ENABLE_FEDERATED_AVATAR = false
|
||||
|
||||
[session]
|
||||
PROVIDER = file
|
||||
|
||||
|
||||
@ -7,10 +7,15 @@ test('ConfigFormValueMapper', () => {
|
||||
|
||||
<!-- top-level key -->
|
||||
<input name="k1" type="checkbox" value="v-key-only" data-config-dyn-key="k1" data-config-value-json="true" data-config-value-type="boolean">
|
||||
|
||||
<input type="hidden" data-config-dyn-key="k2" data-config-value-json='"k2-val"'>
|
||||
<input name="k2">
|
||||
|
||||
<textarea name="repository.open-with.editor-apps"> a = b\n</textarea>
|
||||
|
||||
<input name="k-flipped-true" type="checkbox" data-config-value-type="flipped">
|
||||
<input name="k-flipped-false" type="checkbox" checked data-config-value-type="flipped">
|
||||
|
||||
<!-- sub key -->
|
||||
<input type="hidden" data-config-dyn-key="struct" data-config-value-json='{"SubBoolean": true, "SubTimestamp": 123456789, "OtherKey": "other-value"}'>
|
||||
<input name="struct.SubBoolean" type="checkbox" data-config-value-type="boolean">
|
||||
@ -35,6 +40,8 @@ test('ConfigFormValueMapper', () => {
|
||||
expect(result).toEqual({
|
||||
'k1': 'true',
|
||||
'k2': '"k2-val"',
|
||||
'k-flipped-false': 'false',
|
||||
'k-flipped-true': 'true',
|
||||
'repository.open-with.editor-apps': '[{"DisplayName":"a","OpenURL":"b"}]', // TODO: OPEN-WITH-EDITOR-APP-JSON: it must match backend
|
||||
'struct': '{"SubBoolean":true,"SubTimestamp":123456780,"OtherKey":"other-value","NewKey":"new-value"}',
|
||||
});
|
||||
|
||||
@ -6,14 +6,23 @@ import {submitFormFetchAction} from '../common-fetch-action.ts';
|
||||
|
||||
const {appSubUrl} = window.config;
|
||||
|
||||
function collectCheckboxBooleanValue(el: HTMLInputElement): boolean {
|
||||
const valType = el.getAttribute('data-config-value-type') as ConfigValueType;
|
||||
if (valType === 'boolean') return el.checked;
|
||||
if (valType === 'flipped') return !el.checked;
|
||||
requireExplicitValueType(el);
|
||||
}
|
||||
|
||||
function initSystemConfigAutoCheckbox(el: HTMLInputElement) {
|
||||
el.addEventListener('change', async () => {
|
||||
// if the checkbox is inside a form, we assume it's handled by the form submit and do not send an individual request
|
||||
if (el.closest('form')) return;
|
||||
try {
|
||||
const resp = await POST(`${appSubUrl}/-/admin/config`, {
|
||||
data: new URLSearchParams({key: el.getAttribute('data-config-dyn-key')!, value: String(el.checked)}),
|
||||
const data = new URLSearchParams({
|
||||
key: el.getAttribute('data-config-dyn-key')!,
|
||||
value: String(collectCheckboxBooleanValue(el)),
|
||||
});
|
||||
const resp = await POST(`${appSubUrl}/-/admin/config`, {data});
|
||||
const json: Record<string, any> = await resp.json();
|
||||
if (json.errorMessage) throw new Error(json.errorMessage);
|
||||
} catch (ex) {
|
||||
@ -47,7 +56,7 @@ function extractElemConfigSubKey(el: GeneralFormFieldElement, dynKey: string): s
|
||||
|
||||
// Due to the different design between HTML form elements and the JSON struct of the config values, we need to explicitly define some types.
|
||||
// * checkbox can be used for boolean value, it can also be used for multiple values (array)
|
||||
type ConfigValueType = 'boolean' | 'string' | 'number' | 'timestamp'; // TODO: support more types like array, not used at the moment.
|
||||
type ConfigValueType = 'boolean' | 'flipped' | 'string' | 'number' | 'timestamp'; // TODO: support more types like array, not used at the moment.
|
||||
|
||||
function toDatetimeLocalValue(unixSeconds: number) {
|
||||
const d = new Date(unixSeconds * 1000);
|
||||
@ -102,13 +111,14 @@ export class ConfigFormValueMapper {
|
||||
return true;
|
||||
}
|
||||
|
||||
collectConfigValueFromElement(el: GeneralFormFieldElement, _oldVal: any = null) {
|
||||
collectConfigValueFromElement(el: GeneralFormFieldElement) {
|
||||
let val: any;
|
||||
const valType = this.presetValueTypes[el.name];
|
||||
if (el.matches('[type="checkbox"]')) {
|
||||
if (valType !== 'boolean') requireExplicitValueType(el);
|
||||
val = el.checked;
|
||||
// oldVal: for future use when we support array value with checkbox
|
||||
// TODO: if it needs to support array values in the future,
|
||||
// it needs to iterate the "namedElems" to find all the checkboxes with the same name and collect values accordingly,
|
||||
// and set the namedElems[matchedIdx] to null to avoid duplicate processing.
|
||||
val = collectCheckboxBooleanValue(el);
|
||||
} else if (el.matches('[type="datetime-local"]')) {
|
||||
if (valType !== 'timestamp') requireExplicitValueType(el);
|
||||
val = Math.floor(new Date(el.value).getTime() / 1000) ?? 0; // NaN is fine to JSON.stringify, it becomes null.
|
||||
@ -128,7 +138,7 @@ export class ConfigFormValueMapper {
|
||||
if (!el) continue;
|
||||
const subKey = extractElemConfigSubKey(el, dynKey);
|
||||
if (!subKey) continue; // if not match, skip
|
||||
cfgVal[subKey] = this.collectConfigValueFromElement(el, cfgVal[subKey]);
|
||||
cfgVal[subKey] = this.collectConfigValueFromElement(el);
|
||||
namedElems[idx] = null;
|
||||
}
|
||||
}
|
||||
@ -180,6 +190,7 @@ export class ConfigFormValueMapper {
|
||||
|
||||
// now, the namedElems should only contain the config options without sub values,
|
||||
// directly store the value in formData with key as the element name, for example:
|
||||
// "foo.enabled" => "true"
|
||||
for (const el of namedElems) {
|
||||
if (!el) continue;
|
||||
const dynKey = el.name;
|
||||
|
||||
@ -60,25 +60,6 @@ function initPreInstall() {
|
||||
}
|
||||
|
||||
// TODO: better handling of exclusive relations.
|
||||
document.querySelector<HTMLInputElement>('#offline-mode input')!.addEventListener('change', function () {
|
||||
if (this.checked) {
|
||||
document.querySelector<HTMLInputElement>('#disable-gravatar input')!.checked = true;
|
||||
document.querySelector<HTMLInputElement>('#federated-avatar-lookup input')!.checked = false;
|
||||
}
|
||||
});
|
||||
document.querySelector<HTMLInputElement>('#disable-gravatar input')!.addEventListener('change', function () {
|
||||
if (this.checked) {
|
||||
document.querySelector<HTMLInputElement>('#federated-avatar-lookup input')!.checked = false;
|
||||
} else {
|
||||
document.querySelector<HTMLInputElement>('#offline-mode input')!.checked = false;
|
||||
}
|
||||
});
|
||||
document.querySelector<HTMLInputElement>('#federated-avatar-lookup input')!.addEventListener('change', function () {
|
||||
if (this.checked) {
|
||||
document.querySelector<HTMLInputElement>('#disable-gravatar input')!.checked = false;
|
||||
document.querySelector<HTMLInputElement>('#offline-mode input')!.checked = false;
|
||||
}
|
||||
});
|
||||
document.querySelector<HTMLInputElement>('#enable-openid-signin input')!.addEventListener('change', function () {
|
||||
if (this.checked) {
|
||||
if (!document.querySelector<HTMLInputElement>('#disable-registration input')!.checked) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user