From f453983f808f02bed5c54a8115ff20386540040d Mon Sep 17 00:00:00 2001 From: mStar Date: Sat, 5 Apr 2025 22:01:42 +0200 Subject: [PATCH] Add inserter for self stuff --- storage-new/self.go | 154 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 storage-new/self.go diff --git a/storage-new/self.go b/storage-new/self.go new file mode 100644 index 0000000..b72a5ad --- /dev/null +++ b/storage-new/self.go @@ -0,0 +1,154 @@ +package storage + +import ( + "crypto/ed25519" + "crypto/rand" + "database/sql" + + "git.mstar.dev/mstar/goutils/other" + "github.com/google/uuid" + "github.com/rs/zerolog/log" + "gorm.io/gorm" + + "git.mstar.dev/mstar/linstrom/config" + "git.mstar.dev/mstar/linstrom/storage-new/dbgen" + "git.mstar.dev/mstar/linstrom/storage-new/models" +) + +func InsertSelf() error { + if err := insertRoles(); err != nil { + return other.Error("storage", "failed to save/update default roles", err) + } + duck, err := insertDefaultDuck() + if err != nil { + return other.Error("storage", "failed to save/update default duck", err) + } + server, err := insertServer(duck) + if err != nil { + return other.Error("storage", "failed to save/update self server", err) + } + log.Debug().Any("server", server).Send() + user, err := insertUser(server) + if err != nil { + return other.Error("storage", "failed to save/update self user", err) + } + if err = insertUserPronoun(user); err != nil { + return other.Error("storage", "failed to save/update self user pronoun", err) + } + return nil +} + +func insertRoles() error { + return dbgen.Role.Save(models.AllDefaultRoles...) +} + +func insertDefaultDuck() (*models.MediaMetadata, error) { + dbDuck, err := dbgen.MediaMetadata.Where(dbgen.MediaMetadata.Location.Eq(models.DefaultDuckLocationName)). + First() + if err == nil { + return dbDuck, nil + } else if err != gorm.ErrRecordNotFound { + return nil, err + } + duck := models.MediaMetadata{ + ID: uuid.NewString(), + // NOTE: Default duck technically belongs to the server + // but to avoid cyclic dependency, declare it as unowned + OwnedById: sql.NullString{Valid: false}, + Remote: false, + Location: models.DefaultDuckLocationName, + Type: "image/webp", + Name: "default-duck.webp", + AltText: "a greyscale image of a pidgeon on some smooth surface, likely a liquid. It is captioned with the text \"Duck\"", + Blurred: false, + } + if err := dbgen.MediaMetadata.Create(&duck); err != nil { + return nil, err + } + return &duck, nil +} + +func insertServer(duck *models.MediaMetadata) (*models.RemoteServer, error) { + dbServer, err := dbgen.RemoteServer.Where(dbgen.RemoteServer.ID.Eq(1)).First() + if err == nil { + return dbServer, nil + } else if err != gorm.ErrRecordNotFound { + return nil, err + } + server := models.RemoteServer{ + Model: gorm.Model{ + ID: 1, + }, + ServerType: models.ServerSoftwareLinstrom, + Domain: config.GlobalConfig.General.GetFullDomain(), + Name: config.GlobalConfig.Self.ServerDisplayName, + Icon: duck, + IconId: sql.NullString{String: duck.ID, Valid: true}, + IsSelf: true, + } + err = dbgen.RemoteServer.Save(&server) + if err != nil { + return nil, err + } + return &server, nil +} + +func insertUser(server *models.RemoteServer) (*models.User, error) { + dbUser, err := dbgen.User.GetByUsername("linstrom") + if err == nil { + return dbUser, nil + } + if err != gorm.ErrRecordNotFound { + return nil, err + } + publicKey, privateKey, err := ed25519.GenerateKey(nil) + pkeyId := make([]byte, 64) + _, err = rand.Read(pkeyId) + if err != nil { + return nil, other.Error( + "storage", + "failed to generate passkey ID for linstrom account", + err, + ) + } + user := models.User{ + Username: "linstrom", + Server: *server, + ServerId: server.ID, + DisplayName: config.GlobalConfig.Self.ServerActorDisplayName, + Description: "The default linstrom server user", + IsBot: true, + Icon: nil, + IconId: sql.NullString{Valid: false}, + Background: nil, + BackgroundId: sql.NullString{Valid: false}, + Banner: nil, + BannerId: sql.NullString{Valid: false}, + Indexable: false, + PublicKey: publicKey, + PrivateKey: privateKey, + Verified: true, + FinishedRegistration: true, + PasskeyId: pkeyId, + } + err = dbgen.User.Save(&user) + if err != nil { + return nil, err + } + return &user, err +} + +func insertUserPronoun(user *models.User) error { + _, err := dbgen.UserToPronoun.Where(dbgen.UserToPronoun.UserId.Eq(user.ID)). + Where(dbgen.UserToPronoun.Pronoun.Eq("Yes")).First() + switch err { + case nil: + return nil + case gorm.ErrRecordNotFound: + return dbgen.UserToPronoun.Create( + &models.UserToPronoun{UserId: user.ID, User: *user, Pronoun: "Yes"}, + ) + default: + return err + } +}