diff --git a/internal/ap/ap.go b/internal/ap/ap.go
deleted file mode 100644
index 5d56f3fde..000000000
--- 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 9a3012465..6fa7d23ae 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 5a23b8121..3c7af4522 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 000000000..dd75fa506
--- /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 55ee62773..360d0de28 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 637fa5e3c..000000000
--- 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 edaa7a2dc..000000000
--- 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
-}