diff options
Diffstat (limited to 'internal')
28 files changed, 1114 insertions, 39 deletions
| diff --git a/internal/api/client/auth/auth_test.go b/internal/api/client/auth/auth_test.go index 59a8d7b16..ca606e8f2 100644 --- a/internal/api/client/auth/auth_test.go +++ b/internal/api/client/auth/auth_test.go @@ -109,21 +109,6 @@ func (suite *AuthTestSuite) SetupTest() {  	}  	suite.db = db - -	models := []interface{}{ -		>smodel.Client{}, -		>smodel.Token{}, -		>smodel.User{}, -		>smodel.Account{}, -		>smodel.Application{}, -	} - -	for _, m := range models { -		if err := suite.db.CreateTable(context.Background(), m); err != nil { -			logrus.Panicf("db connection error: %s", err) -		} -	} -  	suite.oauthServer = oauth.New(context.Background(), suite.db)  	if err := suite.db.Put(context.Background(), suite.testAccount); err != nil { diff --git a/internal/cliactions/admin/trans/import.go b/internal/cliactions/admin/trans/import.go index 82defde74..9ab85d62f 100644 --- a/internal/cliactions/admin/trans/import.go +++ b/internal/cliactions/admin/trans/import.go @@ -43,10 +43,6 @@ var Import cliactions.GTSAction = func(ctx context.Context, c *config.Config) er  		return errors.New("no path set")  	} -	if err := dbConn.CreateAllTables(ctx); err != nil { -		return err -	} -  	if err := importer.Import(ctx, path); err != nil {  		return err  	} diff --git a/internal/cliactions/server/server.go b/internal/cliactions/server/server.go index 55a554439..26f3685a2 100644 --- a/internal/cliactions/server/server.go +++ b/internal/cliactions/server/server.go @@ -58,10 +58,6 @@ var Start cliactions.GTSAction = func(ctx context.Context, c *config.Config) err  		return fmt.Errorf("error creating dbservice: %s", err)  	} -	if err := dbService.CreateAllTables(ctx); err != nil { -		return fmt.Errorf("error creating database tables: %s", err) -	} -  	if err := dbService.CreateInstanceAccount(ctx); err != nil {  		return fmt.Errorf("error creating instance account: %s", err)  	} diff --git a/internal/db/bundb/basic.go b/internal/db/bundb/basic.go index 464d40e3e..2ff8dcb9b 100644 --- a/internal/db/bundb/basic.go +++ b/internal/db/bundb/basic.go @@ -21,6 +21,7 @@ package bundb  import (  	"context"  	"errors" +  	"github.com/sirupsen/logrus"  	"github.com/superseriousbusiness/gotosocial/internal/config" diff --git a/internal/db/bundb/migrations/20211113114307_init.go b/internal/db/bundb/migrations/20211113114307_init.go new file mode 100644 index 000000000..d72350d2d --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init.go @@ -0,0 +1,72 @@ +/* +   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 migrations + +import ( +	"context" + +	gtsmodel "github.com/superseriousbusiness/gotosocial/internal/db/bundb/migrations/20211113114307_init" +	"github.com/uptrace/bun" +) + +func init() { +	up := func(ctx context.Context, db *bun.DB) error { +		models := []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{}, +		} +		for _, i := range models { +			if _, err := db.NewCreateTable().Model(i).IfNotExists().Exec(ctx); err != nil { +				return err +			} +		} +		return nil +	} + +	down := func(ctx context.Context, db *bun.DB) error { +		return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error { +			return nil +		}) +	} + +	if err := Migrations.Register(up, down); err != nil { +		panic(err) +	} +} diff --git a/internal/db/bundb/migrations/20211113114307_init/README.md b/internal/db/bundb/migrations/20211113114307_init/README.md new file mode 100644 index 000000000..2e55d3a57 --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/README.md @@ -0,0 +1,7 @@ +A note on when we should set data structures linked to objects in the database to use the +bun `nullzero` tag -- this should only be done if the member type is a pointer, or if the +this primitive type is literally invalid with an empty value (e.g. media IDs which when +empty signifies a null database value, compared to say an account note which when empty +could mean either an empty note OR null database value). + +Obviously it is a little more complex than this in practice, but keep it in mind!
\ No newline at end of file diff --git a/internal/db/bundb/migrations/20211113114307_init/account.go b/internal/db/bundb/migrations/20211113114307_init/account.go new file mode 100644 index 000000000..67a7e435a --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/account.go @@ -0,0 +1,99 @@ +/* +   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 contains types used *internally* by GoToSocial and added/removed/selected from the database. +// These types should never be serialized and/or sent out via public APIs, as they contain sensitive information. +// The annotation used on these structs is for handling them via the bun-db ORM. +// See here for more info on bun model annotations: https://bun.uptrace.dev/guide/models.html +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:"type:timestamptz,nullzero,notnull,default:current_timestamp"`                                        // when was item created +	UpdatedAt               time.Time        `validate:"-" bun:"type:timestamptz,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``. 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:""`                                                                                                   // 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:""`                                                                                                   // A note that this account has on their profile (ie., the account's bio/description of themselves) +	Memorial                bool             `validate:"-" bun:",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 (TODO: migrate to be AlsoKnownAsID) +	MovedToAccountID        string           `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                                                // This account has moved this account id in the database +	Bot                     bool             `validate:"-" bun:",default:false"`                                                                                     // Does this account identify itself as a bot? +	Reason                  string           `validate:"-" bun:""`                                                                                                   // What reason was given for signing up when this account was created? +	Locked                  bool             `validate:"-" bun:",default:true"`                                                                                      // Does this account need an approval for new followers? +	Discoverable            bool             `validate:"-" bun:",default:false"`                                                                                     // Should this account be shown in the instance's profile directory? +	Privacy                 Visibility       `validate:"required_without=Domain,omitempty,oneof=public unlocked followers_only mutuals_only direct" bun:",nullzero"` // Default post privacy for this account +	Sensitive               bool             `validate:"-" bun:",default:false"`                                                                                     // Set posts from this account to sensitive by default? +	Language                string           `validate:"omitempty,bcp47_language_tag" 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:"required_without=Domain,omitempty,url" bun:",nullzero,unique"`                                               // Web URL for this account's profile +	LastWebfingeredAt       time.Time        `validate:"required_with=Domain" bun:"type:timestamptz,nullzero"`                                                       // Last time this account was refreshed/located with webfinger. +	InboxURI                string           `validate:"required_without=Domain,omitempty,url" bun:",nullzero,unique"`                                               // Address of this account's ActivityPub inbox, for sending activity to +	OutboxURI               string           `validate:"required_without=Domain,omitempty,url" bun:",nullzero,unique"`                                               // Address of this account's activitypub outbox +	FollowingURI            string           `validate:"required_without=Domain,omitempty,url" bun:",nullzero,unique"`                                               // URI for getting the following list of this account +	FollowersURI            string           `validate:"required_without=Domain,omitempty,url" bun:",nullzero,unique"`                                               // URI for getting the followers list of this account +	FeaturedCollectionURI   string           `validate:"required_without=Domain,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,url" bun:",nullzero,notnull,unique"`                                                                // Web-reachable location of this account's public key +	SensitizedAt            time.Time        `validate:"-" bun:"type:timestamptz,nullzero"`                                                                          // When was this account set to have all its media shown as sensitive? +	SilencedAt              time.Time        `validate:"-" bun:"type:timestamptz,nullzero"`                                                                          // When was this account silenced (eg., statuses only visible to followers, not public)? +	SuspendedAt             time.Time        `validate:"-" bun:"type:timestamptz,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:",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). +} + +// Relationship describes a requester's relationship with another account. +type Relationship struct { +	ID                  string // The account id. +	Following           bool   // Are you following this user? +	ShowingReblogs      bool   // Are you receiving this user's boosts in your home timeline? +	Notifying           bool   // Have you enabled notifications for this user? +	FollowedBy          bool   // Are you followed by this user? +	Blocking            bool   // Are you blocking this user? +	BlockedBy           bool   // Is this user blocking you? +	Muting              bool   // Are you muting this user? +	MutingNotifications bool   // Are you muting notifications from this user? +	Requested           bool   // Do you have a pending follow request for this user? +	DomainBlocking      bool   // Are you blocking this user's domain? +	Endorsed            bool   // Are you featuring this user on your profile? +	Note                string // Your note on this account. +} diff --git a/internal/db/bundb/migrations/20211113114307_init/application.go b/internal/db/bundb/migrations/20211113114307_init/application.go new file mode 100644 index 000000000..29058426a --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/application.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" + +// 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,unique"`        // id of this item in the database +	CreatedAt    time.Time `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created +	UpdatedAt    time.Time `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item last updated +	Name         string    `validate:"required" bun:",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,uri" bun:",nullzero,notnull"`                                // redirect uri requested by the application for oauth2 flow +	ClientID     string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`                  // 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:",notnull"`                                             // scopes requested when this app was created +} diff --git a/internal/db/bundb/migrations/20211113114307_init/block.go b/internal/db/bundb/migrations/20211113114307_init/block.go new file mode 100644 index 000000000..5a9b59c2c --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/block.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" + +// 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:"type:timestamptz,nullzero,notnull,default:current_timestamp"`      // when was item created +	UpdatedAt       time.Time `validate:"-" bun:"type:timestamptz,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,nullzero"` // 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,nullzero"` // 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/20211113114307_init/client.go b/internal/db/bundb/migrations/20211113114307_init/client.go new file mode 100644 index 000000000..20ca03897 --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/client.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" + +// Client is a wrapper for OAuth client details. +type Client 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:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created +	UpdatedAt time.Time `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item last updated +	Secret    string    `validate:"required,uuid" bun:",nullzero,notnull"`                               // secret generated when client was created +	Domain    string    `validate:"required,uri" bun:",nullzero,notnull"`                                // domain requested for client +	UserID    string    `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                         // id of the user that this client acts on behalf of +} diff --git a/internal/db/bundb/migrations/20211113114307_init/domainblock.go b/internal/db/bundb/migrations/20211113114307_init/domainblock.go new file mode 100644 index 000000000..da3368e0c --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/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:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created +	UpdatedAt          time.Time `validate:"-" bun:"type:timestamptz,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:""`                                                            // Private comment on this block, viewable to admins +	PublicComment      string    `validate:"-" bun:""`                                                            // Public comment on this block, viewable (optionally) by everyone +	Obfuscate          bool      `validate:"-" bun:",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/20211113114307_init/emaildomainblock.go b/internal/db/bundb/migrations/20211113114307_init/emaildomainblock.go new file mode 100644 index 000000000..43a6ce2be --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/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:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created +	UpdatedAt          time.Time `validate:"-" bun:"type:timestamptz,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/20211113114307_init/emoji.go b/internal/db/bundb/migrations/20211113114307_init/emoji.go new file mode 100644 index 000000000..7db8c694c --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/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:"type:timestamptz,nullzero,notnull,default:current_timestamp"`                         // when was item created +	UpdatedAt              time.Time `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"`                         // when was item last updated +	Shortcode              string    `validate:"required" bun:",nullzero,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:"type:timestamptz,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/20211113114307_init/follow.go b/internal/db/bundb/migrations/20211113114307_init/follow.go new file mode 100644 index 000000000..dc54970dd --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/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:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created +	UpdatedAt       time.Time `validate:"-" bun:"type:timestamptz,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,nullzero"` // 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,nullzero"` // Who is the target of this follow ? +	TargetAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                              // Account corresponding to targetAccountID +	ShowReblogs     bool      `validate:"-" bun:",default:true"`                                               // Does this follow also want to see reblogs and not just posts? +	Notify          bool      `validate:"-" bun:",default:false"`                                              // does the following account want to be notified when the followed account posts? +} diff --git a/internal/db/bundb/migrations/20211113114307_init/followrequest.go b/internal/db/bundb/migrations/20211113114307_init/followrequest.go new file mode 100644 index 000000000..aad25e688 --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/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:"type:timestamptz,nullzero,notnull,default:current_timestamp"`   // when was item created +	UpdatedAt       time.Time `validate:"-" bun:"type:timestamptz,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,nullzero"` // 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,nullzero"` // Who is the target of this follow request? +	TargetAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                                // Account corresponding to targetAccountID +	ShowReblogs     bool      `validate:"-" bun:",default:true"`                                                 // Does this follow also want to see reblogs and not just posts? +	Notify          bool      `validate:"-" bun:",default:false"`                                                // does the following account want to be notified when the followed account posts? +} diff --git a/internal/db/bundb/migrations/20211113114307_init/instance.go b/internal/db/bundb/migrations/20211113114307_init/instance.go new file mode 100644 index 000000000..4193a44e2 --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/instance.go @@ -0,0 +1,43 @@ +/* +   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" + +// 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:"type:timestamptz,nullzero,notnull,default:current_timestamp"`              // when was item created +	UpdatedAt              time.Time    `validate:"-" bun:"type:timestamptz,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:""`                                                                         // 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:"type:timestamptz,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:""`                                                                         // Short description of this instance +	Description            string       `validate:"-" bun:""`                                                                         // Longer description of this instance +	Terms                  string       `validate:"-" bun:""`                                                                         // Terms and conditions of this instance +	ContactEmail           string       `validate:"omitempty,email" bun:""`                                                           // 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/20211113114307_init/mediaattachment.go b/internal/db/bundb/migrations/20211113114307_init/mediaattachment.go new file mode 100644 index 000000000..5d4af8e68 --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/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:"type:timestamptz,nullzero,notnull,default:current_timestamp"`                // when was item created +	UpdatedAt         time.Time        `validate:"-" bun:"type:timestamptz,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:",nullzero,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:""`                                                                           // 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:",notnull"`                                             // File size in bytes +	UpdatedAt   time.Time `validate:"-" bun:"type:timestamptz,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:",notnull"`                                             // File size in bytes +	UpdatedAt   time.Time `validate:"-" bun:"type:timestamptz,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/20211113114307_init/mention.go b/internal/db/bundb/migrations/20211113114307_init/mention.go new file mode 100644 index 000000000..81b9b9e72 --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/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:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created +	UpdatedAt        time.Time `validate:"-" bun:"type:timestamptz,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/20211113114307_init/notification.go b/internal/db/bundb/migrations/20211113114307_init/notification.go new file mode 100644 index 000000000..013e8ba35 --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/notification.go @@ -0,0 +1,50 @@ +/* +   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:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                                                                                                                                    // id of this item in the database +	CreatedAt        time.Time        `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"`                                                                                                                             // when was item created +	UpdatedAt        time.Time        `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"`                                                                                                                             // when was item last updated                                                                                                                            // 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/20211113114307_init/routersession.go b/internal/db/bundb/migrations/20211113114307_init/routersession.go new file mode 100644 index 000000000..34c1744bd --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/routersession.go @@ -0,0 +1,30 @@ +/* +   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" + +// 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,unique"`        // id of this item in the database +	CreatedAt time.Time `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created +	UpdatedAt time.Time `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item last updated +	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/20211113114307_init/status.go b/internal/db/bundb/migrations/20211113114307_init/status.go new file mode 100644 index 000000000..e0c339659 --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/status.go @@ -0,0 +1,101 @@ +/* +   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:"type:timestamptz,nullzero,notnull,default:current_timestamp"`                       // when was item created +	UpdatedAt                time.Time          `validate:"-" bun:"type:timestamptz,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:""`                                                                                  // content of this status; likely html-formatted but not guaranteed +	AttachmentIDs            []string           `validate:"dive,ulid" bun:"attachments,array"`                                                         // 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"`                                                                // 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"`                                                            // 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"`                                                              // 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:"oneof=public unlocked followers_only mutuals_only direct" 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 +	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:""`                                                                                  // Original text of the status without formatting +	Pinned                   bool               `validate:"-" bun:",notnull,default:false"`                                                            // Has this status been pinned by its owner? +	Federated                bool               `validate:"-" bun:",notnull"`                                                                          // This status will be federated beyond the local timeline(s) +	Boostable                bool               `validate:"-" bun:",notnull"`                                                                          // This status can be boosted/reblogged +	Replyable                bool               `validate:"-" bun:",notnull"`                                                                          // This status can be replied to +	Likeable                 bool               `validate:"-" bun:",notnull"`                                                                          // This status can be liked/faved +} + +// 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 +) diff --git a/internal/db/bundb/migrations/20211113114307_init/statusbookmark.go b/internal/db/bundb/migrations/20211113114307_init/statusbookmark.go new file mode 100644 index 000000000..73a22aeba --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/statusbookmark.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" + +// 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:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created +	UpdatedAt       time.Time `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item last updated +	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/20211113114307_init/statusfave.go b/internal/db/bundb/migrations/20211113114307_init/statusfave.go new file mode 100644 index 000000000..72a98bd17 --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/statusfave.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" + +// 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:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created +	UpdatedAt       time.Time `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item last updated +	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/20211113114307_init/statusmute.go b/internal/db/bundb/migrations/20211113114307_init/statusmute.go new file mode 100644 index 000000000..849a28c82 --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/statusmute.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" + +// 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:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created +	UpdatedAt       time.Time `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item last updated +	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/20211113114307_init/tag.go b/internal/db/bundb/migrations/20211113114307_init/tag.go new file mode 100644 index 000000000..0bb9daf0b --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/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:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created +	UpdatedAt              time.Time `validate:"-" bun:"type:timestamptz,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:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was this tag last used? +} diff --git a/internal/db/bundb/migrations/20211113114307_init/token.go b/internal/db/bundb/migrations/20211113114307_init/token.go new file mode 100644 index 000000000..19779c100 --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/token.go @@ -0,0 +1,43 @@ +/* +   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" + +// Token is a translation of the gotosocial token with the ExpiresIn fields replaced with ExpiresAt. +type Token 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:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created +	UpdatedAt           time.Time `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item last updated +	ClientID            string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`                  // ID of the client who owns this token +	UserID              string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero"`                          // ID of the user who owns this token +	RedirectURI         string    `validate:"required,uri" bun:",nullzero,notnull"`                                // Oauth redirect URI for this token +	Scope               string    `validate:"required" bun:",notnull"`                                             // Oauth scope +	Code                string    `validate:"-" bun:",pk,nullzero,notnull,default:''"`                             // Code, if present +	CodeChallenge       string    `validate:"-" bun:",nullzero"`                                                   // Code challenge, if code present +	CodeChallengeMethod string    `validate:"-" bun:",nullzero"`                                                   // Code challenge method, if code present +	CodeCreateAt        time.Time `validate:"required_with=Code" bun:"type:timestamptz,nullzero"`                  // Code created time, if code present +	CodeExpiresAt       time.Time `validate:"-" bun:"type:timestamptz,nullzero"`                                   // Code expires at -- null means the code never expires +	Access              string    `validate:"-" bun:",pk,nullzero,notnull,default:''"`                             // User level access token, if present +	AccessCreateAt      time.Time `validate:"required_with=Access" bun:"type:timestamptz,nullzero"`                // User level access token created time, if access present +	AccessExpiresAt     time.Time `validate:"-" bun:"type:timestamptz,nullzero"`                                   // User level access token expires at -- null means the token never expires +	Refresh             string    `validate:"-" bun:",pk,nullzero,notnull,default:''"`                             // Refresh token, if present +	RefreshCreateAt     time.Time `validate:"required_with=Refresh" bun:"type:timestamptz,nullzero"`               // Refresh created at, if refresh present +	RefreshExpiresAt    time.Time `validate:"-" bun:"type:timestamptz,nullzero"`                                   // Refresh expires at -- null means the refresh token never expires +} diff --git a/internal/db/bundb/migrations/20211113114307_init/user.go b/internal/db/bundb/migrations/20211113114307_init/user.go new file mode 100644 index 000000000..481e126b1 --- /dev/null +++ b/internal/db/bundb/migrations/20211113114307_init/user.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 ( +	"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:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created +	UpdatedAt              time.Time    `validate:"-" bun:"type:timestamptz,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:"type:timestamptz,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:"type:timestamptz,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:"min=0" bun:",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:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                         // 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:"type:timestamptz,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:"type:timestamptz,nullzero"`     // When did we send email confirmation to this user? +	ConfirmedAt            time.Time    `validate:"required_with=Email" bun:"type:timestamptz,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:"type:timestamptz,nullzero"`    // When did we email the user their reset-password email? +} diff --git a/internal/db/bundb/migrations/README.md b/internal/db/bundb/migrations/README.md index fee262936..06397b71b 100644 --- a/internal/db/bundb/migrations/README.md +++ b/internal/db/bundb/migrations/README.md @@ -28,29 +28,29 @@ As a template, take one of the existing migration files and modify it, or use th  package migrations  import ( -	"context" +    "context" -	"github.com/uptrace/bun" +    "github.com/uptrace/bun"  )  func init() { -	up := func(ctx context.Context, db *bun.DB) error { -		return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error { -			// your logic here +    up := func(ctx context.Context, db *bun.DB) error { +        return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error { +            // your logic here              return nil -		}) -	} +        }) +    } -	down := func(ctx context.Context, db *bun.DB) error { -		return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error { -			// your logic here +    down := func(ctx context.Context, db *bun.DB) error { +        return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error { +            // your logic here              return nil -		}) -	} +        }) +    } -	if err := Migrations.Register(up, down); err != nil { -		panic(err) -	} +    if err := Migrations.Register(up, down); err != nil { +        panic(err) +    }  }  ``` @@ -61,7 +61,7 @@ Bun requires a very specific format: 14 digits, then letters or underscores.  You can use the following bash command on your branch to generate a suitable migration filename.  ```bash -echo "$(date --utc +%Y%m%H%M%S%N | head -c 14)_$(git rev-parse --abbrev-ref HEAD).go" +echo "$(date --utc +%Y%m%d%H%M%S | head -c 14)_$(git rev-parse --abbrev-ref HEAD).go"  ```  ## Rules of thumb | 
