From 451803b230084d5553962c2b3e3b2a921e9545e8 Mon Sep 17 00:00:00 2001 From: tobi <31960611+tsmethurst@users.noreply.github.com> Date: Wed, 8 Jan 2025 11:29:40 +0100 Subject: [PATCH] [feature] Fetch + create domain permissions from subscriptions nightly (#3635) * peepeepoopoo * test domain perm subs * swagger * envparsing * dries your wets * start on docs * finish up docs * copy paste errors * rename actions package * rename force -> skipCache * move obfuscate parse nearer to where err is checked * make higherPrios a simple slice * don't use receiver for permsFrom funcs * add more context to error logs * defer finished log * use switch for permType instead of if/else * thanks linter, love you <3 * validate csv headers before full read * use bufio scanner --- README.md | 7 +- ROADMAP.md | 2 +- .../action/admin/account/account.go | 3 +- cmd/gotosocial/action/admin/media/list.go | 2 + .../action/admin/media/prune/common.go | 4 +- cmd/gotosocial/action/admin/trans/export.go | 4 +- cmd/gotosocial/action/admin/trans/import.go | 4 +- cmd/gotosocial/action/server/server.go | 27 +- cmd/gotosocial/action/testrig/testrig.go | 29 +- docs/admin/domain_blocks.md | 2 +- docs/admin/domain_permission_subscriptions.md | 145 ++++ docs/admin/settings.md | 89 +- docs/api/swagger.yaml | 40 + ...-settings-federation-subscription-test.png | Bin 0 -> 158370 bytes .../public/admin-settings-federation.png | Bin 97674 -> 122978 bytes internal/{processing => }/admin/actions.go | 60 +- .../{processing => }/admin/actions_test.go | 40 +- internal/admin/domainkeys.go | 51 ++ internal/admin/domainperms.go | 387 +++++++++ internal/admin/util.go | 99 +++ .../api/activitypub/emoji/emojiget_test.go | 2 + internal/api/activitypub/users/user_test.go | 2 + internal/api/auth/auth_test.go | 2 + internal/api/client/accounts/account_test.go | 2 + internal/api/client/admin/admin.go | 2 + internal/api/client/admin/admin_test.go | 2 + .../admin/domainpermissionsubscriptiontest.go | 118 +++ .../domainpermissionsubscruptiontest_test.go | 125 +++ .../api/client/bookmarks/bookmarks_test.go | 2 + .../api/client/favourites/favourites_test.go | 2 + internal/api/client/filters/v1/filter_test.go | 2 + internal/api/client/filters/v2/filter_test.go | 2 + .../client/followedtags/followedtags_test.go | 2 + .../followrequests/followrequest_test.go | 2 + internal/api/client/instance/instance_test.go | 2 + internal/api/client/lists/lists_test.go | 2 + internal/api/client/mutes/mutes_test.go | 2 + .../notifications/notifications_test.go | 2 + internal/api/client/polls/polls_test.go | 2 + internal/api/client/reports/reports_test.go | 2 + internal/api/client/search/search_test.go | 2 + internal/api/client/statuses/status_test.go | 2 + .../api/client/streaming/streaming_test.go | 2 + internal/api/client/tags/tags_test.go | 2 + internal/api/client/user/user_test.go | 2 + internal/api/fileserver/fileserver_test.go | 2 + .../api/wellknown/webfinger/webfinger_test.go | 2 + .../wellknown/webfinger/webfingerget_test.go | 2 + internal/cleaner/media_test.go | 2 + internal/config/config.go | 20 +- internal/config/defaults.go | 16 +- internal/config/flags.go | 2 + internal/config/helpers.gen.go | 56 ++ .../dereferencing/dereferencer_test.go | 2 + .../federatingdb/federatingdb_test.go | 2 + internal/media/media_test.go | 2 + internal/oauth/clientstore_test.go | 2 + internal/processing/account/account_test.go | 2 + internal/processing/admin/account_test.go | 2 +- internal/processing/admin/accountaction.go | 2 +- internal/processing/admin/admin.go | 47 +- internal/processing/admin/admin_test.go | 4 + internal/processing/admin/domainallow.go | 169 +--- internal/processing/admin/domainblock.go | 265 +----- internal/processing/admin/domainkeysexpire.go | 53 +- .../processing/admin/domainpermission_test.go | 2 +- .../admin/domainpermissionsubscription.go | 87 ++ internal/processing/admin/util.go | 74 -- .../conversations/conversations_test.go | 2 + internal/processing/media/media_test.go | 2 + internal/processing/processor.go | 4 +- internal/processing/processor_test.go | 4 + internal/processing/status/status_test.go | 2 + internal/processing/stream/stream_test.go | 2 + internal/processing/timeline/timeline_test.go | 2 + internal/processing/user/user_test.go | 2 + internal/state/state.go | 8 +- internal/subscriptions/domainperms.go | 811 ++++++++++++++++++ internal/subscriptions/subscriptions.go | 42 + internal/subscriptions/subscriptions_test.go | 538 ++++++++++++ internal/transport/derefdomainpermlist.go | 121 +++ internal/transport/transport.go | 14 + internal/transport/transport_test.go | 2 + internal/typeutils/converter_test.go | 2 + internal/typeutils/internaltofrontend.go | 4 +- mkdocs.yml | 1 + test/envparsing.sh | 2 + testrig/config.go | 2 + testrig/processor.go | 14 +- testrig/teststructs.go | 31 +- testrig/transportcontroller.go | 124 ++- .../settings/components/pageable-list.tsx | 2 +- .../admin/domain-permissions/subscriptions.ts | 14 + web/source/settings/style.css | 15 +- .../subscriptions/detail.tsx | 78 +- 95 files changed, 3320 insertions(+), 626 deletions(-) create mode 100644 docs/admin/domain_permission_subscriptions.md create mode 100644 docs/overrides/public/admin-settings-federation-subscription-test.png rename internal/{processing => }/admin/actions.go (75%) rename internal/{processing => }/admin/actions_test.go (80%) create mode 100644 internal/admin/domainkeys.go create mode 100644 internal/admin/domainperms.go create mode 100644 internal/admin/util.go create mode 100644 internal/api/client/admin/domainpermissionsubscriptiontest.go create mode 100644 internal/api/client/admin/domainpermissionsubscruptiontest_test.go create mode 100644 internal/subscriptions/domainperms.go create mode 100644 internal/subscriptions/subscriptions.go create mode 100644 internal/subscriptions/subscriptions_test.go create mode 100644 internal/transport/derefdomainpermlist.go diff --git a/README.md b/README.md index 3f9f357e2..19e5a2ee2 100644 --- a/README.md +++ b/README.md @@ -225,10 +225,11 @@ Simply download the binary + assets (or Docker container), tweak your configurat ### Safety + security features -- Built-in, automatic support for secure HTTPS with [Let's Encrypt](https://letsencrypt.org/). -- Strict privacy enforcement for posts and strict blocking logic. -- Import and export allow lists and deny lists. Subscribe to community-created block lists (think Ad blocker, but for federation!) (feature still in progress). +- Strict privacy enforcement for posts, and strict blocking logic. +- [Choose the visibility of posts on the web view of your profile](https://docs.gotosocial.org/en/latest/user_guide/settings/#visibility-level-of-posts-to-show-on-your-profile). +- [Import, export](https://docs.gotosocial.org/en/latest/admin/settings/#importexport), and [subscribe](https://docs.gotosocial.org/en/latest/admin/domain_permission_subscriptions) to community-created domain allow and domain block lists. - HTTP signature authentication: GoToSocial requires [HTTP Signatures](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12) when sending and receiving messages, to ensure that your messages can't be tampered with and your identity can't be forged. +- Built-in, automatic support for secure HTTPS with [Let's Encrypt](https://letsencrypt.org/). ### Various federation modes diff --git a/ROADMAP.md b/ROADMAP.md index a4894f4fe..3b03475a2 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -71,7 +71,7 @@ These are provided in no specific order. - [x] **Filters v2** -- implement v2 of the filters API. - [x] **Mute accounts** -- mute accounts to prevent their posts showing up in your home timeline (optional: for limited period of time). - [x] **Non-replyable posts** -- design a non-replyable post path for GoToSocial based on https://github.com/mastodon/mastodon/issues/14762#issuecomment-1196889788; allow users to create non-replyable posts. -- [ ] **Block + allow list subscriptions** -- allow instance admins to subscribe their instance to plaintext domain block/allow lists (much of the work for this is already in place). +- [x] **Block + allow list subscriptions** -- allow instance admins to subscribe their instance to domain block/allow lists. - [x] **Direct conversation view** -- allow users to easily page through all direct-message conversations they're a part of. - [ ] **Oauth token management** -- create / view / invalidate OAuth tokens via the settings panel. - [ ] **Status EDIT support** -- edit statuses that you've created, without having to delete + redraft. Federate edits out properly. diff --git a/cmd/gotosocial/action/admin/account/account.go b/cmd/gotosocial/action/admin/account/account.go index 57d0d3805..7dfb6b1d4 100644 --- a/cmd/gotosocial/action/admin/account/account.go +++ b/cmd/gotosocial/action/admin/account/account.go @@ -40,7 +40,8 @@ func initState(ctx context.Context) (*state.State, error) { state.Caches.Init() state.Caches.Start() - // Set the state DB connection + // Only set state DB connection. + // Don't need Actions or Workers for this (yet). dbConn, err := bundb.NewBunDBService(ctx, &state) if err != nil { return nil, fmt.Errorf("error creating dbConn: %w", err) diff --git a/cmd/gotosocial/action/admin/media/list.go b/cmd/gotosocial/action/admin/media/list.go index 547954d4c..a017539ed 100644 --- a/cmd/gotosocial/action/admin/media/list.go +++ b/cmd/gotosocial/action/admin/media/list.go @@ -127,6 +127,8 @@ func setupList(ctx context.Context) (*list, error) { state.Caches.Init() state.Caches.Start() + // Only set state DB connection. + // Don't need Actions or Workers for this. dbService, err := bundb.NewBunDBService(ctx, &state) if err != nil { return nil, fmt.Errorf("error creating dbservice: %w", err) diff --git a/cmd/gotosocial/action/admin/media/prune/common.go b/cmd/gotosocial/action/admin/media/prune/common.go index 5b42a6687..d73676f5b 100644 --- a/cmd/gotosocial/action/admin/media/prune/common.go +++ b/cmd/gotosocial/action/admin/media/prune/common.go @@ -45,10 +45,12 @@ func setupPrune(ctx context.Context) (*prune, error) { state.Caches.Start() // Scheduler is required for the - // claner, but no other workers + // cleaner, but no other workers // are needed for this CLI action. state.Workers.StartScheduler() + // Set state DB connection. + // Don't need Actions for this. dbService, err := bundb.NewBunDBService(ctx, &state) if err != nil { return nil, fmt.Errorf("error creating dbservice: %w", err) diff --git a/cmd/gotosocial/action/admin/trans/export.go b/cmd/gotosocial/action/admin/trans/export.go index f76982a1b..dae2db7db 100644 --- a/cmd/gotosocial/action/admin/trans/export.go +++ b/cmd/gotosocial/action/admin/trans/export.go @@ -33,12 +33,12 @@ import ( var Export action.GTSAction = func(ctx context.Context) error { var state state.State + // Only set state DB connection. + // Don't need Actions or Workers for this. dbConn, err := bundb.NewBunDBService(ctx, &state) if err != nil { return fmt.Errorf("error creating dbservice: %s", err) } - - // Set the state DB connection state.DB = dbConn exporter := trans.NewExporter(dbConn) diff --git a/cmd/gotosocial/action/admin/trans/import.go b/cmd/gotosocial/action/admin/trans/import.go index 1ebf587ff..d34c816bb 100644 --- a/cmd/gotosocial/action/admin/trans/import.go +++ b/cmd/gotosocial/action/admin/trans/import.go @@ -33,12 +33,12 @@ import ( var Import action.GTSAction = func(ctx context.Context) error { var state state.State + // Only set state DB connection. + // Don't need Actions or Workers for this. dbConn, err := bundb.NewBunDBService(ctx, &state) if err != nil { return fmt.Errorf("error creating dbservice: %s", err) } - - // Set the state DB connection state.DB = dbConn importer := trans.NewImporter(dbConn) diff --git a/cmd/gotosocial/action/server/server.go b/cmd/gotosocial/action/server/server.go index 376ade13d..efedda9ec 100644 --- a/cmd/gotosocial/action/server/server.go +++ b/cmd/gotosocial/action/server/server.go @@ -32,6 +32,7 @@ import ( "github.com/KimMachineGun/automemlimit/memlimit" "github.com/gin-gonic/gin" "github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api" apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util" "github.com/superseriousbusiness/gotosocial/internal/cleaner" @@ -44,6 +45,7 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/metrics" "github.com/superseriousbusiness/gotosocial/internal/middleware" tlprocessor "github.com/superseriousbusiness/gotosocial/internal/processing/timeline" + "github.com/superseriousbusiness/gotosocial/internal/subscriptions" "github.com/superseriousbusiness/gotosocial/internal/timeline" "github.com/superseriousbusiness/gotosocial/internal/tracing" "go.uber.org/automaxprocs/maxprocs" @@ -164,6 +166,10 @@ var Start action.GTSAction = func(ctx context.Context) error { // Set DB on state. state.DB = dbService + // Set Actions on state, providing workers to + // Actions as well for triggering side effects. + state.AdminActions = admin.New(dbService, &state.Workers) + // Ensure necessary database instance prerequisites exist. if err := dbService.CreateInstanceAccount(ctx); err != nil { return fmt.Errorf("error creating instance account: %s", err) @@ -283,15 +289,18 @@ var Start action.GTSAction = func(ctx context.Context) error { // Create background cleaner. cleaner := cleaner.New(state) - // Now schedule background cleaning tasks. - if err := cleaner.ScheduleJobs(); err != nil { - return fmt.Errorf("error scheduling cleaner jobs: %w", err) - } + // Create subscriptions fetcher. + subscriptions := subscriptions.New( + state, + transportController, + typeConverter, + ) // Create the processor using all the // other services we've created so far. process = processing.NewProcessor( cleaner, + subscriptions, typeConverter, federator, oauthServer, @@ -302,6 +311,16 @@ var Start action.GTSAction = func(ctx context.Context) error { intFilter, ) + // Schedule background cleaning tasks. + if err := cleaner.ScheduleJobs(); err != nil { + return fmt.Errorf("error scheduling cleaner jobs: %w", err) + } + + // Schedule background subscriptions updating. + if err := subscriptions.ScheduleJobs(); err != nil { + return fmt.Errorf("error scheduling subscriptions jobs: %w", err) + } + // Initialize the specialized workers pools. state.Workers.Client.Init(messages.ClientMsgIndices()) state.Workers.Federator.Init(messages.FederatorMsgIndices()) diff --git a/cmd/gotosocial/action/testrig/testrig.go b/cmd/gotosocial/action/testrig/testrig.go index 19588c70a..0036b7a7d 100644 --- a/cmd/gotosocial/action/testrig/testrig.go +++ b/cmd/gotosocial/action/testrig/testrig.go @@ -20,11 +20,9 @@ package testrig import ( - "bytes" "context" "errors" "fmt" - "io" "net/http" "os" "os/signal" @@ -47,6 +45,7 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/router" "github.com/superseriousbusiness/gotosocial/internal/state" "github.com/superseriousbusiness/gotosocial/internal/storage" + "github.com/superseriousbusiness/gotosocial/internal/subscriptions" "github.com/superseriousbusiness/gotosocial/internal/timeline" "github.com/superseriousbusiness/gotosocial/internal/tracing" "github.com/superseriousbusiness/gotosocial/internal/typeutils" @@ -159,16 +158,8 @@ var Start action.GTSAction = func(ctx context.Context) error { testrig.StandardStorageSetup(state.Storage, "./testrig/media") // build backend handlers - transportController := testrig.NewTestTransportController(state, testrig.NewMockHTTPClient(func(req *http.Request) (*http.Response, error) { - r := io.NopCloser(bytes.NewReader([]byte{})) - return &http.Response{ - StatusCode: 200, - Body: r, - Header: http.Header{ - "Content-Type": req.Header.Values("Accept"), - }, - }, nil - }, "")) + httpClient := testrig.NewMockHTTPClient(nil, "./testrig/media") + transportController := testrig.NewTestTransportController(state, httpClient) mediaManager := testrig.NewTestMediaManager(state) federator := testrig.NewTestFederator(state, transportController, mediaManager) @@ -314,11 +305,23 @@ var Start action.GTSAction = func(ctx context.Context) error { // Create background cleaner. cleaner := cleaner.New(state) - // Now schedule background cleaning tasks. + // Schedule background cleaning tasks. if err := cleaner.ScheduleJobs(); err != nil { return fmt.Errorf("error scheduling cleaner jobs: %w", err) } + // Create subscriptions fetcher. + subscriptions := subscriptions.New( + state, + transportController, + typeConverter, + ) + + // Schedule background subscriptions updating. + if err := subscriptions.ScheduleJobs(); err != nil { + return fmt.Errorf("error scheduling subscriptions jobs: %w", err) + } + // Finally start the main http server! if err := route.Start(); err != nil { return fmt.Errorf("error starting router: %w", err) diff --git a/docs/admin/domain_blocks.md b/docs/admin/domain_blocks.md index 76f11d8a5..f89c84a10 100644 --- a/docs/admin/domain_blocks.md +++ b/docs/admin/domain_blocks.md @@ -2,7 +2,7 @@ GoToSocial supports 'blocking'/'suspending' domains that you don't want your instance to federate with. In our documentation, the two terms 'block' and 'suspend' are used interchangeably with regard to domains, because they mean the same thing: preventing your instance and the instance running on the target domain from communicating with one another, effectively cutting off federation between the two instances. -You can view, create, and remove domain blocks and domain allows using the [instance admin panel](./settings.md#federation). +You can view, create, and remove domain blocks and domain allows using the [instance admin panel](./settings.md#domain-permissions). This document focuses on what domain blocks actually *do* and what side effects are processed when you create a new domain block. diff --git a/docs/admin/domain_permission_subscriptions.md b/docs/admin/domain_permission_subscriptions.md new file mode 100644 index 000000000..77ec831e1 --- /dev/null +++ b/docs/admin/domain_permission_subscriptions.md @@ -0,0 +1,145 @@ +# Domain Permission Subscriptions + +Via the [admin settings panel](./settings.md#subscriptions), you can create and manage domain permission subscriptions. + +Domain permission subscriptions allow you to specify a URL at which a permission list is hosted. Every 24hrs at 11pm (by default), your instance will fetch and parse each list you're subscribed to, in order of priority (highest to lowest), and create domain permissions (or domain permission drafts) based on entries discovered in the lists. + +Each domain permission subscription can be used to create domain allow or domain block entries. + +!!! warning + Currently, via blocklist subscriptions it is only possible to create "suspend" level domain blocks; other severities are not yet supported. Entries of severity "silence" or "limit" etc. on subscribed blocklists will be skipped. + +## Priority + +When you specify multiple domain permission subscriptions, they will be fetched and parsed in order of priority, from highest priority (255) to lowest priority (0). + +Permissions discovered on lists higher up in the priority ranking will override permissions on lists lower down in the priority ranking. + +For example, an instance admin subscribes to two allow lists, "Important List" at priority 255, and "Less Important List" at priority 128. Each of these subscribed lists contain an entry for `good-eggs.example.org`. + +The subscription with the higher priority is the one that now creates and manages the domain allow entry for `good-eggs.example.org`. + +If the subscription with the higher priority is removed, then the next time all the subscriptions are fetched, "Less Important List" will create (or take ownership of) the domain allow instead. + +## Orphan Permissions + +Domain permissions (blocks or allows) that are not currently managed by a domain permission subscription are considered "orphan" permissions. This includes permissions that an admin created in the settings panel by hand, or which were imported manually via the import/export page. + +If you wish, when creating a domain permission subscription, you can set ["adopt orphans"](./settings.md#adopt-orphan-permissions) to true for that subscription. If a domain permission subscription that is set to adopt orphans encounters an orphan permission which is *also present on the list at the subscription's URI*, then it will "adopt" the orphan by setting the orphan's subscription ID to its own ID. + +For example, an instance admin manually creates a domain block for the domain `horrid-trolls.example.org`. Later, they create a domain permission subscription for a block list that contains an entry for `horrid-trolls.example.org`, and they set "adopt orphans" to true. When their instance fetches and parses the list, and creates domain permission entries from it, then the orphan domain block for `horrid-trolls.example.org` gets adopted by the domain permission subscription. Now, if the domain permission subscription is removed, and the option to remove all permissions owned by the subscription is checked, then the domain block for `horrid-trolls.example.org` will also be removed. + +## Fun Stuff To Do With Domain Permission Subscriptions + +### 1. Create an allowlist-federation cluster. + +Domain permission subscriptions make it possible to easily create allowlist-federation clusters, ie., a group of instances can essentially form their own mini-fediverse, wherein each instance runs in [allowlist federation mode](./federation_modes.md#allowlist-federation-mode), and subscribes to a cooperatively-managed allowlist hosted somewhere. + +For example, instances `instance-a.example.org`, `instance-b.example.org`, and `instance-c.example.org` decide that they only want to federate with each other. + +Using some version management platform like GitHub, they host a plaintext-formatted allowlist at something like `https://raw.githubusercontent.com/our-cluster/allowlist/refs/heads/main/allows.txt`. + +The contents of the plaintext-formatted allowlist are as follows: + +```text +instance-a.example.org +instance-b.example.org +instance-c.example.org +``` + +Each instance admin sets their federation mode to `allowlist`, and creates a subscription to create allows from `https://raw.githubusercontent.com/our-cluster/allowlist/refs/heads/main/allows.txt`, which results in domain allow entries being created for their own domain, and for each other domain in the cluster. + +At some point, someone from `instance-d.example.org` asks (out of band) whether they can be added to the cluster. The existing admins agree, and update their plaintext-formatted allowlist to read: + +```text +instance-a.example.org +instance-b.example.org +instance-c.example.org +instance-d.example.org +``` + +The next time each instance fetches the list, a new domain allow entry will be created for `instance-d.example.org`, and it will be able to federate with the other domains on the list. + +### 2. Cooperatively manage a blocklist. + +Domain permission subscriptions make it easy to collaborate on and subscribe to shared blocklists of domains that host illegal / fashy / otherwise undesired accounts and content. + +For example, the admins of instances `instance-e.example.org`, `instance-f.example.org`, and `instance-g.example.org` decide that they are tired of duplicating work by playing whack-a-mole with bad actors. To make their lives easier, they decide to collaborate on a shared blocklist. + +Using some version management platform like GitHub, they host a blocklist at something like `https://raw.githubusercontent.com/baddies/blocklist/refs/heads/main/blocks.csv`. + +When someone discovers a new domain hosting an instance they don't like, they can open a pull request or similar against the list, to add the questionable instance to the domain. + +For example, someone gets an unpleasant reply from a new instance `fashy-arseholes.example.org`. Using their collaboration tools, they propose adding `fashy-arseholes.example.org` to the blocklist. After some deliberation and discussion, the domain is added to the list. + +The next time each of `instance-e.example.org`, `instance-f.example.org`, and `instance-g.example.org` fetch the block list, a block entry will be created for ``fashy-arseholes.example.org``. + +### 3. Subscribe to a blocklist, but ignore some of it. + +Say that `instance-g.example.org` in the previous section decides that they agree with most of the collaboratively-curated blocklist, but they actually would like to keep federating with ``fashy-arseholes.example.org`` for some godforsaken reason. + +This can be done in one of three ways: + +1. The admin of `instance-g.example.org` subscribes to the shared blocklist, but they do so with the ["create as drafts"](./settings.md#create-permissions-as-drafts) option set to true. When their instance fetches the blocklist, a draft block is created for `fashy-arseholes.example.org`. The admin of `instance-g` just leaves the permission as a draft, or rejects it, so it never comes into force. +2. Before the blocklist is re-fetched, the admin of `instance-g.example.org` creates a [domain permission exclude](./settings.md#excludes) entry for ``instance-g.example.org``. The domain ``instance-g.example.org`` then becomes exempt/excluded from automatic permission creation, and so the block for ``instance-g.example.org`` on the shared blocklist does not get created in the database of ``instance-g.example.org`` the next time the list is fetched. +3. The admin of `instance-g.example.org` creates an explicit domain allow entry for `fashy-arseholes.example.org` on their own instance. Because their instance is running in `blocklist` federation mode, [the explicit allow overrides the domain block entry](./federation_modes.md#in-blocklist-mode), and so the domain remains unblocked. + +### 4. Subscribe directly to another instance's blocklist. + +Because GoToSocial is able to fetch and parse JSON-formatted lists of domain permissions, it is possible to subscribe directly to another instance's list of blocked domains via their `/api/v1/instance/domain_blocks` (Mastodon) or `/api/v1/instance/peers?filter=suspended` (GoToSocial) endpoint (if exposed). + +For example, the Mastodon instance `peepee.poopoo.example.org` exposes their block list publicly, and the owner of the GoToSocial instance `instance-h.example.org` decides they quite like the cut of the Mastodon moderator's jib. They create a domain permission subscription of type JSON, and set the URI to `https://peepee.poopoo.example.org/api/v1/instance/domain_blocks`. Every 24 hours, their instance will go fetch the blocklist JSON from the Mastodon instance, and create permissions based on entries discovered therein. + +## Example lists per content type + +Shown below are examples of the different permission list formats that GoToSocial is able to understand and parse. + +Each list contains three domains, `bumfaces.net`, `peepee.poopoo`, and `nothanks.com`. + +### CSV + +CSV lists use content type `text/csv`. + +Mastodon domain permission exports generally use this format. + +```csv +#domain,#severity,#reject_media,#reject_reports,#public_comment,#obfuscate +bumfaces.net,suspend,false,false,big jerks,false +peepee.poopoo,suspend,false,false,harassment,false +nothanks.com,suspend,false,false,,false +``` + +### JSON (application/json) + +JSON lists use content type `application/json`. + +```json +[ + { + "domain": "bumfaces.net", + "suspended_at": "2020-05-13T13:29:12.000Z", + "public_comment": "big jerks" + }, + { + "domain": "peepee.poopoo", + "suspended_at": "2020-05-13T13:29:12.000Z", + "public_comment": "harassment" + }, + { + "domain": "nothanks.com", + "suspended_at": "2020-05-13T13:29:12.000Z" + } +] +``` + +### Plaintext (text/plain) + +Plaintext lists use content type `text/plain`. + +Note that it is not possible to include any fields like "obfuscate" or "public comment" in plaintext lists, as they are simply a newline-separated list of domains. + +```text +bumfaces.net +peepee.poopoo +nothanks.com +``` diff --git a/docs/admin/settings.md b/docs/admin/settings.md index 170d07e6a..37581e177 100644 --- a/docs/admin/settings.md +++ b/docs/admin/settings.md @@ -34,11 +34,11 @@ Clicking on the username of the reported account opens that account in the 'Acco You can use this section to search for an account and perform moderation actions on it. -### Federation +### Domain Permissions ![List of suspended instances, with a field to filter/add new blocks. Below is a link to the bulk import/export interface](../public/admin-settings-federation.png) -In the federation section you can create, delete, and review explicit domain blocks and domain allows. +In the domain permissions section you can create, delete, and review domain blocks, domain allows, drafts, excludes, and subscriptions. For more detail on federation settings, and specifically how domain allows and domain blocks work in combination, please see [the federation modes section](./federation_modes.md), and [the domain blocks section](./domain_blocks.md). @@ -46,20 +46,99 @@ For more detail on federation settings, and specifically how domain allows and d You can enter a domain to suspend in the search field, which will filter the list to show you if you already have a block for it. -Clicking 'suspend' gives you a form to add a public and/or private comment, and submit to add the block. Adding a suspension will suspend all the currently known accounts on the instance, and prevent any new interactions with any user on the blocked instance. +Clicking 'suspend' gives you a form to add a public and/or private comment, and submit to add the block. + +Adding a domain block will suspend all currently known accounts from that domain, and prevent any new interactions with the blocked domain. #### Domain Allows The domain allows section works much like the domain blocks section, described above, only for explicit domain allows rather than domain blocks. -#### Bulk import/export +#### Import/export -Through the link at the bottom of the Federation section (or going to `/settings/admin/federation/import-export`) you can do bulk import/export of blocklists and allowlists. +In this section you can do bulk import/export of domain permissions in JSON, CSV, or plaintext formats. ![List of domains included in an import, providing ways to select some or all of them, change their domains, and update the use of subdomains.](../public/admin-settings-federation-import-export.png) Upon importing a list, either through the input field or from a file, you can review the entries in the list before importing a subset. You'll also be warned for entries that use subdomains, providing an easy way to change them to the main domain. +#### Drafts + +In this section you can create, search through, accept, and reject domain permission drafts. + +Domain permission drafts are domain permissions that have been proposed (either via manual creation or as an entry from a subscribed block / allow list), but have not yet come into force. + +Until it is accepted, a domain permission draft will not have any effect on federation with the domain it targets. Upon acceptance, it will be converted into either a domain block or a domain allow, and start being enforced. + +#### Excludes + +In this section, you can create, search through, and remove domain permission excludes. + +Domain permission excludes prevent permissions for a domain (and all subdomains) from being automatically managed by domain permission subscriptions. + +For example, if you create an exclude entry for the domain `example.org`, then a blocklist or allowlist subscription will exclude entries for `example.org` and any of its subdomains (`sub.example.org`, `another.sub.example.org` etc.) when creating domain permission drafts and domain blocks/allows. + +This functionality allows you to manually manage permissions for excluded domains, in cases where you know you definitely do or don't want to federate with a given domain, no matter what entries are contained in a domain permission subscription. + +Note that by itself, creation of an exclude entry for a given domain does not affect federation with that domain at all, it is only useful in combination with permission subscriptions. + +#### Subscriptions + +In this section, you can create, search through, edit, test, and remove domain permission subscriptions. + +Domain permission subscriptions allow you to specify a URL at which a permission list is hosted. Every 24hrs at 11pm (by default), your instance will fetch and parse each subscribed list, and create domain permissions (or domain permission drafts) based on entries in the lists. + +##### Title + +You can optionally use the title field to set a title for the subscription, as a reminder for yourself and other admins. + +For example, you might subscribe to a list at `https://lists.example.org/baddies.csv` and set the title of the subscription to something that reflects the contents of that list, such as "Basic block list (worst of the worst)", or similar. + +##### Subscription Priority + +When you specify multiple domain permission subscriptions, they will be fetched and parsed in order of priority, from highest priority (255) to lowest priority (0). + +Permissions discovered on lists higher up in the priority ranking will override permissions on lists lower down in the priority ranking. + +For more information on priority, please see the separate [domain permission subscriptions](./domain_permission_subscriptions.md) document. + +##### Permission Type + +You can use this dropdown to select whether permissions discovered at the list URL should be created as domain blocks, or domain allows. + +##### Content Type + +You can use this dropdown to select the content type of the list at the subscribed URL. + +Use CSV for Mastodon-style permission lists, plain for plaintext lists of domain names, or JSON for json-exported lists. + +##### Basic Auth + +Check this box to provide a basic auth username and/or password credential for the subscribed list, which will be sent along with each request to fetch the list. + +##### Adopt Orphan Permissions + +If you check this box, then any existing domain permissions will become managed by this subscription in the following circumstances: + +1. They don't already have a subscription ID (ie., they're not managed by any domain permission subscription). +2. They match a domain permission included in the list at the URL of this subscription. + +For more information on orphan permissions, please see the separate [domain permission subscriptions](./domain_permission_subscriptions.md) document. + +##### Create Permissions as Drafts + +With this box checked (default), any permissions created by this subscription will be created as **drafts** which require manual approval to come into force. + +It is recommended to leave this box checked unless you absolutely trust the subscribed list, to avoid inadvertent blocking or allowing of domains you'd rather not block or allow. + +##### Test a Subscription + +To test whether a subscription can be successfully parsed, first create the subscription, then in the detailed view for that subscription, click on the "Test" button. + +If your instance is able to fetch and parse permissions at the subscription URI, then you will see a list of these after clicking "Test". Otherwise, you will see an error message. + +![Screenshot of the detailed view of a subscription, with arrows pointing to the test section near the bottom.](../public/admin-settings-federation-subscription-test.png) + ## Administration Instance administration settings. diff --git a/docs/api/swagger.yaml b/docs/api/swagger.yaml index 235309ba9..322b79b16 100644 --- a/docs/api/swagger.yaml +++ b/docs/api/swagger.yaml @@ -6436,6 +6436,46 @@ paths: summary: Remove a domain permission subscription. tags: - admin + /api/v1/admin/domain_permission_subscriptions/{id}/test: + post: + description: |- + The response body will be a list of domain permissions that *would* be created by this subscription, OR an error message. + + This is useful in cases where you want to check that your instance can actually fetch + parse a list. + operationId: domainPermissionSubscriptionTest + parameters: + - description: ID of the domain permission draft. + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: Either an array of domain permissions, OR an error message of the form `{"error":"[ERROR MESSAGE HERE]"}` indicating why the list could not be fetched. + schema: + items: + $ref: '#/definitions/domain' + type: array + "400": + description: bad request + "401": + description: unauthorized + "403": + description: forbidden + "406": + description: not acceptable + "409": + description: conflict + "500": + description: internal server error + security: + - OAuth2 Bearer: + - admin + summary: Test one domain permission subscription by making your instance fetch and parse it *without creating permissions*. + tags: + - admin /api/v1/admin/domain_permission_subscriptions/preview: get: description: This view allows you to see the order in which domain permissions will actually be fetched and created. diff --git a/docs/overrides/public/admin-settings-federation-subscription-test.png b/docs/overrides/public/admin-settings-federation-subscription-test.png new file mode 100644 index 0000000000000000000000000000000000000000..8ee9a6aa17a019031411a439100d1799b863da8c GIT binary patch literal 158370 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 literal 97674 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≫b# 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

qq!8CYf%h&oIo3z`R z3tmT!+rCaASl8^RPbd_@SR#Kv7J8{~sQ�#eqCwCH7x`L80jKkqH$3ry0EM|AiZ? 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 V2I*z6`+3JX#LNH3)*o*C@^43rR$u@C diff --git a/internal/processing/admin/actions.go b/internal/admin/actions.go similarity index 75% rename from internal/processing/admin/actions.go rename to internal/admin/actions.go index 968e45baa..057bfe07d 100644 --- a/internal/processing/admin/actions.go +++ b/internal/admin/actions.go @@ -23,11 +23,12 @@ import ( "sync" "time" + "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/gtscontext" "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/log" - "github.com/superseriousbusiness/gotosocial/internal/state" + "github.com/superseriousbusiness/gotosocial/internal/workers" ) func errActionConflict(action *gtsmodel.AdminAction) gtserror.WithCode { @@ -42,15 +43,34 @@ func errActionConflict(action *gtsmodel.AdminAction) gtserror.WithCode { } type Actions struct { - r map[string]*gtsmodel.AdminAction - state *state.State + // Map of running actions. + running map[string]*gtsmodel.AdminAction - // Not embedded struct, - // to shield from access - // by outside packages. + // Lock for running admin actions. + // + // Not embedded struct, to shield + // from access by outside packages. m sync.Mutex + + // DB for storing, updating, + // deleting admin actions etc. + db db.DB + + // Workers for queuing + // admin action side effects. + workers *workers.Workers } +func New(db db.DB, workers *workers.Workers) *Actions { + return &Actions{ + running: make(map[string]*gtsmodel.AdminAction), + db: db, + workers: workers, + } +} + +type ActionF func(context.Context) gtserror.MultiError + // Run runs the given admin action by executing the supplied function. // // Run handles locking, action insertion and updating, so you don't have to! @@ -62,10 +82,10 @@ type Actions struct { // will be updated on the provided admin action in the database. func (a *Actions) Run( ctx context.Context, - action *gtsmodel.AdminAction, - f func(context.Context) gtserror.MultiError, + adminAction *gtsmodel.AdminAction, + f ActionF, ) gtserror.WithCode { - actionKey := action.Key() + actionKey := adminAction.Key() // LOCK THE MAP HERE, since we're // going to do some operations on it. @@ -73,7 +93,7 @@ func (a *Actions) Run( // Bail if an action with // this key is already running. - running, ok := a.r[actionKey] + running, ok := a.running[actionKey] if ok { a.m.Unlock() return errActionConflict(running) @@ -81,7 +101,7 @@ func (a *Actions) Run( // Action with this key not // yet running, create it. - if err := a.state.DB.PutAdminAction(ctx, action); err != nil { + if err := a.db.PutAdminAction(ctx, adminAction); err != nil { err = gtserror.Newf("db error putting admin action %s: %w", actionKey, err) // Don't store in map @@ -92,7 +112,7 @@ func (a *Actions) Run( // Action was inserted, // store in map. - a.r[actionKey] = action + a.running[actionKey] = adminAction // UNLOCK THE MAP HERE, since // we're done modifying it for now. @@ -104,22 +124,22 @@ func (a *Actions) Run( // Run the thing and collect errors. if errs := f(ctx); errs != nil { - action.Errors = make([]string, 0, len(errs)) + adminAction.Errors = make([]string, 0, len(errs)) for _, err := range errs { - action.Errors = append(action.Errors, err.Error()) + adminAction.Errors = append(adminAction.Errors, err.Error()) } } // Action is no longer running: // remove from running map. a.m.Lock() - delete(a.r, actionKey) + delete(a.running, actionKey) a.m.Unlock() // Mark as completed in the db, // storing errors for later review. - action.CompletedAt = time.Now() - if err := a.state.DB.UpdateAdminAction(ctx, action, "completed_at", "errors"); err != nil { + adminAction.CompletedAt = time.Now() + if err := a.db.UpdateAdminAction(ctx, adminAction, "completed_at", "errors"); err != nil { log.Errorf(ctx, "db error marking action %s as completed: %q", actionKey, err) } }() @@ -135,8 +155,8 @@ func (a *Actions) GetRunning() []*gtsmodel.AdminAction { defer a.m.Unlock() // Assemble all currently running actions. - running := make([]*gtsmodel.AdminAction, 0, len(a.r)) - for _, action := range a.r { + running := make([]*gtsmodel.AdminAction, 0, len(a.running)) + for _, action := range a.running { running = append(running, action) } @@ -166,5 +186,5 @@ func (a *Actions) TotalRunning() int { a.m.Lock() defer a.m.Unlock() - return len(a.r) + return len(a.running) } diff --git a/internal/processing/admin/actions_test.go b/internal/admin/actions_test.go similarity index 80% rename from internal/processing/admin/actions_test.go rename to internal/admin/actions_test.go index 9d12ae84d..c5084d955 100644 --- a/internal/processing/admin/actions_test.go +++ b/internal/admin/actions_test.go @@ -32,12 +32,26 @@ import ( "github.com/superseriousbusiness/gotosocial/testrig" ) +const ( + rMediaPath = "../../testrig/media" + rTemplatePath = "../../web/template" +) + type ActionsTestSuite struct { - AdminStandardTestSuite + suite.Suite +} + +func (suite *ActionsTestSuite) SetupSuite() { + testrig.InitTestConfig() + testrig.InitTestLog() } func (suite *ActionsTestSuite) TestActionOverlap() { - ctx := context.Background() + var ( + testStructs = testrig.SetupTestStructs(rMediaPath, rTemplatePath) + ctx = context.Background() + ) + defer testrig.TearDownTestStructs(testStructs) // Suspend account. action1 := >smodel.AdminAction{ @@ -61,7 +75,7 @@ func (suite *ActionsTestSuite) TestActionOverlap() { key2 := action2.Key() suite.Equal("account/01H90S1CXQ97J9625C5YBXZWGT", key2) - errWithCode := suite.adminProcessor.Actions().Run( + errWithCode := testStructs.State.AdminActions.Run( ctx, action1, func(ctx context.Context) gtserror.MultiError { @@ -74,7 +88,7 @@ func (suite *ActionsTestSuite) TestActionOverlap() { // While first action is sleeping, try to // process another with the same key. - errWithCode = suite.adminProcessor.Actions().Run( + errWithCode = testStructs.State.AdminActions.Run( ctx, action2, func(ctx context.Context) gtserror.MultiError { @@ -90,13 +104,13 @@ func (suite *ActionsTestSuite) TestActionOverlap() { // Wait for action to finish. if !testrig.WaitFor(func() bool { - return suite.adminProcessor.Actions().TotalRunning() == 0 + return testStructs.State.AdminActions.TotalRunning() == 0 }) { suite.FailNow("timed out waiting for admin action(s) to finish") } // Try again. - errWithCode = suite.adminProcessor.Actions().Run( + errWithCode = testStructs.State.AdminActions.Run( ctx, action2, func(ctx context.Context) gtserror.MultiError { @@ -107,14 +121,18 @@ func (suite *ActionsTestSuite) TestActionOverlap() { // Wait for action to finish. if !testrig.WaitFor(func() bool { - return suite.adminProcessor.Actions().TotalRunning() == 0 + return testStructs.State.AdminActions.TotalRunning() == 0 }) { suite.FailNow("timed out waiting for admin action(s) to finish") } } func (suite *ActionsTestSuite) TestActionWithErrors() { - ctx := context.Background() + var ( + testStructs = testrig.SetupTestStructs(rMediaPath, rTemplatePath) + ctx = context.Background() + ) + defer testrig.TearDownTestStructs(testStructs) // Suspend a domain. action := >smodel.AdminAction{ @@ -125,7 +143,7 @@ func (suite *ActionsTestSuite) TestActionWithErrors() { AccountID: "01H90S1ZZXP4N74H4A9RVW1MRP", } - errWithCode := suite.adminProcessor.Actions().Run( + errWithCode := testStructs.State.AdminActions.Run( ctx, action, func(ctx context.Context) gtserror.MultiError { @@ -140,13 +158,13 @@ func (suite *ActionsTestSuite) TestActionWithErrors() { // Wait for action to finish. if !testrig.WaitFor(func() bool { - return suite.adminProcessor.Actions().TotalRunning() == 0 + return testStructs.State.AdminActions.TotalRunning() == 0 }) { suite.FailNow("timed out waiting for admin action(s) to finish") } // Get action from the db. - dbAction, err := suite.db.GetAdminAction(ctx, action.ID) + dbAction, err := testStructs.State.DB.GetAdminAction(ctx, action.ID) if err != nil { suite.FailNow(err.Error()) } diff --git a/internal/admin/domainkeys.go b/internal/admin/domainkeys.go new file mode 100644 index 000000000..ad943ce80 --- /dev/null +++ b/internal/admin/domainkeys.go @@ -0,0 +1,51 @@ +// GoToSocial +// Copyright (C) GoToSocial Authors admin@gotosocial.org +// SPDX-License-Identifier: AGPL-3.0-or-later +// +// 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 admin + +import ( + "context" + "time" + + "github.com/superseriousbusiness/gotosocial/internal/gtserror" + "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" +) + +func (a *Actions) DomainKeysExpireF(domain string) ActionF { + return func(ctx context.Context) gtserror.MultiError { + var ( + expiresAt = time.Now() + errs gtserror.MultiError + ) + + // For each account on this domain, expire + // the public key and update the account. + if err := a.rangeDomainAccounts(ctx, domain, func(account *gtsmodel.Account) { + account.PublicKeyExpiresAt = expiresAt + if err := a.db.UpdateAccount(ctx, + account, + "public_key_expires_at", + ); err != nil { + errs.Appendf("db error updating account: %w", err) + } + }); err != nil { + errs.Appendf("db error ranging through accounts: %w", err) + } + + return errs + } +} diff --git a/internal/admin/domainperms.go b/internal/admin/domainperms.go new file mode 100644 index 000000000..fa686df43 --- /dev/null +++ b/internal/admin/domainperms.go @@ -0,0 +1,387 @@ +// GoToSocial +// Copyright (C) GoToSocial Authors admin@gotosocial.org +// SPDX-License-Identifier: AGPL-3.0-or-later +// +// 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 admin + +import ( + "context" + "errors" + "time" + + "codeberg.org/gruf/go-kv" + + "github.com/superseriousbusiness/gotosocial/internal/ap" + "github.com/superseriousbusiness/gotosocial/internal/config" + "github.com/superseriousbusiness/gotosocial/internal/db" + "github.com/superseriousbusiness/gotosocial/internal/gtserror" + "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/internal/log" + "github.com/superseriousbusiness/gotosocial/internal/messages" +) + +// Returns an AdminActionF for +// domain allow side effects. +func (a *Actions) DomainAllowF( + actionID string, + domainAllow *gtsmodel.DomainAllow, +) ActionF { + return func(ctx context.Context) gtserror.MultiError { + l := log. + WithContext(ctx). + WithFields(kv.Fields{ + {"action", "allow"}, + {"actionID", actionID}, + {"domain", domainAllow.Domain}, + }...) + + // Log start + finish. + l.Info("processing side effects") + errs := a.domainAllowSideEffects(ctx, domainAllow) + l.Info("finished processing side effects") + + return errs + } +} + +func (a *Actions) domainAllowSideEffects( + ctx context.Context, + allow *gtsmodel.DomainAllow, +) gtserror.MultiError { + if config.GetInstanceFederationMode() == config.InstanceFederationModeAllowlist { + // We're running in allowlist mode, + // so there are no side effects to + // process here. + return nil + } + + // We're running in blocklist mode or + // some similar mode which necessitates + // domain allow side effects if a block + // was in place when the allow was created. + // + // So, check if there's a block. + block, err := a.db.GetDomainBlock(ctx, allow.Domain) + if err != nil && !errors.Is(err, db.ErrNoEntries) { + errs := gtserror.NewMultiError(1) + errs.Appendf("db error getting domain block %s: %w", allow.Domain, err) + return errs + } + + if block == nil { + // No block? + // No problem! + return nil + } + + // There was a block, over which the new + // allow ought to take precedence. To account + // for this, just run side effects as though + // the domain was being unblocked, while + // leaving the existing block in place. + // + // Any accounts that were suspended by + // the block will be unsuspended and be + // able to interact with the instance again. + return a.domainUnblockSideEffects(ctx, block) +} + +// Returns an AdminActionF for +// domain unallow side effects. +func (a *Actions) DomainUnallowF( + actionID string, + domainAllow *gtsmodel.DomainAllow, +) ActionF { + return func(ctx context.Context) gtserror.MultiError { + l := log. + WithContext(ctx). + WithFields(kv.Fields{ + {"action", "unallow"}, + {"actionID", actionID}, + {"domain", domainAllow.Domain}, + }...) + + // Log start + finish. + l.Info("processing side effects") + errs := a.domainUnallowSideEffects(ctx, domainAllow) + l.Info("finished processing side effects") + + return errs + } +} + +func (a *Actions) domainUnallowSideEffects( + ctx context.Context, + allow *gtsmodel.DomainAllow, +) gtserror.MultiError { + if config.GetInstanceFederationMode() == config.InstanceFederationModeAllowlist { + // We're running in allowlist mode, + // so there are no side effects to + // process here. + return nil + } + + // We're running in blocklist mode or + // some similar mode which necessitates + // domain allow side effects if a block + // was in place when the allow was removed. + // + // So, check if there's a block. + block, err := a.db.GetDomainBlock(ctx, allow.Domain) + if err != nil && !errors.Is(err, db.ErrNoEntries) { + errs := gtserror.NewMultiError(1) + errs.Appendf("db error getting domain block %s: %w", allow.Domain, err) + return errs + } + + if block == nil { + // No block? + // No problem! + return nil + } + + // There was a block, over which the previous + // allow was taking precedence. Now that the + // allow has been removed, we should put the + // side effects of the block back in place. + // + // To do this, process the block side effects + // again as though the block were freshly + // created. This will mark all accounts from + // the blocked domain as suspended, and clean + // up their follows/following, media, etc. + return a.domainBlockSideEffects(ctx, block) +} + +func (a *Actions) DomainBlockF( + actionID string, + domainBlock *gtsmodel.DomainBlock, +) ActionF { + return func(ctx context.Context) gtserror.MultiError { + l := log. + WithContext(ctx). + WithFields(kv.Fields{ + {"action", "block"}, + {"actionID", actionID}, + {"domain", domainBlock.Domain}, + }...) + + skip, err := a.skipBlockSideEffects(ctx, domainBlock.Domain) + if err != nil { + return err + } + + if skip != "" { + l.Infof("skipping side effects: %s", skip) + return nil + } + + l.Info("processing side effects") + errs := a.domainBlockSideEffects(ctx, domainBlock) + l.Info("finished processing side effects") + + return errs + } +} + +// domainBlockSideEffects processes the side effects of a domain block: +// +// 1. Strip most info away from the instance entry for the domain. +// 2. Pass each account from the domain to the processor for deletion. +// +// It should be called asynchronously, since it can take a while when +// there are many accounts present on the given domain. +func (a *Actions) domainBlockSideEffects( + ctx context.Context, + block *gtsmodel.DomainBlock, +) gtserror.MultiError { + var errs gtserror.MultiError + + // If we have an instance entry for this domain, + // update it with the new block ID and clear all fields + instance, err := a.db.GetInstance(ctx, block.Domain) + if err != nil && !errors.Is(err, db.ErrNoEntries) { + errs.Appendf("db error getting instance %s: %w", block.Domain, err) + return errs + } + + if instance != nil { + // We had an entry for this domain. + columns := stubbifyInstance(instance, block.ID) + if err := a.db.UpdateInstance(ctx, instance, columns...); err != nil { + errs.Appendf("db error updating instance: %w", err) + return errs + } + } + + // For each account that belongs to this domain, + // process an account delete message to remove + // that account's posts, media, etc. + if err := a.rangeDomainAccounts(ctx, block.Domain, func(account *gtsmodel.Account) { + if err := a.workers.Client.Process(ctx, &messages.FromClientAPI{ + APObjectType: ap.ActorPerson, + APActivityType: ap.ActivityDelete, + GTSModel: block, + Origin: account, + Target: account, + }); err != nil { + errs.Append(err) + } + }); err != nil { + errs.Appendf("db error ranging through accounts: %w", err) + } + + return errs +} + +func (a *Actions) DomainUnblockF( + actionID string, + domainBlock *gtsmodel.DomainBlock, +) ActionF { + return func(ctx context.Context) gtserror.MultiError { + l := log. + WithContext(ctx). + WithFields(kv.Fields{ + {"action", "unblock"}, + {"actionID", actionID}, + {"domain", domainBlock.Domain}, + }...) + + l.Info("processing side effects") + errs := a.domainUnblockSideEffects(ctx, domainBlock) + l.Info("finished processing side effects") + + return errs + } +} + +// domainUnblockSideEffects processes the side effects of undoing a +// domain block: +// +// 1. Mark instance entry as no longer suspended. +// 2. Mark each account from the domain as no longer suspended, if the +// suspension origin corresponds to the ID of the provided domain block. +// +// It should be called asynchronously, since it can take a while when +// there are many accounts present on the given domain. +func (a *Actions) domainUnblockSideEffects( + ctx context.Context, + block *gtsmodel.DomainBlock, +) gtserror.MultiError { + var errs gtserror.MultiError + + // Update instance entry for this domain, if we have it. + instance, err := a.db.GetInstance(ctx, block.Domain) + if err != nil && !errors.Is(err, db.ErrNoEntries) { + errs.Appendf("db error getting instance %s: %w", block.Domain, err) + } + + if instance != nil { + // We had an entry, update it to signal + // that it's no longer suspended. + instance.SuspendedAt = time.Time{} + instance.DomainBlockID = "" + if err := a.db.UpdateInstance( + ctx, + instance, + "suspended_at", + "domain_block_id", + ); err != nil { + errs.Appendf("db error updating instance: %w", err) + return errs + } + } + + // Unsuspend all accounts whose suspension origin was this domain block. + if err := a.rangeDomainAccounts(ctx, block.Domain, func(account *gtsmodel.Account) { + if account.SuspensionOrigin == "" || account.SuspendedAt.IsZero() { + // Account wasn't suspended, nothing to do. + return + } + + if account.SuspensionOrigin != block.ID { + // Account was suspended, but not by + // this domain block, leave it alone. + return + } + + // Account was suspended by this domain + // block, mark it as unsuspended. + account.SuspendedAt = time.Time{} + account.SuspensionOrigin = "" + + if err := a.db.UpdateAccount( + ctx, + account, + "suspended_at", + "suspension_origin", + ); err != nil { + errs.Appendf("db error updating account %s: %w", account.Username, err) + } + }); err != nil { + errs.Appendf("db error ranging through accounts: %w", err) + } + + return errs +} + +// skipBlockSideEffects checks if side effects of block creation +// should be skipped for the given domain, taking account of +// instance federation mode, and existence of any allows +// which ought to "shield" this domain from being blocked. +// +// If the caller should skip, the returned string will be non-zero +// and will be set to a reason why side effects should be skipped. +// +// - blocklist mode + allow exists: "..." (skip) +// - blocklist mode + no allow: "" (don't skip) +// - allowlist mode + allow exists: "" (don't skip) +// - allowlist mode + no allow: "" (don't skip) +func (a *Actions) skipBlockSideEffects( + ctx context.Context, + domain string, +) (string, gtserror.MultiError) { + var ( + skip string // Assume "" (don't skip). + errs gtserror.MultiError + ) + + // Never skip block side effects in allowlist mode. + fediMode := config.GetInstanceFederationMode() + if fediMode == config.InstanceFederationModeAllowlist { + return skip, errs + } + + // We know we're in blocklist mode. + // + // We want to skip domain block side + // effects if an allow is already + // in place which overrides the block. + + // Check if an explicit allow exists for this domain. + domainAllow, err := a.db.GetDomainAllow(ctx, domain) + if err != nil && !errors.Is(err, db.ErrNoEntries) { + errs.Appendf("error getting domain allow: %w", err) + return skip, errs + } + + if domainAllow != nil { + skip = "running in blocklist mode, and an explicit allow exists for this domain" + return skip, errs + } + + return skip, errs +} diff --git a/internal/admin/util.go b/internal/admin/util.go new file mode 100644 index 000000000..27e81fbb3 --- /dev/null +++ b/internal/admin/util.go @@ -0,0 +1,99 @@ +// GoToSocial +// Copyright (C) GoToSocial Authors admin@gotosocial.org +// SPDX-License-Identifier: AGPL-3.0-or-later +// +// 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 admin + +import ( + "context" + "errors" + "time" + + "github.com/superseriousbusiness/gotosocial/internal/db" + "github.com/superseriousbusiness/gotosocial/internal/gtserror" + "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" +) + +// stubbifyInstance renders the given instance as a stub, +// removing most information from it and marking it as +// suspended. +// +// For caller's convenience, this function returns the db +// names of all columns that are updated by it. +func stubbifyInstance(instance *gtsmodel.Instance, domainBlockID string) []string { + instance.Title = "" + instance.SuspendedAt = time.Now() + instance.DomainBlockID = domainBlockID + instance.ShortDescription = "" + instance.Description = "" + instance.Terms = "" + instance.ContactEmail = "" + instance.ContactAccountUsername = "" + instance.ContactAccountID = "" + instance.Version = "" + + return []string{ + "title", + "suspended_at", + "domain_block_id", + "short_description", + "description", + "terms", + "contact_email", + "contact_account_username", + "contact_account_id", + "version", + } +} + +// rangeDomainAccounts iterates through all accounts +// originating from the given domain, and calls the +// provided range function on each account. +// +// If an error is returned while selecting accounts, +// the loop will stop and return the error. +func (a *Actions) rangeDomainAccounts( + ctx context.Context, + domain string, + rangeF func(*gtsmodel.Account), +) error { + var ( + limit = 50 // Limit selection to avoid spiking mem/cpu. + maxID string // Start with empty string to select from top. + ) + + for { + // Get (next) page of accounts. + accounts, err := a.db.GetInstanceAccounts(ctx, domain, maxID, limit) + if err != nil && !errors.Is(err, db.ErrNoEntries) { + // Real db error. + return gtserror.Newf("db error getting instance accounts: %w", err) + } + + if len(accounts) == 0 { + // No accounts left, we're done. + return nil + } + + // Set next max ID for paging down. + maxID = accounts[len(accounts)-1].ID + + // Call provided range function. + for _, account := range accounts { + rangeF(account) + } + } +} diff --git a/internal/api/activitypub/emoji/emojiget_test.go b/internal/api/activitypub/emoji/emojiget_test.go index 4d687a049..0eb1f5931 100644 --- a/internal/api/activitypub/emoji/emojiget_test.go +++ b/internal/api/activitypub/emoji/emojiget_test.go @@ -25,6 +25,7 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/activitypub/emoji" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -73,6 +74,7 @@ func (suite *EmojiGetTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage suite.tc = typeutils.NewConverter(&suite.state) diff --git a/internal/api/activitypub/users/user_test.go b/internal/api/activitypub/users/user_test.go index 4d55aad3d..10eb33937 100644 --- a/internal/api/activitypub/users/user_test.go +++ b/internal/api/activitypub/users/user_test.go @@ -20,6 +20,7 @@ package users_test import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/activitypub/users" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -84,6 +85,7 @@ func (suite *UserStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.tc = typeutils.NewConverter(&suite.state) testrig.StartTimelines( diff --git a/internal/api/auth/auth_test.go b/internal/api/auth/auth_test.go index d77b1a3d4..c5ceba387 100644 --- a/internal/api/auth/auth_test.go +++ b/internal/api/auth/auth_test.go @@ -26,6 +26,7 @@ import ( "github.com/gin-contrib/sessions/memstore" "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/auth" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" @@ -84,6 +85,7 @@ func (suite *AuthStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage suite.mediaManager = testrig.NewTestMediaManager(&suite.state) diff --git a/internal/api/client/accounts/account_test.go b/internal/api/client/accounts/account_test.go index 2f8664756..db212af22 100644 --- a/internal/api/client/accounts/account_test.go +++ b/internal/api/client/accounts/account_test.go @@ -25,6 +25,7 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/accounts" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" @@ -85,6 +86,7 @@ func (suite *AccountStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/admin/admin.go b/internal/api/client/admin/admin.go index 68a088b4d..a5a16f35f 100644 --- a/internal/api/client/admin/admin.go +++ b/internal/api/client/admin/admin.go @@ -46,6 +46,7 @@ const ( DomainPermissionSubscriptionsPathWithID = DomainPermissionSubscriptionsPath + "/:" + apiutil.IDKey DomainPermissionSubscriptionsPreviewPath = DomainPermissionSubscriptionsPath + "/preview" DomainPermissionSubscriptionRemovePath = DomainPermissionSubscriptionsPathWithID + "/remove" + DomainPermissionSubscriptionTestPath = DomainPermissionSubscriptionsPathWithID + "/test" DomainKeysExpirePath = BasePath + "/domain_keys_expire" HeaderAllowsPath = BasePath + "/header_allows" HeaderAllowsPathWithID = HeaderAllowsPath + "/:" + apiutil.IDKey @@ -129,6 +130,7 @@ func (m *Module) Route(attachHandler func(method string, path string, f ...gin.H attachHandler(http.MethodGet, DomainPermissionSubscriptionsPathWithID, m.DomainPermissionSubscriptionGETHandler) attachHandler(http.MethodPatch, DomainPermissionSubscriptionsPathWithID, m.DomainPermissionSubscriptionPATCHHandler) attachHandler(http.MethodPost, DomainPermissionSubscriptionRemovePath, m.DomainPermissionSubscriptionRemovePOSTHandler) + attachHandler(http.MethodPost, DomainPermissionSubscriptionTestPath, m.DomainPermissionSubscriptionTestPOSTHandler) // header filtering administration routes attachHandler(http.MethodGet, HeaderAllowsPathWithID, m.HeaderFilterAllowGET) diff --git a/internal/api/client/admin/admin_test.go b/internal/api/client/admin/admin_test.go index 962ec3872..479f16f45 100644 --- a/internal/api/client/admin/admin_test.go +++ b/internal/api/client/admin/admin_test.go @@ -25,6 +25,7 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" + adminactions "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/admin" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" @@ -91,6 +92,7 @@ func (suite *AdminStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = adminactions.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/admin/domainpermissionsubscriptiontest.go b/internal/api/client/admin/domainpermissionsubscriptiontest.go new file mode 100644 index 000000000..395a1a69c --- /dev/null +++ b/internal/api/client/admin/domainpermissionsubscriptiontest.go @@ -0,0 +1,118 @@ +// GoToSocial +// Copyright (C) GoToSocial Authors admin@gotosocial.org +// SPDX-License-Identifier: AGPL-3.0-or-later +// +// 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 admin + +import ( + "fmt" + "net/http" + + "github.com/gin-gonic/gin" + apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util" + "github.com/superseriousbusiness/gotosocial/internal/gtserror" + "github.com/superseriousbusiness/gotosocial/internal/oauth" +) + +// DomainPermissionSubscriptionTestPOSTHandler swagger:operation POST /api/v1/admin/domain_permission_subscriptions/{id}/test domainPermissionSubscriptionTest +// +// Test one domain permission subscription by making your instance fetch and parse it *without creating permissions*. +// +// The response body will be a list of domain permissions that *would* be created by this subscription, OR an error message. +// +// This is useful in cases where you want to check that your instance can actually fetch + parse a list. +// +// --- +// tags: +// - admin +// +// produces: +// - application/json +// +// parameters: +// - +// name: id +// required: true +// in: path +// description: ID of the domain permission draft. +// type: string +// +// security: +// - OAuth2 Bearer: +// - admin +// +// responses: +// '200': +// description: >- +// Either an array of domain permissions, OR an error message of the form +// `{"error":"[ERROR MESSAGE HERE]"}` indicating why the list could not be fetched. +// schema: +// type: array +// items: +// "$ref": "#/definitions/domain" +// '400': +// description: bad request +// '401': +// description: unauthorized +// '403': +// description: forbidden +// '406': +// description: not acceptable +// '409': +// description: conflict +// '500': +// description: internal server error +func (m *Module) DomainPermissionSubscriptionTestPOSTHandler(c *gin.Context) { + authed, err := oauth.Authed(c, true, true, true, true) + if err != nil { + apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGetV1) + return + } + + if !*authed.User.Admin { + err := fmt.Errorf("user %s not an admin", authed.User.ID) + apiutil.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGetV1) + return + } + + if authed.Account.IsMoving() { + apiutil.ForbiddenAfterMove(c) + return + } + + if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil { + apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1) + return + } + + id, errWithCode := apiutil.ParseID(c.Param(apiutil.IDKey)) + if errWithCode != nil { + apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) + return + } + + resp, errWithCode := m.processor.Admin().DomainPermissionSubscriptionTest( + c.Request.Context(), + authed.Account, + id, + ) + if errWithCode != nil { + apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) + return + } + + apiutil.JSON(c, http.StatusOK, resp) +} diff --git a/internal/api/client/admin/domainpermissionsubscruptiontest_test.go b/internal/api/client/admin/domainpermissionsubscruptiontest_test.go new file mode 100644 index 000000000..46861aba1 --- /dev/null +++ b/internal/api/client/admin/domainpermissionsubscruptiontest_test.go @@ -0,0 +1,125 @@ +// GoToSocial +// Copyright (C) GoToSocial Authors admin@gotosocial.org +// SPDX-License-Identifier: AGPL-3.0-or-later +// +// 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 admin_test + +import ( + "bytes" + "context" + "encoding/json" + "io" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/api/client/admin" + apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util" + "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/internal/util" +) + +type DomainPermissionSubscriptionTestTestSuite struct { + AdminStandardTestSuite +} + +func (suite *DomainPermissionSubscriptionTestTestSuite) TestDomainPermissionSubscriptionTest() { + var ( + ctx = context.Background() + testAccount = suite.testAccounts["admin_account"] + permSub = >smodel.DomainPermissionSubscription{ + ID: "01JGE681TQSBPAV59GZXPKE62H", + Priority: 255, + Title: "whatever!", + PermissionType: gtsmodel.DomainPermissionBlock, + AsDraft: util.Ptr(false), + AdoptOrphans: util.Ptr(true), + CreatedByAccountID: testAccount.ID, + CreatedByAccount: testAccount, + URI: "https://lists.example.org/baddies.csv", + ContentType: gtsmodel.DomainPermSubContentTypeCSV, + } + ) + + // Create a subscription for a CSV list of baddies. + err := suite.state.DB.PutDomainPermissionSubscription(ctx, permSub) + if err != nil { + suite.FailNow(err.Error()) + } + + // Prepare the request to the /test endpoint. + subPath := strings.ReplaceAll( + admin.DomainPermissionSubscriptionTestPath, + ":id", permSub.ID, + ) + path := "/api" + subPath + recorder := httptest.NewRecorder() + ginCtx := suite.newContext(recorder, http.MethodPost, nil, path, "application/json") + ginCtx.Params = gin.Params{ + gin.Param{ + Key: apiutil.IDKey, + Value: permSub.ID, + }, + } + + // Trigger the handler. + suite.adminModule.DomainPermissionSubscriptionTestPOSTHandler(ginCtx) + suite.Equal(http.StatusOK, recorder.Code) + + // Read the body back. + b, err := io.ReadAll(recorder.Body) + if err != nil { + suite.FailNow(err.Error()) + } + + dst := new(bytes.Buffer) + if err := json.Indent(dst, b, "", " "); err != nil { + suite.FailNow(err.Error()) + } + + // Ensure expected. + suite.Equal(`[ + { + "domain": "bumfaces.net", + "public_comment": "big jerks" + }, + { + "domain": "peepee.poopoo", + "public_comment": "harassment" + }, + { + "domain": "nothanks.com" + } +]`, dst.String()) + + // No permissions should be created + // since this is a dry run / test. + blocked, err := suite.state.DB.AreDomainsBlocked( + ctx, + []string{"bumfaces.net", "peepee.poopoo", "nothanks.com"}, + ) + if err != nil { + suite.FailNow(err.Error()) + } + suite.False(blocked) +} + +func TestDomainPermissionSubscriptionTestTestSuite(t *testing.T) { + suite.Run(t, &DomainPermissionSubscriptionTestTestSuite{}) +} diff --git a/internal/api/client/bookmarks/bookmarks_test.go b/internal/api/client/bookmarks/bookmarks_test.go index cb796e9e8..43c1eeee4 100644 --- a/internal/api/client/bookmarks/bookmarks_test.go +++ b/internal/api/client/bookmarks/bookmarks_test.go @@ -28,6 +28,7 @@ import ( "testing" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/bookmarks" "github.com/superseriousbusiness/gotosocial/internal/api/client/statuses" apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" @@ -95,6 +96,7 @@ func (suite *BookmarkTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/favourites/favourites_test.go b/internal/api/client/favourites/favourites_test.go index bd0ebce2e..dcdc8fee2 100644 --- a/internal/api/client/favourites/favourites_test.go +++ b/internal/api/client/favourites/favourites_test.go @@ -19,6 +19,7 @@ package favourites_test import ( "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/favourites" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -79,6 +80,7 @@ func (suite *FavouritesStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/filters/v1/filter_test.go b/internal/api/client/filters/v1/filter_test.go index 7553008d3..128426435 100644 --- a/internal/api/client/filters/v1/filter_test.go +++ b/internal/api/client/filters/v1/filter_test.go @@ -23,6 +23,7 @@ import ( "time" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" filtersV1 "github.com/superseriousbusiness/gotosocial/internal/api/client/filters/v1" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" @@ -90,6 +91,7 @@ func (suite *FiltersTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/filters/v2/filter_test.go b/internal/api/client/filters/v2/filter_test.go index 8249546fb..20411c090 100644 --- a/internal/api/client/filters/v2/filter_test.go +++ b/internal/api/client/filters/v2/filter_test.go @@ -23,6 +23,7 @@ import ( "time" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" filtersV2 "github.com/superseriousbusiness/gotosocial/internal/api/client/filters/v2" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" @@ -90,6 +91,7 @@ func (suite *FiltersTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/followedtags/followedtags_test.go b/internal/api/client/followedtags/followedtags_test.go index 883ab033b..89a61aca1 100644 --- a/internal/api/client/followedtags/followedtags_test.go +++ b/internal/api/client/followedtags/followedtags_test.go @@ -21,6 +21,7 @@ import ( "testing" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/followedtags" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" @@ -79,6 +80,7 @@ func (suite *FollowedTagsTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/followrequests/followrequest_test.go b/internal/api/client/followrequests/followrequest_test.go index fc9843b4a..1faac2bbc 100644 --- a/internal/api/client/followrequests/followrequest_test.go +++ b/internal/api/client/followrequests/followrequest_test.go @@ -24,6 +24,7 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/followrequests" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" @@ -82,6 +83,7 @@ func (suite *FollowRequestStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/instance/instance_test.go b/internal/api/client/instance/instance_test.go index 8bfe444e5..293c96020 100644 --- a/internal/api/client/instance/instance_test.go +++ b/internal/api/client/instance/instance_test.go @@ -24,6 +24,7 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/instance" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" @@ -84,6 +85,7 @@ func (suite *InstanceStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/lists/lists_test.go b/internal/api/client/lists/lists_test.go index 844d54cbb..ea5adbb5c 100644 --- a/internal/api/client/lists/lists_test.go +++ b/internal/api/client/lists/lists_test.go @@ -19,6 +19,7 @@ package lists_test import ( "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/lists" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -85,6 +86,7 @@ func (suite *ListsStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/mutes/mutes_test.go b/internal/api/client/mutes/mutes_test.go index 5d450e32c..b721b080f 100644 --- a/internal/api/client/mutes/mutes_test.go +++ b/internal/api/client/mutes/mutes_test.go @@ -25,6 +25,7 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/mutes" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" @@ -81,6 +82,7 @@ func (suite *MutesTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/notifications/notifications_test.go b/internal/api/client/notifications/notifications_test.go index 23af65cb4..39fb66691 100644 --- a/internal/api/client/notifications/notifications_test.go +++ b/internal/api/client/notifications/notifications_test.go @@ -19,6 +19,7 @@ package notifications_test import ( "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/notifications" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -81,6 +82,7 @@ func (suite *NotificationsTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/polls/polls_test.go b/internal/api/client/polls/polls_test.go index 5a3c83580..b5552f39e 100644 --- a/internal/api/client/polls/polls_test.go +++ b/internal/api/client/polls/polls_test.go @@ -19,6 +19,7 @@ package polls_test import ( "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/polls" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -76,6 +77,7 @@ func (suite *PollsStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/reports/reports_test.go b/internal/api/client/reports/reports_test.go index b36017d69..031fd953a 100644 --- a/internal/api/client/reports/reports_test.go +++ b/internal/api/client/reports/reports_test.go @@ -19,6 +19,7 @@ package reports_test import ( "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/reports" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -76,6 +77,7 @@ func (suite *ReportsStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/search/search_test.go b/internal/api/client/search/search_test.go index 5ba198062..fecb30d38 100644 --- a/internal/api/client/search/search_test.go +++ b/internal/api/client/search/search_test.go @@ -24,6 +24,7 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/search" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" @@ -80,6 +81,7 @@ func (suite *SearchStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/statuses/status_test.go b/internal/api/client/statuses/status_test.go index 1a92276a1..5a4473344 100644 --- a/internal/api/client/statuses/status_test.go +++ b/internal/api/client/statuses/status_test.go @@ -25,6 +25,7 @@ import ( "strings" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/statuses" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -192,6 +193,7 @@ func (suite *StatusStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/streaming/streaming_test.go b/internal/api/client/streaming/streaming_test.go index acdcafd8a..03cd6f434 100644 --- a/internal/api/client/streaming/streaming_test.go +++ b/internal/api/client/streaming/streaming_test.go @@ -31,6 +31,7 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/streaming" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -92,6 +93,7 @@ func (suite *StreamingTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/tags/tags_test.go b/internal/api/client/tags/tags_test.go index 79c708b10..71a84435a 100644 --- a/internal/api/client/tags/tags_test.go +++ b/internal/api/client/tags/tags_test.go @@ -26,6 +26,7 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/tags" apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" "github.com/superseriousbusiness/gotosocial/internal/config" @@ -87,6 +88,7 @@ func (suite *TagsTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/client/user/user_test.go b/internal/api/client/user/user_test.go index 808daf1a3..320c743f8 100644 --- a/internal/api/client/user/user_test.go +++ b/internal/api/client/user/user_test.go @@ -24,6 +24,7 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/client/user" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/federation" @@ -72,6 +73,7 @@ func (suite *UserStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/api/fileserver/fileserver_test.go b/internal/api/fileserver/fileserver_test.go index e5f684d0c..af6f125dc 100644 --- a/internal/api/fileserver/fileserver_test.go +++ b/internal/api/fileserver/fileserver_test.go @@ -19,6 +19,7 @@ package fileserver_test import ( "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/fileserver" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -98,6 +99,7 @@ func (suite *FileserverTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) testrig.StandardDBSetup(suite.db, nil) testrig.StandardStorageSetup(suite.storage, "../../../testrig/media") diff --git a/internal/api/wellknown/webfinger/webfinger_test.go b/internal/api/wellknown/webfinger/webfinger_test.go index 67ac5a64e..76c1fb5bb 100644 --- a/internal/api/wellknown/webfinger/webfinger_test.go +++ b/internal/api/wellknown/webfinger/webfinger_test.go @@ -19,6 +19,7 @@ package webfinger_test import ( "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/api/wellknown/webfinger" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -79,6 +80,7 @@ func (suite *WebfingerStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.tc = typeutils.NewConverter(&suite.state) testrig.StartTimelines( diff --git a/internal/api/wellknown/webfinger/webfingerget_test.go b/internal/api/wellknown/webfinger/webfingerget_test.go index ce9bc0ccf..b3aec57fe 100644 --- a/internal/api/wellknown/webfinger/webfingerget_test.go +++ b/internal/api/wellknown/webfinger/webfingerget_test.go @@ -39,6 +39,7 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/filter/visibility" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/processing" + "github.com/superseriousbusiness/gotosocial/internal/subscriptions" "github.com/superseriousbusiness/gotosocial/testrig" ) @@ -90,6 +91,7 @@ func (suite *WebfingerGetTestSuite) funkifyAccountDomain(host string, accountDom suite.processor = processing.NewProcessor( cleaner.New(&suite.state), + subscriptions.New(&suite.state, suite.federator.TransportController(), suite.tc), suite.tc, suite.federator, testrig.NewTestOauthServer(suite.db), diff --git a/internal/cleaner/media_test.go b/internal/cleaner/media_test.go index 6e653c07c..afa015783 100644 --- a/internal/cleaner/media_test.go +++ b/internal/cleaner/media_test.go @@ -26,6 +26,7 @@ import ( "time" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/cleaner" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/filter/visibility" @@ -67,6 +68,7 @@ func (suite *MediaTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.storage = testrig.NewInMemoryStorage() suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.state.Storage = suite.storage testrig.StandardStorageSetup(suite.storage, "../../testrig/media") diff --git a/internal/config/config.go b/internal/config/config.go index 2bf2a77ad..72154b3f2 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -78,15 +78,17 @@ type Configuration struct { WebTemplateBaseDir string `name:"web-template-base-dir" usage:"Basedir for html templating files for rendering pages and composing emails."` WebAssetBaseDir string `name:"web-asset-base-dir" usage:"Directory to serve static assets from, accessible at example.org/assets/"` - InstanceFederationMode string `name:"instance-federation-mode" usage:"Set instance federation mode."` - InstanceFederationSpamFilter bool `name:"instance-federation-spam-filter" usage:"Enable basic spam filter heuristics for messages coming from other instances, and drop messages identified as spam"` - InstanceExposePeers bool `name:"instance-expose-peers" usage:"Allow unauthenticated users to query /api/v1/instance/peers?filter=open"` - InstanceExposeSuspended bool `name:"instance-expose-suspended" usage:"Expose suspended instances via web UI, and allow unauthenticated users to query /api/v1/instance/peers?filter=suspended"` - InstanceExposeSuspendedWeb bool `name:"instance-expose-suspended-web" usage:"Expose list of suspended instances as webpage on /about/suspended"` - InstanceExposePublicTimeline bool `name:"instance-expose-public-timeline" usage:"Allow unauthenticated users to query /api/v1/timelines/public"` - InstanceDeliverToSharedInboxes bool `name:"instance-deliver-to-shared-inboxes" usage:"Deliver federated messages to shared inboxes, if they're available."` - InstanceInjectMastodonVersion bool `name:"instance-inject-mastodon-version" usage:"This injects a Mastodon compatible version in /api/v1/instance to help Mastodon clients that use that version for feature detection"` - InstanceLanguages language.Languages `name:"instance-languages" usage:"BCP47 language tags for the instance. Used to indicate the preferred languages of instance residents (in order from most-preferred to least-preferred)."` + InstanceFederationMode string `name:"instance-federation-mode" usage:"Set instance federation mode."` + InstanceFederationSpamFilter bool `name:"instance-federation-spam-filter" usage:"Enable basic spam filter heuristics for messages coming from other instances, and drop messages identified as spam"` + InstanceExposePeers bool `name:"instance-expose-peers" usage:"Allow unauthenticated users to query /api/v1/instance/peers?filter=open"` + InstanceExposeSuspended bool `name:"instance-expose-suspended" usage:"Expose suspended instances via web UI, and allow unauthenticated users to query /api/v1/instance/peers?filter=suspended"` + InstanceExposeSuspendedWeb bool `name:"instance-expose-suspended-web" usage:"Expose list of suspended instances as webpage on /about/suspended"` + InstanceExposePublicTimeline bool `name:"instance-expose-public-timeline" usage:"Allow unauthenticated users to query /api/v1/timelines/public"` + InstanceDeliverToSharedInboxes bool `name:"instance-deliver-to-shared-inboxes" usage:"Deliver federated messages to shared inboxes, if they're available."` + InstanceInjectMastodonVersion bool `name:"instance-inject-mastodon-version" usage:"This injects a Mastodon compatible version in /api/v1/instance to help Mastodon clients that use that version for feature detection"` + InstanceLanguages language.Languages `name:"instance-languages" usage:"BCP47 language tags for the instance. Used to indicate the preferred languages of instance residents (in order from most-preferred to least-preferred)."` + InstanceSubscriptionsProcessFrom string `name:"instance-subscriptions-process-from" usage:"Time of day from which to start running instance subscriptions processing jobs. Should be in the format 'hh:mm:ss', eg., '15:04:05'."` + InstanceSubscriptionsProcessEvery time.Duration `name:"instance-subscriptions-process-every" usage:"Period to elapse between instance subscriptions processing jobs, starting from instance-subscriptions-process-from."` AccountsRegistrationOpen bool `name:"accounts-registration-open" usage:"Allow anyone to submit an account signup request. If false, server will be invite-only."` AccountsReasonRequired bool `name:"accounts-reason-required" usage:"Do new account signups require a reason to be submitted on registration?"` diff --git a/internal/config/defaults.go b/internal/config/defaults.go index 97d96d1ba..8c2ae90de 100644 --- a/internal/config/defaults.go +++ b/internal/config/defaults.go @@ -58,13 +58,15 @@ var Defaults = Configuration{ WebTemplateBaseDir: "./web/template/", WebAssetBaseDir: "./web/assets/", - InstanceFederationMode: InstanceFederationModeDefault, - InstanceFederationSpamFilter: false, - InstanceExposePeers: false, - InstanceExposeSuspended: false, - InstanceExposeSuspendedWeb: false, - InstanceDeliverToSharedInboxes: true, - InstanceLanguages: make(language.Languages, 0), + InstanceFederationMode: InstanceFederationModeDefault, + InstanceFederationSpamFilter: false, + InstanceExposePeers: false, + InstanceExposeSuspended: false, + InstanceExposeSuspendedWeb: false, + InstanceDeliverToSharedInboxes: true, + InstanceLanguages: make(language.Languages, 0), + InstanceSubscriptionsProcessFrom: "23:00", // 11pm, + InstanceSubscriptionsProcessEvery: 24 * time.Hour, // 1/day. AccountsRegistrationOpen: false, AccountsReasonRequired: true, diff --git a/internal/config/flags.go b/internal/config/flags.go index f96709e70..6f0957c36 100644 --- a/internal/config/flags.go +++ b/internal/config/flags.go @@ -90,6 +90,8 @@ func (s *ConfigState) AddServerFlags(cmd *cobra.Command) { cmd.Flags().Bool(InstanceExposeSuspendedWebFlag(), cfg.InstanceExposeSuspendedWeb, fieldtag("InstanceExposeSuspendedWeb", "usage")) cmd.Flags().Bool(InstanceDeliverToSharedInboxesFlag(), cfg.InstanceDeliverToSharedInboxes, fieldtag("InstanceDeliverToSharedInboxes", "usage")) cmd.Flags().StringSlice(InstanceLanguagesFlag(), cfg.InstanceLanguages.TagStrs(), fieldtag("InstanceLanguages", "usage")) + cmd.Flags().String(InstanceSubscriptionsProcessFromFlag(), cfg.InstanceSubscriptionsProcessFrom, fieldtag("InstanceSubscriptionsProcessFrom", "usage")) + cmd.Flags().Duration(InstanceSubscriptionsProcessEveryFlag(), cfg.InstanceSubscriptionsProcessEvery, fieldtag("InstanceSubscriptionsProcessEvery", "usage")) // Accounts cmd.Flags().Bool(AccountsRegistrationOpenFlag(), cfg.AccountsRegistrationOpen, fieldtag("AccountsRegistrationOpen", "usage")) diff --git a/internal/config/helpers.gen.go b/internal/config/helpers.gen.go index 625c4ea78..e1c41638c 100644 --- a/internal/config/helpers.gen.go +++ b/internal/config/helpers.gen.go @@ -1000,6 +1000,62 @@ func GetInstanceLanguages() language.Languages { return global.GetInstanceLangua // SetInstanceLanguages safely sets the value for global configuration 'InstanceLanguages' field func SetInstanceLanguages(v language.Languages) { global.SetInstanceLanguages(v) } +// GetInstanceSubscriptionsProcessFrom safely fetches the Configuration value for state's 'InstanceSubscriptionsProcessFrom' field +func (st *ConfigState) GetInstanceSubscriptionsProcessFrom() (v string) { + st.mutex.RLock() + v = st.config.InstanceSubscriptionsProcessFrom + st.mutex.RUnlock() + return +} + +// SetInstanceSubscriptionsProcessFrom safely sets the Configuration value for state's 'InstanceSubscriptionsProcessFrom' field +func (st *ConfigState) SetInstanceSubscriptionsProcessFrom(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.InstanceSubscriptionsProcessFrom = v + st.reloadToViper() +} + +// InstanceSubscriptionsProcessFromFlag returns the flag name for the 'InstanceSubscriptionsProcessFrom' field +func InstanceSubscriptionsProcessFromFlag() string { return "instance-subscriptions-process-from" } + +// GetInstanceSubscriptionsProcessFrom safely fetches the value for global configuration 'InstanceSubscriptionsProcessFrom' field +func GetInstanceSubscriptionsProcessFrom() string { + return global.GetInstanceSubscriptionsProcessFrom() +} + +// SetInstanceSubscriptionsProcessFrom safely sets the value for global configuration 'InstanceSubscriptionsProcessFrom' field +func SetInstanceSubscriptionsProcessFrom(v string) { global.SetInstanceSubscriptionsProcessFrom(v) } + +// GetInstanceSubscriptionsProcessEvery safely fetches the Configuration value for state's 'InstanceSubscriptionsProcessEvery' field +func (st *ConfigState) GetInstanceSubscriptionsProcessEvery() (v time.Duration) { + st.mutex.RLock() + v = st.config.InstanceSubscriptionsProcessEvery + st.mutex.RUnlock() + return +} + +// SetInstanceSubscriptionsProcessEvery safely sets the Configuration value for state's 'InstanceSubscriptionsProcessEvery' field +func (st *ConfigState) SetInstanceSubscriptionsProcessEvery(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.InstanceSubscriptionsProcessEvery = v + st.reloadToViper() +} + +// InstanceSubscriptionsProcessEveryFlag returns the flag name for the 'InstanceSubscriptionsProcessEvery' field +func InstanceSubscriptionsProcessEveryFlag() string { return "instance-subscriptions-process-every" } + +// GetInstanceSubscriptionsProcessEvery safely fetches the value for global configuration 'InstanceSubscriptionsProcessEvery' field +func GetInstanceSubscriptionsProcessEvery() time.Duration { + return global.GetInstanceSubscriptionsProcessEvery() +} + +// SetInstanceSubscriptionsProcessEvery safely sets the value for global configuration 'InstanceSubscriptionsProcessEvery' field +func SetInstanceSubscriptionsProcessEvery(v time.Duration) { + global.SetInstanceSubscriptionsProcessEvery(v) +} + // GetAccountsRegistrationOpen safely fetches the Configuration value for state's 'AccountsRegistrationOpen' field func (st *ConfigState) GetAccountsRegistrationOpen() (v bool) { st.mutex.RLock() diff --git a/internal/federation/dereferencing/dereferencer_test.go b/internal/federation/dereferencing/dereferencer_test.go index f00e876ae..9878a1b50 100644 --- a/internal/federation/dereferencing/dereferencer_test.go +++ b/internal/federation/dereferencing/dereferencer_test.go @@ -20,6 +20,7 @@ package dereferencing_test import ( "github.com/stretchr/testify/suite" "github.com/superseriousbusiness/activity/streams/vocab" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/federation/dereferencing" "github.com/superseriousbusiness/gotosocial/internal/filter/interaction" @@ -77,6 +78,7 @@ func (suite *DereferencerStandardTestSuite) SetupTest() { suite.client = testrig.NewMockHTTPClient(nil, "../../../testrig/media") suite.storage = testrig.NewInMemoryStorage() suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.state.Storage = suite.storage visFilter := visibility.NewFilter(&suite.state) diff --git a/internal/federation/federatingdb/federatingdb_test.go b/internal/federation/federatingdb/federatingdb_test.go index 360094887..2f07914ae 100644 --- a/internal/federation/federatingdb/federatingdb_test.go +++ b/internal/federation/federatingdb/federatingdb_test.go @@ -22,6 +22,7 @@ import ( "time" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/federation/federatingdb" "github.com/superseriousbusiness/gotosocial/internal/filter/visibility" @@ -91,6 +92,7 @@ func (suite *FederatingDBTestSuite) SetupTest() { testrig.StandardDBSetup(suite.db, suite.testAccounts) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) } func (suite *FederatingDBTestSuite) TearDownTest() { diff --git a/internal/media/media_test.go b/internal/media/media_test.go index 0980bf295..f46f837da 100644 --- a/internal/media/media_test.go +++ b/internal/media/media_test.go @@ -19,6 +19,7 @@ package media_test import ( "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/filter/visibility" gtsmodel "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" @@ -53,6 +54,7 @@ func (suite *MediaStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.storage = testrig.NewInMemoryStorage() suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.state.Storage = suite.storage testrig.StandardStorageSetup(suite.storage, "../../testrig/media") diff --git a/internal/oauth/clientstore_test.go b/internal/oauth/clientstore_test.go index fc3dabc3a..0ced34de6 100644 --- a/internal/oauth/clientstore_test.go +++ b/internal/oauth/clientstore_test.go @@ -22,6 +22,7 @@ import ( "testing" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/oauth" "github.com/superseriousbusiness/gotosocial/internal/state" @@ -54,6 +55,7 @@ func (suite *PgClientStoreTestSuite) SetupTest() { testrig.InitTestConfig() suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) testrig.StandardDBSetup(suite.db, nil) } diff --git a/internal/processing/account/account_test.go b/internal/processing/account/account_test.go index 8eec1f9dd..7bd9658dc 100644 --- a/internal/processing/account/account_test.go +++ b/internal/processing/account/account_test.go @@ -22,6 +22,7 @@ import ( "time" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" "github.com/superseriousbusiness/gotosocial/internal/federation" @@ -93,6 +94,7 @@ func (suite *AccountStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.tc = typeutils.NewConverter(&suite.state) testrig.StartTimelines( diff --git a/internal/processing/admin/account_test.go b/internal/processing/admin/account_test.go index 59b8afc77..baa6eb646 100644 --- a/internal/processing/admin/account_test.go +++ b/internal/processing/admin/account_test.go @@ -53,7 +53,7 @@ func (suite *AccountTestSuite) TestAccountActionSuspend() { // Wait for action to finish. if !testrig.WaitFor(func() bool { - return suite.adminProcessor.Actions().TotalRunning() == 0 + return suite.state.AdminActions.TotalRunning() == 0 }) { suite.FailNow("timed out waiting for admin action(s) to finish") } diff --git a/internal/processing/admin/accountaction.go b/internal/processing/admin/accountaction.go index 59d4b420e..959f2cfcd 100644 --- a/internal/processing/admin/accountaction.go +++ b/internal/processing/admin/accountaction.go @@ -68,7 +68,7 @@ func (p *Processor) accountActionSuspend( ) (string, gtserror.WithCode) { actionID := id.NewULID() - errWithCode := p.actions.Run( + errWithCode := p.state.AdminActions.Run( ctx, >smodel.AdminAction{ ID: actionID, diff --git a/internal/processing/admin/admin.go b/internal/processing/admin/admin.go index 170298ca5..08e6bf0d5 100644 --- a/internal/processing/admin/admin.go +++ b/internal/processing/admin/admin.go @@ -21,10 +21,10 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/cleaner" "github.com/superseriousbusiness/gotosocial/internal/email" "github.com/superseriousbusiness/gotosocial/internal/federation" - "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/media" "github.com/superseriousbusiness/gotosocial/internal/processing/common" "github.com/superseriousbusiness/gotosocial/internal/state" + "github.com/superseriousbusiness/gotosocial/internal/subscriptions" "github.com/superseriousbusiness/gotosocial/internal/transport" "github.com/superseriousbusiness/gotosocial/internal/typeutils" ) @@ -33,21 +33,14 @@ type Processor struct { // common processor logic c *common.Processor - state *state.State - cleaner *cleaner.Cleaner - converter *typeutils.Converter - federator *federation.Federator - media *media.Manager - transport transport.Controller - email email.Sender - - // admin Actions currently - // undergoing processing - actions *Actions -} - -func (p *Processor) Actions() *Actions { - return p.actions + state *state.State + cleaner *cleaner.Cleaner + subscriptions *subscriptions.Subscriptions + converter *typeutils.Converter + federator *federation.Federator + media *media.Manager + transport transport.Controller + email email.Sender } // New returns a new admin processor. @@ -55,6 +48,7 @@ func New( common *common.Processor, state *state.State, cleaner *cleaner.Cleaner, + subscriptions *subscriptions.Subscriptions, federator *federation.Federator, converter *typeutils.Converter, mediaManager *media.Manager, @@ -62,17 +56,14 @@ func New( emailSender email.Sender, ) Processor { return Processor{ - c: common, - state: state, - cleaner: cleaner, - converter: converter, - federator: federator, - media: mediaManager, - transport: transportController, - email: emailSender, - actions: &Actions{ - r: make(map[string]*gtsmodel.AdminAction), - state: state, - }, + c: common, + state: state, + cleaner: cleaner, + subscriptions: subscriptions, + converter: converter, + federator: federator, + media: mediaManager, + transport: transportController, + email: emailSender, } } diff --git a/internal/processing/admin/admin_test.go b/internal/processing/admin/admin_test.go index 3251264b6..f0839f2f6 100644 --- a/internal/processing/admin/admin_test.go +++ b/internal/processing/admin/admin_test.go @@ -19,6 +19,7 @@ package admin_test import ( "github.com/stretchr/testify/suite" + adminactions "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/cleaner" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -33,6 +34,7 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/processing/admin" "github.com/superseriousbusiness/gotosocial/internal/state" "github.com/superseriousbusiness/gotosocial/internal/storage" + "github.com/superseriousbusiness/gotosocial/internal/subscriptions" "github.com/superseriousbusiness/gotosocial/internal/transport" "github.com/superseriousbusiness/gotosocial/internal/typeutils" "github.com/superseriousbusiness/gotosocial/testrig" @@ -89,6 +91,7 @@ func (suite *AdminStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = adminactions.New(suite.state.DB, &suite.state.Workers) suite.tc = typeutils.NewConverter(&suite.state) testrig.StartTimelines( @@ -109,6 +112,7 @@ func (suite *AdminStandardTestSuite) SetupTest() { suite.processor = processing.NewProcessor( cleaner.New(&suite.state), + subscriptions.New(&suite.state, suite.transportController, suite.tc), suite.tc, suite.federator, suite.oauthServer, diff --git a/internal/processing/admin/domainallow.go b/internal/processing/admin/domainallow.go index bab54e308..13f0307f2 100644 --- a/internal/processing/admin/domainallow.go +++ b/internal/processing/admin/domainallow.go @@ -22,14 +22,11 @@ import ( "errors" "fmt" - "codeberg.org/gruf/go-kv" apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" - "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/id" - "github.com/superseriousbusiness/gotosocial/internal/log" "github.com/superseriousbusiness/gotosocial/internal/text" ) @@ -69,84 +66,30 @@ func (p *Processor) createDomainAllow( } } - actionID := id.NewULID() + // Run admin action to process + // side effects of allow. + action := >smodel.AdminAction{ + ID: id.NewULID(), + TargetCategory: gtsmodel.AdminActionCategoryDomain, + TargetID: domainAllow.Domain, + Type: gtsmodel.AdminActionUnsuspend, + AccountID: adminAcct.ID, + } - // Process domain allow side - // effects asynchronously. - if errWithCode := p.actions.Run( + if errWithCode := p.state.AdminActions.Run( ctx, - >smodel.AdminAction{ - ID: actionID, - TargetCategory: gtsmodel.AdminActionCategoryDomain, - TargetID: domain, - Type: gtsmodel.AdminActionSuspend, - AccountID: adminAcct.ID, - Text: domainAllow.PrivateComment, - }, - func(ctx context.Context) gtserror.MultiError { - // Log start + finish. - l := log.WithFields(kv.Fields{ - {"domain", domain}, - {"actionID", actionID}, - }...).WithContext(ctx) - - l.Info("processing domain allow side effects") - defer func() { l.Info("finished processing domain allow side effects") }() - - return p.domainAllowSideEffects(ctx, domainAllow) - }, + action, + p.state.AdminActions.DomainAllowF(action.ID, domainAllow), ); errWithCode != nil { - return nil, actionID, errWithCode + return nil, action.ID, errWithCode } apiDomainAllow, errWithCode := p.apiDomainPerm(ctx, domainAllow, false) if errWithCode != nil { - return nil, actionID, errWithCode + return nil, action.ID, errWithCode } - return apiDomainAllow, actionID, nil -} - -func (p *Processor) domainAllowSideEffects( - ctx context.Context, - allow *gtsmodel.DomainAllow, -) gtserror.MultiError { - if config.GetInstanceFederationMode() == config.InstanceFederationModeAllowlist { - // We're running in allowlist mode, - // so there are no side effects to - // process here. - return nil - } - - // We're running in blocklist mode or - // some similar mode which necessitates - // domain allow side effects if a block - // was in place when the allow was created. - // - // So, check if there's a block. - block, err := p.state.DB.GetDomainBlock(ctx, allow.Domain) - if err != nil && !errors.Is(err, db.ErrNoEntries) { - errs := gtserror.NewMultiError(1) - errs.Appendf("db error getting domain block %s: %w", allow.Domain, err) - return errs - } - - if block == nil { - // No block? - // No problem! - return nil - } - - // There was a block, over which the new - // allow ought to take precedence. To account - // for this, just run side effects as though - // the domain was being unblocked, while - // leaving the existing block in place. - // - // Any accounts that were suspended by - // the block will be unsuspended and be - // able to interact with the instance again. - return p.domainUnblockSideEffects(ctx, block) + return apiDomainAllow, action.ID, nil } func (p *Processor) deleteDomainAllow( @@ -179,77 +122,23 @@ func (p *Processor) deleteDomainAllow( return nil, "", gtserror.NewErrorInternalError(err) } - actionID := id.NewULID() + // Run admin action to process + // side effects of unallow. + action := >smodel.AdminAction{ + ID: id.NewULID(), + TargetCategory: gtsmodel.AdminActionCategoryDomain, + TargetID: domainAllow.Domain, + Type: gtsmodel.AdminActionUnsuspend, + AccountID: adminAcct.ID, + } - // Process domain unallow side - // effects asynchronously. - if errWithCode := p.actions.Run( + if errWithCode := p.state.AdminActions.Run( ctx, - >smodel.AdminAction{ - ID: actionID, - TargetCategory: gtsmodel.AdminActionCategoryDomain, - TargetID: domainAllow.Domain, - Type: gtsmodel.AdminActionUnsuspend, - AccountID: adminAcct.ID, - }, - func(ctx context.Context) gtserror.MultiError { - // Log start + finish. - l := log.WithFields(kv.Fields{ - {"domain", domainAllow.Domain}, - {"actionID", actionID}, - }...).WithContext(ctx) - - l.Info("processing domain unallow side effects") - defer func() { l.Info("finished processing domain unallow side effects") }() - - return p.domainUnallowSideEffects(ctx, domainAllow) - }, + action, + p.state.AdminActions.DomainUnallowF(action.ID, domainAllow), ); errWithCode != nil { - return nil, actionID, errWithCode + return nil, action.ID, errWithCode } - return apiDomainAllow, actionID, nil -} - -func (p *Processor) domainUnallowSideEffects( - ctx context.Context, - allow *gtsmodel.DomainAllow, -) gtserror.MultiError { - if config.GetInstanceFederationMode() == config.InstanceFederationModeAllowlist { - // We're running in allowlist mode, - // so there are no side effects to - // process here. - return nil - } - - // We're running in blocklist mode or - // some similar mode which necessitates - // domain allow side effects if a block - // was in place when the allow was removed. - // - // So, check if there's a block. - block, err := p.state.DB.GetDomainBlock(ctx, allow.Domain) - if err != nil && !errors.Is(err, db.ErrNoEntries) { - errs := gtserror.NewMultiError(1) - errs.Appendf("db error getting domain block %s: %w", allow.Domain, err) - return errs - } - - if block == nil { - // No block? - // No problem! - return nil - } - - // There was a block, over which the previous - // allow was taking precedence. Now that the - // allow has been removed, we should put the - // side effects of the block back in place. - // - // To do this, process the block side effects - // again as though the block were freshly - // created. This will mark all accounts from - // the blocked domain as suspended, and clean - // up their follows/following, media, etc. - return p.domainBlockSideEffects(ctx, block) + return apiDomainAllow, action.ID, nil } diff --git a/internal/processing/admin/domainblock.go b/internal/processing/admin/domainblock.go index 2fe10c97b..f8c1a6708 100644 --- a/internal/processing/admin/domainblock.go +++ b/internal/processing/admin/domainblock.go @@ -21,18 +21,12 @@ import ( "context" "errors" "fmt" - "time" - "codeberg.org/gruf/go-kv" - "github.com/superseriousbusiness/gotosocial/internal/ap" apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" - "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/id" - "github.com/superseriousbusiness/gotosocial/internal/log" - "github.com/superseriousbusiness/gotosocial/internal/messages" "github.com/superseriousbusiness/gotosocial/internal/text" ) @@ -72,149 +66,31 @@ func (p *Processor) createDomainBlock( } } - actionID := id.NewULID() + // Run admin action to process + // side effects of block. + action := >smodel.AdminAction{ + ID: id.NewULID(), + TargetCategory: gtsmodel.AdminActionCategoryDomain, + TargetID: domain, + Type: gtsmodel.AdminActionSuspend, + AccountID: adminAcct.ID, + Text: domainBlock.PrivateComment, + } - // Process domain block side - // effects asynchronously. - if errWithCode := p.actions.Run( + if errWithCode := p.state.AdminActions.Run( ctx, - >smodel.AdminAction{ - ID: actionID, - TargetCategory: gtsmodel.AdminActionCategoryDomain, - TargetID: domain, - Type: gtsmodel.AdminActionSuspend, - AccountID: adminAcct.ID, - Text: domainBlock.PrivateComment, - }, - func(ctx context.Context) gtserror.MultiError { - // Log start + finish. - l := log.WithFields(kv.Fields{ - {"domain", domain}, - {"actionID", actionID}, - }...).WithContext(ctx) - - skip, err := p.skipBlockSideEffects(ctx, domain) - if err != nil { - return err - } - if skip != "" { - l.Infof("skipping domain block side effects: %s", skip) - return nil - } - - l.Info("processing domain block side effects") - defer func() { l.Info("finished processing domain block side effects") }() - - return p.domainBlockSideEffects(ctx, domainBlock) - }, + action, + p.state.AdminActions.DomainBlockF(action.ID, domainBlock), ); errWithCode != nil { - return nil, actionID, errWithCode + return nil, action.ID, errWithCode } apiDomainBlock, errWithCode := p.apiDomainPerm(ctx, domainBlock, false) if errWithCode != nil { - return nil, actionID, errWithCode + return nil, action.ID, errWithCode } - return apiDomainBlock, actionID, nil -} - -// skipBlockSideEffects checks if side effects of block creation -// should be skipped for the given domain, taking account of -// instance federation mode, and existence of any allows -// which ought to "shield" this domain from being blocked. -// -// If the caller should skip, the returned string will be non-zero -// and will be set to a reason why side effects should be skipped. -// -// - blocklist mode + allow exists: "..." (skip) -// - blocklist mode + no allow: "" (don't skip) -// - allowlist mode + allow exists: "" (don't skip) -// - allowlist mode + no allow: "" (don't skip) -func (p *Processor) skipBlockSideEffects( - ctx context.Context, - domain string, -) (string, gtserror.MultiError) { - var ( - skip string // Assume "" (don't skip). - errs gtserror.MultiError - ) - - // Never skip block side effects in allowlist mode. - fediMode := config.GetInstanceFederationMode() - if fediMode == config.InstanceFederationModeAllowlist { - return skip, errs - } - - // We know we're in blocklist mode. - // - // We want to skip domain block side - // effects if an allow is already - // in place which overrides the block. - - // Check if an explicit allow exists for this domain. - domainAllow, err := p.state.DB.GetDomainAllow(ctx, domain) - if err != nil && !errors.Is(err, db.ErrNoEntries) { - errs.Appendf("error getting domain allow: %w", err) - return skip, errs - } - - if domainAllow != nil { - skip = "running in blocklist mode, and an explicit allow exists for this domain" - return skip, errs - } - - return skip, errs -} - -// domainBlockSideEffects processes the side effects of a domain block: -// -// 1. Strip most info away from the instance entry for the domain. -// 2. Pass each account from the domain to the processor for deletion. -// -// It should be called asynchronously, since it can take a while when -// there are many accounts present on the given domain. -func (p *Processor) domainBlockSideEffects( - ctx context.Context, - block *gtsmodel.DomainBlock, -) gtserror.MultiError { - var errs gtserror.MultiError - - // If we have an instance entry for this domain, - // update it with the new block ID and clear all fields - instance, err := p.state.DB.GetInstance(ctx, block.Domain) - if err != nil && !errors.Is(err, db.ErrNoEntries) { - errs.Appendf("db error getting instance %s: %w", block.Domain, err) - return errs - } - - if instance != nil { - // We had an entry for this domain. - columns := stubbifyInstance(instance, block.ID) - if err := p.state.DB.UpdateInstance(ctx, instance, columns...); err != nil { - errs.Appendf("db error updating instance: %w", err) - return errs - } - } - - // For each account that belongs to this domain, - // process an account delete message to remove - // that account's posts, media, etc. - if err := p.rangeDomainAccounts(ctx, block.Domain, func(account *gtsmodel.Account) { - if err := p.state.Workers.Client.Process(ctx, &messages.FromClientAPI{ - APObjectType: ap.ActorPerson, - APActivityType: ap.ActivityDelete, - GTSModel: block, - Origin: account, - Target: account, - }); err != nil { - errs.Append(err) - } - }); err != nil { - errs.Appendf("db error ranging through accounts: %w", err) - } - - return errs + return apiDomainBlock, action.ID, nil } func (p *Processor) deleteDomainBlock( @@ -247,104 +123,23 @@ func (p *Processor) deleteDomainBlock( return nil, "", gtserror.NewErrorInternalError(err) } - actionID := id.NewULID() + // Run admin action to process + // side effects of unblock. + action := >smodel.AdminAction{ + ID: id.NewULID(), + TargetCategory: gtsmodel.AdminActionCategoryDomain, + TargetID: domainBlock.Domain, + Type: gtsmodel.AdminActionUnsuspend, + AccountID: adminAcct.ID, + } - // Process domain unblock side - // effects asynchronously. - if errWithCode := p.actions.Run( + if errWithCode := p.state.AdminActions.Run( ctx, - >smodel.AdminAction{ - ID: actionID, - TargetCategory: gtsmodel.AdminActionCategoryDomain, - TargetID: domainBlock.Domain, - Type: gtsmodel.AdminActionUnsuspend, - AccountID: adminAcct.ID, - }, - func(ctx context.Context) gtserror.MultiError { - // Log start + finish. - l := log.WithFields(kv.Fields{ - {"domain", domainBlock.Domain}, - {"actionID", actionID}, - }...).WithContext(ctx) - - l.Info("processing domain unblock side effects") - defer func() { l.Info("finished processing domain unblock side effects") }() - - return p.domainUnblockSideEffects(ctx, domainBlock) - }, + action, + p.state.AdminActions.DomainUnblockF(action.ID, domainBlock), ); errWithCode != nil { - return nil, actionID, errWithCode + return nil, action.ID, errWithCode } - return apiDomainBlock, actionID, nil -} - -// domainUnblockSideEffects processes the side effects of undoing a -// domain block: -// -// 1. Mark instance entry as no longer suspended. -// 2. Mark each account from the domain as no longer suspended, if the -// suspension origin corresponds to the ID of the provided domain block. -// -// It should be called asynchronously, since it can take a while when -// there are many accounts present on the given domain. -func (p *Processor) domainUnblockSideEffects( - ctx context.Context, - block *gtsmodel.DomainBlock, -) gtserror.MultiError { - var errs gtserror.MultiError - - // Update instance entry for this domain, if we have it. - instance, err := p.state.DB.GetInstance(ctx, block.Domain) - if err != nil && !errors.Is(err, db.ErrNoEntries) { - errs.Appendf("db error getting instance %s: %w", block.Domain, err) - } - - if instance != nil { - // We had an entry, update it to signal - // that it's no longer suspended. - instance.SuspendedAt = time.Time{} - instance.DomainBlockID = "" - if err := p.state.DB.UpdateInstance( - ctx, - instance, - "suspended_at", - "domain_block_id", - ); err != nil { - errs.Appendf("db error updating instance: %w", err) - return errs - } - } - - // Unsuspend all accounts whose suspension origin was this domain block. - if err := p.rangeDomainAccounts(ctx, block.Domain, func(account *gtsmodel.Account) { - if account.SuspensionOrigin == "" || account.SuspendedAt.IsZero() { - // Account wasn't suspended, nothing to do. - return - } - - if account.SuspensionOrigin != block.ID { - // Account was suspended, but not by - // this domain block, leave it alone. - return - } - - // Account was suspended by this domain - // block, mark it as unsuspended. - account.SuspendedAt = time.Time{} - account.SuspensionOrigin = "" - - if err := p.state.DB.UpdateAccount( - ctx, - account, - "suspended_at", - "suspension_origin", - ); err != nil { - errs.Appendf("db error updating account %s: %w", account.Username, err) - } - }); err != nil { - errs.Appendf("db error ranging through accounts: %w", err) - } - - return errs + return apiDomainBlock, action.ID, nil } diff --git a/internal/processing/admin/domainkeysexpire.go b/internal/processing/admin/domainkeysexpire.go index 9853becbd..0613f502d 100644 --- a/internal/processing/admin/domainkeysexpire.go +++ b/internal/processing/admin/domainkeysexpire.go @@ -19,7 +19,6 @@ package admin import ( "context" - "time" "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" @@ -39,47 +38,23 @@ func (p *Processor) DomainKeysExpire( adminAcct *gtsmodel.Account, domain string, ) (string, gtserror.WithCode) { - actionID := id.NewULID() + // Run admin action to process + // side effects of key expiry. + action := >smodel.AdminAction{ + ID: id.NewULID(), + TargetCategory: gtsmodel.AdminActionCategoryDomain, + TargetID: domain, + Type: gtsmodel.AdminActionExpireKeys, + AccountID: adminAcct.ID, + } - // Process key expiration asynchronously. - if errWithCode := p.actions.Run( + if errWithCode := p.state.AdminActions.Run( ctx, - >smodel.AdminAction{ - ID: actionID, - TargetCategory: gtsmodel.AdminActionCategoryDomain, - TargetID: domain, - Type: gtsmodel.AdminActionExpireKeys, - AccountID: adminAcct.ID, - }, - func(ctx context.Context) gtserror.MultiError { - return p.domainKeysExpireSideEffects(ctx, domain) - }, + action, + p.state.AdminActions.DomainKeysExpireF(domain), ); errWithCode != nil { - return actionID, errWithCode + return action.ID, errWithCode } - return actionID, nil -} - -func (p *Processor) domainKeysExpireSideEffects(ctx context.Context, domain string) gtserror.MultiError { - var ( - expiresAt = time.Now() - errs gtserror.MultiError - ) - - // For each account on this domain, expire - // the public key and update the account. - if err := p.rangeDomainAccounts(ctx, domain, func(account *gtsmodel.Account) { - account.PublicKeyExpiresAt = expiresAt - if err := p.state.DB.UpdateAccount(ctx, - account, - "public_key_expires_at", - ); err != nil { - errs.Appendf("db error updating account: %w", err) - } - }); err != nil { - errs.Appendf("db error ranging through accounts: %w", err) - } - - return errs + return action.ID, nil } diff --git a/internal/processing/admin/domainpermission_test.go b/internal/processing/admin/domainpermission_test.go index 5a73693db..c8f3560c3 100644 --- a/internal/processing/admin/domainpermission_test.go +++ b/internal/processing/admin/domainpermission_test.go @@ -186,7 +186,7 @@ func (suite *DomainBlockTestSuite) awaitAction(actionID string) { ctx := context.Background() if !testrig.WaitFor(func() bool { - return suite.adminProcessor.Actions().TotalRunning() == 0 + return suite.state.AdminActions.TotalRunning() == 0 }) { suite.FailNow("timed out waiting for admin action(s) to finish") } diff --git a/internal/processing/admin/domainpermissionsubscription.go b/internal/processing/admin/domainpermissionsubscription.go index 3d2f63d56..6c051222c 100644 --- a/internal/processing/admin/domainpermissionsubscription.go +++ b/internal/processing/admin/domainpermissionsubscription.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "net/url" + "slices" apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util" @@ -283,3 +284,89 @@ func (p *Processor) DomainPermissionSubscriptionRemove( return p.apiDomainPermSub(ctx, permSub) } + +func (p *Processor) DomainPermissionSubscriptionTest( + ctx context.Context, + acct *gtsmodel.Account, + id string, +) (any, gtserror.WithCode) { + permSub, err := p.state.DB.GetDomainPermissionSubscriptionByID(ctx, id) + if err != nil && !errors.Is(err, db.ErrNoEntries) { + err := gtserror.Newf("db error getting domain permission subscription %s: %w", id, err) + return nil, gtserror.NewErrorInternalError(err) + } + + if permSub == nil { + err := fmt.Errorf("domain permission subscription %s not found", id) + return nil, gtserror.NewErrorNotFound(err, err.Error()) + } + + // To process the test/dry-run correctly, we need to get + // all domain perm subs of this type with a *higher* priority, + // to know whether we ought to create permissions or not. + permSubs, err := p.state.DB.GetDomainPermissionSubscriptionsByPriority( + ctx, + permSub.PermissionType, + ) + if err != nil && !errors.Is(err, db.ErrNoEntries) { + err := gtserror.Newf("db error: %w", err) + return nil, gtserror.NewErrorInternalError(err) + } + + // Find the index of the targeted + // subscription in the slice. + index := slices.IndexFunc( + permSubs, + func(ps *gtsmodel.DomainPermissionSubscription) bool { + return ps.ID == permSub.ID + }, + ) + + // Get a transport for calling permSub.URI. + tsport, err := p.transport.NewTransportForUsername(ctx, acct.Username) + if err != nil { + err := gtserror.Newf("error getting transport: %w", err) + return nil, gtserror.NewErrorInternalError(err) + } + + // Everything *before* the targeted + // subscription has a higher priority. + higherPrios := permSubs[:index] + + // Call the permSub.URI and parse a list of perms from it. + // Any error returned here is a "real" one, not an error + // from fetching / parsing the list. + createdPerms, err := p.subscriptions.ProcessDomainPermissionSubscription( + ctx, + permSub, + tsport, + higherPrios, + true, // Dry run. + ) + if err != nil { + err := gtserror.Newf("error doing dry-run: %w", err) + return nil, gtserror.NewErrorInternalError(err) + } + + // If permSub has an error set on it now, + // we should return it to the caller. + if permSub.Error != "" { + return map[string]string{ + "error": permSub.Error, + }, nil + } + + // No error, so return the list of + // perms that would have been created. + apiPerms := make([]*apimodel.DomainPermission, 0, len(createdPerms)) + for _, perm := range createdPerms { + apiPerm, errWithCode := p.apiDomainPerm(ctx, perm, false) + if errWithCode != nil { + return nil, errWithCode + } + + apiPerms = append(apiPerms, apiPerm) + } + + return apiPerms, nil +} diff --git a/internal/processing/admin/util.go b/internal/processing/admin/util.go index aef435856..f04b3654b 100644 --- a/internal/processing/admin/util.go +++ b/internal/processing/admin/util.go @@ -19,86 +19,12 @@ package admin import ( "context" - "errors" - "time" apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" - "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" ) -// stubbifyInstance renders the given instance as a stub, -// removing most information from it and marking it as -// suspended. -// -// For caller's convenience, this function returns the db -// names of all columns that are updated by it. -func stubbifyInstance(instance *gtsmodel.Instance, domainBlockID string) []string { - instance.Title = "" - instance.SuspendedAt = time.Now() - instance.DomainBlockID = domainBlockID - instance.ShortDescription = "" - instance.Description = "" - instance.Terms = "" - instance.ContactEmail = "" - instance.ContactAccountUsername = "" - instance.ContactAccountID = "" - instance.Version = "" - - return []string{ - "title", - "suspended_at", - "domain_block_id", - "short_description", - "description", - "terms", - "contact_email", - "contact_account_username", - "contact_account_id", - "version", - } -} - -// rangeDomainAccounts iterates through all accounts -// originating from the given domain, and calls the -// provided range function on each account. -// -// If an error is returned while selecting accounts, -// the loop will stop and return the error. -func (p *Processor) rangeDomainAccounts( - ctx context.Context, - domain string, - rangeF func(*gtsmodel.Account), -) error { - var ( - limit = 50 // Limit selection to avoid spiking mem/cpu. - maxID string // Start with empty string to select from top. - ) - - for { - // Get (next) page of accounts. - accounts, err := p.state.DB.GetInstanceAccounts(ctx, domain, maxID, limit) - if err != nil && !errors.Is(err, db.ErrNoEntries) { - // Real db error. - return gtserror.Newf("db error getting instance accounts: %w", err) - } - - if len(accounts) == 0 { - // No accounts left, we're done. - return nil - } - - // Set next max ID for paging down. - maxID = accounts[len(accounts)-1].ID - - // Call provided range function. - for _, account := range accounts { - rangeF(account) - } - } -} - // apiDomainPerm is a cheeky shortcut for returning // the API version of the given domain permission, // or an appropriate error if something goes wrong. diff --git a/internal/processing/conversations/conversations_test.go b/internal/processing/conversations/conversations_test.go index cc7ec617e..831ba1a43 100644 --- a/internal/processing/conversations/conversations_test.go +++ b/internal/processing/conversations/conversations_test.go @@ -23,6 +23,7 @@ import ( "time" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/db" dbtest "github.com/superseriousbusiness/gotosocial/internal/db/test" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -103,6 +104,7 @@ func (suite *ConversationsTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.tc = typeutils.NewConverter(&suite.state) suite.filter = visibility.NewFilter(&suite.state) diff --git a/internal/processing/media/media_test.go b/internal/processing/media/media_test.go index 80f1a7be7..2930733c4 100644 --- a/internal/processing/media/media_test.go +++ b/internal/processing/media/media_test.go @@ -19,6 +19,7 @@ package media_test import ( "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/filter/visibility" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" @@ -75,6 +76,7 @@ func (suite *MediaStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.tc = typeutils.NewConverter(&suite.state) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/processing/processor.go b/internal/processing/processor.go index ce0f1cfb8..8dabfba96 100644 --- a/internal/processing/processor.go +++ b/internal/processing/processor.go @@ -48,6 +48,7 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/processing/user" "github.com/superseriousbusiness/gotosocial/internal/processing/workers" "github.com/superseriousbusiness/gotosocial/internal/state" + "github.com/superseriousbusiness/gotosocial/internal/subscriptions" "github.com/superseriousbusiness/gotosocial/internal/text" "github.com/superseriousbusiness/gotosocial/internal/typeutils" ) @@ -180,6 +181,7 @@ func (p *Processor) Workers() *workers.Processor { // NewProcessor returns a new Processor. func NewProcessor( cleaner *cleaner.Cleaner, + subscriptions *subscriptions.Subscriptions, converter *typeutils.Converter, federator *federation.Federator, oauthServer oauth.Server, @@ -210,7 +212,7 @@ func NewProcessor( // Instantiate the rest of the sub // processors + pin them to this struct. processor.account = account.New(&common, state, converter, mediaManager, federator, visFilter, parseMentionFunc) - processor.admin = admin.New(&common, state, cleaner, federator, converter, mediaManager, federator.TransportController(), emailSender) + processor.admin = admin.New(&common, state, cleaner, subscriptions, federator, converter, mediaManager, federator.TransportController(), emailSender) processor.conversations = conversations.New(state, converter, visFilter) processor.fedi = fedi.New(state, &common, converter, federator, visFilter) processor.filtersv1 = filtersv1.New(state, converter, &processor.stream) diff --git a/internal/processing/processor_test.go b/internal/processing/processor_test.go index d0898a98d..f152f3fad 100644 --- a/internal/processing/processor_test.go +++ b/internal/processing/processor_test.go @@ -21,6 +21,7 @@ import ( "context" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/cleaner" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" @@ -34,6 +35,7 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/state" "github.com/superseriousbusiness/gotosocial/internal/storage" "github.com/superseriousbusiness/gotosocial/internal/stream" + "github.com/superseriousbusiness/gotosocial/internal/subscriptions" "github.com/superseriousbusiness/gotosocial/internal/transport" "github.com/superseriousbusiness/gotosocial/internal/typeutils" "github.com/superseriousbusiness/gotosocial/testrig" @@ -102,6 +104,7 @@ func (suite *ProcessingStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.testActivities = testrig.NewTestActivities(suite.testAccounts) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage @@ -125,6 +128,7 @@ func (suite *ProcessingStandardTestSuite) SetupTest() { suite.processor = processing.NewProcessor( cleaner.New(&suite.state), + subscriptions.New(&suite.state, suite.transportController, suite.typeconverter), suite.typeconverter, suite.federator, suite.oauthServer, diff --git a/internal/processing/status/status_test.go b/internal/processing/status/status_test.go index b3c446d14..74aef7188 100644 --- a/internal/processing/status/status_test.go +++ b/internal/processing/status/status_test.go @@ -19,6 +19,7 @@ package status_test import ( "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/federation" "github.com/superseriousbusiness/gotosocial/internal/filter/interaction" @@ -84,6 +85,7 @@ func (suite *StatusStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.typeConverter = typeutils.NewConverter(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.tc = testrig.NewTestTransportController(&suite.state, testrig.NewMockHTTPClient(nil, "../../../testrig/media")) suite.storage = testrig.NewInMemoryStorage() diff --git a/internal/processing/stream/stream_test.go b/internal/processing/stream/stream_test.go index 2569ac701..96ea65b0f 100644 --- a/internal/processing/stream/stream_test.go +++ b/internal/processing/stream/stream_test.go @@ -19,6 +19,7 @@ package stream_test import ( "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/oauth" @@ -50,6 +51,7 @@ func (suite *StreamTestSuite) SetupTest() { suite.testTokens = testrig.NewTestTokens() suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.oauthServer = testrig.NewTestOauthServer(suite.db) suite.streamProcessor = stream.New(&suite.state, suite.oauthServer) diff --git a/internal/processing/timeline/timeline_test.go b/internal/processing/timeline/timeline_test.go index 593bfb8f3..8ff6be5d1 100644 --- a/internal/processing/timeline/timeline_test.go +++ b/internal/processing/timeline/timeline_test.go @@ -19,6 +19,7 @@ package timeline_test import ( "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/filter/visibility" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" @@ -55,6 +56,7 @@ func (suite *TimelineStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.timeline = timeline.New( &suite.state, diff --git a/internal/processing/user/user_test.go b/internal/processing/user/user_test.go index e473c5bb0..2a9e0a89f 100644 --- a/internal/processing/user/user_test.go +++ b/internal/processing/user/user_test.go @@ -19,6 +19,7 @@ package user_test import ( "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" @@ -49,6 +50,7 @@ func (suite *UserStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.sentEmails = make(map[string]string) suite.emailSender = testrig.NewEmailSender("../../../web/template/", suite.sentEmails) diff --git a/internal/state/state.go b/internal/state/state.go index 90683acd4..8aefa658a 100644 --- a/internal/state/state.go +++ b/internal/state/state.go @@ -19,6 +19,7 @@ package state import ( "codeberg.org/gruf/go-mutexes" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/cache" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/storage" @@ -61,9 +62,14 @@ type State struct { // Storage provides access to the storage driver. Storage *storage.Driver - // Workers provides access to this state's collection of worker pools. + // Workers provides access to this + // state's collection of worker pools. Workers workers.Workers + // Struct to manage running admin + // actions (and locks thereupon). + AdminActions *admin.Actions + // prevent pass-by-value. _ nocopy } diff --git a/internal/subscriptions/domainperms.go b/internal/subscriptions/domainperms.go new file mode 100644 index 000000000..b1e22a0be --- /dev/null +++ b/internal/subscriptions/domainperms.go @@ -0,0 +1,811 @@ +// GoToSocial +// Copyright (C) GoToSocial Authors admin@gotosocial.org +// SPDX-License-Identifier: AGPL-3.0-or-later +// +// 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 subscriptions + +import ( + "bufio" + "context" + "encoding/csv" + "encoding/json" + "errors" + "fmt" + "io" + "slices" + "strconv" + "strings" + "time" + + "codeberg.org/gruf/go-kv" + + "github.com/miekg/dns" + "github.com/superseriousbusiness/gotosocial/internal/admin" + apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" + "github.com/superseriousbusiness/gotosocial/internal/config" + "github.com/superseriousbusiness/gotosocial/internal/db" + "github.com/superseriousbusiness/gotosocial/internal/gtserror" + "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/internal/id" + "github.com/superseriousbusiness/gotosocial/internal/log" + "github.com/superseriousbusiness/gotosocial/internal/transport" + "github.com/superseriousbusiness/gotosocial/internal/util" +) + +// ScheduleJobs schedules domain permission subscription +// fetching + updating using configured parameters. +// +// Returns an error if `MediaCleanupFrom` +// is not a valid format (hh:mm:ss). +func (s *Subscriptions) ScheduleJobs() error { + const hourMinute = "15:04" + + var ( + now = time.Now() + processEvery = config.GetInstanceSubscriptionsProcessEvery() + processFromStr = config.GetInstanceSubscriptionsProcessFrom() + ) + + // Parse processFromStr as hh:mm. + // Resulting time will be on 1 Jan year zero. + processFrom, err := time.Parse(hourMinute, processFromStr) + if err != nil { + return gtserror.Newf( + "error parsing '%s' in time format 'hh:mm': %w", + processFromStr, err, + ) + } + + // Time travel from + // year zero, groovy. + firstProcessAt := time.Date( + now.Year(), + now.Month(), + now.Day(), + processFrom.Hour(), + processFrom.Minute(), + 0, + 0, + now.Location(), + ) + + // Ensure first processing is in the future. + for firstProcessAt.Before(now) { + firstProcessAt = firstProcessAt.Add(processEvery) + } + + fn := func(ctx context.Context, start time.Time) { + log.Info(ctx, "starting instance subscriptions processing") + + // In blocklist (default) mode, process allows + // first to provide immunity to block side effects. + // + // In allowlist mode, process blocks first to + // ensure allowlist doesn't override blocks. + var order [2]gtsmodel.DomainPermissionType + if config.GetInstanceFederationMode() == config.InstanceFederationModeBlocklist { + order = [2]gtsmodel.DomainPermissionType{ + gtsmodel.DomainPermissionAllow, + gtsmodel.DomainPermissionBlock, + } + } else { + order = [2]gtsmodel.DomainPermissionType{ + gtsmodel.DomainPermissionBlock, + gtsmodel.DomainPermissionAllow, + } + } + + // Fetch + process subscribed perms in order. + for _, permType := range order { + s.ProcessDomainPermissionSubscriptions(ctx, permType) + } + + log.Infof(ctx, "finished instance subscriptions processing after %s", time.Since(start)) + } + + log.Infof(nil, + "scheduling instance subscriptions processing to run every %s, starting from %s; next processing will run at %s", + processEvery, processFromStr, firstProcessAt, + ) + + // Schedule processing to execute according to schedule. + if !s.state.Workers.Scheduler.AddRecurring( + "@subsprocessing", + firstProcessAt, + processEvery, + fn, + ) { + panic("failed to schedule @subsprocessing") + } + + return nil +} + +// ProcessDomainPermissionSubscriptions processes all domain permission +// subscriptions of the given permission type by, in turn, calling the +// URI of each subscription, parsing the result into a list of domain +// permissions, and creating (or skipping) each permission as appropriate. +func (s *Subscriptions) ProcessDomainPermissionSubscriptions( + ctx context.Context, + permType gtsmodel.DomainPermissionType, +) { + log.Info(ctx, "start") + defer log.Info(ctx, "finished") + + // Get permission subscriptions in priority order (highest -> lowest). + permSubs, err := s.state.DB.GetDomainPermissionSubscriptionsByPriority(ctx, permType) + if err != nil && !errors.Is(err, db.ErrNoEntries) { + // Real db error. + log.Errorf(ctx, "db error getting domain perm subs by priority: %v", err) + return + } + + if len(permSubs) == 0 { + // No subscriptions of this + // type, so nothing to do. + return + } + + // Get a transport using the instance account, + // we can reuse this for each HTTP call. + tsport, err := s.transportController.NewTransportForUsername(ctx, "") + if err != nil { + log.Errorf(ctx, "error getting transport for instance account: %v", err) + return + } + + for i, permSub := range permSubs { + // Higher priority permission subs = everything + // above this permission sub in the slice. + higherPrios := permSubs[:i] + + _, err := s.ProcessDomainPermissionSubscription( + ctx, + permSub, + tsport, + higherPrios, + false, // Not dry. Wet, if you will. + ) + if err != nil { + // Real db error. + log.Errorf(ctx, + "error processing domain permission subscription %s: %v", + permSub.URI, err, + ) + return + } + + // Update this perm sub. + err = s.state.DB.UpdateDomainPermissionSubscription(ctx, permSub) + if err != nil { + // Real db error. + log.Errorf(ctx, "db error updating domain perm sub: %v", err) + return + } + } +} + +// ProcessDomainPermissionSubscription processes one domain permission +// subscription by dereferencing the URI, parsing the response into a list +// of permissions, and for each discovered permission either creating an +// entry in the database, or ignoring it if it's excluded or already +// covered by a higher-priority subscription. +// +// On success, the slice of discovered DomainPermissions will be returned. +// In case of parsing error, or error on the remote side, permSub.Error +// will be updated with the calling/parsing error, and `nil, nil` will be +// returned. In case of an actual db error, `nil, err` will be returned and +// the caller should handle it. +// +// getHigherPrios should be a function for returning a slice of domain +// permission subscriptions with a higher priority than the given permSub. +// +// If dry == true, then the URI will still be called, and permissions +// will be parsed, but they will not actually be created. +// +// Note that while this function modifies fields on the given permSub, +// it's up to the caller to update it in the database (if desired). +func (s *Subscriptions) ProcessDomainPermissionSubscription( + ctx context.Context, + permSub *gtsmodel.DomainPermissionSubscription, + tsport transport.Transport, + higherPrios []*gtsmodel.DomainPermissionSubscription, + dry bool, +) ([]gtsmodel.DomainPermission, error) { + l := log. + WithContext(ctx). + WithFields(kv.Fields{ + {"permType", permSub.PermissionType.String()}, + {"permSubURI", permSub.URI}, + }...) + + // Set FetchedAt as we're + // going to attempt this now. + permSub.FetchedAt = time.Now() + + // Call the URI, and only skip + // cache if we're doing a dry run. + resp, err := tsport.DereferenceDomainPermissions( + ctx, permSub, dry, + ) + if err != nil { + // Couldn't get this one, + // set error + return. + errStr := err.Error() + l.Warnf("couldn't dereference permSubURI: %+v", err) + permSub.Error = errStr + return nil, nil + } + + // If the permissions at URI weren't modified + // since last time, just update some metadata + // to indicate a successful fetch, and return. + if resp.Unmodified { + l.Debug("received 304 Not Modified from remote") + permSub.SuccessfullyFetchedAt = permSub.FetchedAt + if permSub.ETag == "" && resp.ETag != "" { + // We didn't have an ETag before but + // we have one now: probably the remote + // added ETag support in the meantime. + permSub.ETag = resp.ETag + } + return nil, nil + } + + // At this point we know we got a 200 OK + // from the URI, so we've got a live body! + // Try to parse the body as a list of wantedPerms + // that the subscription wants to create. + var wantedPerms []gtsmodel.DomainPermission + + switch permSub.ContentType { + + // text/csv + case gtsmodel.DomainPermSubContentTypeCSV: + wantedPerms, err = permsFromCSV(l, permSub.PermissionType, resp.Body) + + // application/json + case gtsmodel.DomainPermSubContentTypeJSON: + wantedPerms, err = permsFromJSON(l, permSub.PermissionType, resp.Body) + + // text/plain + case gtsmodel.DomainPermSubContentTypePlain: + wantedPerms, err = permsFromPlain(l, permSub.PermissionType, resp.Body) + } + + if err != nil { + // We retrieved the permissions from remote but + // the connection died halfway through transfer, + // or we couldn't parse the results, or something. + // Just set error and return. + errStr := err.Error() + l.Warnf("couldn't parse results: %+v", err) + permSub.Error = errStr + return nil, nil + } + + if len(wantedPerms) == 0 { + // Fetch was OK, and parsing was, on the surface at + // least, OK, but we didn't get any perms. Consider + // this an error as users will probably want to know. + const errStr = "fetch successful but parsed zero usable results" + l.Warn(errStr) + permSub.Error = errStr + return nil, nil + } + + // This can now be considered a successful fetch. + permSub.SuccessfullyFetchedAt = permSub.FetchedAt + permSub.ETag = resp.ETag + permSub.Error = "" + + // Keep track of which domain perms are + // created (or would be, if dry == true). + createdPerms := make([]gtsmodel.DomainPermission, 0, len(wantedPerms)) + + // Iterate through wantedPerms and + // create (or dry create) each one. + for _, wantedPerm := range wantedPerms { + l = l.WithField("domain", wantedPerm.GetDomain()) + created, err := s.processDomainPermission( + ctx, l, + wantedPerm, + permSub, + higherPrios, + dry, + ) + if err != nil { + // Proper db error. + return nil, err + } + + if !created { + continue + } + + createdPerms = append(createdPerms, wantedPerm) + } + + return createdPerms, nil +} + +// processDomainPermission processes one wanted domain +// permission discovered via a domain permission sub's URI. +// +// Error will only be returned in case of an actual database +// error, else the error will be logged and nil returned. +func (s *Subscriptions) processDomainPermission( + ctx context.Context, + l log.Entry, + wantedPerm gtsmodel.DomainPermission, + permSub *gtsmodel.DomainPermissionSubscription, + higherPrios []*gtsmodel.DomainPermissionSubscription, + dry bool, +) (bool, error) { + // Set to true if domain permission + // actually (would be) created. + var created bool + + // If domain is excluded from automatic + // permission creation, don't process it. + domain := wantedPerm.GetDomain() + excluded, err := s.state.DB.IsDomainPermissionExcluded(ctx, domain) + if err != nil { + // Proper db error. + return created, err + } + + if excluded { + l.Debug("domain is excluded, skipping") + return created, nil + } + + // Check if a permission already exists for + // this domain, and if it's covered already + // by a higher-priority subscription. + existingPerm, covered, err := s.existingCovered( + ctx, permSub.PermissionType, domain, higherPrios, + ) + if err != nil { + // Proper db error. + return created, err + } + + if covered { + l.Debug("domain is covered by a higher-priority subscription, skipping") + return created, nil + } + + // At this point we know we + // should create the perm. + created = true + + if dry { + // Don't do creation or side + // effects if we're dry running. + return created, nil + } + + // Handle perm creation differently depending + // on whether or not a perm already existed. + existing := !util.IsNil(existingPerm) + switch { + + case !existing && *permSub.AsDraft: + // No existing perm, create as draft. + err = s.state.DB.PutDomainPermissionDraft( + ctx, + >smodel.DomainPermissionDraft{ + ID: id.NewULID(), + PermissionType: permSub.PermissionType, + Domain: domain, + CreatedByAccountID: permSub.CreatedByAccount.ID, + CreatedByAccount: permSub.CreatedByAccount, + PrivateComment: permSub.URI, + PublicComment: wantedPerm.GetPublicComment(), + Obfuscate: wantedPerm.GetObfuscate(), + SubscriptionID: permSub.ID, + }, + ) + + case !existing && !*permSub.AsDraft: + // No existing perm, create a new one of the + // appropriate type, and process side effects. + var ( + insertF func() error + action *gtsmodel.AdminAction + actionF admin.ActionF + ) + + if permSub.PermissionType == gtsmodel.DomainPermissionBlock { + // Prepare to insert + process a block. + domainBlock := >smodel.DomainBlock{ + ID: id.NewULID(), + Domain: domain, + CreatedByAccountID: permSub.CreatedByAccount.ID, + CreatedByAccount: permSub.CreatedByAccount, + PrivateComment: permSub.URI, + PublicComment: wantedPerm.GetPublicComment(), + Obfuscate: wantedPerm.GetObfuscate(), + SubscriptionID: permSub.ID, + } + insertF = func() error { return s.state.DB.CreateDomainBlock(ctx, domainBlock) } + + action = >smodel.AdminAction{ + ID: id.NewULID(), + TargetCategory: gtsmodel.AdminActionCategoryDomain, + TargetID: domain, + Type: gtsmodel.AdminActionSuspend, + AccountID: permSub.CreatedByAccountID, + } + actionF = s.state.AdminActions.DomainBlockF(action.ID, domainBlock) + + } else { + // Prepare to insert + process an allow. + domainAllow := >smodel.DomainAllow{ + ID: id.NewULID(), + Domain: domain, + CreatedByAccountID: permSub.CreatedByAccount.ID, + CreatedByAccount: permSub.CreatedByAccount, + PrivateComment: permSub.URI, + PublicComment: wantedPerm.GetPublicComment(), + Obfuscate: wantedPerm.GetObfuscate(), + SubscriptionID: permSub.ID, + } + insertF = func() error { return s.state.DB.CreateDomainAllow(ctx, domainAllow) } + + action = >smodel.AdminAction{ + ID: id.NewULID(), + TargetCategory: gtsmodel.AdminActionCategoryDomain, + TargetID: domain, + Type: gtsmodel.AdminActionUnsuspend, + AccountID: permSub.CreatedByAccountID, + } + actionF = s.state.AdminActions.DomainAllowF(action.ID, domainAllow) + } + + // Insert the new perm in the db. + if err = insertF(); err != nil { + // Couldn't insert wanted perm, + // don't process side effects. + break + } + + // Run admin action to process + // side effects of permission. + err = s.state.AdminActions.Run(ctx, action, actionF) + + case existingPerm.GetSubscriptionID() != "" || *permSub.AdoptOrphans: + // Perm exists but we should adopt/take + // it by copying over desired fields. + existingPerm.SetCreatedByAccountID(wantedPerm.GetCreatedByAccountID()) + existingPerm.SetCreatedByAccount(wantedPerm.GetCreatedByAccount()) + existingPerm.SetSubscriptionID(permSub.ID) + existingPerm.SetObfuscate(wantedPerm.GetObfuscate()) + existingPerm.SetPrivateComment(wantedPerm.GetPrivateComment()) + existingPerm.SetPublicComment(wantedPerm.GetPublicComment()) + + switch p := existingPerm.(type) { + case *gtsmodel.DomainBlock: + err = s.state.DB.UpdateDomainBlock(ctx, p) + case *gtsmodel.DomainAllow: + err = s.state.DB.UpdateDomainAllow(ctx, p) + } + + default: + // Perm exists but we should leave it alone. + l.Debug("domain is covered by a higher-priority subscription, skipping") + } + + if err != nil && !errors.Is(err, db.ErrAlreadyExists) { + // Proper db error. + return created, err + } + + created = true + return created, nil +} + +func permsFromCSV( + l log.Entry, + permType gtsmodel.DomainPermissionType, + body io.ReadCloser, +) ([]gtsmodel.DomainPermission, error) { + csvReader := csv.NewReader(body) + + // Read and validate column headers. + columnHeaders, err := csvReader.Read() + if err != nil { + body.Close() + return nil, gtserror.NewfAt(3, "error decoding csv column headers: %w", err) + } + + if !slices.Equal( + columnHeaders, + []string{ + "#domain", + "#severity", + "#reject_media", + "#reject_reports", + "#public_comment", + "#obfuscate", + }, + ) { + body.Close() + err := gtserror.NewfAt(3, "unexpected column headers in csv: %+v", columnHeaders) + return nil, err + } + + // Read remaining CSV records. + records, err := csvReader.ReadAll() + + // Totally done + // with body now. + body.Close() + + // Check for decode error. + if err != nil { + err := gtserror.NewfAt(3, "error decoding body into csv: %w", err) + return nil, err + } + + // Make sure we actually + // have some records. + if len(records) == 0 { + return nil, nil + } + + // Convert records to permissions slice. + perms := make([]gtsmodel.DomainPermission, 0, len(records)) + for _, record := range records { + if len(record) != 6 { + l.Warnf("skipping invalid-length record: %+v", record) + continue + } + + var ( + domainRaw = record[0] + severity = record[1] + publicComment = record[4] + obfuscateStr = record[5] + ) + + if severity != "suspend" { + l.Warnf("skipping non-suspend record: %+v", record) + continue + } + + obfuscate, err := strconv.ParseBool(obfuscateStr) + if err != nil { + l.Warnf("couldn't parse obfuscate field of record: %+v", record) + continue + } + + // Normalize + validate domain. + domain, err := validateDomain(domainRaw) + if err != nil { + l.Warnf("skipping invalid domain %s: %+v", domainRaw, err) + continue + } + + // Instantiate the permission + // as either block or allow. + var perm gtsmodel.DomainPermission + switch permType { + case gtsmodel.DomainPermissionBlock: + perm = >smodel.DomainBlock{Domain: domain} + case gtsmodel.DomainPermissionAllow: + perm = >smodel.DomainAllow{Domain: domain} + } + + // Set remaining fields. + perm.SetPublicComment(publicComment) + perm.SetObfuscate(&obfuscate) + + // We're done. + perms = append(perms, perm) + } + + return perms, nil +} + +func permsFromJSON( + l log.Entry, + permType gtsmodel.DomainPermissionType, + body io.ReadCloser, +) ([]gtsmodel.DomainPermission, error) { + var ( + dec = json.NewDecoder(body) + apiPerms = make([]*apimodel.DomainPermission, 0) + ) + + // Read body into memory as + // slice of domain permissions. + if err := dec.Decode(&apiPerms); err != nil { + _ = body.Close() // ensure closed. + return nil, gtserror.NewfAt(3, "error decoding into json: %w", err) + } + + // Perform a secondary decode just to ensure we drained the + // entirety of the data source. Error indicates either extra + // trailing garbage, or multiple JSON values (invalid data). + if err := dec.Decode(&struct{}{}); err != io.EOF { + _ = body.Close() // ensure closed. + return nil, gtserror.NewfAt(3, "data remaining after json") + } + + // Done with body. + _ = body.Close() + + // Convert apimodel perms to barebones internal perms. + perms := make([]gtsmodel.DomainPermission, 0, len(apiPerms)) + for _, apiPerm := range apiPerms { + + // Normalize + validate domain. + domainRaw := apiPerm.Domain.Domain + domain, err := validateDomain(domainRaw) + if err != nil { + l.Warnf("skipping invalid domain %s: %+v", domainRaw, err) + continue + } + + // Instantiate the permission + // as either block or allow. + var perm gtsmodel.DomainPermission + switch permType { + case gtsmodel.DomainPermissionBlock: + perm = >smodel.DomainBlock{Domain: domain} + case gtsmodel.DomainPermissionAllow: + perm = >smodel.DomainAllow{Domain: domain} + } + + // Set remaining fields. + perm.SetPublicComment(apiPerm.PublicComment) + perm.SetObfuscate(&apiPerm.Obfuscate) + + // We're done. + perms = append(perms, perm) + } + + return perms, nil +} + +func permsFromPlain( + l log.Entry, + permType gtsmodel.DomainPermissionType, + body io.ReadCloser, +) ([]gtsmodel.DomainPermission, error) { + // Scan + split by line. + sc := bufio.NewScanner(body) + + // Read into domains + // line by line. + var domains []string + for sc.Scan() { + domains = append(domains, sc.Text()) + } + + // Whatever happened, we're + // done with the body now. + body.Close() + + // Check if error reading body. + if err := sc.Err(); err != nil { + return nil, gtserror.NewfAt(3, "error decoding into plain: %w", err) + } + + // Convert raw domains to permissions. + perms := make([]gtsmodel.DomainPermission, 0, len(domains)) + for _, domainRaw := range domains { + + // Normalize + validate domain. + domain, err := validateDomain(domainRaw) + if err != nil { + l.Warnf("skipping invalid domain %s: %+v", domainRaw, err) + continue + } + + // Instantiate the permission + // as either block or allow. + var perm gtsmodel.DomainPermission + switch permType { + case gtsmodel.DomainPermissionBlock: + perm = >smodel.DomainBlock{Domain: domain} + case gtsmodel.DomainPermissionAllow: + perm = >smodel.DomainAllow{Domain: domain} + } + + // We're done. + perms = append(perms, perm) + } + + return perms, nil +} + +func validateDomain(domain string) (string, error) { + // Basic validation. + if _, ok := dns.IsDomainName(domain); !ok { + err := fmt.Errorf("invalid domain name") + return "", err + } + + // Convert to punycode. + domain, err := util.Punify(domain) + if err != nil { + err := fmt.Errorf("could not punify domain: %w", err) + return "", err + } + + // Check for invalid characters + // after the punification process. + if strings.ContainsAny(domain, "*, \n") { + err := fmt.Errorf("invalid char(s) in domain") + return "", err + } + + return domain, nil +} + +func (s *Subscriptions) existingCovered( + ctx context.Context, + permType gtsmodel.DomainPermissionType, + domain string, + higherPrios []*gtsmodel.DomainPermissionSubscription, +) ( + existingPerm gtsmodel.DomainPermission, + covered bool, + err error, +) { + // Check for existing perm + // of appropriate type. + var dbErr error + switch permType { + case gtsmodel.DomainPermissionBlock: + existingPerm, dbErr = s.state.DB.GetDomainBlock(ctx, domain) + case gtsmodel.DomainPermissionAllow: + existingPerm, dbErr = s.state.DB.GetDomainAllow(ctx, domain) + } + + if dbErr != nil && !errors.Is(dbErr, db.ErrNoEntries) { + // Real db error. + err = dbErr + return + } + + if util.IsNil(existingPerm) { + // Can't be covered if + // no existing perm. + return + } + + subscriptionID := existingPerm.GetSubscriptionID() + if subscriptionID == "" { + // Can't be covered if + // no subscription ID. + return + } + + // Covered if subscription ID is in the slice + // of higher-priority permission subscriptions. + covered = slices.ContainsFunc( + higherPrios, + func(permSub *gtsmodel.DomainPermissionSubscription) bool { + return permSub.ID == subscriptionID + }, + ) + + return +} diff --git a/internal/subscriptions/subscriptions.go b/internal/subscriptions/subscriptions.go new file mode 100644 index 000000000..3826cf185 --- /dev/null +++ b/internal/subscriptions/subscriptions.go @@ -0,0 +1,42 @@ +// GoToSocial +// Copyright (C) GoToSocial Authors admin@gotosocial.org +// SPDX-License-Identifier: AGPL-3.0-or-later +// +// 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 subscriptions + +import ( + "github.com/superseriousbusiness/gotosocial/internal/state" + "github.com/superseriousbusiness/gotosocial/internal/transport" + "github.com/superseriousbusiness/gotosocial/internal/typeutils" +) + +type Subscriptions struct { + state *state.State + transportController transport.Controller + tc *typeutils.Converter +} + +func New( + state *state.State, + transportController transport.Controller, + tc *typeutils.Converter, +) *Subscriptions { + return &Subscriptions{ + state: state, + transportController: transportController, + tc: tc, + } +} diff --git a/internal/subscriptions/subscriptions_test.go b/internal/subscriptions/subscriptions_test.go new file mode 100644 index 000000000..0d3003a79 --- /dev/null +++ b/internal/subscriptions/subscriptions_test.go @@ -0,0 +1,538 @@ +// GoToSocial +// Copyright (C) GoToSocial Authors admin@gotosocial.org +// SPDX-License-Identifier: AGPL-3.0-or-later +// +// 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 subscriptions_test + +import ( + "context" + "errors" + "testing" + "time" + + "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/db" + "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/internal/subscriptions" + "github.com/superseriousbusiness/gotosocial/internal/util" + "github.com/superseriousbusiness/gotosocial/testrig" +) + +const ( + rMediaPath = "../../testrig/media" + rTemplatePath = "../../web/template" +) + +type SubscriptionsTestSuite struct { + suite.Suite + + testAccounts map[string]*gtsmodel.Account +} + +func (suite *SubscriptionsTestSuite) SetupSuite() { + testrig.InitTestConfig() + testrig.InitTestLog() + suite.testAccounts = testrig.NewTestAccounts() +} + +func (suite *SubscriptionsTestSuite) TestDomainBlocksCSV() { + var ( + ctx = context.Background() + testStructs = testrig.SetupTestStructs(rMediaPath, rTemplatePath) + testAccount = suite.testAccounts["admin_account"] + subscriptions = subscriptions.New( + testStructs.State, + testStructs.TransportController, + testStructs.TypeConverter, + ) + + // Create a subscription for a CSV list of baddies. + testSubscription = >smodel.DomainPermissionSubscription{ + ID: "01JGE681TQSBPAV59GZXPKE62H", + Priority: 255, + Title: "whatever!", + PermissionType: gtsmodel.DomainPermissionBlock, + AsDraft: util.Ptr(false), + AdoptOrphans: util.Ptr(true), + CreatedByAccountID: testAccount.ID, + CreatedByAccount: testAccount, + URI: "https://lists.example.org/baddies.csv", + ContentType: gtsmodel.DomainPermSubContentTypeCSV, + } + ) + defer testrig.TearDownTestStructs(testStructs) + + // Store test subscription. + if err := testStructs.State.DB.PutDomainPermissionSubscription( + ctx, testSubscription, + ); err != nil { + suite.FailNow(err.Error()) + } + + // Process all subscriptions. + subscriptions.ProcessDomainPermissionSubscriptions(ctx, testSubscription.PermissionType) + + // We should now have blocks for + // each domain on the subscribed list. + for _, domain := range []string{ + "bumfaces.net", + "peepee.poopoo", + "nothanks.com", + } { + var ( + perm gtsmodel.DomainPermission + err error + ) + if !testrig.WaitFor(func() bool { + perm, err = testStructs.State.DB.GetDomainBlock(ctx, domain) + return err == nil + }) { + suite.FailNowf("", "timed out waiting for domain %s", domain) + } + + suite.Equal(testSubscription.ID, perm.GetSubscriptionID()) + } + + // The just-fetched perm sub should + // have ETag and count etc set now. + permSub, err := testStructs.State.DB.GetDomainPermissionSubscriptionByID( + ctx, testSubscription.ID, + ) + if err != nil { + suite.FailNow(err.Error()) + } + + // Should have some perms now. + count, err := testStructs.State.DB.CountDomainPermissionSubscriptionPerms(ctx, permSub.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + suite.Equal("bigbums6969", permSub.ETag) + suite.EqualValues(3, count) + suite.WithinDuration(time.Now(), permSub.FetchedAt, 1*time.Minute) + suite.WithinDuration(time.Now(), permSub.SuccessfullyFetchedAt, 1*time.Minute) +} + +func (suite *SubscriptionsTestSuite) TestDomainBlocksJSON() { + var ( + ctx = context.Background() + testStructs = testrig.SetupTestStructs(rMediaPath, rTemplatePath) + testAccount = suite.testAccounts["admin_account"] + subscriptions = subscriptions.New( + testStructs.State, + testStructs.TransportController, + testStructs.TypeConverter, + ) + + // Create a subscription for a JSON list of baddies. + testSubscription = >smodel.DomainPermissionSubscription{ + ID: "01JGE681TQSBPAV59GZXPKE62H", + Priority: 255, + Title: "whatever!", + PermissionType: gtsmodel.DomainPermissionBlock, + AsDraft: util.Ptr(false), + AdoptOrphans: util.Ptr(true), + CreatedByAccountID: testAccount.ID, + CreatedByAccount: testAccount, + URI: "https://lists.example.org/baddies.json", + ContentType: gtsmodel.DomainPermSubContentTypeJSON, + } + ) + defer testrig.TearDownTestStructs(testStructs) + + // Store test subscription. + if err := testStructs.State.DB.PutDomainPermissionSubscription( + ctx, testSubscription, + ); err != nil { + suite.FailNow(err.Error()) + } + + // Process all subscriptions. + subscriptions.ProcessDomainPermissionSubscriptions(ctx, testSubscription.PermissionType) + + // We should now have blocks for + // each domain on the subscribed list. + for _, domain := range []string{ + "bumfaces.net", + "peepee.poopoo", + "nothanks.com", + } { + var ( + perm gtsmodel.DomainPermission + err error + ) + if !testrig.WaitFor(func() bool { + perm, err = testStructs.State.DB.GetDomainBlock(ctx, domain) + return err == nil + }) { + suite.FailNowf("", "timed out waiting for domain %s", domain) + } + + suite.Equal(testSubscription.ID, perm.GetSubscriptionID()) + } + + // The just-fetched perm sub should + // have ETag and count etc set now. + permSub, err := testStructs.State.DB.GetDomainPermissionSubscriptionByID( + ctx, testSubscription.ID, + ) + if err != nil { + suite.FailNow(err.Error()) + } + + // Should have some perms now. + count, err := testStructs.State.DB.CountDomainPermissionSubscriptionPerms(ctx, permSub.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + suite.Equal("don't modify me daddy", permSub.ETag) + suite.EqualValues(3, count) + suite.WithinDuration(time.Now(), permSub.FetchedAt, 1*time.Minute) + suite.WithinDuration(time.Now(), permSub.SuccessfullyFetchedAt, 1*time.Minute) +} + +func (suite *SubscriptionsTestSuite) TestDomainBlocksPlain() { + var ( + ctx = context.Background() + testStructs = testrig.SetupTestStructs(rMediaPath, rTemplatePath) + testAccount = suite.testAccounts["admin_account"] + subscriptions = subscriptions.New( + testStructs.State, + testStructs.TransportController, + testStructs.TypeConverter, + ) + + // Create a subscription for a plain list of baddies. + testSubscription = >smodel.DomainPermissionSubscription{ + ID: "01JGE681TQSBPAV59GZXPKE62H", + Priority: 255, + Title: "whatever!", + PermissionType: gtsmodel.DomainPermissionBlock, + AsDraft: util.Ptr(false), + AdoptOrphans: util.Ptr(true), + CreatedByAccountID: testAccount.ID, + CreatedByAccount: testAccount, + URI: "https://lists.example.org/baddies.txt", + ContentType: gtsmodel.DomainPermSubContentTypePlain, + } + ) + defer testrig.TearDownTestStructs(testStructs) + + // Store test subscription. + if err := testStructs.State.DB.PutDomainPermissionSubscription( + ctx, testSubscription, + ); err != nil { + suite.FailNow(err.Error()) + } + + // Process all subscriptions. + subscriptions.ProcessDomainPermissionSubscriptions(ctx, testSubscription.PermissionType) + + // We should now have blocks for + // each domain on the subscribed list. + for _, domain := range []string{ + "bumfaces.net", + "peepee.poopoo", + "nothanks.com", + } { + var ( + perm gtsmodel.DomainPermission + err error + ) + if !testrig.WaitFor(func() bool { + perm, err = testStructs.State.DB.GetDomainBlock(ctx, domain) + return err == nil + }) { + suite.FailNowf("", "timed out waiting for domain %s", domain) + } + + suite.Equal(testSubscription.ID, perm.GetSubscriptionID()) + } + + // The just-fetched perm sub should + // have ETag and count etc set now. + permSub, err := testStructs.State.DB.GetDomainPermissionSubscriptionByID( + ctx, testSubscription.ID, + ) + if err != nil { + suite.FailNow(err.Error()) + } + + // Should have some perms now. + count, err := testStructs.State.DB.CountDomainPermissionSubscriptionPerms(ctx, permSub.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + suite.Equal("this is a legit etag i swear", permSub.ETag) + suite.EqualValues(3, count) + suite.WithinDuration(time.Now(), permSub.FetchedAt, 1*time.Minute) + suite.WithinDuration(time.Now(), permSub.SuccessfullyFetchedAt, 1*time.Minute) +} + +func (suite *SubscriptionsTestSuite) TestDomainBlocksCSVETag() { + var ( + ctx = context.Background() + testStructs = testrig.SetupTestStructs(rMediaPath, rTemplatePath) + testAccount = suite.testAccounts["admin_account"] + subscriptions = subscriptions.New( + testStructs.State, + testStructs.TransportController, + testStructs.TypeConverter, + ) + + // Create a subscription for a CSV list of baddies. + // Include the ETag so it gets sent with the request. + testSubscription = >smodel.DomainPermissionSubscription{ + ID: "01JGE681TQSBPAV59GZXPKE62H", + Priority: 255, + Title: "whatever!", + PermissionType: gtsmodel.DomainPermissionBlock, + AsDraft: util.Ptr(false), + AdoptOrphans: util.Ptr(true), + CreatedByAccountID: testAccount.ID, + CreatedByAccount: testAccount, + URI: "https://lists.example.org/baddies.csv", + ContentType: gtsmodel.DomainPermSubContentTypeCSV, + ETag: "bigbums6969", + } + ) + defer testrig.TearDownTestStructs(testStructs) + + // Store test subscription. + if err := testStructs.State.DB.PutDomainPermissionSubscription( + ctx, testSubscription, + ); err != nil { + suite.FailNow(err.Error()) + } + + // Process all subscriptions. + subscriptions.ProcessDomainPermissionSubscriptions(ctx, testSubscription.PermissionType) + + // We should now NOT have blocks for the domains + // on the list, as the remote will have returned + // 304, indicating we should do nothing. + for _, domain := range []string{ + "bumfaces.net", + "peepee.poopoo", + "nothanks.com", + } { + _, err := testStructs.State.DB.GetDomainBlock(ctx, domain) + if !errors.Is(err, db.ErrNoEntries) { + suite.FailNowf("", "domain perm %s created when it shouldn't be") + } + } + + // The just-fetched perm sub should + // have ETag and count etc set now. + permSub, err := testStructs.State.DB.GetDomainPermissionSubscriptionByID( + ctx, testSubscription.ID, + ) + if err != nil { + suite.FailNow(err.Error()) + } + + // Should have no perms. + count, err := testStructs.State.DB.CountDomainPermissionSubscriptionPerms(ctx, permSub.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + suite.Equal("bigbums6969", permSub.ETag) + suite.Zero(count) + suite.WithinDuration(time.Now(), permSub.FetchedAt, 1*time.Minute) + suite.WithinDuration(time.Now(), permSub.SuccessfullyFetchedAt, 1*time.Minute) +} + +func (suite *SubscriptionsTestSuite) TestDomainBlocks404() { + var ( + ctx = context.Background() + testStructs = testrig.SetupTestStructs(rMediaPath, rTemplatePath) + testAccount = suite.testAccounts["admin_account"] + subscriptions = subscriptions.New( + testStructs.State, + testStructs.TransportController, + testStructs.TypeConverter, + ) + + // Create a subscription for a CSV list of baddies. + // The endpoint will return a 404 so we can test erroring. + testSubscription = >smodel.DomainPermissionSubscription{ + ID: "01JGE681TQSBPAV59GZXPKE62H", + Priority: 255, + Title: "whatever!", + PermissionType: gtsmodel.DomainPermissionBlock, + AsDraft: util.Ptr(false), + AdoptOrphans: util.Ptr(true), + CreatedByAccountID: testAccount.ID, + CreatedByAccount: testAccount, + URI: "https://lists.example.org/does_not_exist.csv", + ContentType: gtsmodel.DomainPermSubContentTypeCSV, + } + ) + defer testrig.TearDownTestStructs(testStructs) + + // Store test subscription. + if err := testStructs.State.DB.PutDomainPermissionSubscription( + ctx, testSubscription, + ); err != nil { + suite.FailNow(err.Error()) + } + + // Process all subscriptions. + subscriptions.ProcessDomainPermissionSubscriptions(ctx, testSubscription.PermissionType) + + // The just-fetched perm sub should have an error set on it. + permSub, err := testStructs.State.DB.GetDomainPermissionSubscriptionByID( + ctx, testSubscription.ID, + ) + if err != nil { + suite.FailNow(err.Error()) + } + + // Should have no perms. + count, err := testStructs.State.DB.CountDomainPermissionSubscriptionPerms(ctx, permSub.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + suite.Zero(count) + suite.WithinDuration(time.Now(), permSub.FetchedAt, 1*time.Minute) + suite.Zero(permSub.SuccessfullyFetchedAt) + suite.Equal(`DereferenceDomainPermissions: GET request to https://lists.example.org/does_not_exist.csv failed: status="" body="{"error":"not found"}"`, permSub.Error) +} + +func (suite *SubscriptionsTestSuite) TestDomainBlocksWrongContentTypeCSV() { + var ( + ctx = context.Background() + testStructs = testrig.SetupTestStructs(rMediaPath, rTemplatePath) + testAccount = suite.testAccounts["admin_account"] + subscriptions = subscriptions.New( + testStructs.State, + testStructs.TransportController, + testStructs.TypeConverter, + ) + + // Create a subscription for a plaintext list of baddies, + // but try to parse as CSV content type (shouldn't work). + testSubscription = >smodel.DomainPermissionSubscription{ + ID: "01JGE681TQSBPAV59GZXPKE62H", + Priority: 255, + Title: "whatever!", + PermissionType: gtsmodel.DomainPermissionBlock, + AsDraft: util.Ptr(false), + AdoptOrphans: util.Ptr(true), + CreatedByAccountID: testAccount.ID, + CreatedByAccount: testAccount, + URI: "https://lists.example.org/baddies.txt", + ContentType: gtsmodel.DomainPermSubContentTypeCSV, + } + ) + defer testrig.TearDownTestStructs(testStructs) + + // Store test subscription. + if err := testStructs.State.DB.PutDomainPermissionSubscription( + ctx, testSubscription, + ); err != nil { + suite.FailNow(err.Error()) + } + + // Process all subscriptions. + subscriptions.ProcessDomainPermissionSubscriptions(ctx, testSubscription.PermissionType) + + // The just-fetched perm sub should have an error set on it. + permSub, err := testStructs.State.DB.GetDomainPermissionSubscriptionByID( + ctx, testSubscription.ID, + ) + if err != nil { + suite.FailNow(err.Error()) + } + + // Should have no perms. + count, err := testStructs.State.DB.CountDomainPermissionSubscriptionPerms(ctx, permSub.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + suite.Zero(count) + suite.WithinDuration(time.Now(), permSub.FetchedAt, 1*time.Minute) + suite.Zero(permSub.SuccessfullyFetchedAt) + suite.Equal(`ProcessDomainPermissionSubscription: unexpected column headers in csv: [bumfaces.net]`, permSub.Error) +} + +func (suite *SubscriptionsTestSuite) TestDomainBlocksWrongContentTypePlain() { + var ( + ctx = context.Background() + testStructs = testrig.SetupTestStructs(rMediaPath, rTemplatePath) + testAccount = suite.testAccounts["admin_account"] + subscriptions = subscriptions.New( + testStructs.State, + testStructs.TransportController, + testStructs.TypeConverter, + ) + + // Create a subscription for a plaintext list of baddies, + // but try to parse as CSV content type (shouldn't work). + testSubscription = >smodel.DomainPermissionSubscription{ + ID: "01JGE681TQSBPAV59GZXPKE62H", + Priority: 255, + Title: "whatever!", + PermissionType: gtsmodel.DomainPermissionBlock, + AsDraft: util.Ptr(false), + AdoptOrphans: util.Ptr(true), + CreatedByAccountID: testAccount.ID, + CreatedByAccount: testAccount, + URI: "https://lists.example.org/baddies.csv", + ContentType: gtsmodel.DomainPermSubContentTypePlain, + } + ) + defer testrig.TearDownTestStructs(testStructs) + + // Store test subscription. + if err := testStructs.State.DB.PutDomainPermissionSubscription( + ctx, testSubscription, + ); err != nil { + suite.FailNow(err.Error()) + } + + // Process all subscriptions. + subscriptions.ProcessDomainPermissionSubscriptions(ctx, testSubscription.PermissionType) + + // The just-fetched perm sub should have an error set on it. + permSub, err := testStructs.State.DB.GetDomainPermissionSubscriptionByID( + ctx, testSubscription.ID, + ) + if err != nil { + suite.FailNow(err.Error()) + } + + // Should have no perms. + count, err := testStructs.State.DB.CountDomainPermissionSubscriptionPerms(ctx, permSub.ID) + if err != nil { + suite.FailNow(err.Error()) + } + + suite.Zero(count) + suite.WithinDuration(time.Now(), permSub.FetchedAt, 1*time.Minute) + suite.Zero(permSub.SuccessfullyFetchedAt) + suite.Equal(`fetch successful but parsed zero usable results`, permSub.Error) +} + +func TestSubscriptionTestSuite(t *testing.T) { + suite.Run(t, new(SubscriptionsTestSuite)) +} diff --git a/internal/transport/derefdomainpermlist.go b/internal/transport/derefdomainpermlist.go new file mode 100644 index 000000000..c81117bc6 --- /dev/null +++ b/internal/transport/derefdomainpermlist.go @@ -0,0 +1,121 @@ +// GoToSocial +// Copyright (C) GoToSocial Authors admin@gotosocial.org +// SPDX-License-Identifier: AGPL-3.0-or-later +// +// 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 transport + +import ( + "context" + "io" + "net/http" + + "github.com/superseriousbusiness/gotosocial/internal/gtserror" + "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" +) + +type DereferenceDomainPermissionsResp struct { + // Set only if response was 200 OK. + // It's up to the caller to close + // this when they're done with it. + Body io.ReadCloser + + // True if response + // was 304 Not Modified. + Unmodified bool + + // May be set + // if 200 or 304. + ETag string +} + +func (t *transport) DereferenceDomainPermissions( + ctx context.Context, + permSub *gtsmodel.DomainPermissionSubscription, + skipCache bool, +) (*DereferenceDomainPermissionsResp, error) { + // Prepare new HTTP request to endpoint + req, err := http.NewRequestWithContext(ctx, "GET", permSub.URI, nil) + if err != nil { + return nil, err + } + + // Set basic auth header if necessary. + if permSub.FetchUsername != "" || permSub.FetchPassword != "" { + req.SetBasicAuth(permSub.FetchUsername, permSub.FetchPassword) + } + + // Set relevant Accept headers. + // Allow fallback in case target doesn't + // negotiate content type correctly. + req.Header.Add("Accept-Charset", "utf-8") + req.Header.Add("Accept", permSub.ContentType.String()+","+"*/*") + + // If skipCache is true, we want to skip setting Cache + // headers so that we definitely don't get a 304 back. + if !skipCache { + // If we've successfully fetched this list + // before, set If-Modified-Since to last + // success to make the request conditional. + // + // See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since + if !permSub.SuccessfullyFetchedAt.IsZero() { + timeStr := permSub.SuccessfullyFetchedAt.Format(http.TimeFormat) + req.Header.Add("If-Modified-Since", timeStr) + } + + // If we've got an ETag stored for this list, set + // If-None-Match to make the request conditional. + // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag#caching_of_unchanged_resources. + if len(permSub.ETag) != 0 { + req.Header.Add("If-None-Match", permSub.ETag) + } + } + + // Perform the HTTP request + rsp, err := t.GET(req) + if err != nil { + return nil, err + } + + // If we have an unexpected / error response, + // wrap + return as error. This will also drain + // and close the response body for us. + if rsp.StatusCode != http.StatusOK && + rsp.StatusCode != http.StatusNotModified { + err := gtserror.NewFromResponse(rsp) + return nil, err + } + + // Check already if we were given an ETag + // we can use, as ETag is often returned + // even on 304 Not Modified responses. + permsResp := &DereferenceDomainPermissionsResp{ + ETag: rsp.Header.Get("Etag"), + } + + if rsp.StatusCode == http.StatusNotModified { + // Nothing has changed on the remote side + // since we last fetched, so there's nothing + // to do and we don't need to read the body. + rsp.Body.Close() + permsResp.Unmodified = true + } else { + // Return the live body to the caller. + permsResp.Body = rsp.Body + } + + return permsResp, nil +} diff --git a/internal/transport/transport.go b/internal/transport/transport.go index 7f7e985fc..45d43ff18 100644 --- a/internal/transport/transport.go +++ b/internal/transport/transport.go @@ -78,6 +78,20 @@ type Transport interface { // DereferenceInstance dereferences remote instance information, first by checking /api/v1/instance, and then by checking /.well-known/nodeinfo. DereferenceInstance(ctx context.Context, iri *url.URL) (*gtsmodel.Instance, error) + // DereferenceDomainPermissions dereferences the + // permissions list present at the given permSub's URI. + // + // If "force", then If-Modified-Since and If-None-Match + // headers will *NOT* be sent with the outgoing request. + // + // If err == nil and Unmodified == false, then it's up + // to the caller to close the returned io.ReadCloser. + DereferenceDomainPermissions( + ctx context.Context, + permSub *gtsmodel.DomainPermissionSubscription, + force bool, + ) (*DereferenceDomainPermissionsResp, error) + // Finger performs a webfinger request with the given username and domain, and returns the bytes from the response body. Finger(ctx context.Context, targetUsername string, targetDomain string) ([]byte, error) } diff --git a/internal/transport/transport_test.go b/internal/transport/transport_test.go index 3a884d53f..c51c0755f 100644 --- a/internal/transport/transport_test.go +++ b/internal/transport/transport_test.go @@ -21,6 +21,7 @@ import ( "context" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/email" "github.com/superseriousbusiness/gotosocial/internal/federation" @@ -74,6 +75,7 @@ func (suite *TransportTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) suite.storage = testrig.NewInMemoryStorage() suite.state.Storage = suite.storage diff --git a/internal/typeutils/converter_test.go b/internal/typeutils/converter_test.go index 0676bea1b..a5fe5201b 100644 --- a/internal/typeutils/converter_test.go +++ b/internal/typeutils/converter_test.go @@ -20,6 +20,7 @@ package typeutils_test import ( "github.com/stretchr/testify/suite" "github.com/superseriousbusiness/activity/streams/vocab" + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/filter/visibility" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" @@ -499,6 +500,7 @@ func (suite *TypeUtilsTestSuite) SetupTest() { suite.db = testrig.NewTestDB(&suite.state) suite.state.DB = suite.db + suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers) storage := testrig.NewInMemoryStorage() suite.state.Storage = storage diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go index a90e88a70..2af479125 100644 --- a/internal/typeutils/internaltofrontend.go +++ b/internal/typeutils/internaltofrontend.go @@ -2119,7 +2119,9 @@ func (c *Converter) DomainPermToAPIDomainPerm( domainPerm.PrivateComment = d.GetPrivateComment() domainPerm.SubscriptionID = d.GetSubscriptionID() domainPerm.CreatedBy = d.GetCreatedByAccountID() - domainPerm.CreatedAt = util.FormatISO8601(d.GetCreatedAt()) + if createdAt := d.GetCreatedAt(); !createdAt.IsZero() { + domainPerm.CreatedAt = util.FormatISO8601(createdAt) + } // If this is a draft, also add the permission type. if _, ok := d.(*gtsmodel.DomainPermissionDraft); ok { diff --git a/mkdocs.yml b/mkdocs.yml index 1b12db12b..82bb03791 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -138,6 +138,7 @@ nav: - "admin/signups.md" - "admin/federation_modes.md" - "admin/domain_blocks.md" + - "admin/domain_permission_subscriptions.md" - "admin/request_filtering_modes.md" - "admin/robots.md" - "admin/cli.md" diff --git a/test/envparsing.sh b/test/envparsing.sh index 68ad24d14..94d0855ca 100755 --- a/test/envparsing.sh +++ b/test/envparsing.sh @@ -115,6 +115,8 @@ EXPECT=$(cat << "EOF" "nl", "en-GB" ], + "instance-subscriptions-process-every": 86400000000000, + "instance-subscriptions-process-from": "23:00", "landing-page-user": "admin", "letsencrypt-cert-dir": "/gotosocial/storage/certs", "letsencrypt-email-address": "", diff --git a/testrig/config.go b/testrig/config.go index 673ed46b6..0a957a831 100644 --- a/testrig/config.go +++ b/testrig/config.go @@ -99,6 +99,8 @@ func testDefaults() config.Configuration { TagStr: "en-gb", }, }, + InstanceSubscriptionsProcessFrom: "23:00", // 11pm, + InstanceSubscriptionsProcessEvery: 24 * time.Hour, // 1/day. AccountsRegistrationOpen: true, AccountsReasonRequired: true, diff --git a/testrig/processor.go b/testrig/processor.go index e098de33a..bbb8d9d1d 100644 --- a/testrig/processor.go +++ b/testrig/processor.go @@ -26,15 +26,27 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/media" "github.com/superseriousbusiness/gotosocial/internal/processing" "github.com/superseriousbusiness/gotosocial/internal/state" + "github.com/superseriousbusiness/gotosocial/internal/subscriptions" "github.com/superseriousbusiness/gotosocial/internal/typeutils" ) // NewTestProcessor returns a Processor suitable for testing purposes. // The passed in state will have its worker functions set appropriately, // but the state will not be initialized. -func NewTestProcessor(state *state.State, federator *federation.Federator, emailSender email.Sender, mediaManager *media.Manager) *processing.Processor { +func NewTestProcessor( + state *state.State, + federator *federation.Federator, + emailSender email.Sender, + mediaManager *media.Manager, +) *processing.Processor { + return processing.NewProcessor( cleaner.New(state), + subscriptions.New( + state, + federator.TransportController(), + typeutils.NewConverter(state), + ), typeutils.NewConverter(state), federator, NewTestOauthServer(state.DB), diff --git a/testrig/teststructs.go b/testrig/teststructs.go index b88e37d55..58986bffa 100644 --- a/testrig/teststructs.go +++ b/testrig/teststructs.go @@ -18,6 +18,7 @@ package testrig import ( + "github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/cleaner" "github.com/superseriousbusiness/gotosocial/internal/email" "github.com/superseriousbusiness/gotosocial/internal/filter/interaction" @@ -25,6 +26,8 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/processing" "github.com/superseriousbusiness/gotosocial/internal/processing/common" "github.com/superseriousbusiness/gotosocial/internal/state" + "github.com/superseriousbusiness/gotosocial/internal/subscriptions" + "github.com/superseriousbusiness/gotosocial/internal/transport" "github.com/superseriousbusiness/gotosocial/internal/typeutils" ) @@ -38,12 +41,13 @@ import ( // and worker queues, which was causing issues // when running all tests at once. type TestStructs struct { - State *state.State - Common *common.Processor - Processor *processing.Processor - HTTPClient *MockHTTPClient - TypeConverter *typeutils.Converter - EmailSender email.Sender + State *state.State + Common *common.Processor + Processor *processing.Processor + HTTPClient *MockHTTPClient + TypeConverter *typeutils.Converter + EmailSender email.Sender + TransportController transport.Controller } func SetupTestStructs( @@ -56,6 +60,7 @@ func SetupTestStructs( db := NewTestDB(&state) state.DB = db + state.AdminActions = admin.New(db, &state.Workers) storage := NewInMemoryStorage() state.Storage = storage @@ -89,6 +94,7 @@ func SetupTestStructs( processor := processing.NewProcessor( cleaner.New(&state), + subscriptions.New(&state, transportController, typeconverter), typeconverter, federator, oauthServer, @@ -105,12 +111,13 @@ func SetupTestStructs( StandardStorageSetup(storage, rMediaPath) return &TestStructs{ - State: &state, - Common: &common, - Processor: processor, - HTTPClient: httpClient, - TypeConverter: typeconverter, - EmailSender: emailSender, + State: &state, + Common: &common, + Processor: processor, + HTTPClient: httpClient, + TypeConverter: typeconverter, + EmailSender: emailSender, + TransportController: transportController, } } diff --git a/testrig/transportcontroller.go b/testrig/transportcontroller.go index 385c620db..8faed93ad 100644 --- a/testrig/transportcontroller.go +++ b/testrig/transportcontroller.go @@ -41,6 +41,8 @@ import ( const ( applicationJSON = "application/json" applicationActivityJSON = "application/activity+json" + textCSV = "text/csv" + textPlain = "text/plain" ) // NewTestTransportController returns a test transport controller with the given http client. @@ -101,6 +103,7 @@ func NewMockHTTPClient(do func(req *http.Request) (*http.Response, error), relat responseBytes = []byte(`{"error":"404 not found"}`) responseContentType = applicationJSON responseContentLength = len(responseBytes) + extraHeaders = make(map[string]string, 0) reqURLString = req.URL.String() ) @@ -124,11 +127,13 @@ func NewMockHTTPClient(do func(req *http.Request) (*http.Response, error), relat responseContentType = applicationJSON responseContentLength = len(responseBytes) } else if strings.Contains(reqURLString, ".well-known/webfinger") { - responseCode, responseBytes, responseContentType, responseContentLength = WebfingerResponse(req) + responseCode, responseBytes, responseContentType, responseContentLength, extraHeaders = WebfingerResponse(req) } else if strings.Contains(reqURLString, ".weird-webfinger-location/webfinger") { - responseCode, responseBytes, responseContentType, responseContentLength = WebfingerResponse(req) + responseCode, responseBytes, responseContentType, responseContentLength, extraHeaders = WebfingerResponse(req) } else if strings.Contains(reqURLString, ".well-known/host-meta") { - responseCode, responseBytes, responseContentType, responseContentLength = HostMetaResponse(req) + responseCode, responseBytes, responseContentType, responseContentLength, extraHeaders = HostMetaResponse(req) + } else if strings.Contains(reqURLString, "lists.example.org") { + responseCode, responseBytes, responseContentType, responseContentLength, extraHeaders = DomainPermissionSubscriptionResponse(req) } else if note, ok := mockHTTPClient.TestRemoteStatuses[reqURLString]; ok { // the request is for a note that we have stored noteI, err := streams.Serialize(note) @@ -239,14 +244,23 @@ func NewMockHTTPClient(do func(req *http.Request) (*http.Response, error), relat } log.Debugf(nil, "returning response %s", string(responseBytes)) + reader := bytes.NewReader(responseBytes) readCloser := io.NopCloser(reader) + + header := http.Header{ + "Content-Type": {responseContentType}, + } + for k, v := range extraHeaders { + header.Add(k, v) + } + return &http.Response{ Request: req, StatusCode: responseCode, Body: readCloser, ContentLength: int64(responseContentLength), - Header: http.Header{"Content-Type": {responseContentType}}, + Header: header, }, nil } @@ -261,7 +275,13 @@ func (m *MockHTTPClient) DoSigned(req *http.Request, sign httpclient.SignFunc) ( return m.do(req) } -func HostMetaResponse(req *http.Request) (responseCode int, responseBytes []byte, responseContentType string, responseContentLength int) { +func HostMetaResponse(req *http.Request) ( + responseCode int, + responseBytes []byte, + responseContentType string, + responseContentLength int, + extraHeaders map[string]string, +) { var hm *apimodel.HostMeta if req.URL.String() == "https://misconfigured-instance.com/.well-known/host-meta" { @@ -297,7 +317,13 @@ func HostMetaResponse(req *http.Request) (responseCode int, responseBytes []byte return } -func WebfingerResponse(req *http.Request) (responseCode int, responseBytes []byte, responseContentType string, responseContentLength int) { +func WebfingerResponse(req *http.Request) ( + responseCode int, + responseBytes []byte, + responseContentType string, + responseContentLength int, + extraHeaders map[string]string, +) { var wfr *apimodel.WellKnownResponse switch req.URL.String() { @@ -410,3 +436,89 @@ func WebfingerResponse(req *http.Request) (responseCode int, responseBytes []byt responseContentLength = len(wfrJSON) return } + +func DomainPermissionSubscriptionResponse(req *http.Request) ( + responseCode int, + responseBytes []byte, + responseContentType string, + responseContentLength int, + extraHeaders map[string]string, +) { + + const ( + csvResp = `#domain,#severity,#reject_media,#reject_reports,#public_comment,#obfuscate +bumfaces.net,suspend,false,false,big jerks,false +peepee.poopoo,suspend,false,false,harassment,false +nothanks.com,suspend,false,false,,false` + csvRespETag = "bigbums6969" + + textResp = `bumfaces.net +peepee.poopoo +nothanks.com` + textRespETag = "this is a legit etag i swear" + + jsonResp = `[ + { + "domain": "bumfaces.net", + "suspended_at": "2020-05-13T13:29:12.000Z", + "public_comment": "big jerks" + }, + { + "domain": "peepee.poopoo", + "suspended_at": "2020-05-13T13:29:12.000Z", + "public_comment": "harassment" + }, + { + "domain": "nothanks.com", + "suspended_at": "2020-05-13T13:29:12.000Z" + } +]` + jsonRespETag = "don't modify me daddy" + ) + + switch req.URL.String() { + case "https://lists.example.org/baddies.csv": + extraHeaders = map[string]string{"ETag": csvRespETag} + if req.Header.Get("If-None-Match") == csvRespETag { + // Cached. + responseCode = http.StatusNotModified + } else { + responseBytes = []byte(csvResp) + responseContentType = textCSV + responseCode = http.StatusOK + } + responseContentLength = len(responseBytes) + + case "https://lists.example.org/baddies.txt": + extraHeaders = map[string]string{"ETag": textRespETag} + if req.Header.Get("If-None-Match") == textRespETag { + // Cached. + responseCode = http.StatusNotModified + } else { + responseBytes = []byte(textResp) + responseContentType = textPlain + responseCode = http.StatusOK + } + responseContentLength = len(responseBytes) + + case "https://lists.example.org/baddies.json": + extraHeaders = map[string]string{"ETag": jsonRespETag} + if req.Header.Get("If-None-Match") == jsonRespETag { + // Cached. + responseCode = http.StatusNotModified + } else { + responseBytes = []byte(jsonResp) + responseContentType = applicationJSON + responseCode = http.StatusOK + } + responseContentLength = len(responseBytes) + + default: + responseCode = http.StatusNotFound + responseBytes = []byte(`{"error":"not found"}`) + responseContentType = applicationJSON + responseContentLength = len(responseBytes) + } + + return +} diff --git a/web/source/settings/components/pageable-list.tsx b/web/source/settings/components/pageable-list.tsx index 3571fb1cd..92c5e220d 100644 --- a/web/source/settings/components/pageable-list.tsx +++ b/web/source/settings/components/pageable-list.tsx @@ -30,7 +30,7 @@ export interface PageableListProps { items?: T[]; itemToEntry: (_item: T) => ReactNode; isLoading: boolean; - isFetching: boolean; + isFetching?: boolean; isError: boolean; error: FetchBaseQueryError | SerializedError | undefined; emptyMessage: ReactNode; diff --git a/web/source/settings/lib/query/admin/domain-permissions/subscriptions.ts b/web/source/settings/lib/query/admin/domain-permissions/subscriptions.ts index f065aaf54..fef512a56 100644 --- a/web/source/settings/lib/query/admin/domain-permissions/subscriptions.ts +++ b/web/source/settings/lib/query/admin/domain-permissions/subscriptions.ts @@ -20,6 +20,7 @@ import { gtsApi } from "../../gts-api"; import type { + DomainPerm, DomainPermSub, DomainPermSubCreateUpdateParams, DomainPermSubSearchParams, @@ -120,6 +121,13 @@ const extended = gtsApi.injectEndpoints({ asForm: true, body: { remove_children: remove_children }, }), + }), + + testDomainPermissionSubscription: build.mutation<{ error: string } | DomainPerm[], string>({ + query: (id) => ({ + method: "POST", + url: `/api/v1/admin/domain_permission_subscriptions/${id}/test`, + }), }) }), }); @@ -154,6 +162,11 @@ const useUpdateDomainPermissionSubscriptionMutation = extended.useUpdateDomainPe */ const useRemoveDomainPermissionSubscriptionMutation = extended.useRemoveDomainPermissionSubscriptionMutation; +/** + * Test a domain permission subscription to see if data can be fetched + parsed. + */ +const useTestDomainPermissionSubscriptionMutation = extended.useTestDomainPermissionSubscriptionMutation; + export { useLazySearchDomainPermissionSubscriptionsQuery, useGetDomainPermissionSubscriptionQuery, @@ -161,4 +174,5 @@ export { useGetDomainPermissionSubscriptionsPreviewQuery, useUpdateDomainPermissionSubscriptionMutation, useRemoveDomainPermissionSubscriptionMutation, + useTestDomainPermissionSubscriptionMutation, }; diff --git a/web/source/settings/style.css b/web/source/settings/style.css index bbb8fd61c..75e7e7e3f 100644 --- a/web/source/settings/style.css +++ b/web/source/settings/style.css @@ -1426,6 +1426,18 @@ button.tab-button { } } +.domain-permission-subscription-details { + > .list > .entries > .perm-preview { + gap: 0.5rem; + } + + > .perm-issue > b > code { + background: $info-bg; + padding: 0; + } +} + + .domain-permission-subscription-title { font-size: 1.2rem; font-weight: bold; @@ -1451,7 +1463,8 @@ button.tab-button { } } -.domain-permission-subscription-remove { +.domain-permission-subscription-remove, +.domain-permission-subscription-test { gap: 1rem; } diff --git a/web/source/settings/views/moderation/domain-permissions/subscriptions/detail.tsx b/web/source/settings/views/moderation/domain-permissions/subscriptions/detail.tsx index 408d81b92..06f1582ae 100644 --- a/web/source/settings/views/moderation/domain-permissions/subscriptions/detail.tsx +++ b/web/source/settings/views/moderation/domain-permissions/subscriptions/detail.tsx @@ -17,19 +17,20 @@ along with this program. If not, see . */ -import React, { useState } from "react"; +import React, { ReactNode, useState } from "react"; import { useLocation, useParams } from "wouter"; import { useBaseUrl } from "../../../../lib/navigation/util"; import BackButton from "../../../../components/back-button"; -import { useGetDomainPermissionSubscriptionQuery, useRemoveDomainPermissionSubscriptionMutation, useUpdateDomainPermissionSubscriptionMutation } from "../../../../lib/query/admin/domain-permissions/subscriptions"; +import { useGetDomainPermissionSubscriptionQuery, useRemoveDomainPermissionSubscriptionMutation, useTestDomainPermissionSubscriptionMutation, useUpdateDomainPermissionSubscriptionMutation } from "../../../../lib/query/admin/domain-permissions/subscriptions"; import { useBoolInput, useNumberInput, useTextInput } from "../../../../lib/form"; import FormWithData from "../../../../lib/form/form-with-data"; -import { DomainPermSub } from "../../../../lib/types/domain-permission"; +import { DomainPerm, DomainPermSub } from "../../../../lib/types/domain-permission"; import MutationButton from "../../../../components/form/mutation-button"; import { Checkbox, NumberInput, Select, TextInput } from "../../../../components/form/inputs"; import useFormSubmit from "../../../../lib/form/submit"; import UsernameLozenge from "../../../../components/username-lozenge"; import { urlValidator } from "../../../../lib/util/formvalidators"; +import { PageableList } from "../../../../components/pageable-list"; export default function DomainPermissionSubscriptionDetail() { const params = useParams(); @@ -56,6 +57,7 @@ function DomainPermSubForm({ data: permSub }: { data: DomainPermSub }) {

Domain Permission Subscription Detail

+ ); @@ -382,3 +384,73 @@ function DeleteDomainPermSub({ permSub, backLocation }: { permSub: DomainPermSub ); } + +function TestDomainPermSub({ permSub }: { permSub: DomainPermSub }) { + const permType = permSub.permission_type; + if (!permType) { + throw "permission_type was undefined"; + } + + const [ testSub, testRes ] = useTestDomainPermissionSubscriptionMutation(); + const onSubmit = (e) => { + e.preventDefault(); + testSub(permSub.id); + }; + + // Function to map an item to a list entry. + function itemToEntry(perm: DomainPerm): ReactNode { + return ( + + { perm.domain } + { perm.public_comment && <>({ perm.public_comment }) } + + ); + } + + return ( + <> +
+

Test Subscription

+ Click the "test" button to instruct your instance to do a test + fetch and parse of the {permType} list at the subscription URI. +
+ If the fetch is successful, you will see a list of {permType}s + (or {permType} drafts) that *would* be created by this subscription, + along with the public comment for each {permType} (if applicable). +
+ The test does not actually create those {permType}s in your database. + + + { testRes.data && "error" in testRes.data + ?
+ + + The following issue was encountered when doing a fetch + parse: +
{ testRes.data.error } +
This may be due to a temporary outage at the remote URL, + or you may wish to check your subscription settings and test again. +
+
+ : <> + { testRes.data && `${testRes.data?.length} ${permType}s would be created by this subscription:`} + No entries!
} + /> + + } + + ); +}