From 81760963b04501e237a2822570fb580104aacd0a Mon Sep 17 00:00:00 2001 From: tsmethurst <tobi.smethurst@klarrio.com> Date: Sat, 20 Mar 2021 19:04:27 +0100 Subject: [PATCH] formatting,comments --- internal/config/config.go | 4 +- internal/gtsmodel/account.go | 158 +++++++++++++++++++++++++---------- internal/gtsmodel/status.go | 8 +- internal/gtsmodel/user.go | 121 +++++++++++++++++++-------- pkg/mastotypes/oauth.go | 8 +- 5 files changed, 212 insertions(+), 87 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index 8e2656e3..ce194cd5 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -48,7 +48,7 @@ func Default() *Config { // TODO: find a way of doing this without code repetition, because having to // repeat all values here and elsewhere is annoying and gonna be prone to mistakes. return &Config{ - DBConfig: &DBConfig{}, + DBConfig: &DBConfig{}, TemplateConfig: &TemplateConfig{}, } } @@ -56,7 +56,7 @@ func Default() *Config { // Empty just returns an empty config func Empty() *Config { return &Config{ - DBConfig: &DBConfig{}, + DBConfig: &DBConfig{}, TemplateConfig: &TemplateConfig{}, } } diff --git a/internal/gtsmodel/account.go b/internal/gtsmodel/account.go index 84ba027b..7bc8118a 100644 --- a/internal/gtsmodel/account.go +++ b/internal/gtsmodel/account.go @@ -26,60 +26,130 @@ import ( "time" ) -// Account represents a GoToSocial user account +// 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 + + /* + ACCOUNT METADATA + */ + + // Avatar image for this account Avatar + // Header image for this account Header - URI string - URL string - ID string `pg:"type:uuid,default:gen_random_uuid(),pk,notnull"` - Username string - Domain string - Secret string - PrivateKey string - PublicKey string - RemoteURL string - CreatedAt time.Time `pg:"type:timestamp,notnull"` - UpdatedAt time.Time `pg:"type:timestamp,notnull"` - Note string - DisplayName string + // 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 map[string]string + // 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"` - Locked bool - LastWebfingeredAt time.Time `pg:"type:timestamp"` - InboxURL string - OutboxURL string - SharedInboxURL string - FollowersURL string - Protocol int - Memorial bool - MovedToAccountID int - FeaturedCollectionURL string - Fields map[string]string - ActorType string - Discoverable bool - AlsoKnownAs string - SilencedAt time.Time `pg:"type:timestamp"` - SuspendedAt time.Time `pg:"type:timestamp"` - TrustLevel int - HideCollections bool - SensitizedAt time.Time `pg:"type:timestamp"` - SuspensionOrigin int + + /* + PRIVACY SETTINGS + */ + + // Does this account need an approval for new followers? + Locked bool + // Should this account be shown in the instance's profile directory? + Discoverable bool + + /* + 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"` + // RemoteURL where this account is located. Will be empty if this is a local account. + RemoteURL 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 string + // Publickey for encoding activitypub requests, will be defined for both local and remote accounts + PublicKey string + + /* + 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 } +// Avatar represents the avatar for the account for display purposes type Avatar struct { - AvatarFileName string - AvatarContentType string - AvatarFileSize int - AvatarUpdatedAt *time.Time `pg:"type:timestamp"` - AvatarRemoteURL *url.URL `pg:"type:text"` + // File name of the avatar on local storage + AvatarFileName string + // Gif? png? jpeg? + AvatarContentType string + AvatarFileSize int + AvatarUpdatedAt *time.Time `pg:"type:timestamp"` + // Where can we retrieve the avatar? + AvatarRemoteURL *url.URL `pg:"type:text"` AvatarStorageSchemaVersion int } +// Header represents the header of the account for display purposes type Header struct { - HeaderFileName string - HeaderContentType string - HeaderFileSize int - HeaderUpdatedAt *time.Time `pg:"type:timestamp"` - HeaderRemoteURL *url.URL `pg:"type:text"` + // File name of the header on local storage + HeaderFileName string + // Gif? png? jpeg? + HeaderContentType string + HeaderFileSize int + HeaderUpdatedAt *time.Time `pg:"type:timestamp"` + // Where can we retrieve the header? + HeaderRemoteURL *url.URL `pg:"type:text"` HeaderStorageSchemaVersion int } diff --git a/internal/gtsmodel/status.go b/internal/gtsmodel/status.go index 39c45093..22e88c08 100644 --- a/internal/gtsmodel/status.go +++ b/internal/gtsmodel/status.go @@ -22,11 +22,11 @@ import "time" type Status struct { ID string `pg:"type:uuid,default:gen_random_uuid(),pk,notnull"` - URI string - URL string + URI string `pg:",unique"` + URL string `pg:",unique"` Content string - CreatedAt time.Time `pg:"type:timestamp,notnull"` - UpdatedAt time.Time `pg:"type:timestamp,notnull"` + CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` + UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` Local bool AccountID string InReplyToID string diff --git a/internal/gtsmodel/user.go b/internal/gtsmodel/user.go index 577590dd..c105899b 100644 --- a/internal/gtsmodel/user.go +++ b/internal/gtsmodel/user.go @@ -23,43 +23,98 @@ import ( "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 { - ID string `pg:"type:uuid,default:gen_random_uuid(),pk,notnull"` - Email string `pg:",notnull"` - CreatedAt time.Time `pg:"type:timestamp,notnull"` - UpdatedAt time.Time `pg:"type:timestamp,notnull"` - EncryptedPassword string `pg:",notnull"` - ResetPasswordToken string - ResetPasswordSentAt time.Time `pg:"type:timestamp"` - SignInCount int - CurrentSignInAt time.Time `pg:"type:timestamp"` - LastSignInAt time.Time `pg:"type:timestamp"` - CurrentSignInIP net.IP - LastSignInIP net.IP - Admin bool - ConfirmationToken string - ConfirmedAt time.Time `pg:"type:timestamp"` - ConfirmationSentAt time.Time `pg:"type:timestamp"` - UnconfirmedEmail string - Locale string + /* + 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:",notnull,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 - ConsumedTimestamp int OTPRequiredForLogin bool - LastEmailedAt time.Time `pg:"type:timestamp"` OTPBackupCodes []string - FilteredLanguages []string - AccountID string `pg:",notnull"` - Disabled bool - Moderator bool - InviteID string - RememberToken string - ChosenLanguages []string - CreatedByApplicationID string - Approved bool - SignInToken string - SignInTokenSentAt time.Time `pg:"type:timestamp"` - WebauthnID string - SignUpIP net.IP + ConsumedTimestamp int + RememberToken string + SignInToken string + SignInTokenSentAt time.Time `pg:"type:timestamp"` + WebauthnID string } diff --git a/pkg/mastotypes/oauth.go b/pkg/mastotypes/oauth.go index 1b45b38e..d93ea079 100644 --- a/pkg/mastotypes/oauth.go +++ b/pkg/mastotypes/oauth.go @@ -22,16 +22,16 @@ package mastotypes // See here: https://docs.joinmastodon.org/methods/apps/oauth/ type OAuthAuthorize struct { // Forces the user to re-login, which is necessary for authorizing with multiple accounts from the same instance. - ForceLogin string `form:"force_login,omitempty"` + ForceLogin string `form:"force_login,omitempty"` // Should be set equal to `code`. ResponseType string `form:"response_type"` // Client ID, obtained during app registration. - ClientID string `form:"client_id"` + ClientID string `form:"client_id"` // Set a URI to redirect the user to. // If this parameter is set to urn:ietf:wg:oauth:2.0:oob then the authorization code will be shown instead. // Must match one of the redirect URIs declared during app registration. - RedirectURI string `form:"redirect_uri"` + RedirectURI string `form:"redirect_uri"` // List of requested OAuth scopes, separated by spaces (or by pluses, if using query parameters). // Must be a subset of scopes declared during app registration. If not provided, defaults to read. - Scope string `form:"scope,omitempty"` + Scope string `form:"scope,omitempty"` }