code.gitea.io/gitea@v1.21.7/models/migrations/v1_13/v151.go (about) 1 // Copyright 2020 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package v1_13 //nolint 5 6 import ( 7 "context" 8 "fmt" 9 "strings" 10 11 "code.gitea.io/gitea/modules/log" 12 "code.gitea.io/gitea/modules/setting" 13 14 "xorm.io/xorm" 15 "xorm.io/xorm/schemas" 16 ) 17 18 func SetDefaultPasswordToArgon2(x *xorm.Engine) error { 19 switch { 20 case setting.Database.Type.IsMySQL(): 21 _, err := x.Exec("ALTER TABLE `user` ALTER passwd_hash_algo SET DEFAULT 'argon2';") 22 return err 23 case setting.Database.Type.IsPostgreSQL(): 24 _, err := x.Exec("ALTER TABLE `user` ALTER COLUMN passwd_hash_algo SET DEFAULT 'argon2';") 25 return err 26 case setting.Database.Type.IsMSSQL(): 27 // need to find the constraint and drop it, then recreate it. 28 sess := x.NewSession() 29 defer sess.Close() 30 if err := sess.Begin(); err != nil { 31 return err 32 } 33 res, err := sess.QueryString("SELECT [name] FROM sys.default_constraints WHERE parent_object_id=OBJECT_ID(?) AND COL_NAME(parent_object_id, parent_column_id)=?;", "user", "passwd_hash_algo") 34 if err != nil { 35 return err 36 } 37 if len(res) > 0 { 38 constraintName := res[0]["name"] 39 log.Error("Results of select constraint: %s", constraintName) 40 _, err := sess.Exec("ALTER TABLE [user] DROP CONSTRAINT " + constraintName) 41 if err != nil { 42 return err 43 } 44 _, err = sess.Exec("ALTER TABLE [user] ADD CONSTRAINT " + constraintName + " DEFAULT 'argon2' FOR passwd_hash_algo") 45 if err != nil { 46 return err 47 } 48 } else { 49 _, err := sess.Exec("ALTER TABLE [user] ADD DEFAULT('argon2') FOR passwd_hash_algo") 50 if err != nil { 51 return err 52 } 53 } 54 return sess.Commit() 55 56 case setting.Database.Type.IsSQLite3(): 57 // drop through 58 default: 59 log.Fatal("Unrecognized DB") 60 } 61 62 tables, err := x.DBMetas() 63 if err != nil { 64 return err 65 } 66 67 // Now for SQLite we have to recreate the table 68 var table *schemas.Table 69 tableName := "user" 70 71 for _, table = range tables { 72 if table.Name == tableName { 73 break 74 } 75 } 76 if table == nil || table.Name != tableName { 77 type User struct { 78 PasswdHashAlgo string `xorm:"NOT NULL DEFAULT 'argon2'"` 79 } 80 return x.Sync(new(User)) 81 } 82 column := table.GetColumn("passwd_hash_algo") 83 if column == nil { 84 type User struct { 85 PasswdHashAlgo string `xorm:"NOT NULL DEFAULT 'argon2'"` 86 } 87 return x.Sync(new(User)) 88 } 89 90 tempTableName := "tmp_recreate__user" 91 column.Default = "'argon2'" 92 93 createTableSQL, _, err := x.Dialect().CreateTableSQL(context.Background(), x.DB(), table, tempTableName) 94 if err != nil { 95 return err 96 } 97 98 sess := x.NewSession() 99 defer sess.Close() 100 if err := sess.Begin(); err != nil { 101 return err 102 } 103 if _, err := sess.Exec(createTableSQL); err != nil { 104 log.Error("Unable to create table %s. Error: %v\n", tempTableName, err, createTableSQL) 105 return err 106 } 107 for _, index := range table.Indexes { 108 if _, err := sess.Exec(x.Dialect().CreateIndexSQL(tempTableName, index)); err != nil { 109 log.Error("Unable to create indexes on temporary table %s. Error: %v", tempTableName, err) 110 return err 111 } 112 } 113 114 newTableColumns := table.Columns() 115 if len(newTableColumns) == 0 { 116 return fmt.Errorf("no columns in new table") 117 } 118 hasID := false 119 for _, column := range newTableColumns { 120 hasID = hasID || (column.IsPrimaryKey && column.IsAutoIncrement) 121 } 122 123 sqlStringBuilder := &strings.Builder{} 124 _, _ = sqlStringBuilder.WriteString("INSERT INTO `") 125 _, _ = sqlStringBuilder.WriteString(tempTableName) 126 _, _ = sqlStringBuilder.WriteString("` (`") 127 _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Name) 128 _, _ = sqlStringBuilder.WriteString("`") 129 for _, column := range newTableColumns[1:] { 130 _, _ = sqlStringBuilder.WriteString(", `") 131 _, _ = sqlStringBuilder.WriteString(column.Name) 132 _, _ = sqlStringBuilder.WriteString("`") 133 } 134 _, _ = sqlStringBuilder.WriteString(")") 135 _, _ = sqlStringBuilder.WriteString(" SELECT ") 136 if newTableColumns[0].Default != "" { 137 _, _ = sqlStringBuilder.WriteString("COALESCE(`") 138 _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Name) 139 _, _ = sqlStringBuilder.WriteString("`, ") 140 _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Default) 141 _, _ = sqlStringBuilder.WriteString(")") 142 } else { 143 _, _ = sqlStringBuilder.WriteString("`") 144 _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Name) 145 _, _ = sqlStringBuilder.WriteString("`") 146 } 147 148 for _, column := range newTableColumns[1:] { 149 if column.Default != "" { 150 _, _ = sqlStringBuilder.WriteString(", COALESCE(`") 151 _, _ = sqlStringBuilder.WriteString(column.Name) 152 _, _ = sqlStringBuilder.WriteString("`, ") 153 _, _ = sqlStringBuilder.WriteString(column.Default) 154 _, _ = sqlStringBuilder.WriteString(")") 155 } else { 156 _, _ = sqlStringBuilder.WriteString(", `") 157 _, _ = sqlStringBuilder.WriteString(column.Name) 158 _, _ = sqlStringBuilder.WriteString("`") 159 } 160 } 161 _, _ = sqlStringBuilder.WriteString(" FROM `") 162 _, _ = sqlStringBuilder.WriteString(tableName) 163 _, _ = sqlStringBuilder.WriteString("`") 164 165 if _, err := sess.Exec(sqlStringBuilder.String()); err != nil { 166 log.Error("Unable to set copy data in to temp table %s. Error: %v", tempTableName, err) 167 return err 168 } 169 170 // SQLite will drop all the constraints on the old table 171 if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { 172 log.Error("Unable to drop old table %s. Error: %v", tableName, err) 173 return err 174 } 175 176 for _, index := range table.Indexes { 177 if _, err := sess.Exec(x.Dialect().DropIndexSQL(tempTableName, index)); err != nil { 178 log.Error("Unable to drop indexes on temporary table %s. Error: %v", tempTableName, err) 179 return err 180 } 181 } 182 183 if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`", tempTableName, tableName)); err != nil { 184 log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) 185 return err 186 } 187 188 for _, index := range table.Indexes { 189 if _, err := sess.Exec(x.Dialect().CreateIndexSQL(tableName, index)); err != nil { 190 log.Error("Unable to recreate indexes on table %s. Error: %v", tableName, err) 191 return err 192 } 193 } 194 195 return sess.Commit() 196 }