Comment all new code
Some checks are pending
/ test (push) Waiting to run

This commit is contained in:
Melody Becker 2025-04-02 15:33:07 +02:00
parent b6f12b7acf
commit 8f8ad3035a
Signed by: mstar
SSH key fingerprint: SHA256:9VAo09aaVNTWKzPW7Hq2LW+ox9OdwmTSHRoD4mlz1yI
33 changed files with 166 additions and 111 deletions

View file

@ -1,6 +1,6 @@
package models
// Just a list of all models stored in the database
// A list of all models stored in the database
var AllTypes = []any{
&Emote{},
&Feed{},

View file

@ -2,15 +2,17 @@ package models
import "gorm.io/gorm"
// An emote is effectively an assignment of a name and server
// Emotes are combinations of a name, the server it originated from
// and the media for it
//
// TODO: Include the case of unicode icons being used as emote
type Emote struct {
gorm.Model
// Media used for this emote
Metadata MediaMetadata // `gorm:"foreignKey:MetadataId"`
MetadataId string
gorm.Model // Standard gorm model for id and timestamps
Metadata MediaMetadata // The media used by this emote
MetadataId string // Id of the media information, primarily for gorm
// Name of the emote. Also the text for using it in a message (ex. :bob:)
Name string
// Server the emote is from
Server RemoteServer // `gorm:"foreignKey:ServerId;references:ID"`
ServerId uint
Server RemoteServer // Server the emote is from
ServerId uint // Id of the server
}

View file

@ -6,26 +6,27 @@ import (
"gorm.io/gorm"
)
// A feed is the initial entry point for all inbound Activitypub events.
// A feed is the initial entry point for inbound Activitypub events.
// However, its primary and only user-facing use case is to be a collection
// of inbound messages, nothing else.
//
// Thus, the flow for inbound events is the following:
// If the event is a note:
// Feeds are split into two groups, default and non-default.
// Default feeds are feeds automatically created for each user, where their normal
// timeline lives in. Additionally, they also relay inbound non-note events,
// such as likes/reactions, boosts or follow requests, to their owner.
// Default feeds also act using their owner's username (others would ge a follow request from
// `username@host`).
//
// Add it to the receiving feed. If it's a reply and the feed is a default
// create a notification for the owner
//
// If it's an event:
//
// If the feed is not a default feed for a user, discard the event
// If it is the default feed for a user, create a notification for the owner
// Non-default feeds, in comparison, are explicitly created by users and can be shared
// between them. Thus, they also only accept note events, dropping everything else.
// They also are explicitly labeled as such when issuing follow requests (ex `somename-feed@host`)
type Feed struct {
gorm.Model
// The name of the feed. Will be equal to the owner username if a default feed
Name string
Owner User
OwnerId string
IsDefault bool // Whether the feed is the default one for the user
Owner User // The owner of the feed
OwnerId string // Id of the owner
IsDefault bool // Whether the feed is the default one for the user
// If a feed is the default one for a user, use that user's public key.
// Otherwise, use its own key
PublicKey sql.NullString

View file

@ -6,9 +6,10 @@ import (
"gorm.io/gorm"
)
// Metadata for describing some media
// Media is, at least for Linstrom, always stored on a separate server,
// be that the remote server it originated from or an s3 bucket
// MediaMetadata contains metadata about some media file.
// These files are never stored directly by Linstrom.
// Instead, they are either stored on the remote server they originated from
// or an s3 bucket if uploaded to Linstrom.
type MediaMetadata struct {
ID string `gorm:"primarykey;type:uuid;default:gen_random_uuid()"` // The unique ID of this media file
CreatedAt time.Time // When this entry was created
@ -17,7 +18,7 @@ type MediaMetadata struct {
// Soft delete means that this entry still exists in the db, but gorm won't include it anymore unless specifically told to
// If not null, this entry is marked as deleted
DeletedAt gorm.DeletedAt `gorm:"index"`
OwnedBy string // Account id this media belongs to
OwnedById string // Account id this media belongs to
Remote bool // whether the attachment is a remote one
// Where the media is stored. Url
Location string

View file

@ -6,14 +6,7 @@ import (
"gorm.io/gorm"
)
// User created content, containing some message, maybe attachments,
// tags, pings or other extra things
//
// Data defined in extra structs (links are included at the bottom):
// - Attachments: models.NoteToAttachment
// - Emotes: models.NoteToEmote
// - Pings: models.NoteToPing
// - Tags: models.NoteTag
// A note describes some user generated text content.
type Note struct {
ID string `gorm:"primarykey;type:uuid;default:gen_random_uuid()"` // Make ID a string (uuid) for other implementations
CreatedAt time.Time // When this entry was created
@ -22,9 +15,9 @@ type Note struct {
// Soft delete means that this entry still exists in the db, but gorm won't include it anymore unless specifically told to
// If not null, this entry is marked as deleted
DeletedAt gorm.DeletedAt `gorm:"index"`
Creator User
CreatorId string
Remote bool // Whether the note is originally a remote one and just "cached"
Creator User // The user that created this note
CreatorId string // Id of the creator user
Remote bool // Whether the note is originally a remote one and just "cached"
// Raw content of the note. So without additional formatting applied
// Might already have formatting applied beforehand from the origin server
RawContent string
@ -34,8 +27,8 @@ type Note struct {
AccessLevel NoteAccessLevel // Where to send this message to (public, home, followers, dm)
OriginServer string // Url of the origin server. Also the primary key for those
AttachmentRelations []NoteToAttachment `gorm:"foreignKey:NoteId"`
EmoteRelations []NoteToEmote `gorm:"foreignKey:NoteId"`
PingRelations []NoteToPing `gorm:"foreignKey:NoteId"`
Tags []NoteTag `gorm:"foreignKey:NoteId"`
AttachmentRelations []NoteToAttachment `gorm:"foreignKey:NoteId"` // Attachments added on to this note
EmoteRelations []NoteToEmote `gorm:"foreignKey:NoteId"` // Emotes used in this note
PingRelations []NoteToPing `gorm:"foreignKey:NoteId"` // Pings/mentions this note performs
Tags []NoteTag `gorm:"foreignKey:NoteId"` // Tags this note contains
}

View file

@ -3,8 +3,8 @@ package models
// A binding of one note to one media attachment
type NoteToAttachment struct {
ID uint64 `gorm:"primarykey"`
Note Note
Note Note // The note being bound
NoteId string
Attachment MediaMetadata
Attachment MediaMetadata // The media being bound to
AttachmentId string
}

View file

@ -3,8 +3,8 @@ package models
// A binding of one note to one emote
type NoteToEmote struct {
ID uint64 `gorm:"primarykey"`
Note Note
Note Note // The note being bound
NoteId string
Emote Emote
Emote Emote // The emote being included
EmoteId string
}

View file

@ -17,11 +17,13 @@ import "time"
// Also need to store the boosts a user has performed somewhere
// Maybe adjust Reaction? Though a separate table might be a better option
// Assigns a note to a feed
// Assigns a note to a feed.
// Multiple notes may be assigned to multiple feeds, but each feed may contain
// one note at most once.
type NoteToFeed struct {
ID uint64 `gorm:"primarykey"`
CreatedAt time.Time
Note Note
Note Note // The note being assigned
NoteId string
// Feed Feed
// FeedId uint64

View file

@ -1,10 +1,12 @@
package models
// A binding of one note to one mentioned account
// A binding of one note to one mentioned account.
// A note may ping multiple users, but each ping wil be stored
// at most once
type NoteToPing struct {
ID uint64 `gorm:"primarykey"`
Note Note
Note Note // The note mentioning an account
NoteId string
PingTarget User
PingTarget User // The account being mentioned
PingTargetId string
}

View file

@ -1,9 +1,11 @@
package models
// A binding of one note to one string (hash)tag
// A binding of one note to one string (hash)tag.
// A note may contain multiple tags, but each tag will be stored at most
// once per note
type NoteTag struct {
ID uint64 `gorm:"primarykey"`
Note Note
Note Note // The note containing a tag
NoteId string
Tag string
Tag string // The tag contained
}

View file

@ -2,7 +2,7 @@ package models
import "gorm.io/gorm"
// A binding of one note to one account reacting to it with one emote
// A Reaction is a user liking a note using an emote
type Reaction struct {
gorm.Model
Note Note

View file

@ -1,6 +1,10 @@
package models
import "gorm.io/gorm"
import (
"database/sql"
"gorm.io/gorm"
)
// RemoteServer describes an ActivityPub server
// This includes self too
@ -9,7 +13,7 @@ type RemoteServer struct {
ServerType ServerSoftwareType // What software the server is running. Useful for formatting
Domain string // `gorm:"primaryKey"` // Domain the server exists under. Additional primary key
Name string // What the server wants to be known as (usually same as url)
Icon MediaMetadata
IconId string // ID of a media file
IsSelf bool // Whether this server is yours truly
Icon *MediaMetadata // The icon used by the server. May be empty
IconId sql.NullString // ID of a media file
IsSelf bool // Whether this server is yours truly
}

View file

@ -8,18 +8,19 @@ import (
type ServerSoftwareType string
const (
// Includes forks like glitch-soc, etc
// Mastodon and forks (glitch-soc, etc)
ServerSoftwareMastodon = ServerSoftwareType("Mastodon")
// Includes forks like Ice Shrimp, Sharkey, Cutiekey, etc
// Misskey and forks (Ice Shrimp, Sharkey, Cutiekey, etc)
ServerSoftwareMisskey = ServerSoftwareType("Misskey")
// Includes Akkoma
// Plemora and Akkoma
ServerSoftwarePlemora = ServerSoftwareType("Plemora")
// Wafrn is a new entry
// Wafrn with no known forks
ServerSoftwareWafrn = ServerSoftwareType("Wafrn")
// And of course, yours truly
// Linstrom with no known forks
ServerSoftwareLinstrom = ServerSoftwareType("Linstrom")
)
// A list of all known server software systems
var AllServerSoftwareTypes = []ServerSoftwareType{
ServerSoftwareMastodon,
ServerSoftwareMisskey,

View file

@ -2,21 +2,19 @@ package models
import (
"time"
"gorm.io/gen"
)
// AccessToken maps a unique token to one account.
// Access to server resource may only happen with a valid access token.
// Access tokens are granted by [auth-new/auth.Authenticator].
// Each account may have multiple access tokens at any time
type AccessToken struct {
User User
User User // The account the token belongs to
UserId string
Token string `gorm:"primarykey;type:uuid;default:gen_random_uuid()"`
Name string // Token name will be empty if autogenerated with sucessful login
// The token itself is a uuid value
Token string `gorm:"primarykey;type:uuid;default:gen_random_uuid()"`
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
// at a point in the future this server should never reach
ExpiresAt time.Time `gorm:"default:TIMESTAMP WITH TIME ZONE '9999-12-30 23:59:59+00'"`
}
type IAccessToken interface {
// INSERT INTO @@table (user_id, token, name, {{if expiresAt != nil}}, )
NewToken(user *User, name string, expiresAt *time.Time) (gen.T, error)
}

View file

@ -2,10 +2,10 @@ package models
import "time"
// A token used during the login process
// Each user may only have at most one login process active at the same time
// Technically, that could be used to permanently block someone from logging in
// by starting a new login process every time the target has just started one
// A LoginProcessToken contains a token used during the login process.
// Login tokens are used during login to identify and track the login process
// if said process involves multiple steps (2fa and passkey)..
// Each user may have multiple active login processes at the same time.
type LoginProcessToken struct {
ID uint64 `gorm:"primarykey"`
User User

View file

@ -7,11 +7,11 @@ import (
"gorm.io/gorm"
)
// A user describes an account for creating content.
// A user describes an account for creating content and events.
// This may be controlled by either a human or some external script
//
// Data stored externally:
// - Feed connections (which note belongs in the feed of this user, for what reason)
// - Feed connections (which note belongs in the feed of this user, for what reason), see [NoteToFeed]
type User struct {
// ID is a uuid for this account
//

View file

@ -6,13 +6,15 @@ import "database/sql/driver"
type AuthenticationMethodType string
const (
AuthMethodPassword AuthenticationMethodType = "password"
AuthMethodGAuth AuthenticationMethodType = "g-auth" // Google Authenticator / totp
AuthMethodMail AuthenticationMethodType = "mail"
AuthMethodPasskey2fa AuthenticationMethodType = "passkey-2fa" // Passkey used as 2fa factor
AuthMethodPassword AuthenticationMethodType = "password" // Password based authentication
AuthMethodGAuth AuthenticationMethodType = "g-auth" // Totp based 2nd factor
AuthMethodMail AuthenticationMethodType = "mail" // Mail based 2nd factor. Unused
AuthMethodPasskey2fa AuthenticationMethodType = "passkey-2fa" // Passkey based 2nd factor. Unused
AuthMethodPasskey AuthenticationMethodType = "passkey" // Passkey as only auth key
)
// A list of all known authentication methods.
// Known != supported
var AllAuthMethods = []AuthenticationMethodType{
AuthMethodPassword, AuthMethodGAuth, AuthMethodMail, AuthMethodPasskey, AuthMethodPasskey2fa,
}

View file

@ -10,12 +10,12 @@ import (
type BeingType string
const (
BEING_HUMAN = BeingType("human")
BEING_CAT = BeingType("cat")
BEING_FOX = BeingType("fox")
BEING_DOG = BeingType("dog")
BEING_ROBOT = BeingType("robot")
BEING_DOLL = BeingType("doll")
BEING_HUMAN = BeingType("human") // Is a human
BEING_CAT = BeingType("cat") // Is a cat
BEING_FOX = BeingType("fox") // Is a fox
BEING_DOG = BeingType("dog") // Is a dog
BEING_ROBOT = BeingType("robot") // Is a robot
BEING_DOLL = BeingType("doll") // Is a doll
)
var AllBeings = []BeingType{BEING_HUMAN, BEING_CAT, BEING_FOX, BEING_DOG, BEING_ROBOT, BEING_DOLL}

View file

@ -1,7 +1,9 @@
package models
// Defines an account to be a being of the set type
// Multiple are possible for combination
// Defines an user to be a being of the set type
// Each user may have multiple mappings
//
// TODO: Decide whether Being here could be changed to an open string instead
type UserToBeing struct {
ID uint64 `gorm:"primarykey"`
User User

View file

@ -6,7 +6,8 @@ import (
"gorm.io/gorm"
)
// One key-value field attached to an account
// A UserInfoField describes one custom key-value information field.
// Each user may have none, one or more of these fields.
// If the value is an uri, the server may attempt to verify ownership
// over that uri by checking the content for a `rel="me"` anchor
// linking back to the account the field is attached to

View file

@ -6,14 +6,14 @@ import "database/sql/driver"
type RelationType string
const (
RelationFollow RelationType = "follow"
RelationMute RelationType = "mute"
RelationNoBoosts RelationType = "no-boosts"
RelationBlock RelationType = "block"
RelationPreventFollow RelationType = "prevent-follow"
RelationFollow RelationType = "follow" // X follows Y
RelationMute RelationType = "mute" // X has Y muted (X doesn't see Y, but Y still X)
RelationNoBoosts RelationType = "no-boosts" // X has Ys boosts muted
RelationBlock RelationType = "block" // X has Y blocked (X doesn't see Y and Y doesn't see X)
RelationPreventFollow RelationType = "prevent-follow" // X blocks Y from following (Y can still see X)
)
// var AllBeings = []BeingType{BEING_HUMAN, BEING_CAT, BEING_FOX, BEING_DOG, BEING_ROBOT, BEING_DOLL}
// List of all relation types known
var AllRelations = []RelationType{
RelationFollow,
RelationMute,

View file

@ -2,7 +2,7 @@ package models
import "gorm.io/gorm"
// "Cached" extra data for accounts, in case they are remote
// UserRemoteLinks contains cached links for remote users
type UserRemoteLinks struct {
// ---- Section: gorm
// Sets this struct up as a value that an Account may have

View file

@ -1,7 +1,8 @@
package models
// A (hash)tag appearing on an account's profile description
// Accounts may have multiple tags, but each tag may only be stored once at most
// Users may have multiple tags, but each user to tag relation may only
// appear at most once
type UserToTag struct {
ID uint64 `gorm:"primarykey"`
User User

View file

@ -1,5 +1,8 @@
package models
// Adds one pronoun to a user.
// Each user may have zero, one or more pronouns
// but each user to pronoun relation may appear at most once
type UserToPronoun struct {
ID uint64 `gorm:"primarykey"`
User User

View file

@ -1,8 +1,9 @@
package models
// A link of one account to one role
// There may be multiple of these links per user and per role
// But a role may only be linked at most once to the same user
// Each user may have one or more roles
// (every user has the default role and their personal one)
// but each user to role combination may appear at most once
type UserToRole struct {
ID uint64 `gorm:"primarykey"`
User User

View file

@ -5,9 +5,9 @@ package models
// each describing a different aspect
type UserToUserRelation struct {
ID uint64 `gorm:"primarykey"`
User User
User User // The user X described in [RelationType]
UserId string
TargetUser User
TargetUser User // The user Y described in [RelationType]
TargetUserId string
Relation RelationType `gorm:"type:relation_type"`
}