Defaults and start of config

This commit is contained in:
mStar 2024-05-31 17:21:29 +02:00
parent 3086b0e9b4
commit 1fbdf7fc9d
6 changed files with 128 additions and 10 deletions

26
config/config.go Normal file
View file

@ -0,0 +1,26 @@
package config
type ConfigSSL struct {
HandleSSL bool // Whether Linstrom should handle SSL encryption itself
// If Linstrom is to handle SSL, whether it should use LetsEncrypt for certificates
UseLetsEncrypt *bool
// Path to the certificate if Linstrom is to handle SSL while not using LetsEncrypt
CertificateFile *string
// Mail adress to use in case of using LetsEncrypt
AdminMail *string
}
type ConfigGeneral struct {
Domain string // The domain this server operates under
}
type ConfigAdmin struct {
Username string
PasswordHash string
}
type Config struct {
General ConfigGeneral
SSL ConfigSSL
Admin ConfigAdmin
}

View file

@ -13,10 +13,21 @@ type MediaFile struct {
DeletedAt gorm.DeletedAt `gorm:"index"` DeletedAt gorm.DeletedAt `gorm:"index"`
Remote bool // whether the attachment is a remote one Remote bool // whether the attachment is a remote one
Link string // url if remote attachment, identifier if local Link string // url if remote attachment, identifier if local
Type string // What media type this is, eg image/png
// Whether this media has been cached locally // Whether this media has been cached locally
// Only really used for user and server icons, not attachments // Only really used for user and server icons, not attachments
// If true, Link will be read as file path. url otherwise
// Reason: Attachments would take way to much space considering that they are often only loaded a few times at most // Reason: Attachments would take way to much space considering that they are often only loaded a few times at most
// And caching a file for those few times would be a waste of storage // And caching a file for those few times would be a waste of storage
// Caching user and server icons locally however should reduce burden on remote servers by quite a bit though // Caching user and server icons locally however should reduce burden on remote servers by quite a bit though
LocallyCached bool LocallyCached bool
} }
// Placeholder media file. Acts as placeholder for media file fields that have not been initialised yet but need a value
var placeholderMediaFile = &MediaFile{
ID: "placeholder",
Remote: false,
Link: "placeholder", // TODO: Replace this with a file path to a staticly included image
Type: "image/png",
LocallyCached: true,
}

View file

@ -26,3 +26,19 @@ type Note struct {
OriginServer string // Url of the origin server. Also the primary key for those OriginServer string // Url of the origin server. Also the primary key for those
Tags []string `gorm:"serializer:json"` // Hashtags Tags []string `gorm:"serializer:json"` // Hashtags
} }
var placeholderNote = &Note{
ID: "placeholder",
Creator: "placeholder",
Remote: false,
RawContent: "placeholder",
ContentWarning: nil,
Attachments: []string{},
Emotes: []string{},
RepliesTo: nil,
Quotes: nil,
Target: NOTE_TARGET_HOME,
Pings: []string{},
OriginServer: "placeholder",
Tags: []string{},
}

View file

@ -16,3 +16,11 @@ type RemoteServer struct {
Icon string // ID of a media file Icon string // ID of a media file
IsSelf bool // Whether this server is yours truly IsSelf bool // Whether this server is yours truly
} }
var placeholderServer = &RemoteServer{
ID: "placeholder",
ServerType: REMOTE_SERVER_LINSTROM,
Name: "placeholder",
Icon: "placeholder",
IsSelf: false,
}

View file

@ -1,23 +1,26 @@
package storage package storage
import ( import (
"fmt"
"github.com/glebarez/sqlite" "github.com/glebarez/sqlite"
"gorm.io/driver/postgres" "gorm.io/driver/postgres"
"gorm.io/gorm" "gorm.io/gorm"
) )
// Storage is responsible for all database, cache and media related actions
// and serves as the lowest layer of the cake
type Storage struct { type Storage struct {
db *gorm.DB db *gorm.DB
} }
// Build a new storage using sqlite as database backend
func NewStorageSqlite(filePath string) (*Storage, error) { func NewStorageSqlite(filePath string) (*Storage, error) {
db, err := gorm.Open(sqlite.Open(filePath)) db, err := gorm.Open(sqlite.Open(filePath))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Storage{ return storageFromEmptyDb(db)
db: db,
}, nil
} }
func NewStoragePostgres(dbUrl string) (*Storage, error) { func NewStoragePostgres(dbUrl string) (*Storage, error) {
@ -25,6 +28,35 @@ func NewStoragePostgres(dbUrl string) (*Storage, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return storageFromEmptyDb(db)
}
func storageFromEmptyDb(db *gorm.DB) (*Storage, error) {
// AutoMigrate ensures the db is in a state where all the structs given here
// have their own tables and relations setup. It also updates tables if necessary
db.AutoMigrate(
placeholderMediaFile,
placeholderUser(),
placeholderNote,
placeholderServer,
)
// Afterwards add the placeholder entries for each table.
// FirstOrCreate either creates a new entry or retrieves the first matching one
// We only care about the creation if there is none yet, so no need to carry the result over
if res := db.FirstOrCreate(placeholderMediaFile); res.Error != nil {
return nil, fmt.Errorf("failed to add placeholder media file: %w", res.Error)
}
if res := db.FirstOrCreate(placeholderUser()); res.Error != nil {
return nil, fmt.Errorf("failed to add placeholder media file: %w", res.Error)
}
if res := db.FirstOrCreate(placeholderNote); res.Error != nil {
return nil, fmt.Errorf("failed to add placeholder media file: %w", res.Error)
}
if res := db.FirstOrCreate(placeholderServer); res.Error != nil {
return nil, fmt.Errorf("failed to add placeholder media file: %w", res.Error)
}
// And finally, build the actual storage struct
return &Storage{ return &Storage{
db: db, db: db,
}, nil }, nil

View file

@ -12,7 +12,8 @@ import (
// This can be a bot, remote or not // This can be a bot, remote or not
// If remote, this is used for caching the account // If remote, this is used for caching the account
type User struct { type User struct {
ID string `gorm:"primarykey"` // ID is the full handle, eg @max@example.com ID string `gorm:"primarykey"` // ID is a uuid for this account
Handle string // Handle is the full handle, eg @max@example.com
CreatedAt time.Time // When this entry was created CreatedAt time.Time // When this entry was created
UpdatedAt time.Time // When this account was last updated. Will also be used for refreshing remote accounts UpdatedAt time.Time // When this account was last updated. Will also be used for refreshing remote accounts
DeletedAt gorm.DeletedAt `gorm:"index"` DeletedAt gorm.DeletedAt `gorm:"index"`
@ -29,7 +30,7 @@ type User struct {
Background string // ID of a media file used as background image Background string // ID of a media file used as background image
Banner string // ID of a media file used as banner Banner string // ID of a media file used as banner
Indexable bool // Whether this account can be found by crawlers Indexable bool // Whether this account can be found by crawlers
PublicKeyPem string // The public key of the account PublicKeyPem *string // The public key of the account
// Whether this account restricts following // Whether this account restricts following
// If true, the owner must approve of a follow request first // If true, the owner must approve of a follow request first
RestrictedFollow bool RestrictedFollow bool
@ -58,10 +59,34 @@ type User struct {
func NewEmptyUser() *User { func NewEmptyUser() *User {
return &User{ return &User{
ID: uuid.NewString(), ID: uuid.NewString(),
CreatedAt: time.Now(), Handle: "placeholder",
UpdatedAt: time.Now(), Remote: false,
Remote: false, Server: "placeholder",
Server: "placeholder", DisplayName: "placeholder",
CustomFields: []uint{},
Description: "placeholder",
Tags: []string{},
IsBot: true,
Follows: []string{},
Followers: []string{},
Icon: "placeholder",
Background: "placeholder",
Banner: "placeholder",
Indexable: false,
PublicKeyPem: nil,
RestrictedFollow: false,
IdentifiesAs: []Being{BEING_ROBOT},
Gender: []string{"it", "its"},
PasswordHash: []byte("placeholder"),
TotpToken: []byte("placeholder"),
Passkeys: map[string]webauthn.Credential{},
PrivateKeyPem: nil,
} }
} }
func placeholderUser() *User {
tmp := NewEmptyUser()
tmp.ID = "placeholder"
return tmp
}