From d919301d36504d5fd79bb01b318b67befa3c7abc Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Wed, 4 Nov 2026 05:28:49 +0000 Subject: [PATCH] refactor: remove UnmarshalHandleDoubleEncode patch and fix repo unit TODO (#39998) Remove the `UnmarshalHandleDoubleEncode` runtime workaround for an old xorm bug, and normalize legacy double-encoded JSON in `repo_unit.config` and `login_source.cfg` with a migration instead. - Config `FromDB` no longer fails on corrupted values. A broken auth source is deactivated, so admins can still fix it in the admin panel - Remove `ProjectsConfig.GetProjectsMode`, `FromDB` already defaults `ProjectsMode` Actually it doesn't need so many changes, just because AI thinks it should handle "corrupted database value" for auth sources. --------- Signed-off-by: wxiaoguang Co-authored-by: silverwind --- modelmigration/migrations.go | 1 + modelmigration/v29/v365.go | 95 +++++++++++++++++++++++++++ modelmigration/v29/v365_test.go | 95 +++++++++++++++++++++++++++ models/actions/config.go | 4 +- models/auth/source.go | 33 +++++++++- models/auth/source_test.go | 42 +++++++++++- models/db/convert.go | 19 ++++++ models/repo/repo_unit.go | 48 ++++---------- models/repo/repo_unit_actions.go | 5 +- modules/json/json.go | 36 ---------- modules/json/json_test.go | 8 --- services/auth/source/ldap/source.go | 18 +---- services/auth/source/oauth2/source.go | 5 +- services/auth/source/pam/source.go | 12 +--- services/auth/source/smtp/source.go | 12 +--- services/auth/source/sspi/source.go | 18 ++--- templates/repo/settings/options.tmpl | 12 ++-- 17 files changed, 318 insertions(+), 145 deletions(-) create mode 100644 modelmigration/v29/v365.go create mode 100644 modelmigration/v29/v365_test.go diff --git a/modelmigration/migrations.go b/modelmigration/migrations.go index fc4bc6a8937..dd1fa3cab38 100644 --- a/modelmigration/migrations.go +++ b/modelmigration/migrations.go @@ -441,6 +441,7 @@ func prepareMigrationTasks() []*migration { newMigration(362, "Add reusable_workflow_ref column to action_run_job", v29.AddReusableWorkflowRefToActionRunJob), newMigration(363, "Add release_id to reaction table", v29.AddReleaseIDToReaction), newMigration(364, "Add new table project_workflow", v29.AddProjectWorkflow), + newMigration(365, "Normalize legacy repository unit and login source JSON", v29.NormalizeLegacyConfigJSON), } return preparedMigrations } diff --git a/modelmigration/v29/v365.go b/modelmigration/v29/v365.go new file mode 100644 index 00000000000..3825decc5d6 --- /dev/null +++ b/modelmigration/v29/v365.go @@ -0,0 +1,95 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v29 + +import ( + "context" + "encoding/binary" + + "gitea.dev/modelmigration/base" + "gitea.dev/modules/json" + "gitea.dev/modules/util" +) + +// unmarshalHandleDoubleEncode - due to a bug in xorm (see https://gitea.com/xorm/xorm/pulls/1957) - it's +// possible that a Blob may be double encoded or gain an unwanted prefix of 0xff 0xfe. +func unmarshalHandleDoubleEncode(bs []byte, v any) error { + if len(bs) == 0 { + // json.Unmarshal will report errors if input is empty (nil or zero-length) + // It seems that XORM ignores the nil but still passes zero-length string into this function + // To be consistent, we should treat all empty inputs as success + return nil + } + err := json.Unmarshal(bs, v) + if err != nil { + ok := true + rs := []byte{} + temp := make([]byte, 2) + for _, rn := range string(bs) { + if rn > 0xffff { + ok = false + break + } + binary.LittleEndian.PutUint16(temp, uint16(rn)) + rs = append(rs, temp...) + } + if ok { + if len(rs) > 1 && rs[0] == 0xff && rs[1] == 0xfe { + rs = rs[2:] + } + err = json.Unmarshal(rs, v) + } + } + if err != nil && len(bs) > 2 && bs[0] == 0xff && bs[1] == 0xfe { + err = json.Unmarshal(bs[2:], v) + } + return err +} + +func normalizeLegacyConfigJSON(config string) string { + if config == "" || json.Valid(util.UnsafeStringToBytes(config)) { + return config + } + + m := map[any]any{} + err := unmarshalHandleDoubleEncode(util.UnsafeStringToBytes(config), &m) + if err != nil { + return config + } + if bs, err := json.Marshal(m); err == nil { + return string(bs) + } + return config +} + +func NormalizeLegacyConfigJSON(ctx context.Context, x base.EngineMigration) error { + type RepoUnit struct { + ID int64 + Config string + } + type LoginSource struct { + ID int64 + Cfg string + } + return base.EngineTransaction(x, func(sess base.Session) error { + if err := base.IterateTableByColumn(ctx, x, sess, "id", nil, func(_ context.Context, unit *RepoUnit) error { + config := normalizeLegacyConfigJSON(unit.Config) + if config == unit.Config { + return nil + } + _, err := sess.ID(unit.ID).Cols("config").Update(&RepoUnit{Config: config}) + return err + }); err != nil { + return err + } + return base.IterateTableByColumn(ctx, x, sess, "id", nil, func(_ context.Context, source *LoginSource) error { + config := normalizeLegacyConfigJSON(source.Cfg) + if config == source.Cfg { + return nil + } + _, err := sess.ID(source.ID).Cols("cfg").Update(&LoginSource{Cfg: config}) + return err + }) + }) +} diff --git a/modelmigration/v29/v365_test.go b/modelmigration/v29/v365_test.go new file mode 100644 index 00000000000..f8e4ddeac62 --- /dev/null +++ b/modelmigration/v29/v365_test.go @@ -0,0 +1,95 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v29 + +import ( + "testing" + + "gitea.dev/modelmigration/migrationtest" + "gitea.dev/modules/setting" + "gitea.dev/modules/test" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNormalizeLegacyConfigJSONValue(t *testing.T) { + const ( + config = `{"Host":"smtp.example.com"}` + packed = "≻潈瑳㨢猢瑭⹰硥浡汰⹥潣≭⁽" + ) + for _, tc := range []struct { + name, input, want string + }{ + {"empty", "", ""}, + {"valid", config + " ", config + " "}, + {"unicode and large number", ` {"name":"例😀","id":9007199254740993} `, ` {"name":"例😀","id":9007199254740993} `}, + {"double encoded", packed, config}, + {"double encoded with BOM", "\ufeff" + packed, config}, + {"BOM", "\xff\xfe" + config, config}, + {"BOM with non-BMP rune", "\xff\xfe" + `{"name":"😀"}`, `{"name":"😀"}`}, + {"corrupt", "invalid", "invalid"}, + {"corrupt non-BMP rune", "invalid😀", "invalid😀"}, + } { + t.Run(tc.name, func(t *testing.T) { + got := normalizeLegacyConfigJSON(tc.input) + assert.Equal(t, tc.want, got) + assert.Equal(t, got, normalizeLegacyConfigJSON(got)) + }) + } +} + +func TestNormalizeLegacyConfigJSON(t *testing.T) { + type RepoUnit struct { + ID int64 `xorm:"pk autoincr"` + RepoID int64 + Config string `xorm:"TEXT"` + } + type LoginSource struct { + ID int64 `xorm:"pk autoincr"` + Name string + Cfg string `xorm:"TEXT"` + } + x, cleanup := migrationtest.PrepareTestEnv(t, 0, new(RepoUnit), new(LoginSource)) + defer cleanup() + if x == nil || t.Failed() { + return + } + defer test.MockVariableValue(&setting.Database.IterateBufferSize, 2)() + + inputs := []string{ + ` {"id":9007199254740993,"name":"例😀"} `, + "≻潈瑳㨢猢瑭⹰硥浡汰⹥潣≭⁽", + "\ufeff≻潈瑳㨢猢瑭⹰硥浡汰⹥潣≭⁽", + "", + "invalid", + } + want := []string{inputs[0], `{"Host":"smtp.example.com"}`, `{"Host":"smtp.example.com"}`, "", "invalid", ""} + for _, input := range inputs { + _, err := x.Insert(&RepoUnit{RepoID: 42, Config: input}) + require.NoError(t, err) + _, err = x.Insert(&LoginSource{Name: "test", Cfg: input}) + require.NoError(t, err) + } + _, err := x.Exec("INSERT INTO `repo_unit` (`repo_id`, `config`) VALUES (?, NULL)", 42) + require.NoError(t, err) + _, err = x.Exec("INSERT INTO `login_source` (`name`, `cfg`) VALUES (?, NULL)", "test") + require.NoError(t, err) + + for range 2 { + require.NoError(t, NormalizeLegacyConfigJSON(t.Context(), x)) + var units []RepoUnit + require.NoError(t, x.Asc("id").Find(&units)) + require.Len(t, units, len(want)) + var sources []LoginSource + require.NoError(t, x.Asc("id").Find(&sources)) + require.Len(t, sources, len(want)) + for i, config := range want { + assert.Equal(t, config, units[i].Config) + assert.EqualValues(t, 42, units[i].RepoID) + assert.Equal(t, config, sources[i].Cfg) + assert.Equal(t, "test", sources[i].Name) + } + } +} diff --git a/models/actions/config.go b/models/actions/config.go index 6821669a81e..81cbb2b9454 100644 --- a/models/actions/config.go +++ b/models/actions/config.go @@ -6,10 +6,10 @@ package actions import ( "context" + "gitea.dev/models/db" "gitea.dev/models/perm" repo_model "gitea.dev/models/repo" user_model "gitea.dev/models/user" - "gitea.dev/modules/json" "gitea.dev/modules/util" "xorm.io/xorm/convert" @@ -30,7 +30,7 @@ type OwnerActionsConfig struct { var _ convert.ConversionFrom = (*OwnerActionsConfig)(nil) func (cfg *OwnerActionsConfig) FromDB(bytes []byte) error { - _ = json.Unmarshal(bytes, cfg) + db.UnmarshalFromDB(bytes, cfg) cfg.TokenPermissionMode, _ = util.EnumValue(cfg.TokenPermissionMode) return nil } diff --git a/models/auth/source.go b/models/auth/source.go index 2533ab5040e..bfcd81b1bd1 100644 --- a/models/auth/source.go +++ b/models/auth/source.go @@ -10,6 +10,7 @@ import ( "reflect" "gitea.dev/models/db" + "gitea.dev/modules/graceful" "gitea.dev/modules/log" "gitea.dev/modules/optional" "gitea.dev/modules/setting" @@ -60,14 +61,40 @@ var Names = map[Type]string{ type Config interface { convert.Conversion SetAuthSource(*Source) + GetAuthSource() *Source } type ConfigBase struct { - AuthSource *Source + AuthSource *Source `json:"-"` } -func (p *ConfigBase) SetAuthSource(s *Source) { - p.AuthSource = s +func (c *ConfigBase) SetAuthSource(source *Source) { + c.AuthSource = source +} + +func (c *ConfigBase) GetAuthSource() *Source { + return c.AuthSource +} + +func UnmarshalAuthSourceConfig(bs []byte, v Config) { + if db.UnmarshalFromDB(bs, &v) { + return + } + // This is only a workaround because we don't know whether this unmarshal happens on sign-in page or admin panel. + // * Admin should have the chance to edit the auth source in admin panel, so FromDB should not return an error + // * The sign-in page should not use the auth source in the next login attempt, but we don't have a clear way to disable it immediately (acceptable) + // Actually, corrupted database value is a really rare case, just because AI thinks it should be handled. + authSourceID := v.GetAuthSource().ID + log.Error("Unable to unmarshal login source id=%d, will mark it as inactive to avoid unexpected sign-in issues", authSourceID) + go graceful.GetManager().RunWithShutdownContext(func(ctx context.Context) { + // A small time window to avoid race condition with admin's editing because there is no other way. + // The UpdateUnix field is not filled when this function is called. + _, err := db.GetEngine(ctx).ID(authSourceID).And("is_active = ? AND updated_unix < ?", true, timeutil.TimeStampNow()-5). + Cols("is_active").Update(&Source{IsActive: false}) + if err != nil { + log.Error("Unable to set login source id=%d to inactive: %v", authSourceID, err) + } + }) } // SkipVerifiable configurations provide a IsSkipVerify to check if SkipVerify is set diff --git a/models/auth/source_test.go b/models/auth/source_test.go index b09fc7f4b06..4c915863978 100644 --- a/models/auth/source_test.go +++ b/models/auth/source_test.go @@ -6,10 +6,15 @@ package auth_test import ( "strings" "testing" + "time" auth_model "gitea.dev/models/auth" + "gitea.dev/models/db" "gitea.dev/models/unittest" "gitea.dev/modules/json" + "gitea.dev/modules/setting" + "gitea.dev/modules/test" + "gitea.dev/modules/timeutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -24,7 +29,8 @@ type TestSource struct { // FromDB fills up a LDAPConfig from serialized format. func (source *TestSource) FromDB(bs []byte) error { - return json.Unmarshal(bs, &source) + auth_model.UnmarshalAuthSourceConfig(bs, source) + return nil } // ToDB exports a LDAPConfig to a serialized format. @@ -53,3 +59,37 @@ func TestDumpAuthSource(t *testing.T) { // INSERT INTO `login_source` (`id`, `type`, `name`, `is_active`, `is_sync_enabled`, `two_factor_policy`, `cfg`, `created_unix`, `updated_unix`) VALUES (1,6,'TestSource',0,0,'','{"TestField":"TestValue"}',1774179784,1774179784); assert.Contains(t, sb.String(), `'{"TestField":"TestValue"}'`) } + +func TestUnmarshalAuthSourceConfig(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + defer test.MockVariableValue(&setting.IsProd, true)() + defer test.MockVariableValue(&setting.IsInTesting, false)() + + cfg := &TestSource{} + source := &auth_model.Source{Type: auth_model.OAuth2, Name: t.Name(), IsActive: true, Cfg: cfg} + err := db.Insert(t.Context(), source) + require.NoError(t, err) + cfg.SetAuthSource(source) + + t.Run("ValidConfig", func(t *testing.T) { + for _, data := range []string{`{"TestField":"TestValue"}`, "", "null"} { + auth_model.UnmarshalAuthSourceConfig([]byte(data), cfg) + assert.Equal(t, "TestValue", cfg.TestField) + assert.Same(t, source, cfg.GetAuthSource()) + } + }) + + t.Run("InvalidConfigDeactivatesSource", func(t *testing.T) { + _, err = db.GetEngine(t.Context()).ID(source.ID).NoAutoTime().Cols("updated_unix").Update(&auth_model.Source{UpdatedUnix: timeutil.TimeStampNow() - 60}) + require.NoError(t, err) + has, _ := db.GetEngine(t.Context()).ID(source.ID).And("is_active=?", true).Get(&auth_model.Source{}) + assert.True(t, has) + + auth_model.UnmarshalAuthSourceConfig([]byte(`{"TestField":false}`), cfg) + assert.Same(t, source, cfg.GetAuthSource()) + require.Eventually(t, func() bool { + has, _ := db.GetEngine(t.Context()).ID(source.ID).And("is_active=?", false).Get(&auth_model.Source{}) + return has + }, time.Second, time.Millisecond) + }) +} diff --git a/models/db/convert.go b/models/db/convert.go index 125449705c0..3d9eac47354 100644 --- a/models/db/convert.go +++ b/models/db/convert.go @@ -6,6 +6,7 @@ package db import ( "fmt" + "gitea.dev/modules/json" "gitea.dev/modules/setting" "xorm.io/xorm" @@ -84,3 +85,21 @@ func CellToInt[T ~int | int64](cell xorm.Cell, def T) (ret T, has bool, err erro } return T(val), true, err } + +func UnmarshalFromDB(data []byte, v any) bool { + if len(data) == 0 { + return true + } + err := json.Unmarshal(data, v) + if err != nil { + // Even if database value is corrupted, we should not let it cause unnecessary 500 error or block user's operation + // Corrupted database value is a really rare case, it should never happen unless site admin manually modified the database. + // Although some database values will be printed into logs, it isn't a real problem + // because such case should never really happen. If it happens, logging the value + // is the only way to tell site admin which record is wrong since there is no other context information, + // and then they need to re-create the config (with new secrets) + setting.PanicInDevOrTesting("UnmarshalFromDB %q failed: %v", string(data), err) + return false + } + return true +} diff --git a/models/repo/repo_unit.go b/models/repo/repo_unit.go index 4ea8f6d22d6..91d8073832a 100644 --- a/models/repo/repo_unit.go +++ b/models/repo/repo_unit.go @@ -56,12 +56,11 @@ func init() { // UnitConfig describes common unit config type UnitConfig struct{} -// FromDB fills up a UnitConfig from serialized format. func (cfg *UnitConfig) FromDB(bs []byte) error { - return json.UnmarshalHandleDoubleEncode(bs, &cfg) + db.UnmarshalFromDB(bs, cfg) + return nil } -// ToDB exports a UnitConfig to a serialized format. func (cfg *UnitConfig) ToDB() ([]byte, error) { return json.Marshal(cfg) } @@ -71,12 +70,11 @@ type ExternalWikiConfig struct { ExternalWikiURL string } -// FromDB fills up a ExternalWikiConfig from serialized format. func (cfg *ExternalWikiConfig) FromDB(bs []byte) error { - return json.UnmarshalHandleDoubleEncode(bs, &cfg) + db.UnmarshalFromDB(bs, cfg) + return nil } -// ToDB exports a ExternalWikiConfig to a serialized format. func (cfg *ExternalWikiConfig) ToDB() ([]byte, error) { return json.Marshal(cfg) } @@ -89,12 +87,11 @@ type ExternalTrackerConfig struct { ExternalTrackerRegexpPattern string } -// FromDB fills up a ExternalTrackerConfig from serialized format. func (cfg *ExternalTrackerConfig) FromDB(bs []byte) error { - return json.UnmarshalHandleDoubleEncode(bs, &cfg) + db.UnmarshalFromDB(bs, cfg) + return nil } -// ToDB exports a ExternalTrackerConfig to a serialized format. func (cfg *ExternalTrackerConfig) ToDB() ([]byte, error) { return json.Marshal(cfg) } @@ -106,12 +103,11 @@ type IssuesConfig struct { EnableDependencies bool } -// FromDB fills up a IssuesConfig from serialized format. func (cfg *IssuesConfig) FromDB(bs []byte) error { - return json.UnmarshalHandleDoubleEncode(bs, &cfg) + db.UnmarshalFromDB(bs, cfg) + return nil } -// ToDB exports a IssuesConfig to a serialized format. func (cfg *IssuesConfig) ToDB() ([]byte, error) { return json.Marshal(cfg) } @@ -155,16 +151,14 @@ func DefaultPullRequestsConfig() *PullRequestsConfig { return cfg } -// FromDB fills up a PullRequestsConfig from serialized format. func (cfg *PullRequestsConfig) FromDB(bs []byte) error { // set default values for existing PullRequestConfig in DB *cfg = *DefaultPullRequestsConfig() - _ = json.UnmarshalHandleDoubleEncode(bs, &cfg) // don't let corrupted database value cause unnecessary 500 error + db.UnmarshalFromDB(bs, cfg) cfg.DefaultUpdateStyle = util.IfZero(cfg.DefaultUpdateStyle, UpdateStyleMerge) return nil } -// ToDB exports a PullRequestsConfig to a serialized format. func (cfg *PullRequestsConfig) ToDB() ([]byte, error) { return json.Marshal(cfg) } @@ -228,34 +222,18 @@ type ProjectsConfig struct { ProjectsMode ProjectsMode } -// FromDB fills up a ProjectsConfig from serialized format. func (cfg *ProjectsConfig) FromDB(bs []byte) error { - // TODO: remove GetProjectsMode, only use ProjectsMode - cfg.ProjectsMode = ProjectsModeAll - return json.UnmarshalHandleDoubleEncode(bs, &cfg) + db.UnmarshalFromDB(bs, cfg) + cfg.ProjectsMode = util.IfZero(cfg.ProjectsMode, ProjectsModeAll) + return nil } -// ToDB exports a ProjectsConfig to a serialized format. func (cfg *ProjectsConfig) ToDB() ([]byte, error) { return json.Marshal(cfg) } -func (cfg *ProjectsConfig) GetProjectsMode() ProjectsMode { - if cfg.ProjectsMode != "" { - return cfg.ProjectsMode - } - - return ProjectsModeAll -} - func (cfg *ProjectsConfig) IsProjectsAllowed(m ProjectsMode) bool { - projectsMode := cfg.GetProjectsMode() - - if m == ProjectsModeNone { - return true - } - - return projectsMode == m || projectsMode == ProjectsModeAll + return m == ProjectsModeNone || cfg.ProjectsMode == m || cfg.ProjectsMode == ProjectsModeAll } // BeforeSet is invoked from XORM before setting the value of a field of this object. diff --git a/models/repo/repo_unit_actions.go b/models/repo/repo_unit_actions.go index 65f04b414b6..12f018bef08 100644 --- a/models/repo/repo_unit_actions.go +++ b/models/repo/repo_unit_actions.go @@ -6,6 +6,7 @@ package repo import ( "slices" + "gitea.dev/models/db" "gitea.dev/models/perm" "gitea.dev/models/unit" "gitea.dev/modules/json" @@ -173,14 +174,12 @@ func (cfg *ActionsConfig) ClampPermissions(perms ActionsTokenPermissions) Action return ClampActionsTokenPermissions(perms, maxPerms) } -// FromDB fills up a ActionsConfig from serialized format. func (cfg *ActionsConfig) FromDB(bs []byte) error { - _ = json.UnmarshalHandleDoubleEncode(bs, &cfg) + db.UnmarshalFromDB(bs, cfg) cfg.TokenPermissionMode, _ = util.EnumValue(cfg.TokenPermissionMode) return nil } -// ToDB exports a ActionsConfig to a serialized format. func (cfg *ActionsConfig) ToDB() ([]byte, error) { return json.Marshal(cfg) } diff --git a/modules/json/json.go b/modules/json/json.go index eea9a1e6e7b..769ca1f3f43 100644 --- a/modules/json/json.go +++ b/modules/json/json.go @@ -5,7 +5,6 @@ package json import ( "bytes" - "encoding/binary" "encoding/json" //nolint:depguard // this package wraps it "io" ) @@ -81,38 +80,3 @@ func MarshalIndent(v any, prefix, indent string) ([]byte, error) { func Valid(data []byte) bool { return json.Valid(data) } - -// UnmarshalHandleDoubleEncode - due to a bug in xorm (see https://gitea.com/xorm/xorm/pulls/1957) - it's -// possible that a Blob may be double encoded or gain an unwanted prefix of 0xff 0xfe. -func UnmarshalHandleDoubleEncode(bs []byte, v any) error { - if len(bs) == 0 { - // json.Unmarshal will report errors if input is empty (nil or zero-length) - // It seems that XORM ignores the nil but still passes zero-length string into this function - // To be consistent, we should treat all empty inputs as success - return nil - } - err := json.Unmarshal(bs, v) - if err != nil { - ok := true - rs := []byte{} - temp := make([]byte, 2) - for _, rn := range string(bs) { - if rn > 0xffff { - ok = false - break - } - binary.LittleEndian.PutUint16(temp, uint16(rn)) - rs = append(rs, temp...) - } - if ok { - if len(rs) > 1 && rs[0] == 0xff && rs[1] == 0xfe { - rs = rs[2:] - } - err = json.Unmarshal(rs, v) - } - } - if err != nil && len(bs) > 2 && bs[0] == 0xff && bs[1] == 0xfe { - err = json.Unmarshal(bs[2:], v) - } - return err -} diff --git a/modules/json/json_test.go b/modules/json/json_test.go index 2fa4da4cf79..ce3b02dc427 100644 --- a/modules/json/json_test.go +++ b/modules/json/json_test.go @@ -10,14 +10,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestGiteaDBJSONUnmarshal(t *testing.T) { - var m map[any]any - err := UnmarshalHandleDoubleEncode(nil, &m) - assert.NoError(t, err) - err = UnmarshalHandleDoubleEncode([]byte(""), &m) - assert.NoError(t, err) -} - func TestIndent(t *testing.T) { buf := &bytes.Buffer{} err := Indent(buf, []byte(`{"a":1}`), ">", " ") diff --git a/services/auth/source/ldap/source.go b/services/auth/source/ldap/source.go index 8e6f878bbe2..ddfb8136386 100644 --- a/services/auth/source/ldap/source.go +++ b/services/auth/source/ldap/source.go @@ -13,14 +13,7 @@ import ( "gitea.dev/modules/setting" ) -// .____ ________ _____ __________ -// | | \______ \ / _ \\______ \ -// | | | | \ / /_\ \| ___/ -// | |___ | ` \/ | \ | -// |_______ \/_______ /\____|__ /____| -// \/ \/ \/ - -// Package ldap provide functions & structure to query a LDAP ldap directory +// Package ldap provide functions & structure to query an LDAP directory // For now, it's mainly tested again an MS Active Directory service, see README.md for more information // Source Basic LDAP authentication service @@ -60,12 +53,8 @@ type Source struct { UserUID string // User Attribute listed in Group } -// FromDB fills up a LDAPConfig from serialized format. -func (source *Source) FromDB(bs []byte) error { - err := json.UnmarshalHandleDoubleEncode(bs, &source) - if err != nil { - return err - } +func (source *Source) FromDB(bs []byte) (err error) { + auth.UnmarshalAuthSourceConfig(bs, source) if source.BindPasswordEncrypt != "" { source.BindPassword, err = secret.DecryptSecret(setting.SecretKey, source.BindPasswordEncrypt) if err != nil { @@ -76,7 +65,6 @@ func (source *Source) FromDB(bs []byte) error { return nil } -// ToDB exports a LDAPConfig to a serialized format. func (source *Source) ToDB() ([]byte, error) { var err error source.BindPasswordEncrypt, err = secret.EncryptSecret(setting.SecretKey, source.BindPassword) diff --git a/services/auth/source/oauth2/source.go b/services/auth/source/oauth2/source.go index da7f61200c2..fed70ea23ef 100644 --- a/services/auth/source/oauth2/source.go +++ b/services/auth/source/oauth2/source.go @@ -33,12 +33,11 @@ type Source struct { ExternalIDClaim string } -// FromDB fills up an OAuth2Config from serialized format. func (source *Source) FromDB(bs []byte) error { - return json.UnmarshalHandleDoubleEncode(bs, &source) + auth.UnmarshalAuthSourceConfig(bs, source) + return nil } -// ToDB exports an OAuth2Config to a serialized format. func (source *Source) ToDB() ([]byte, error) { return json.Marshal(source) } diff --git a/services/auth/source/pam/source.go b/services/auth/source/pam/source.go index 3f782e73cff..dd92e99e155 100644 --- a/services/auth/source/pam/source.go +++ b/services/auth/source/pam/source.go @@ -8,13 +8,6 @@ import ( "gitea.dev/modules/json" ) -// __________ _____ _____ -// \______ \/ _ \ / \ -// | ___/ /_\ \ / \ / \ -// | | / | \/ Y \ -// |____| \____|__ /\____|__ / -// \/ \/ - // Source holds configuration for the PAM login source. type Source struct { auth.ConfigBase `json:"-"` @@ -23,12 +16,11 @@ type Source struct { EmailDomain string } -// FromDB fills up a PAMConfig from serialized format. func (source *Source) FromDB(bs []byte) error { - return json.UnmarshalHandleDoubleEncode(bs, &source) + auth.UnmarshalAuthSourceConfig(bs, source) + return nil } -// ToDB exports a PAMConfig to a serialized format. func (source *Source) ToDB() ([]byte, error) { return json.Marshal(source) } diff --git a/services/auth/source/smtp/source.go b/services/auth/source/smtp/source.go index 13b4668e9df..5ecdedfbc39 100644 --- a/services/auth/source/smtp/source.go +++ b/services/auth/source/smtp/source.go @@ -8,13 +8,6 @@ import ( "gitea.dev/modules/json" ) -// _________ __________________________ -// / _____/ / \__ ___/\______ \ -// \_____ \ / \ / \| | | ___/ -// / \/ Y \ | | | -// /_______ /\____|__ /____| |____| -// \/ \/ - // Source holds configuration for the SMTP login source. type Source struct { auth.ConfigBase `json:"-"` @@ -29,12 +22,11 @@ type Source struct { DisableHelo bool } -// FromDB fills up an SMTPConfig from serialized format. func (source *Source) FromDB(bs []byte) error { - return json.UnmarshalHandleDoubleEncode(bs, &source) + auth.UnmarshalAuthSourceConfig(bs, source) + return nil } -// ToDB exports an SMTPConfig to a serialized format. func (source *Source) ToDB() ([]byte, error) { return json.Marshal(source) } diff --git a/services/auth/source/sspi/source.go b/services/auth/source/sspi/source.go index 267c269de60..9e51c61e5c9 100644 --- a/services/auth/source/sspi/source.go +++ b/services/auth/source/sspi/source.go @@ -8,13 +8,6 @@ import ( "gitea.dev/modules/json" ) -// _________ ___________________.___ -// / _____// _____/\______ \ | -// \_____ \ \_____ \ | ___/ | -// / \/ \ | | | | -// /_______ /_______ / |____| |___| -// \/ \/ - // Source holds configuration for SSPI single sign-on. type Source struct { auth.ConfigBase `json:"-"` @@ -26,14 +19,13 @@ type Source struct { DefaultLanguage string } -// FromDB fills up an SSPIConfig from serialized format. -func (cfg *Source) FromDB(bs []byte) error { - return json.UnmarshalHandleDoubleEncode(bs, &cfg) +func (source *Source) FromDB(bs []byte) error { + auth.UnmarshalAuthSourceConfig(bs, source) + return nil } -// ToDB exports an SSPIConfig to a serialized format. -func (cfg *Source) ToDB() ([]byte, error) { - return json.Marshal(cfg) +func (source *Source) ToDB() ([]byte, error) { + return json.Marshal(source) } func init() { diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl index 787a73daf11..fe4c4865dc9 100644 --- a/templates/repo/settings/options.tmpl +++ b/templates/repo/settings/options.tmpl @@ -466,19 +466,19 @@