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"`
 }