diff options
Diffstat (limited to 'internal/db/bundb')
21 files changed, 937 insertions, 7 deletions
| diff --git a/internal/db/bundb/bundb_test.go b/internal/db/bundb/bundb_test.go index b789375af..faa67456d 100644 --- a/internal/db/bundb/bundb_test.go +++ b/internal/db/bundb/bundb_test.go @@ -24,7 +24,6 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/config"  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" -	"github.com/superseriousbusiness/gotosocial/internal/oauth"  )  type BunDBStandardTestSuite struct { @@ -35,8 +34,8 @@ type BunDBStandardTestSuite struct {  	log    *logrus.Logger  	// standard suite models -	testTokens       map[string]*oauth.Token -	testClients      map[string]*oauth.Client +	testTokens       map[string]*gtsmodel.Token +	testClients      map[string]*gtsmodel.Client  	testApplications map[string]*gtsmodel.Application  	testUsers        map[string]*gtsmodel.User  	testAccounts     map[string]*gtsmodel.Account diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation.go b/internal/db/bundb/migrations/20210816411877_struct_validation.go index 660d94517..15d2d7659 100644 --- a/internal/db/bundb/migrations/20210816411877_struct_validation.go +++ b/internal/db/bundb/migrations/20210816411877_struct_validation.go @@ -21,16 +21,45 @@ package migrations  import (  	"context" -	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" +	gtsmodel "github.com/superseriousbusiness/gotosocial/internal/db/bundb/migrations/20210816411877_struct_validation"  	"github.com/uptrace/bun"  )  func init() { + +	var models []interface{} = []interface{}{ +		>smodel.Account{}, +		>smodel.Application{}, +		>smodel.Block{}, +		>smodel.DomainBlock{}, +		>smodel.EmailDomainBlock{}, +		>smodel.Follow{}, +		>smodel.FollowRequest{}, +		>smodel.MediaAttachment{}, +		>smodel.Mention{}, +		>smodel.Status{}, +		>smodel.StatusToEmoji{}, +		>smodel.StatusToTag{}, +		>smodel.StatusFave{}, +		>smodel.StatusBookmark{}, +		>smodel.StatusMute{}, +		>smodel.Tag{}, +		>smodel.User{}, +		>smodel.Emoji{}, +		>smodel.Instance{}, +		>smodel.Notification{}, +		>smodel.RouterSession{}, +		>smodel.Token{}, +		>smodel.Client{}, +	} +  	up := func(ctx context.Context, db *bun.DB) error {  		return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error { -			_, err := tx.NewCreateTable().Model(>smodel.Account{}).IfNotExists().Exec(ctx) -			if err != nil { -				return err +			for _, m := range models { +				_, err := tx.NewCreateTable().Model(m).IfNotExists().Exec(ctx) +				if err != nil { +					return err +				}  			}  			return nil diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/account.go b/internal/db/bundb/migrations/20210816411877_struct_validation/account.go new file mode 100644 index 000000000..6c957b5c0 --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/account.go @@ -0,0 +1,78 @@ +/* +   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 gtsmodel + +import ( +	"crypto/rsa" +	"time" +) + +// Account represents either a local or a remote fediverse account, gotosocial or otherwise (mastodon, pleroma, etc). +type Account struct { +	ID                      string           `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                                      // id of this item in the database +	CreatedAt               time.Time        `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                               // when was item created +	UpdatedAt               time.Time        `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                               // when was item last updated +	Username                string           `validate:"required" bun:",nullzero,notnull,unique:userdomain"`                                                // Username of the account, should just be a string of [a-zA-Z0-9_]. Can be added to domain to create the full username in the form ``[username]@[domain]`` eg., ``user_96@example.org``. Username and domain should be unique *with* each other +	Domain                  string           `validate:"omitempty,fqdn" bun:",nullzero,unique:userdomain"`                                                  // 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. +	AvatarMediaAttachmentID string           `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                                       // Database ID of the media attachment, if present +	AvatarMediaAttachment   *MediaAttachment `validate:"-" bun:"rel:belongs-to"`                                                                            // MediaAttachment corresponding to avatarMediaAttachmentID +	AvatarRemoteURL         string           `validate:"omitempty,url" bun:",nullzero"`                                                                     // For a non-local account, where can the header be fetched? +	HeaderMediaAttachmentID string           `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                                       // Database ID of the media attachment, if present +	HeaderMediaAttachment   *MediaAttachment `validate:"-" bun:"rel:belongs-to"`                                                                            // MediaAttachment corresponding to headerMediaAttachmentID +	HeaderRemoteURL         string           `validate:"omitempty,url" bun:",nullzero"`                                                                     // For a non-local account, where can the header be fetched? +	DisplayName             string           `validate:"-" bun:",nullzero"`                                                                                 // DisplayName for this account. Can be empty, then just the Username will be used for display purposes. +	Fields                  []Field          `validate:"-"`                                                                                                 // a key/value map of fields that this account has added to their profile +	Note                    string           `validate:"-" bun:",nullzero"`                                                                                 // A note that this account has on their profile (ie., the account's bio/description of themselves) +	Memorial                bool             `validate:"-" bun:",nullzero,default:false"`                                                                   // Is this a memorial account, ie., has the user passed away? +	AlsoKnownAs             string           `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                                       // This account is associated with x account id +	MovedToAccountID        string           `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                                       // This account has moved this account id in the database +	Bot                     bool             `validate:"-" bun:",nullzero,default:false"`                                                                   // Does this account identify itself as a bot? +	Reason                  string           `validate:"-" bun:",nullzero"`                                                                                 // What reason was given for signing up when this account was created? +	Locked                  bool             `validate:"-" bun:",nullzero,default:true"`                                                                    // Does this account need an approval for new followers? +	Discoverable            bool             `validate:"-" bun:",nullzero,default:false"`                                                                   // Should this account be shown in the instance's profile directory? +	Privacy                 Visibility       `validate:"oneof=public unlocked followers_only mutuals_only direct" bun:",nullzero,notnull,default:'public'"` // Default post privacy for this account +	Sensitive               bool             `validate:"-" bun:",nullzero,default:false"`                                                                   // Set posts from this account to sensitive by default? +	Language                string           `validate:"-" bun:",nullzero,notnull,default:'en'"`                                                            // What language does this account post in? +	URI                     string           `validate:"required,url" bun:",nullzero,notnull,unique"`                                                       // ActivityPub URI for this account. +	URL                     string           `validate:"omitempty,url" bun:",unique,nullzero"`                                                              // Web URL for this account's profile +	LastWebfingeredAt       time.Time        `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                               // Last time this account was refreshed/located with webfinger. +	InboxURI                string           `validate:"omitempty,url" bun:",nullzero,unique"`                                                              // Address of this account's ActivityPub inbox, for sending activity to +	OutboxURI               string           `validate:"omitempty,url" bun:",nullzero,unique"`                                                              // Address of this account's activitypub outbox +	FollowingURI            string           `validate:"omitempty,url" bun:",nullzero,unique"`                                                              // URI for getting the following list of this account +	FollowersURI            string           `validate:"omitempty,url" bun:",nullzero,unique"`                                                              // URI for getting the followers list of this account +	FeaturedCollectionURI   string           `validate:"omitempty,url" bun:",nullzero,unique"`                                                              // URL for getting the featured collection list of this account +	ActorType               string           `validate:"oneof=Application Group Organization Person Service " bun:",nullzero,notnull"`                      // What type of activitypub actor is this account? +	PrivateKey              *rsa.PrivateKey  `validate:"required_without=Domain"`                                                                           // Privatekey for validating activitypub requests, will only be defined for local accounts +	PublicKey               *rsa.PublicKey   `validate:"required"`                                                                                          // Publickey for encoding activitypub requests, will be defined for both local and remote accounts +	PublicKeyURI            string           `validate:"required" bun:",nullzero,notnull"`                                                                  // Web-reachable location of this account's public key +	SensitizedAt            time.Time        `validate:"-" bun:",nullzero"`                                                                                 // When was this account set to have all its media shown as sensitive? +	SilencedAt              time.Time        `validate:"-" bun:",nullzero"`                                                                                 // When was this account silenced (eg., statuses only visible to followers, not public)? +	SuspendedAt             time.Time        `validate:"-" bun:",nullzero"`                                                                                 // When was this account suspended (eg., don't allow it to log in/post, don't accept media/posts from this account) +	HideCollections         bool             `validate:"-" bun:",nullzero,default:false"`                                                                   // Hide this account's collections +	SuspensionOrigin        string           `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                                       // id of the database entry that caused this account to become suspended -- can be an account ID or a domain block ID +} + +// 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    `validate:"required"`          // Name of this field. +	Value      string    `validate:"required"`          // Value of this field. +	VerifiedAt time.Time `validate:"-" bun:",nullzero"` // This field was verified at (optional). +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/application.go b/internal/db/bundb/migrations/20210816411877_struct_validation/application.go new file mode 100644 index 000000000..0791aae6a --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/application.go @@ -0,0 +1,32 @@ +/* +   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 gtsmodel + +// 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           string `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull"` // id of this application in the db +	Name         string `validate:"required" bun:",nullzero,notnull"`                      // name of the application given when it was created (eg., 'tusky') +	Website      string `validate:"omitempty,url" bun:",nullzero"`                         // website for the application given when it was created (eg., 'https://tusky.app') +	RedirectURI  string `validate:"required" bun:",nullzero,notnull"`                      // redirect uri requested by the application for oauth2 flow +	ClientID     string `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`           // id of the associated oauth client entity in the db +	ClientSecret string `validate:"required,uuid" bun:",nullzero,notnull"`                 // secret of the associated oauth client entity in the db +	Scopes       string `validate:"required" bun:",nullzero,default:'read'"`               // scopes requested when this app was created +	VapidKey     string `validate:"-" bun:",nullzero"`                                     // a vapid key generated for this app when it was created +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/block.go b/internal/db/bundb/migrations/20210816411877_struct_validation/block.go new file mode 100644 index 000000000..61595c12d --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/block.go @@ -0,0 +1,15 @@ +package gtsmodel + +import "time" + +// Block refers to the blocking of one account by another. +type Block struct { +	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`    // id of this item in the database +	CreatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`             // when was item created +	UpdatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`             // when was item last updated +	URI             string    `validate:"required,url" bun:",notnull,nullzero,unique"`                     // ActivityPub uri of this block. +	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),unique:blocksrctarget,notnull"` // Who does this block originate from? +	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                          // Account corresponding to accountID +	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),unique:blocksrctarget,notnull"` // Who is the target of this block ? +	TargetAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                          // Account corresponding to targetAccountID +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/domainblock.go b/internal/db/bundb/migrations/20210816411877_struct_validation/domainblock.go new file mode 100644 index 000000000..dd05ef0c6 --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/domainblock.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 gtsmodel + +import "time" + +// DomainBlock represents a federation block against a particular domain +type DomainBlock struct { +	ID                 string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database +	CreatedAt          time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created +	UpdatedAt          time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated +	Domain             string    `validate:"required,fqdn" bun:",nullzero,notnull"`                        // domain to block. Eg. 'whatever.com' +	CreatedByAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // Account ID of the creator of this block +	CreatedByAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to createdByAccountID +	PrivateComment     string    `validate:"-" bun:",nullzero"`                                            // Private comment on this block, viewable to admins +	PublicComment      string    `validate:"-" bun:",nullzero"`                                            // Public comment on this block, viewable (optionally) by everyone +	Obfuscate          bool      `validate:"-" bun:",nullzero,default:false"`                              // whether the domain name should appear obfuscated when displaying it publicly +	SubscriptionID     string    `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                  // if this block was created through a subscription, what's the subscription ID? +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/emaildomainblock.go b/internal/db/bundb/migrations/20210816411877_struct_validation/emaildomainblock.go new file mode 100644 index 000000000..38f4a9580 --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/emaildomainblock.go @@ -0,0 +1,31 @@ +/* +   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 gtsmodel + +import "time" + +// EmailDomainBlock represents a domain that the server should automatically reject sign-up requests from. +type EmailDomainBlock struct { +	ID                 string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database +	CreatedAt          time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created +	UpdatedAt          time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated +	Domain             string    `validate:"required,fqdn" bun:",nullzero,notnull"`                        // Email domain to block. Eg. 'gmail.com' or 'hotmail.com' +	CreatedByAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // Account ID of the creator of this block +	CreatedByAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to createdByAccountID +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/emoji.go b/internal/db/bundb/migrations/20210816411877_struct_validation/emoji.go new file mode 100644 index 000000000..71287130a --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/emoji.go @@ -0,0 +1,45 @@ +/* +   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 gtsmodel + +import "time" + +// Emoji represents a custom emoji that's been uploaded through the admin UI, and is useable by instance denizens. +type Emoji struct { +	ID                     string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                                // id of this item in the database +	CreatedAt              time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                         // when was item created +	UpdatedAt              time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                         // when was item last updated +	Shortcode              string    `validate:"required" bun:",notnull,unique:shortcodedomain"`                                              // 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. +	Domain                 string    `validate:"omitempty,fqdn" bun:",notnull,default:'',unique:shortcodedomain"`                             // Origin domain of this emoji, eg 'example.org', 'queer.party'. empty string for local emojis. +	ImageRemoteURL         string    `validate:"required_without=ImageURL,omitempty,url" bun:",nullzero"`                                     // Where can this emoji be retrieved remotely? Null for local emojis. +	ImageStaticRemoteURL   string    `validate:"required_without=ImageStaticURL,omitempty,url" bun:",nullzero"`                               // Where can a static / non-animated version of this emoji be retrieved remotely? Null for local emojis. +	ImageURL               string    `validate:"required_without=ImageRemoteURL,required_without=Domain,omitempty,url" bun:",nullzero"`       // Where can this emoji be retrieved from the local server? Null for remote emojis. +	ImageStaticURL         string    `validate:"required_without=ImageStaticRemoteURL,required_without=Domain,omitempty,url" bun:",nullzero"` // Where can a static version of this emoji be retrieved from the local server? Null for remote emojis. +	ImagePath              string    `validate:"required,file" bun:",nullzero,notnull"`                                                       // Path of the emoji image in the server storage system. +	ImageStaticPath        string    `validate:"required,file" bun:",nullzero,notnull"`                                                       // Path of a static version of the emoji image in the server storage system +	ImageContentType       string    `validate:"required" bun:",nullzero,notnull"`                                                            // MIME content type of the emoji image +	ImageStaticContentType string    `validate:"required" bun:",nullzero,notnull"`                                                            // MIME content type of the static version of the emoji image. +	ImageFileSize          int       `validate:"required,min=1" bun:",nullzero,notnull"`                                                      // Size of the emoji image file in bytes, for serving purposes. +	ImageStaticFileSize    int       `validate:"required,min=1" bun:",nullzero,notnull"`                                                      // Size of the static version of the emoji image file in bytes, for serving purposes. +	ImageUpdatedAt         time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                         // When was the emoji image last updated? +	Disabled               bool      `validate:"-" bun:",notnull,default:false"`                                                              // Has a moderation action disabled this emoji from being shown? +	URI                    string    `validate:"url" bun:",nullzero,notnull,unique"`                                                          // ActivityPub uri of this emoji. Something like 'https://example.org/emojis/1234' +	VisibleInPicker        bool      `validate:"-" bun:",notnull,default:true"`                                                               // Is this emoji visible in the admin emoji picker? +	CategoryID             string    `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                                 // In which emoji category is this emoji visible? +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/follow.go b/internal/db/bundb/migrations/20210816411877_struct_validation/follow.go new file mode 100644 index 000000000..c2b2633b9 --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/follow.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 gtsmodel + +import "time" + +// Follow represents one account following another, and the metadata around that follow. +type Follow struct { +	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database +	CreatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created +	UpdatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated +	URI             string    `validate:"required,url" bun:",notnull,nullzero,unique"`                  // ActivityPub uri of this follow. +	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),unique:srctarget,notnull"`   // Who does this follow originate from? +	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to accountID +	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),unique:srctarget,notnull"`   // Who is the target of this follow ? +	TargetAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to targetAccountID +	ShowReblogs     bool      `validate:"-" bun:",nullzero,default:true"`                               // Does this follow also want to see reblogs and not just posts? +	Notify          bool      `validate:"-" bun:",nullzero,default:false"`                              // does the following account want to be notified when the followed account posts? +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/followrequest.go b/internal/db/bundb/migrations/20210816411877_struct_validation/followrequest.go new file mode 100644 index 000000000..ae22f6487 --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/followrequest.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 gtsmodel + +import "time" + +// FollowRequest represents one account requesting to follow another, and the metadata around that request. +type FollowRequest struct { +	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database +	CreatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created +	UpdatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated +	URI             string    `validate:"required,url" bun:",notnull,nullzero,unique"`                  // ActivityPub uri of this follow (request). +	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),unique:frsrctarget,notnull"` // Who does this follow request originate from? +	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to accountID +	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),unique:frsrctarget,notnull"` // Who is the target of this follow request? +	TargetAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to targetAccountID +	ShowReblogs     bool      `validate:"-" bun:",nullzero,default:true"`                               // Does this follow also want to see reblogs and not just posts? +	Notify          bool      `validate:"-" bun:",nullzero,default:false"`                              // does the following account want to be notified when the followed account posts? +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/instance.go b/internal/db/bundb/migrations/20210816411877_struct_validation/instance.go new file mode 100644 index 000000000..4d36dbba8 --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/instance.go @@ -0,0 +1,25 @@ +package gtsmodel + +import "time" + +// Instance represents a federated instance, either local or remote. +type Instance struct { +	ID                     string       `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                     // id of this item in the database +	CreatedAt              time.Time    `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                              // when was item created +	UpdatedAt              time.Time    `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                              // when was item last updated +	Domain                 string       `validate:"required,fqdn" bun:",nullzero,notnull,unique"`                                     // Instance domain eg example.org +	Title                  string       `validate:"-" bun:",nullzero"`                                                                // Title of this instance as it would like to be displayed. +	URI                    string       `validate:"required,url" bun:",nullzero,notnull,unique"`                                      // base URI of this instance eg https://example.org +	SuspendedAt            time.Time    `validate:"-" bun:",nullzero"`                                                                // When was this instance suspended, if at all? +	DomainBlockID          string       `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                      // ID of any existing domain block for this instance in the database +	DomainBlock            *DomainBlock `validate:"-" bun:"rel:belongs-to"`                                                           // Domain block corresponding to domainBlockID +	ShortDescription       string       `validate:"-" bun:",nullzero"`                                                                // Short description of this instance +	Description            string       `validate:"-" bun:",nullzero"`                                                                // Longer description of this instance +	Terms                  string       `validate:"-" bun:",nullzero"`                                                                // Terms and conditions of this instance +	ContactEmail           string       `validate:"omitempty,email" bun:",nullzero"`                                                  // Contact email address for this instance +	ContactAccountUsername string       `validate:"required_with=ContactAccountID" bun:",nullzero"`                                   // Username of the contact account for this instance +	ContactAccountID       string       `validate:"required_with=ContactAccountUsername,omitempty,ulid" bun:"type:CHAR(26),nullzero"` // Contact account ID in the database for this instance +	ContactAccount         *Account     `validate:"-" bun:"rel:belongs-to"`                                                           // account corresponding to contactAccountID +	Reputation             int64        `validate:"-" bun:",notnull,default:0"`                                                       // Reputation score of this instance +	Version                string       `validate:"-" bun:",nullzero"`                                                                // Version of the software used on this instance +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/mediaattachment.go b/internal/db/bundb/migrations/20210816411877_struct_validation/mediaattachment.go new file mode 100644 index 000000000..53f226ad7 --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/mediaattachment.go @@ -0,0 +1,117 @@ +/* +   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 gtsmodel + +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                string           `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                       // id of this item in the database +	CreatedAt         time.Time        `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                // when was item created +	UpdatedAt         time.Time        `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                // when was item last updated +	StatusID          string           `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                        // ID of the status to which this is attached +	URL               string           `validate:"required_without=RemoteURL,omitempty,url" bun:",nullzero"`                           // Where can the attachment be retrieved on *this* server +	RemoteURL         string           `validate:"required_without=URL,omitempty,url" bun:",nullzero"`                                 // Where can the attachment be retrieved on a remote server (empty for local media) +	Type              FileType         `validate:"oneof=Image Gif Audio Video Unknown" bun:",notnull"`                                 // Type of file (image/gif/audio/video) +	FileMeta          FileMeta         `validate:"required" bun:",nullzero,notnull"`                                                   // Metadata about the file +	AccountID         string           `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`                                 // To which account does this attachment belong +	Account           *Account         `validate:"-" bun:"rel:has-one"`                                                                // Account corresponding to accountID +	Description       string           `validate:"-" bun:",nullzero"`                                                                  // Description of the attachment (for screenreaders) +	ScheduledStatusID string           `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                        // To which scheduled status does this attachment belong +	Blurhash          string           `validate:"required_if=Type Image,required_if=Type Gif,required_if=Type Video" bun:",nullzero"` // What is the generated blurhash of this attachment +	Processing        ProcessingStatus `validate:"oneof=0 1 2 666" bun:",notnull,default:2"`                                           // What is the processing status of this attachment +	File              File             `validate:"required" bun:",notnull,nullzero"`                                                   // metadata for the whole file +	Thumbnail         Thumbnail        `validate:"required" bun:",notnull,nullzero"`                                                   // small image thumbnail derived from a larger image, video, or audio file. +	Avatar            bool             `validate:"-" bun:",notnull,default:false"`                                                     // Is this attachment being used as an avatar? +	Header            bool             `validate:"-" bun:",notnull,default:false"`                                                     // Is this attachment being used as a header? +} + +// File refers to the metadata for the whole file +type File struct { +	Path        string    `validate:"required,file" bun:",nullzero,notnull"`               // Path of the file in storage. +	ContentType string    `validate:"required" bun:",nullzero,notnull"`                    // MIME content type of the file. +	FileSize    int       `validate:"required" bun:",nullzero,notnull"`                    // File size in bytes +	UpdatedAt   time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"` // When was the file last updated. +} + +// Thumbnail refers to a small image thumbnail derived from a larger image, video, or audio file. +type Thumbnail struct { +	Path        string    `validate:"required,file" bun:",nullzero,notnull"`                    // Path of the file in storage. +	ContentType string    `validate:"required" bun:",nullzero,notnull"`                         // MIME content type of the file. +	FileSize    int       `validate:"required" bun:",nullzero,notnull"`                         // File size in bytes +	UpdatedAt   time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`      // When was the file last updated. +	URL         string    `validate:"required_without=RemoteURL,omitempty,url" bun:",nullzero"` // What is the URL of the thumbnail on the local server +	RemoteURL   string    `validate:"required_without=URL,omitempty,url" bun:",nullzero"`       // What is the remote URL of the thumbnail (empty for local media) +} + +// ProcessingStatus refers to how far along in the processing stage the attachment is. +type ProcessingStatus int + +// MediaAttachment processing states. +const ( +	ProcessingStatusReceived   ProcessingStatus = 0   // ProcessingStatusReceived indicates the attachment has been received and is awaiting processing. No thumbnail available yet. +	ProcessingStatusProcessing ProcessingStatus = 1   // ProcessingStatusProcessing indicates the attachment is currently being processed. Thumbnail is available but full media is not. +	ProcessingStatusProcessed  ProcessingStatus = 2   // ProcessingStatusProcessed indicates the attachment has been fully processed and is ready to be served. +	ProcessingStatusError      ProcessingStatus = 666 // ProcessingStatusError indicates something went wrong processing the attachment and it won't be tried again--these can be deleted. +) + +// FileType refers to the file type of the media attaachment. +type FileType string + +// MediaAttachment file types. +const ( +	FileTypeImage   FileType = "Image"   // FileTypeImage is for jpegs and pngs +	FileTypeGif     FileType = "Gif"     // FileTypeGif is for native gifs and soundless videos that have been converted to gifs +	FileTypeAudio   FileType = "Audio"   // FileTypeAudio is for audio-only files (no video) +	FileTypeVideo   FileType = "Video"   // FileTypeVideo is for files with audio + visual +	FileTypeUnknown FileType = "Unknown" // FileTypeUnknown is for unknown file types (surprise surprise!) +) + +// FileMeta describes metadata about the actual contents of the file. +type FileMeta struct { +	Original Original `validate:"required"` +	Small    Small +	Focus    Focus +} + +// Small can be used for a thumbnail of any media type +type Small struct { +	Width  int     `validate:"required_with=Height Size Aspect"`  // width in pixels +	Height int     `validate:"required_with=Width Size Aspect"`   // height in pixels +	Size   int     `validate:"required_with=Width Height Aspect"` // size in pixels (width * height) +	Aspect float64 `validate:"required_with=Widhth Height Size"`  // aspect ratio (width / height) +} + +// Original can be used for original metadata for any media type +type Original struct { +	Width  int     `validate:"required_with=Height Size Aspect"`  // width in pixels +	Height int     `validate:"required_with=Width Size Aspect"`   // height in pixels +	Size   int     `validate:"required_with=Width Height Aspect"` // size in pixels (width * height) +	Aspect float64 `validate:"required_with=Widhth Height Size"`  // aspect ratio (width / height) +} + +// Focus describes the 'center' of the image for display purposes. +// X and Y should each be between -1 and 1 +type Focus struct { +	X float32 `validate:"omitempty,max=1,min=-1"` +	Y float32 `validate:"omitempty,max=1,min=-1"` +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/mention.go b/internal/db/bundb/migrations/20210816411877_struct_validation/mention.go new file mode 100644 index 000000000..d8359745d --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/mention.go @@ -0,0 +1,59 @@ +/* +   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 gtsmodel + +import "time" + +// Mention refers to the 'tagging' or 'mention' of a user within a status. +type Mention struct { +	ID               string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database +	CreatedAt        time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created +	UpdatedAt        time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated +	StatusID         string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // ID of the status this mention originates from +	Status           *Status   `validate:"-" bun:"rel:belongs-to"`                                       // status referred to by statusID +	OriginAccountID  string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // ID of the mention creator account +	OriginAccountURI string    `validate:"url" bun:",nullzero,notnull"`                                  // ActivityPub URI of the originator/creator of the mention +	OriginAccount    *Account  `validate:"-" bun:"rel:belongs-to"`                                       // account referred to by originAccountID +	TargetAccountID  string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // Mention target/receiver account ID +	TargetAccount    *Account  `validate:"-" bun:"rel:belongs-to"`                                       // account referred to by targetAccountID +	Silent           bool      `validate:"-" bun:",notnull,default:false"`                               // Prevent this mention from generating a notification? + +	/* +		NON-DATABASE CONVENIENCE FIELDS +		These fields are just for convenience while passing the mention +		around internally, to make fewer database calls and whatnot. They're +		not meant to be put in the database! +	*/ + +	// NameString is for putting in the namestring of the mentioned user +	// before the mention is dereferenced. Should be in a form along the lines of: +	// @whatever_username@example.org +	// +	// This will not be put in the database, it's just for convenience. +	NameString string `validate:"-" 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 `validate:"-" 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 `validate:"-" bun:"-"` +	// A pointer to the gtsmodel account of the mentioned account. +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/notification.go b/internal/db/bundb/migrations/20210816411877_struct_validation/notification.go new file mode 100644 index 000000000..bb69bc8d4 --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/notification.go @@ -0,0 +1,49 @@ +/* +   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 gtsmodel + +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               string           `validate:"ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                                                                                                                                             // id of this item in the database +	CreatedAt        time.Time        `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                                                                                                                             // when was item created +	NotificationType NotificationType `validate:"oneof=follow follow_request mention reblog favourite poll status" bun:",nullzero,notnull"`                                                                                                        // Type of this notification +	TargetAccountID  string           `validate:"ulid" bun:"type:CHAR(26),nullzero,notnull"`                                                                                                                                                       // Which account does this notification target (ie., who will receive the notification?) +	TargetAccount    *Account         `validate:"-" bun:"rel:belongs-to"`                                                                                                                                                                          // Which account performed the action that created this notification? +	OriginAccountID  string           `validate:"ulid" bun:"type:CHAR(26),nullzero,notnull"`                                                                                                                                                       // ID of the account that performed the action that created the notification. +	OriginAccount    *Account         `validate:"-" bun:"rel:belongs-to"`                                                                                                                                                                          // Account corresponding to originAccountID +	StatusID         string           `validate:"required_if=NotificationType mention,required_if=NotificationType reblog,required_if=NotificationType favourite,required_if=NotificationType status,omitempty,ulid" bun:"type:CHAR(26),nullzero"` // If the notification pertains to a status, what is the database ID of that status? +	Status           *Status          `validate:"-" bun:"rel:belongs-to"`                                                                                                                                                                          // Status corresponding to statusID +	Read             bool             `validate:"-" bun:",notnull,default:false"`                                                                                                                                                                  // Notification has been seen/read +} + +// NotificationType describes the reason/type of this notification. +type NotificationType string + +// Notification Types +const ( +	NotificationFollow        NotificationType = "follow"         // NotificationFollow -- someone followed you +	NotificationFollowRequest NotificationType = "follow_request" // NotificationFollowRequest -- someone requested to follow you +	NotificationMention       NotificationType = "mention"        // NotificationMention -- someone mentioned you in their status +	NotificationReblog        NotificationType = "reblog"         // NotificationReblog -- someone boosted one of your statuses +	NotificationFave          NotificationType = "favourite"      // NotificationFave -- someone faved/liked one of your statuses +	NotificationPoll          NotificationType = "poll"           // NotificationPoll -- a poll you voted in or created has ended +	NotificationStatus        NotificationType = "status"         // NotificationStatus -- someone you enabled notifications for has posted a status. +) diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/routersession.go b/internal/db/bundb/migrations/20210816411877_struct_validation/routersession.go new file mode 100644 index 000000000..374264fe4 --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/routersession.go @@ -0,0 +1,26 @@ +/* +   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 gtsmodel + +// RouterSession is used to store and retrieve settings for a router session. +type RouterSession struct { +	ID    string `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull"` +	Auth  []byte `validate:"required,len=32" bun:"type:bytea,notnull,nullzero"` +	Crypt []byte `validate:"required,len=32" bun:"type:bytea,notnull,nullzero"` +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/status.go b/internal/db/bundb/migrations/20210816411877_struct_validation/status.go new file mode 100644 index 000000000..d81a45ec3 --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/status.go @@ -0,0 +1,116 @@ +/* +   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 gtsmodel + +import ( +	"time" +) + +// Status represents a user-created 'post' or 'status' in the database, either remote or local +type Status struct { +	ID                       string             `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                              // id of this item in the database +	CreatedAt                time.Time          `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                       // when was item created +	UpdatedAt                time.Time          `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                       // when was item last updated +	URI                      string             `validate:"required,url" bun:",unique,nullzero,notnull"`                                               // activitypub URI of this status +	URL                      string             `validate:"url" bun:",nullzero"`                                                                       // web url for viewing this status +	Content                  string             `validate:"-" bun:",nullzero"`                                                                         // content of this status; likely html-formatted but not guaranteed +	AttachmentIDs            []string           `validate:"dive,ulid" bun:"attachments,array,nullzero"`                                                // Database IDs of any media attachments associated with this status +	Attachments              []*MediaAttachment `validate:"-" bun:"attached_media,rel:has-many"`                                                       // Attachments corresponding to attachmentIDs +	TagIDs                   []string           `validate:"dive,ulid" bun:"tags,array,nullzero"`                                                       // Database IDs of any tags used in this status +	Tags                     []*Tag             `validate:"-" bun:"attached_tags,m2m:status_to_tags"`                                                  // Tags corresponding to tagIDs. https://bun.uptrace.dev/guide/relations.html#many-to-many-relation +	MentionIDs               []string           `validate:"dive,ulid" bun:"mentions,array,nullzero"`                                                   // Database IDs of any mentions in this status +	Mentions                 []*Mention         `validate:"-" bun:"attached_mentions,rel:has-many"`                                                    // Mentions corresponding to mentionIDs +	EmojiIDs                 []string           `validate:"dive,ulid" bun:"emojis,array,nullzero"`                                                     // Database IDs of any emojis used in this status +	Emojis                   []*Emoji           `validate:"-" bun:"attached_emojis,m2m:status_to_emojis"`                                              // Emojis corresponding to emojiIDs. https://bun.uptrace.dev/guide/relations.html#many-to-many-relation +	Local                    bool               `validate:"-" bun:",notnull,default:false"`                                                            // is this status from a local account? +	AccountID                string             `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`                                        // which account posted this status? +	Account                  *Account           `validate:"-" bun:"rel:belongs-to"`                                                                    // account corresponding to accountID +	AccountURI               string             `validate:"required,url" bun:",nullzero,notnull"`                                                      // activitypub uri of the owner of this status +	InReplyToID              string             `validate:"required_with=InReplyToURI InReplyToAccountID,omitempty,ulid" bun:"type:CHAR(26),nullzero"` // id of the status this status replies to +	InReplyToURI             string             `validate:"required_with=InReplyToID InReplyToAccountID,omitempty,url" bun:",nullzero"`                // activitypub uri of the status this status is a reply to +	InReplyToAccountID       string             `validate:"required_with=InReplyToID InReplyToURI,omitempty,ulid" bun:"type:CHAR(26),nullzero"`        // id of the account that this status replies to +	InReplyTo                *Status            `validate:"-" bun:"-"`                                                                                 // status corresponding to inReplyToID +	InReplyToAccount         *Account           `validate:"-" bun:"rel:belongs-to"`                                                                    // account corresponding to inReplyToAccountID +	BoostOfID                string             `validate:"required_with=BoostOfAccountID,omitempty,ulid" bun:"type:CHAR(26),nullzero"`                // id of the status this status is a boost of +	BoostOfAccountID         string             `validate:"required_with=BoostOfID,omitempty,ulid" bun:"type:CHAR(26),nullzero"`                       // id of the account that owns the boosted status +	BoostOf                  *Status            `validate:"-" bun:"-"`                                                                                 // status that corresponds to boostOfID +	BoostOfAccount           *Account           `validate:"-" bun:"rel:belongs-to"`                                                                    // account that corresponds to boostOfAccountID +	ContentWarning           string             `validate:"-" bun:",nullzero"`                                                                         // cw string for this status +	Visibility               Visibility         `validate:"-" bun:",nullzero,notnull"`                                                                 // visibility entry for this status +	Sensitive                bool               `validate:"-" bun:",notnull,default:false"`                                                            // mark the status as sensitive? +	Language                 string             `validate:"-" bun:",nullzero"`                                                                         // what language is this status written in? +	CreatedWithApplicationID string             `validate:"required_if=Local true,omitempty,ulid" bun:"type:CHAR(26),nullzero"`                        // Which application was used to create this status? +	CreatedWithApplication   *Application       `validate:"-" bun:"rel:belongs-to"`                                                                    // application corresponding to createdWithApplicationID +	VisibilityAdvanced       VisibilityAdvanced `validate:"required" bun:",nullzero,notnull" `                                                         // advanced visibility for this status +	ActivityStreamsType      string             `validate:"required" bun:",nullzero,notnull"`                                                          // What is the activitystreams type of this status? See: https://www.w3.org/TR/activitystreams-vocabulary/#object-types. Will probably almost always be Note but who knows!. +	Text                     string             `validate:"-" bun:",nullzero"`                                                                         // Original text of the status without formatting +	Pinned                   bool               `validate:"-" bun:",notnull,default:false" `                                                           // Has this status been pinned by its owner? +} + +// StatusToTag is an intermediate struct to facilitate the many2many relationship between a status and one or more tags. +type StatusToTag struct { +	StatusID string  `validate:"ulid,required" bun:"type:CHAR(26),unique:statustag,nullzero,notnull"` +	Status   *Status `validate:"-" bun:"rel:belongs-to"` +	TagID    string  `validate:"ulid,required" bun:"type:CHAR(26),unique:statustag,nullzero,notnull"` +	Tag      *Tag    `validate:"-" 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  `validate:"ulid,required" bun:"type:CHAR(26),unique:statusemoji,nullzero,notnull"` +	Status   *Status `validate:"-" bun:"rel:belongs-to"` +	EmojiID  string  `validate:"ulid,required" bun:"type:CHAR(26),unique:statusemoji,nullzero,notnull"` +	Emoji    *Emoji  `validate:"-" bun:"rel:belongs-to"` +} + +// Visibility represents the visibility granularity of a status. +type Visibility string + +const ( +	// VisibilityPublic means this status will be visible to everyone on all timelines. +	VisibilityPublic Visibility = "public" +	// VisibilityUnlocked means this status will be visible to everyone, but will only show on home timeline to followers, and in lists. +	VisibilityUnlocked Visibility = "unlocked" +	// VisibilityFollowersOnly means this status is viewable to followers only. +	VisibilityFollowersOnly Visibility = "followers_only" +	// VisibilityMutualsOnly means this status is visible to mutual followers only. +	VisibilityMutualsOnly Visibility = "mutuals_only" +	// VisibilityDirect means this status is visible only to mentioned recipients. +	VisibilityDirect Visibility = "direct" +	// VisibilityDefault is used when no other setting can be found. +	VisibilityDefault Visibility = VisibilityUnlocked +) + +// VisibilityAdvanced models flags for fine-tuning visibility and interactivity of a status. +// +// All flags default to true. +// +// If PUBLIC is selected, flags will all be overwritten to TRUE regardless of what is selected. +// +// If UNLOCKED is selected, any flags can be turned on or off in any combination. +// +// If FOLLOWERS-ONLY or MUTUALS-ONLY are selected, boostable will always be FALSE. Other flags can be turned on or off as desired. +// +// If DIRECT is selected, boostable will be FALSE, and all other flags will be TRUE. +type VisibilityAdvanced struct { +	Federated bool `validate:"-" bun:",notnull,default:true"` // This status will be federated beyond the local timeline(s) +	Boostable bool `validate:"-" bun:",notnull,default:true"` // This status can be boosted/reblogged +	Replyable bool `validate:"-" bun:",notnull,default:true"` // This status can be replied to +	Likeable  bool `validate:"-" bun:",notnull,default:true"` // This status can be liked/faved +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/statusbookmark.go b/internal/db/bundb/migrations/20210816411877_struct_validation/statusbookmark.go new file mode 100644 index 000000000..76a2a866d --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/statusbookmark.go @@ -0,0 +1,33 @@ +/* +   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 gtsmodel + +import "time" + +// StatusBookmark refers to one account having a 'bookmark' of the status of another account. +type StatusBookmark struct { +	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database +	CreatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created +	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id of the account that created ('did') the bookmark +	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // account that created the bookmark +	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id the account owning the bookmarked status +	TargetAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                       // account owning the bookmarked status +	StatusID        string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // database id of the status that has been bookmarked +	Status          *Status   `validate:"-" bun:"rel:belongs-to"`                                       // the bookmarked status +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/statusfave.go b/internal/db/bundb/migrations/20210816411877_struct_validation/statusfave.go new file mode 100644 index 000000000..6647e941a --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/statusfave.go @@ -0,0 +1,34 @@ +/* +   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 gtsmodel + +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              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database +	CreatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created +	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id of the account that created ('did') the fave +	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // account that created the fave +	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id the account owning the faved status +	TargetAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                       // account owning the faved status +	StatusID        string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // database id of the status that has been 'faved' +	Status          *Status   `validate:"-" bun:"rel:belongs-to"`                                       // the faved status +	URI             string    `validate:"required,url" bun:",nullzero,notnull"`                         // ActivityPub URI of this fave +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/statusmute.go b/internal/db/bundb/migrations/20210816411877_struct_validation/statusmute.go new file mode 100644 index 000000000..70789e557 --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/statusmute.go @@ -0,0 +1,33 @@ +/* +   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 gtsmodel + +import "time" + +// StatusMute refers to one account having muted the status of another account or its own. +type StatusMute struct { +	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database +	CreatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created +	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id of the account that created ('did') the mute +	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // pointer to the account specified by accountID +	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id the account owning the muted status (can be the same as accountID) +	TargetAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                       // pointer to the account specified by targetAccountID +	StatusID        string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // database id of the status that has been muted +	Status          *Status   `validate:"-" bun:"rel:belongs-to"`                                       // pointer to the muted status specified by statusID +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/tag.go b/internal/db/bundb/migrations/20210816411877_struct_validation/tag.go new file mode 100644 index 000000000..14ff26f87 --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/tag.go @@ -0,0 +1,34 @@ +/* +   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 gtsmodel + +import "time" + +// Tag represents a hashtag for gathering public statuses together. +type Tag struct { +	ID                     string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database +	CreatedAt              time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created +	UpdatedAt              time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated +	URL                    string    `validate:"required,url" bun:",nullzero,notnull"`                         // Href/web address of this tag, eg https://example.org/tags/somehashtag +	Name                   string    `validate:"required" bun:",unique,nullzero,notnull"`                      // name of this tag -- the tag without the hash part +	FirstSeenFromAccountID string    `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                  // Which account ID is the first one we saw using this tag? +	Useable                bool      `validate:"-" bun:",notnull,default:true"`                                // can our instance users use this tag? +	Listable               bool      `validate:"-" bun:",notnull,default:true"`                                // can our instance users look up this tag? +	LastStatusAt           time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was this tag last used? +} diff --git a/internal/db/bundb/migrations/20210816411877_struct_validation/user.go b/internal/db/bundb/migrations/20210816411877_struct_validation/user.go new file mode 100644 index 000000000..e0568d6a0 --- /dev/null +++ b/internal/db/bundb/migrations/20210816411877_struct_validation/user.go @@ -0,0 +1,70 @@ +/* +   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 gtsmodel + +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 { +	ID                     string       `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database +	CreatedAt              time.Time    `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created +	UpdatedAt              time.Time    `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated +	Email                  string       `validate:"required_with=ConfirmedAt" bun:",nullzero,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 +	AccountID              string       `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull,unique"`    // The id of the local gtsmodel.Account entry for this user. +	Account                *Account     `validate:"-" bun:"rel:belongs-to"`                                       // Pointer to the account of this user that corresponds to AccountID. +	EncryptedPassword      string       `validate:"required" bun:",nullzero,notnull"`                             // 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. +	SignUpIP               net.IP       `validate:"-" bun:",nullzero"`                                            // From what IP was this user created? +	CurrentSignInAt        time.Time    `validate:"-" bun:",nullzero"`                                            // When did the user sign in with their current session. +	CurrentSignInIP        net.IP       `validate:"-" bun:",nullzero"`                                            // What's the most recent IP of this user +	LastSignInAt           time.Time    `validate:"-" bun:",nullzero"`                                            // When did this user last sign in? +	LastSignInIP           net.IP       `validate:"-" bun:",nullzero"`                                            // What's the previous IP of this user? +	SignInCount            int          `validate:"-" bun:",nullzero,notnull,default:0"`                          // How many times has this user signed in? +	InviteID               string       `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                  // id of the user who invited this user (who let this joker in?) +	ChosenLanguages        []string     `validate:"-" bun:",nullzero"`                                            // What languages does this user want to see? +	FilteredLanguages      []string     `validate:"-" bun:",nullzero"`                                            // What languages does this user not want to see? +	Locale                 string       `validate:"-" bun:",nullzero"`                                            // In what timezone/locale is this user located? +	CreatedByApplicationID string       `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // Which application id created this user? See gtsmodel.Application +	CreatedByApplication   *Application `validate:"-" bun:"rel:belongs-to"`                                       // Pointer to the application corresponding to createdbyapplicationID. +	LastEmailedAt          time.Time    `validate:"-" bun:",nullzero"`                                            // When was this user last contacted by email. +	ConfirmationToken      string       `validate:"required_with=ConfirmationSentAt" bun:",nullzero"`             // What confirmation token did we send this user/what are we expecting back? +	ConfirmationSentAt     time.Time    `validate:"required_with=ConfirmationToken" bun:",nullzero"`              // When did we send email confirmation to this user? +	ConfirmedAt            time.Time    `validate:"required_with=Email" bun:",nullzero"`                          // When did the user confirm their email address +	UnconfirmedEmail       string       `validate:"required_without=Email" bun:",nullzero"`                       // Email address that hasn't yet been confirmed +	Moderator              bool         `validate:"-" bun:",notnull,default:false"`                               // Is this user a moderator? +	Admin                  bool         `validate:"-" bun:",notnull,default:false"`                               // Is this user an admin? +	Disabled               bool         `validate:"-" bun:",notnull,default:false"`                               // Is this user disabled from posting? +	Approved               bool         `validate:"-" bun:",notnull,default:false"`                               // Has this user been approved by a moderator? +	ResetPasswordToken     string       `validate:"required_with=ResetPasswordSentAt" bun:",nullzero"`            // The generated token that the user can use to reset their password +	ResetPasswordSentAt    time.Time    `validate:"required_with=ResetPasswordToken" bun:",nullzero"`             // When did we email the user their reset-password email? + +	EncryptedOTPSecret     string    `validate:"-" bun:",nullzero"` +	EncryptedOTPSecretIv   string    `validate:"-" bun:",nullzero"` +	EncryptedOTPSecretSalt string    `validate:"-" bun:",nullzero"` +	OTPRequiredForLogin    bool      `validate:"-" bun:",notnull,default:false"` +	OTPBackupCodes         []string  `validate:"-" bun:",nullzero"` +	ConsumedTimestamp      int       `validate:"-" bun:",nullzero"` +	RememberToken          string    `validate:"-" bun:",nullzero"` +	SignInToken            string    `validate:"-" bun:",nullzero"` +	SignInTokenSentAt      time.Time `validate:"-" bun:",nullzero"` +	WebauthnID             string    `validate:"-" bun:",nullzero"` +} | 
