diff --git a/internal/ap/ap.go b/internal/ap/ap.go deleted file mode 100644 index 5d56f3f..0000000 --- a/internal/ap/ap.go +++ /dev/null @@ -1,35 +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 ap provides ActivityPub/federation functionality for GoToSocial -package ap - -import ( -// "github.com/go-fed/activity/pub" -) - -// Service is an activityPub service that uses go-fed to provide federation capabilities -type Service interface { -} - -type service struct { -} - -// NewService returns an activityPub Service -func NewService() { -} diff --git a/internal/db/actions.go b/internal/db/actions.go index 9a30124..6fa7d23 100644 --- a/internal/db/actions.go +++ b/internal/db/actions.go @@ -29,8 +29,8 @@ 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 { db, err := New(ctx, c, log) - if err != nil { - return err - } - return db.CreateSchema(ctx) + if err != nil { + return err + } + return db.CreateSchema(ctx) } diff --git a/internal/db/postgres.go b/internal/db/postgres.go index 5a23b81..3c7af45 100644 --- a/internal/db/postgres.go +++ b/internal/db/postgres.go @@ -25,6 +25,7 @@ import ( "net/url" "regexp" "strings" + "sync" "time" "github.com/go-fed/activity/streams/vocab" @@ -41,6 +42,7 @@ type postgresService struct { conn *pg.DB log *logrus.Entry cancel context.CancelFunc + locks *sync.Map } // newPostgresService returns a postgresService derived from the provided config, which implements the go-fed DB interface. @@ -109,6 +111,7 @@ func newPostgresService(ctx context.Context, c *config.Config, log *logrus.Entry conn: conn, log: log, cancel: cancel, + locks: &sync.Map{}, }, nil } @@ -171,10 +174,31 @@ func derivePGOptions(c *config.Config) (*pg.Options, error) { GO-FED DB INTERFACE-IMPLEMENTING FUNCTIONS */ func (ps *postgresService) Lock(ctx context.Context, id *url.URL) error { + // 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() + } return nil } func (ps *postgresService) Unlock(ctx context.Context, id *url.URL) error { + // 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() return nil } diff --git a/internal/federation/federation.go b/internal/federation/federation.go new file mode 100644 index 0000000..dd75fa5 --- /dev/null +++ b/internal/federation/federation.go @@ -0,0 +1,112 @@ +/* + 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 federation provides ActivityPub/federation functionality for GoToSocial +package federation + +import ( + "context" + "net/http" + "net/url" + "time" + + "github.com/go-fed/activity/pub" + "github.com/go-fed/activity/streams/vocab" + "github.com/gotosocial/gotosocial/internal/db" +) + +func New(db db.DB) pub.FederatingActor { + fs := &FederationService{} + return pub.NewFederatingActor(fs, fs, db, fs) +} + +type FederationService struct { +} + +// AuthenticateGetInbox determines whether the request is for a GET call to the Actor's Inbox. +func (fs *FederationService) AuthenticateGetInbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) { + // TODO + return nil, false, nil +} + +// AuthenticateGetOutbox determines whether the request is for a GET call to the Actor's Outbox. +func (fs *FederationService) AuthenticateGetOutbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) { + // TODO + return nil, false, nil +} + +// GetOutbox returns a proper paginated view of the Outbox for serving in a response. +func (fs *FederationService) GetOutbox(ctx context.Context, r *http.Request) (vocab.ActivityStreamsOrderedCollectionPage, error) { + // TODO + return nil, nil +} + +// NewTransport returns a new pub.Transport for federating with peer software. +func (fs *FederationService) NewTransport(ctx context.Context, actorBoxIRI *url.URL, gofedAgent string) (pub.Transport, error) { + // TODO + return nil, nil +} + +func (fs *FederationService) PostInboxRequestBodyHook(ctx context.Context, r *http.Request, activity pub.Activity) (context.Context, error) { + // TODO + return nil, nil +} + +func (fs *FederationService) AuthenticatePostInbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) { + // TODO + return nil, false, nil +} + +func (fs *FederationService) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, error) { + // TODO + return false, nil +} + +func (fs *FederationService) FederatingCallbacks(ctx context.Context) (pub.FederatingWrappedCallbacks, []interface{}, error) { + // TODO + return pub.FederatingWrappedCallbacks{}, nil, nil +} + +func (fs *FederationService) DefaultCallback(ctx context.Context, activity pub.Activity) error { + // TODO + return nil +} + +func (fs *FederationService) MaxInboxForwardingRecursionDepth(ctx context.Context) int { + // TODO + return 0 +} + +func (fs *FederationService) MaxDeliveryRecursionDepth(ctx context.Context) int { + // TODO + return 0 +} + +func (fs *FederationService) FilterForwarding(ctx context.Context, potentialRecipients []*url.URL, a pub.Activity) ([]*url.URL, error) { + // TODO + return nil, nil +} + +func (fs *FederationService) GetInbox(ctx context.Context, r *http.Request) (vocab.ActivityStreamsOrderedCollectionPage, error) { + // TODO + return nil, nil +} + +func (fs *FederationService) Now() time.Time { + return time.Now() +} diff --git a/internal/model/account.go b/internal/model/account.go index 55ee627..360d0de 100644 --- a/internal/model/account.go +++ b/internal/model/account.go @@ -66,6 +66,24 @@ type Account struct { SuspensionOrigin int } +type Avatar struct { + AvatarFileName string + AvatarContentType string + AvatarFileSize int + AvatarUpdatedAt *time.Time `pg:"type:timestamp"` + AvatarRemoteURL *url.URL `pg:"type:text"` + AvatarStorageSchemaVersion int +} + +type Header struct { + HeaderFileName string + HeaderContentType string + HeaderFileSize int + HeaderUpdatedAt *time.Time `pg:"type:timestamp"` + HeaderRemoteURL *url.URL `pg:"type:text"` + HeaderStorageSchemaVersion int +} + func StubAccount() *Account { remoteURL, _ := url.Parse("https://example.org/@someuser") diff --git a/internal/model/avatar.go b/internal/model/avatar.go deleted file mode 100644 index 637fa5e..0000000 --- a/internal/model/avatar.go +++ /dev/null @@ -1,33 +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 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 deleted file mode 100644 index edaa7a2..0000000 --- a/internal/model/header.go +++ /dev/null @@ -1,33 +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 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 -}