Database updates (#144)

* start moving some database stuff around

* continue moving db stuff around

* more fiddling

* more updates

* and some more

* and yet more

* i broke SOMETHING but what, it's a mystery

* tidy up

* vendor ttlcache

* use ttlcache

* fix up some tests

* rename some stuff

* little reminder

* some more updates
This commit is contained in:
tobi
2021-08-20 12:26:56 +02:00
committed by GitHub
parent ce190d867c
commit 4920229a3b
164 changed files with 4850 additions and 2617 deletions

View File

@@ -45,11 +45,13 @@ type Account struct {
*/
// ID of the avatar as a media attachment
AvatarMediaAttachmentID string `pg:"type:CHAR(26)"`
AvatarMediaAttachmentID string `pg:"type:CHAR(26)"`
AvatarMediaAttachment *MediaAttachment `pg:"rel:has-one"`
// For a non-local account, where can the header be fetched?
AvatarRemoteURL string
// ID of the header as a media attachment
HeaderMediaAttachmentID string `pg:"type:CHAR(26)"`
HeaderMediaAttachmentID string `pg:"type:CHAR(26)"`
HeaderMediaAttachment *MediaAttachment `pg:"rel:has-one"`
// For a non-local account, where can the header be fetched?
HeaderRemoteURL string
// DisplayName for this account. Can be empty, then just the Username will be used for display purposes.

View File

@@ -31,7 +31,8 @@ type DomainBlock struct {
// When was this block updated
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
// Account ID of the creator of this block
CreatedByAccountID string `pg:"type:CHAR(26),notnull"`
CreatedByAccountID string `pg:"type:CHAR(26),notnull"`
CreatedByAccount *Account `pg:"rel:belongs-to"`
// Private comment on this block, viewable to admins
PrivateComment string
// Public comment on this block, viewable (optionally) by everyone

View File

@@ -31,5 +31,6 @@ type EmailDomainBlock struct {
// When was this block updated
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
// Account ID of the creator of this block
CreatedByAccountID string `pg:"type:CHAR(26),notnull"`
CreatedByAccountID string `pg:"type:CHAR(26),notnull"`
CreatedByAccount *Account `pg:"rel:belongs-to"`
}

View File

@@ -73,5 +73,6 @@ type Emoji struct {
// Is this emoji visible in the admin emoji picker?
VisibleInPicker bool `pg:",notnull,default:true"`
// In which emoji category is this emoji visible?
CategoryID string `pg:"type:CHAR(26)"`
CategoryID string `pg:"type:CHAR(26)"`
Status *Status `pg:"rel:belongs-to"`
}

View File

@@ -29,9 +29,11 @@ type Follow struct {
// When was this follow last updated?
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
// Who does this follow belong to?
AccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"`
AccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"`
Account *Account `pg:"rel:belongs-to"`
// Who does AccountID follow?
TargetAccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"`
TargetAccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"`
TargetAccount *Account `pg:"rel:has-one"`
// Does this follow also want to see reblogs and not just posts?
ShowReblogs bool `pg:"default:true"`
// What is the activitypub URI of this follow?

View File

@@ -29,9 +29,11 @@ type FollowRequest struct {
// When was this follow request last updated?
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
// Who does this follow request originate from?
AccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"`
AccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"`
Account Account `pg:"rel:has-one"`
// Who is the target of this follow request?
TargetAccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"`
TargetAccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"`
TargetAccount Account `pg:"rel:has-one"`
// Does this follow also want to see reblogs and not just posts?
ShowReblogs bool `pg:"default:true"`
// What is the activitypub URI of this follow request?

View File

@@ -19,7 +19,8 @@ type Instance struct {
// When was this instance suspended, if at all?
SuspendedAt time.Time
// ID of any existing domain block for this instance in the database
DomainBlockID string `pg:"type:CHAR(26)"`
DomainBlockID string `pg:"type:CHAR(26)"`
DomainBlock *DomainBlock `pg:"rel:has-one"`
// Short description of this instance
ShortDescription string
// Longer description of this instance
@@ -31,7 +32,8 @@ type Instance struct {
// Username of the contact account for this instance
ContactAccountUsername string
// Contact account ID in the database for this instance
ContactAccountID string `pg:"type:CHAR(26)"`
ContactAccountID string `pg:"type:CHAR(26)"`
ContactAccount *Account `pg:"rel:has-one"`
// Reputation score of this instance
Reputation int64 `pg:",notnull,default:0"`
// Version of the software used on this instance

View File

@@ -42,7 +42,8 @@ type MediaAttachment struct {
// Metadata about the file
FileMeta FileMeta
// To which account does this attachment belong
AccountID string `pg:"type:CHAR(26),notnull"`
AccountID string `pg:"type:CHAR(26),notnull"`
Account *Account `pg:"rel:belongs-to"`
// Description of the attachment (for screenreaders)
Description string
// To which scheduled status does this attachment belong

View File

@@ -25,17 +25,20 @@ type Mention struct {
// ID of this mention in the database
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
// ID of the status this mention originates from
StatusID string `pg:"type:CHAR(26),notnull"`
StatusID string `pg:"type:CHAR(26),notnull"`
Status *Status `pg:"rel:belongs-to"`
// When was this mention created?
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
// When was this mention last updated?
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
// What's the internal account ID of the originator of the mention?
OriginAccountID string `pg:"type:CHAR(26),notnull"`
OriginAccountID string `pg:"type:CHAR(26),notnull"`
OriginAccount *Account `pg:"rel:has-one"`
// What's the AP URI of the originator of the mention?
OriginAccountURI string `pg:",notnull"`
// What's the internal account ID of the mention target?
TargetAccountID string `pg:"type:CHAR(26),notnull"`
TargetAccountID string `pg:"type:CHAR(26),notnull"`
TargetAccount *Account `pg:"rel:has-one"`
// Prevent this mention from generating a notification?
Silent bool
@@ -52,14 +55,14 @@ type Mention struct {
//
// This will not be put in the database, it's just for convenience.
NameString string `pg:"-"`
// MentionedAccountURI is the AP ID (uri) of the user mentioned.
// TargetAccountURI is the AP ID (uri) of the user mentioned.
//
// This will not be put in the database, it's just for convenience.
MentionedAccountURI string `pg:"-"`
// MentionedAccountURL is the web url of the user mentioned.
TargetAccountURI string `pg:"-"`
// TargetAccountURL is the web url of the user mentioned.
//
// This will not be put in the database, it's just for convenience.
MentionedAccountURL string `pg:"-"`
TargetAccountURL string `pg:"-"`
// A pointer to the gtsmodel account of the mentioned account.
GTSAccount *Account `pg:"-"`
}

View File

@@ -29,24 +29,16 @@ type Notification struct {
// Creation time of this notification
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
// Which account does this notification target (ie., who will receive the notification?)
TargetAccountID string `pg:"type:CHAR(26),notnull"`
TargetAccountID string `pg:"type:CHAR(26),notnull"`
TargetAccount *Account `pg:"rel:has-one"`
// Which account performed the action that created this notification?
OriginAccountID string `pg:"type:CHAR(26),notnull"`
OriginAccountID string `pg:"type:CHAR(26),notnull"`
OriginAccount *Account `pg:"rel:has-one"`
// If the notification pertains to a status, what is the database ID of that status?
StatusID string `pg:"type:CHAR(26)"`
StatusID string `pg:"type:CHAR(26)"`
Status *Status `pg:"rel:has-one"`
// Has this notification been read already?
Read bool
/*
NON-DATABASE fields
*/
// gts model of the target account, won't be put in the database, it's just for convenience when passing the notification around.
GTSTargetAccount *Account `pg:"-"`
// gts model of the origin account, won't be put in the database, it's just for convenience when passing the notification around.
GTSOriginAccount *Account `pg:"-"`
// gts model of the relevant status, won't be put in the database, it's just for convenience when passing the notification around.
GTSStatus *Status `pg:"-"`
}
// NotificationType describes the reason/type of this notification.

View File

@@ -33,13 +33,17 @@ type Status struct {
// the html-formatted content of this status
Content string
// Database IDs of any media attachments associated with this status
Attachments []string `pg:",array"`
AttachmentIDs []string `pg:"attachments,array"`
Attachments []*MediaAttachment `pg:"attached_media,rel:has-many"`
// Database IDs of any tags used in this status
Tags []string `pg:",array"`
TagIDs []string `pg:"tags,array"`
Tags []*Tag `pg:"attached_tags,many2many:status_to_tags"` // https://pg.uptrace.dev/orm/many-to-many-relation/
// Database IDs of any mentions in this status
Mentions []string `pg:",array"`
MentionIDs []string `pg:"mentions,array"`
Mentions []*Mention `pg:"attached_mentions,rel:has-many"`
// Database IDs of any emojis used in this status
Emojis []string `pg:",array"`
EmojiIDs []string `pg:"emojis,array"`
Emojis []*Emoji `pg:"attached_emojis,many2many:status_to_emojis"` // https://pg.uptrace.dev/orm/many-to-many-relation/
// when was this status created?
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
// when was this status updated?
@@ -47,19 +51,24 @@ type Status struct {
// is this status from a local account?
Local bool
// which account posted this status?
AccountID string `pg:"type:CHAR(26),notnull"`
AccountID string `pg:"type:CHAR(26),notnull"`
Account *Account `pg:"rel:has-one"`
// AP uri of the owner of this status
AccountURI string
// id of the status this status is a reply to
InReplyToID string `pg:"type:CHAR(26)"`
InReplyToID string `pg:"type:CHAR(26)"`
InReplyTo *Status `pg:"rel:has-one"`
// AP uri of the status this status is a reply to
InReplyToURI string
// id of the account that this status replies to
InReplyToAccountID string `pg:"type:CHAR(26)"`
InReplyToAccountID string `pg:"type:CHAR(26)"`
InReplyToAccount *Account `pg:"rel:has-one"`
// id of the status this status is a boost of
BoostOfID string `pg:"type:CHAR(26)"`
BoostOfID string `pg:"type:CHAR(26)"`
BoostOf *Status `pg:"rel:has-one"`
// id of the account that owns the boosted status
BoostOfAccountID string `pg:"type:CHAR(26)"`
BoostOfAccountID string `pg:"type:CHAR(26)"`
BoostOfAccount *Account `pg:"rel:has-one"`
// cw string for this status
ContentWarning string
// visibility entry for this status
@@ -69,7 +78,8 @@ type Status struct {
// what language is this status written in?
Language string
// Which application was used to create this status?
CreatedWithApplicationID string `pg:"type:CHAR(26)"`
CreatedWithApplicationID string `pg:"type:CHAR(26)"`
CreatedWithApplication *Application `pg:"rel:has-one"`
// advanced visibility for this status
VisibilityAdvanced *VisibilityAdvanced
// What is the activitystreams type of this status? See: https://www.w3.org/TR/activitystreams-vocabulary/#object-types
@@ -79,32 +89,18 @@ type Status struct {
Text string
// Has this status been pinned by its owner?
Pinned bool
}
/*
INTERNAL MODEL NON-DATABASE FIELDS
// StatusToTag is an intermediate struct to facilitate the many2many relationship between a status and one or more tags.
type StatusToTag struct {
StatusID string `pg:"unique:statustag"`
TagID string `pg:"unique:statustag"`
}
These are for convenience while passing the status around internally,
but these fields should *never* be put in the db.
*/
// Account that created this status
GTSAuthorAccount *Account `pg:"-"`
// Mentions created in this status
GTSMentions []*Mention `pg:"-"`
// Hashtags used in this status
GTSTags []*Tag `pg:"-"`
// Emojis used in this status
GTSEmojis []*Emoji `pg:"-"`
// MediaAttachments used in this status
GTSMediaAttachments []*MediaAttachment `pg:"-"`
// Status being replied to
GTSReplyToStatus *Status `pg:"-"`
// Account being replied to
GTSReplyToAccount *Account `pg:"-"`
// Status being boosted
GTSBoostedStatus *Status `pg:"-"`
// Account of the boosted status
GTSBoostedAccount *Account `pg:"-"`
// StatusToEmoji is an intermediate struct to facilitate the many2many relationship between a status and one or more emojis.
type StatusToEmoji struct {
StatusID string `pg:"unique:statusemoji"`
EmojiID string `pg:"unique:statusemoji"`
}
// Visibility represents the visibility granularity of a status.

View File

@@ -27,9 +27,11 @@ type StatusBookmark struct {
// when was this bookmark created
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
// id of the account that created ('did') the bookmarking
AccountID string `pg:"type:CHAR(26),notnull"`
AccountID string `pg:"type:CHAR(26),notnull"`
Account *Account `pg:"rel:belongs-to"`
// id the account owning the bookmarked status
TargetAccountID string `pg:"type:CHAR(26),notnull"`
TargetAccountID string `pg:"type:CHAR(26),notnull"`
TargetAccount *Account `pg:"rel:has-one"`
// database id of the status that has been bookmarked
StatusID string `pg:"type:CHAR(26),notnull"`
}

View File

@@ -27,18 +27,14 @@ type StatusFave struct {
// when was this fave created
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
// id of the account that created ('did') the fave
AccountID string `pg:"type:CHAR(26),notnull"`
AccountID string `pg:"type:CHAR(26),notnull"`
Account *Account `pg:"rel:has-one"`
// id the account owning the faved status
TargetAccountID string `pg:"type:CHAR(26),notnull"`
TargetAccountID string `pg:"type:CHAR(26),notnull"`
TargetAccount *Account `pg:"rel:has-one"`
// database id of the status that has been 'faved'
StatusID string `pg:"type:CHAR(26),notnull"`
StatusID string `pg:"type:CHAR(26),notnull"`
Status *Status `pg:"rel:has-one"`
// ActivityPub URI of this fave
URI string `pg:",notnull"`
// GTSStatus is the status being interacted with. It won't be put or retrieved from the db, it's just for conveniently passing a pointer around.
GTSStatus *Status `pg:"-"`
// GTSTargetAccount is the account being interacted with. It won't be put or retrieved from the db, it's just for conveniently passing a pointer around.
GTSTargetAccount *Account `pg:"-"`
// GTSFavingAccount is the account doing the faving. It won't be put or retrieved from the db, it's just for conveniently passing a pointer around.
GTSFavingAccount *Account `pg:"-"`
}

View File

@@ -27,9 +27,12 @@ type StatusMute struct {
// when was this mute created
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
// id of the account that created ('did') the mute
AccountID string `pg:"type:CHAR(26),notnull"`
AccountID string `pg:"type:CHAR(26),notnull"`
Account *Account `pg:"rel:belongs-to"`
// id the account owning the muted status (can be the same as accountID)
TargetAccountID string `pg:"type:CHAR(26),notnull"`
TargetAccountID string `pg:"type:CHAR(26),notnull"`
TargetAccount *Account `pg:"rel:has-one"`
// database id of the status that has been muted
StatusID string `pg:"type:CHAR(26),notnull"`
StatusID string `pg:"type:CHAR(26),notnull"`
Status *Status `pg:"rel:has-one"`
}

View File

@@ -27,7 +27,7 @@ type Tag struct {
// Href of this tag, eg https://example.org/tags/somehashtag
URL string
// name of this tag -- the tag without the hash part
Name string `pg:",unique,pk,notnull"`
Name string `pg:",unique,notnull"`
// Which account ID is the first one we saw using this tag?
FirstSeenFromAccountID string `pg:"type:CHAR(26)"`
// when was this tag created

View File

@@ -35,7 +35,8 @@ type User struct {
// confirmed email address for this user, this should be unique -- only one email address registered per instance, multiple users per email are not supported
Email string `pg:"default:null,unique"`
// The id of the local gtsmodel.Account entry for this user, if it exists (unconfirmed users don't have an account yet)
AccountID string `pg:"type:CHAR(26),unique"`
AccountID string `pg:"type:CHAR(26),unique"`
Account *Account `pg:"rel:has-one"`
// The encrypted password of this user, generated using https://pkg.go.dev/golang.org/x/crypto/bcrypt#GenerateFromPassword. A salt is included so we're safe against 🌈 tables
EncryptedPassword string `pg:",notnull"`
@@ -68,7 +69,8 @@ type User struct {
// In what timezone/locale is this user located?
Locale string
// Which application id created this user? See gtsmodel.Application
CreatedByApplicationID string `pg:"type:CHAR(26)"`
CreatedByApplicationID string `pg:"type:CHAR(26)"`
CreatedByApplication *Application `pg:"rel:has-one"`
// When did we last contact this user
LastEmailedAt time.Time `pg:"type:timestamp"`