| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | /* | 
					
						
							|  |  |  |    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 db | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"net/url" | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | 	"regexp" | 
					
						
							| 
									
										
										
										
											2021-03-03 18:12:02 +01:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2021-03-07 13:05:33 +01:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-07 22:03:36 +01:00
										 |  |  | 	"github.com/go-fed/activity/streams" | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	"github.com/go-fed/activity/streams/vocab" | 
					
						
							| 
									
										
										
										
											2021-03-05 18:31:12 +01:00
										 |  |  | 	"github.com/go-pg/pg/extra/pgdebug" | 
					
						
							|  |  |  | 	"github.com/go-pg/pg/v10" | 
					
						
							|  |  |  | 	"github.com/go-pg/pg/v10/orm" | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | 	"github.com/gotosocial/gotosocial/internal/config" | 
					
						
							| 
									
										
										
										
											2021-03-05 18:31:12 +01:00
										 |  |  | 	"github.com/gotosocial/gotosocial/internal/model" | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 	"github.com/sirupsen/logrus" | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type postgresService struct { | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | 	config *config.DBConfig | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	conn   *pg.DB | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 	log    *logrus.Entry | 
					
						
							|  |  |  | 	cancel context.CancelFunc | 
					
						
							| 
									
										
										
										
											2021-03-07 13:05:33 +01:00
										 |  |  | 	locks  *sync.Map | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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. | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func newPostgresService(ctx context.Context, c *config.Config, log *logrus.Entry) (*postgresService, error) { | 
					
						
							|  |  |  | 	opts, err := derivePGOptions(c) | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("could not create postgres service: %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-05 18:31:12 +01:00
										 |  |  | 	log.Debugf("using pg options: %+v", opts) | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	readyChan := make(chan interface{}) | 
					
						
							| 
									
										
										
										
											2021-03-05 18:31:12 +01:00
										 |  |  | 	opts.OnConnect = func(ctx context.Context, c *pg.Conn) error { | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 		close(readyChan) | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// create a connection | 
					
						
							|  |  |  | 	pgCtx, cancel := context.WithCancel(ctx) | 
					
						
							|  |  |  | 	conn := pg.Connect(opts).WithContext(pgCtx) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-05 18:31:12 +01:00
										 |  |  | 	// 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, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 	// 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 | 
					
						
							| 
									
										
										
										
											2021-03-05 18:31:12 +01:00
										 |  |  | 	if err := conn.Ping(ctx); err != nil { | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 		cancel() | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("db connection error: %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-05 18:31:12 +01:00
										 |  |  | 	// print out discovered postgres version | 
					
						
							|  |  |  | 	var version string | 
					
						
							|  |  |  | 	if _, err = conn.QueryOneContext(ctx, pg.Scan(&version), "SELECT version()"); err != nil { | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 		cancel() | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("db connection error: %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-05 18:31:12 +01:00
										 |  |  | 	log.Infof("connected to postgres version: %s", version) | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// make sure the opts.OnConnect function has been triggered | 
					
						
							|  |  |  | 	// and closed the ready channel | 
					
						
							|  |  |  | 	select { | 
					
						
							|  |  |  | 	case <-readyChan: | 
					
						
							|  |  |  | 		log.Infof("postgres connection ready") | 
					
						
							|  |  |  | 	case <-time.After(5 * time.Second): | 
					
						
							|  |  |  | 		cancel() | 
					
						
							|  |  |  | 		return nil, errors.New("db connection timeout") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-05 18:31:12 +01:00
										 |  |  | 	acc := model.StubAccount() | 
					
						
							|  |  |  | 	if _, err := conn.Model(acc).Returning("id").Insert(); err != nil { | 
					
						
							|  |  |  | 		cancel() | 
					
						
							| 
									
										
										
										
											2021-03-08 22:37:56 +01:00
										 |  |  | 		return nil, fmt.Errorf("db insert error: %s", err) | 
					
						
							| 
									
										
										
										
											2021-03-05 18:31:12 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-08 22:37:56 +01:00
										 |  |  | 	log.Infof("created account with id %s", acc.ID) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	note := &model.Note{ | 
					
						
							|  |  |  | 		Visibility: &model.Visibility{ | 
					
						
							|  |  |  | 			Local: true, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		CreatedAt: time.Now(), | 
					
						
							|  |  |  | 		UpdatedAt: time.Now(), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if _, err := conn.Model(note).Returning("id").Insert(); err != nil { | 
					
						
							|  |  |  | 		cancel() | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("db insert error: %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	log.Infof("created note with id %s", note.ID) | 
					
						
							| 
									
										
										
										
											2021-03-05 18:31:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 	// we can confidently return this useable postgres service now | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return &postgresService{ | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | 		config: c.DBConfig, | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 		conn:   conn, | 
					
						
							|  |  |  | 		log:    log, | 
					
						
							|  |  |  | 		cancel: cancel, | 
					
						
							| 
									
										
										
										
											2021-03-07 13:05:33 +01:00
										 |  |  | 		locks:  &sync.Map{}, | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  | 	HANDY STUFF | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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. | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | 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) | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 12:07:24 +01:00
										 |  |  | 	// validate port | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | 	if c.DBConfig.Port == 0 { | 
					
						
							| 
									
										
										
										
											2021-03-04 12:07:24 +01:00
										 |  |  | 		return nil, errors.New("no port set") | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// validate address | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | 	if c.DBConfig.Address == "" { | 
					
						
							| 
									
										
										
										
											2021-03-04 12:07:24 +01:00
										 |  |  | 		return nil, errors.New("no address set") | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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) | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// validate username | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | 	if c.DBConfig.User == "" { | 
					
						
							| 
									
										
										
										
											2021-03-04 12:07:24 +01:00
										 |  |  | 		return nil, errors.New("no user set") | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// validate that there's a password | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | 	if c.DBConfig.Password == "" { | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 		return nil, errors.New("no password set") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// validate database | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | 	if c.DBConfig.Database == "" { | 
					
						
							| 
									
										
										
										
											2021-03-04 12:07:24 +01:00
										 |  |  | 		return nil, errors.New("no database set") | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | 	// We can rely on the pg library we're using to set | 
					
						
							|  |  |  | 	// sensible defaults for everything we don't set here. | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	options := &pg.Options{ | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | 		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, | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return options, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |    GO-FED DB INTERFACE-IMPLEMENTING FUNCTIONS | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) Lock(ctx context.Context, id *url.URL) error { | 
					
						
							| 
									
										
										
										
											2021-03-07 13:05:33 +01:00
										 |  |  | 	// Before any other Database methods are called, the relevant `id` | 
					
						
							|  |  |  | 	// entries are locked to allow for fine-grained concurrency. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Strategy: create a new lock, if stored, continue. Otherwise, lock the | 
					
						
							|  |  |  | 	// existing mutex. | 
					
						
							|  |  |  | 	mu := &sync.Mutex{} | 
					
						
							|  |  |  | 	mu.Lock() // Optimistically lock if we do store it. | 
					
						
							|  |  |  | 	i, loaded := ps.locks.LoadOrStore(id.String(), mu) | 
					
						
							|  |  |  | 	if loaded { | 
					
						
							|  |  |  | 		mu = i.(*sync.Mutex) | 
					
						
							|  |  |  | 		mu.Lock() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) Unlock(ctx context.Context, id *url.URL) error { | 
					
						
							| 
									
										
										
										
											2021-03-07 13:05:33 +01:00
										 |  |  | 	// Once Go-Fed is done calling Database methods, the relevant `id` | 
					
						
							|  |  |  | 	// entries are unlocked. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	i, ok := ps.locks.Load(id.String()) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return errors.New("missing an id in unlock") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	mu := i.(*sync.Mutex) | 
					
						
							|  |  |  | 	mu.Unlock() | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) InboxContains(ctx context.Context, inbox *url.URL, id *url.URL) (bool, error) { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return false, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) GetInbox(ctx context.Context, inboxIRI *url.URL) (inbox vocab.ActivityStreamsOrderedCollectionPage, err error) { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) SetInbox(ctx context.Context, inbox vocab.ActivityStreamsOrderedCollectionPage) error { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) Owns(ctx context.Context, id *url.URL) (owns bool, err error) { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return false, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) ActorForOutbox(ctx context.Context, outboxIRI *url.URL) (actorIRI *url.URL, err error) { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) ActorForInbox(ctx context.Context, inboxIRI *url.URL) (actorIRI *url.URL, err error) { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) OutboxForInbox(ctx context.Context, inboxIRI *url.URL) (outboxIRI *url.URL, err error) { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) Exists(ctx context.Context, id *url.URL) (exists bool, err error) { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return false, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) Get(ctx context.Context, id *url.URL) (value vocab.Type, err error) { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) Create(ctx context.Context, asType vocab.Type) error { | 
					
						
							| 
									
										
										
										
											2021-03-07 22:03:36 +01:00
										 |  |  | 	t, err := streams.NewTypeResolver() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := t.Resolve(ctx, asType); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	asType.GetTypeName() | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) Update(ctx context.Context, asType vocab.Type) error { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) Delete(ctx context.Context, id *url.URL) error { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) GetOutbox(ctx context.Context, outboxIRI *url.URL) (inbox vocab.ActivityStreamsOrderedCollectionPage, err error) { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) SetOutbox(ctx context.Context, outbox vocab.ActivityStreamsOrderedCollectionPage) error { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) NewID(ctx context.Context, t vocab.Type) (id *url.URL, err error) { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) Followers(ctx context.Context, actorIRI *url.URL) (followers vocab.ActivityStreamsCollection, err error) { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) Following(ctx context.Context, actorIRI *url.URL) (followers vocab.ActivityStreamsCollection, err error) { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 14:38:18 +01:00
										 |  |  | func (ps *postgresService) Liked(ctx context.Context, actorIRI *url.URL) (followers vocab.ActivityStreamsCollection, err error) { | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  | 	EXTRA FUNCTIONS | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-02 22:52:31 +01:00
										 |  |  | func (ps *postgresService) Stop(ctx context.Context) error { | 
					
						
							|  |  |  | 	ps.log.Info("closing db connection") | 
					
						
							|  |  |  | 	if err := ps.conn.Close(); err != nil { | 
					
						
							|  |  |  | 		// only cancel if there's a problem closing the db | 
					
						
							|  |  |  | 		ps.cancel() | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2021-03-02 18:26:30 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-03-05 18:31:12 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (ps *postgresService) CreateSchema(ctx context.Context) error { | 
					
						
							|  |  |  | 	models := []interface{}{ | 
					
						
							|  |  |  | 		(*model.Account)(nil), | 
					
						
							| 
									
										
										
										
											2021-03-08 22:37:56 +01:00
										 |  |  | 		(*model.Note)(nil), | 
					
						
							| 
									
										
										
										
											2021-03-05 18:31:12 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | } |