From 5f8cb5d6af41a8d0e9129bec82eead0d2b556139 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 22 Dec 2021 00:25:38 +0800 Subject: [PATCH 01/25] Add system setting table with cache and also add cache supports for user setting --- models/consistency.go | 4 +- models/migrations/migrations.go | 2 + models/migrations/v216.go | 23 +++ models/repo.go | 19 ++- models/{appstate => system}/appstate.go | 2 +- models/{admin => system}/main_test.go | 2 +- models/{admin => system}/notice.go | 2 +- models/{admin => system}/notice_test.go | 2 +- models/system/setting.go | 141 ++++++++++++++++++ models/system/setting_test.go | 51 +++++++ models/user/setting.go | 28 ++++ modules/{appstate => system}/appstate.go | 2 +- modules/{appstate => system}/appstate_test.go | 2 +- modules/{appstate => system}/db.go | 8 +- modules/{appstate => system}/item_runtime.go | 2 +- modules/system/setting.go | 35 +++++ modules/system/user_setting.go | 38 +++++ modules/updatechecker/update_checker.go | 6 +- routers/init.go | 10 +- routers/web/admin/notice.go | 10 +- routers/web/repo/middlewares.go | 4 +- services/cron/tasks.go | 6 +- services/migrations/gitea_downloader.go | 8 +- services/migrations/migrate.go | 4 +- services/mirror/mirror_pull.go | 12 +- services/repository/check.go | 14 +- services/user/user.go | 6 +- services/wiki/wiki.go | 5 +- 28 files changed, 385 insertions(+), 63 deletions(-) create mode 100644 models/migrations/v216.go rename models/{appstate => system}/appstate.go (98%) rename models/{admin => system}/main_test.go (96%) rename models/{admin => system}/notice.go (99%) rename models/{admin => system}/notice_test.go (99%) create mode 100644 models/system/setting.go create mode 100644 models/system/setting_test.go rename modules/{appstate => system}/appstate.go (97%) rename modules/{appstate => system}/appstate_test.go (98%) rename modules/{appstate => system}/db.go (77%) rename modules/{appstate => system}/item_runtime.go (96%) create mode 100644 modules/system/setting.go create mode 100644 modules/system/user_setting.go diff --git a/models/consistency.go b/models/consistency.go index abef7243f17e6..49a11de6cccfc 100644 --- a/models/consistency.go +++ b/models/consistency.go @@ -5,9 +5,9 @@ package models import ( - admin_model "code.gitea.io/gitea/models/admin" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" + system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" @@ -131,7 +131,7 @@ func DeleteOrphanedIssues() error { // Remove issue attachment files. for i := range attachmentPaths { - admin_model.RemoveAllWithNotice(db.DefaultContext, "Delete issue attachment", attachmentPaths[i]) + system_model.RemoveAllWithNotice(db.DefaultContext, "Delete issue attachment", attachmentPaths[i]) } return nil } diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 5a2297ac0d3c2..f8ef4844a809c 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -387,6 +387,8 @@ var migrations = []Migration{ NewMigration("Add auto merge table", addAutoMergeTable), // v215 -> v216 NewMigration("allow to view files in PRs", addReviewViewedFiles), + // v216 -> v217 + NewMigration("Create key/value table for system settings", createSystemSettingsTable), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v216.go b/models/migrations/v216.go new file mode 100644 index 0000000000000..a30fed9e32292 --- /dev/null +++ b/models/migrations/v216.go @@ -0,0 +1,23 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package migrations + +import ( + "fmt" + + "xorm.io/xorm" +) + +func createSystemSettingsTable(x *xorm.Engine) error { + type SystemSetting struct { + ID int64 `xorm:"pk autoincr"` + SettingKey string `xorm:"varchar(255) unique"` // ensure key is always lowercase + SettingValue string `xorm:"text"` + } + if err := x.Sync2(new(SystemSetting)); err != nil { + return fmt.Errorf("sync2: %v", err) + } + return nil +} diff --git a/models/repo.go b/models/repo.go index d2ad560948b0c..fb33f02151d90 100644 --- a/models/repo.go +++ b/models/repo.go @@ -16,7 +16,6 @@ import ( _ "image/jpeg" // Needed for jpeg support - admin_model "code.gitea.io/gitea/models/admin" asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" @@ -25,6 +24,7 @@ import ( access_model "code.gitea.io/gitea/models/perm/access" project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" + system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/models/webhook" @@ -44,6 +44,9 @@ var ItemsPerPage = 40 // NewRepoContext creates a new repository context func NewRepoContext() { unit.LoadUnitConfig() + + system_model.RemoveAllWithNotice(db.DefaultContext, "Clean up temporary repository uploads", setting.Repository.Upload.TempPath) + system_model.RemoveAllWithNotice(db.DefaultContext, "Clean up temporary repositories", LocalCopyPath()) } // CheckRepoUnitUser check whether user could visit the unit of this repository @@ -800,36 +803,36 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error { // Remove repository files. repoPath := repo.RepoPath() - admin_model.RemoveAllWithNotice(db.DefaultContext, "Delete repository files", repoPath) + system_model.RemoveAllWithNotice(db.DefaultContext, "Delete repository files", repoPath) // Remove wiki files if repo.HasWiki() { - admin_model.RemoveAllWithNotice(db.DefaultContext, "Delete repository wiki", repo.WikiPath()) + system_model.RemoveAllWithNotice(db.DefaultContext, "Delete repository wiki", repo.WikiPath()) } // Remove archives for _, archive := range archivePaths { - admin_model.RemoveStorageWithNotice(db.DefaultContext, storage.RepoArchives, "Delete repo archive file", archive) + system_model.RemoveStorageWithNotice(db.DefaultContext, storage.RepoArchives, "Delete repo archive file", archive) } // Remove lfs objects for _, lfsObj := range lfsPaths { - admin_model.RemoveStorageWithNotice(db.DefaultContext, storage.LFS, "Delete orphaned LFS file", lfsObj) + system_model.RemoveStorageWithNotice(db.DefaultContext, storage.LFS, "Delete orphaned LFS file", lfsObj) } // Remove issue attachment files. for _, attachment := range attachmentPaths { - admin_model.RemoveStorageWithNotice(db.DefaultContext, storage.Attachments, "Delete issue attachment", attachment) + system_model.RemoveStorageWithNotice(db.DefaultContext, storage.Attachments, "Delete issue attachment", attachment) } // Remove release attachment files. for _, releaseAttachment := range releaseAttachments { - admin_model.RemoveStorageWithNotice(db.DefaultContext, storage.Attachments, "Delete release attachment", releaseAttachment) + system_model.RemoveStorageWithNotice(db.DefaultContext, storage.Attachments, "Delete release attachment", releaseAttachment) } // Remove attachment with no issue_id and release_id. for _, newAttachment := range newAttachmentPaths { - admin_model.RemoveStorageWithNotice(db.DefaultContext, storage.Attachments, "Delete issue attachment", newAttachment) + system_model.RemoveStorageWithNotice(db.DefaultContext, storage.Attachments, "Delete issue attachment", newAttachment) } if len(repo.Avatar) > 0 { diff --git a/models/appstate/appstate.go b/models/system/appstate.go similarity index 98% rename from models/appstate/appstate.go rename to models/system/appstate.go index aa5a59e1a3aed..c11a2512aba92 100644 --- a/models/appstate/appstate.go +++ b/models/system/appstate.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package appstate +package system import ( "context" diff --git a/models/admin/main_test.go b/models/system/main_test.go similarity index 96% rename from models/admin/main_test.go rename to models/system/main_test.go index 693b70fbf7581..031753b7c079d 100644 --- a/models/admin/main_test.go +++ b/models/system/main_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package admin +package system import ( "path/filepath" diff --git a/models/admin/notice.go b/models/system/notice.go similarity index 99% rename from models/admin/notice.go rename to models/system/notice.go index 77277e4b2d873..d514cee99db11 100644 --- a/models/admin/notice.go +++ b/models/system/notice.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package admin +package system import ( "context" diff --git a/models/admin/notice_test.go b/models/system/notice_test.go similarity index 99% rename from models/admin/notice_test.go rename to models/system/notice_test.go index b4613db8e7477..0564fdc0dcbdb 100644 --- a/models/admin/notice_test.go +++ b/models/system/notice_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package admin +package system import ( "testing" diff --git a/models/system/setting.go b/models/system/setting.go new file mode 100644 index 0000000000000..aa35fe2695a7a --- /dev/null +++ b/models/system/setting.go @@ -0,0 +1,141 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package system + +import ( + "context" + "fmt" + "strings" + + "code.gitea.io/gitea/models/db" + + "xorm.io/builder" +) + +// Setting is a key value store of user settings +type Setting struct { + ID int64 `xorm:"pk autoincr"` + SettingKey string `xorm:"varchar(255) unique"` // ensure key is always lowercase + SettingValue string `xorm:"text"` +} + +// TableName sets the table name for the settings struct +func (s *Setting) TableName() string { + return "system_setting" +} + +func init() { + db.RegisterModel(new(Setting)) +} + +// ErrSettingIsNotExist represents an error that a setting is not exist with special key +type ErrSettingIsNotExist struct { + Key string +} + +// Error implements error +func (err ErrSettingIsNotExist) Error() string { + return fmt.Sprintf("System setting[%s] is not exist", err.Key) +} + +// IsErrSettingIsNotExist return true if err is ErrSettingIsNotExist +func IsErrSettingIsNotExist(err error) bool { + _, ok := err.(ErrSettingIsNotExist) + return ok +} + +// GetSetting returns specific setting +func GetSetting(key string) (*Setting, error) { + v, err := GetSettings([]string{key}) + if err != nil { + return nil, err + } + if len(v) == 0 { + return nil, ErrSettingIsNotExist{key} + } + return v[key], nil +} + +// GetSettings returns specific settings +func GetSettings(keys []string) (map[string]*Setting, error) { + settings := make([]*Setting, 0, len(keys)) + if err := db.GetEngine(db.DefaultContext). + Where(builder.In("setting_key", keys)). + Find(&settings); err != nil { + return nil, err + } + settingsMap := make(map[string]*Setting) + for _, s := range settings { + settingsMap[s.SettingKey] = s + } + return settingsMap, nil +} + +// GetAllSettings returns all settings from user +func GetAllSettings() (map[string]*Setting, error) { + settings := make([]*Setting, 0, 5) + if err := db.GetEngine(db.DefaultContext). + Find(&settings); err != nil { + return nil, err + } + settingsMap := make(map[string]*Setting) + for _, s := range settings { + settingsMap[s.SettingKey] = s + } + return settingsMap, nil +} + +// DeleteSetting deletes a specific setting for a user +func DeleteSetting(setting *Setting) error { + _, err := db.GetEngine(db.DefaultContext).Delete(setting) + return err +} + +// SetSetting updates a users' setting for a specific key +func SetSetting(setting *Setting) error { + if strings.ToLower(setting.SettingKey) != setting.SettingKey { + return fmt.Errorf("setting key should be lowercase") + } + return upsertSettingValue(setting.SettingKey, setting.SettingValue) +} + +func upsertSettingValue(key, value string) error { + return db.WithTx(func(ctx context.Context) error { + e := db.GetEngine(ctx) + + // here we use a general method to do a safe upsert for different databases (and most transaction levels) + // 1. try to UPDATE the record and acquire the transaction write lock + // if UPDATE returns non-zero rows are changed, OK, the setting is saved correctly + // if UPDATE returns "0 rows changed", two possibilities: (a) record doesn't exist (b) value is not changed + // 2. do a SELECT to check if the row exists or not (we already have the transaction lock) + // 3. if the row doesn't exist, do an INSERT (we are still protected by the transaction lock, so it's safe) + // + // to optimize the SELECT in step 2, we can use an extra column like `revision=revision+1` + // to make sure the UPDATE always returns a non-zero value for existing (unchanged) records. + + res, err := e.Exec("UPDATE system_setting SET setting_value=? WHERE setting_key=?", value, key) + if err != nil { + return err + } + rows, _ := res.RowsAffected() + if rows > 0 { + // the existing row is updated, so we can return + return nil + } + + // in case the value isn't changed, update would return 0 rows changed, so we need this check + has, err := e.Exist(&Setting{SettingKey: key}) + if err != nil { + return err + } + if has { + return nil + } + + // if no existing row, insert a new row + _, err = e.Insert(&Setting{SettingKey: key, SettingValue: value}) + return err + }) +} diff --git a/models/system/setting_test.go b/models/system/setting_test.go new file mode 100644 index 0000000000000..ba7bb31e4aae2 --- /dev/null +++ b/models/system/setting_test.go @@ -0,0 +1,51 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package system + +import ( + "testing" + + "code.gitea.io/gitea/models/unittest" + + "github.com/stretchr/testify/assert" +) + +func TestSettings(t *testing.T) { + keyName := "server.LFS_LOCKS_PAGING_NUM" + assert.NoError(t, unittest.PrepareTestDatabase()) + + newSetting := &Setting{SettingKey: keyName, SettingValue: "50"} + + // create setting + err := SetSetting(newSetting) + assert.NoError(t, err) + // test about saving unchanged values + err = SetSetting(newSetting) + assert.NoError(t, err) + + // get specific setting + settings, err := GetSettings([]string{keyName}) + assert.NoError(t, err) + assert.Len(t, settings, 1) + assert.EqualValues(t, newSetting.SettingValue, settings[keyName].SettingValue) + + // updated setting + updatedSetting := &Setting{SettingKey: keyName, SettingValue: "100"} + err = SetSetting(updatedSetting) + assert.NoError(t, err) + + // get all settings + settings, err = GetAllSettings() + assert.NoError(t, err) + assert.Len(t, settings, 1) + assert.EqualValues(t, updatedSetting.SettingValue, settings[updatedSetting.SettingKey].SettingValue) + + // delete setting + err = DeleteSetting(&Setting{SettingKey: keyName}) + assert.NoError(t, err) + settings, err = GetAllSettings() + assert.NoError(t, err) + assert.Len(t, settings, 0) +} diff --git a/models/user/setting.go b/models/user/setting.go index fbb6fbab30337..5fe7c2ec23249 100644 --- a/models/user/setting.go +++ b/models/user/setting.go @@ -31,6 +31,34 @@ func init() { db.RegisterModel(new(Setting)) } +// ErrUserSettingIsNotExist represents an error that a setting is not exist with special key +type ErrUserSettingIsNotExist struct { + Key string +} + +// Error implements error +func (err ErrUserSettingIsNotExist) Error() string { + return fmt.Sprintf("Setting[%s] is not exist", err.Key) +} + +// IsErrUserSettingIsNotExist return true if err is ErrSettingIsNotExist +func IsErrUserSettingIsNotExist(err error) bool { + _, ok := err.(ErrUserSettingIsNotExist) + return ok +} + +// GetSetting returns specific setting +func GetSetting(uid int64, key string) (*Setting, error) { + v, err := GetUserSettings(uid, []string{key}) + if err != nil { + return nil, err + } + if len(v) == 0 { + return nil, ErrUserSettingIsNotExist{key} + } + return v[key], nil +} + // GetUserSettings returns specific settings from user func GetUserSettings(uid int64, keys []string) (map[string]*Setting, error) { settings := make([]*Setting, 0, len(keys)) diff --git a/modules/appstate/appstate.go b/modules/system/appstate.go similarity index 97% rename from modules/appstate/appstate.go rename to modules/system/appstate.go index f65f5367e235d..deee8cd0296d5 100644 --- a/modules/appstate/appstate.go +++ b/modules/system/appstate.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package appstate +package system // StateStore is the interface to get/set app state items type StateStore interface { diff --git a/modules/appstate/appstate_test.go b/modules/system/appstate_test.go similarity index 98% rename from modules/appstate/appstate_test.go rename to modules/system/appstate_test.go index e4a0d72850e70..fb0c2aaf9f45f 100644 --- a/modules/appstate/appstate_test.go +++ b/modules/system/appstate_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package appstate +package system import ( "path/filepath" diff --git a/modules/appstate/db.go b/modules/system/db.go similarity index 77% rename from modules/appstate/db.go rename to modules/system/db.go index 2538d1b5c8e1a..b1c283c488d59 100644 --- a/modules/appstate/db.go +++ b/modules/system/db.go @@ -2,10 +2,10 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package appstate +package system import ( - "code.gitea.io/gitea/models/appstate" + "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/json" "github.com/yuin/goldmark/util" @@ -16,7 +16,7 @@ type DBStore struct{} // Get reads the state item func (f *DBStore) Get(item StateItem) error { - content, err := appstate.GetAppStateContent(item.Name()) + content, err := system.GetAppStateContent(item.Name()) if err != nil { return err } @@ -32,5 +32,5 @@ func (f *DBStore) Set(item StateItem) error { if err != nil { return err } - return appstate.SaveAppStateContent(item.Name(), util.BytesToReadOnlyString(b)) + return system.SaveAppStateContent(item.Name(), util.BytesToReadOnlyString(b)) } diff --git a/modules/appstate/item_runtime.go b/modules/system/item_runtime.go similarity index 96% rename from modules/appstate/item_runtime.go rename to modules/system/item_runtime.go index 7fdc53f64247a..ef758a5675e10 100644 --- a/modules/appstate/item_runtime.go +++ b/modules/system/item_runtime.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package appstate +package system // RuntimeState contains app state for runtime, and we can save remote version for update checker here in future type RuntimeState struct { diff --git a/modules/system/setting.go b/modules/system/setting.go new file mode 100644 index 0000000000000..81b20347453c4 --- /dev/null +++ b/modules/system/setting.go @@ -0,0 +1,35 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package system + +import ( + "code.gitea.io/gitea/models/system" + "code.gitea.io/gitea/modules/cache" +) + +func genKey(key string) string { + return "system.setting." + key +} + +// GetSetting returns the setting value via the key +func GetSetting(key string) (string, error) { + return cache.GetString(genKey(key), func() (string, error) { + res, err := system.GetSetting(key) + if err != nil { + return "", err + } + return res.SettingValue, nil + }) +} + +// SetSetting sets the setting value +func SetSetting(key, value string) error { + cache.Remove(genKey(key)) + + return system.SetSetting(&system.Setting{ + SettingKey: key, + SettingValue: value, + }) +} diff --git a/modules/system/user_setting.go b/modules/system/user_setting.go new file mode 100644 index 0000000000000..02f76c0ac5fe0 --- /dev/null +++ b/modules/system/user_setting.go @@ -0,0 +1,38 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package system + +import ( + "fmt" + + "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/cache" +) + +func genUserKey(userID int64, key string) string { + return fmt.Sprintf("user_%d.setting.%s", userID, key) +} + +// GetUserSetting returns the user setting value via the key +func GetUserSetting(userID int64, key string) (string, error) { + return cache.GetString(genUserKey(userID, key), func() (string, error) { + res, err := user.GetSetting(userID, key) + if err != nil { + return "", err + } + return res.SettingValue, nil + }) +} + +// SetUserSetting sets the user setting value +func SetUserSetting(userID int64, key, value string) error { + cache.Remove(genUserKey(userID, key)) + + return user.SetSetting(&user.Setting{ + UserID: userID, + SettingKey: key, + SettingValue: value, + }) +} diff --git a/modules/updatechecker/update_checker.go b/modules/updatechecker/update_checker.go index 9c1569b15e75a..816fb3764c5e2 100644 --- a/modules/updatechecker/update_checker.go +++ b/modules/updatechecker/update_checker.go @@ -8,10 +8,10 @@ import ( "io" "net/http" - "code.gitea.io/gitea/modules/appstate" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/proxy" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/system" "github.com/hashicorp/go-version" ) @@ -64,13 +64,13 @@ func GiteaUpdateChecker(httpEndpoint string) error { // UpdateRemoteVersion updates the latest available version of Gitea func UpdateRemoteVersion(version string) (err error) { - return appstate.AppState.Set(&CheckerState{LatestVersion: version}) + return system.AppState.Set(&CheckerState{LatestVersion: version}) } // GetRemoteVersion returns the current remote version (or currently installed version if fail to fetch from DB) func GetRemoteVersion() string { item := new(CheckerState) - if err := appstate.AppState.Get(item); err != nil { + if err := system.AppState.Get(item); err != nil { return "" } return item.LatestVersion diff --git a/routers/init.go b/routers/init.go index 6036499362944..6c59af1061e63 100644 --- a/routers/init.go +++ b/routers/init.go @@ -13,7 +13,6 @@ import ( "code.gitea.io/gitea/models" asymkey_model "code.gitea.io/gitea/models/asymkey" - "code.gitea.io/gitea/modules/appstate" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/eventsource" "code.gitea.io/gitea/modules/git" @@ -29,6 +28,7 @@ import ( "code.gitea.io/gitea/modules/ssh" "code.gitea.io/gitea/modules/storage" "code.gitea.io/gitea/modules/svg" + "code.gitea.io/gitea/modules/system" "code.gitea.io/gitea/modules/translation" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" @@ -77,8 +77,8 @@ func InitGitServices() { } func syncAppPathForGit(ctx context.Context) error { - runtimeState := new(appstate.RuntimeState) - if err := appstate.AppState.Get(runtimeState); err != nil { + runtimeState := new(system.RuntimeState) + if err := system.AppState.Get(runtimeState); err != nil { return err } if runtimeState.LastAppPath != setting.AppPath { @@ -91,7 +91,7 @@ func syncAppPathForGit(ctx context.Context) error { mustInit(asymkey_model.RewriteAllPublicKeys) runtimeState.LastAppPath = setting.AppPath - return appstate.AppState.Set(runtimeState) + return system.AppState.Set(runtimeState) } return nil } @@ -136,7 +136,7 @@ func GlobalInitInstalled(ctx context.Context) { mustInitCtx(ctx, common.InitDBEngine) log.Info("ORM engine initialization successful!") - mustInit(appstate.Init) + mustInit(system.Init) mustInit(oauth2.Init) models.NewRepoContext() diff --git a/routers/web/admin/notice.go b/routers/web/admin/notice.go index b50549b80454f..f5ec294cc361e 100644 --- a/routers/web/admin/notice.go +++ b/routers/web/admin/notice.go @@ -9,7 +9,7 @@ import ( "net/http" "strconv" - admin_model "code.gitea.io/gitea/models/admin" + system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" @@ -26,13 +26,13 @@ func Notices(ctx *context.Context) { ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminNotices"] = true - total := admin_model.CountNotices() + total := system_model.CountNotices() page := ctx.FormInt("page") if page <= 1 { page = 1 } - notices, err := admin_model.Notices(page, setting.UI.Admin.NoticePagingNum) + notices, err := system_model.Notices(page, setting.UI.Admin.NoticePagingNum) if err != nil { ctx.ServerError("Notices", err) return @@ -57,7 +57,7 @@ func DeleteNotices(ctx *context.Context) { } } - if err := admin_model.DeleteNoticesByIDs(ids); err != nil { + if err := system_model.DeleteNoticesByIDs(ids); err != nil { ctx.Flash.Error("DeleteNoticesByIDs: " + err.Error()) ctx.Status(http.StatusInternalServerError) } else { @@ -68,7 +68,7 @@ func DeleteNotices(ctx *context.Context) { // EmptyNotices delete all the notices func EmptyNotices(ctx *context.Context) { - if err := admin_model.DeleteNotices(0, 0); err != nil { + if err := system_model.DeleteNotices(0, 0); err != nil { ctx.ServerError("DeleteNotices", err) return } diff --git a/routers/web/repo/middlewares.go b/routers/web/repo/middlewares.go index ae4177cf1e639..c9e8eb4a89e3f 100644 --- a/routers/web/repo/middlewares.go +++ b/routers/web/repo/middlewares.go @@ -7,7 +7,7 @@ package repo import ( "fmt" - admin_model "code.gitea.io/gitea/models/admin" + system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" @@ -24,7 +24,7 @@ func SetEditorconfigIfExists(ctx *context.Context) { if err != nil && !git.IsErrNotExist(err) { description := fmt.Sprintf("Error while getting .editorconfig file: %v", err) - if err := admin_model.CreateRepositoryNotice(description); err != nil { + if err := system_model.CreateRepositoryNotice(description); err != nil { ctx.ServerError("ErrCreatingReporitoryNotice", err) } return diff --git a/services/cron/tasks.go b/services/cron/tasks.go index 2252ad21e2549..0ff857b278394 100644 --- a/services/cron/tasks.go +++ b/services/cron/tasks.go @@ -10,8 +10,8 @@ import ( "reflect" "sync" - admin_model "code.gitea.io/gitea/models/admin" "code.gitea.io/gitea/models/db" + system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" @@ -114,7 +114,7 @@ func (t *Task) RunWithUser(doer *user_model.User, config Config) { t.LastDoer = doerName t.lock.Unlock() - if err := admin_model.CreateNotice(ctx, admin_model.NoticeTask, config.FormatMessage("en-US", t.Name, "cancelled", doerName, message)); err != nil { + if err := system_model.CreateNotice(ctx, system_model.NoticeTask, config.FormatMessage("en-US", t.Name, "cancelled", doerName, message)); err != nil { log.Error("CreateNotice: %v", err) } return @@ -127,7 +127,7 @@ func (t *Task) RunWithUser(doer *user_model.User, config Config) { t.lock.Unlock() if config.DoNoticeOnSuccess() { - if err := admin_model.CreateNotice(ctx, admin_model.NoticeTask, config.FormatMessage("en-US", t.Name, "finished", doerName)); err != nil { + if err := system_model.CreateNotice(ctx, system_model.NoticeTask, config.FormatMessage("en-US", t.Name, "finished", doerName)); err != nil { log.Error("CreateNotice: %v", err) } } diff --git a/services/migrations/gitea_downloader.go b/services/migrations/gitea_downloader.go index 3c02e112ca73e..d2c75810f62aa 100644 --- a/services/migrations/gitea_downloader.go +++ b/services/migrations/gitea_downloader.go @@ -14,7 +14,7 @@ import ( "strings" "time" - admin_model "code.gitea.io/gitea/models/admin" + system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/log" base "code.gitea.io/gitea/modules/migration" "code.gitea.io/gitea/modules/structs" @@ -403,7 +403,7 @@ func (g *GiteaDownloader) GetIssues(page, perPage int) ([]*base.Issue, bool, err reactions, err := g.getIssueReactions(issue.Index) if err != nil { log.Warn("Unable to load reactions during migrating issue #%d to %s/%s. Error: %v", issue.Index, g.repoOwner, g.repoName, err) - if err2 := admin_model.CreateRepositoryNotice( + if err2 := system_model.CreateRepositoryNotice( fmt.Sprintf("Unable to load reactions during migrating issue #%d to %s/%s. Error: %v", issue.Index, g.repoOwner, g.repoName, err)); err2 != nil { log.Error("create repository notice failed: ", err2) } @@ -465,7 +465,7 @@ func (g *GiteaDownloader) GetComments(commentable base.Commentable) ([]*base.Com reactions, err := g.getCommentReactions(comment.ID) if err != nil { log.Warn("Unable to load comment reactions during migrating issue #%d for comment %d to %s/%s. Error: %v", commentable.GetForeignIndex(), comment.ID, g.repoOwner, g.repoName, err) - if err2 := admin_model.CreateRepositoryNotice( + if err2 := system_model.CreateRepositoryNotice( fmt.Sprintf("Unable to load reactions during migrating issue #%d for comment %d to %s/%s. Error: %v", commentable.GetForeignIndex(), comment.ID, g.repoOwner, g.repoName, err)); err2 != nil { log.Error("create repository notice failed: ", err2) } @@ -544,7 +544,7 @@ func (g *GiteaDownloader) GetPullRequests(page, perPage int) ([]*base.PullReques reactions, err := g.getIssueReactions(pr.Index) if err != nil { log.Warn("Unable to load reactions during migrating pull #%d to %s/%s. Error: %v", pr.Index, g.repoOwner, g.repoName, err) - if err2 := admin_model.CreateRepositoryNotice( + if err2 := system_model.CreateRepositoryNotice( fmt.Sprintf("Unable to load reactions during migrating pull #%d to %s/%s. Error: %v", pr.Index, g.repoOwner, g.repoName, err)); err2 != nil { log.Error("create repository notice failed: ", err2) } diff --git a/services/migrations/migrate.go b/services/migrations/migrate.go index 700f06af35dc0..3a445b2939569 100644 --- a/services/migrations/migrate.go +++ b/services/migrations/migrate.go @@ -14,8 +14,8 @@ import ( "strings" "code.gitea.io/gitea/models" - admin_model "code.gitea.io/gitea/models/admin" repo_model "code.gitea.io/gitea/models/repo" + system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/hostmatcher" "code.gitea.io/gitea/modules/log" @@ -129,7 +129,7 @@ func MigrateRepository(ctx context.Context, doer *user_model.User, ownerName str if err1 := uploader.Rollback(); err1 != nil { log.Error("rollback failed: %v", err1) } - if err2 := admin_model.CreateRepositoryNotice(fmt.Sprintf("Migrate repository from %s failed: %v", opts.OriginalURL, err)); err2 != nil { + if err2 := system_model.CreateRepositoryNotice(fmt.Sprintf("Migrate repository from %s failed: %v", opts.OriginalURL, err)); err2 != nil { log.Error("create respotiry notice failed: ", err2) } return nil, err diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go index c51483821bd65..22a8b950847ec 100644 --- a/services/mirror/mirror_pull.go +++ b/services/mirror/mirror_pull.go @@ -11,9 +11,9 @@ import ( "time" "code.gitea.io/gitea/models" - admin_model "code.gitea.io/gitea/models/admin" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" + system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/lfs" @@ -189,7 +189,7 @@ func pruneBrokenReferences(ctx context.Context, log.Error("Failed to prune mirror repository %s%-v references:\nStdout: %s\nStderr: %s\nErr: %v", wiki, m.Repo, stdoutMessage, stderrMessage, pruneErr) desc := fmt.Sprintf("Failed to prune mirror repository %s'%s' references: %s", wiki, repoPath, stderrMessage) - if err := admin_model.CreateRepositoryNotice(desc); err != nil { + if err := system_model.CreateRepositoryNotice(desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } // this if will only be reached on a successful prune so try to get the mirror again @@ -267,7 +267,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo if err != nil { log.Error("SyncMirrors [repo: %-v]: failed to update mirror repository:\nStdout: %s\nStderr: %s\nErr: %v", m.Repo, stdoutMessage, stderrMessage, err) desc := fmt.Sprintf("Failed to update mirror repository '%s': %s", repoPath, stderrMessage) - if err = admin_model.CreateRepositoryNotice(desc); err != nil { + if err = system_model.CreateRepositoryNotice(desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } return nil, false @@ -356,7 +356,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo if err != nil { log.Error("SyncMirrors [repo: %-v Wiki]: failed to update mirror repository wiki:\nStdout: %s\nStderr: %s\nErr: %v", m.Repo, stdoutMessage, stderrMessage, err) desc := fmt.Sprintf("Failed to update mirror repository wiki '%s': %s", wikiPath, stderrMessage) - if err = admin_model.CreateRepositoryNotice(desc); err != nil { + if err = system_model.CreateRepositoryNotice(desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } return nil, false @@ -568,7 +568,7 @@ func checkAndUpdateEmptyRepository(m *repo_model.Mirror, gitRepo *git.Repository if !git.IsErrUnsupportedVersion(err) { log.Error("Failed to update default branch of underlying git repository %-v. Error: %v", m.Repo, err) desc := fmt.Sprintf("Failed to uupdate default branch of underlying git repository '%s': %v", m.Repo.RepoPath(), err) - if err = admin_model.CreateRepositoryNotice(desc); err != nil { + if err = system_model.CreateRepositoryNotice(desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } return false @@ -579,7 +579,7 @@ func checkAndUpdateEmptyRepository(m *repo_model.Mirror, gitRepo *git.Repository if err := repo_model.UpdateRepositoryCols(db.DefaultContext, m.Repo, "default_branch", "is_empty"); err != nil { log.Error("Failed to update default branch of repository %-v. Error: %v", m.Repo, err) desc := fmt.Sprintf("Failed to uupdate default branch of repository '%s': %v", m.Repo.RepoPath(), err) - if err = admin_model.CreateRepositoryNotice(desc); err != nil { + if err = system_model.CreateRepositoryNotice(desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } return false diff --git a/services/repository/check.go b/services/repository/check.go index 6fb86d0dc3c25..38aaae42c016b 100644 --- a/services/repository/check.go +++ b/services/repository/check.go @@ -11,9 +11,9 @@ import ( "time" "code.gitea.io/gitea/models" - admin_model "code.gitea.io/gitea/models/admin" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" + system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" @@ -41,7 +41,7 @@ func GitFsck(ctx context.Context, timeout time.Duration, args []string) error { repoPath := repo.RepoPath() if err := git.Fsck(ctx, repoPath, timeout, args...); err != nil { log.Warn("Failed to health check repository (%v): %v", repo, err) - if err = admin_model.CreateRepositoryNotice("Failed to health check repository (%s): %v", repo.FullName(), err); err != nil { + if err = system_model.CreateRepositoryNotice("Failed to health check repository (%s): %v", repo.FullName(), err); err != nil { log.Error("CreateRepositoryNotice: %v", err) } } @@ -82,7 +82,7 @@ func GitGcRepos(ctx context.Context, timeout time.Duration, args ...string) erro if err != nil { log.Error("Repository garbage collection failed for %v. Stdout: %s\nError: %v", repo, stdout, err) desc := fmt.Sprintf("Repository garbage collection failed for %s. Stdout: %s\nError: %v", repo.RepoPath(), stdout, err) - if err = admin_model.CreateRepositoryNotice(desc); err != nil { + if err = system_model.CreateRepositoryNotice(desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } return fmt.Errorf("Repository garbage collection failed in repo: %s: Error: %v", repo.FullName(), err) @@ -92,7 +92,7 @@ func GitGcRepos(ctx context.Context, timeout time.Duration, args ...string) erro if err := models.UpdateRepoSize(ctx, repo); err != nil { log.Error("Updating size as part of garbage collection failed for %v. Stdout: %s\nError: %v", repo, stdout, err) desc := fmt.Sprintf("Updating size as part of garbage collection failed for %s. Stdout: %s\nError: %v", repo.RepoPath(), stdout, err) - if err = admin_model.CreateRepositoryNotice(desc); err != nil { + if err = system_model.CreateRepositoryNotice(desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } return fmt.Errorf("Updating size as part of garbage collection failed in repo: %s: Error: %v", repo.FullName(), err) @@ -134,7 +134,7 @@ func gatherMissingRepoRecords(ctx context.Context) ([]*repo_model.Repository, er if strings.HasPrefix(err.Error(), "Aborted gathering missing repo") { return nil, err } - if err2 := admin_model.CreateRepositoryNotice("gatherMissingRepoRecords: %v", err); err2 != nil { + if err2 := system_model.CreateRepositoryNotice("gatherMissingRepoRecords: %v", err); err2 != nil { log.Error("CreateRepositoryNotice: %v", err2) } return nil, err @@ -162,7 +162,7 @@ func DeleteMissingRepositories(ctx context.Context, doer *user_model.User) error log.Trace("Deleting %d/%d...", repo.OwnerID, repo.ID) if err := models.DeleteRepository(doer, repo.OwnerID, repo.ID); err != nil { log.Error("Failed to DeleteRepository %s [%d]: Error: %v", repo.FullName(), repo.ID, err) - if err2 := admin_model.CreateRepositoryNotice("Failed to DeleteRepository %s [%d]: Error: %v", repo.FullName(), repo.ID, err); err2 != nil { + if err2 := system_model.CreateRepositoryNotice("Failed to DeleteRepository %s [%d]: Error: %v", repo.FullName(), repo.ID, err); err2 != nil { log.Error("CreateRepositoryNotice: %v", err) } } @@ -190,7 +190,7 @@ func ReinitMissingRepositories(ctx context.Context) error { log.Trace("Initializing %d/%d...", repo.OwnerID, repo.ID) if err := git.InitRepository(ctx, repo.RepoPath(), true); err != nil { log.Error("Unable (re)initialize repository %d at %s. Error: %v", repo.ID, repo.RepoPath(), err) - if err2 := admin_model.CreateRepositoryNotice("InitRepository [%d]: %v", repo.ID, err); err2 != nil { + if err2 := system_model.CreateRepositoryNotice("InitRepository [%d]: %v", repo.ID, err); err2 != nil { log.Error("CreateRepositoryNotice: %v", err2) } } diff --git a/services/user/user.go b/services/user/user.go index 4db4d7ca17f12..148c3a57f071a 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -13,12 +13,12 @@ import ( "time" "code.gitea.io/gitea/models" - admin_model "code.gitea.io/gitea/models/admin" asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" packages_model "code.gitea.io/gitea/models/packages" repo_model "code.gitea.io/gitea/models/repo" + system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/avatar" "code.gitea.io/gitea/modules/log" @@ -87,7 +87,7 @@ func DeleteUser(u *user_model.User) error { path := user_model.UserPath(u.Name) if err := util.RemoveAll(path); err != nil { err = fmt.Errorf("Failed to RemoveAll %s: %v", path, err) - _ = admin_model.CreateNotice(ctx, admin_model.NoticeTask, fmt.Sprintf("delete user '%s': %v", u.Name, err)) + _ = system_model.CreateNotice(ctx, system_model.NoticeTask, fmt.Sprintf("delete user '%s': %v", u.Name, err)) return err } @@ -95,7 +95,7 @@ func DeleteUser(u *user_model.User) error { avatarPath := u.CustomAvatarRelativePath() if err := storage.Avatars.Delete(avatarPath); err != nil { err = fmt.Errorf("Failed to remove %s: %v", avatarPath, err) - _ = admin_model.CreateNotice(ctx, admin_model.NoticeTask, fmt.Sprintf("delete user '%s': %v", u.Name, err)) + _ = system_model.CreateNotice(ctx, system_model.NoticeTask, fmt.Sprintf("delete user '%s': %v", u.Name, err)) return err } } diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index 43e35eed692e4..75c9be44a0202 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -13,8 +13,9 @@ import ( "strings" "code.gitea.io/gitea/models" - admin_model "code.gitea.io/gitea/models/admin" + "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" + system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" @@ -380,6 +381,6 @@ func DeleteWiki(ctx context.Context, repo *repo_model.Repository) error { return err } - admin_model.RemoveAllWithNotice(ctx, "Delete repository wiki", repo.WikiPath()) + system_model.RemoveAllWithNotice(ctx, "Delete repository wiki", repo.WikiPath()) return nil } From 7a8f5825517bb5e302cc893c702a400af5dac39a Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 14 Apr 2022 21:59:06 +0800 Subject: [PATCH 02/25] Fix merge --- models/issue.go | 4 ++-- modules/system/user_setting.go | 6 +----- services/cron/tasks_extended.go | 4 ++-- services/wiki/wiki.go | 1 - 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/models/issue.go b/models/issue.go index 1a66e5e95bbaa..2a83e458015b7 100644 --- a/models/issue.go +++ b/models/issue.go @@ -13,7 +13,6 @@ import ( "strconv" "strings" - admin_model "code.gitea.io/gitea/models/admin" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/foreignreference" issues_model "code.gitea.io/gitea/models/issues" @@ -22,6 +21,7 @@ import ( access_model "code.gitea.io/gitea/models/perm/access" project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" + system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" @@ -2047,7 +2047,7 @@ func deleteIssue(ctx context.Context, issue *Issue) error { } for i := range attachments { - admin_model.RemoveStorageWithNotice(ctx, storage.Attachments, "Delete issue attachment", attachments[i].RelativePath()) + system_model.RemoveStorageWithNotice(ctx, storage.Attachments, "Delete issue attachment", attachments[i].RelativePath()) } // delete all database data still assigned to this issue diff --git a/modules/system/user_setting.go b/modules/system/user_setting.go index 02f76c0ac5fe0..eaf146c08dd6e 100644 --- a/modules/system/user_setting.go +++ b/modules/system/user_setting.go @@ -30,9 +30,5 @@ func GetUserSetting(userID int64, key string) (string, error) { func SetUserSetting(userID int64, key, value string) error { cache.Remove(genUserKey(userID, key)) - return user.SetSetting(&user.Setting{ - UserID: userID, - SettingKey: key, - SettingValue: value, - }) + return user.SetUserSetting(userID, key, value) } diff --git a/services/cron/tasks_extended.go b/services/cron/tasks_extended.go index 41bd5c4420be5..e9e101ae456f1 100644 --- a/services/cron/tasks_extended.go +++ b/services/cron/tasks_extended.go @@ -9,9 +9,9 @@ import ( "time" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/models/admin" asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/updatechecker" @@ -166,7 +166,7 @@ func registerDeleteOldSystemNotices() { OlderThan: 365 * 24 * time.Hour, }, func(ctx context.Context, _ *user_model.User, config Config) error { olderThanConfig := config.(*OlderThanConfig) - return admin.DeleteOldSystemNotices(olderThanConfig.OlderThan) + return system.DeleteOldSystemNotices(olderThanConfig.OlderThan) }) } diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index 75c9be44a0202..0cbfc0694eddf 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -13,7 +13,6 @@ import ( "strings" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unit" From 705f284541adbc394fa8cef4b4898e7d05a17051 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 12 May 2022 00:05:07 +0800 Subject: [PATCH 03/25] fix build --- models/repo.go | 3 --- services/repository/repository.go | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/models/repo.go b/models/repo.go index fb33f02151d90..ee2acacb7c402 100644 --- a/models/repo.go +++ b/models/repo.go @@ -44,9 +44,6 @@ var ItemsPerPage = 40 // NewRepoContext creates a new repository context func NewRepoContext() { unit.LoadUnitConfig() - - system_model.RemoveAllWithNotice(db.DefaultContext, "Clean up temporary repository uploads", setting.Repository.Upload.TempPath) - system_model.RemoveAllWithNotice(db.DefaultContext, "Clean up temporary repositories", LocalCopyPath()) } // CheckRepoUnitUser check whether user could visit the unit of this repository diff --git a/services/repository/repository.go b/services/repository/repository.go index 6799ca586ed9b..8e1bbe2bf4b55 100644 --- a/services/repository/repository.go +++ b/services/repository/repository.go @@ -9,11 +9,11 @@ import ( "fmt" "code.gitea.io/gitea/models" - admin_model "code.gitea.io/gitea/models/admin" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" packages_model "code.gitea.io/gitea/models/packages" repo_model "code.gitea.io/gitea/models/repo" + system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification" @@ -81,7 +81,7 @@ func PushCreateRepo(authUser, owner *user_model.User, repoName string) (*repo_mo // Init start repository service func Init() error { repo_module.LoadRepoConfig() - admin_model.RemoveAllWithNotice(db.DefaultContext, "Clean up temporary repository uploads", setting.Repository.Upload.TempPath) - admin_model.RemoveAllWithNotice(db.DefaultContext, "Clean up temporary repositories", repo_module.LocalCopyPath()) + system_model.RemoveAllWithNotice(db.DefaultContext, "Clean up temporary repository uploads", setting.Repository.Upload.TempPath) + system_model.RemoveAllWithNotice(db.DefaultContext, "Clean up temporary repositories", repo_module.LocalCopyPath()) return initPushQueue() } From 7c0127ad46eb719d891962ecf334c1b05ee866dc Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 13 May 2022 00:49:18 +0800 Subject: [PATCH 04/25] Add ui for some config --- models/migrations/v216.go | 53 ++++- models/system/setting.go | 51 +++- modules/setting/picture.go | 4 + modules/setting/setting.go | 6 + routers/web/admin/admin.go | 169 -------------- routers/web/admin/config.go | 217 ++++++++++++++++++ routers/web/web.go | 9 +- templates/admin/config.tmpl | 12 +- .../{admin-common.js => admin/common.js} | 0 web_src/js/features/admin/config.js | 27 +++ .../{admin-emails.js => admin/emails.js} | 0 .../{admin-users.js => admin/users.js} | 0 web_src/js/index.js | 8 +- 13 files changed, 366 insertions(+), 190 deletions(-) create mode 100644 routers/web/admin/config.go rename web_src/js/features/{admin-common.js => admin/common.js} (100%) create mode 100644 web_src/js/features/admin/config.js rename web_src/js/features/{admin-emails.js => admin/emails.js} (100%) rename web_src/js/features/{admin-users.js => admin/users.js} (100%) diff --git a/models/migrations/v216.go b/models/migrations/v216.go index a30fed9e32292..284ccda172321 100644 --- a/models/migrations/v216.go +++ b/models/migrations/v216.go @@ -6,18 +6,59 @@ package migrations import ( "fmt" + "strconv" + + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/timeutil" "xorm.io/xorm" ) -func createSystemSettingsTable(x *xorm.Engine) error { - type SystemSetting struct { - ID int64 `xorm:"pk autoincr"` - SettingKey string `xorm:"varchar(255) unique"` // ensure key is always lowercase - SettingValue string `xorm:"text"` +type SystemSetting struct { + ID int64 `xorm:"pk autoincr"` + SettingKey string `xorm:"varchar(255) unique"` // ensure key is always lowercase + SettingValue string `xorm:"text"` + Version int `xorm:"version"` // prevent to override + Created timeutil.TimeStamp `xorm:"created"` + Updated timeutil.TimeStamp `xorm:"updated"` +} + +func insertSettingsIfNotExist(x *xorm.Engine, sysSettings []*SystemSetting) error { + sess := x.NewSession() + defer sess.Close() + if err := sess.Begin(); err != nil { + return err + } + for _, setting := range sysSettings { + exist, err := sess.Table("system_setting").Where("setting_key=?", setting.SettingKey).Exist() + if err != nil { + return err + } + if !exist { + if _, err := sess.Insert(setting); err != nil { + return err + } + } } + return sess.Commit() +} + +func createSystemSettingsTable(x *xorm.Engine) error { if err := x.Sync2(new(SystemSetting)); err != nil { return fmt.Errorf("sync2: %v", err) } - return nil + + // migrate xx to database + sysSettings := []*SystemSetting{ + { + SettingKey: "disable_gravatar", + SettingValue: strconv.FormatBool(setting.DisableGravatar), + }, + { + SettingKey: "enable_federated_avatar", + SettingValue: strconv.FormatBool(setting.EnableFederatedAvatar), + }, + } + + return insertSettingsIfNotExist(x, sysSettings) } diff --git a/models/system/setting.go b/models/system/setting.go index aa35fe2695a7a..2713d8b759e7c 100644 --- a/models/system/setting.go +++ b/models/system/setting.go @@ -7,18 +7,23 @@ package system import ( "context" "fmt" + "strconv" "strings" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/timeutil" "xorm.io/builder" ) // Setting is a key value store of user settings type Setting struct { - ID int64 `xorm:"pk autoincr"` - SettingKey string `xorm:"varchar(255) unique"` // ensure key is always lowercase - SettingValue string `xorm:"text"` + ID int64 `xorm:"pk autoincr"` + SettingKey string `xorm:"varchar(255) unique"` // ensure key is always lowercase + SettingValue string `xorm:"text"` + Version int `xorm:"version"` // prevent to override + Created timeutil.TimeStamp `xorm:"created"` + Updated timeutil.TimeStamp `xorm:"updated"` } // TableName sets the table name for the settings struct @@ -46,6 +51,22 @@ func IsErrSettingIsNotExist(err error) bool { return ok } +// ErrDataExpired represents an error that update a record which has been updated by another thread +type ErrDataExpired struct { + Key string +} + +// Error implements error +func (err ErrDataExpired) Error() string { + return fmt.Sprintf("System setting[%s] has been updated by another thread", err.Key) +} + +// IsErrDataExpired return true if err is ErrDataExpired +func IsErrDataExpired(err error) bool { + _, ok := err.(ErrDataExpired) + return ok +} + // GetSetting returns specific setting func GetSetting(key string) (*Setting, error) { v, err := GetSettings([]string{key}) @@ -73,8 +94,22 @@ func GetSettings(keys []string) (map[string]*Setting, error) { return settingsMap, nil } +type AllSettings map[string]*Setting + +func (settings AllSettings) Get(key string) Setting { + if v, ok := settings[key]; ok { + return *v + } + return Setting{} +} + +func (settings AllSettings) GetBool(key string) bool { + b, _ := strconv.ParseBool(settings.Get(key).SettingValue) + return b +} + // GetAllSettings returns all settings from user -func GetAllSettings() (map[string]*Setting, error) { +func GetAllSettings() (AllSettings, error) { settings := make([]*Setting, 0, 5) if err := db.GetEngine(db.DefaultContext). Find(&settings); err != nil { @@ -98,10 +133,10 @@ func SetSetting(setting *Setting) error { if strings.ToLower(setting.SettingKey) != setting.SettingKey { return fmt.Errorf("setting key should be lowercase") } - return upsertSettingValue(setting.SettingKey, setting.SettingValue) + return upsertSettingValue(setting.SettingKey, setting.SettingValue, setting.Version) } -func upsertSettingValue(key, value string) error { +func upsertSettingValue(key, value string, version int) error { return db.WithTx(func(ctx context.Context) error { e := db.GetEngine(ctx) @@ -115,7 +150,7 @@ func upsertSettingValue(key, value string) error { // to optimize the SELECT in step 2, we can use an extra column like `revision=revision+1` // to make sure the UPDATE always returns a non-zero value for existing (unchanged) records. - res, err := e.Exec("UPDATE system_setting SET setting_value=? WHERE setting_key=?", value, key) + res, err := e.Exec("UPDATE system_setting SET setting_value=? WHERE setting_key=? AND version=?", value, key, version) if err != nil { return err } @@ -131,7 +166,7 @@ func upsertSettingValue(key, value string) error { return err } if has { - return nil + return ErrDataExpired{Key: key} } // if no existing row, insert a new row diff --git a/modules/setting/picture.go b/modules/setting/picture.go index a6d3447dcc398..526aad00e9740 100644 --- a/modules/setting/picture.go +++ b/modules/setting/picture.go @@ -69,8 +69,12 @@ func newPictureService() { default: GravatarSource = source } + DisableGravatar = sec.Key("DISABLE_GRAVATAR").MustBool() + deprecatedSettingDB("", "DISABLE_GRAVATAR") EnableFederatedAvatar = sec.Key("ENABLE_FEDERATED_AVATAR").MustBool(!InstallLock) + deprecatedSettingDB("", "ENABLE_FEDERATED_AVATAR") + if OfflineMode { DisableGravatar = true EnableFederatedAvatar = false diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 5e317b39ea289..1d7b7a7d9e84c 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -583,6 +583,12 @@ func deprecatedSetting(oldSection, oldKey, newSection, newKey string) { } } +func deprecatedSettingDB(oldSection, oldKey string) { + if Cfg.Section(oldSection).HasKey(oldKey) { + log.Error("Deprecated `[%s]` `%s` present which has been copied to database table sys_setting", oldSection, oldKey) + } +} + // loadFromConf initializes configuration context. // NOTE: do not print any log except error. func loadFromConf(allowEmpty bool, extraConfig string) { diff --git a/routers/web/admin/admin.go b/routers/web/admin/admin.go index 78347e67c4bd0..2fa08b98d9294 100644 --- a/routers/web/admin/admin.go +++ b/routers/web/admin/admin.go @@ -8,36 +8,26 @@ package admin import ( "fmt" "net/http" - "net/url" - "os" "runtime" "strconv" - "strings" "time" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/queue" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/updatechecker" - "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/cron" "code.gitea.io/gitea/services/forms" - "code.gitea.io/gitea/services/mailer" - - "gitea.com/go-chi/session" ) const ( tplDashboard base.TplName = "admin/dashboard" - tplConfig base.TplName = "admin/config" tplMonitor base.TplName = "admin/monitor" tplStacktrace base.TplName = "admin/stacktrace" tplQueue base.TplName = "admin/queue" @@ -164,165 +154,6 @@ func DashboardPost(ctx *context.Context) { } } -// SendTestMail send test mail to confirm mail service is OK -func SendTestMail(ctx *context.Context) { - email := ctx.FormString("email") - // Send a test email to the user's email address and redirect back to Config - if err := mailer.SendTestMail(email); err != nil { - ctx.Flash.Error(ctx.Tr("admin.config.test_mail_failed", email, err)) - } else { - ctx.Flash.Info(ctx.Tr("admin.config.test_mail_sent", email)) - } - - ctx.Redirect(setting.AppSubURL + "/admin/config") -} - -func shadowPasswordKV(cfgItem, splitter string) string { - fields := strings.Split(cfgItem, splitter) - for i := 0; i < len(fields); i++ { - if strings.HasPrefix(fields[i], "password=") { - fields[i] = "password=******" - break - } - } - return strings.Join(fields, splitter) -} - -func shadowURL(provider, cfgItem string) string { - u, err := url.Parse(cfgItem) - if err != nil { - log.Error("Shadowing Password for %v failed: %v", provider, err) - return cfgItem - } - if u.User != nil { - atIdx := strings.Index(cfgItem, "@") - if atIdx > 0 { - colonIdx := strings.LastIndex(cfgItem[:atIdx], ":") - if colonIdx > 0 { - return cfgItem[:colonIdx+1] + "******" + cfgItem[atIdx:] - } - } - } - return cfgItem -} - -func shadowPassword(provider, cfgItem string) string { - switch provider { - case "redis": - return shadowPasswordKV(cfgItem, ",") - case "mysql": - // root:@tcp(localhost:3306)/macaron?charset=utf8 - atIdx := strings.Index(cfgItem, "@") - if atIdx > 0 { - colonIdx := strings.Index(cfgItem[:atIdx], ":") - if colonIdx > 0 { - return cfgItem[:colonIdx+1] + "******" + cfgItem[atIdx:] - } - } - return cfgItem - case "postgres": - // user=jiahuachen dbname=macaron port=5432 sslmode=disable - if !strings.HasPrefix(cfgItem, "postgres://") { - return shadowPasswordKV(cfgItem, " ") - } - fallthrough - case "couchbase": - return shadowURL(provider, cfgItem) - // postgres://pqgotest:password@localhost/pqgotest?sslmode=verify-full - // Notice: use shadowURL - } - return cfgItem -} - -// Config show admin config page -func Config(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("admin.config") - ctx.Data["PageIsAdmin"] = true - ctx.Data["PageIsAdminConfig"] = true - - ctx.Data["CustomConf"] = setting.CustomConf - ctx.Data["AppUrl"] = setting.AppURL - ctx.Data["Domain"] = setting.Domain - ctx.Data["OfflineMode"] = setting.OfflineMode - ctx.Data["DisableRouterLog"] = setting.DisableRouterLog - ctx.Data["RunUser"] = setting.RunUser - ctx.Data["RunMode"] = util.ToTitleCase(setting.RunMode) - if version, err := git.LocalVersion(); err == nil { - ctx.Data["GitVersion"] = version.Original() - } - ctx.Data["RepoRootPath"] = setting.RepoRootPath - ctx.Data["CustomRootPath"] = setting.CustomPath - ctx.Data["StaticRootPath"] = setting.StaticRootPath - ctx.Data["LogRootPath"] = setting.LogRootPath - ctx.Data["ScriptType"] = setting.ScriptType - ctx.Data["ReverseProxyAuthUser"] = setting.ReverseProxyAuthUser - ctx.Data["ReverseProxyAuthEmail"] = setting.ReverseProxyAuthEmail - - ctx.Data["SSH"] = setting.SSH - ctx.Data["LFS"] = setting.LFS - - ctx.Data["Service"] = setting.Service - ctx.Data["DbCfg"] = setting.Database - ctx.Data["Webhook"] = setting.Webhook - - ctx.Data["MailerEnabled"] = false - if setting.MailService != nil { - ctx.Data["MailerEnabled"] = true - ctx.Data["Mailer"] = setting.MailService - } - - ctx.Data["CacheAdapter"] = setting.CacheService.Adapter - ctx.Data["CacheInterval"] = setting.CacheService.Interval - - ctx.Data["CacheConn"] = shadowPassword(setting.CacheService.Adapter, setting.CacheService.Conn) - ctx.Data["CacheItemTTL"] = setting.CacheService.TTL - - sessionCfg := setting.SessionConfig - if sessionCfg.Provider == "VirtualSession" { - var realSession session.Options - if err := json.Unmarshal([]byte(sessionCfg.ProviderConfig), &realSession); err != nil { - log.Error("Unable to unmarshall session config for virtualed provider config: %s\nError: %v", sessionCfg.ProviderConfig, err) - } - sessionCfg.Provider = realSession.Provider - sessionCfg.ProviderConfig = realSession.ProviderConfig - sessionCfg.CookieName = realSession.CookieName - sessionCfg.CookiePath = realSession.CookiePath - sessionCfg.Gclifetime = realSession.Gclifetime - sessionCfg.Maxlifetime = realSession.Maxlifetime - sessionCfg.Secure = realSession.Secure - sessionCfg.Domain = realSession.Domain - } - sessionCfg.ProviderConfig = shadowPassword(sessionCfg.Provider, sessionCfg.ProviderConfig) - ctx.Data["SessionConfig"] = sessionCfg - - ctx.Data["DisableGravatar"] = setting.DisableGravatar - ctx.Data["EnableFederatedAvatar"] = setting.EnableFederatedAvatar - - ctx.Data["Git"] = setting.Git - - type envVar struct { - Name, Value string - } - - envVars := map[string]*envVar{} - if len(os.Getenv("GITEA_WORK_DIR")) > 0 { - envVars["GITEA_WORK_DIR"] = &envVar{"GITEA_WORK_DIR", os.Getenv("GITEA_WORK_DIR")} - } - if len(os.Getenv("GITEA_CUSTOM")) > 0 { - envVars["GITEA_CUSTOM"] = &envVar{"GITEA_CUSTOM", os.Getenv("GITEA_CUSTOM")} - } - - ctx.Data["EnvVars"] = envVars - ctx.Data["Loggers"] = setting.GetLogDescriptions() - ctx.Data["EnableAccessLog"] = setting.EnableAccessLog - ctx.Data["AccessLogTemplate"] = setting.AccessLogTemplate - ctx.Data["DisableRouterLog"] = setting.DisableRouterLog - ctx.Data["EnableXORMLog"] = setting.EnableXORMLog - ctx.Data["LogSQL"] = setting.Database.LogSQL - - ctx.HTML(http.StatusOK, tplConfig) -} - // Monitor show admin monitor page func Monitor(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.monitor") diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go new file mode 100644 index 0000000000000..9966c71175136 --- /dev/null +++ b/routers/web/admin/config.go @@ -0,0 +1,217 @@ +// Copyright 2014 The Gogs Authors. All rights reserved. +// Copyright 2019 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package admin + +import ( + "net/http" + "net/url" + "os" + "strings" + + system_model "code.gitea.io/gitea/models/system" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/services/mailer" + "gitea.com/go-chi/session" +) + +const tplConfig base.TplName = "admin/config" + +// SendTestMail send test mail to confirm mail service is OK +func SendTestMail(ctx *context.Context) { + email := ctx.FormString("email") + // Send a test email to the user's email address and redirect back to Config + if err := mailer.SendTestMail(email); err != nil { + ctx.Flash.Error(ctx.Tr("admin.config.test_mail_failed", email, err)) + } else { + ctx.Flash.Info(ctx.Tr("admin.config.test_mail_sent", email)) + } + + ctx.Redirect(setting.AppSubURL + "/admin/config") +} + +func shadowPasswordKV(cfgItem, splitter string) string { + fields := strings.Split(cfgItem, splitter) + for i := 0; i < len(fields); i++ { + if strings.HasPrefix(fields[i], "password=") { + fields[i] = "password=******" + break + } + } + return strings.Join(fields, splitter) +} + +func shadowURL(provider, cfgItem string) string { + u, err := url.Parse(cfgItem) + if err != nil { + log.Error("Shadowing Password for %v failed: %v", provider, err) + return cfgItem + } + if u.User != nil { + atIdx := strings.Index(cfgItem, "@") + if atIdx > 0 { + colonIdx := strings.LastIndex(cfgItem[:atIdx], ":") + if colonIdx > 0 { + return cfgItem[:colonIdx+1] + "******" + cfgItem[atIdx:] + } + } + } + return cfgItem +} + +func shadowPassword(provider, cfgItem string) string { + switch provider { + case "redis": + return shadowPasswordKV(cfgItem, ",") + case "mysql": + // root:@tcp(localhost:3306)/macaron?charset=utf8 + atIdx := strings.Index(cfgItem, "@") + if atIdx > 0 { + colonIdx := strings.Index(cfgItem[:atIdx], ":") + if colonIdx > 0 { + return cfgItem[:colonIdx+1] + "******" + cfgItem[atIdx:] + } + } + return cfgItem + case "postgres": + // user=jiahuachen dbname=macaron port=5432 sslmode=disable + if !strings.HasPrefix(cfgItem, "postgres://") { + return shadowPasswordKV(cfgItem, " ") + } + fallthrough + case "couchbase": + return shadowURL(provider, cfgItem) + // postgres://pqgotest:password@localhost/pqgotest?sslmode=verify-full + // Notice: use shadowURL + } + return cfgItem +} + +// Config show admin config page +func Config(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("admin.config") + ctx.Data["PageIsAdmin"] = true + ctx.Data["PageIsAdminConfig"] = true + + systemSettings, err := system_model.GetAllSettings() + if err != nil { + ctx.ServerError("system_model.GetAllSettings", err) + return + } + + // All editable settings from UI + ctx.Data["SystemSettings"] = systemSettings + ctx.PageData["adminConfigPage"] = map[string]string{ + "abc": "", + } + + ctx.Data["CustomConf"] = setting.CustomConf + ctx.Data["AppUrl"] = setting.AppURL + ctx.Data["Domain"] = setting.Domain + ctx.Data["OfflineMode"] = setting.OfflineMode + ctx.Data["DisableRouterLog"] = setting.DisableRouterLog + ctx.Data["RunUser"] = setting.RunUser + ctx.Data["RunMode"] = util.ToTitleCase(setting.RunMode) + if version, err := git.LocalVersion(); err == nil { + ctx.Data["GitVersion"] = version.Original() + } + ctx.Data["RepoRootPath"] = setting.RepoRootPath + ctx.Data["CustomRootPath"] = setting.CustomPath + ctx.Data["StaticRootPath"] = setting.StaticRootPath + ctx.Data["LogRootPath"] = setting.LogRootPath + ctx.Data["ScriptType"] = setting.ScriptType + ctx.Data["ReverseProxyAuthUser"] = setting.ReverseProxyAuthUser + ctx.Data["ReverseProxyAuthEmail"] = setting.ReverseProxyAuthEmail + + ctx.Data["SSH"] = setting.SSH + ctx.Data["LFS"] = setting.LFS + + ctx.Data["Service"] = setting.Service + ctx.Data["DbCfg"] = setting.Database + ctx.Data["Webhook"] = setting.Webhook + + ctx.Data["MailerEnabled"] = false + if setting.MailService != nil { + ctx.Data["MailerEnabled"] = true + ctx.Data["Mailer"] = setting.MailService + } + + ctx.Data["CacheAdapter"] = setting.CacheService.Adapter + ctx.Data["CacheInterval"] = setting.CacheService.Interval + + ctx.Data["CacheConn"] = shadowPassword(setting.CacheService.Adapter, setting.CacheService.Conn) + ctx.Data["CacheItemTTL"] = setting.CacheService.TTL + + sessionCfg := setting.SessionConfig + if sessionCfg.Provider == "VirtualSession" { + var realSession session.Options + if err := json.Unmarshal([]byte(sessionCfg.ProviderConfig), &realSession); err != nil { + log.Error("Unable to unmarshall session config for virtualed provider config: %s\nError: %v", sessionCfg.ProviderConfig, err) + } + sessionCfg.Provider = realSession.Provider + sessionCfg.ProviderConfig = realSession.ProviderConfig + sessionCfg.CookieName = realSession.CookieName + sessionCfg.CookiePath = realSession.CookiePath + sessionCfg.Gclifetime = realSession.Gclifetime + sessionCfg.Maxlifetime = realSession.Maxlifetime + sessionCfg.Secure = realSession.Secure + sessionCfg.Domain = realSession.Domain + } + sessionCfg.ProviderConfig = shadowPassword(sessionCfg.Provider, sessionCfg.ProviderConfig) + ctx.Data["SessionConfig"] = sessionCfg + + ctx.Data["Git"] = setting.Git + + type envVar struct { + Name, Value string + } + + envVars := map[string]*envVar{} + if len(os.Getenv("GITEA_WORK_DIR")) > 0 { + envVars["GITEA_WORK_DIR"] = &envVar{"GITEA_WORK_DIR", os.Getenv("GITEA_WORK_DIR")} + } + if len(os.Getenv("GITEA_CUSTOM")) > 0 { + envVars["GITEA_CUSTOM"] = &envVar{"GITEA_CUSTOM", os.Getenv("GITEA_CUSTOM")} + } + + ctx.Data["EnvVars"] = envVars + ctx.Data["Loggers"] = setting.GetLogDescriptions() + ctx.Data["EnableAccessLog"] = setting.EnableAccessLog + ctx.Data["AccessLogTemplate"] = setting.AccessLogTemplate + ctx.Data["DisableRouterLog"] = setting.DisableRouterLog + ctx.Data["EnableXORMLog"] = setting.EnableXORMLog + ctx.Data["LogSQL"] = setting.Database.LogSQL + + ctx.HTML(http.StatusOK, tplConfig) +} + +func ChangeConfig(ctx *context.Context) { + key := strings.TrimSpace(ctx.FormString("key")) + if key == "" { + ctx.JSON(http.StatusOK, map[string]string{}) + return + } + value := ctx.FormString("value") + + theSetting, err := system_model.GetSetting(key) + if err != nil { + ctx.JSON(http.StatusOK, map[string]string{}) + return + } + theSetting.SettingValue = value + + if err := system_model.SetSetting(theSetting); err != nil { + ctx.JSON(http.StatusOK, map[string]string{}) + return + } + + ctx.Redirect(ctx.Req.URL.String(), 302) +} diff --git a/routers/web/web.go b/routers/web/web.go index 1e550286f9eb1..6185199d491ee 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -463,8 +463,13 @@ func RegisterRoutes(m *web.Route) { m.Group("/admin", func() { m.Get("", adminReq, admin.Dashboard) m.Post("", adminReq, bindIgnErr(forms.AdminDashboardForm{}), admin.DashboardPost) - m.Get("/config", admin.Config) - m.Post("/config/test_mail", admin.SendTestMail) + + m.Group("/config", func() { + m.Get("", admin.Config) + m.Post("", admin.ChangeConfig) + m.Post("/test_mail", admin.SendTestMail) + }) + m.Group("/monitor", func() { m.Get("", admin.Monitor) m.Get("/stacktrace", admin.GoroutineStacktrace) diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index 2a27baf53596b..a8fc7b64100d5 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -294,10 +294,18 @@
{{.i18n.Tr "admin.config.disable_gravatar"}}
-
{{if .DisableGravatar}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}
+
+
+ +
+
{{.i18n.Tr "admin.config.enable_federated_avatar"}}
-
{{if .EnableFederatedAvatar}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}
+
+
+ +
+
diff --git a/web_src/js/features/admin-common.js b/web_src/js/features/admin/common.js similarity index 100% rename from web_src/js/features/admin-common.js rename to web_src/js/features/admin/common.js diff --git a/web_src/js/features/admin/config.js b/web_src/js/features/admin/config.js new file mode 100644 index 0000000000000..7199fd97a4227 --- /dev/null +++ b/web_src/js/features/admin/config.js @@ -0,0 +1,27 @@ +import $ from 'jquery'; + +const {appSubUrl, csrfToken} = window.config; + +export function initAdminConfigs() { + const isAdminConfigPage = window.config.pageData.adminConfigPage; + if (!isAdminConfigPage) return; + + $("input[type='checkbox']").on('change', (e) => { + const $this = $(e.currentTarget); + $.ajax({ + type: 'POST', + url: `${appSubUrl}/admin/config`, + data: { + _csrf: csrfToken, + key: $this.attr("name"), + value: $this.is(':checked'), + }, + success: (data, _, jqXHR) => { + + } + }); + + e.preventDefault(); + return false; + }); +} diff --git a/web_src/js/features/admin-emails.js b/web_src/js/features/admin/emails.js similarity index 100% rename from web_src/js/features/admin-emails.js rename to web_src/js/features/admin/emails.js diff --git a/web_src/js/features/admin-users.js b/web_src/js/features/admin/users.js similarity index 100% rename from web_src/js/features/admin-users.js rename to web_src/js/features/admin/users.js diff --git a/web_src/js/index.js b/web_src/js/index.js index 4343c2d9652df..3dd97fe1f07f5 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -16,7 +16,8 @@ import initRepoMigration from './features/repo-migration.js'; import initRepoProject from './features/repo-projects.js'; import initServiceWorker from './features/serviceworker.js'; import initTableSort from './features/tablesort.js'; -import {initAdminUserListSearchForm} from './features/admin-users.js'; +import {initAdminUserListSearchForm} from './features/admin/users.js'; +import {initAdminConfigs} from './features/admin/config.js'; import {initMarkupAnchors} from './markup/anchors.js'; import {initNotificationCount, initNotificationsTable} from './features/notification.js'; import {initRepoIssueContentHistory} from './features/repo-issue-content.js'; @@ -57,8 +58,8 @@ import { initHeadNavbarContentToggle, } from './features/common-global.js'; import {initRepoTopicBar} from './features/repo-home.js'; -import {initAdminEmails} from './features/admin-emails.js'; -import {initAdminCommon} from './features/admin-common.js'; +import {initAdminEmails} from './features/admin/emails.js'; +import {initAdminCommon} from './features/admin/common.js'; import {initRepoTemplateSearch} from './features/repo-template.js'; import {initRepoCodeView} from './features/repo-code.js'; import {initSshKeyFormParser} from './features/sshkey-helper.js'; @@ -128,6 +129,7 @@ $(document).ready(() => { initAdminCommon(); initAdminEmails(); initAdminUserListSearchForm(); + initAdminConfigs(); initDashboardRepoList(); From 6dfbaeef98e866d05e213a3e3905a9dd86dadabb Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 14 May 2022 10:50:20 +0800 Subject: [PATCH 05/25] Finished to change two system settings --- models/avatars/avatar.go | 18 ++++--- models/avatars/avatar_test.go | 11 ++-- models/fixtures/system_setting.yml | 11 ++++ models/system/setting.go | 82 ++++++++++++++++++++++++++++- models/user/avatar.go | 9 +++- modules/setting/picture.go | 56 ++++++-------------- modules/setting/setting.go | 1 + modules/system/setting.go | 11 +++- modules/templates/helper.go | 3 +- options/locale/locale_en-US.ini | 3 ++ routers/install/install.go | 23 ++++++-- routers/web/admin/config.go | 24 +++++---- templates/admin/config.tmpl | 4 +- web_src/js/features/admin/config.js | 17 ++++-- 14 files changed, 196 insertions(+), 77 deletions(-) create mode 100644 models/fixtures/system_setting.yml diff --git a/models/avatars/avatar.go b/models/avatars/avatar.go index 9f7b0c474ff05..f11bb2fff3ec3 100644 --- a/models/avatars/avatar.go +++ b/models/avatars/avatar.go @@ -13,6 +13,7 @@ import ( "sync" "code.gitea.io/gitea/models/db" + system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/log" @@ -72,7 +73,7 @@ func GetEmailForHash(md5Sum string) (string, error) { // LibravatarURL returns the URL for the given email. Slow due to the DNS lookup. // This function should only be called if a federated avatar service is enabled. func LibravatarURL(email string) (*url.URL, error) { - urlStr, err := setting.LibravatarService.FromEmail(email) + urlStr, err := system_model.LibravatarService.FromEmail(email) if err != nil { log.Error("LibravatarService.FromEmail(email=%s): error %v", email, err) return nil, err @@ -150,7 +151,7 @@ func generateEmailAvatarLink(email string, size int, final bool) string { } var err error - if setting.EnableFederatedAvatar && setting.LibravatarService != nil { + if setting.EnableFederatedAvatar && system_model.LibravatarService != nil { emailHash := saveEmailHash(email) if final { // for final link, we can spend more time on slow external query @@ -166,11 +167,14 @@ func generateEmailAvatarLink(email string, size int, final bool) string { urlStr += "?size=" + strconv.Itoa(size) } return urlStr - } else if !setting.DisableGravatar { - // copy GravatarSourceURL, because we will modify its Path. - avatarURLCopy := *setting.GravatarSourceURL - avatarURLCopy.Path = path.Join(avatarURLCopy.Path, HashEmail(email)) - return generateRecognizedAvatarURL(avatarURLCopy, size) + } else { + disableGravatar, _ := system_model.GetSetting("disable_gravatar") + if !disableGravatar.GetValueBool() { + // copy GravatarSourceURL, because we will modify its Path. + avatarURLCopy := *system_model.GravatarSourceURL + avatarURLCopy.Path = path.Join(avatarURLCopy.Path, HashEmail(email)) + return generateRecognizedAvatarURL(avatarURLCopy, size) + } } return DefaultAvatarLink() } diff --git a/models/avatars/avatar_test.go b/models/avatars/avatar_test.go index 4d6255ca5fefb..7c06cc9c0f4b7 100644 --- a/models/avatars/avatar_test.go +++ b/models/avatars/avatar_test.go @@ -8,6 +8,7 @@ import ( "net/url" "testing" + system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/setting" "github.com/stretchr/testify/assert" @@ -16,15 +17,15 @@ import ( const gravatarSource = "https://secure.gravatar.com/avatar/" func disableGravatar() { - setting.EnableFederatedAvatar = false - setting.LibravatarService = nil - setting.DisableGravatar = true + system_model.SetSettingNoVersion("enable_federated_avatar", "false") + system_model.SetSettingNoVersion("disable_gravatar", "true") + system_model.LibravatarService = nil } func enableGravatar(t *testing.T) { - setting.DisableGravatar = false + system_model.SetSettingNoVersion("disable_gravatar", "false") var err error - setting.GravatarSourceURL, err = url.Parse(gravatarSource) + system_model.GravatarSourceURL, err = url.Parse(gravatarSource) assert.NoError(t, err) } diff --git a/models/fixtures/system_setting.yml b/models/fixtures/system_setting.yml new file mode 100644 index 0000000000000..b0d101e01ff6f --- /dev/null +++ b/models/fixtures/system_setting.yml @@ -0,0 +1,11 @@ +- + id: 1 + setting_key: 'disable_gravatar' + setting_value: 'false' + version: 1 + +- + id: 2 + setting_key: 'enable_federated_avatar' + setting_value: 'false' + versin: 1 diff --git a/models/system/setting.go b/models/system/setting.go index 2713d8b759e7c..5381b72ebb819 100644 --- a/models/system/setting.go +++ b/models/system/setting.go @@ -6,12 +6,16 @@ package system import ( "context" + "errors" "fmt" + "net/url" "strconv" "strings" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" + "strk.kbt.io/projects/go/libravatar" "xorm.io/builder" ) @@ -31,6 +35,11 @@ func (s *Setting) TableName() string { return "system_setting" } +func (s *Setting) GetValueBool() bool { + b, _ := strconv.ParseBool(s.SettingValue) + return b +} + func init() { db.RegisterModel(new(Setting)) } @@ -108,6 +117,10 @@ func (settings AllSettings) GetBool(key string) bool { return b } +func (settings AllSettings) GetVersion(key string) int { + return settings.Get(key).Version +} + // GetAllSettings returns all settings from user func GetAllSettings() (AllSettings, error) { settings := make([]*Setting, 0, 5) @@ -128,12 +141,31 @@ func DeleteSetting(setting *Setting) error { return err } +func SetSettingNoVersion(key, value string) error { + s, err := GetSetting(key) + if errors.Is(err, ErrSettingIsNotExist{}) { + return SetSetting(&Setting{ + SettingKey: key, + SettingValue: value, + }) + } + if err != nil { + return err + } + s.SettingValue = value + return SetSetting(s) +} + // SetSetting updates a users' setting for a specific key func SetSetting(setting *Setting) error { if strings.ToLower(setting.SettingKey) != setting.SettingKey { return fmt.Errorf("setting key should be lowercase") } - return upsertSettingValue(setting.SettingKey, setting.SettingValue, setting.Version) + if err := upsertSettingValue(setting.SettingKey, setting.SettingValue, setting.Version); err != nil { + return err + } + setting.Version++ + return nil } func upsertSettingValue(key, value string, version int) error { @@ -150,7 +182,7 @@ func upsertSettingValue(key, value string, version int) error { // to optimize the SELECT in step 2, we can use an extra column like `revision=revision+1` // to make sure the UPDATE always returns a non-zero value for existing (unchanged) records. - res, err := e.Exec("UPDATE system_setting SET setting_value=? WHERE setting_key=? AND version=?", value, key, version) + res, err := e.Exec("UPDATE system_setting SET setting_value=?, version = version+1 WHERE setting_key=? AND version=?", value, key, version) if err != nil { return err } @@ -174,3 +206,49 @@ func upsertSettingValue(key, value string, version int) error { return err }) } + +var ( + GravatarSourceURL *url.URL + LibravatarService *libravatar.Libravatar +) + +func Init() error { + var disableGravatar bool + disableGravatarSetting, err := GetSetting("disable_gravatar") + if IsErrSettingIsNotExist(err) { + disableGravatar = setting.GetDefaultDisableGravatar() + disableGravatarSetting = &Setting{SettingValue: strconv.FormatBool(disableGravatar)} + } else if err != nil { + return err + } else { + disableGravatar = disableGravatarSetting.GetValueBool() + } + + enableFederatedAvatarSetting, err := GetSetting("enable_federated_avatar") + if IsErrSettingIsNotExist(err) { + enableFederatedAvatarSetting = &Setting{SettingValue: strconv.FormatBool(setting.GetDefaultEnableFederatedAvatar(disableGravatar))} + } + if err != nil { + return err + } + + if enableFederatedAvatarSetting.GetValueBool() || !disableGravatarSetting.GetValueBool() { + var err error + GravatarSourceURL, err = url.Parse(setting.GravatarSource) + if err != nil { + return fmt.Errorf("Failed to parse Gravatar URL(%s): %v", setting.GravatarSource, err) + } + } + + if enableFederatedAvatarSetting.GetValueBool() { + LibravatarService = libravatar.New() + if GravatarSourceURL.Scheme == "https" { + LibravatarService.SetUseHTTPS(true) + LibravatarService.SetSecureFallbackHost(GravatarSourceURL.Host) + } else { + LibravatarService.SetUseHTTPS(false) + LibravatarService.SetFallbackHost(GravatarSourceURL.Host) + } + } + return nil +} diff --git a/models/user/avatar.go b/models/user/avatar.go index 6a44a3bcb3c32..af569950dff60 100644 --- a/models/user/avatar.go +++ b/models/user/avatar.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/models/avatars" "code.gitea.io/gitea/models/db" + system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/avatar" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -67,10 +68,16 @@ func (u *User) AvatarLinkWithSize(size int) string { useLocalAvatar := false autoGenerateAvatar := false + var disableGravatar bool + disableGravatarSetting, _ := system_model.GetSetting("disable_gravatar") + if disableGravatarSetting != nil { + disableGravatar = disableGravatarSetting.GetValueBool() + } + switch { case u.UseCustomAvatar: useLocalAvatar = true - case setting.DisableGravatar, setting.OfflineMode: + case disableGravatar, setting.OfflineMode: useLocalAvatar = true autoGenerateAvatar = true } diff --git a/modules/setting/picture.go b/modules/setting/picture.go index 526aad00e9740..ea3b890bcf128 100644 --- a/modules/setting/picture.go +++ b/modules/setting/picture.go @@ -4,14 +4,6 @@ package setting -import ( - "net/url" - - "code.gitea.io/gitea/modules/log" - - "strk.kbt.io/projects/go/libravatar" -) - // settings var ( // Picture settings @@ -29,11 +21,9 @@ var ( RenderedSizeFactor: 3, } + DisableGravatar bool // Depreciated: migrated to database + EnableFederatedAvatar bool // Depreciated: migrated to database GravatarSource string - GravatarSourceURL *url.URL - DisableGravatar bool - EnableFederatedAvatar bool - LibravatarService *libravatar.Libravatar RepoAvatar = struct { Storage @@ -70,39 +60,27 @@ func newPictureService() { GravatarSource = source } - DisableGravatar = sec.Key("DISABLE_GRAVATAR").MustBool() + DisableGravatar = sec.Key("DISABLE_GRAVATAR").MustBool(GetDefaultDisableGravatar()) deprecatedSettingDB("", "DISABLE_GRAVATAR") - EnableFederatedAvatar = sec.Key("ENABLE_FEDERATED_AVATAR").MustBool(!InstallLock) + EnableFederatedAvatar = sec.Key("ENABLE_FEDERATED_AVATAR").MustBool(GetDefaultEnableFederatedAvatar(DisableGravatar)) deprecatedSettingDB("", "ENABLE_FEDERATED_AVATAR") + newRepoAvatarService() +} + +func GetDefaultDisableGravatar() bool { + return !OfflineMode +} + +func GetDefaultEnableFederatedAvatar(disableGravatar bool) bool { + v := !InstallLock if OfflineMode { - DisableGravatar = true - EnableFederatedAvatar = false + v = false } - if DisableGravatar { - EnableFederatedAvatar = false + if disableGravatar { + v = false } - if EnableFederatedAvatar || !DisableGravatar { - var err error - GravatarSourceURL, err = url.Parse(GravatarSource) - if err != nil { - log.Fatal("Failed to parse Gravatar URL(%s): %v", - GravatarSource, err) - } - } - - if EnableFederatedAvatar { - LibravatarService = libravatar.New() - if GravatarSourceURL.Scheme == "https" { - LibravatarService.SetUseHTTPS(true) - LibravatarService.SetSecureFallbackHost(GravatarSourceURL.Host) - } else { - LibravatarService.SetUseHTTPS(false) - LibravatarService.SetFallbackHost(GravatarSourceURL.Host) - } - } - - newRepoAvatarService() + return v } func newRepoAvatarService() { diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 1d7b7a7d9e84c..77bb5a59be306 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -583,6 +583,7 @@ func deprecatedSetting(oldSection, oldKey, newSection, newKey string) { } } +// deprecatedSettingDB add a hint that the configuration has been moved to database but still kept in app.ini func deprecatedSettingDB(oldSection, oldKey string) { if Cfg.Section(oldSection).HasKey(oldKey) { log.Error("Deprecated `[%s]` `%s` present which has been copied to database table sys_setting", oldSection, oldKey) diff --git a/modules/system/setting.go b/modules/system/setting.go index 81b20347453c4..afeb5834e4127 100644 --- a/modules/system/setting.go +++ b/modules/system/setting.go @@ -5,6 +5,8 @@ package system import ( + "strconv" + "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/cache" ) @@ -24,12 +26,19 @@ func GetSetting(key string) (string, error) { }) } +func GetSetingBool(key string) bool { + s, _ := GetSetting(key) + b, _ := strconv.ParseBool(s) + return b +} + // SetSetting sets the setting value -func SetSetting(key, value string) error { +func SetSetting(key, value string, version int) error { cache.Remove(genKey(key)) return system.SetSetting(&system.Setting{ SettingKey: key, SettingValue: value, + Version: version, }) } diff --git a/modules/templates/helper.go b/modules/templates/helper.go index cc0fed7442205..2efc4c89e9df9 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -38,6 +38,7 @@ import ( "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/svg" + system_module "code.gitea.io/gitea/modules/system" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/gitdiff" @@ -79,7 +80,7 @@ func NewFuncMap() []template.FuncMap { return setting.Domain }, "DisableGravatar": func() bool { - return setting.DisableGravatar + return system_module.GetSetingBool("disable_gravatar") }, "DefaultShowFullName": func() bool { return setting.UI.DefaultShowFullName diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 66dad56fd08fa..7393566f6e63e 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2852,6 +2852,9 @@ config.access_log_template = Template config.xorm_log_mode = XORM Log Mode config.xorm_log_sql = Log SQL +config.get_setting_failed = Get setting %s failed +config.set_setting_failed = Set setting %s failed + monitor.cron = Cron Tasks monitor.name = Name monitor.schedule = Schedule diff --git a/routers/install/install.go b/routers/install/install.go index 3fc5f0536ad72..b01f4199eb859 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -11,12 +11,14 @@ import ( "os" "os/exec" "path/filepath" + "strconv" "strings" "time" "code.gitea.io/gitea/models/db" db_install "code.gitea.io/gitea/models/db/install" "code.gitea.io/gitea/models/migrations" + system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" @@ -143,8 +145,19 @@ func Install(ctx *context.Context) { // Server and other services settings form.OfflineMode = setting.OfflineMode - form.DisableGravatar = setting.DisableGravatar - form.EnableFederatedAvatar = setting.EnableFederatedAvatar + disableGravatarSetting, _ := system_model.GetSetting("disable_gravatar") + if disableGravatarSetting != nil { + form.DisableGravatar = disableGravatarSetting.GetValueBool() + } else { + form.DisableGravatar = false + } + + enableFederatedAvatarSetting, _ := system_model.GetSetting("enable_federated_avatar") + if enableFederatedAvatarSetting != nil { + form.EnableFederatedAvatar = enableFederatedAvatarSetting.GetValueBool() + } else { + form.EnableFederatedAvatar = false + } form.EnableOpenIDSignIn = setting.Service.EnableOpenIDSignIn form.EnableOpenIDSignUp = setting.Service.EnableOpenIDSignUp form.DisableRegistration = setting.Service.DisableRegistration @@ -434,7 +447,11 @@ func SubmitInstall(ctx *context.Context) { cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").SetValue(fmt.Sprint(form.MailNotify)) cfg.Section("server").Key("OFFLINE_MODE").SetValue(fmt.Sprint(form.OfflineMode)) - cfg.Section("picture").Key("DISABLE_GRAVATAR").SetValue(fmt.Sprint(form.DisableGravatar)) + // if you are reinstalling, this maybe not right because of missing version + if err := system_model.SetSettingNoVersion("disable_gravatar", strconv.FormatBool(form.DisableGravatar)); err != nil { + ctx.RenderWithErr(ctx.Tr("install.secret_key_failed", err), tplInstall, &form) + return + } cfg.Section("picture").Key("ENABLE_FEDERATED_AVATAR").SetValue(fmt.Sprint(form.EnableFederatedAvatar)) cfg.Section("openid").Key("ENABLE_OPENID_SIGNIN").SetValue(fmt.Sprint(form.EnableOpenIDSignIn)) cfg.Section("openid").Key("ENABLE_OPENID_SIGNUP").SetValue(fmt.Sprint(form.EnableOpenIDSignUp)) diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go index 9966c71175136..1860362bbf7da 100644 --- a/routers/web/admin/config.go +++ b/routers/web/admin/config.go @@ -18,6 +18,7 @@ import ( "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + system_module "code.gitea.io/gitea/modules/system" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/mailer" "gitea.com/go-chi/session" @@ -196,22 +197,23 @@ func Config(ctx *context.Context) { func ChangeConfig(ctx *context.Context) { key := strings.TrimSpace(ctx.FormString("key")) if key == "" { - ctx.JSON(http.StatusOK, map[string]string{}) + ctx.JSON(http.StatusOK, map[string]string{ + "redirect": ctx.Req.URL.String(), + }) return } value := ctx.FormString("value") + version := ctx.FormInt("version") - theSetting, err := system_model.GetSetting(key) - if err != nil { - ctx.JSON(http.StatusOK, map[string]string{}) - return - } - theSetting.SettingValue = value - - if err := system_model.SetSetting(theSetting); err != nil { - ctx.JSON(http.StatusOK, map[string]string{}) + if err := system_module.SetSetting(key, value, version); err != nil { + log.Error("set setting failed: %v", err) + ctx.JSON(http.StatusOK, map[string]string{ + "err": ctx.Tr("admin.config.set_setting_failed", key), + }) return } - ctx.Redirect(ctx.Req.URL.String(), 302) + ctx.JSON(http.StatusOK, map[string]interface{}{ + "version": version + 1, + }) } diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index a8fc7b64100d5..4e787142657fe 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -296,14 +296,14 @@
{{.i18n.Tr "admin.config.disable_gravatar"}}
- +
{{.i18n.Tr "admin.config.enable_federated_avatar"}}
- +
diff --git a/web_src/js/features/admin/config.js b/web_src/js/features/admin/config.js index 7199fd97a4227..f4e7f9a461054 100644 --- a/web_src/js/features/admin/config.js +++ b/web_src/js/features/admin/config.js @@ -9,15 +9,22 @@ export function initAdminConfigs() { $("input[type='checkbox']").on('change', (e) => { const $this = $(e.currentTarget); $.ajax({ - type: 'POST', url: `${appSubUrl}/admin/config`, + type: 'POST', data: { _csrf: csrfToken, - key: $this.attr("name"), + key: $this.attr('name'), value: $this.is(':checked'), - }, - success: (data, _, jqXHR) => { - + version: $this.attr('version'), + } + }).done((resp) => { + if (resp) { + console.info(resp); + if (resp.redirect) { + window.location.href = resp.redirect; + } else if (resp.version) { + $this.attr('version', resp.version); + } } }); From faea1dae3465ca57a4c2dcfbbfbc27dbf3ffff08 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 14 May 2022 15:13:49 +0800 Subject: [PATCH 06/25] Fix theme --- web_src/less/_base.less | 1 + web_src/less/_form.less | 2 +- web_src/less/themes/theme-arc-green.css | 762 +++++++++++++++++++++++ web_src/less/themes/theme-arc-green.less | 1 + 4 files changed, 765 insertions(+), 1 deletion(-) create mode 100644 web_src/less/themes/theme-arc-green.css diff --git a/web_src/less/_base.less b/web_src/less/_base.less index 461195df01804..7833c7b550b4e 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -123,6 +123,7 @@ --color-timeline: #ececec; --color-input-text: #212121; --color-input-background: #ffffff; + --color-input-toggle-background: #dedede; --color-input-border: #dedede; --color-input-border-hover: #cecece; --color-navbar: #f8f8f8; diff --git a/web_src/less/_form.less b/web_src/less/_form.less index 99aec18f482af..134a6d0bb2041 100644 --- a/web_src/less/_form.less +++ b/web_src/less/_form.less @@ -113,7 +113,7 @@ textarea:focus, } .ui.toggle.checkbox label::before { - background: var(--color-input-background); + background: var(--color-input-toggle-background); } .ui.toggle.checkbox label, diff --git a/web_src/less/themes/theme-arc-green.css b/web_src/less/themes/theme-arc-green.css new file mode 100644 index 0000000000000..b9f7cc9536bdd --- /dev/null +++ b/web_src/less/themes/theme-arc-green.css @@ -0,0 +1,762 @@ +.chroma .hl { + background-color: #3f424d; +} +/* LineHighlight */ +.chroma .lnt { + color: #7f7f7f; +} +/* LineNumbersTable */ +.chroma .ln { + color: #7f7f7f; +} +/* LineNumbers */ +.chroma .k { + color: #f63; +} +/* Keyword */ +.chroma .kc { + color: #fa1; +} +/* KeywordConstant */ +.chroma .kd { + color: #9daccc; +} +/* KeywordDeclaration */ +.chroma .kn { + color: #fa1; +} +/* KeywordNamespace */ +.chroma .kp { + color: #5f8700; +} +/* KeywordPseudo */ +.chroma .kr { + color: #f63; +} +/* KeywordReserved */ +.chroma .kt { + color: #9daccc; +} +/* KeywordType */ +.chroma .na { + color: #8a8a8a; +} +/* NameAttribute */ +.chroma .nb { + color: #9daccc; +} +/* NameBuiltin */ +.chroma .bp { + color: #9daccc; +} +/* NameBuiltinPseudo */ +.chroma .nc { + color: #fa1; +} +/* NameClass */ +.chroma .no { + color: #fa1; +} +/* NameConstant */ +.chroma .nd { + color: #9daccc; +} +/* NameDecorator */ +.chroma .ni { + color: #fa1; +} +/* NameEntity */ +.chroma .ne { + color: #af8700; +} +/* NameException */ +.chroma .nf { + color: #9daccc; +} +/* NameFunction */ +.chroma .nl { + color: #fa1; +} +/* NameLabel */ +.chroma .nn { + color: #fa1; +} +/* NameNamespace */ +.chroma .nx { + color: #9daccc; +} +/* NameOther */ +.chroma .nt { + color: #9daccc; +} +/* NameTag */ +.chroma .nv { + color: #9daccc; +} +/* NameVariable */ +.chroma .vc { + color: #f81; +} +/* NameVariableClass */ +.chroma .vg { + color: #fa1; +} +/* NameVariableGlobal */ +.chroma .vi { + color: #fa1; +} +/* NameVariableInstance */ +.chroma .s { + color: #1af; +} +/* LiteralString */ +.chroma .sa { + color: #1af; +} +/* LiteralStringAffix */ +.chroma .sb { + color: #a0cc75; +} +/* LiteralStringBacktick */ +.chroma .sc { + color: #1af; +} +/* LiteralStringChar */ +.chroma .dl { + color: #1af; +} +/* LiteralStringDelimiter */ +.chroma .sd { + color: #6a737d; +} +/* LiteralStringDoc */ +.chroma .s2 { + color: #a0cc75; +} +/* LiteralStringDouble */ +.chroma .se { + color: #f63; +} +/* LiteralStringEscape */ +.chroma .sh { + color: #1af; +} +/* LiteralStringHeredoc */ +.chroma .si { + color: #fa1; +} +/* LiteralStringInterpol */ +.chroma .sx { + color: #fa1; +} +/* LiteralStringOther */ +.chroma .sr { + color: #97c; +} +/* LiteralStringRegex */ +.chroma .s1 { + color: #a0cc75; +} +/* LiteralStringSingle */ +.chroma .ss { + color: #fa1; +} +/* LiteralStringSymbol */ +.chroma .m { + color: #1af; +} +/* LiteralNumber */ +.chroma .mb { + color: #1af; +} +/* LiteralNumberBin */ +.chroma .mf { + color: #1af; +} +/* LiteralNumberFloat */ +.chroma .mh { + color: #1af; +} +/* LiteralNumberHex */ +.chroma .mi { + color: #1af; +} +/* LiteralNumberInteger */ +.chroma .il { + color: #1af; +} +/* LiteralNumberIntegerLong */ +.chroma .mo { + color: #1af; +} +/* LiteralNumberOct */ +.chroma .o { + color: #f63; +} +/* Operator */ +.chroma .ow { + color: #5f8700; +} +/* OperatorWord */ +.chroma .c { + color: #6a737d; +} +/* Comment */ +.chroma .ch { + color: #6a737d; +} +/* CommentHashbang */ +.chroma .cm { + color: #6a737d; +} +/* CommentMultiline */ +.chroma .c1 { + color: #6a737d; +} +/* CommentSingle */ +.chroma .cs { + color: #95ad; +} +/* CommentSpecial */ +.chroma .cp { + color: #fc6; +} +/* CommentPreproc */ +.chroma .cpf { + color: #03dfff; +} +/* CommentPreprocFile */ +.chroma .gd { + color: #fff; + background-color: #5f3737; +} +/* GenericDeleted */ +.chroma .ge { + color: #ef5; +} +/* GenericEmph */ +.chroma .gr { + color: #f33; +} +/* GenericError */ +.chroma .gh { + color: #fa1; +} +/* GenericHeading */ +.chroma .gi { + color: #fff; + background-color: #3a523a; +} +/* GenericInserted */ +.chroma .go { + color: #888888; +} +/* GenericOutput */ +.chroma .gp { + color: #555555; +} +/* GenericPrompt */ +.chroma .gu { + color: #9daccc; +} +/* GenericSubheading */ +.chroma .gt { + color: #f63; +} +/* GenericTraceback */ +.chroma .w { + color: #bbbbbb; +} +/* TextWhitespace */ +.CodeMirror.cm-s-default .cm-property, +.CodeMirror.cm-s-paper .cm-property { + color: #a0cc75; +} +.CodeMirror.cm-s-default .cm-header, +.CodeMirror.cm-s-paper .cm-header { + color: #9daccc; +} +.CodeMirror.cm-s-default .cm-quote, +.CodeMirror.cm-s-paper .cm-quote { + color: #009900; +} +.CodeMirror.cm-s-default .cm-keyword, +.CodeMirror.cm-s-paper .cm-keyword { + color: #cc8a61; +} +.CodeMirror.cm-s-default .cm-atom, +.CodeMirror.cm-s-paper .cm-atom { + color: #ef5e77; +} +.CodeMirror.cm-s-default .cm-number, +.CodeMirror.cm-s-paper .cm-number { + color: #ff5656; +} +.CodeMirror.cm-s-default .cm-def, +.CodeMirror.cm-s-paper .cm-def { + color: #e4e4e4; +} +.CodeMirror.cm-s-default .cm-variable-2, +.CodeMirror.cm-s-paper .cm-variable-2 { + color: #00bdbf; +} +.CodeMirror.cm-s-default .cm-variable-3, +.CodeMirror.cm-s-paper .cm-variable-3 { + color: #008855; +} +.CodeMirror.cm-s-default .cm-comment, +.CodeMirror.cm-s-paper .cm-comment { + color: #8e9ab3; +} +.CodeMirror.cm-s-default .cm-string, +.CodeMirror.cm-s-paper .cm-string { + color: #a77272; +} +.CodeMirror.cm-s-default .cm-string-2, +.CodeMirror.cm-s-paper .cm-string-2 { + color: #ff5500; +} +.CodeMirror.cm-s-default .cm-meta, +.CodeMirror.cm-s-paper .cm-meta, +.CodeMirror.cm-s-default .cm-qualifier, +.CodeMirror.cm-s-paper .cm-qualifier { + color: #ffb176; +} +.CodeMirror.cm-s-default .cm-builtin, +.CodeMirror.cm-s-paper .cm-builtin { + color: #b7c951; +} +.CodeMirror.cm-s-default .cm-bracket, +.CodeMirror.cm-s-paper .cm-bracket { + color: #999977; +} +.CodeMirror.cm-s-default .cm-tag, +.CodeMirror.cm-s-paper .cm-tag { + color: #f1d273; +} +.CodeMirror.cm-s-default .cm-attribute, +.CodeMirror.cm-s-paper .cm-attribute { + color: #bfcc70; +} +.CodeMirror.cm-s-default .cm-hr, +.CodeMirror.cm-s-paper .cm-hr { + color: #999999; +} +.CodeMirror.cm-s-default .cm-url, +.CodeMirror.cm-s-paper .cm-url { + color: #c5cfd0; +} +.CodeMirror.cm-s-default .cm-link, +.CodeMirror.cm-s-paper .cm-link { + color: #d8c792; +} +.CodeMirror.cm-s-default .cm-error, +.CodeMirror.cm-s-paper .cm-error { + color: #dbdbeb; +} +:root { + --is-dark-theme: true; + --color-primary: #87ab63; + --color-primary-dark-1: #93b373; + --color-primary-dark-2: #9fbc82; + --color-primary-dark-3: #abc492; + --color-primary-dark-4: #b7cda1; + --color-primary-dark-5: #cfddc1; + --color-primary-dark-6: #e7eee0; + --color-primary-dark-7: #f8faf6; + --color-primary-light-1: #7a9e55; + --color-primary-light-2: #6c8c4c; + --color-primary-light-3: #5f7b42; + --color-primary-light-4: #516939; + --color-primary-light-5: #364626; + --color-primary-light-6: #1b2313; + --color-primary-light-7: #080b06; + --color-primary-alpha-10: #87ab6319; + --color-primary-alpha-20: #87ab6333; + --color-primary-alpha-30: #87ab634b; + --color-primary-alpha-40: #87ab6366; + --color-primary-alpha-50: #87ab6380; + --color-primary-alpha-60: #87ab6399; + --color-primary-alpha-70: #87ab63b3; + --color-primary-alpha-80: #87ab63cc; + --color-primary-alpha-90: #87ab63e1; + --color-secondary: #454a57; + --color-secondary-dark-1: #505665; + --color-secondary-dark-2: #5b6273; + --color-secondary-dark-3: #71798e; + --color-secondary-dark-4: #7f8699; + --color-secondary-dark-5: #8c93a4; + --color-secondary-dark-6: #9aa0af; + --color-secondary-dark-7: #a8adba; + --color-secondary-dark-8: #b6bac5; + --color-secondary-dark-9: #c4c7d0; + --color-secondary-dark-10: #d2d4db; + --color-secondary-dark-11: #dfe1e6; + --color-secondary-dark-12: #edeef1; + --color-secondary-dark-13: #fbfbfc; + --color-secondary-light-1: #373b46; + --color-secondary-light-2: #292c34; + --color-secondary-light-3: #1c1e23; + --color-secondary-light-4: #0e0f11; + --color-secondary-alpha-10: #454a5719; + --color-secondary-alpha-20: #454a5733; + --color-secondary-alpha-30: #454a574b; + --color-secondary-alpha-40: #454a5766; + --color-secondary-alpha-50: #454a5780; + --color-secondary-alpha-60: #454a5799; + --color-secondary-alpha-70: #454a57b3; + --color-secondary-alpha-80: #454a57cc; + --color-secondary-alpha-90: #454a57e1; + /* colors */ + --color-red: #db2828; + --color-orange: #f2711c; + --color-yellow: #fbbd08; + --color-olive: #b5cc18; + --color-green: #21ba45; + --color-teal: #00b5ad; + --color-blue: #2185d0; + --color-violet: #6435c9; + --color-purple: #a333c8; + --color-pink: #e03997; + --color-brown: #a5673f; + --color-grey: #767a85; + --color-black: #1e222e; + --color-gold: #a1882b; + --color-white: #ffffff; + --color-diff-removed-word-bg: #6f3333; + --color-diff-added-word-bg: #3c653c; + --color-diff-removed-row-bg: #3c2626; + --color-diff-moved-row-bg: #818044; + --color-diff-added-row-bg: #283e2d; + --color-diff-removed-row-border: #634343; + --color-diff-moved-row-border: #bcca6f; + --color-diff-added-row-border: #314a37; + --color-diff-inactive: #353846; + --color-error-border: #a53a37; + --color-error-bg: #482c2c; + --color-error-text: #ff4433; + --color-success-border: #458a57; + --color-success-bg: #284034; + --color-success-text: #6cc664; + --color-warning-border: #bb9d00; + --color-warning-bg: #3a3a30; + --color-warning-text: #fbbd08; + --color-info-border: #306090; + --color-info-bg: #26354c; + --color-info-text: #38a8e8; + /* target-based colors */ + --color-body: #383c4a; + --color-box-header: #404652; + --color-box-body: #303440; + --color-text-dark: #dbe0ea; + --color-text: #bbc0ca; + --color-text-light: #a6aab5; + --color-text-light-2: #8a8e99; + --color-text-light-3: #707687; + --color-footer: #2e323e; + --color-timeline: #4c525e; + --color-input-text: #d5dbe6; + --color-input-background: #292d39; + --color-input-toggle-background: #454a57; + --color-input-border: #454a57; + --color-input-border-hover: #505667; + --color-navbar: #2a2e3a; + --color-navbar-transparent: #2a2e3a00; + --color-light: #00000028; + --color-light-mimic-enabled: rgba(0, 0, 0, calc(40 / 255 * 222 / 255 / var(--opacity-disabled))); + --color-light-border: #ffffff28; + --color-hover: #ffffff10; + --color-active: #ffffff16; + --color-menu: #2e323e; + --color-card: #2e323e; + --color-markup-table-row: #ffffff06; + --color-markup-code-block: #292d39; + --color-button: #353846; + --color-code-bg: #2a2e3a; + --color-code-sidebar-bg: #2e323e; + --color-shadow: #00000060; + --color-secondary-bg: #2a2e3a; + --color-text-focus: #fff; + --color-expand-button: #3c404d; + --color-placeholder-text: #6a737d; + --color-editor-line-highlight: var(--color-primary-light-5); + --color-project-board-bg: var(--color-secondary-light-2); + --color-caret: var(--color-text); + /* should ideally be --color-text-dark, see #15651 */ + --color-reaction-bg: #ffffff12; + --color-reaction-active-bg: var(--color-primary-alpha-40); +} +::-webkit-calendar-picker-indicator { + filter: invert(0.8); +} +.ui.horizontal.segments > .segment { + background-color: #383c4a; +} +.ui.green.progress .bar { + background-color: #668844; +} +.ui.progress.success .bar { + background-color: #7b9e57 !important; +} +.following.bar.light { + background: #2e323e; + border-color: var(--color-secondary-alpha-40); +} +.following.bar .top.menu a.item:hover { + color: #fff; +} +.feeds .list ul li.private { + background: #353945; +} +.ui.red.label, +.ui.red.labels .label { + background-color: #7d3434 !important; + border-color: #8a2121 !important; +} +.ui.yellow.label, +.ui.yellow.labels .label { + border-color: #664d02 !important; + background-color: #936e00 !important; +} +.ui.accordion .title:not(.ui) { + color: #dbdbdb; +} +.ui.green.label, +.ui.green.labels .label, +.ui.basic.green.label { + background-color: #2d693b !important; + border-color: #2d693b !important; +} +.ui.green.labels a.label:hover, +.ui.basic.green.labels a.label:hover, +a.ui.ui.ui.green.label:hover, +a.ui.basic.green.label:hover { + background-color: #3d794b !important; + border-color: #3d794b !important; + color: #fff !important; +} +.ui.divider:not(.vertical):not(.horizontal) { + border-bottom-color: var(--color-secondary); + border-top-color: transparent; +} +.form .help { + color: #7f8699; +} +.ui .text.light.grey { + color: #7f8699 !important; +} +.ui.form .fields.error .field textarea, +.ui.form .fields.error .field select, +.ui.form .fields.error .field input:not([type]), +.ui.form .fields.error .field input[type="date"], +.ui.form .fields.error .field input[type="datetime-local"], +.ui.form .fields.error .field input[type="email"], +.ui.form .fields.error .field input[type="number"], +.ui.form .fields.error .field input[type="password"], +.ui.form .fields.error .field input[type="search"], +.ui.form .fields.error .field input[type="tel"], +.ui.form .fields.error .field input[type="time"], +.ui.form .fields.error .field input[type="text"], +.ui.form .fields.error .field input[type="file"], +.ui.form .fields.error .field input[type="url"], +.ui.form .field.error textarea, +.ui.form .field.error select, +.ui.form .field.error input:not([type]), +.ui.form .field.error input[type="date"], +.ui.form .field.error input[type="datetime-local"], +.ui.form .field.error input[type="email"], +.ui.form .field.error input[type="number"], +.ui.form .field.error input[type="password"], +.ui.form .field.error input[type="search"], +.ui.form .field.error input[type="tel"], +.ui.form .field.error input[type="time"], +.ui.form .field.error input[type="text"], +.ui.form .field.error input[type="file"], +.ui.form .field.error input[type="url"] { + background-color: #522; + border: 1px solid #7d3434; + color: #f9cbcb; +} +.ui.form .field.error select:focus, +.ui.form .field.error input:not([type]):focus, +.ui.form .field.error input[type="date"]:focus, +.ui.form .field.error input[type="datetime-local"]:focus, +.ui.form .field.error input[type="email"]:focus, +.ui.form .field.error input[type="number"]:focus, +.ui.form .field.error input[type="password"]:focus, +.ui.form .field.error input[type="search"]:focus, +.ui.form .field.error input[type="tel"]:focus, +.ui.form .field.error input[type="time"]:focus, +.ui.form .field.error input[type="text"]:focus, +.ui.form .field.error input[type="file"]:focus, +.ui.form .field.error input[type="url"]:focus { + background-color: #522; + border: 1px solid #a04141; + color: #f9cbcb; +} +.ui.green.button, +.ui.green.buttons .button { + background-color: #87ab63; +} +.ui.green.button:hover, +.ui.green.buttons .button:hover { + background-color: #a0cc75; +} +.ui.search > .results { + background: #383c4a; + border-color: var(--color-secondary); +} +.ui.search > .results .result:hover, +.ui.category.search > .results .category .result:hover { + background: var(--color-secondary); +} +.ui.search > .results .result .title { + color: #dbdbdb; +} +.ui.table > thead > tr > th { + background: var(--color-secondary); + color: #dbdbdb !important; +} +.repository.file.list #repo-files-table tr { + background: #2a2e3a; +} +.repository.file.list #repo-files-table tr:hover { + background-color: #393d4a !important; +} +.overflow.menu .items .item { + color: #9d9d9d; +} +.overflow.menu .items .item:hover { + color: #dbdbdb; +} +.ui.list > .item > .content { + color: var(--color-secondary-dark-6) !important; +} +.repository .navbar .active.item, +.repository .navbar .active.item:hover { + border-color: transparent !important; +} +.repository .diff-stats li { + border-color: var(--color-secondary); +} +.tag-code, +.tag-code td { + background: #353945 !important; +} +.tag-code td.lines-num { + background-color: #3a3e4c !important; +} +.tag-code td.lines-type-marker, +td.blob-hunk { + color: #dbdbdb !important; +} +.ui.red.button, +.ui.red.buttons .button { + background-color: #7d3434; +} +.ui.red.button:hover, +.ui.red.buttons .button:hover { + background-color: #984646; +} +.ui.list .list > .item .header, +.ui.list > .item .header { + color: #dedede; +} +.ui.list .list > .item .description, +.ui.list > .item .description { + color: var(--color-secondary-dark-6); +} +.repository.labels .ui.basic.black.label { + background-color: #bbbbbb !important; +} +.lines-num { + color: var(--color-secondary-dark-6) !important; + border-color: var(--color-secondary) !important; +} +td.blob-excerpt { + background-color: rgba(0, 0, 0, 0.15); +} +.lines-code.active, +.lines-code .active { + background: #534d1b !important; +} +.ui.ui.ui.ui.table tr.active, +.ui.ui.table td.active { + color: #dbdbdb; +} +.ui.active.label { + background: #393d4a; + border-color: #393d4a; + color: #dbdbdb; +} +.ui.header .sub.header { + color: var(--color-secondary-dark-6); +} +.ui.dividing.header { + border-bottom: 1px solid var(--color-secondary); +} +.ui.modal > .header { + background: var(--color-secondary); + color: #dbdbdb; +} +.ui.modal > .actions { + background: var(--color-secondary); + border-color: var(--color-secondary); +} +.ui.modal > .content { + background: #383c4a; +} +.minicolors-panel { + background: var(--color-secondary) !important; + border-color: #6a737d !important; +} +/* invert emojis that are hard to read otherwise */ +.emoji[aria-label="check mark"], +.emoji[aria-label="currency exchange"], +.emoji[aria-label="TOP arrow"], +.emoji[aria-label="END arrow"], +.emoji[aria-label="ON! arrow"], +.emoji[aria-label="SOON arrow"], +.emoji[aria-label="heavy dollar sign"], +.emoji[aria-label="copyright"], +.emoji[aria-label="registered"], +.emoji[aria-label="trade mark"], +.emoji[aria-label="multiply"], +.emoji[aria-label="plus"], +.emoji[aria-label="minus"], +.emoji[aria-label="divide"], +.emoji[aria-label="curly loop"], +.emoji[aria-label="double curly loop"], +.emoji[aria-label="wavy dash"], +.emoji[aria-label="paw prints"], +.emoji[aria-label="musical note"], +.emoji[aria-label="musical notes"] { + filter: invert(100%) hue-rotate(180deg); +} +.edit-diff > div > .ui.table { + border-left-color: var(--color-secondary) !important; + border-right-color: var(--color-secondary) !important; +} +footer .container .links > * { + border-left-color: #888; +} +.repository.release #release-list > li .detail .dot { + background-color: #505667; + border-color: #383c4a; +} +.tribute-container { + box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.6); +} +.repository .repo-header .ui.huge.breadcrumb.repo-title .repo-header-icon .avatar { + color: #2a2e3a; +} +img[src$="/img/matrix.svg"] { + filter: invert(80%); +} +.is-loading::after { + border-color: #4a4c58 #4a4c58 #d7d7da #d7d7da; +} +.markup-block-error { + border: 1px solid rgba(121, 71, 66, 0.5) !important; + border-bottom: none !important; +} diff --git a/web_src/less/themes/theme-arc-green.less b/web_src/less/themes/theme-arc-green.less index 01150d353e311..b8550c56122c6 100644 --- a/web_src/less/themes/theme-arc-green.less +++ b/web_src/less/themes/theme-arc-green.less @@ -104,6 +104,7 @@ --color-timeline: #4c525e; --color-input-text: #d5dbe6; --color-input-background: #292d39; + --color-input-toggle-background: #454a57; --color-input-border: #454a57; --color-input-border-hover: #505667; --color-navbar: #2a2e3a; From 6fbfaf03db1e6496970332db03379a9cbd690efb Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 14 May 2022 15:39:58 +0800 Subject: [PATCH 07/25] Fix lint --- web_src/js/features/admin/config.js | 4 ++-- web_src/less/themes/theme-arc-green.css | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/web_src/js/features/admin/config.js b/web_src/js/features/admin/config.js index f4e7f9a461054..1e71e8037e909 100644 --- a/web_src/js/features/admin/config.js +++ b/web_src/js/features/admin/config.js @@ -1,11 +1,11 @@ import $ from 'jquery'; -const {appSubUrl, csrfToken} = window.config; - export function initAdminConfigs() { const isAdminConfigPage = window.config.pageData.adminConfigPage; if (!isAdminConfigPage) return; + const {appSubUrl, csrfToken} = window.config; + $("input[type='checkbox']").on('change', (e) => { const $this = $(e.currentTarget); $.ajax({ diff --git a/web_src/less/themes/theme-arc-green.css b/web_src/less/themes/theme-arc-green.css index b9f7cc9536bdd..c9cd103c3d2d4 100644 --- a/web_src/less/themes/theme-arc-green.css +++ b/web_src/less/themes/theme-arc-green.css @@ -487,7 +487,7 @@ --color-reaction-active-bg: var(--color-primary-alpha-40); } ::-webkit-calendar-picker-indicator { - filter: invert(0.8); + filter: invert(.8); } .ui.horizontal.segments > .segment { background-color: #383c4a; @@ -674,7 +674,7 @@ td.blob-hunk { border-color: var(--color-secondary) !important; } td.blob-excerpt { - background-color: rgba(0, 0, 0, 0.15); + background-color: rgba(0, 0, 0, .15); } .lines-code.active, .lines-code .active { @@ -745,7 +745,7 @@ footer .container .links > * { border-color: #383c4a; } .tribute-container { - box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.6); + box-shadow: 0 .25rem .5rem rgba(0, 0, 0, .6); } .repository .repo-header .ui.huge.breadcrumb.repo-title .repo-header-icon .avatar { color: #2a2e3a; @@ -757,6 +757,6 @@ img[src$="/img/matrix.svg"] { border-color: #4a4c58 #4a4c58 #d7d7da #d7d7da; } .markup-block-error { - border: 1px solid rgba(121, 71, 66, 0.5) !important; + border: 1px solid rgba(121, 71, 66, .5) !important; border-bottom: none !important; } From 9cdc89f7a1f2cdb483596fd0599bb88ca08cc911 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 14 May 2022 21:19:39 +0800 Subject: [PATCH 08/25] Fix wrong reference --- contrib/pr/checkout.go | 3 ++- models/avatars/avatar.go | 6 ++++-- models/unittest/testdb.go | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/contrib/pr/checkout.go b/contrib/pr/checkout.go index f6d29f3c5b574..e12f219bbf9b1 100644 --- a/contrib/pr/checkout.go +++ b/contrib/pr/checkout.go @@ -26,6 +26,7 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" + system_model "code.gitea.io/gitea/models/system" gitea_git "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup/external" @@ -61,7 +62,7 @@ func runPR() { } setting.AppWorkPath = curDir setting.StaticRootPath = curDir - setting.GravatarSourceURL, err = url.Parse("https://secure.gravatar.com/avatar/") + system_model.GravatarSourceURL, err = url.Parse("https://secure.gravatar.com/avatar/") if err != nil { log.Fatalf("url.Parse: %v\n", err) } diff --git a/models/avatars/avatar.go b/models/avatars/avatar.go index f11bb2fff3ec3..b29481fac8e7a 100644 --- a/models/avatars/avatar.go +++ b/models/avatars/avatar.go @@ -150,8 +150,10 @@ func generateEmailAvatarLink(email string, size int, final bool) string { return DefaultAvatarLink() } + enableFederatedAvatar, _ := system_model.GetSetting("enable_federated_avatar") + var err error - if setting.EnableFederatedAvatar && system_model.LibravatarService != nil { + if enableFederatedAvatar != nil && enableFederatedAvatar.GetValueBool() && system_model.LibravatarService != nil { emailHash := saveEmailHash(email) if final { // for final link, we can spend more time on slow external query @@ -169,7 +171,7 @@ func generateEmailAvatarLink(email string, size int, final bool) string { return urlStr } else { disableGravatar, _ := system_model.GetSetting("disable_gravatar") - if !disableGravatar.GetValueBool() { + if disableGravatar != nil && !disableGravatar.GetValueBool() { // copy GravatarSourceURL, because we will modify its Path. avatarURLCopy := *system_model.GravatarSourceURL avatarURLCopy.Path = path.Join(avatarURLCopy.Path, HashEmail(email)) diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go index 117614a7a4f30..3970d2b0db2f6 100644 --- a/models/unittest/testdb.go +++ b/models/unittest/testdb.go @@ -17,6 +17,7 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" "code.gitea.io/gitea/modules/util" + system_model "code.gitea.io/gita/models/system" "github.com/stretchr/testify/assert" "xorm.io/xorm" @@ -90,7 +91,7 @@ func MainTest(m *testing.M, testOpts *TestOptions) { setting.AppDataPath = appDataPath setting.AppWorkPath = testOpts.GiteaRootPath setting.StaticRootPath = testOpts.GiteaRootPath - setting.GravatarSourceURL, err = url.Parse("https://secure.gravatar.com/avatar/") + system_model.GravatarSourceURL, err = url.Parse("https://secure.gravatar.com/avatar/") if err != nil { fatalTestError("url.Parse: %v\n", err) } From b21acd7c03dcc1a159277ee090bcf8ee839e4210 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 14 May 2022 23:56:18 +0800 Subject: [PATCH 09/25] Fix build --- models/unittest/testdb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go index 3970d2b0db2f6..ef6b3295086b9 100644 --- a/models/unittest/testdb.go +++ b/models/unittest/testdb.go @@ -13,11 +13,11 @@ import ( "testing" "code.gitea.io/gitea/models/db" + system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" "code.gitea.io/gitea/modules/util" - system_model "code.gitea.io/gita/models/system" "github.com/stretchr/testify/assert" "xorm.io/xorm" From 4d56b1aeece907cb6b016045b0a7405c394a5786 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 16 May 2022 15:52:36 +0800 Subject: [PATCH 10/25] Fix import --- models/system/setting.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/system/setting.go b/models/system/setting.go index 5381b72ebb819..6aaf93a9c9b4b 100644 --- a/models/system/setting.go +++ b/models/system/setting.go @@ -15,8 +15,8 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" - "strk.kbt.io/projects/go/libravatar" + "strk.kbt.io/projects/go/libravatar" "xorm.io/builder" ) From 9cf689517bc0cdfabc374cb527015d04ab308186 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 26 May 2022 10:10:26 +0800 Subject: [PATCH 11/25] Fix test --- Makefile | 2 +- contrib/pr/checkout.go | 2 +- models/avatars/avatar.go | 17 ++++---- models/system/main_test.go | 5 ++- models/system/notice_test.go | 73 ++++++++++++++++++----------------- models/system/setting_test.go | 21 +++++----- routers/web/admin/config.go | 1 + 7 files changed, 63 insertions(+), 58 deletions(-) diff --git a/Makefile b/Makefile index fed225b166a3c..d725bd3bcb86a 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ AIR_PACKAGE ?= github.com/cosmtrek/air@v1.29.0 EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.4.0 ERRCHECK_PACKAGE ?= github.com/kisielk/errcheck@v1.6.0 GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.3.1 -GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46.0 +GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46.2 GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10 MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4 SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.29.0 diff --git a/contrib/pr/checkout.go b/contrib/pr/checkout.go index e12f219bbf9b1..b697937137a52 100644 --- a/contrib/pr/checkout.go +++ b/contrib/pr/checkout.go @@ -25,8 +25,8 @@ import ( "time" "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/unittest" system_model "code.gitea.io/gitea/models/system" + "code.gitea.io/gitea/models/unittest" gitea_git "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup/external" diff --git a/models/avatars/avatar.go b/models/avatars/avatar.go index b29481fac8e7a..24af24d47de1e 100644 --- a/models/avatars/avatar.go +++ b/models/avatars/avatar.go @@ -169,15 +169,16 @@ func generateEmailAvatarLink(email string, size int, final bool) string { urlStr += "?size=" + strconv.Itoa(size) } return urlStr - } else { - disableGravatar, _ := system_model.GetSetting("disable_gravatar") - if disableGravatar != nil && !disableGravatar.GetValueBool() { - // copy GravatarSourceURL, because we will modify its Path. - avatarURLCopy := *system_model.GravatarSourceURL - avatarURLCopy.Path = path.Join(avatarURLCopy.Path, HashEmail(email)) - return generateRecognizedAvatarURL(avatarURLCopy, size) - } } + + disableGravatar, _ := system_model.GetSetting("disable_gravatar") + if disableGravatar != nil && !disableGravatar.GetValueBool() { + // copy GravatarSourceURL, because we will modify its Path. + avatarURLCopy := *system_model.GravatarSourceURL + avatarURLCopy.Path = path.Join(avatarURLCopy.Path, HashEmail(email)) + return generateRecognizedAvatarURL(avatarURLCopy, size) + } + return DefaultAvatarLink() } diff --git a/models/system/main_test.go b/models/system/main_test.go index 031753b7c079d..a0b54c13123d1 100644 --- a/models/system/main_test.go +++ b/models/system/main_test.go @@ -2,18 +2,19 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package system +package system_test import ( "path/filepath" "testing" "code.gitea.io/gitea/models/unittest" + + _ "code.gitea.io/gitea/models/system" // register models of system ) func TestMain(m *testing.M) { unittest.MainTest(m, &unittest.TestOptions{ GiteaRootPath: filepath.Join("..", ".."), - FixtureFiles: []string{"notice.yml"}, }) } diff --git a/models/system/notice_test.go b/models/system/notice_test.go index 0564fdc0dcbdb..768bcca66cdd6 100644 --- a/models/system/notice_test.go +++ b/models/system/notice_test.go @@ -2,20 +2,21 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package system +package system_test import ( "testing" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert" ) func TestNotice_TrStr(t *testing.T) { - notice := &Notice{ - Type: NoticeRepository, + notice := &system.Notice{ + Type: system.NoticeRepository, Description: "test description", } assert.Equal(t, "admin.notices.type_1", notice.TrStr()) @@ -24,24 +25,24 @@ func TestNotice_TrStr(t *testing.T) { func TestCreateNotice(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - noticeBean := &Notice{ - Type: NoticeRepository, + noticeBean := &system.Notice{ + Type: system.NoticeRepository, Description: "test description", } unittest.AssertNotExistsBean(t, noticeBean) - assert.NoError(t, CreateNotice(db.DefaultContext, noticeBean.Type, noticeBean.Description)) + assert.NoError(t, system.CreateNotice(db.DefaultContext, noticeBean.Type, noticeBean.Description)) unittest.AssertExistsAndLoadBean(t, noticeBean) } func TestCreateRepositoryNotice(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - noticeBean := &Notice{ - Type: NoticeRepository, + noticeBean := &system.Notice{ + Type: system.NoticeRepository, Description: "test description", } unittest.AssertNotExistsBean(t, noticeBean) - assert.NoError(t, CreateRepositoryNotice(noticeBean.Description)) + assert.NoError(t, system.CreateRepositoryNotice(noticeBean.Description)) unittest.AssertExistsAndLoadBean(t, noticeBean) } @@ -49,20 +50,20 @@ func TestCreateRepositoryNotice(t *testing.T) { func TestCountNotices(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.Equal(t, int64(3), CountNotices()) + assert.Equal(t, int64(3), system.CountNotices()) } func TestNotices(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - notices, err := Notices(1, 2) + notices, err := system.Notices(1, 2) assert.NoError(t, err) if assert.Len(t, notices, 2) { assert.Equal(t, int64(3), notices[0].ID) assert.Equal(t, int64(2), notices[1].ID) } - notices, err = Notices(2, 2) + notices, err = system.Notices(2, 2) assert.NoError(t, err) if assert.Len(t, notices, 1) { assert.Equal(t, int64(1), notices[0].ID) @@ -72,45 +73,45 @@ func TestNotices(t *testing.T) { func TestDeleteNotice(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 3}) - assert.NoError(t, DeleteNotice(3)) - unittest.AssertNotExistsBean(t, &Notice{ID: 3}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 3}) + assert.NoError(t, system.DeleteNotice(3)) + unittest.AssertNotExistsBean(t, &system.Notice{ID: 3}) } func TestDeleteNotices(t *testing.T) { // delete a non-empty range assert.NoError(t, unittest.PrepareTestDatabase()) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 1}) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 2}) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 3}) - assert.NoError(t, DeleteNotices(1, 2)) - unittest.AssertNotExistsBean(t, &Notice{ID: 1}) - unittest.AssertNotExistsBean(t, &Notice{ID: 2}) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 3}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 1}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 2}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 3}) + assert.NoError(t, system.DeleteNotices(1, 2)) + unittest.AssertNotExistsBean(t, &system.Notice{ID: 1}) + unittest.AssertNotExistsBean(t, &system.Notice{ID: 2}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 3}) } func TestDeleteNotices2(t *testing.T) { // delete an empty range assert.NoError(t, unittest.PrepareTestDatabase()) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 1}) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 2}) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 3}) - assert.NoError(t, DeleteNotices(3, 2)) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 1}) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 2}) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 3}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 1}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 2}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 3}) + assert.NoError(t, system.DeleteNotices(3, 2)) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 1}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 2}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 3}) } func TestDeleteNoticesByIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 1}) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 2}) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 3}) - assert.NoError(t, DeleteNoticesByIDs([]int64{1, 3})) - unittest.AssertNotExistsBean(t, &Notice{ID: 1}) - unittest.AssertExistsAndLoadBean(t, &Notice{ID: 2}) - unittest.AssertNotExistsBean(t, &Notice{ID: 3}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 1}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 2}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 3}) + assert.NoError(t, system.DeleteNoticesByIDs([]int64{1, 3})) + unittest.AssertNotExistsBean(t, &system.Notice{ID: 1}) + unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 2}) + unittest.AssertNotExistsBean(t, &system.Notice{ID: 3}) } diff --git a/models/system/setting_test.go b/models/system/setting_test.go index ba7bb31e4aae2..017cbee52b549 100644 --- a/models/system/setting_test.go +++ b/models/system/setting_test.go @@ -2,11 +2,12 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package system +package system_test import ( "testing" + "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert" @@ -16,36 +17,36 @@ func TestSettings(t *testing.T) { keyName := "server.LFS_LOCKS_PAGING_NUM" assert.NoError(t, unittest.PrepareTestDatabase()) - newSetting := &Setting{SettingKey: keyName, SettingValue: "50"} + newSetting := &system.Setting{SettingKey: keyName, SettingValue: "50"} // create setting - err := SetSetting(newSetting) + err := system.SetSetting(newSetting) assert.NoError(t, err) // test about saving unchanged values - err = SetSetting(newSetting) + err = system.SetSetting(newSetting) assert.NoError(t, err) // get specific setting - settings, err := GetSettings([]string{keyName}) + settings, err := system.GetSettings([]string{keyName}) assert.NoError(t, err) assert.Len(t, settings, 1) assert.EqualValues(t, newSetting.SettingValue, settings[keyName].SettingValue) // updated setting - updatedSetting := &Setting{SettingKey: keyName, SettingValue: "100"} - err = SetSetting(updatedSetting) + updatedSetting := &system.Setting{SettingKey: keyName, SettingValue: "100"} + err = system.SetSetting(updatedSetting) assert.NoError(t, err) // get all settings - settings, err = GetAllSettings() + settings, err = system.GetAllSettings() assert.NoError(t, err) assert.Len(t, settings, 1) assert.EqualValues(t, updatedSetting.SettingValue, settings[updatedSetting.SettingKey].SettingValue) // delete setting - err = DeleteSetting(&Setting{SettingKey: keyName}) + err = system.DeleteSetting(&system.Setting{SettingKey: keyName}) assert.NoError(t, err) - settings, err = GetAllSettings() + settings, err = system.GetAllSettings() assert.NoError(t, err) assert.Len(t, settings, 0) } diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go index 1860362bbf7da..f47ab7f0ea555 100644 --- a/routers/web/admin/config.go +++ b/routers/web/admin/config.go @@ -21,6 +21,7 @@ import ( system_module "code.gitea.io/gitea/modules/system" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/mailer" + "gitea.com/go-chi/session" ) From 790fdae1291938ef9d3bc2144cd966d88b15aa6b Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 26 May 2022 14:19:40 +0800 Subject: [PATCH 12/25] Fix test --- models/avatars/avatar_test.go | 17 +++++++++-------- models/avatars/main_test.go | 18 ++++++++++++++++++ models/fixtures/system_setting.yml | 6 +++++- models/main_test.go | 1 + models/system/main_test.go | 1 + models/system/setting.go | 11 +++++------ models/system/setting_test.go | 13 +++++++------ 7 files changed, 46 insertions(+), 21 deletions(-) create mode 100644 models/avatars/main_test.go diff --git a/models/avatars/avatar_test.go b/models/avatars/avatar_test.go index 7c06cc9c0f4b7..69fd6cf62f7c9 100644 --- a/models/avatars/avatar_test.go +++ b/models/avatars/avatar_test.go @@ -5,7 +5,6 @@ package avatars import ( - "net/url" "testing" system_model "code.gitea.io/gitea/models/system" @@ -16,17 +15,19 @@ import ( const gravatarSource = "https://secure.gravatar.com/avatar/" -func disableGravatar() { - system_model.SetSettingNoVersion("enable_federated_avatar", "false") - system_model.SetSettingNoVersion("disable_gravatar", "true") +func disableGravatar(t *testing.T) { + err := system_model.SetSettingNoVersion("enable_federated_avatar", "false") + assert.NoError(t, err) + err = system_model.SetSettingNoVersion("disable_gravatar", "true") + assert.NoError(t, err) system_model.LibravatarService = nil } func enableGravatar(t *testing.T) { - system_model.SetSettingNoVersion("disable_gravatar", "false") - var err error - system_model.GravatarSourceURL, err = url.Parse(gravatarSource) + err := system_model.SetSettingNoVersion("disable_gravatar", "false") assert.NoError(t, err) + setting.GravatarSource = gravatarSource + system_model.Init() } func TestHashEmail(t *testing.T) { @@ -43,7 +44,7 @@ func TestHashEmail(t *testing.T) { func TestSizedAvatarLink(t *testing.T) { setting.AppSubURL = "/testsuburl" - disableGravatar() + disableGravatar(t) assert.Equal(t, "/testsuburl/assets/img/avatar_default.png", GenerateEmailAvatarFastLink("gitea@example.com", 100)) diff --git a/models/avatars/main_test.go b/models/avatars/main_test.go new file mode 100644 index 0000000000000..5af9af20fbae2 --- /dev/null +++ b/models/avatars/main_test.go @@ -0,0 +1,18 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package avatars + +import ( + "path/filepath" + "testing" + + "code.gitea.io/gitea/models/unittest" +) + +func TestMain(m *testing.M) { + unittest.MainTest(m, &unittest.TestOptions{ + GiteaRootPath: filepath.Join("..", ".."), + }) +} diff --git a/models/fixtures/system_setting.yml b/models/fixtures/system_setting.yml index b0d101e01ff6f..6c960168fcb81 100644 --- a/models/fixtures/system_setting.yml +++ b/models/fixtures/system_setting.yml @@ -3,9 +3,13 @@ setting_key: 'disable_gravatar' setting_value: 'false' version: 1 + created: 1653533198 + updated: 1653533198 - id: 2 setting_key: 'enable_federated_avatar' setting_value: 'false' - versin: 1 + version: 1 + created: 1653533198 + updated: 1653533198 diff --git a/models/main_test.go b/models/main_test.go index 96231e4704d16..83b4348e2ca13 100644 --- a/models/main_test.go +++ b/models/main_test.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" + _ "code.gitea.io/gitea/models/system" "github.com/stretchr/testify/assert" ) diff --git a/models/system/main_test.go b/models/system/main_test.go index a0b54c13123d1..a56c76aedcd2c 100644 --- a/models/system/main_test.go +++ b/models/system/main_test.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/models/unittest" + _ "code.gitea.io/gitea/models" // register models _ "code.gitea.io/gitea/models/system" // register models of system ) diff --git a/models/system/setting.go b/models/system/setting.go index 6aaf93a9c9b4b..c6b7d7fcd0452 100644 --- a/models/system/setting.go +++ b/models/system/setting.go @@ -6,7 +6,6 @@ package system import ( "context" - "errors" "fmt" "net/url" "strconv" @@ -90,6 +89,9 @@ func GetSetting(key string) (*Setting, error) { // GetSettings returns specific settings func GetSettings(keys []string) (map[string]*Setting, error) { + for i := 0; i < len(keys); i++ { + keys[i] = strings.ToLower(keys[i]) + } settings := make([]*Setting, 0, len(keys)) if err := db.GetEngine(db.DefaultContext). Where(builder.In("setting_key", keys)). @@ -143,7 +145,7 @@ func DeleteSetting(setting *Setting) error { func SetSettingNoVersion(key, value string) error { s, err := GetSetting(key) - if errors.Is(err, ErrSettingIsNotExist{}) { + if IsErrSettingIsNotExist(err) { return SetSetting(&Setting{ SettingKey: key, SettingValue: value, @@ -158,10 +160,7 @@ func SetSettingNoVersion(key, value string) error { // SetSetting updates a users' setting for a specific key func SetSetting(setting *Setting) error { - if strings.ToLower(setting.SettingKey) != setting.SettingKey { - return fmt.Errorf("setting key should be lowercase") - } - if err := upsertSettingValue(setting.SettingKey, setting.SettingValue, setting.Version); err != nil { + if err := upsertSettingValue(strings.ToLower(setting.SettingKey), setting.SettingValue, setting.Version); err != nil { return err } setting.Version++ diff --git a/models/system/setting_test.go b/models/system/setting_test.go index 017cbee52b549..d25fc05f31d1b 100644 --- a/models/system/setting_test.go +++ b/models/system/setting_test.go @@ -5,6 +5,7 @@ package system_test import ( + "strings" "testing" "code.gitea.io/gitea/models/system" @@ -30,23 +31,23 @@ func TestSettings(t *testing.T) { settings, err := system.GetSettings([]string{keyName}) assert.NoError(t, err) assert.Len(t, settings, 1) - assert.EqualValues(t, newSetting.SettingValue, settings[keyName].SettingValue) + assert.EqualValues(t, newSetting.SettingValue, settings[strings.ToLower(keyName)].SettingValue) // updated setting - updatedSetting := &system.Setting{SettingKey: keyName, SettingValue: "100"} + updatedSetting := &system.Setting{SettingKey: keyName, SettingValue: "100", Version: newSetting.Version} err = system.SetSetting(updatedSetting) assert.NoError(t, err) // get all settings settings, err = system.GetAllSettings() assert.NoError(t, err) - assert.Len(t, settings, 1) - assert.EqualValues(t, updatedSetting.SettingValue, settings[updatedSetting.SettingKey].SettingValue) + assert.Len(t, settings, 3) + assert.EqualValues(t, updatedSetting.SettingValue, settings[strings.ToLower(updatedSetting.SettingKey)].SettingValue) // delete setting - err = system.DeleteSetting(&system.Setting{SettingKey: keyName}) + err = system.DeleteSetting(&system.Setting{SettingKey: strings.ToLower(keyName)}) assert.NoError(t, err) settings, err = system.GetAllSettings() assert.NoError(t, err) - assert.Len(t, settings, 0) + assert.Len(t, settings, 2) } From d8c215cf8586e6a777354fb84e6201b318712918 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 26 May 2022 14:37:38 +0800 Subject: [PATCH 13/25] Fix fmt --- models/main_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/models/main_test.go b/models/main_test.go index 83b4348e2ca13..c339bd3bfe9e3 100644 --- a/models/main_test.go +++ b/models/main_test.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" + _ "code.gitea.io/gitea/models/system" "github.com/stretchr/testify/assert" From b968f1dc87566548a31357740589de6f618a78c3 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 26 May 2022 17:03:43 +0800 Subject: [PATCH 14/25] Fix bug --- models/repo.go | 1 + 1 file changed, 1 insertion(+) diff --git a/models/repo.go b/models/repo.go index ee2acacb7c402..fa2ba3c16b557 100644 --- a/models/repo.go +++ b/models/repo.go @@ -44,6 +44,7 @@ var ItemsPerPage = 40 // NewRepoContext creates a new repository context func NewRepoContext() { unit.LoadUnitConfig() + system_model.Init() } // CheckRepoUnitUser check whether user could visit the unit of this repository From 6927ed8a4b93a32b0385305eb34026734a16c374 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 26 May 2022 19:36:21 +0800 Subject: [PATCH 15/25] Fix bug --- models/avatars/avatar_test.go | 3 ++- models/repo.go | 6 +++--- routers/init.go | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/models/avatars/avatar_test.go b/models/avatars/avatar_test.go index 69fd6cf62f7c9..18bfe0a3c48d2 100644 --- a/models/avatars/avatar_test.go +++ b/models/avatars/avatar_test.go @@ -27,7 +27,8 @@ func enableGravatar(t *testing.T) { err := system_model.SetSettingNoVersion("disable_gravatar", "false") assert.NoError(t, err) setting.GravatarSource = gravatarSource - system_model.Init() + err = system_model.Init() + assert.NoError(t, err) } func TestHashEmail(t *testing.T) { diff --git a/models/repo.go b/models/repo.go index fa2ba3c16b557..5e085e239b922 100644 --- a/models/repo.go +++ b/models/repo.go @@ -41,10 +41,10 @@ import ( // ItemsPerPage maximum items per page in forks, watchers and stars of a repo var ItemsPerPage = 40 -// NewRepoContext creates a new repository context -func NewRepoContext() { +// Init initialize model +func Init() error { unit.LoadUnitConfig() - system_model.Init() + return system_model.Init() } // CheckRepoUnitUser check whether user could visit the unit of this repository diff --git a/routers/init.go b/routers/init.go index 6c59af1061e63..a21c847a66d19 100644 --- a/routers/init.go +++ b/routers/init.go @@ -139,7 +139,7 @@ func GlobalInitInstalled(ctx context.Context) { mustInit(system.Init) mustInit(oauth2.Init) - models.NewRepoContext() + mustInit(models.Init) mustInit(repo_service.Init) // Booting long running goroutines. From 0d40c6106dd7ad3c702085f4c601e4424fd6b901 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 26 May 2022 19:53:31 +0800 Subject: [PATCH 16/25] Use constant store setting keys --- models/avatars/avatar.go | 4 ++-- models/avatars/avatar_test.go | 6 +++--- models/migrations/v216.go | 4 ++-- models/system/setting.go | 4 ++-- models/system/setting_key.go | 11 +++++++++++ models/user/avatar.go | 2 +- modules/templates/helper.go | 3 ++- routers/install/install.go | 6 +++--- templates/admin/config.tmpl | 4 ++-- 9 files changed, 28 insertions(+), 16 deletions(-) create mode 100644 models/system/setting_key.go diff --git a/models/avatars/avatar.go b/models/avatars/avatar.go index 24af24d47de1e..418e9b9ccc6db 100644 --- a/models/avatars/avatar.go +++ b/models/avatars/avatar.go @@ -150,7 +150,7 @@ func generateEmailAvatarLink(email string, size int, final bool) string { return DefaultAvatarLink() } - enableFederatedAvatar, _ := system_model.GetSetting("enable_federated_avatar") + enableFederatedAvatar, _ := system_model.GetSetting(system_model.KeyPictureEnableFederatedAvatar) var err error if enableFederatedAvatar != nil && enableFederatedAvatar.GetValueBool() && system_model.LibravatarService != nil { @@ -171,7 +171,7 @@ func generateEmailAvatarLink(email string, size int, final bool) string { return urlStr } - disableGravatar, _ := system_model.GetSetting("disable_gravatar") + disableGravatar, _ := system_model.GetSetting(system_model.KeyPictureDisableGravatar) if disableGravatar != nil && !disableGravatar.GetValueBool() { // copy GravatarSourceURL, because we will modify its Path. avatarURLCopy := *system_model.GravatarSourceURL diff --git a/models/avatars/avatar_test.go b/models/avatars/avatar_test.go index 18bfe0a3c48d2..a305e511c0f78 100644 --- a/models/avatars/avatar_test.go +++ b/models/avatars/avatar_test.go @@ -16,15 +16,15 @@ import ( const gravatarSource = "https://secure.gravatar.com/avatar/" func disableGravatar(t *testing.T) { - err := system_model.SetSettingNoVersion("enable_federated_avatar", "false") + err := system_model.SetSettingNoVersion(system_model.KeyPictureEnableFederatedAvatar, "false") assert.NoError(t, err) - err = system_model.SetSettingNoVersion("disable_gravatar", "true") + err = system_model.SetSettingNoVersion(system_model.KeyPictureDisableGravatar, "true") assert.NoError(t, err) system_model.LibravatarService = nil } func enableGravatar(t *testing.T) { - err := system_model.SetSettingNoVersion("disable_gravatar", "false") + err := system_model.SetSettingNoVersion(system_model.KeyPictureDisableGravatar, "false") assert.NoError(t, err) setting.GravatarSource = gravatarSource err = system_model.Init() diff --git a/models/migrations/v216.go b/models/migrations/v216.go index 284ccda172321..ec3133231d8bd 100644 --- a/models/migrations/v216.go +++ b/models/migrations/v216.go @@ -51,11 +51,11 @@ func createSystemSettingsTable(x *xorm.Engine) error { // migrate xx to database sysSettings := []*SystemSetting{ { - SettingKey: "disable_gravatar", + SettingKey: "picture.disable_gravatar", SettingValue: strconv.FormatBool(setting.DisableGravatar), }, { - SettingKey: "enable_federated_avatar", + SettingKey: "picture.enable_federated_avatar", SettingValue: strconv.FormatBool(setting.EnableFederatedAvatar), }, } diff --git a/models/system/setting.go b/models/system/setting.go index c6b7d7fcd0452..a3000f8f1f286 100644 --- a/models/system/setting.go +++ b/models/system/setting.go @@ -213,7 +213,7 @@ var ( func Init() error { var disableGravatar bool - disableGravatarSetting, err := GetSetting("disable_gravatar") + disableGravatarSetting, err := GetSetting(KeyPictureDisableGravatar) if IsErrSettingIsNotExist(err) { disableGravatar = setting.GetDefaultDisableGravatar() disableGravatarSetting = &Setting{SettingValue: strconv.FormatBool(disableGravatar)} @@ -223,7 +223,7 @@ func Init() error { disableGravatar = disableGravatarSetting.GetValueBool() } - enableFederatedAvatarSetting, err := GetSetting("enable_federated_avatar") + enableFederatedAvatarSetting, err := GetSetting(KeyPictureEnableFederatedAvatar) if IsErrSettingIsNotExist(err) { enableFederatedAvatarSetting = &Setting{SettingValue: strconv.FormatBool(setting.GetDefaultEnableFederatedAvatar(disableGravatar))} } diff --git a/models/system/setting_key.go b/models/system/setting_key.go new file mode 100644 index 0000000000000..5a6ea6ed722fd --- /dev/null +++ b/models/system/setting_key.go @@ -0,0 +1,11 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package system + +// enumerate all system setting keys +const ( + KeyPictureDisableGravatar = "picture.disable_gravatar" + KeyPictureEnableFederatedAvatar = "picture.enable_federated_avatar" +) diff --git a/models/user/avatar.go b/models/user/avatar.go index af569950dff60..1c75c7406bd3a 100644 --- a/models/user/avatar.go +++ b/models/user/avatar.go @@ -69,7 +69,7 @@ func (u *User) AvatarLinkWithSize(size int) string { autoGenerateAvatar := false var disableGravatar bool - disableGravatarSetting, _ := system_model.GetSetting("disable_gravatar") + disableGravatarSetting, _ := system_model.GetSetting(system_model.KeyPictureDisableGravatar) if disableGravatarSetting != nil { disableGravatar = disableGravatarSetting.GetValueBool() } diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 2efc4c89e9df9..0dc7a5f2f8b63 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -27,6 +27,7 @@ import ( "code.gitea.io/gitea/models/avatars" "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" + system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/emoji" @@ -80,7 +81,7 @@ func NewFuncMap() []template.FuncMap { return setting.Domain }, "DisableGravatar": func() bool { - return system_module.GetSetingBool("disable_gravatar") + return system_module.GetSetingBool(system_model.KeyPictureDisableGravatar) }, "DefaultShowFullName": func() bool { return setting.UI.DefaultShowFullName diff --git a/routers/install/install.go b/routers/install/install.go index b01f4199eb859..abb41e37039cf 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -145,14 +145,14 @@ func Install(ctx *context.Context) { // Server and other services settings form.OfflineMode = setting.OfflineMode - disableGravatarSetting, _ := system_model.GetSetting("disable_gravatar") + disableGravatarSetting, _ := system_model.GetSetting(system_model.KeyPictureDisableGravatar) if disableGravatarSetting != nil { form.DisableGravatar = disableGravatarSetting.GetValueBool() } else { form.DisableGravatar = false } - enableFederatedAvatarSetting, _ := system_model.GetSetting("enable_federated_avatar") + enableFederatedAvatarSetting, _ := system_model.GetSetting("") if enableFederatedAvatarSetting != nil { form.EnableFederatedAvatar = enableFederatedAvatarSetting.GetValueBool() } else { @@ -448,7 +448,7 @@ func SubmitInstall(ctx *context.Context) { cfg.Section("server").Key("OFFLINE_MODE").SetValue(fmt.Sprint(form.OfflineMode)) // if you are reinstalling, this maybe not right because of missing version - if err := system_model.SetSettingNoVersion("disable_gravatar", strconv.FormatBool(form.DisableGravatar)); err != nil { + if err := system_model.SetSettingNoVersion(system_model.KeyPictureDisableGravatar, strconv.FormatBool(form.DisableGravatar)); err != nil { ctx.RenderWithErr(ctx.Tr("install.secret_key_failed", err), tplInstall, &form) return } diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index 4e787142657fe..a0ed432303ec0 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -296,14 +296,14 @@
{{.i18n.Tr "admin.config.disable_gravatar"}}
- +
{{.i18n.Tr "admin.config.enable_federated_avatar"}}
- +
From ddcac804d6e7d06b9a606a17118cc46c15e92d5f Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 27 May 2022 00:39:20 +0800 Subject: [PATCH 17/25] Fix test --- Makefile | 2 +- contrib/pr/checkout.go | 8 +------- models/system/setting.go | 16 ++++++++++++---- models/unittest/testdb.go | 10 +++++----- modules/repository/commits_test.go | 12 ++++++++++++ modules/setting/picture.go | 2 +- modules/system/setting.go | 2 +- modules/templates/helper.go | 2 +- 8 files changed, 34 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index d725bd3bcb86a..fed225b166a3c 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ AIR_PACKAGE ?= github.com/cosmtrek/air@v1.29.0 EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.4.0 ERRCHECK_PACKAGE ?= github.com/kisielk/errcheck@v1.6.0 GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.3.1 -GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46.2 +GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46.0 GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10 MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4 SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.29.0 diff --git a/contrib/pr/checkout.go b/contrib/pr/checkout.go index b697937137a52..deb28b0d217d2 100644 --- a/contrib/pr/checkout.go +++ b/contrib/pr/checkout.go @@ -14,7 +14,6 @@ import ( "fmt" "log" "net/http" - "net/url" "os" "os/exec" "os/user" @@ -25,7 +24,6 @@ import ( "time" "code.gitea.io/gitea/models/db" - system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unittest" gitea_git "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/markup" @@ -62,11 +60,7 @@ func runPR() { } setting.AppWorkPath = curDir setting.StaticRootPath = curDir - system_model.GravatarSourceURL, err = url.Parse("https://secure.gravatar.com/avatar/") - if err != nil { - log.Fatalf("url.Parse: %v\n", err) - } - + setting.GravatarSource = "https://secure.gravatar.com/avatar/" setting.AppURL = "http://localhost:8080/" setting.HTTPPort = "8080" setting.SSH.Domain = "localhost" diff --git a/models/system/setting.go b/models/system/setting.go index a3000f8f1f286..ff8b48e61801b 100644 --- a/models/system/setting.go +++ b/models/system/setting.go @@ -223,15 +223,23 @@ func Init() error { disableGravatar = disableGravatarSetting.GetValueBool() } + var enableFederatedAvatar bool enableFederatedAvatarSetting, err := GetSetting(KeyPictureEnableFederatedAvatar) if IsErrSettingIsNotExist(err) { - enableFederatedAvatarSetting = &Setting{SettingValue: strconv.FormatBool(setting.GetDefaultEnableFederatedAvatar(disableGravatar))} - } - if err != nil { + enableFederatedAvatar = setting.GetDefaultEnableFederatedAvatar(disableGravatar) + enableFederatedAvatarSetting = &Setting{SettingValue: strconv.FormatBool(enableFederatedAvatar)} + } else if err != nil { return err + } else { + enableFederatedAvatar = disableGravatarSetting.GetValueBool() + } + + if setting.OfflineMode { + disableGravatar = true + enableFederatedAvatar = false } - if enableFederatedAvatarSetting.GetValueBool() || !disableGravatarSetting.GetValueBool() { + if disableGravatar || !enableFederatedAvatar { var err error GravatarSourceURL, err = url.Parse(setting.GravatarSource) if err != nil { diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go index ef6b3295086b9..f8b1fd8732920 100644 --- a/models/unittest/testdb.go +++ b/models/unittest/testdb.go @@ -7,7 +7,6 @@ package unittest import ( "context" "fmt" - "net/url" "os" "path/filepath" "testing" @@ -91,10 +90,8 @@ func MainTest(m *testing.M, testOpts *TestOptions) { setting.AppDataPath = appDataPath setting.AppWorkPath = testOpts.GiteaRootPath setting.StaticRootPath = testOpts.GiteaRootPath - system_model.GravatarSourceURL, err = url.Parse("https://secure.gravatar.com/avatar/") - if err != nil { - fatalTestError("url.Parse: %v\n", err) - } + setting.GravatarSource = "https://secure.gravatar.com/avatar/" + setting.Attachment.Storage.Path = filepath.Join(setting.AppDataPath, "attachments") setting.LFS.Storage.Path = filepath.Join(setting.AppDataPath, "lfs") @@ -110,6 +107,9 @@ func MainTest(m *testing.M, testOpts *TestOptions) { if err = storage.Init(); err != nil { fatalTestError("storage.Init: %v\n", err) } + if err = system_model.Init(); err != nil { + fatalTestError("models.Init: %v\n", err) + } if err = util.RemoveAll(repoRootPath); err != nil { fatalTestError("util.RemoveAll: %v\n", err) diff --git a/modules/repository/commits_test.go b/modules/repository/commits_test.go index 37181d2dcd0d0..8c1d1b8a17d92 100644 --- a/modules/repository/commits_test.go +++ b/modules/repository/commits_test.go @@ -11,8 +11,10 @@ import ( "time" repo_model "code.gitea.io/gitea/models/repo" + system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/setting" "github.com/stretchr/testify/assert" ) @@ -100,6 +102,14 @@ func TestPushCommits_ToAPIPayloadCommits(t *testing.T) { assert.EqualValues(t, []string{"readme.md"}, headCommit.Modified) } +func enableGravatar(t *testing.T) { + err := system_model.SetSettingNoVersion(system_model.KeyPictureDisableGravatar, "false") + assert.NoError(t, err) + setting.GravatarSource = "https://secure.gravatar.com/avatar" + err = system_model.Init() + assert.NoError(t, err) +} + func TestPushCommits_AvatarLink(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) @@ -123,6 +133,8 @@ func TestPushCommits_AvatarLink(t *testing.T) { }, } + enableGravatar(t) + assert.Equal(t, "https://secure.gravatar.com/avatar/ab53a2911ddf9b4817ac01ddcd3d975f?d=identicon&s=84", pushCommits.AvatarLink("user2@example.com")) diff --git a/modules/setting/picture.go b/modules/setting/picture.go index ea3b890bcf128..af9041ade3673 100644 --- a/modules/setting/picture.go +++ b/modules/setting/picture.go @@ -21,9 +21,9 @@ var ( RenderedSizeFactor: 3, } + GravatarSource string DisableGravatar bool // Depreciated: migrated to database EnableFederatedAvatar bool // Depreciated: migrated to database - GravatarSource string RepoAvatar = struct { Storage diff --git a/modules/system/setting.go b/modules/system/setting.go index afeb5834e4127..2454193b04776 100644 --- a/modules/system/setting.go +++ b/modules/system/setting.go @@ -26,7 +26,7 @@ func GetSetting(key string) (string, error) { }) } -func GetSetingBool(key string) bool { +func GetSettingBool(key string) bool { s, _ := GetSetting(key) b, _ := strconv.ParseBool(s) return b diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 0dc7a5f2f8b63..3700ec330e77b 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -81,7 +81,7 @@ func NewFuncMap() []template.FuncMap { return setting.Domain }, "DisableGravatar": func() bool { - return system_module.GetSetingBool(system_model.KeyPictureDisableGravatar) + return system_module.GetSettingBool(system_model.KeyPictureDisableGravatar) }, "DefaultShowFullName": func() bool { return setting.UI.DefaultShowFullName From 9d7f2f8fda4755d279f5a021f001514fc4a4c1b7 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 1 Jun 2022 15:10:26 +0800 Subject: [PATCH 18/25] Fix wrong file --- web_src/less/themes/theme-arc-green.css | 762 ------------------------ 1 file changed, 762 deletions(-) delete mode 100644 web_src/less/themes/theme-arc-green.css diff --git a/web_src/less/themes/theme-arc-green.css b/web_src/less/themes/theme-arc-green.css deleted file mode 100644 index c9cd103c3d2d4..0000000000000 --- a/web_src/less/themes/theme-arc-green.css +++ /dev/null @@ -1,762 +0,0 @@ -.chroma .hl { - background-color: #3f424d; -} -/* LineHighlight */ -.chroma .lnt { - color: #7f7f7f; -} -/* LineNumbersTable */ -.chroma .ln { - color: #7f7f7f; -} -/* LineNumbers */ -.chroma .k { - color: #f63; -} -/* Keyword */ -.chroma .kc { - color: #fa1; -} -/* KeywordConstant */ -.chroma .kd { - color: #9daccc; -} -/* KeywordDeclaration */ -.chroma .kn { - color: #fa1; -} -/* KeywordNamespace */ -.chroma .kp { - color: #5f8700; -} -/* KeywordPseudo */ -.chroma .kr { - color: #f63; -} -/* KeywordReserved */ -.chroma .kt { - color: #9daccc; -} -/* KeywordType */ -.chroma .na { - color: #8a8a8a; -} -/* NameAttribute */ -.chroma .nb { - color: #9daccc; -} -/* NameBuiltin */ -.chroma .bp { - color: #9daccc; -} -/* NameBuiltinPseudo */ -.chroma .nc { - color: #fa1; -} -/* NameClass */ -.chroma .no { - color: #fa1; -} -/* NameConstant */ -.chroma .nd { - color: #9daccc; -} -/* NameDecorator */ -.chroma .ni { - color: #fa1; -} -/* NameEntity */ -.chroma .ne { - color: #af8700; -} -/* NameException */ -.chroma .nf { - color: #9daccc; -} -/* NameFunction */ -.chroma .nl { - color: #fa1; -} -/* NameLabel */ -.chroma .nn { - color: #fa1; -} -/* NameNamespace */ -.chroma .nx { - color: #9daccc; -} -/* NameOther */ -.chroma .nt { - color: #9daccc; -} -/* NameTag */ -.chroma .nv { - color: #9daccc; -} -/* NameVariable */ -.chroma .vc { - color: #f81; -} -/* NameVariableClass */ -.chroma .vg { - color: #fa1; -} -/* NameVariableGlobal */ -.chroma .vi { - color: #fa1; -} -/* NameVariableInstance */ -.chroma .s { - color: #1af; -} -/* LiteralString */ -.chroma .sa { - color: #1af; -} -/* LiteralStringAffix */ -.chroma .sb { - color: #a0cc75; -} -/* LiteralStringBacktick */ -.chroma .sc { - color: #1af; -} -/* LiteralStringChar */ -.chroma .dl { - color: #1af; -} -/* LiteralStringDelimiter */ -.chroma .sd { - color: #6a737d; -} -/* LiteralStringDoc */ -.chroma .s2 { - color: #a0cc75; -} -/* LiteralStringDouble */ -.chroma .se { - color: #f63; -} -/* LiteralStringEscape */ -.chroma .sh { - color: #1af; -} -/* LiteralStringHeredoc */ -.chroma .si { - color: #fa1; -} -/* LiteralStringInterpol */ -.chroma .sx { - color: #fa1; -} -/* LiteralStringOther */ -.chroma .sr { - color: #97c; -} -/* LiteralStringRegex */ -.chroma .s1 { - color: #a0cc75; -} -/* LiteralStringSingle */ -.chroma .ss { - color: #fa1; -} -/* LiteralStringSymbol */ -.chroma .m { - color: #1af; -} -/* LiteralNumber */ -.chroma .mb { - color: #1af; -} -/* LiteralNumberBin */ -.chroma .mf { - color: #1af; -} -/* LiteralNumberFloat */ -.chroma .mh { - color: #1af; -} -/* LiteralNumberHex */ -.chroma .mi { - color: #1af; -} -/* LiteralNumberInteger */ -.chroma .il { - color: #1af; -} -/* LiteralNumberIntegerLong */ -.chroma .mo { - color: #1af; -} -/* LiteralNumberOct */ -.chroma .o { - color: #f63; -} -/* Operator */ -.chroma .ow { - color: #5f8700; -} -/* OperatorWord */ -.chroma .c { - color: #6a737d; -} -/* Comment */ -.chroma .ch { - color: #6a737d; -} -/* CommentHashbang */ -.chroma .cm { - color: #6a737d; -} -/* CommentMultiline */ -.chroma .c1 { - color: #6a737d; -} -/* CommentSingle */ -.chroma .cs { - color: #95ad; -} -/* CommentSpecial */ -.chroma .cp { - color: #fc6; -} -/* CommentPreproc */ -.chroma .cpf { - color: #03dfff; -} -/* CommentPreprocFile */ -.chroma .gd { - color: #fff; - background-color: #5f3737; -} -/* GenericDeleted */ -.chroma .ge { - color: #ef5; -} -/* GenericEmph */ -.chroma .gr { - color: #f33; -} -/* GenericError */ -.chroma .gh { - color: #fa1; -} -/* GenericHeading */ -.chroma .gi { - color: #fff; - background-color: #3a523a; -} -/* GenericInserted */ -.chroma .go { - color: #888888; -} -/* GenericOutput */ -.chroma .gp { - color: #555555; -} -/* GenericPrompt */ -.chroma .gu { - color: #9daccc; -} -/* GenericSubheading */ -.chroma .gt { - color: #f63; -} -/* GenericTraceback */ -.chroma .w { - color: #bbbbbb; -} -/* TextWhitespace */ -.CodeMirror.cm-s-default .cm-property, -.CodeMirror.cm-s-paper .cm-property { - color: #a0cc75; -} -.CodeMirror.cm-s-default .cm-header, -.CodeMirror.cm-s-paper .cm-header { - color: #9daccc; -} -.CodeMirror.cm-s-default .cm-quote, -.CodeMirror.cm-s-paper .cm-quote { - color: #009900; -} -.CodeMirror.cm-s-default .cm-keyword, -.CodeMirror.cm-s-paper .cm-keyword { - color: #cc8a61; -} -.CodeMirror.cm-s-default .cm-atom, -.CodeMirror.cm-s-paper .cm-atom { - color: #ef5e77; -} -.CodeMirror.cm-s-default .cm-number, -.CodeMirror.cm-s-paper .cm-number { - color: #ff5656; -} -.CodeMirror.cm-s-default .cm-def, -.CodeMirror.cm-s-paper .cm-def { - color: #e4e4e4; -} -.CodeMirror.cm-s-default .cm-variable-2, -.CodeMirror.cm-s-paper .cm-variable-2 { - color: #00bdbf; -} -.CodeMirror.cm-s-default .cm-variable-3, -.CodeMirror.cm-s-paper .cm-variable-3 { - color: #008855; -} -.CodeMirror.cm-s-default .cm-comment, -.CodeMirror.cm-s-paper .cm-comment { - color: #8e9ab3; -} -.CodeMirror.cm-s-default .cm-string, -.CodeMirror.cm-s-paper .cm-string { - color: #a77272; -} -.CodeMirror.cm-s-default .cm-string-2, -.CodeMirror.cm-s-paper .cm-string-2 { - color: #ff5500; -} -.CodeMirror.cm-s-default .cm-meta, -.CodeMirror.cm-s-paper .cm-meta, -.CodeMirror.cm-s-default .cm-qualifier, -.CodeMirror.cm-s-paper .cm-qualifier { - color: #ffb176; -} -.CodeMirror.cm-s-default .cm-builtin, -.CodeMirror.cm-s-paper .cm-builtin { - color: #b7c951; -} -.CodeMirror.cm-s-default .cm-bracket, -.CodeMirror.cm-s-paper .cm-bracket { - color: #999977; -} -.CodeMirror.cm-s-default .cm-tag, -.CodeMirror.cm-s-paper .cm-tag { - color: #f1d273; -} -.CodeMirror.cm-s-default .cm-attribute, -.CodeMirror.cm-s-paper .cm-attribute { - color: #bfcc70; -} -.CodeMirror.cm-s-default .cm-hr, -.CodeMirror.cm-s-paper .cm-hr { - color: #999999; -} -.CodeMirror.cm-s-default .cm-url, -.CodeMirror.cm-s-paper .cm-url { - color: #c5cfd0; -} -.CodeMirror.cm-s-default .cm-link, -.CodeMirror.cm-s-paper .cm-link { - color: #d8c792; -} -.CodeMirror.cm-s-default .cm-error, -.CodeMirror.cm-s-paper .cm-error { - color: #dbdbeb; -} -:root { - --is-dark-theme: true; - --color-primary: #87ab63; - --color-primary-dark-1: #93b373; - --color-primary-dark-2: #9fbc82; - --color-primary-dark-3: #abc492; - --color-primary-dark-4: #b7cda1; - --color-primary-dark-5: #cfddc1; - --color-primary-dark-6: #e7eee0; - --color-primary-dark-7: #f8faf6; - --color-primary-light-1: #7a9e55; - --color-primary-light-2: #6c8c4c; - --color-primary-light-3: #5f7b42; - --color-primary-light-4: #516939; - --color-primary-light-5: #364626; - --color-primary-light-6: #1b2313; - --color-primary-light-7: #080b06; - --color-primary-alpha-10: #87ab6319; - --color-primary-alpha-20: #87ab6333; - --color-primary-alpha-30: #87ab634b; - --color-primary-alpha-40: #87ab6366; - --color-primary-alpha-50: #87ab6380; - --color-primary-alpha-60: #87ab6399; - --color-primary-alpha-70: #87ab63b3; - --color-primary-alpha-80: #87ab63cc; - --color-primary-alpha-90: #87ab63e1; - --color-secondary: #454a57; - --color-secondary-dark-1: #505665; - --color-secondary-dark-2: #5b6273; - --color-secondary-dark-3: #71798e; - --color-secondary-dark-4: #7f8699; - --color-secondary-dark-5: #8c93a4; - --color-secondary-dark-6: #9aa0af; - --color-secondary-dark-7: #a8adba; - --color-secondary-dark-8: #b6bac5; - --color-secondary-dark-9: #c4c7d0; - --color-secondary-dark-10: #d2d4db; - --color-secondary-dark-11: #dfe1e6; - --color-secondary-dark-12: #edeef1; - --color-secondary-dark-13: #fbfbfc; - --color-secondary-light-1: #373b46; - --color-secondary-light-2: #292c34; - --color-secondary-light-3: #1c1e23; - --color-secondary-light-4: #0e0f11; - --color-secondary-alpha-10: #454a5719; - --color-secondary-alpha-20: #454a5733; - --color-secondary-alpha-30: #454a574b; - --color-secondary-alpha-40: #454a5766; - --color-secondary-alpha-50: #454a5780; - --color-secondary-alpha-60: #454a5799; - --color-secondary-alpha-70: #454a57b3; - --color-secondary-alpha-80: #454a57cc; - --color-secondary-alpha-90: #454a57e1; - /* colors */ - --color-red: #db2828; - --color-orange: #f2711c; - --color-yellow: #fbbd08; - --color-olive: #b5cc18; - --color-green: #21ba45; - --color-teal: #00b5ad; - --color-blue: #2185d0; - --color-violet: #6435c9; - --color-purple: #a333c8; - --color-pink: #e03997; - --color-brown: #a5673f; - --color-grey: #767a85; - --color-black: #1e222e; - --color-gold: #a1882b; - --color-white: #ffffff; - --color-diff-removed-word-bg: #6f3333; - --color-diff-added-word-bg: #3c653c; - --color-diff-removed-row-bg: #3c2626; - --color-diff-moved-row-bg: #818044; - --color-diff-added-row-bg: #283e2d; - --color-diff-removed-row-border: #634343; - --color-diff-moved-row-border: #bcca6f; - --color-diff-added-row-border: #314a37; - --color-diff-inactive: #353846; - --color-error-border: #a53a37; - --color-error-bg: #482c2c; - --color-error-text: #ff4433; - --color-success-border: #458a57; - --color-success-bg: #284034; - --color-success-text: #6cc664; - --color-warning-border: #bb9d00; - --color-warning-bg: #3a3a30; - --color-warning-text: #fbbd08; - --color-info-border: #306090; - --color-info-bg: #26354c; - --color-info-text: #38a8e8; - /* target-based colors */ - --color-body: #383c4a; - --color-box-header: #404652; - --color-box-body: #303440; - --color-text-dark: #dbe0ea; - --color-text: #bbc0ca; - --color-text-light: #a6aab5; - --color-text-light-2: #8a8e99; - --color-text-light-3: #707687; - --color-footer: #2e323e; - --color-timeline: #4c525e; - --color-input-text: #d5dbe6; - --color-input-background: #292d39; - --color-input-toggle-background: #454a57; - --color-input-border: #454a57; - --color-input-border-hover: #505667; - --color-navbar: #2a2e3a; - --color-navbar-transparent: #2a2e3a00; - --color-light: #00000028; - --color-light-mimic-enabled: rgba(0, 0, 0, calc(40 / 255 * 222 / 255 / var(--opacity-disabled))); - --color-light-border: #ffffff28; - --color-hover: #ffffff10; - --color-active: #ffffff16; - --color-menu: #2e323e; - --color-card: #2e323e; - --color-markup-table-row: #ffffff06; - --color-markup-code-block: #292d39; - --color-button: #353846; - --color-code-bg: #2a2e3a; - --color-code-sidebar-bg: #2e323e; - --color-shadow: #00000060; - --color-secondary-bg: #2a2e3a; - --color-text-focus: #fff; - --color-expand-button: #3c404d; - --color-placeholder-text: #6a737d; - --color-editor-line-highlight: var(--color-primary-light-5); - --color-project-board-bg: var(--color-secondary-light-2); - --color-caret: var(--color-text); - /* should ideally be --color-text-dark, see #15651 */ - --color-reaction-bg: #ffffff12; - --color-reaction-active-bg: var(--color-primary-alpha-40); -} -::-webkit-calendar-picker-indicator { - filter: invert(.8); -} -.ui.horizontal.segments > .segment { - background-color: #383c4a; -} -.ui.green.progress .bar { - background-color: #668844; -} -.ui.progress.success .bar { - background-color: #7b9e57 !important; -} -.following.bar.light { - background: #2e323e; - border-color: var(--color-secondary-alpha-40); -} -.following.bar .top.menu a.item:hover { - color: #fff; -} -.feeds .list ul li.private { - background: #353945; -} -.ui.red.label, -.ui.red.labels .label { - background-color: #7d3434 !important; - border-color: #8a2121 !important; -} -.ui.yellow.label, -.ui.yellow.labels .label { - border-color: #664d02 !important; - background-color: #936e00 !important; -} -.ui.accordion .title:not(.ui) { - color: #dbdbdb; -} -.ui.green.label, -.ui.green.labels .label, -.ui.basic.green.label { - background-color: #2d693b !important; - border-color: #2d693b !important; -} -.ui.green.labels a.label:hover, -.ui.basic.green.labels a.label:hover, -a.ui.ui.ui.green.label:hover, -a.ui.basic.green.label:hover { - background-color: #3d794b !important; - border-color: #3d794b !important; - color: #fff !important; -} -.ui.divider:not(.vertical):not(.horizontal) { - border-bottom-color: var(--color-secondary); - border-top-color: transparent; -} -.form .help { - color: #7f8699; -} -.ui .text.light.grey { - color: #7f8699 !important; -} -.ui.form .fields.error .field textarea, -.ui.form .fields.error .field select, -.ui.form .fields.error .field input:not([type]), -.ui.form .fields.error .field input[type="date"], -.ui.form .fields.error .field input[type="datetime-local"], -.ui.form .fields.error .field input[type="email"], -.ui.form .fields.error .field input[type="number"], -.ui.form .fields.error .field input[type="password"], -.ui.form .fields.error .field input[type="search"], -.ui.form .fields.error .field input[type="tel"], -.ui.form .fields.error .field input[type="time"], -.ui.form .fields.error .field input[type="text"], -.ui.form .fields.error .field input[type="file"], -.ui.form .fields.error .field input[type="url"], -.ui.form .field.error textarea, -.ui.form .field.error select, -.ui.form .field.error input:not([type]), -.ui.form .field.error input[type="date"], -.ui.form .field.error input[type="datetime-local"], -.ui.form .field.error input[type="email"], -.ui.form .field.error input[type="number"], -.ui.form .field.error input[type="password"], -.ui.form .field.error input[type="search"], -.ui.form .field.error input[type="tel"], -.ui.form .field.error input[type="time"], -.ui.form .field.error input[type="text"], -.ui.form .field.error input[type="file"], -.ui.form .field.error input[type="url"] { - background-color: #522; - border: 1px solid #7d3434; - color: #f9cbcb; -} -.ui.form .field.error select:focus, -.ui.form .field.error input:not([type]):focus, -.ui.form .field.error input[type="date"]:focus, -.ui.form .field.error input[type="datetime-local"]:focus, -.ui.form .field.error input[type="email"]:focus, -.ui.form .field.error input[type="number"]:focus, -.ui.form .field.error input[type="password"]:focus, -.ui.form .field.error input[type="search"]:focus, -.ui.form .field.error input[type="tel"]:focus, -.ui.form .field.error input[type="time"]:focus, -.ui.form .field.error input[type="text"]:focus, -.ui.form .field.error input[type="file"]:focus, -.ui.form .field.error input[type="url"]:focus { - background-color: #522; - border: 1px solid #a04141; - color: #f9cbcb; -} -.ui.green.button, -.ui.green.buttons .button { - background-color: #87ab63; -} -.ui.green.button:hover, -.ui.green.buttons .button:hover { - background-color: #a0cc75; -} -.ui.search > .results { - background: #383c4a; - border-color: var(--color-secondary); -} -.ui.search > .results .result:hover, -.ui.category.search > .results .category .result:hover { - background: var(--color-secondary); -} -.ui.search > .results .result .title { - color: #dbdbdb; -} -.ui.table > thead > tr > th { - background: var(--color-secondary); - color: #dbdbdb !important; -} -.repository.file.list #repo-files-table tr { - background: #2a2e3a; -} -.repository.file.list #repo-files-table tr:hover { - background-color: #393d4a !important; -} -.overflow.menu .items .item { - color: #9d9d9d; -} -.overflow.menu .items .item:hover { - color: #dbdbdb; -} -.ui.list > .item > .content { - color: var(--color-secondary-dark-6) !important; -} -.repository .navbar .active.item, -.repository .navbar .active.item:hover { - border-color: transparent !important; -} -.repository .diff-stats li { - border-color: var(--color-secondary); -} -.tag-code, -.tag-code td { - background: #353945 !important; -} -.tag-code td.lines-num { - background-color: #3a3e4c !important; -} -.tag-code td.lines-type-marker, -td.blob-hunk { - color: #dbdbdb !important; -} -.ui.red.button, -.ui.red.buttons .button { - background-color: #7d3434; -} -.ui.red.button:hover, -.ui.red.buttons .button:hover { - background-color: #984646; -} -.ui.list .list > .item .header, -.ui.list > .item .header { - color: #dedede; -} -.ui.list .list > .item .description, -.ui.list > .item .description { - color: var(--color-secondary-dark-6); -} -.repository.labels .ui.basic.black.label { - background-color: #bbbbbb !important; -} -.lines-num { - color: var(--color-secondary-dark-6) !important; - border-color: var(--color-secondary) !important; -} -td.blob-excerpt { - background-color: rgba(0, 0, 0, .15); -} -.lines-code.active, -.lines-code .active { - background: #534d1b !important; -} -.ui.ui.ui.ui.table tr.active, -.ui.ui.table td.active { - color: #dbdbdb; -} -.ui.active.label { - background: #393d4a; - border-color: #393d4a; - color: #dbdbdb; -} -.ui.header .sub.header { - color: var(--color-secondary-dark-6); -} -.ui.dividing.header { - border-bottom: 1px solid var(--color-secondary); -} -.ui.modal > .header { - background: var(--color-secondary); - color: #dbdbdb; -} -.ui.modal > .actions { - background: var(--color-secondary); - border-color: var(--color-secondary); -} -.ui.modal > .content { - background: #383c4a; -} -.minicolors-panel { - background: var(--color-secondary) !important; - border-color: #6a737d !important; -} -/* invert emojis that are hard to read otherwise */ -.emoji[aria-label="check mark"], -.emoji[aria-label="currency exchange"], -.emoji[aria-label="TOP arrow"], -.emoji[aria-label="END arrow"], -.emoji[aria-label="ON! arrow"], -.emoji[aria-label="SOON arrow"], -.emoji[aria-label="heavy dollar sign"], -.emoji[aria-label="copyright"], -.emoji[aria-label="registered"], -.emoji[aria-label="trade mark"], -.emoji[aria-label="multiply"], -.emoji[aria-label="plus"], -.emoji[aria-label="minus"], -.emoji[aria-label="divide"], -.emoji[aria-label="curly loop"], -.emoji[aria-label="double curly loop"], -.emoji[aria-label="wavy dash"], -.emoji[aria-label="paw prints"], -.emoji[aria-label="musical note"], -.emoji[aria-label="musical notes"] { - filter: invert(100%) hue-rotate(180deg); -} -.edit-diff > div > .ui.table { - border-left-color: var(--color-secondary) !important; - border-right-color: var(--color-secondary) !important; -} -footer .container .links > * { - border-left-color: #888; -} -.repository.release #release-list > li .detail .dot { - background-color: #505667; - border-color: #383c4a; -} -.tribute-container { - box-shadow: 0 .25rem .5rem rgba(0, 0, 0, .6); -} -.repository .repo-header .ui.huge.breadcrumb.repo-title .repo-header-icon .avatar { - color: #2a2e3a; -} -img[src$="/img/matrix.svg"] { - filter: invert(80%); -} -.is-loading::after { - border-color: #4a4c58 #4a4c58 #d7d7da #d7d7da; -} -.markup-block-error { - border: 1px solid rgba(121, 71, 66, .5) !important; - border-bottom: none !important; -} From e51e3e2196b68713ec6a822e6d70395acc5f95cf Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Wed, 1 Jun 2022 16:32:07 +0200 Subject: [PATCH 19/25] Update models/migrations/v216.go --- models/migrations/v216.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/migrations/v216.go b/models/migrations/v216.go index ec3133231d8bd..8a3a9c877e75d 100644 --- a/models/migrations/v216.go +++ b/models/migrations/v216.go @@ -1,4 +1,4 @@ -// Copyright 2021 The Gitea Authors. All rights reserved. +// Copyright 2022 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. From 5bda8b32ba02691d390812a875a83aa678969e3f Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 15 Jun 2022 11:24:32 +0800 Subject: [PATCH 20/25] Fix some bugs --- routers/web/admin/config.go | 2 +- web_src/js/features/admin/config.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go index 6047cf88f11a8..b0f84f1acd326 100644 --- a/routers/web/admin/config.go +++ b/routers/web/admin/config.go @@ -155,7 +155,7 @@ func Config(ctx *context.Context) { if sessionCfg.Provider == "VirtualSession" { var realSession session.Options if err := json.Unmarshal([]byte(sessionCfg.ProviderConfig), &realSession); err != nil { - log.Error("Unable to unmarshall session config for virtualed provider config: %s\nError: %v", sessionCfg.ProviderConfig, err) + log.Error("Unable to unmarshall session config for virtual provider config: %s\nError: %v", sessionCfg.ProviderConfig, err) } sessionCfg.Provider = realSession.Provider sessionCfg.ProviderConfig = realSession.ProviderConfig diff --git a/web_src/js/features/admin/config.js b/web_src/js/features/admin/config.js index 1e71e8037e909..a93f42d89a495 100644 --- a/web_src/js/features/admin/config.js +++ b/web_src/js/features/admin/config.js @@ -19,7 +19,6 @@ export function initAdminConfigs() { } }).done((resp) => { if (resp) { - console.info(resp); if (resp.redirect) { window.location.href = resp.redirect; } else if (resp.version) { From 10f4c6d733596adbe05bb357b4b09e8fb3ab9c90 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 17 Aug 2022 13:51:54 +0800 Subject: [PATCH 21/25] Fix typo --- templates/admin/config.tmpl | 4 ++-- web_src/js/features/admin/config.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index 5fbc96c2c8adc..5851257ad4a72 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -303,14 +303,14 @@
{{.locale.Tr "admin.config.disable_gravatar"}}
- +
{{.locale.Tr "admin.config.enable_federated_avatar"}}
- +
diff --git a/web_src/js/features/admin/config.js b/web_src/js/features/admin/config.js index a93f42d89a495..b942873913598 100644 --- a/web_src/js/features/admin/config.js +++ b/web_src/js/features/admin/config.js @@ -1,11 +1,11 @@ import $ from 'jquery'; +const {appSubUrl, csrfToken, pageData} = window.config; + export function initAdminConfigs() { - const isAdminConfigPage = window.config.pageData.adminConfigPage; + const isAdminConfigPage = pageData?.adminConfigPage; if (!isAdminConfigPage) return; - const {appSubUrl, csrfToken} = window.config; - $("input[type='checkbox']").on('change', (e) => { const $this = $(e.currentTarget); $.ajax({ From f837aecf191c85b68a32008aee943bc50405bdef Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 17 Aug 2022 14:15:59 +0800 Subject: [PATCH 22/25] popup a tooltip when setting failed --- web_src/js/features/admin/config.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web_src/js/features/admin/config.js b/web_src/js/features/admin/config.js index b942873913598..f5d8fae8facf3 100644 --- a/web_src/js/features/admin/config.js +++ b/web_src/js/features/admin/config.js @@ -1,4 +1,5 @@ import $ from 'jquery'; +import {showTemporaryTooltip} from '../../modules/tippy.js'; const {appSubUrl, csrfToken, pageData} = window.config; @@ -23,6 +24,9 @@ export function initAdminConfigs() { window.location.href = resp.redirect; } else if (resp.version) { $this.attr('version', resp.version); + } else if (resp.err) { + showTemporaryTooltip(e.currentTarget, resp.err); + $this.prop('checked', !$this.is(':checked')); } } }); From c2e6e22929564a38239fb9a69dfacf7c96c1dd6a Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 17 Aug 2022 14:26:17 +0800 Subject: [PATCH 23/25] Fix error --- routers/web/admin/config.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go index 6022fbc652e70..614d3d4f662bb 100644 --- a/routers/web/admin/config.go +++ b/routers/web/admin/config.go @@ -40,8 +40,6 @@ func SendTestMail(ctx *context.Context) { ctx.Redirect(setting.AppSubURL + "/admin/config") } - - func shadowPasswordKV(cfgItem, splitter string) string { fields := strings.Split(cfgItem, splitter) for i := 0; i < len(fields); i++ { @@ -113,9 +111,7 @@ func Config(ctx *context.Context) { // All editable settings from UI ctx.Data["SystemSettings"] = systemSettings - ctx.PageData["adminConfigPage"] = map[string]string{ - "abc": "", - } + ctx.PageData["adminConfigPage"] = true ctx.Data["CustomConf"] = setting.CustomConf ctx.Data["AppUrl"] = setting.AppURL From 5ce610ab3ab71767b167024602ad3b81a0503bf3 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 17 Oct 2022 02:33:29 +0800 Subject: [PATCH 24/25] Fix bug --- routers/install/install.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/install/install.go b/routers/install/install.go index 1c40685ed09db..8a0d34d97631b 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -156,7 +156,7 @@ func Install(ctx *context.Context) { form.DisableGravatar = false } - enableFederatedAvatarSetting, _ := system_model.GetSetting("") + enableFederatedAvatarSetting, _ := system_model.GetSetting(system_model.KeyPictureEnableFederatedAvatar) if enableFederatedAvatarSetting != nil { form.EnableFederatedAvatar = enableFederatedAvatarSetting.GetValueBool() } else { From a0a2cd5fcac1c9f4a1f84e0337c91d724b66d6e1 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sun, 16 Oct 2022 22:09:22 +0200 Subject: [PATCH 25/25] Update modules/system/setting.go --- modules/system/setting.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/system/setting.go b/modules/system/setting.go index 2454193b04776..aebf24a501949 100644 --- a/modules/system/setting.go +++ b/modules/system/setting.go @@ -26,6 +26,8 @@ func GetSetting(key string) (string, error) { }) } +// GetSettingBool return bool value of setting, +// none existing keys and errors are ignored and result in false func GetSettingBool(key string) bool { s, _ := GetSetting(key) b, _ := strconv.ParseBool(s)