122 lines
3.1 KiB
Go
122 lines
3.1 KiB
Go
// TODO: Unify function names
|
|
|
|
// Storage is the handler for cache and db access
|
|
// It handles storing various data in the database as well as caching that data
|
|
// Said data includes notes, accounts, metadata about media files, servers and similar
|
|
package storage
|
|
|
|
import (
|
|
"crypto/ed25519"
|
|
"fmt"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
"gitlab.com/mstarongitlab/linstrom/config"
|
|
"gitlab.com/mstarongitlab/linstrom/storage/cache"
|
|
"gorm.io/driver/postgres"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// Always keep a reference of the server's own RemoteServer entry here
|
|
// Removes the need to perform a db request every time a new local anything
|
|
// is created
|
|
var serverSelf RemoteServer
|
|
|
|
// Storage is responsible for all database, cache and media related actions
|
|
// and serves as the lowest layer of the cake
|
|
type Storage struct {
|
|
db *gorm.DB
|
|
cache *cache.Cache
|
|
}
|
|
|
|
func NewStorage(dbUrl string, cache *cache.Cache) (*Storage, error) {
|
|
db, err := gorm.Open(postgres.Open(dbUrl), &gorm.Config{
|
|
Logger: newGormLogger(log.Logger),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = db.AutoMigrate(
|
|
MediaMetadata{},
|
|
Account{},
|
|
RemoteServer{},
|
|
Note{},
|
|
Role{},
|
|
PasskeySession{},
|
|
InboundJob{},
|
|
OutboundJob{},
|
|
AccessToken{},
|
|
Emote{},
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to apply migrations: %w", err)
|
|
}
|
|
|
|
s := &Storage{db, cache}
|
|
|
|
if err = s.insertSelfFromConfig(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return s, nil
|
|
}
|
|
|
|
func (s *Storage) insertSelfFromConfig() error {
|
|
const ServerActorId = "self"
|
|
|
|
var err error
|
|
|
|
// Insert server info
|
|
serverData := RemoteServer{}
|
|
err = s.db.Where("id = 1").
|
|
Attrs(RemoteServer{
|
|
Domain: config.GlobalConfig.General.GetFullDomain(),
|
|
}).
|
|
Assign(RemoteServer{
|
|
IsSelf: true,
|
|
Name: config.GlobalConfig.Self.ServerDisplayName,
|
|
// Icon: "", // TODO: Set to server icon media
|
|
}).FirstOrCreate(&serverData).Error
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// Set module specific global var
|
|
serverSelf = serverData
|
|
|
|
// Insert server actor
|
|
serverActor := Account{}
|
|
serverActorPublicKey, serverActorPrivateKey, err := ed25519.GenerateKey(nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = s.db.Where(Account{ID: ServerActorId}).
|
|
// Values to always (re)set after launch
|
|
Assign(Account{
|
|
DisplayName: config.GlobalConfig.Self.ServerActorDisplayName,
|
|
// Server: serverData,
|
|
ServerId: serverData.ID,
|
|
// CustomFields: []uint{},
|
|
Description: "Server actor of a Linstrom server",
|
|
// Tags: []string{},
|
|
IsBot: true,
|
|
// Followers: []string{},
|
|
// Follows: []string{},
|
|
// Icon: "", // TODO: Replace with reference to server icon
|
|
// Background: "", // TODO: Replace with reference to background media
|
|
// Banner: "", // TODO: Replace with reference to banner media
|
|
Indexable: false,
|
|
RestrictedFollow: false,
|
|
IdentifiesAs: []Being{},
|
|
Gender: []string{},
|
|
Roles: []string{}, // TODO: Add server actor role once created
|
|
}).
|
|
// Values that'll only be set on first creation
|
|
Attrs(Account{
|
|
PublicKey: serverActorPublicKey,
|
|
PrivateKey: serverActorPrivateKey,
|
|
}).
|
|
FirstOrCreate(&serverActor).Error
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|