127 lines
3.1 KiB
Go
127 lines
3.1 KiB
Go
package storage
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"git.mstar.dev/mstar/goutils/other"
|
|
"git.mstar.dev/mstar/goutils/sliceutils"
|
|
"gorm.io/gorm"
|
|
|
|
"git.mstar.dev/mstar/linstrom/storage-new/models"
|
|
)
|
|
|
|
func Migrate(db *gorm.DB) error {
|
|
if err := createAccountAuthMethodType(db); err != nil {
|
|
return other.Error("storage", "Failed to create Auth Method type", err)
|
|
}
|
|
if err := createBeingType(db); err != nil {
|
|
return other.Error("storage", "Failed to create Being type", err)
|
|
}
|
|
if err := createAccountRelationType(db); err != nil {
|
|
return other.Error("storage", "Failed to create Account Relation type", err)
|
|
}
|
|
if err := createRemoteServerSoftwareType(db); err != nil {
|
|
return other.Error("storage", "Failed to create Server Software type", err)
|
|
}
|
|
if err := migrateTypes(db); err != nil {
|
|
return other.Error("storage", "Failed to automigrate data structs", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Returns the raw error created by gorm, with no wrapping
|
|
func migrateTypes(db *gorm.DB) error {
|
|
if err := db.AutoMigrate(
|
|
&models.Emote{},
|
|
&models.MediaMetadata{},
|
|
&models.Note{},
|
|
&models.NoteToAttachment{},
|
|
&models.NoteToEmote{},
|
|
&models.NoteToPing{},
|
|
&models.NoteTag{},
|
|
&models.Reaction{},
|
|
&models.RemoteServer{},
|
|
&models.Role{},
|
|
&models.User{},
|
|
&models.UserAuthMethod{},
|
|
&models.UserToBeing{},
|
|
&models.UserInfoField{},
|
|
&models.UserToUserRelation{},
|
|
&models.UserRemoteLinks{},
|
|
&models.UserToRole{},
|
|
&models.UserToTag{},
|
|
); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Ensure the being enum exists for the user
|
|
func createBeingType(db *gorm.DB) error {
|
|
return migrateEnum(
|
|
db,
|
|
"being_type",
|
|
sliceutils.Map(models.AllBeings, func(t models.BeingType) string { return string(t) }),
|
|
)
|
|
}
|
|
|
|
func createAccountRelationType(db *gorm.DB) error {
|
|
return migrateEnum(
|
|
db,
|
|
"relation_type",
|
|
sliceutils.Map(
|
|
models.AllRelations,
|
|
func(t models.RelationType) string { return string(t) },
|
|
),
|
|
)
|
|
}
|
|
|
|
func createAccountAuthMethodType(db *gorm.DB) error {
|
|
return migrateEnum(
|
|
db,
|
|
"auth_method_type",
|
|
sliceutils.Map(
|
|
models.AllAuthMethods,
|
|
func(t models.AuthenticationMethodType) string { return string(t) },
|
|
),
|
|
)
|
|
}
|
|
|
|
func createRemoteServerSoftwareType(db *gorm.DB) error {
|
|
return migrateEnum(
|
|
db,
|
|
"server_software_type",
|
|
sliceutils.Map(
|
|
models.AllServerSoftwareTypes,
|
|
func(t models.ServerSoftwareType) string { return string(t) },
|
|
),
|
|
)
|
|
}
|
|
|
|
// Helper function for ensuring the existence of an enum with the given values
|
|
func migrateEnum(db *gorm.DB, name string, values []string) error {
|
|
if err := db.Exec("DROP TYPE IF EXISTS " + name).Error; err != nil {
|
|
return other.Error(
|
|
"storage",
|
|
fmt.Sprintf("Failed to remove old type %s (if it exists)", name),
|
|
err,
|
|
)
|
|
}
|
|
queryBuilder := strings.Builder{}
|
|
queryBuilder.WriteString("CREATE TYPE")
|
|
queryBuilder.WriteString(name)
|
|
queryBuilder.WriteString("AS ENUM (")
|
|
blen := len(values)
|
|
for i, btype := range values {
|
|
queryBuilder.WriteString("'" + string(btype) + "'")
|
|
// Append comma everywhere except last entry
|
|
if i+1 < blen {
|
|
queryBuilder.WriteString(",")
|
|
}
|
|
}
|
|
if err := db.Exec(queryBuilder.String()).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|