Remove id autogeneration from db models

Remove automatic uuid v4 ID generation from the models and replace it
with `shared.NewId()`, which generates an Id depending on the config
setting
This commit is contained in:
Melody Becker 2025-05-06 14:34:32 +02:00
parent 412a8be600
commit e182949a8d
Signed by: mstar
SSH key fingerprint: SHA256:vkXfS9FG2pVNVfvDrzd1VW9n8VJzqqdKQGljxxX8uK8
9 changed files with 24 additions and 12 deletions

View file

@ -3,6 +3,7 @@ package config
import ( import (
"fmt" "fmt"
"os" "os"
"strings"
"git.mstar.dev/mstar/goutils/other" "git.mstar.dev/mstar/goutils/other"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
@ -131,12 +132,12 @@ type ConfigExperimental struct {
// if the other server also requires authorized fetch for the server actor // if the other server also requires authorized fetch for the server actor
// Changing this setting is not expected to cause permanent problems // Changing this setting is not expected to cause permanent problems
AuthFetchForServerActor bool `toml:"auth_fetch_for_server_actor"` AuthFetchForServerActor bool `toml:"auth_fetch_for_server_actor"`
// Use cuid2 for generation of new IDs that are expected to be used via Activitypub // Set the provider for ID generation.
// They are shorter than the main method used (uuid v4) but should still provide enough // Default is "xid".
// uniqueness such that collisions are not to be expected. // Options are "uuid", "cuid" and "xid"
// Changing this option will only affect new ID generations, not update existing ones // Changing this option will only affect new ID generations, not update existing ones
// As of now, even that doesn't work due to implementation details // As of now, even that doesn't work due to implementation details
UseCuid2Ids bool `toml:"use_cuid2_ids"` IdGenerator string `toml:"id_generator"`
} }
type Config struct { type Config struct {
@ -220,6 +221,7 @@ var defaultConfig Config = Config{
Experimental: ConfigExperimental{ Experimental: ConfigExperimental{
UseEd25519Keys: false, UseEd25519Keys: false,
AuthFetchForServerActor: false, AuthFetchForServerActor: false,
IdGenerator: "xid",
}, },
} }
@ -322,6 +324,7 @@ func ReadAndWriteToGlobal(fileName string) error {
log.Error().Err(err).Bytes("config-data-raw", data).Msg("Failed to unmarshal config file") log.Error().Err(err).Bytes("config-data-raw", data).Msg("Failed to unmarshal config file")
return err return err
} }
config.Experimental.IdGenerator = strings.ToLower(config.Experimental.IdGenerator)
GlobalConfig = config GlobalConfig = config
log.Info().Str("config-file", fileName).Msg("Read and applied config file") log.Info().Str("config-file", fileName).Msg("Read and applied config file")
return nil return nil

View file

@ -3,15 +3,21 @@ package shared
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/nrednav/cuid2" "github.com/nrednav/cuid2"
"github.com/rs/xid"
"git.mstar.dev/mstar/linstrom/config" "git.mstar.dev/mstar/linstrom/config"
) )
// Generate a new string ID // Generate a new string ID
func NewId() string { func NewId() string {
if config.GlobalConfig.Experimental.UseCuid2Ids { switch config.GlobalConfig.Experimental.IdGenerator {
return cuid2.Generate() case "uuid":
} else {
return uuid.NewString() return uuid.NewString()
case "cuid":
return cuid2.Generate()
case "xid":
return xid.New().String()
default:
return xid.New().String()
} }
} }

View file

@ -12,7 +12,7 @@ import (
// Instead, they are either stored on the remote server they originated from // Instead, they are either stored on the remote server they originated from
// or an s3 bucket if uploaded to Linstrom. // or an s3 bucket if uploaded to Linstrom.
type MediaMetadata struct { type MediaMetadata struct {
ID string `gorm:"primarykey;default:gen_random_uuid()"` // The unique ID of this media file ID string `gorm:"primarykey"` // The unique ID of this media file
CreatedAt time.Time // When this entry was created CreatedAt time.Time // When this entry was created
UpdatedAt time.Time // When this entry was last updated UpdatedAt time.Time // When this entry was last updated
// When this entry was deleted (for soft deletions) // When this entry was deleted (for soft deletions)

View file

@ -9,7 +9,7 @@ import (
// A note describes some user generated text content. // A note describes some user generated text content.
type Note struct { type Note struct {
ID string `gorm:"primarykey;default:gen_random_uuid()"` // Make ID a string (uuid) for other implementations ID string `gorm:"primarykey"` // Make ID a string for other implementations
CreatedAt time.Time // When this entry was created CreatedAt time.Time // When this entry was created
UpdatedAt time.Time // When this entry was last updated UpdatedAt time.Time // When this entry was last updated
// When this entry was deleted (for soft deletions) // When this entry was deleted (for soft deletions)

View file

@ -14,7 +14,7 @@ type AccessToken struct {
User User // The account the token belongs to User User // The account the token belongs to
UserId string UserId string
// The token itself is a uuid value // The token itself is a uuid value
Token string `gorm:"primarykey;type:uuid;default:gen_random_uuid()"` Token string `gorm:"primarykey"`
Name string // Token name will be empty if autogenerated with sucessful login Name string // Token name will be empty if autogenerated with sucessful login
// Every token expires, even if set to "not expire". If set to "not expire", it just expires // Every token expires, even if set to "not expire". If set to "not expire", it just expires
// at a point in the future this server should never reach // at a point in the future this server should never reach

View file

@ -10,7 +10,7 @@ type LoginProcessToken struct {
ID uint64 `gorm:"primarykey"` ID uint64 `gorm:"primarykey"`
User User User User
UserId string `gorm:"unique"` UserId string `gorm:"unique"`
Token string `gorm:"type:uuid;default:gen_random_uuid()"` Token string
Name string Name string
ExpiresAt time.Time ExpiresAt time.Time
} }

View file

@ -27,7 +27,7 @@ type User struct {
// Same also applies for other types that use a UUID as primary key // Same also applies for other types that use a UUID as primary key
// TODO: Change this to generate via cuid or uuid, depending on config // TODO: Change this to generate via cuid or uuid, depending on config
// Or remove autogeneration alltogether // Or remove autogeneration alltogether
ID string `gorm:"primarykey;default:gen_random_uuid()"` ID string `gorm:"primarykey"`
// Username of the user (eg "max" if the full username is @max@example.com) // Username of the user (eg "max" if the full username is @max@example.com)
// Assume unchangable (once set by a user) to be kind to other implementations // Assume unchangable (once set by a user) to be kind to other implementations
// Would be an easy avenue to fuck with them though // Would be an easy avenue to fuck with them though

View file

@ -129,6 +129,7 @@ func insertUser(
) )
} }
user := models.User{ user := models.User{
ID: shared.NewId(),
Username: shared.ServerActorName, Username: shared.ServerActorName,
Server: *server, Server: *server,
ServerId: server.ID, ServerId: server.ID,

View file

@ -129,6 +129,7 @@ func createLocalUser(w http.ResponseWriter, r *http.Request) {
u := dbgen.User u := dbgen.User
query := u.Select( query := u.Select(
u.ID,
u.Username, u.Username,
u.DisplayName, u.DisplayName,
u.Description, u.Description,
@ -149,6 +150,7 @@ func createLocalUser(w http.ResponseWriter, r *http.Request) {
query = query.Select(u.Location) query = query.Select(u.Location)
} }
user := models.User{ user := models.User{
ID: shared.NewId(),
Username: data.Username, Username: data.Username,
DisplayName: data.Displayname, DisplayName: data.Displayname,
Description: data.Description, Description: data.Description,