diff options
Diffstat (limited to 'internal/db/model')
-rw-r--r-- | internal/db/model/README.md | 5 | ||||
-rw-r--r-- | internal/db/model/account.go | 164 | ||||
-rw-r--r-- | internal/db/model/application.go | 55 | ||||
-rw-r--r-- | internal/db/model/domainblock.go | 47 | ||||
-rw-r--r-- | internal/db/model/emaildomainblock.go | 35 | ||||
-rw-r--r-- | internal/db/model/follow.go | 41 | ||||
-rw-r--r-- | internal/db/model/followrequest.go | 41 | ||||
-rw-r--r-- | internal/db/model/mediaattachment.go | 136 | ||||
-rw-r--r-- | internal/db/model/status.go | 63 | ||||
-rw-r--r-- | internal/db/model/user.go | 120 |
10 files changed, 707 insertions, 0 deletions
diff --git a/internal/db/model/README.md b/internal/db/model/README.md new file mode 100644 index 000000000..12a05ddec --- /dev/null +++ b/internal/db/model/README.md @@ -0,0 +1,5 @@ +# gtsmodel + +This package contains types used *internally* by GoToSocial and added/removed/selected from the database. As such, they contain sensitive fields which should **never** be serialized or reach the API level. Use the [mastotypes](../../pkg/mastotypes) package for that. + +The annotation used on these structs is for handling them via the go-pg ORM. See [here](https://pg.uptrace.dev/models/). diff --git a/internal/db/model/account.go b/internal/db/model/account.go new file mode 100644 index 000000000..70ee92929 --- /dev/null +++ b/internal/db/model/account.go @@ -0,0 +1,164 @@ +/* + 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. + + 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 model 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/ +package model + +import ( + "crypto/rsa" + "net/url" + "time" +) + +// Account represents either a local or a remote fediverse account, gotosocial or otherwise (mastodon, pleroma, etc) +type Account struct { + /* + BASIC INFO + */ + + // id of this account in the local database; the end-user will never need to know this, it's strictly internal + ID string `pg:"type:uuid,default:gen_random_uuid(),pk,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 + // Domain of the account, will be empty 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 + + /* + ACCOUNT METADATA + */ + + // File name of the avatar on local storage + AvatarFileName string + // Gif? png? jpeg? + AvatarContentType string + // Size of the avatar in bytes + AvatarFileSize int + // When was the avatar last updated? + AvatarUpdatedAt time.Time `pg:"type:timestamp"` + // Where can the avatar be retrieved? + AvatarRemoteURL *url.URL `pg:"type:text"` + // File name of the header on local storage + HeaderFileName string + // Gif? png? jpeg? + HeaderContentType string + // Size of the header in bytes + HeaderFileSize int + // When was the header last updated? + HeaderUpdatedAt time.Time `pg:"type:timestamp"` + // Where can the header be retrieved? + HeaderRemoteURL *url.URL `pg:"type:text"` + // DisplayName for this account. Can be empty, then just the Username will be used for display purposes. + DisplayName string + // a key/value map of fields that this account has added to their profile + Fields []Field + // A note that this account has on their profile (ie., the account's bio/description of themselves) + Note string + // Is this a memorial account, ie., has the user passed away? + Memorial bool + // This account has moved this account id in the database + MovedToAccountID int + // When was this account created? + CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + // When was this account last updated? + UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + // When should this account function until + SubscriptionExpiresAt time.Time `pg:"type:timestamp"` + // Does this account identify itself as a bot? + Bot bool + // What reason was given for signing up when this account was created? + Reason string + + /* + USER AND PRIVACY PREFERENCES + */ + + // Does this account need an approval for new followers? + Locked bool + // Should this account be shown in the instance's profile directory? + Discoverable bool + // Default post privacy for this account + Privacy string + // Set posts from this account to sensitive by default? + Sensitive bool + // What language does this account post in? + Language string + + /* + ACTIVITYPUB THINGS + */ + + // What is the activitypub URI for this account discovered by webfinger? + URI string `pg:",unique"` + // At which URL can we see the user account in a web browser? + URL string `pg:",unique"` + // Last time this account was located using the webfinger API. + LastWebfingeredAt time.Time `pg:"type:timestamp"` + // Address of this account's activitypub inbox, for sending activity to + InboxURL string `pg:",unique"` + // Address of this account's activitypub outbox + OutboxURL string `pg:",unique"` + // Don't support shared inbox right now so this is just a stub for a future implementation + SharedInboxURL string `pg:",unique"` + // URL for getting the followers list of this account + FollowersURL string `pg:",unique"` + // URL for getting the featured collection list of this account + FeaturedCollectionURL string `pg:",unique"` + // What type of activitypub actor is this account? + ActorType string + // This account is associated with x account id + AlsoKnownAs string + + /* + CRYPTO FIELDS + */ + + Secret string + // Privatekey for validating activitypub requests, will obviously only be defined for local accounts + PrivateKey *rsa.PrivateKey + // Publickey for encoding activitypub requests, will be defined for both local and remote accounts + PublicKey *rsa.PublicKey + + /* + ADMIN FIELDS + */ + + // When was this account set to have all its media shown as sensitive? + SensitizedAt time.Time `pg:"type:timestamp"` + // When was this account silenced (eg., statuses only visible to followers, not public)? + SilencedAt time.Time `pg:"type:timestamp"` + // 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"` + // How much do we trust this account 🤔 + TrustLevel int + // Should we hide this account's collections? + HideCollections bool + // id of the user that suspended this account through an admin action + SuspensionOrigin int +} + +// Field represents a key value field on an account, for things like pronouns, website, etc. +// VerifiedAt is optional, to be used only if Value is a URL to a webpage that contains the +// username of the user. +type Field struct { + Name string + Value string + VerifiedAt time.Time `pg:"type:timestamp"` +} diff --git a/internal/db/model/application.go b/internal/db/model/application.go new file mode 100644 index 000000000..c8eea6430 --- /dev/null +++ b/internal/db/model/application.go @@ -0,0 +1,55 @@ +/* + 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. + + 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 model + +import "github.com/superseriousbusiness/gotosocial/pkg/mastotypes" + +// Application represents an application that can perform actions on behalf of a user. +// 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:uuid,default:gen_random_uuid(),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') + Website string + // redirect uri requested by the application for oauth2 flow + RedirectURI string + // id of the associated oauth client entity in the db + ClientID string + // secret of the associated oauth client entity in the db + ClientSecret string + // scopes requested when this app was created + Scopes string + // a vapid key generated for this app when it was created + VapidKey string +} + +// ToMasto returns this application as a mastodon api type, ready for serialization +func (a *Application) ToMasto() *mastotypes.Application { + return &mastotypes.Application{ + ID: a.ID, + Name: a.Name, + Website: a.Website, + RedirectURI: a.RedirectURI, + ClientID: a.ClientID, + ClientSecret: a.ClientSecret, + VapidKey: a.VapidKey, + } +} diff --git a/internal/db/model/domainblock.go b/internal/db/model/domainblock.go new file mode 100644 index 000000000..e6e89bc20 --- /dev/null +++ b/internal/db/model/domainblock.go @@ -0,0 +1,47 @@ +/* + 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. + + 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 model + +import "time" + +// DomainBlock represents a federation block against a particular domain, of varying severity. +type DomainBlock struct { + // ID of this block in the database + ID string `pg:"type:uuid,default:gen_random_uuid(),pk,notnull,unique"` + // Domain to block. If ANY PART of the candidate domain contains this string, it will be blocked. + // For example: 'example.org' also blocks 'gts.example.org'. '.com' blocks *any* '.com' domains. + // TODO: implement wildcards here + Domain string `pg:",notnull"` + // When was this block created + CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + // 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:",notnull"` + // TODO: define this + Severity int + // Reject media from this domain? + RejectMedia bool + // Reject reports from this domain? + RejectReports bool + // Private comment on this block, viewable to admins + PrivateComment string + // Public comment on this block, viewable (optionally) by everyone + PublicComment string +} diff --git a/internal/db/model/emaildomainblock.go b/internal/db/model/emaildomainblock.go new file mode 100644 index 000000000..6610a2075 --- /dev/null +++ b/internal/db/model/emaildomainblock.go @@ -0,0 +1,35 @@ +/* + 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. + + 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 model + +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:uuid,default:gen_random_uuid(),pk,notnull,unique"` + // Email domain to block. Eg. 'gmail.com' or 'hotmail.com' + Domain string `pg:",notnull"` + // When was this block created + CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + // 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:",notnull"` +} diff --git a/internal/db/model/follow.go b/internal/db/model/follow.go new file mode 100644 index 000000000..36e19e72e --- /dev/null +++ b/internal/db/model/follow.go @@ -0,0 +1,41 @@ +/* + 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. + + 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 model + +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:uuid,default:gen_random_uuid(),pk,notnull,unique"` + // When was this follow created? + CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + // When was this follow last updated? + UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + // Who does this follow belong to? + AccountID string `pg:",unique:srctarget,notnull"` + // Who does AccountID follow? + TargetAccountID string `pg:",unique:srctarget,notnull"` + // 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? + URI string `pg:",unique"` + // does the following account want to be notified when the followed account posts? + Notify bool +} diff --git a/internal/db/model/followrequest.go b/internal/db/model/followrequest.go new file mode 100644 index 000000000..50d8a5f03 --- /dev/null +++ b/internal/db/model/followrequest.go @@ -0,0 +1,41 @@ +/* + 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. + + 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 model + +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:uuid,default:gen_random_uuid(),pk,notnull,unique"` + // When was this follow request created? + CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + // 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:",unique:srctarget,notnull"` + // Who is the target of this follow request? + TargetAccountID string `pg:",unique:srctarget,notnull"` + // 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? + URI string `pg:",unique"` + // does the following account want to be notified when the followed account posts? + Notify bool +} diff --git a/internal/db/model/mediaattachment.go b/internal/db/model/mediaattachment.go new file mode 100644 index 000000000..3aff18d80 --- /dev/null +++ b/internal/db/model/mediaattachment.go @@ -0,0 +1,136 @@ +/* + 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. + + 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 model + +import ( + "time" +) + +// MediaAttachment represents a user-uploaded media attachment: an image/video/audio/gif that is +// 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:uuid,default:gen_random_uuid(),pk,notnull,unique"` + // ID of the status to which this is attached + StatusID string + // Where can the attachment be retrieved on a remote server + RemoteURL string + // When was the attachment created + CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + // When was the attachment last updated + UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + // Type of file (image/gif/audio/video) + Type FileType `pg:",notnull"` + // Metadata about the file + FileMeta FileMeta + // To which account does this attachment belong + AccountID string `pg:",notnull"` + // Description of the attachment (for screenreaders) + Description string + // To which scheduled status does this attachment belong + ScheduledStatusID string + // What is the generated blurhash of this attachment + Blurhash string + // What is the processing status of this attachment + Processing ProcessingStatus + // metadata for the whole file + File File + // small image thumbnail derived from a larger image, video, or audio file. + Thumbnail Thumbnail + // Is this attachment being used as an avatar? + Avatar bool + // Is this attachment being used as a header? + Header bool +} + +// File refers to the metadata for the whole file +type File struct { + // What is the path of the file in storage. + Path string + // What is the MIME content type of the file. + ContentType string + // 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()"` +} + +// Thumbnail refers to a small image thumbnail derived from a larger image, video, or audio file. +type Thumbnail struct { + // What is the path of the file in storage + Path string + // What is the MIME content type of the file. + ContentType string + // 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()"` + // What is the remote URL of the thumbnail + RemoteURL string +} + +// ProcessingStatus refers to how far along in the processing stage the attachment is. +type ProcessingStatus int + +const ( + // ProcessingStatusReceived: the attachment has been received and is awaiting processing. No thumbnail available yet. + ProcessingStatusReceived ProcessingStatus = 0 + // ProcessingStatusProcessing: the attachment is currently being processed. Thumbnail is available but full media is not. + ProcessingStatusProcessing ProcessingStatus = 1 + // ProcessingStatusProcessed: the attachment has been fully processed and is ready to be served. + ProcessingStatusProcessed ProcessingStatus = 2 + // ProcessingStatusError: something went wrong processing the attachment and it won't be tried again--these can be deleted. + ProcessingStatusError ProcessingStatus = 666 +) + +// FileType refers to the file type of the media attaachment. +type FileType string + +const ( + // FileTypeImage is for jpegs and pngs + FileTypeImage FileType = "image" + // FileTypeGif is for native gifs and soundless videos that have been converted to gifs + FileTypeGif FileType = "gif" + // FileTypeAudio is for audio-only files (no video) + FileTypeAudio FileType = "audio" + // FileTypeVideo is for files with audio + visual + FileTypeVideo FileType = "video" +) + +// FileMeta describes metadata about the actual contents of the file. +type FileMeta struct { + Original Original + Small Small +} + +// Small implements SmallMeta and can be used for a thumbnail of any media type +type Small struct { + Width int + Height int + Size int + Aspect float64 +} + +// ImageOriginal implements OriginalMeta for still images +type Original struct { + Width int + Height int + Size int + Aspect float64 +} diff --git a/internal/db/model/status.go b/internal/db/model/status.go new file mode 100644 index 000000000..d15258727 --- /dev/null +++ b/internal/db/model/status.go @@ -0,0 +1,63 @@ +/* + 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. + + 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 model + +import "time" + +// 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:uuid,default:gen_random_uuid(),pk,notnull"` + // uri at which this status is reachable + URI string `pg:",unique"` + // web url for viewing this status + URL string `pg:",unique"` + // the html-formatted content of this status + Content string + // when was this status created? + CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + // when was this status updated? + UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + // is this status from a local account? + Local bool + // which account posted this status? + AccountID string + // id of the status this status is a reply to + InReplyToID string + // id of the status this status is a boost of + BoostOfID string + // cw string for this status + ContentWarning string + // visibility entry for this status + Visibility *Visibility +} + +// Visibility represents the visibility granularity of a status. It is a combination of flags. +type Visibility struct { + // Is this status viewable as a direct message? + Direct bool + // Is this status viewable to followers? + Followers bool + // Is this status viewable on the local timeline? + Local bool + // Is this status boostable but not shown on public timelines? + Unlisted bool + // Is this status shown on public and federated timelines? + Public bool +} diff --git a/internal/db/model/user.go b/internal/db/model/user.go new file mode 100644 index 000000000..61e9954d5 --- /dev/null +++ b/internal/db/model/user.go @@ -0,0 +1,120 @@ +/* + 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. + + 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 model + +import ( + "net" + "time" +) + +// User represents an actual human user of gotosocial. Note, this is a LOCAL gotosocial user, not a remote account. +// To cross reference this local user with their account (which can be local or remote), use the AccountID field. +type User struct { + /* + BASIC INFO + */ + + // 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:uuid,default:gen_random_uuid(),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"` + // 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:"default:'',notnull,unique"` + // 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"` + + /* + USER METADATA + */ + + // When was this user created? + CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + // From what IP was this user created? + SignUpIP net.IP + // When was this user updated (eg., password changed, email address changed)? + UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + // When did this user sign in for their current session? + CurrentSignInAt time.Time `pg:"type:timestamp"` + // What's the most recent IP of this user + CurrentSignInIP net.IP + // When did this user last sign in? + LastSignInAt time.Time `pg:"type:timestamp"` + // What's the previous IP of this user? + LastSignInIP net.IP + // 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 + // What languages does this user want to see? + ChosenLanguages []string + // What languages does this user not want to see? + FilteredLanguages []string + // In what timezone/locale is this user located? + Locale string + // Which application id created this user? See gtsmodel.Application + CreatedByApplicationID string + // When did we last contact this user + LastEmailedAt time.Time `pg:"type:timestamp"` + + /* + USER CONFIRMATION + */ + + // 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"` + // When did we send email confirmation to this user? + ConfirmationSentAt time.Time `pg:"type:timestamp"` + // Email address that hasn't yet been confirmed + UnconfirmedEmail string + + /* + ACL FLAGS + */ + + // Is this user a moderator? + Moderator bool + // Is this user an admin? + Admin bool + // Is this user disabled from posting? + Disabled bool + // Has this user been approved by a moderator? + Approved bool + + /* + USER SECURITY + */ + + // 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"` + + EncryptedOTPSecret string + EncryptedOTPSecretIv string + EncryptedOTPSecretSalt string + OTPRequiredForLogin bool + OTPBackupCodes []string + ConsumedTimestamp int + RememberToken string + SignInToken string + SignInTokenSentAt time.Time `pg:"type:timestamp"` + WebauthnID string +} |