diff options
author | 2021-03-05 18:31:12 +0100 | |
---|---|---|
committer | 2021-03-05 18:31:12 +0100 | |
commit | 59963090cbcee395463b7767e3807ce7c0aa6f43 (patch) | |
tree | 7eade814709bb692e24ee6495b201bc1c4b34d6d /internal | |
parent | tidying up here and there (diff) | |
download | gotosocial-59963090cbcee395463b7767e3807ce7c0aa6f43.tar.xz |
create db schemas for accounts
Diffstat (limited to 'internal')
-rw-r--r-- | internal/db/actions.go | 4 | ||||
-rw-r--r-- | internal/db/db.go | 8 | ||||
-rw-r--r-- | internal/db/postgres.go | 56 | ||||
-rw-r--r-- | internal/model/account.go | 80 | ||||
-rw-r--r-- | internal/model/avatar.go | 33 | ||||
-rw-r--r-- | internal/model/header.go | 33 | ||||
-rw-r--r-- | internal/server/actions.go | 4 |
7 files changed, 210 insertions, 8 deletions
diff --git a/internal/db/actions.go b/internal/db/actions.go index ae3d8cadf..9a3012465 100644 --- a/internal/db/actions.go +++ b/internal/db/actions.go @@ -28,9 +28,9 @@ import ( // Initialize will initialize the database given in the config for use with GoToSocial var Initialize action.GTSAction = func(ctx context.Context, c *config.Config, log *logrus.Logger) error { - _, err := New(ctx, c, log) + db, err := New(ctx, c, log) if err != nil { return err } - return nil + return db.CreateSchema(ctx) } diff --git a/internal/db/db.go b/internal/db/db.go index df38ae1fb..4ea4e1af6 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -42,7 +42,15 @@ type DB interface { /* ANY ADDITIONAL DESIRED FUNCTIONS */ + + // CreateSchema should populate the database with the required tables + CreateSchema(context.Context) error + + // Stop should stop and close the database connection cleanly, returning an error if this is not possible Stop(context.Context) error + + // IsHealthy should return nil if the database connection is healthy, or an error if not + IsHealthy(context.Context) error } // New returns a new database service that satisfies the Service interface and, by extension, diff --git a/internal/db/postgres.go b/internal/db/postgres.go index 2982596d0..5a23b8121 100644 --- a/internal/db/postgres.go +++ b/internal/db/postgres.go @@ -28,8 +28,11 @@ import ( "time" "github.com/go-fed/activity/streams/vocab" - "github.com/go-pg/pg" + "github.com/go-pg/pg/extra/pgdebug" + "github.com/go-pg/pg/v10" + "github.com/go-pg/pg/v10/orm" "github.com/gotosocial/gotosocial/internal/config" + "github.com/gotosocial/gotosocial/internal/model" "github.com/sirupsen/logrus" ) @@ -47,9 +50,10 @@ func newPostgresService(ctx context.Context, c *config.Config, log *logrus.Entry if err != nil { return nil, fmt.Errorf("could not create postgres service: %s", err) } + log.Debugf("using pg options: %+v", opts) readyChan := make(chan interface{}) - opts.OnConnect = func(c *pg.Conn) error { + opts.OnConnect = func(ctx context.Context, c *pg.Conn) error { close(readyChan) return nil } @@ -58,19 +62,30 @@ func newPostgresService(ctx context.Context, c *config.Config, log *logrus.Entry pgCtx, cancel := context.WithCancel(ctx) conn := pg.Connect(opts).WithContext(pgCtx) + // this will break the logfmt format we normally log in, + // since we can't choose where pg outputs to and it defaults to + // stdout. So use this option with care! + if log.Logger.GetLevel() >= logrus.TraceLevel { + conn.AddQueryHook(pgdebug.DebugHook{ + // Print all queries. + Verbose: true, + }) + } + // actually *begin* the connection so that we can tell if the db is there // and listening, and also trigger the opts.OnConnect function passed in above - tx, err := conn.Begin() - if err != nil { + if err := conn.Ping(ctx); err != nil { cancel() return nil, fmt.Errorf("db connection error: %s", err) } - // close the transaction we just started so it doesn't hang around - if err := tx.Rollback(); err != nil { + // print out discovered postgres version + var version string + if _, err = conn.QueryOneContext(ctx, pg.Scan(&version), "SELECT version()"); err != nil { cancel() return nil, fmt.Errorf("db connection error: %s", err) } + log.Infof("connected to postgres version: %s", version) // make sure the opts.OnConnect function has been triggered // and closed the ready channel @@ -82,6 +97,12 @@ func newPostgresService(ctx context.Context, c *config.Config, log *logrus.Entry return nil, errors.New("db connection timeout") } + acc := model.StubAccount() + if _, err := conn.Model(acc).Returning("id").Insert(); err != nil { + cancel() + return nil, errors.New("db insert error") + } + // we can confidently return this useable postgres service now return &postgresService{ config: c.DBConfig, @@ -242,3 +263,26 @@ func (ps *postgresService) Stop(ctx context.Context) error { } return nil } + +func (ps *postgresService) CreateSchema(ctx context.Context) error { + models := []interface{}{ + (*model.Account)(nil), + } + ps.log.Info("creating db schema") + + for _, model := range models { + err := ps.conn.Model(model).CreateTable(&orm.CreateTableOptions{ + IfNotExists: true, + }) + if err != nil { + return err + } + } + + ps.log.Info("db schema created") + return nil +} + +func (ps *postgresService) IsHealthy(ctx context.Context) error { + return ps.conn.Ping(ctx) +} diff --git a/internal/model/account.go b/internal/model/account.go new file mode 100644 index 000000000..55ee62773 --- /dev/null +++ b/internal/model/account.go @@ -0,0 +1,80 @@ +/* + GoToSocial + Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +package model + +import ( + "net/url" + "time" +) + +// Account represents a user account +type Account struct { + Avatar + Header + ID int `pg:"type:uuid,default:gen_random_uuid(),pk,notnull"` + Username string + Domain string + Secret string + PrivateKey string + PublicKey string + RemoteURL *url.URL `pg:"type:text"` + SalmonURL *url.URL `pg:"type:text"` + HubURL *url.URL `pg:"type:text"` + CreatedAt time.Time `pg:"type:timestamp,notnull"` + UpdatedAt time.Time `pg:"type:timestamp,notnull"` + Note string + DisplayName string + URI *url.URL `pg:"type:text"` + URL *url.URL `pg:"type:text"` + SubscriptionExpiresAt time.Time `pg:"type:timestamp"` + Locked bool + LastWebfingeredAt time.Time `pg:"type:timestamp"` + InboxURL *url.URL `pg:"type:text"` + OutboxURL *url.URL `pg:"type:text"` + SharedInboxURL *url.URL `pg:"type:text"` + FollowersURL *url.URL `pg:"type:text"` + Protocol int + Memorial bool + MovedToAccountID int + FeaturedCollectionURL *url.URL `pg:"type:text"` + Fields map[string]string + ActorType string + Discoverable bool + AlsoKnownAs string + SilencedAt time.Time `pg:"type:timestamp"` + SuspendedAt time.Time `pg:"type:timestamp"` + TrustLevel int + HideCollections bool + DevicesURL *url.URL `pg:"type:text"` + SensitizedAt time.Time `pg:"type:timestamp"` + SuspensionOrigin int +} + +func StubAccount() *Account { + + remoteURL, _ := url.Parse("https://example.org/@someuser") + + return &Account{ + Username: "some_user", + Domain: "example.org", + RemoteURL: remoteURL, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } +} diff --git a/internal/model/avatar.go b/internal/model/avatar.go new file mode 100644 index 000000000..637fa5e3c --- /dev/null +++ b/internal/model/avatar.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 model + +import ( + "net/url" + "time" +) + +type Avatar struct { + AvatarFileName string + AvatarContentType string + AvatarFileSize int + AvatarUpdatedAt *time.Time `pg:"type:timestamp"` + AvatarRemoteURL *url.URL `pg:"type:text"` + AvatarStorageSchemaVersion int +} diff --git a/internal/model/header.go b/internal/model/header.go new file mode 100644 index 000000000..edaa7a2dc --- /dev/null +++ b/internal/model/header.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 model + +import ( + "net/url" + "time" +) + +type Header struct { + HeaderFileName string + HeaderContentType string + HeaderFileSize int + HeaderUpdatedAt *time.Time `pg:"type:timestamp"` + HeaderRemoteURL *url.URL `pg:"type:text"` + HeaderStorageSchemaVersion int +} diff --git a/internal/server/actions.go b/internal/server/actions.go index b3047c334..6ff3045b5 100644 --- a/internal/server/actions.go +++ b/internal/server/actions.go @@ -38,6 +38,10 @@ var Run action.GTSAction = func(ctx context.Context, c *config.Config, log *logr return fmt.Errorf("error creating dbservice: %s", err) } + if err := dbService.CreateSchema(ctx); err != nil { + return fmt.Errorf("error creating dbschema: %s", err) + } + // catch shutdown signals from the operating system sigs := make(chan os.Signal, 1) signal.Notify(sigs, os.Interrupt, syscall.SIGTERM) |