summaryrefslogtreecommitdiffstats
path: root/models/migrations/v1_17
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--models/migrations/v1_17/main_test.go14
-rw-r--r--models/migrations/v1_17/v211.go12
-rw-r--r--models/migrations/v1_17/v212.go93
-rw-r--r--models/migrations/v1_17/v213.go17
-rw-r--r--models/migrations/v1_17/v214.go22
-rw-r--r--models/migrations/v1_17/v215.go24
-rw-r--r--models/migrations/v1_17/v216.go7
-rw-r--r--models/migrations/v1_17/v217.go25
-rw-r--r--models/migrations/v1_17/v218.go52
-rw-r--r--models/migrations/v1_17/v219.go30
-rw-r--r--models/migrations/v1_17/v220.go23
-rw-r--r--models/migrations/v1_17/v221.go74
-rw-r--r--models/migrations/v1_17/v221_test.go63
-rw-r--r--models/migrations/v1_17/v222.go64
-rw-r--r--models/migrations/v1_17/v223.go98
15 files changed, 618 insertions, 0 deletions
diff --git a/models/migrations/v1_17/main_test.go b/models/migrations/v1_17/main_test.go
new file mode 100644
index 0000000..8a787f6
--- /dev/null
+++ b/models/migrations/v1_17/main_test.go
@@ -0,0 +1,14 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ "testing"
+
+ migration_tests "code.gitea.io/gitea/models/migrations/test"
+)
+
+func TestMain(m *testing.M) {
+ migration_tests.MainTest(m)
+}
diff --git a/models/migrations/v1_17/v211.go b/models/migrations/v1_17/v211.go
new file mode 100644
index 0000000..9b72c86
--- /dev/null
+++ b/models/migrations/v1_17/v211.go
@@ -0,0 +1,12 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ "xorm.io/xorm"
+)
+
+func CreateForeignReferenceTable(_ *xorm.Engine) error {
+ return nil // This table was dropped in v1_19/v237.go
+}
diff --git a/models/migrations/v1_17/v212.go b/models/migrations/v1_17/v212.go
new file mode 100644
index 0000000..e3f9437
--- /dev/null
+++ b/models/migrations/v1_17/v212.go
@@ -0,0 +1,93 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+)
+
+func AddPackageTables(x *xorm.Engine) error {
+ type Package struct {
+ ID int64 `xorm:"pk autoincr"`
+ OwnerID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
+ RepoID int64 `xorm:"INDEX"`
+ Type string `xorm:"UNIQUE(s) INDEX NOT NULL"`
+ Name string `xorm:"NOT NULL"`
+ LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
+ SemverCompatible bool `xorm:"NOT NULL DEFAULT false"`
+ }
+
+ if err := x.Sync(new(Package)); err != nil {
+ return err
+ }
+
+ type PackageVersion struct {
+ ID int64 `xorm:"pk autoincr"`
+ PackageID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
+ CreatorID int64 `xorm:"NOT NULL DEFAULT 0"`
+ Version string `xorm:"NOT NULL"`
+ LowerVersion string `xorm:"UNIQUE(s) INDEX NOT NULL"`
+ CreatedUnix timeutil.TimeStamp `xorm:"created INDEX NOT NULL"`
+ IsInternal bool `xorm:"INDEX NOT NULL DEFAULT false"`
+ MetadataJSON string `xorm:"metadata_json TEXT"`
+ DownloadCount int64 `xorm:"NOT NULL DEFAULT 0"`
+ }
+
+ if err := x.Sync(new(PackageVersion)); err != nil {
+ return err
+ }
+
+ type PackageProperty struct {
+ ID int64 `xorm:"pk autoincr"`
+ RefType int64 `xorm:"INDEX NOT NULL"`
+ RefID int64 `xorm:"INDEX NOT NULL"`
+ Name string `xorm:"INDEX NOT NULL"`
+ Value string `xorm:"TEXT NOT NULL"`
+ }
+
+ if err := x.Sync(new(PackageProperty)); err != nil {
+ return err
+ }
+
+ type PackageFile struct {
+ ID int64 `xorm:"pk autoincr"`
+ VersionID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
+ BlobID int64 `xorm:"INDEX NOT NULL"`
+ Name string `xorm:"NOT NULL"`
+ LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
+ CompositeKey string `xorm:"UNIQUE(s) INDEX"`
+ IsLead bool `xorm:"NOT NULL DEFAULT false"`
+ CreatedUnix timeutil.TimeStamp `xorm:"created INDEX NOT NULL"`
+ }
+
+ if err := x.Sync(new(PackageFile)); err != nil {
+ return err
+ }
+
+ type PackageBlob struct {
+ ID int64 `xorm:"pk autoincr"`
+ Size int64 `xorm:"NOT NULL DEFAULT 0"`
+ HashMD5 string `xorm:"hash_md5 char(32) UNIQUE(md5) INDEX NOT NULL"`
+ HashSHA1 string `xorm:"hash_sha1 char(40) UNIQUE(sha1) INDEX NOT NULL"`
+ HashSHA256 string `xorm:"hash_sha256 char(64) UNIQUE(sha256) INDEX NOT NULL"`
+ HashSHA512 string `xorm:"hash_sha512 char(128) UNIQUE(sha512) INDEX NOT NULL"`
+ CreatedUnix timeutil.TimeStamp `xorm:"created INDEX NOT NULL"`
+ }
+
+ if err := x.Sync(new(PackageBlob)); err != nil {
+ return err
+ }
+
+ type PackageBlobUpload struct {
+ ID string `xorm:"pk"`
+ BytesReceived int64 `xorm:"NOT NULL DEFAULT 0"`
+ HashStateBytes []byte `xorm:"BLOB"`
+ CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
+ UpdatedUnix timeutil.TimeStamp `xorm:"updated INDEX NOT NULL"`
+ }
+
+ return x.Sync(new(PackageBlobUpload))
+}
diff --git a/models/migrations/v1_17/v213.go b/models/migrations/v1_17/v213.go
new file mode 100644
index 0000000..bb3f466
--- /dev/null
+++ b/models/migrations/v1_17/v213.go
@@ -0,0 +1,17 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ "xorm.io/xorm"
+)
+
+func AddAllowMaintainerEdit(x *xorm.Engine) error {
+ // PullRequest represents relation between pull request and repositories.
+ type PullRequest struct {
+ AllowMaintainerEdit bool `xorm:"NOT NULL DEFAULT false"`
+ }
+
+ return x.Sync(new(PullRequest))
+}
diff --git a/models/migrations/v1_17/v214.go b/models/migrations/v1_17/v214.go
new file mode 100644
index 0000000..2268164
--- /dev/null
+++ b/models/migrations/v1_17/v214.go
@@ -0,0 +1,22 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ "xorm.io/xorm"
+)
+
+func AddAutoMergeTable(x *xorm.Engine) error {
+ type MergeStyle string
+ type PullAutoMerge struct {
+ ID int64 `xorm:"pk autoincr"`
+ PullID int64 `xorm:"UNIQUE"`
+ DoerID int64 `xorm:"NOT NULL"`
+ MergeStyle MergeStyle `xorm:"varchar(30)"`
+ Message string `xorm:"LONGTEXT"`
+ CreatedUnix int64 `xorm:"created"`
+ }
+
+ return x.Sync(&PullAutoMerge{})
+}
diff --git a/models/migrations/v1_17/v215.go b/models/migrations/v1_17/v215.go
new file mode 100644
index 0000000..b338f85
--- /dev/null
+++ b/models/migrations/v1_17/v215.go
@@ -0,0 +1,24 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ "code.gitea.io/gitea/models/pull"
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+)
+
+func AddReviewViewedFiles(x *xorm.Engine) error {
+ type ReviewState struct {
+ ID int64 `xorm:"pk autoincr"`
+ UserID int64 `xorm:"NOT NULL UNIQUE(pull_commit_user)"`
+ PullID int64 `xorm:"NOT NULL INDEX UNIQUE(pull_commit_user) DEFAULT 0"`
+ CommitSHA string `xorm:"NOT NULL VARCHAR(40) UNIQUE(pull_commit_user)"`
+ UpdatedFiles map[string]pull.ViewedState `xorm:"NOT NULL LONGTEXT JSON"`
+ UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
+ }
+
+ return x.Sync(new(ReviewState))
+}
diff --git a/models/migrations/v1_17/v216.go b/models/migrations/v1_17/v216.go
new file mode 100644
index 0000000..268f472
--- /dev/null
+++ b/models/migrations/v1_17/v216.go
@@ -0,0 +1,7 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+// This migration added non-ideal indices to the action table which on larger datasets slowed things down
+// it has been superseded by v218.go
diff --git a/models/migrations/v1_17/v217.go b/models/migrations/v1_17/v217.go
new file mode 100644
index 0000000..3f970b6
--- /dev/null
+++ b/models/migrations/v1_17/v217.go
@@ -0,0 +1,25 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ "code.gitea.io/gitea/modules/setting"
+
+ "xorm.io/xorm"
+)
+
+func AlterHookTaskTextFieldsToLongText(x *xorm.Engine) error {
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+
+ if setting.Database.Type.IsMySQL() {
+ if _, err := sess.Exec("ALTER TABLE `hook_task` CHANGE `payload_content` `payload_content` LONGTEXT, CHANGE `request_content` `request_content` LONGTEXT, change `response_content` `response_content` LONGTEXT"); err != nil {
+ return err
+ }
+ }
+ return sess.Commit()
+}
diff --git a/models/migrations/v1_17/v218.go b/models/migrations/v1_17/v218.go
new file mode 100644
index 0000000..4c05a9b
--- /dev/null
+++ b/models/migrations/v1_17/v218.go
@@ -0,0 +1,52 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+ "xorm.io/xorm/schemas"
+)
+
+type improveActionTableIndicesAction struct {
+ ID int64 `xorm:"pk autoincr"`
+ UserID int64 // Receiver user id.
+ OpType int
+ ActUserID int64 // Action user id.
+ RepoID int64
+ CommentID int64 `xorm:"INDEX"`
+ IsDeleted bool `xorm:"NOT NULL DEFAULT false"`
+ RefName string
+ IsPrivate bool `xorm:"NOT NULL DEFAULT false"`
+ Content string `xorm:"TEXT"`
+ CreatedUnix timeutil.TimeStamp `xorm:"created"`
+}
+
+// TableName sets the name of this table
+func (*improveActionTableIndicesAction) TableName() string {
+ return "action"
+}
+
+// TableIndices implements xorm's TableIndices interface
+func (*improveActionTableIndicesAction) TableIndices() []*schemas.Index {
+ repoIndex := schemas.NewIndex("r_u_d", schemas.IndexType)
+ repoIndex.AddColumn("repo_id", "user_id", "is_deleted")
+
+ actUserIndex := schemas.NewIndex("au_r_c_u_d", schemas.IndexType)
+ actUserIndex.AddColumn("act_user_id", "repo_id", "created_unix", "user_id", "is_deleted")
+ indices := []*schemas.Index{actUserIndex, repoIndex}
+ if setting.Database.Type.IsPostgreSQL() {
+ cudIndex := schemas.NewIndex("c_u_d", schemas.IndexType)
+ cudIndex.AddColumn("created_unix", "user_id", "is_deleted")
+ indices = append(indices, cudIndex)
+ }
+
+ return indices
+}
+
+func ImproveActionTableIndices(x *xorm.Engine) error {
+ return x.Sync(&improveActionTableIndicesAction{})
+}
diff --git a/models/migrations/v1_17/v219.go b/models/migrations/v1_17/v219.go
new file mode 100644
index 0000000..d266029
--- /dev/null
+++ b/models/migrations/v1_17/v219.go
@@ -0,0 +1,30 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ "time"
+
+ "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+)
+
+func AddSyncOnCommitColForPushMirror(x *xorm.Engine) error {
+ type PushMirror struct {
+ ID int64 `xorm:"pk autoincr"`
+ RepoID int64 `xorm:"INDEX"`
+ Repo *repo.Repository `xorm:"-"`
+ RemoteName string
+
+ SyncOnCommit bool `xorm:"NOT NULL DEFAULT true"`
+ Interval time.Duration
+ CreatedUnix timeutil.TimeStamp `xorm:"created"`
+ LastUpdateUnix timeutil.TimeStamp `xorm:"INDEX last_update"`
+ LastError string `xorm:"text"`
+ }
+
+ return x.Sync(new(PushMirror))
+}
diff --git a/models/migrations/v1_17/v220.go b/models/migrations/v1_17/v220.go
new file mode 100644
index 0000000..d400716
--- /dev/null
+++ b/models/migrations/v1_17/v220.go
@@ -0,0 +1,23 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ packages_model "code.gitea.io/gitea/models/packages"
+ container_module "code.gitea.io/gitea/modules/packages/container"
+
+ "xorm.io/xorm"
+ "xorm.io/xorm/schemas"
+)
+
+func AddContainerRepositoryProperty(x *xorm.Engine) (err error) {
+ if x.Dialect().URI().DBType == schemas.SQLITE {
+ _, err = x.Exec("INSERT INTO package_property (ref_type, ref_id, name, value) SELECT ?, p.id, ?, u.lower_name || '/' || p.lower_name FROM package p JOIN `user` u ON p.owner_id = u.id WHERE p.type = ?",
+ packages_model.PropertyTypePackage, container_module.PropertyRepository, packages_model.TypeContainer)
+ } else {
+ _, err = x.Exec("INSERT INTO package_property (ref_type, ref_id, name, value) SELECT ?, p.id, ?, CONCAT(u.lower_name, '/', p.lower_name) FROM package p JOIN `user` u ON p.owner_id = u.id WHERE p.type = ?",
+ packages_model.PropertyTypePackage, container_module.PropertyRepository, packages_model.TypeContainer)
+ }
+ return err
+}
diff --git a/models/migrations/v1_17/v221.go b/models/migrations/v1_17/v221.go
new file mode 100644
index 0000000..9e15938
--- /dev/null
+++ b/models/migrations/v1_17/v221.go
@@ -0,0 +1,74 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ "encoding/base32"
+ "fmt"
+
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+)
+
+func StoreWebauthnCredentialIDAsBytes(x *xorm.Engine) error {
+ // Create webauthnCredential table
+ type webauthnCredential struct {
+ ID int64 `xorm:"pk autoincr"`
+ Name string
+ LowerName string `xorm:"unique(s)"`
+ UserID int64 `xorm:"INDEX unique(s)"`
+ CredentialID string `xorm:"INDEX VARCHAR(410)"`
+ // Note the lack of INDEX here - these will be created once the column is renamed in v223.go
+ CredentialIDBytes []byte `xorm:"VARBINARY(1024)"` // CredentialID is at most 1023 bytes as per spec released 20 July 2022
+ PublicKey []byte
+ AttestationType string
+ AAGUID []byte
+ SignCount uint32 `xorm:"BIGINT"`
+ CloneWarning bool
+ CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
+ UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
+ }
+ if err := x.Sync(&webauthnCredential{}); err != nil {
+ return err
+ }
+
+ var start int
+ creds := make([]*webauthnCredential, 0, 50)
+ for {
+ err := x.Select("id, credential_id").OrderBy("id").Limit(50, start).Find(&creds)
+ if err != nil {
+ return err
+ }
+
+ err = func() error {
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return fmt.Errorf("unable to allow start session. Error: %w", err)
+ }
+ for _, cred := range creds {
+ cred.CredentialIDBytes, err = base32.HexEncoding.DecodeString(cred.CredentialID)
+ if err != nil {
+ return fmt.Errorf("unable to parse credential id %s for credential[%d]: %w", cred.CredentialID, cred.ID, err)
+ }
+ count, err := sess.ID(cred.ID).Cols("credential_id_bytes").Update(cred)
+ if count != 1 || err != nil {
+ return fmt.Errorf("unable to update credential id bytes for credential[%d]: %d,%w", cred.ID, count, err)
+ }
+ }
+ return sess.Commit()
+ }()
+ if err != nil {
+ return err
+ }
+
+ if len(creds) < 50 {
+ break
+ }
+ start += 50
+ creds = creds[:0]
+ }
+ return nil
+}
diff --git a/models/migrations/v1_17/v221_test.go b/models/migrations/v1_17/v221_test.go
new file mode 100644
index 0000000..0f6db2a
--- /dev/null
+++ b/models/migrations/v1_17/v221_test.go
@@ -0,0 +1,63 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ "encoding/base32"
+ "testing"
+
+ migration_tests "code.gitea.io/gitea/models/migrations/test"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func Test_StoreWebauthnCredentialIDAsBytes(t *testing.T) {
+ // Create webauthnCredential table
+ type WebauthnCredential struct {
+ ID int64 `xorm:"pk autoincr"`
+ Name string
+ LowerName string `xorm:"unique(s)"`
+ UserID int64 `xorm:"INDEX unique(s)"`
+ CredentialID string `xorm:"INDEX VARCHAR(410)"`
+ PublicKey []byte
+ AttestationType string
+ AAGUID []byte
+ SignCount uint32 `xorm:"BIGINT"`
+ CloneWarning bool
+ }
+
+ type ExpectedWebauthnCredential struct {
+ ID int64 `xorm:"pk autoincr"`
+ CredentialID string // CredentialID is at most 1023 bytes as per spec released 20 July 2022
+ }
+
+ type ConvertedWebauthnCredential struct {
+ ID int64 `xorm:"pk autoincr"`
+ CredentialIDBytes []byte `xorm:"VARBINARY(1024)"` // CredentialID is at most 1023 bytes as per spec released 20 July 2022
+ }
+
+ // Prepare and load the testing database
+ x, deferable := migration_tests.PrepareTestEnv(t, 0, new(WebauthnCredential), new(ExpectedWebauthnCredential))
+ defer deferable()
+ if x == nil || t.Failed() {
+ return
+ }
+
+ err := StoreWebauthnCredentialIDAsBytes(x)
+ require.NoError(t, err)
+
+ expected := []ExpectedWebauthnCredential{}
+ err = x.Table("expected_webauthn_credential").Asc("id").Find(&expected)
+ require.NoError(t, err)
+
+ got := []ConvertedWebauthnCredential{}
+ err = x.Table("webauthn_credential").Select("id, credential_id_bytes").Asc("id").Find(&got)
+ require.NoError(t, err)
+
+ for i, e := range expected {
+ credIDBytes, _ := base32.HexEncoding.DecodeString(e.CredentialID)
+ assert.Equal(t, credIDBytes, got[i].CredentialIDBytes)
+ }
+}
diff --git a/models/migrations/v1_17/v222.go b/models/migrations/v1_17/v222.go
new file mode 100644
index 0000000..2ffb94e
--- /dev/null
+++ b/models/migrations/v1_17/v222.go
@@ -0,0 +1,64 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ "context"
+ "fmt"
+
+ "code.gitea.io/gitea/models/migrations/base"
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+)
+
+func DropOldCredentialIDColumn(x *xorm.Engine) error {
+ // This migration maybe rerun so that we should check if it has been run
+ credentialIDExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webauthn_credential", "credential_id")
+ if err != nil {
+ return err
+ }
+ if !credentialIDExist {
+ // Column is already non-extant
+ return nil
+ }
+ credentialIDBytesExists, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webauthn_credential", "credential_id_bytes")
+ if err != nil {
+ return err
+ }
+ if !credentialIDBytesExists {
+ // looks like 221 hasn't properly run
+ return fmt.Errorf("webauthn_credential does not have a credential_id_bytes column... it is not safe to run this migration")
+ }
+
+ // Create webauthnCredential table
+ type webauthnCredential struct {
+ ID int64 `xorm:"pk autoincr"`
+ Name string
+ LowerName string `xorm:"unique(s)"`
+ UserID int64 `xorm:"INDEX unique(s)"`
+ CredentialID string `xorm:"INDEX VARCHAR(410)"`
+ // Note the lack of the INDEX on CredentialIDBytes - we will add this in v223.go
+ CredentialIDBytes []byte `xorm:"VARBINARY(1024)"` // CredentialID is at most 1023 bytes as per spec released 20 July 2022
+ PublicKey []byte
+ AttestationType string
+ AAGUID []byte
+ SignCount uint32 `xorm:"BIGINT"`
+ CloneWarning bool
+ CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
+ UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
+ }
+ if err := x.Sync(&webauthnCredential{}); err != nil {
+ return err
+ }
+
+ // Drop the old credential ID
+ sess := x.NewSession()
+ defer sess.Close()
+
+ if err := base.DropTableColumns(sess, "webauthn_credential", "credential_id"); err != nil {
+ return fmt.Errorf("unable to drop old credentialID column: %w", err)
+ }
+ return sess.Commit()
+}
diff --git a/models/migrations/v1_17/v223.go b/models/migrations/v1_17/v223.go
new file mode 100644
index 0000000..3592eb1
--- /dev/null
+++ b/models/migrations/v1_17/v223.go
@@ -0,0 +1,98 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_17 //nolint
+
+import (
+ "context"
+ "fmt"
+
+ "code.gitea.io/gitea/models/migrations/base"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+)
+
+func RenameCredentialIDBytes(x *xorm.Engine) error {
+ // This migration maybe rerun so that we should check if it has been run
+ credentialIDExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webauthn_credential", "credential_id")
+ if err != nil {
+ return err
+ }
+ if credentialIDExist {
+ credentialIDBytesExists, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webauthn_credential", "credential_id_bytes")
+ if err != nil {
+ return err
+ }
+ if !credentialIDBytesExists {
+ return nil
+ }
+ }
+
+ err = func() error {
+ // webauthnCredential table
+ type webauthnCredential struct {
+ ID int64 `xorm:"pk autoincr"`
+ Name string
+ LowerName string `xorm:"unique(s)"`
+ UserID int64 `xorm:"INDEX unique(s)"`
+ // Note the lack of INDEX here
+ CredentialIDBytes []byte `xorm:"VARBINARY(1024)"` // CredentialID is at most 1023 bytes as per spec released 20 July 2022
+ PublicKey []byte
+ AttestationType string
+ AAGUID []byte
+ SignCount uint32 `xorm:"BIGINT"`
+ CloneWarning bool
+ CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
+ UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
+ }
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+
+ if err := sess.Sync(new(webauthnCredential)); err != nil {
+ return fmt.Errorf("error on Sync: %w", err)
+ }
+
+ if credentialIDExist {
+ // if both errors and message exist, drop message at first
+ if err := base.DropTableColumns(sess, "webauthn_credential", "credential_id"); err != nil {
+ return err
+ }
+ }
+
+ if setting.Database.Type.IsMySQL() {
+ if _, err := sess.Exec("ALTER TABLE `webauthn_credential` CHANGE credential_id_bytes credential_id VARBINARY(1024)"); err != nil {
+ return err
+ }
+ } else {
+ if _, err := sess.Exec("ALTER TABLE `webauthn_credential` RENAME COLUMN credential_id_bytes TO credential_id"); err != nil {
+ return err
+ }
+ }
+ return sess.Commit()
+ }()
+ if err != nil {
+ return err
+ }
+
+ // Create webauthnCredential table
+ type webauthnCredential struct {
+ ID int64 `xorm:"pk autoincr"`
+ Name string
+ LowerName string `xorm:"unique(s)"`
+ UserID int64 `xorm:"INDEX unique(s)"`
+ CredentialID []byte `xorm:"INDEX VARBINARY(1024)"` // CredentialID is at most 1023 bytes as per spec released 20 July 2022
+ PublicKey []byte
+ AttestationType string
+ AAGUID []byte
+ SignCount uint32 `xorm:"BIGINT"`
+ CloneWarning bool
+ CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
+ UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
+ }
+ return x.Sync(&webauthnCredential{})
+}