summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorLibravatar tsmethurst <tobi.smethurst@klarrio.com>2021-03-05 18:31:12 +0100
committerLibravatar tsmethurst <tobi.smethurst@klarrio.com>2021-03-05 18:31:12 +0100
commit59963090cbcee395463b7767e3807ce7c0aa6f43 (patch)
tree7eade814709bb692e24ee6495b201bc1c4b34d6d /internal
parenttidying up here and there (diff)
downloadgotosocial-59963090cbcee395463b7767e3807ce7c0aa6f43.tar.xz
create db schemas for accounts
Diffstat (limited to 'internal')
-rw-r--r--internal/db/actions.go4
-rw-r--r--internal/db/db.go8
-rw-r--r--internal/db/postgres.go56
-rw-r--r--internal/model/account.go80
-rw-r--r--internal/model/avatar.go33
-rw-r--r--internal/model/header.go33
-rw-r--r--internal/server/actions.go4
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)