mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-26 20:52:41 +01:00
feat: inverted disable_gravatar logic to enable_gravatar
Frontend still interacts directly with the database entry name `picture.disable_gravatar` so logic needs flipped when writing, but logic to read automatically flips based on config.Invert() being called during init or INI read.
This commit is contained in:
parent
ebd88af075
commit
589712db26
@ -216,8 +216,8 @@ func generateEmailAvatarLink(ctx context.Context, email string, size int, final
|
||||
return urlStr
|
||||
}
|
||||
|
||||
disableGravatar := setting.Config().Picture.DisableGravatar.Value(ctx)
|
||||
if !disableGravatar {
|
||||
enableGravatar := setting.Config().Picture.EnableGravatar.Value(ctx)
|
||||
if enableGravatar {
|
||||
// copy GravatarSourceURL, because we will modify its Path.
|
||||
avatarURLCopy := *avatarSetting.gravatarSourceURL
|
||||
avatarURLCopy.Path = path.Join(avatarURLCopy.Path, HashEmail(email))
|
||||
|
||||
@ -19,12 +19,14 @@ const gravatarSource = "https://secure.gravatar.com/avatar/"
|
||||
func disableGravatar(t *testing.T) {
|
||||
err := system_model.SetSettings(t.Context(), map[string]string{setting.Config().Picture.EnableFederatedAvatar.DynKey(): "false"})
|
||||
assert.NoError(t, err)
|
||||
err = system_model.SetSettings(t.Context(), map[string]string{setting.Config().Picture.DisableGravatar.DynKey(): "true"})
|
||||
// EnableGravatar.DynKey == picture.disable_gravatar for backwards compatability; .Value will flip correctly but the true value here is misleading
|
||||
err = system_model.SetSettings(t.Context(), map[string]string{setting.Config().Picture.EnableGravatar.DynKey(): "true"})
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func enableGravatar(t *testing.T) {
|
||||
err := system_model.SetSettings(t.Context(), map[string]string{setting.Config().Picture.DisableGravatar.DynKey(): "false"})
|
||||
// EnableGravatar.DynKey == picture.disable_gravatar for backwards compatability; .Value will flip correctly but the false value here is misleading
|
||||
err := system_model.SetSettings(t.Context(), map[string]string{setting.Config().Picture.EnableGravatar.DynKey(): "false"})
|
||||
assert.NoError(t, err)
|
||||
setting.GravatarSource = gravatarSource
|
||||
}
|
||||
|
||||
@ -69,12 +69,12 @@ func (u *User) AvatarLinkWithSize(ctx context.Context, size int) string {
|
||||
useLocalAvatar := false
|
||||
autoGenerateAvatar := false
|
||||
|
||||
disableGravatar := setting.Config().Picture.DisableGravatar.Value(ctx)
|
||||
enableGravatar := setting.Config().Picture.EnableGravatar.Value(ctx)
|
||||
|
||||
switch {
|
||||
case u.UseCustomAvatar:
|
||||
case u.UseCustomAvatar, enableGravatar:
|
||||
useLocalAvatar = true
|
||||
case disableGravatar, setting.OfflineMode:
|
||||
case setting.OfflineMode:
|
||||
useLocalAvatar = true
|
||||
autoGenerateAvatar = true
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
type PictureStruct struct {
|
||||
DisableGravatar *config.Value[bool]
|
||||
EnableGravatar *config.Value[bool]
|
||||
EnableFederatedAvatar *config.Value[bool]
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ func initDefaultConfig() {
|
||||
config.SetCfgSecKeyGetter(&cfgSecKeyGetter{})
|
||||
defaultConfig = &ConfigStruct{
|
||||
Picture: &PictureStruct{
|
||||
DisableGravatar: config.ValueJSON[bool]("picture.disable_gravatar").WithFileConfig(config.CfgSecKey{Sec: "picture", Key: "DISABLE_GRAVATAR"}),
|
||||
EnableGravatar: config.ValueJSON[bool]("picture.disable_gravatar").WithFileConfig(config.CfgSecKey{Sec: "picture", Key: "DISABLE_GRAVATAR"}).Invert(),
|
||||
EnableFederatedAvatar: config.ValueJSON[bool]("picture.enable_federated_avatar").WithFileConfig(config.CfgSecKey{Sec: "picture", Key: "ENABLE_FEDERATED_AVATAR"}),
|
||||
},
|
||||
Repository: &RepositoryStruct{
|
||||
|
||||
@ -22,8 +22,9 @@ type Value[T any] struct {
|
||||
cfgSecKey CfgSecKey
|
||||
dynKey string
|
||||
|
||||
def, value T
|
||||
revision int
|
||||
def, value T
|
||||
revision int
|
||||
flipBoolean bool
|
||||
}
|
||||
|
||||
func (value *Value[T]) parse(key, valStr string) (v T) {
|
||||
@ -33,6 +34,17 @@ func (value *Value[T]) parse(key, valStr string) (v T) {
|
||||
log.Error("Unable to unmarshal json config for key %q, err: %v", key, err)
|
||||
}
|
||||
}
|
||||
|
||||
if value.flipBoolean {
|
||||
// if value is of type bool
|
||||
if _, ok := any(v).(bool); ok {
|
||||
// invert the boolean value upon retrieval
|
||||
v = any(!any(v).(bool)).(T)
|
||||
} else {
|
||||
log.Warn("Ignoring attempt to invert key '%q' for non boolean type", key)
|
||||
}
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
@ -93,6 +105,11 @@ func (value *Value[T]) WithFileConfig(cfgSecKey CfgSecKey) *Value[T] {
|
||||
return value
|
||||
}
|
||||
|
||||
func (value *Value[bool]) Invert() *Value[bool] {
|
||||
value.flipBoolean = true
|
||||
return value
|
||||
}
|
||||
|
||||
func ValueJSON[T any](dynKey string) *Value[T] {
|
||||
return &Value[T]{dynKey: dynKey}
|
||||
}
|
||||
|
||||
35
modules/setting/config/value_test.go
Normal file
35
modules/setting/config/value_test.go
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValue_parse(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string // description of this test case
|
||||
// Named input parameters for target function.
|
||||
key string
|
||||
valStr string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "Parse Invert Retrieval",
|
||||
key: "picture.disable_gravatar",
|
||||
valStr: "false",
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
value := ValueJSON[bool]("picture.disable_gravatar").WithFileConfig(CfgSecKey{Sec: "picture", Key: "DISABLE_GRAVATAR"}).Invert()
|
||||
got := value.parse(tt.key, tt.valStr)
|
||||
|
||||
if got != tt.want {
|
||||
t.Errorf("parse() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -23,7 +23,7 @@ var (
|
||||
}
|
||||
|
||||
GravatarSource string
|
||||
DisableGravatar bool // Depreciated: migrated to database
|
||||
EnableGravatar bool // Depreciated: migrated to database
|
||||
EnableFederatedAvatar bool // Depreciated: migrated to database
|
||||
|
||||
RepoAvatar = struct {
|
||||
@ -65,9 +65,9 @@ func loadAvatarsFrom(rootCfg ConfigProvider) error {
|
||||
GravatarSource = source
|
||||
}
|
||||
|
||||
DisableGravatar = sec.Key("DISABLE_GRAVATAR").MustBool(GetDefaultDisableGravatar())
|
||||
EnableGravatar = !sec.Key("DISABLE_GRAVATAR").MustBool(GetDefaultDisableGravatar())
|
||||
deprecatedSettingDB(rootCfg, "", "DISABLE_GRAVATAR")
|
||||
EnableFederatedAvatar = sec.Key("ENABLE_FEDERATED_AVATAR").MustBool(GetDefaultEnableFederatedAvatar(DisableGravatar))
|
||||
EnableFederatedAvatar = sec.Key("ENABLE_FEDERATED_AVATAR").MustBool(GetDefaultEnableFederatedAvatar(EnableGravatar))
|
||||
deprecatedSettingDB(rootCfg, "", "ENABLE_FEDERATED_AVATAR")
|
||||
|
||||
return nil
|
||||
@ -77,14 +77,12 @@ func GetDefaultDisableGravatar() bool {
|
||||
return OfflineMode
|
||||
}
|
||||
|
||||
func GetDefaultEnableFederatedAvatar(disableGravatar bool) bool {
|
||||
func GetDefaultEnableFederatedAvatar(enableGravatar bool) bool {
|
||||
v := !InstallLock
|
||||
if OfflineMode {
|
||||
v = false
|
||||
}
|
||||
if disableGravatar {
|
||||
if OfflineMode || !enableGravatar {
|
||||
v = false
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
|
||||
@ -316,8 +316,8 @@ mail_notify = Enable Email Notifications
|
||||
server_service_title = Server and Third-Party Service Settings
|
||||
offline_mode = Enable Local Mode
|
||||
offline_mode_popup = Disable third-party content delivery networks and serve all resources locally.
|
||||
disable_gravatar = Disable Gravatar
|
||||
disable_gravatar_popup = Disable Gravatar and third-party avatar sources. A default avatar will be used unless a user locally uploads an avatar.
|
||||
enable_gravatar = Enable Gravatar
|
||||
enable_gravatar_popup = Enable Gravatar and third-party avatar sources. A default avatar will be used unless a user locally uploads an avatar.
|
||||
federated_avatar_lookup = Enable Federated Avatars
|
||||
federated_avatar_lookup_popup = Enable federated avatar lookup using Libravatar.
|
||||
disable_registration = Disable Self-Registration
|
||||
@ -3433,7 +3433,7 @@ config.cookie_life_time = Cookie Life Time
|
||||
|
||||
config.picture_config = Picture and Avatar Configuration
|
||||
config.picture_service = Picture Service
|
||||
config.disable_gravatar = Disable Gravatar
|
||||
config.enable_gravatar = Enable Gravatar
|
||||
config.enable_federated_avatar = Enable Federated Avatars
|
||||
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.
|
||||
config.git_guide_remote_name = Repository remote name for git commands in the guide
|
||||
|
||||
@ -136,7 +136,7 @@ func Install(ctx *context.Context) {
|
||||
|
||||
// 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.EnableGravatar = setting.EnableGravatar // 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
|
||||
@ -427,7 +427,7 @@ func SubmitInstall(ctx *context.Context) {
|
||||
|
||||
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.EnableGravatar.DynKey(): strconv.FormatBool(!form.EnableGravatar), // invert value as it is stored as disable_gravatar for backwards compatability
|
||||
setting.Config().Picture.EnableFederatedAvatar.DynKey(): strconv.FormatBool(form.EnableFederatedAvatar),
|
||||
}); err != nil {
|
||||
ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
|
||||
|
||||
@ -203,6 +203,11 @@ func ChangeConfig(ctx *context.Context) {
|
||||
return json.Marshal(b)
|
||||
}
|
||||
|
||||
marshalBoolInvert := func(v string) ([]byte, error) {
|
||||
b, _ := strconv.ParseBool(v)
|
||||
return json.Marshal(!b)
|
||||
}
|
||||
|
||||
marshalString := func(emptyDefault string) func(v string) ([]byte, error) {
|
||||
return func(v string) ([]byte, error) {
|
||||
return json.Marshal(util.IfZero(v, emptyDefault))
|
||||
@ -230,8 +235,9 @@ func ChangeConfig(ctx *context.Context) {
|
||||
}
|
||||
return json.Marshal(openWithEditorApps)
|
||||
}
|
||||
|
||||
marshallers := map[string]func(string) ([]byte, error){
|
||||
cfg.Picture.DisableGravatar.DynKey(): marshalBool,
|
||||
cfg.Picture.EnableGravatar.DynKey(): marshalBoolInvert, // Invert for backwards compatability with old database semantics
|
||||
cfg.Picture.EnableFederatedAvatar.DynKey(): marshalBool,
|
||||
cfg.Repository.OpenWithEditorApps.DynKey(): marshalOpenWithApps,
|
||||
cfg.Repository.GitGuideRemoteName.DynKey(): marshalString(cfg.Repository.GitGuideRemoteName.DefaultValue()),
|
||||
|
||||
@ -316,7 +316,7 @@ func editUserCommon(ctx *context.Context) {
|
||||
ctx.Data["DisableGitHooks"] = setting.DisableGitHooks
|
||||
ctx.Data["DisableImportLocal"] = !setting.ImportLocalPaths
|
||||
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
|
||||
ctx.Data["DisableGravatar"] = setting.Config().Picture.DisableGravatar.Value(ctx)
|
||||
ctx.Data["EnableGravatar"] = setting.Config().Picture.EnableGravatar.Value(ctx)
|
||||
}
|
||||
|
||||
// EditUser show editing user page
|
||||
|
||||
@ -47,7 +47,7 @@ func Profile(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings.profile")
|
||||
ctx.Data["PageIsSettingsProfile"] = true
|
||||
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
|
||||
ctx.Data["DisableGravatar"] = setting.Config().Picture.DisableGravatar.Value(ctx)
|
||||
ctx.Data["EnableGravatar"] = setting.Config().Picture.EnableGravatar.Value(ctx)
|
||||
|
||||
ctx.Data["UserDisabledFeatures"] = user_model.DisabledFeaturesWithLoginType(ctx.Doer)
|
||||
|
||||
@ -59,7 +59,7 @@ func ProfilePost(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsProfile"] = true
|
||||
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
|
||||
ctx.Data["DisableGravatar"] = setting.Config().Picture.DisableGravatar.Value(ctx)
|
||||
ctx.Data["EnableGravatar"] = setting.Config().Picture.EnableGravatar.Value(ctx)
|
||||
ctx.Data["UserDisabledFeatures"] = user_model.DisabledFeaturesWithLoginType(ctx.Doer)
|
||||
|
||||
if ctx.HasError() {
|
||||
|
||||
@ -46,7 +46,7 @@ type InstallForm struct {
|
||||
MailNotify bool
|
||||
|
||||
OfflineMode bool
|
||||
DisableGravatar bool
|
||||
EnableGravatar bool
|
||||
EnableFederatedAvatar bool
|
||||
EnableOpenIDSignIn bool
|
||||
EnableOpenIDSignUp bool
|
||||
|
||||
@ -3,10 +3,10 @@
|
||||
</h4>
|
||||
<div class="ui attached table segment">
|
||||
<dl class="admin-dl-horizontal">
|
||||
<dt>{{ctx.Locale.Tr "admin.config.disable_gravatar"}}</dt>
|
||||
<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="picture.disable_gravatar" {{if .SystemConfig.Picture.EnableGravatar.Value ctx}}checked{{end}}><label></label>
|
||||
</div>
|
||||
</dd>
|
||||
<div class="divider"></div>
|
||||
|
||||
@ -174,7 +174,7 @@
|
||||
<div class="ui attached segment">
|
||||
<form class="ui form" action="./avatar" method="post" enctype="multipart/form-data">
|
||||
{{.CsrfTokenHtml}}
|
||||
{{if not .DisableGravatar}}
|
||||
{{if .EnableGravatar}}
|
||||
<div class="inline field">
|
||||
<div class="ui radio checkbox">
|
||||
<input name="source" value="lookup" type="radio" {{if not .User.UseCustomAvatar}}checked{{end}}>
|
||||
|
||||
@ -210,9 +210,9 @@
|
||||
</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 class="ui checkbox" id="enable-gravatar">
|
||||
<label data-tooltip-content="{{ctx.Locale.Tr "install.enable_gravatar_popup"}}">{{ctx.Locale.Tr "install.enable_gravatar"}}</label>
|
||||
<input name="enable_gravatar" type="checkbox" {{if .enable_gravatar}}checked{{end}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
|
||||
@ -103,7 +103,7 @@
|
||||
<div class="ui attached segment">
|
||||
<form class="ui form" action="{{.Link}}/avatar" method="post" enctype="multipart/form-data">
|
||||
{{.CsrfTokenHtml}}
|
||||
{{if not .DisableGravatar}}
|
||||
{{if .EnableGravatar}}
|
||||
<div class="inline field">
|
||||
<div class="ui radio checkbox">
|
||||
<input name="source" value="lookup" type="radio" {{if not .SignedUser.UseCustomAvatar}}checked{{end}}>
|
||||
|
||||
@ -62,20 +62,20 @@ 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>('#enable-gravatar input').checked = false;
|
||||
document.querySelector<HTMLInputElement>('#federated-avatar-lookup input').checked = false;
|
||||
}
|
||||
});
|
||||
document.querySelector<HTMLInputElement>('#disable-gravatar input').addEventListener('change', function () {
|
||||
document.querySelector<HTMLInputElement>('#enable-gravatar input').addEventListener('change', function () {
|
||||
if (this.checked) {
|
||||
document.querySelector<HTMLInputElement>('#federated-avatar-lookup input').checked = false;
|
||||
document.querySelector<HTMLInputElement>('#federated-avatar-lookup input').checked = true;
|
||||
} else {
|
||||
document.querySelector<HTMLInputElement>('#offline-mode input').checked = false;
|
||||
document.querySelector<HTMLInputElement>('#offline-mode input').checked = true;
|
||||
}
|
||||
});
|
||||
document.querySelector<HTMLInputElement>('#federated-avatar-lookup input').addEventListener('change', function () {
|
||||
if (this.checked) {
|
||||
document.querySelector<HTMLInputElement>('#disable-gravatar input').checked = false;
|
||||
document.querySelector<HTMLInputElement>('#enable-gravatar input').checked = false;
|
||||
document.querySelector<HTMLInputElement>('#offline-mode input').checked = false;
|
||||
}
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user