From 052783db664ab529a52026e5a2bbfa2d5ca427d2 Mon Sep 17 00:00:00 2001 From: tsmethurst Date: Thu, 4 Mar 2021 14:38:18 +0100 Subject: tidying up here and there --- internal/db/actions.go | 36 +++++++++++++++++++++ internal/db/db.go | 57 +++++++++++++++++++++++++++++++++ internal/db/postgres.go | 83 ++++++++++++++++++++++++++----------------------- internal/db/service.go | 67 --------------------------------------- 4 files changed, 137 insertions(+), 106 deletions(-) create mode 100644 internal/db/actions.go create mode 100644 internal/db/db.go delete mode 100644 internal/db/service.go (limited to 'internal/db') diff --git a/internal/db/actions.go b/internal/db/actions.go new file mode 100644 index 000000000..ae3d8cadf --- /dev/null +++ b/internal/db/actions.go @@ -0,0 +1,36 @@ +/* + 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 . +*/ + +package db + +import ( + "context" + + "github.com/gotosocial/gotosocial/internal/action" + "github.com/gotosocial/gotosocial/internal/config" + "github.com/sirupsen/logrus" +) + +// 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) + if err != nil { + return err + } + return nil +} diff --git a/internal/db/db.go b/internal/db/db.go new file mode 100644 index 000000000..df38ae1fb --- /dev/null +++ b/internal/db/db.go @@ -0,0 +1,57 @@ +/* + 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 . +*/ + +package db + +import ( + "context" + "fmt" + "strings" + + "github.com/go-fed/activity/pub" + "github.com/gotosocial/gotosocial/internal/config" + "github.com/sirupsen/logrus" +) + +const dbTypePostgres string = "POSTGRES" + +// DB provides methods for interacting with an underlying database (for now, just postgres). +// The function mapping lines up with the DB interface described in go-fed. +// See here: https://github.com/go-fed/activity/blob/master/pub/database.go +type DB interface { + /* + GO-FED DATABASE FUNCTIONS + */ + pub.Database + + /* + ANY ADDITIONAL DESIRED FUNCTIONS + */ + Stop(context.Context) error +} + +// New returns a new database service that satisfies the Service interface and, by extension, +// the go-fed database interface described here: https://github.com/go-fed/activity/blob/master/pub/database.go +func New(ctx context.Context, c *config.Config, log *logrus.Logger) (DB, error) { + switch strings.ToUpper(c.DBConfig.Type) { + case dbTypePostgres: + return newPostgresService(ctx, c, log.WithField("service", "db")) + default: + return nil, fmt.Errorf("database type %s not supported", c.DBConfig.Type) + } +} diff --git a/internal/db/postgres.go b/internal/db/postgres.go index 1eb3eb4b9..2982596d0 100644 --- a/internal/db/postgres.go +++ b/internal/db/postgres.go @@ -23,17 +23,18 @@ import ( "errors" "fmt" "net/url" + "regexp" "strings" "time" "github.com/go-fed/activity/streams/vocab" "github.com/go-pg/pg" - "github.com/gotosocial/gotosocial/internal/consts" + "github.com/gotosocial/gotosocial/internal/config" "github.com/sirupsen/logrus" ) type postgresService struct { - config *Config + config *config.DBConfig conn *pg.DB log *logrus.Entry cancel context.CancelFunc @@ -41,8 +42,8 @@ type postgresService struct { // newPostgresService returns a postgresService derived from the provided config, which implements the go-fed DB interface. // Under the hood, it uses https://github.com/go-pg/pg to create and maintain a database connection. -func newPostgresService(ctx context.Context, config *Config, log *logrus.Entry) (*postgresService, error) { - opts, err := derivePGOptions(config) +func newPostgresService(ctx context.Context, c *config.Config, log *logrus.Entry) (*postgresService, error) { + opts, err := derivePGOptions(c) if err != nil { return nil, fmt.Errorf("could not create postgres service: %s", err) } @@ -83,7 +84,7 @@ func newPostgresService(ctx context.Context, config *Config, log *logrus.Entry) // we can confidently return this useable postgres service now return &postgresService{ - config: config, + config: c.DBConfig, conn: conn, log: log, cancel: cancel, @@ -96,46 +97,50 @@ func newPostgresService(ctx context.Context, config *Config, log *logrus.Entry) // derivePGOptions takes an application config and returns either a ready-to-use *pg.Options // with sensible defaults, or an error if it's not satisfied by the provided config. -func derivePGOptions(config *Config) (*pg.Options, error) { - if strings.ToUpper(config.Type) != dbTypePostgres { - return nil, fmt.Errorf("expected db type of %s but got %s", dbTypePostgres, config.Type) +func derivePGOptions(c *config.Config) (*pg.Options, error) { + if strings.ToUpper(c.DBConfig.Type) != dbTypePostgres { + return nil, fmt.Errorf("expected db type of %s but got %s", dbTypePostgres, c.DBConfig.Type) } // validate port - if config.Port == 0 { + if c.DBConfig.Port == 0 { return nil, errors.New("no port set") } // validate address - if config.Address == "" { + if c.DBConfig.Address == "" { return nil, errors.New("no address set") } - if !consts.HostnameRegex.MatchString(config.Address) && !consts.IPV4Regex.MatchString(config.Address) && config.Address != "localhost" { - return nil, fmt.Errorf("address %s was neither an ipv4 address nor a valid hostname", config.Address) + + ipv4Regex := regexp.MustCompile(`^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$`) + hostnameRegex := regexp.MustCompile(`^(?:[a-z0-9]+(?:-[a-z0-9]+)*\.)+[a-z]{2,}$`) + if !hostnameRegex.MatchString(c.DBConfig.Address) && !ipv4Regex.MatchString(c.DBConfig.Address) && c.DBConfig.Address != "localhost" { + return nil, fmt.Errorf("address %s was neither an ipv4 address nor a valid hostname", c.DBConfig.Address) } // validate username - if config.User == "" { + if c.DBConfig.User == "" { return nil, errors.New("no user set") } // validate that there's a password - if config.Password == "" { + if c.DBConfig.Password == "" { return nil, errors.New("no password set") } // validate database - if config.Database == "" { + if c.DBConfig.Database == "" { return nil, errors.New("no database set") } // We can rely on the pg library we're using to set // sensible defaults for everything we don't set here. options := &pg.Options{ - Addr: fmt.Sprintf("%s:%d", config.Address, config.Port), - User: config.User, - Password: config.Password, - Database: config.Database, + Addr: fmt.Sprintf("%s:%d", c.DBConfig.Address, c.DBConfig.Port), + User: c.DBConfig.User, + Password: c.DBConfig.Password, + Database: c.DBConfig.Database, + ApplicationName: c.ApplicationName, } return options, nil @@ -144,83 +149,83 @@ func derivePGOptions(config *Config) (*pg.Options, error) { /* GO-FED DB INTERFACE-IMPLEMENTING FUNCTIONS */ -func (ps *postgresService) Lock(c context.Context, id *url.URL) error { +func (ps *postgresService) Lock(ctx context.Context, id *url.URL) error { return nil } -func (ps *postgresService) Unlock(c context.Context, id *url.URL) error { +func (ps *postgresService) Unlock(ctx context.Context, id *url.URL) error { return nil } -func (ps *postgresService) InboxContains(c context.Context, inbox *url.URL, id *url.URL) (bool, error) { +func (ps *postgresService) InboxContains(ctx context.Context, inbox *url.URL, id *url.URL) (bool, error) { return false, nil } -func (ps *postgresService) GetInbox(c context.Context, inboxIRI *url.URL) (inbox vocab.ActivityStreamsOrderedCollectionPage, err error) { +func (ps *postgresService) GetInbox(ctx context.Context, inboxIRI *url.URL) (inbox vocab.ActivityStreamsOrderedCollectionPage, err error) { return nil, nil } -func (ps *postgresService) SetInbox(c context.Context, inbox vocab.ActivityStreamsOrderedCollectionPage) error { +func (ps *postgresService) SetInbox(ctx context.Context, inbox vocab.ActivityStreamsOrderedCollectionPage) error { return nil } -func (ps *postgresService) Owns(c context.Context, id *url.URL) (owns bool, err error) { +func (ps *postgresService) Owns(ctx context.Context, id *url.URL) (owns bool, err error) { return false, nil } -func (ps *postgresService) ActorForOutbox(c context.Context, outboxIRI *url.URL) (actorIRI *url.URL, err error) { +func (ps *postgresService) ActorForOutbox(ctx context.Context, outboxIRI *url.URL) (actorIRI *url.URL, err error) { return nil, nil } -func (ps *postgresService) ActorForInbox(c context.Context, inboxIRI *url.URL) (actorIRI *url.URL, err error) { +func (ps *postgresService) ActorForInbox(ctx context.Context, inboxIRI *url.URL) (actorIRI *url.URL, err error) { return nil, nil } -func (ps *postgresService) OutboxForInbox(c context.Context, inboxIRI *url.URL) (outboxIRI *url.URL, err error) { +func (ps *postgresService) OutboxForInbox(ctx context.Context, inboxIRI *url.URL) (outboxIRI *url.URL, err error) { return nil, nil } -func (ps *postgresService) Exists(c context.Context, id *url.URL) (exists bool, err error) { +func (ps *postgresService) Exists(ctx context.Context, id *url.URL) (exists bool, err error) { return false, nil } -func (ps *postgresService) Get(c context.Context, id *url.URL) (value vocab.Type, err error) { +func (ps *postgresService) Get(ctx context.Context, id *url.URL) (value vocab.Type, err error) { return nil, nil } -func (ps *postgresService) Create(c context.Context, asType vocab.Type) error { +func (ps *postgresService) Create(ctx context.Context, asType vocab.Type) error { return nil } -func (ps *postgresService) Update(c context.Context, asType vocab.Type) error { +func (ps *postgresService) Update(ctx context.Context, asType vocab.Type) error { return nil } -func (ps *postgresService) Delete(c context.Context, id *url.URL) error { +func (ps *postgresService) Delete(ctx context.Context, id *url.URL) error { return nil } -func (ps *postgresService) GetOutbox(c context.Context, outboxIRI *url.URL) (inbox vocab.ActivityStreamsOrderedCollectionPage, err error) { +func (ps *postgresService) GetOutbox(ctx context.Context, outboxIRI *url.URL) (inbox vocab.ActivityStreamsOrderedCollectionPage, err error) { return nil, nil } -func (ps *postgresService) SetOutbox(c context.Context, outbox vocab.ActivityStreamsOrderedCollectionPage) error { +func (ps *postgresService) SetOutbox(ctx context.Context, outbox vocab.ActivityStreamsOrderedCollectionPage) error { return nil } -func (ps *postgresService) NewID(c context.Context, t vocab.Type) (id *url.URL, err error) { +func (ps *postgresService) NewID(ctx context.Context, t vocab.Type) (id *url.URL, err error) { return nil, nil } -func (ps *postgresService) Followers(c context.Context, actorIRI *url.URL) (followers vocab.ActivityStreamsCollection, err error) { +func (ps *postgresService) Followers(ctx context.Context, actorIRI *url.URL) (followers vocab.ActivityStreamsCollection, err error) { return nil, nil } -func (ps *postgresService) Following(c context.Context, actorIRI *url.URL) (followers vocab.ActivityStreamsCollection, err error) { +func (ps *postgresService) Following(ctx context.Context, actorIRI *url.URL) (followers vocab.ActivityStreamsCollection, err error) { return nil, nil } -func (ps *postgresService) Liked(c context.Context, actorIRI *url.URL) (followers vocab.ActivityStreamsCollection, err error) { +func (ps *postgresService) Liked(ctx context.Context, actorIRI *url.URL) (followers vocab.ActivityStreamsCollection, err error) { return nil, nil } diff --git a/internal/db/service.go b/internal/db/service.go deleted file mode 100644 index 4449a984f..000000000 --- a/internal/db/service.go +++ /dev/null @@ -1,67 +0,0 @@ -/* - 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 . -*/ - -package db - -import ( - "context" - "fmt" - "strings" - - "github.com/go-fed/activity/pub" - "github.com/sirupsen/logrus" -) - -const dbTypePostgres string = "POSTGRES" - -// Service provides methods for interacting with an underlying database (for now, just postgres). -// The function mapping lines up with the Database interface described in go-fed. -// See here: https://github.com/go-fed/activity/blob/master/pub/database.go -type Service interface { - /* - GO-FED DATABASE FUNCTIONS - */ - pub.Database - - /* - ANY ADDITIONAL DESIRED FUNCTIONS - */ - Stop(context.Context) error -} - -// Config provides configuration options for the database connection -type Config struct { - Type string `yaml:"type,omitempty"` - Address string `yaml:"address,omitempty"` - Port int `yaml:"port,omitempty"` - User string `yaml:"user,omitempty"` - Password string `yaml:"password,omitempty"` - Database string `yaml:"database,omitempty"` - ApplicationName string `yaml:"applicationName,omitempty"` -} - -// NewService returns a new database service that satisfies the Service interface and, by extension, -// the go-fed database interface described here: https://github.com/go-fed/activity/blob/master/pub/database.go -func NewService(context context.Context, config *Config, log *logrus.Logger) (Service, error) { - switch strings.ToUpper(config.Type) { - case dbTypePostgres: - return newPostgresService(context, config, log.WithField("service", "db")) - default: - return nil, fmt.Errorf("database type %s not supported", config.Type) - } -} -- cgit v1.2.3