diff options
author | 2021-08-25 15:34:33 +0200 | |
---|---|---|
committer | 2021-08-25 15:34:33 +0200 | |
commit | 2dc9fc1626507bb54417fc4a1920b847cafb27a2 (patch) | |
tree | 4ddeac479b923db38090aac8bd9209f3646851c1 /internal/gtsmodel | |
parent | Manually approves followers (#146) (diff) | |
download | gotosocial-2dc9fc1626507bb54417fc4a1920b847cafb27a2.tar.xz |
Pg to bun (#148)
* start moving to bun
* changing more stuff
* more
* and yet more
* tests passing
* seems stable now
* more big changes
* small fix
* little fixes
Diffstat (limited to 'internal/gtsmodel')
-rw-r--r-- | internal/gtsmodel/account.go | 60 | ||||
-rw-r--r-- | internal/gtsmodel/application.go | 4 | ||||
-rw-r--r-- | internal/gtsmodel/block.go | 16 | ||||
-rw-r--r-- | internal/gtsmodel/domainblock.go | 14 | ||||
-rw-r--r-- | internal/gtsmodel/emaildomainblock.go | 12 | ||||
-rw-r--r-- | internal/gtsmodel/emoji.go | 33 | ||||
-rw-r--r-- | internal/gtsmodel/follow.go | 18 | ||||
-rw-r--r-- | internal/gtsmodel/followrequest.go | 18 | ||||
-rw-r--r-- | internal/gtsmodel/instance.go | 22 | ||||
-rw-r--r-- | internal/gtsmodel/mediaattachment.go | 20 | ||||
-rw-r--r-- | internal/gtsmodel/mention.go | 26 | ||||
-rw-r--r-- | internal/gtsmodel/messages.go | 32 | ||||
-rw-r--r-- | internal/gtsmodel/notification.go | 18 | ||||
-rw-r--r-- | internal/gtsmodel/routersession.go | 6 | ||||
-rw-r--r-- | internal/gtsmodel/status.go | 72 | ||||
-rw-r--r-- | internal/gtsmodel/statusbookmark.go | 14 | ||||
-rw-r--r-- | internal/gtsmodel/statusfave.go | 18 | ||||
-rw-r--r-- | internal/gtsmodel/statusmute.go | 16 | ||||
-rw-r--r-- | internal/gtsmodel/tag.go | 16 | ||||
-rw-r--r-- | internal/gtsmodel/user.go | 40 |
20 files changed, 241 insertions, 234 deletions
diff --git a/internal/gtsmodel/account.go b/internal/gtsmodel/account.go index 9673dcb2c..98d2dcfc9 100644 --- a/internal/gtsmodel/account.go +++ b/internal/gtsmodel/account.go @@ -18,8 +18,8 @@ // Package gtsmodel contains types used *internally* by GoToSocial and added/removed/selected from the database. // These types should never be serialized and/or sent out via public APIs, as they contain sensitive information. -// The annotation used on these structs is for handling them via the go-pg ORM (hence why they're in this db subdir). -// See here for more info on go-pg model annotations: https://pg.uptrace.dev/models/ +// The annotation used on these structs is for handling them via the bun-db ORM. +// See here for more info on bun model annotations: https://bun.uptrace.dev/guide/models.html package gtsmodel import ( @@ -34,24 +34,24 @@ type Account struct { */ // id of this account in the local database - ID string `pg:"type:CHAR(26),pk,notnull,unique"` + ID string `bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // Username of the account, should just be a string of [a-z0-9_]. Can be added to domain to create the full username in the form ``[username]@[domain]`` eg., ``user_96@example.org`` - Username string `pg:",notnull,unique:userdomain"` // username and domain should be unique *with* each other + Username string `bun:",notnull,unique:userdomain,nullzero"` // username and domain should be unique *with* each other // Domain of the account, will be null if this is a local account, otherwise something like ``example.org`` or ``mastodon.social``. Should be unique with username. - Domain string `pg:",unique:userdomain"` // username and domain should be unique *with* each other + Domain string `bun:",unique:userdomain,nullzero"` // username and domain should be unique *with* each other /* ACCOUNT METADATA */ // ID of the avatar as a media attachment - AvatarMediaAttachmentID string `pg:"type:CHAR(26)"` - AvatarMediaAttachment *MediaAttachment `pg:"rel:has-one"` + AvatarMediaAttachmentID string `bun:"type:CHAR(26),nullzero"` + AvatarMediaAttachment *MediaAttachment `bun:"rel:belongs-to"` // 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)"` - HeaderMediaAttachment *MediaAttachment `pg:"rel:has-one"` + HeaderMediaAttachmentID string `bun:"type:CHAR(26),nullzero"` + HeaderMediaAttachment *MediaAttachment `bun:"rel:belongs-to"` // 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. @@ -63,11 +63,11 @@ type Account struct { // Is this a memorial account, ie., has the user passed away? Memorial bool // This account has moved this account id in the database - MovedToAccountID string `pg:"type:CHAR(26)"` + MovedToAccountID string `bun:"type:CHAR(26),nullzero"` // When was this account created? - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // When was this account last updated? - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // Does this account identify itself as a bot? Bot bool // What reason was given for signing up when this account was created? @@ -78,36 +78,36 @@ type Account struct { */ // Does this account need an approval for new followers? - Locked bool `pg:",default:true,use_zero"` + Locked bool `bun:",default:true"` // Should this account be shown in the instance's profile directory? - Discoverable bool `pg:",default:false"` + Discoverable bool `bun:",default:false"` // Default post privacy for this account - Privacy Visibility `pg:",default:'public'"` + Privacy Visibility `bun:",default:'public'"` // Set posts from this account to sensitive by default? - Sensitive bool `pg:",default:false"` + Sensitive bool `bun:",default:false"` // What language does this account post in? - Language string `pg:",default:'en'"` + Language string `bun:",default:'en'"` /* ACTIVITYPUB THINGS */ // What is the activitypub URI for this account discovered by webfinger? - URI string `pg:",unique"` + URI string `bun:",unique,nullzero"` // At which URL can we see the user account in a web browser? - URL string `pg:",unique"` + URL string `bun:",unique,nullzero"` // Last time this account was located using the webfinger API. - LastWebfingeredAt time.Time `pg:"type:timestamp"` + LastWebfingeredAt time.Time `bun:",nullzero"` // Address of this account's activitypub inbox, for sending activity to - InboxURI string `pg:",unique"` + InboxURI string `bun:",unique,nullzero"` // Address of this account's activitypub outbox - OutboxURI string `pg:",unique"` + OutboxURI string `bun:",unique,nullzero"` // URI for getting the following list of this account - FollowingURI string `pg:",unique"` + FollowingURI string `bun:",unique,nullzero"` // URI for getting the followers list of this account - FollowersURI string `pg:",unique"` + FollowersURI string `bun:",unique,nullzero"` // URL for getting the featured collection list of this account - FeaturedCollectionURI string `pg:",unique"` + FeaturedCollectionURI string `bun:",unique,nullzero"` // What type of activitypub actor is this account? ActorType string // This account is associated with x account id @@ -129,15 +129,15 @@ type Account struct { */ // When was this account set to have all its media shown as sensitive? - SensitizedAt time.Time `pg:"type:timestamp"` + SensitizedAt time.Time `bun:",nullzero"` // When was this account silenced (eg., statuses only visible to followers, not public)? - SilencedAt time.Time `pg:"type:timestamp"` + SilencedAt time.Time `bun:",nullzero"` // When was this account suspended (eg., don't allow it to log in/post, don't accept media/posts from this account) - SuspendedAt time.Time `pg:"type:timestamp"` + SuspendedAt time.Time `bun:",nullzero"` // Should we hide this account's collections? HideCollections bool // id of the database entry that caused this account to become suspended -- can be an account ID or a domain block ID - SuspensionOrigin string `pg:"type:CHAR(26)"` + SuspensionOrigin string `bun:"type:CHAR(26),nullzero"` } // Field represents a key value field on an account, for things like pronouns, website, etc. @@ -146,5 +146,5 @@ type Account struct { type Field struct { Name string Value string - VerifiedAt time.Time `pg:"type:timestamp"` + VerifiedAt time.Time `bun:",nullzero"` } diff --git a/internal/gtsmodel/application.go b/internal/gtsmodel/application.go index 91287dff3..a6976eafd 100644 --- a/internal/gtsmodel/application.go +++ b/internal/gtsmodel/application.go @@ -22,7 +22,7 @@ package gtsmodel // It is used to authorize tokens etc, and is associated with an oauth client id in the database. type Application struct { // id of this application in the db - ID string `pg:"type:CHAR(26),pk,notnull"` + ID string `bun:"type:CHAR(26),pk,notnull"` // name of the application given when it was created (eg., 'tusky') Name string // website for the application given when it was created (eg., 'https://tusky.app') @@ -30,7 +30,7 @@ type Application struct { // redirect uri requested by the application for oauth2 flow RedirectURI string // id of the associated oauth client entity in the db - ClientID string `pg:"type:CHAR(26)"` + ClientID string `bun:"type:CHAR(26)"` // secret of the associated oauth client entity in the db ClientSecret string // scopes requested when this app was created diff --git a/internal/gtsmodel/block.go b/internal/gtsmodel/block.go index 32afede55..0c762837d 100644 --- a/internal/gtsmodel/block.go +++ b/internal/gtsmodel/block.go @@ -5,17 +5,17 @@ import "time" // Block refers to the blocking of one account by another. type Block struct { // id of this block in the database - ID string `pg:"type:CHAR(26),pk,notnull"` + ID string `bun:"type:CHAR(26),pk,notnull"` // When was this block created - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // When was this block updated - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // Who created this block? - AccountID string `pg:"type:CHAR(26),notnull"` - Account *Account `pg:"rel:has-one"` + AccountID string `bun:"type:CHAR(26),notnull"` + Account *Account `bun:"rel:belongs-to"` // Who is targeted by this block? - TargetAccountID string `pg:"type:CHAR(26),notnull"` - TargetAccount *Account `pg:"rel:has-one"` + TargetAccountID string `bun:"type:CHAR(26),notnull"` + TargetAccount *Account `bun:"rel:belongs-to"` // Activitypub URI for this block - URI string `pg:",notnull"` + URI string `bun:",notnull"` } diff --git a/internal/gtsmodel/domainblock.go b/internal/gtsmodel/domainblock.go index 1bed86d8f..03d5ab0af 100644 --- a/internal/gtsmodel/domainblock.go +++ b/internal/gtsmodel/domainblock.go @@ -23,16 +23,16 @@ import "time" // DomainBlock represents a federation block against a particular domain type DomainBlock struct { // ID of this block in the database - ID string `pg:"type:CHAR(26),pk,notnull,unique"` + ID string `bun:"type:CHAR(26),pk,notnull,unique"` // blocked domain - Domain string `pg:",pk,notnull,unique"` + Domain string `bun:",pk,notnull,unique"` // When was this block created - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // When was this block updated - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // Account ID of the creator of this block - CreatedByAccountID string `pg:"type:CHAR(26),notnull"` - CreatedByAccount *Account `pg:"rel:belongs-to"` + CreatedByAccountID string `bun:"type:CHAR(26),notnull"` + CreatedByAccount *Account `bun:"rel:belongs-to"` // Private comment on this block, viewable to admins PrivateComment string // Public comment on this block, viewable (optionally) by everyone @@ -40,5 +40,5 @@ type DomainBlock struct { // whether the domain name should appear obfuscated when displaying it publicly Obfuscate bool // if this block was created through a subscription, what's the subscription ID? - SubscriptionID string `pg:"type:CHAR(26)"` + SubscriptionID string `bun:"type:CHAR(26),nullzero"` } diff --git a/internal/gtsmodel/emaildomainblock.go b/internal/gtsmodel/emaildomainblock.go index 374454374..1919172fa 100644 --- a/internal/gtsmodel/emaildomainblock.go +++ b/internal/gtsmodel/emaildomainblock.go @@ -23,14 +23,14 @@ import "time" // EmailDomainBlock represents a domain that the server should automatically reject sign-up requests from. type EmailDomainBlock struct { // ID of this block in the database - ID string `pg:"type:CHAR(26),pk,notnull,unique"` + ID string `bun:"type:CHAR(26),pk,notnull,unique"` // Email domain to block. Eg. 'gmail.com' or 'hotmail.com' - Domain string `pg:",notnull"` + Domain string `bun:",notnull"` // When was this block created - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // When was this block updated - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // Account ID of the creator of this block - CreatedByAccountID string `pg:"type:CHAR(26),notnull"` - CreatedByAccount *Account `pg:"rel:belongs-to"` + CreatedByAccountID string `bun:"type:CHAR(26),notnull"` + CreatedByAccount *Account `bun:"rel:belongs-to"` } diff --git a/internal/gtsmodel/emoji.go b/internal/gtsmodel/emoji.go index f0996d1a3..3b02c14e7 100644 --- a/internal/gtsmodel/emoji.go +++ b/internal/gtsmodel/emoji.go @@ -23,16 +23,16 @@ import "time" // Emoji represents a custom emoji that's been uploaded through the admin UI, and is useable by instance denizens. type Emoji struct { // database ID of this emoji - ID string `pg:"type:CHAR(26),pk,notnull"` + ID string `bun:"type:CHAR(26),pk,notnull"` // String shortcode for this emoji -- the part that's between colons. This should be lowercase a-z_ // eg., 'blob_hug' 'purple_heart' Must be unique with domain. - Shortcode string `pg:",notnull,unique:shortcodedomain"` + Shortcode string `bun:",notnull,unique:shortcodedomain"` // Origin domain of this emoji, eg 'example.org', 'queer.party'. empty string for local emojis. - Domain string `pg:",notnull,default:'',use_zero,unique:shortcodedomain"` + Domain string `bun:",notnull,default:'',unique:shortcodedomain"` // When was this emoji created. Must be unique with shortcode. - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // When was this emoji updated - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // Where can this emoji be retrieved remotely? Null for local emojis. // For remote emojis, it'll be something like: // https://hackers.town/system/custom_emojis/images/000/049/842/original/1b74481204feabfd.png @@ -51,28 +51,27 @@ type Emoji struct { ImageStaticURL string // Path of the emoji image in the server storage system. Will be something like: // '/gotosocial/storage/6339820e-ef65-4166-a262-5a9f46adb1a7/emoji/original/bfa6c9c5-6c25-4ea4-98b4-d78b8126fb52.png' - ImagePath string `pg:",notnull"` + ImagePath string `bun:",notnull"` // Path of a static version of the emoji image in the server storage system. Will be something like: // '/gotosocial/storage/6339820e-ef65-4166-a262-5a9f46adb1a7/emoji/small/bfa6c9c5-6c25-4ea4-98b4-d78b8126fb52.png' - ImageStaticPath string `pg:",notnull"` + ImageStaticPath string `bun:",notnull"` // MIME content type of the emoji image // Probably "image/png" - ImageContentType string `pg:",notnull"` + ImageContentType string `bun:",notnull"` // MIME content type of the static version of the emoji image. - ImageStaticContentType string `pg:",notnull"` + ImageStaticContentType string `bun:",notnull"` // Size of the emoji image file in bytes, for serving purposes. - ImageFileSize int `pg:",notnull"` + ImageFileSize int `bun:",notnull"` // Size of the static version of the emoji image file in bytes, for serving purposes. - ImageStaticFileSize int `pg:",notnull"` + ImageStaticFileSize int `bun:",notnull"` // When was the emoji image last updated? - ImageUpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + ImageUpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // Has a moderation action disabled this emoji from being shown? - Disabled bool `pg:",notnull,default:false"` + Disabled bool `bun:",notnull,default:false"` // ActivityStreams uri of this emoji. Something like 'https://example.org/emojis/1234' - URI string `pg:",notnull,unique"` + URI string `bun:",notnull,unique"` // Is this emoji visible in the admin emoji picker? - VisibleInPicker bool `pg:",notnull,default:true"` + VisibleInPicker bool `bun:",notnull,default:true"` // In which emoji category is this emoji visible? - CategoryID string `pg:"type:CHAR(26)"` - Status *Status `pg:"rel:belongs-to"` + CategoryID string `bun:"type:CHAR(26),nullzero"` } diff --git a/internal/gtsmodel/follow.go b/internal/gtsmodel/follow.go index 8f169f8c4..3d3eb1f1b 100644 --- a/internal/gtsmodel/follow.go +++ b/internal/gtsmodel/follow.go @@ -23,21 +23,21 @@ import "time" // Follow represents one account following another, and the metadata around that follow. type Follow struct { // id of this follow in the database - ID string `pg:"type:CHAR(26),pk,notnull,unique"` + ID string `bun:"type:CHAR(26),pk,notnull,unique"` // When was this follow created? - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // When was this follow last updated? - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // Who does this follow belong to? - AccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"` - Account *Account `pg:"rel:belongs-to"` + AccountID string `bun:"type:CHAR(26),unique:srctarget,notnull"` + Account *Account `bun:"rel:belongs-to"` // Who does AccountID follow? - TargetAccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"` - TargetAccount *Account `pg:"rel:has-one"` + TargetAccountID string `bun:"type:CHAR(26),unique:srctarget,notnull"` + TargetAccount *Account `bun:"rel:belongs-to"` // Does this follow also want to see reblogs and not just posts? - ShowReblogs bool `pg:"default:true"` + ShowReblogs bool `bun:"default:true"` // What is the activitypub URI of this follow? - URI string `pg:",unique"` + URI string `bun:",unique"` // does the following account want to be notified when the followed account posts? Notify bool } diff --git a/internal/gtsmodel/followrequest.go b/internal/gtsmodel/followrequest.go index 752c7d0a2..5a6cb5e02 100644 --- a/internal/gtsmodel/followrequest.go +++ b/internal/gtsmodel/followrequest.go @@ -23,21 +23,21 @@ import "time" // FollowRequest represents one account requesting to follow another, and the metadata around that request. type FollowRequest struct { // id of this follow request in the database - ID string `pg:"type:CHAR(26),pk,notnull,unique"` + ID string `bun:"type:CHAR(26),pk,notnull,unique"` // When was this follow request created? - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // When was this follow request last updated? - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // Who does this follow request originate from? - AccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"` - Account Account `pg:"rel:has-one"` + AccountID string `bun:"type:CHAR(26),unique:frsrctarget,notnull"` + Account *Account `bun:"rel:belongs-to"` // Who is the target of this follow request? - TargetAccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"` - TargetAccount Account `pg:"rel:has-one"` + TargetAccountID string `bun:"type:CHAR(26),unique:frsrctarget,notnull"` + TargetAccount *Account `bun:"rel:belongs-to"` // Does this follow also want to see reblogs and not just posts? - ShowReblogs bool `pg:"default:true"` + ShowReblogs bool `bun:"default:true"` // What is the activitypub URI of this follow request? - URI string `pg:",unique"` + URI string `bun:",unique,nullzero"` // does the following account want to be notified when the followed account posts? Notify bool } diff --git a/internal/gtsmodel/instance.go b/internal/gtsmodel/instance.go index 7b453a0b3..5bfe942f7 100644 --- a/internal/gtsmodel/instance.go +++ b/internal/gtsmodel/instance.go @@ -5,22 +5,22 @@ import "time" // Instance represents a federated instance, either local or remote. type Instance struct { // ID of this instance in the database - ID string `pg:"type:CHAR(26),pk,notnull,unique"` + ID string `bun:"type:CHAR(26),pk,notnull,unique"` // Instance domain eg example.org - Domain string `pg:",pk,notnull,unique"` + Domain string `bun:",pk,notnull,unique"` // Title of this instance as it would like to be displayed. Title string // base URI of this instance eg https://example.org - URI string `pg:",notnull,unique"` + URI string `bun:",notnull,unique"` // When was this instance created in the db? - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // When was this instance last updated in the db? - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // When was this instance suspended, if at all? - SuspendedAt time.Time + SuspendedAt time.Time `bun:",nullzero"` // ID of any existing domain block for this instance in the database - DomainBlockID string `pg:"type:CHAR(26)"` - DomainBlock *DomainBlock `pg:"rel:has-one"` + DomainBlockID string `bun:"type:CHAR(26),nullzero"` + DomainBlock *DomainBlock `bun:"rel:belongs-to"` // Short description of this instance ShortDescription string // Longer description of this instance @@ -32,10 +32,10 @@ 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)"` - ContactAccount *Account `pg:"rel:has-one"` + ContactAccountID string `bun:"type:CHAR(26),nullzero"` + ContactAccount *Account `bun:"rel:belongs-to"` // Reputation score of this instance - Reputation int64 `pg:",notnull,default:0"` + Reputation int64 `bun:",notnull,default:0"` // Version of the software used on this instance Version string } diff --git a/internal/gtsmodel/mediaattachment.go b/internal/gtsmodel/mediaattachment.go index 0f12caaad..b767e538c 100644 --- a/internal/gtsmodel/mediaattachment.go +++ b/internal/gtsmodel/mediaattachment.go @@ -26,28 +26,28 @@ import ( // somewhere in storage and that can be retrieved and served by the router. type MediaAttachment struct { // ID of the attachment in the database - ID string `pg:"type:CHAR(26),pk,notnull,unique"` + ID string `bun:"type:CHAR(26),pk,notnull,unique"` // ID of the status to which this is attached - StatusID string `pg:"type:CHAR(26)"` + StatusID string `bun:"type:CHAR(26),nullzero"` // Where can the attachment be retrieved on *this* server URL string // Where can the attachment be retrieved on a remote server (empty for local media) RemoteURL string // When was the attachment created - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // When was the attachment last updated - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // Type of file (image/gif/audio/video) - Type FileType `pg:",notnull"` + Type FileType `bun:",notnull"` // Metadata about the file FileMeta FileMeta // To which account does this attachment belong - AccountID string `pg:"type:CHAR(26),notnull"` - Account *Account `pg:"rel:belongs-to"` + AccountID string `bun:"type:CHAR(26),notnull"` + Account *Account `bun:"rel:has-one"` // Description of the attachment (for screenreaders) Description string // To which scheduled status does this attachment belong - ScheduledStatusID string `pg:"type:CHAR(26)"` + ScheduledStatusID string `bun:"type:CHAR(26),nullzero"` // What is the generated blurhash of this attachment Blurhash string // What is the processing status of this attachment @@ -71,7 +71,7 @@ type File struct { // What is the size of the file in bytes. FileSize int // When was the file last updated. - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:"type:timestamp,notnull,default:current_timestamp"` } // Thumbnail refers to a small image thumbnail derived from a larger image, video, or audio file. @@ -83,7 +83,7 @@ type Thumbnail struct { // What is the size of the file in bytes FileSize int // When was the file last updated - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:"type:timestamp,notnull,default:current_timestamp"` // What is the URL of the thumbnail on the local server URL string // What is the remote URL of the thumbnail (empty for local media) diff --git a/internal/gtsmodel/mention.go b/internal/gtsmodel/mention.go index 931e681db..ce5977659 100644 --- a/internal/gtsmodel/mention.go +++ b/internal/gtsmodel/mention.go @@ -23,22 +23,22 @@ import "time" // Mention refers to the 'tagging' or 'mention' of a user within a status. type Mention struct { // ID of this mention in the database - ID string `pg:"type:CHAR(26),pk,notnull,unique"` + ID string `bun:"type:CHAR(26),pk,notnull,unique"` // ID of the status this mention originates from - StatusID string `pg:"type:CHAR(26),notnull"` - Status *Status `pg:"rel:belongs-to"` + StatusID string `bun:"type:CHAR(26),notnull"` + Status *Status `bun:"rel:belongs-to"` // When was this mention created? - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // When was this mention last updated? - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // What's the internal account ID of the originator of the mention? - OriginAccountID string `pg:"type:CHAR(26),notnull"` - OriginAccount *Account `pg:"rel:has-one"` + OriginAccountID string `bun:"type:CHAR(26),notnull"` + OriginAccount *Account `bun:"rel:belongs-to"` // What's the AP URI of the originator of the mention? - OriginAccountURI string `pg:",notnull"` + OriginAccountURI string `bun:",notnull"` // What's the internal account ID of the mention target? - TargetAccountID string `pg:"type:CHAR(26),notnull"` - TargetAccount *Account `pg:"rel:has-one"` + TargetAccountID string `bun:"type:CHAR(26),notnull"` + TargetAccount *Account `bun:"rel:belongs-to"` // Prevent this mention from generating a notification? Silent bool @@ -54,15 +54,15 @@ type Mention struct { // @whatever_username@example.org // // This will not be put in the database, it's just for convenience. - NameString string `pg:"-"` + NameString string `bun:"-"` // TargetAccountURI is the AP ID (uri) of the user mentioned. // // This will not be put in the database, it's just for convenience. - TargetAccountURI string `pg:"-"` + TargetAccountURI string `bun:"-"` // TargetAccountURL is the web url of the user mentioned. // // This will not be put in the database, it's just for convenience. - TargetAccountURL string `pg:"-"` + TargetAccountURL string `bun:"-"` // A pointer to the gtsmodel account of the mentioned account. } diff --git a/internal/gtsmodel/messages.go b/internal/gtsmodel/messages.go index 910c74898..62beb0adc 100644 --- a/internal/gtsmodel/messages.go +++ b/internal/gtsmodel/messages.go @@ -1,11 +1,22 @@ -package gtsmodel +/* + GoToSocial + Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. -// // ToClientAPI wraps a message that travels from the processor into the client API -// type ToClientAPI struct { -// APObjectType ActivityStreamsObject -// APActivityType ActivityStreamsActivity -// Activity interface{} -// } + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +package gtsmodel // FromClientAPI wraps a message that travels from client API into the processor type FromClientAPI struct { @@ -16,13 +27,6 @@ type FromClientAPI struct { TargetAccount *Account } -// // ToFederator wraps a message that travels from the processor into the federator -// type ToFederator struct { -// APObjectType ActivityStreamsObject -// APActivityType ActivityStreamsActivity -// GTSModel interface{} -// } - // FromFederator wraps a message that travels from the federator into the processor type FromFederator struct { APObjectType string diff --git a/internal/gtsmodel/notification.go b/internal/gtsmodel/notification.go index b85bc969e..14ab90802 100644 --- a/internal/gtsmodel/notification.go +++ b/internal/gtsmodel/notification.go @@ -23,20 +23,20 @@ import "time" // Notification models an alert/notification sent to an account about something like a reblog, like, new follow request, etc. type Notification struct { // ID of this notification in the database - ID string `pg:"type:CHAR(26),pk,notnull"` + ID string `bun:"type:CHAR(26),pk,notnull"` // Type of this notification - NotificationType NotificationType `pg:",notnull"` + NotificationType NotificationType `bun:",notnull"` // Creation time of this notification - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // Which account does this notification target (ie., who will receive the notification?) - TargetAccountID string `pg:"type:CHAR(26),notnull"` - TargetAccount *Account `pg:"rel:has-one"` + TargetAccountID string `bun:"type:CHAR(26),notnull"` + TargetAccount *Account `bun:"rel:belongs-to"` // Which account performed the action that created this notification? - OriginAccountID string `pg:"type:CHAR(26),notnull"` - OriginAccount *Account `pg:"rel:has-one"` + OriginAccountID string `bun:"type:CHAR(26),notnull"` + OriginAccount *Account `bun:"rel:belongs-to"` // If the notification pertains to a status, what is the database ID of that status? - StatusID string `pg:"type:CHAR(26)"` - Status *Status `pg:"rel:has-one"` + StatusID string `bun:"type:CHAR(26),nullzero"` + Status *Status `bun:"rel:belongs-to"` // Has this notification been read already? Read bool } diff --git a/internal/gtsmodel/routersession.go b/internal/gtsmodel/routersession.go index c0f8e1f4d..7f3bd85c3 100644 --- a/internal/gtsmodel/routersession.go +++ b/internal/gtsmodel/routersession.go @@ -20,7 +20,7 @@ package gtsmodel // RouterSession is used to store and retrieve settings for a router session. type RouterSession struct { - ID string `pg:"type:CHAR(26),pk,notnull"` - Auth []byte `pg:",notnull"` - Crypt []byte `pg:",notnull"` + ID string `bun:"type:CHAR(26),pk,notnull"` + Auth []byte `bun:"type:bytea,notnull"` + Crypt []byte `bun:"type:bytea,notnull"` } diff --git a/internal/gtsmodel/status.go b/internal/gtsmodel/status.go index 354f37e04..fd33bd788 100644 --- a/internal/gtsmodel/status.go +++ b/internal/gtsmodel/status.go @@ -25,61 +25,61 @@ import ( // Status represents a user-created 'post' or 'status' in the database, either remote or local type Status struct { // id of the status in the database - ID string `pg:"type:CHAR(26),pk,notnull"` + ID string `bun:"type:CHAR(26),pk,notnull"` // uri at which this status is reachable - URI string `pg:",unique"` + URI string `bun:",unique,nullzero"` // web url for viewing this status - URL string `pg:",unique"` + URL string `bun:",unique,nullzero"` // the html-formatted content of this status Content string // Database IDs of any media attachments associated with this status - AttachmentIDs []string `pg:"attachments,array"` - Attachments []*MediaAttachment `pg:"attached_media,rel:has-many"` + AttachmentIDs []string `bun:"attachments,array"` + Attachments []*MediaAttachment `bun:"attached_media,rel:has-many"` // Database IDs of any tags used in this status - TagIDs []string `pg:"tags,array"` - Tags []*Tag `pg:"attached_tags,many2many:status_to_tags"` // https://pg.uptrace.dev/orm/many-to-many-relation/ + TagIDs []string `bun:"tags,array"` + Tags []*Tag `bun:"attached_tags,m2m:status_to_tags"` // https://bun.uptrace.dev/guide/relations.html#many-to-many-relation // Database IDs of any mentions in this status - MentionIDs []string `pg:"mentions,array"` - Mentions []*Mention `pg:"attached_mentions,rel:has-many"` + MentionIDs []string `bun:"mentions,array"` + Mentions []*Mention `bun:"attached_mentions,rel:has-many"` // Database IDs of any emojis used in this status - EmojiIDs []string `pg:"emojis,array"` - Emojis []*Emoji `pg:"attached_emojis,many2many:status_to_emojis"` // https://pg.uptrace.dev/orm/many-to-many-relation/ + EmojiIDs []string `bun:"emojis,array"` + Emojis []*Emoji `bun:"attached_emojis,m2m:status_to_emojis"` // https://bun.uptrace.dev/guide/relations.html#many-to-many-relation // when was this status created? - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",notnull,nullzero,default:current_timestamp"` // when was this status updated? - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:",notnull,nullzero,default:current_timestamp"` // is this status from a local account? Local bool // which account posted this status? - AccountID string `pg:"type:CHAR(26),notnull"` - Account *Account `pg:"rel:has-one"` + AccountID string `bun:"type:CHAR(26),notnull"` + Account *Account `bun:"rel:belongs-to"` // 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)"` - InReplyTo *Status `pg:"rel:has-one"` + InReplyToID string `bun:"type:CHAR(26),nullzero"` + InReplyTo *Status `bun:"-"` // 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)"` - InReplyToAccount *Account `pg:"rel:has-one"` + InReplyToAccountID string `bun:"type:CHAR(26),nullzero"` + InReplyToAccount *Account `bun:"rel:belongs-to"` // id of the status this status is a boost of - BoostOfID string `pg:"type:CHAR(26)"` - BoostOf *Status `pg:"rel:has-one"` + BoostOfID string `bun:"type:CHAR(26),nullzero"` + BoostOf *Status `bun:"-"` // id of the account that owns the boosted status - BoostOfAccountID string `pg:"type:CHAR(26)"` - BoostOfAccount *Account `pg:"rel:has-one"` + BoostOfAccountID string `bun:"type:CHAR(26),nullzero"` + BoostOfAccount *Account `bun:"rel:belongs-to"` // cw string for this status ContentWarning string // visibility entry for this status - Visibility Visibility `pg:",notnull"` + Visibility Visibility `bun:",notnull"` // mark the status as sensitive? Sensitive bool // what language is this status written in? Language string // Which application was used to create this status? - CreatedWithApplicationID string `pg:"type:CHAR(26)"` - CreatedWithApplication *Application `pg:"rel:has-one"` + CreatedWithApplicationID string `bun:"type:CHAR(26),nullzero"` + CreatedWithApplication *Application `bun:"rel:belongs-to"` // 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 @@ -93,14 +93,18 @@ type Status struct { // 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"` + StatusID string `bun:"type:CHAR(26),unique:statustag,nullzero"` + Status *Status `bun:"rel:belongs-to"` + TagID string `bun:"type:CHAR(26),unique:statustag,nullzero"` + Tag *Tag `bun:"rel:belongs-to"` } // 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"` + StatusID string `bun:"type:CHAR(26),unique:statusemoji,nullzero"` + Status *Status `bun:"rel:belongs-to"` + EmojiID string `bun:"type:CHAR(26),unique:statusemoji,nullzero"` + Emoji *Emoji `bun:"rel:belongs-to"` } // Visibility represents the visibility granularity of a status. @@ -134,11 +138,11 @@ const ( // If DIRECT is selected, boostable will be FALSE, and all other flags will be TRUE. type VisibilityAdvanced struct { // This status will be federated beyond the local timeline(s) - Federated bool `pg:"default:true"` + Federated bool `bun:"default:true"` // This status can be boosted/reblogged - Boostable bool `pg:"default:true"` + Boostable bool `bun:"default:true"` // This status can be replied to - Replyable bool `pg:"default:true"` + Replyable bool `bun:"default:true"` // This status can be liked/faved - Likeable bool `pg:"default:true"` + Likeable bool `bun:"default:true"` } diff --git a/internal/gtsmodel/statusbookmark.go b/internal/gtsmodel/statusbookmark.go index 468939bae..26dafa420 100644 --- a/internal/gtsmodel/statusbookmark.go +++ b/internal/gtsmodel/statusbookmark.go @@ -23,15 +23,15 @@ import "time" // StatusBookmark refers to one account having a 'bookmark' of the status of another account type StatusBookmark struct { // id of this bookmark in the database - ID string `pg:"type:CHAR(26),pk,notnull,unique"` + ID string `bun:"type:CHAR(26),pk,notnull,unique"` // when was this bookmark created - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // id of the account that created ('did') the bookmarking - AccountID string `pg:"type:CHAR(26),notnull"` - Account *Account `pg:"rel:belongs-to"` + AccountID string `bun:"type:CHAR(26),notnull"` + Account *Account `bun:"rel:belongs-to"` // id the account owning the bookmarked status - TargetAccountID string `pg:"type:CHAR(26),notnull"` - TargetAccount *Account `pg:"rel:has-one"` + TargetAccountID string `bun:"type:CHAR(26),notnull"` + TargetAccount *Account `bun:"rel:belongs-to"` // database id of the status that has been bookmarked - StatusID string `pg:"type:CHAR(26),notnull"` + StatusID string `bun:"type:CHAR(26),notnull"` } diff --git a/internal/gtsmodel/statusfave.go b/internal/gtsmodel/statusfave.go index 17952673a..3b816af56 100644 --- a/internal/gtsmodel/statusfave.go +++ b/internal/gtsmodel/statusfave.go @@ -23,18 +23,18 @@ import "time" // StatusFave refers to a 'fave' or 'like' in the database, from one account, targeting the status of another account type StatusFave struct { // id of this fave in the database - ID string `pg:"type:CHAR(26),pk,notnull,unique"` + ID string `bun:"type:CHAR(26),pk,notnull,unique"` // when was this fave created - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // id of the account that created ('did') the fave - AccountID string `pg:"type:CHAR(26),notnull"` - Account *Account `pg:"rel:has-one"` + AccountID string `bun:"type:CHAR(26),notnull"` + Account *Account `bun:"rel:belongs-to"` // id the account owning the faved status - TargetAccountID string `pg:"type:CHAR(26),notnull"` - TargetAccount *Account `pg:"rel:has-one"` + TargetAccountID string `bun:"type:CHAR(26),notnull"` + TargetAccount *Account `bun:"rel:belongs-to"` // database id of the status that has been 'faved' - StatusID string `pg:"type:CHAR(26),notnull"` - Status *Status `pg:"rel:has-one"` + StatusID string `bun:"type:CHAR(26),notnull"` + Status *Status `bun:"rel:belongs-to"` // ActivityPub URI of this fave - URI string `pg:",notnull"` + URI string `bun:",notnull"` } diff --git a/internal/gtsmodel/statusmute.go b/internal/gtsmodel/statusmute.go index 472a5ec09..56a792ab4 100644 --- a/internal/gtsmodel/statusmute.go +++ b/internal/gtsmodel/statusmute.go @@ -23,16 +23,16 @@ import "time" // StatusMute refers to one account having muted the status of another account or its own type StatusMute struct { // id of this mute in the database - ID string `pg:"type:CHAR(26),pk,notnull,unique"` + ID string `bun:"type:CHAR(26),pk,notnull,unique"` // when was this mute created - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // id of the account that created ('did') the mute - AccountID string `pg:"type:CHAR(26),notnull"` - Account *Account `pg:"rel:belongs-to"` + AccountID string `bun:"type:CHAR(26),notnull"` + Account *Account `bun:"rel:belongs-to"` // id the account owning the muted status (can be the same as accountID) - TargetAccountID string `pg:"type:CHAR(26),notnull"` - TargetAccount *Account `pg:"rel:has-one"` + TargetAccountID string `bun:"type:CHAR(26),notnull"` + TargetAccount *Account `bun:"rel:belongs-to"` // database id of the status that has been muted - StatusID string `pg:"type:CHAR(26),notnull"` - Status *Status `pg:"rel:has-one"` + StatusID string `bun:"type:CHAR(26),notnull"` + Status *Status `bun:"rel:belongs-to"` } diff --git a/internal/gtsmodel/tag.go b/internal/gtsmodel/tag.go index 27cce1c8b..5006a36f4 100644 --- a/internal/gtsmodel/tag.go +++ b/internal/gtsmodel/tag.go @@ -23,21 +23,21 @@ import "time" // Tag represents a hashtag for gathering public statuses together type Tag struct { // id of this tag in the database - ID string `pg:",unique,type:CHAR(26),pk,notnull"` + ID string `bun:",unique,type:CHAR(26),pk,notnull"` // 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,notnull"` + Name string `bun:",unique,notnull"` // Which account ID is the first one we saw using this tag? - FirstSeenFromAccountID string `pg:"type:CHAR(26)"` + FirstSeenFromAccountID string `bun:"type:CHAR(26),nullzero"` // when was this tag created - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // when was this tag last updated - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // can our instance users use this tag? - Useable bool `pg:",notnull,default:true"` + Useable bool `bun:",notnull,default:true"` // can our instance users look up this tag? - Listable bool `pg:",notnull,default:true"` + Listable bool `bun:",notnull,default:true"` // when was this tag last used? - LastStatusAt time.Time `pg:"type:timestamp,notnull,default:now()"` + LastStatusAt time.Time `bun:",nullzero"` } diff --git a/internal/gtsmodel/user.go b/internal/gtsmodel/user.go index fe8ebcabe..f439be439 100644 --- a/internal/gtsmodel/user.go +++ b/internal/gtsmodel/user.go @@ -31,37 +31,37 @@ type User struct { */ // id of this user in the local database; the end-user will never need to know this, it's strictly internal - ID string `pg:"type:CHAR(26),pk,notnull,unique"` + ID string `bun:"type:CHAR(26),pk,notnull,unique"` // 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"` + Email string `bun:"default:null,unique,nullzero"` // 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"` - Account *Account `pg:"rel:has-one"` + AccountID string `bun:"type:CHAR(26),unique,nullzero"` + Account *Account `bun:"rel:belongs-to"` // 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"` + EncryptedPassword string `bun:",notnull"` /* USER METADATA */ // When was this user created? - CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // From what IP was this user created? - SignUpIP net.IP + SignUpIP net.IP `bun:",nullzero"` // When was this user updated (eg., password changed, email address changed)? - UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` // When did this user sign in for their current session? - CurrentSignInAt time.Time `pg:"type:timestamp"` + CurrentSignInAt time.Time `bun:",nullzero"` // What's the most recent IP of this user - CurrentSignInIP net.IP + CurrentSignInIP net.IP `bun:",nullzero"` // When did this user last sign in? - LastSignInAt time.Time `pg:"type:timestamp"` + LastSignInAt time.Time `bun:",nullzero"` // What's the previous IP of this user? - LastSignInIP net.IP + LastSignInIP net.IP `bun:",nullzero"` // How many times has this user signed in? SignInCount int // id of the user who invited this user (who let this guy in?) - InviteID string `pg:"type:CHAR(26)"` + InviteID string `bun:"type:CHAR(26),nullzero"` // What languages does this user want to see? ChosenLanguages []string // What languages does this user not want to see? @@ -69,10 +69,10 @@ 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)"` - CreatedByApplication *Application `pg:"rel:has-one"` + CreatedByApplicationID string `bun:"type:CHAR(26),nullzero"` + CreatedByApplication *Application `bun:"rel:belongs-to"` // When did we last contact this user - LastEmailedAt time.Time `pg:"type:timestamp"` + LastEmailedAt time.Time `bun:",nullzero"` /* USER CONFIRMATION @@ -81,9 +81,9 @@ type User struct { // What confirmation token did we send this user/what are we expecting back? ConfirmationToken string // When did the user confirm their email address - ConfirmedAt time.Time `pg:"type:timestamp"` + ConfirmedAt time.Time `bun:",nullzero"` // When did we send email confirmation to this user? - ConfirmationSentAt time.Time `pg:"type:timestamp"` + ConfirmationSentAt time.Time `bun:",nullzero"` // Email address that hasn't yet been confirmed UnconfirmedEmail string @@ -107,7 +107,7 @@ type User struct { // The generated token that the user can use to reset their password ResetPasswordToken string // When did we email the user their reset-password email? - ResetPasswordSentAt time.Time `pg:"type:timestamp"` + ResetPasswordSentAt time.Time `bun:",nullzero"` EncryptedOTPSecret string EncryptedOTPSecretIv string @@ -117,6 +117,6 @@ type User struct { ConsumedTimestamp int RememberToken string SignInToken string - SignInTokenSentAt time.Time `pg:"type:timestamp"` + SignInTokenSentAt time.Time `bun:",nullzero"` WebauthnID string } |