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 @@ 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 @@ 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 @@ "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 @@ "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 @@ // 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 @@ func(context.Context, time.Time) { // 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 @@ func(context.Context, time.Time) { 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 @@ "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 @@ 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 @@ // 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 zcmeFYbx>SO_b!Z+1WSSjcS4XE7+gbwYeEQa0}Kv>yM&+#4#6#WaCg^11_+SguEE_0 zxFk6z=e%`q)mOi&?|$Du@1}sgyH`KG*3+wddaqvd;gzBk&I8g1NJvOHGScG8NJ!{L zNJwZS_b~2C_|0~#?*4VTsi-?BgPo~u?4ZVGmJn(OR~ra5#Kp`Q3CU&3>XjBQD$PB_ z8G$ego`g`?^ekhOShyYmkH&P0AJ~tNcH_KJZ-e7`{2TVS*&p7~)XaQIdS!Fmd(ZXI z&*14=-TP?OGEKg7kRE@N=dem_(mV_ zS9gzWvnDUFpuWFbmYBwP+3n!>>KbDAzz?{R7>33t$S&eCGYShv>FN1qYX;it?QkNy znq2%1Ea6BEZS8hsR+g7r@zh=?M*xC|kW8vPgs#0htJ387BqP0;ybZ(OwmXK`(Fjoeh zv@d%mI}a^3T_L4w8YO<`!8NV7Vl;To5u;0pTC$&x+CC8Wv^wH^BiQEg%J1_LuoSnX5Bs14LRAJYfDdL@Z0 zF%k5&INE?lY<-yM26-G1DMzD*972xuRLpn#vh8-^%(7^E#V?K^1Z4*hcEo{==H#Q< zW!oH1k?VwVp60{SvH5R55h3FyuF)6%~0PbJWRq|)bK;~Gc|a{>XJjm(EH3#M#NCrHt*L{9jQ{}P z?Ci|$3}T1cnE*KW`S}4rP5>t-+nofPy{okY*oDp7p6(~aZwzsWy`i0%je{A~n))Xu z*Z}J2AWTbpS5N)7epWUL3V-0O?f+uojt_tf*apDC4g^?P0sh^>-a*3Y4&*O|{*Nu} zRqiG#KpA2Wb+j{tNH{^P9q9fIVPyEHy^W)t30W$HoN&gV_vtxOv$OdB6rB5QLw@z<~E( zP%_r`4q$6T$WN#{aCWmh94B zf>5$EyYou0<-fK131xH##m&XT#mUFd&jv97bFgtiI62tBJRl$&$N&i8G2#M&j19Pc zK^YkeNJ8zbz<0xGW(78Z0Bo#HepUP=TtMuVj4&-HJMf>9SC(K0DKh+9%)5!?z02T*3K<+?+oZJFH4gnyK z3J0$Mh+BZ0hvnzvzvQ7tX2!1nPtrdp54F(mA(u9@zw6)iSJCeo^#)@5`|0DP1V19lsLw@f6M7M_;J2->wAYvwWJl=72=bpc~qJH{opqT$t z+SwHHa}@3fV*_%q{qKYU{xTTwbIthMVj;l)#);4`fqyMBckO7NXG|#a(N#Ki5f{pTujAfYJ1k%h0t-T`(Q6QYEJsaJ$ib-Id{UWpnK9~ zK0)=Hnl4>)TT@--u~iNAr{CX-Kf-E~g^pO5A}dqV(=?^puU*qMiM@MBGnck?$e9c> z;XIP}sT%^daCC<>O^N?=4GILyQq%r@Df1Had<^>g`t}ID{O=lCT1Ro8!oO>Rq$yrg zv;3)3miqs;nWgs)ZT#x3QL48DSBPwh>Codxe_fHXo4^P*dCehM>q(Y{v1(H>At6T1 z0}F}2ExySgw4=5d>qk1REC3UYp%D!Ju@^y@lKos&Y+Hs!g<$YmJmKG%7h7LepI7tv zP8`t;3m;LxZTmw*kDe48dU-BsXRM-!m-9%fY2k!jNwS9`LtEhsjlY{mUgi^_O!k2b z=h4-czi$|@>fYqraBEMR89{ZPU-s?wtBtDE{DGAAbPVvZ{0=TuN-I#Aj4pM#SRP$} zCQqHI{1htyobgKaZ$q-Y%948n3rMY73r4&0H<|Z~b9B32lKeA5*S1qWg&G43C8RkE z1ibI!M8Bh#b{bgV;3-W%WaBk~KRd+ECSmTPpaz z=Nm)p>C9;n1isPA#ugObMev5>9ke0ALl_zzrUNZ)lD#bqaLC$q&U9X;0eO}0qE7Qr zuc27%BR~zd@{yIneTt4xH6^)KgspA6C6o)jdSRP$za5W%{TncXTj?;7-P!ylm{N-| zrVDM`A@x{f2pjsm&SQ+rmS`m^AyK?NUD$HIHa5GT7e8tBa!WhDrZ(cWaQl80(&FqB z?l0(|vt7P^2*!Itcm}`w9E^##7n(uwW@?>TexL z89%(u^o&_AB7N80LU+U*NI2iivHy6n74#6Lah6&%dRfX~lBy{b$6~zH*n-?U{bdaX zE7yi#^37{xbstFzDUQMpB}283w38VikMm#EgJH1zKCu4D11ZyQVW)? zSb&M611I_v;J5SL5L8d4q`aRT%}=}^@R}#6s5hp@=lcNuZA8v_AXm245REp+!9%&0 z>!6{v9l9+*DYLfB0eLUT?1$OA1gRGuoZgx_5E6CE-E%bmQO2jqJi>uMgRkBRhuxM2 zhbl)?7posSDQxw5Dh&0b2-8{*>^($zNgdYr!siFFU+b<4&Iw1rO4%S*}c%;p9pqu?ZfB!(3wwV|G`Si*gO=abNi#mY=b&*5JU*5A-ljAW6R* zy+=JjRQzYQe z+po~y;%e!yMY{?`dtkF#>z=zcfVr_-TbJ;A7qrsSHI~O+cl+70#*bc&$tMr7;8Emg zO$XRm@{&2<+^@-rwZy}+o@;h#(84-H?U2>4*{btKh)~`LBzk;D!1)d1PvM!{n^W)K zAzZ4VQ|{J#%aTaMb8eV%JZH~#TzOLn2;wJpsz;V*%EB4?aalsxT5==HHc=_v4A3ds zXQXE<5{hiAG-&Vy^iG|N$w-4hWLYxfml~UcK>&mLeSuD6ndmL**a#LpM%}y1Kt@u=fuTC$T6@GimgB0UHOYRQB zFJhJK^;jL+ z#F^dL*?MuYT=)0iZPVlKXb&}}8JD_1yA$?WiY*P)JUi4V+z*cTsafAG&V~@BtB!T? z^%p^Xt9@%7I{l9=iDgXRVXl}&J@$TQWkC$GA0)+%A+yhb`z9urA)6aXas zejKPjNFIfZM{WpR?sMVt^~-Mwbi+;dmV+mr2Iz_e&@@dyda@nLz#DV!nWTQ%9}b^M z4jBa{du75n3-y>Z{Vu`IMiC?xDKQl}AVWuTSMDNyeHW>(&gV85XPeK1OQ{hvMSMpf zelM;t)P|Z;>n=Oh9U;k7SJKhA$sDAMt@-sawb-b)wtD7saf@{9SteI&T)4+=zS<*U zlm_botMG&>KZ;&L=y0)mh5H5K6&flmWGQ2g;)D50a1toGGk&Kq@dzKJO39duAsEa6 z^wYOEIM~)-N9avPeG0!%V8n>uz>+YbW09b<`(_T?YnyI&*9a6 z<%I)n_CQ}8Yqv394s-@Wz;55^Jc$Wj=|ja!SeWcq7Zka$>|l|RJvX6p=Nng(mIA7a zXyB9F)pv^_Y^vwsP6MWo zS9}|~#GE!caQ9~0x~p0$Y%X+_Q!qq)sTQLf>J4FSgMi)Ty!ohoD}KL%?(omhX-2fV zoyF0HG!v)CkR0^n`*4>-v73f*4Kq;(hJn?|29b6Bm50R%d{NC-i3=vZ4E#<^1?z~` za5;k>F1Z@VS1`GFmkz??Q}!vI(=hqVb3sNzXkJko=f#CL#c0UK} zFA(uZ6#$Zlag5HX=Jz+XDkjsk9GiBE>Olq`q5s*(6eq3ekn#vmEwWvm zbhzG;Bn1!;r;Fpxtu+cOEbPPcFGm~6yCt#Sb08${_9$FZagP%x?~MGnNL&Q(Ss_7IqhsI+ib(>>Vx3H8BcRO=zR@WPtsFC1K z;@Wr?;NK9VQH<0+bz-7DP3d4E;BV3#%(!kO1+jKYFe?;y+K2YIo6{;V{B=ze#CF zNEnahh2~nBef7D?gf6WebeOH_BKWCZXdWAEQ>1J>K4Bd4Z2rK7UpP>*vXNWN`k-QH zCL!$&8`lnJd_V0aXPI6Hr(+F1!SILR;w|ZtLA`@-pESsei_&#dq%@9CSOc6>p4%57 z2VhcQ9@EnvuCE9mpE9W7F2Y&Mc@arJ zoMC0Bks^h)C4ho7QrOtgJS_*$R%gFTX__A%z~EwbR^4mpc{P0AwQqSnMO9&dwc2_@ z!t20<4Y|_tiFUou>@@Hoa=IT4(-=&ww*5%?=wp2nj$oUx^}?`>=QAC8Vo;+SaCbB8 zT>1HBq;Ds^(W_VGjTpK`u!H>-WUk8E9z_ATPe<=ct!(jO882mDtr$+fPGu4^OMDsM zBVxvjyuit3YksWtJ6*=;BvOJf0+d*~X9c2yMkfu~#IPHUS&JH5BNKYsPy_j5S6O#9 zD|wB7oX~y9kBR6`$%&-Nc682;j9Po9ar@aP+GRh#+MgzHgO<)1ry}>Z=a}E(L$3|k zU}5YFUX2JamB;$66%tty!28n`EHCu7~@e#3D^{$%vg~#&=5EJ(;GLe z2C!96t01MmhXvrN^tv=$?C}VeY&d2|+@M-$PNtT^*tG1?BYYBd^5R7PPN>Ep!ZldE z-kQmF13f;+_Zn-h40P*|Bl^TQz?bQ$$1jWlTxhly=|mq^o5h;kbrtDs&)&3$Tx@Dw z;v`HPptKTYBS?@H`OyAd2Xo!0-F8YYD#1t^8YWSxx-e_7VPWQ%R3a2WZS=TaB7DL+ z)TShJFRC!zlVq$5Pfe8;)6hVsm#sOvt##xx3$Hw-nELRb`5srmhc0m82JO*Tj99o{ zYsM;BkVusOC|B>SK)8QkN;Wr@9VVX6_iC;XZVDsHU?vgfXpgx2#>m6Lv5%Jv8=Hg# z^oeJxn2cFn#F3exjvLPU<+UxVSlljK}&`d#(5sCnlI^+Sa~8QmFUFFj@L>9^u>b%M0+9VPG& zw)%;W>F|u@fmY$A$JPz`6i(M#zcj?*q>?IG2X_l6*UDjiVPl5-G=MPoe}u+`IF~eNl$6Za3riwLQ1`Aqjbq*o$HGQ$9&Q;y^uI z1LDSk;IyJubz~CV*CEZfw$|Hg;b8T9yWTj4>xeeB;kPwL3B`u2?pOSCdbZe@l$9j6 z1OV;XaxNpziiy(}Vpqp*uW|(zG1T3q7qiTt(31HrKwsnq57b-9v1kbHqD2)*mS17q#d)&xKN=*QP zr99S3fz-a&A98PTe7`qvqy*{=v7sVlc`}cBoT{l<5_5|PGrLbZTWsheDwZu$J;02% z5|GsDg=e}hu0m`(7}fj1b(Jt|r;@&6f`wX4%w_Af$XeI?_OVtpjLev7#@gHzNsN;X zIS1|iqaOx2%P>xtcjNXJ+o|PxuLk`X8V_ce3T5oxnP4#r9kDKJ5jh2t-V~WmclNEt zM|&3Or-L&C7+^&S)gOm+FM>iZ7`kX04J~HQV8o6&shh`4U}%5*!R$WEAo^&{{(Rir zQe2Zp{KUOoS2`sTzL0wjK8wTe`%5;4GSuR1W(w<#U9Y@WSL0eB7Wr6(I6vHBSVDYX zY+P~Nu>`743{;n7nv-oQSH_i0Mz(s(#OuiP)ekH<;>pr#Bl__Q4c02D;_F0wW-6u- z>$H#oZHP3y4`A;(s ztUFpXOcLv=qYYy7E^3RjxrZkEL&kO2r`ce(C`3a6m77y2_F4upDeD1Bz_uJ2r)`0? zA+3S12?9H;ks$t1Tm#T8lBiNb`}i~nScWg~12?td2<1K7JBA3XfRlw5ve+mu2X4KV zmav`zy&QK?TDyG(C~UsvJfe;{x17fOA~~@x6sqeI{p70rL7evlYNJq|JJ<>bFy(CS z<9NYHURA9{A7%4R!nUAvky1LM1etlwEG^e*2oW@U+AQQE=Kg}!KW$)w)Avkt_Vr0z z)L;kP?e=Yk4(5c@(@Y0acMxME;;|ZU1q#vodIy@3deqRrBBm!YICevQ#CdO>Y{t$t z$NcG>csQuS4X=}i@M~Bo5e@imtM11xr({#uR3GC^2BxS7mfd@BNW@mSheqwb*)-0C zv|sGq1a%0?c087=_~7TfC%@3@ZtB>N>EN}GKZU*XaR7;&gIt5JB`dS9?h5sko#lby zY{os(Q))KYyxb_V?}3>}V!%Lwr4||}`Z(bXzv&d1W7byGL03t|i_~B%KqxYxw6Y!( zGH@Tm$^Esu{`uEB6S5iE_t7}=SH=`w9a4#tnDH0$b=hJ;+@C}|GxP69DI^cupIfh% zW!O;1U1Pvd)NJ`HrRG-dHI&wzeFo=3gJ5=RR55WJ!V*(J}X< zBb&x=F*t30gWECbLhF2Ex+;4sxh~jM&QP{Pqyz7EG@+<ETCSBhB*^UC;XlaAWH^ zG?GpVm*=^zkGPg_tdczaY$AP7gNAOYSLt`o>DVt?`zgCC&v#K~i|5f>C~C#KmlZd? zbO5jJA-S;%*J-Ef?kv?NwfMZk%LCqw;D8{ToI=B!#7`q9JXjN#{VHQb;X_FkX&1p~ zp91KJ^bj5)q!i=Ky)d~3=ryJ-Ow`)gXuR8hdMZI;do6UkAE;!1iC-bj@@n)v8_gsgqlV}aNzWBIY*O*9Qjv1PqHa9#?2Z>_dz+?-OM zQ<*e16~SZW3k3GcDl+2)7AcT;-qOw3ycQ&_Cwu2x8INNrq9X7)w@SmgJ_hZIJ&gVQ zW1a+<^&QJPNrPGuWBrtsX;g*#vmudF0lfju!Amy5iE2>sN5#G9aekBK5=3RD3;7R} zFxIP74R<*~*IBKq%(^O~EzN>;6=EqOh1GFSjqLv0D-<51*i?`(;@YNU;JO{o1ZaWR z?gdcrYO$r|nwQR&8&sFp-Hr9DhyAJ7lMMaF2PZJKO#BZ&BV*FS_5l>-#{OxFP7FKL zo@4V99L~JBqphUh!WoI@U#Rcx)}{>#e;BLgYT7_=f63OGeXfC9aZp1Mzh_2lR6^TC*d47;)$o@qVG}l8JB$Le ztie}{eq1xKh%3)FV4}21az_J*A5@;4xKOV znwx}_v;c^{eA6)&aN;oOb~69;Rsgr$UC-;{L{R}oU;86mYO(>)G!vN|nfP%uYaa`X zRoy~`nCXfLZhR%dJKURFO2$=sZDVcae1Du`wtIxX^`Q)n;_a2qV{r%B!Pv06|HTkz}?)&6LVQ!*E^pXSHYm%%ZK!cuee zbZ$IQk=igda>O4nS%gdn97C=-HsXuO2%Oy9(MP|+-hI=|x3x-r zGoXFC{gHY8dQ*PYB>>AKSU|mKEF+!X+zbX3Iyhvtx8^?T87P@O`X)2!y8(0|AwJoa zE(nrDyL4MJ<_2P;hH&;9laR9M{t8%brf8Cuf6h_+z)sG5pAVkleuM)&0@)JPwt8*8 zPFfs)G9Sev#gb}uxxitM$)AG-D|<;0-xMqmZ`V895V4Y?)vKu3_Id$HjWeNZ!zc4| zso_^brPIiaK}`!X6hW@yVgJtzjsn94aYSKP>%5<0Yvj9!M!)zcruGS8dvtX4hrIbg zyJ4#QnkkEn(mMOdZgoYaSz!uJ!!(}tL*y+s9zf__$g@}$VeZU!BHn&}qv8sTv1n`Z>KDpSquj#;K(Zu1#qbFD{*m z`NLAd3s0s#Eb=<8WDJvCoDMi&Fw~b`?Wp964maA9 zhrO<#PO04P6YPJo!;UUvnRLxOy{42qE1`B+bDwy0YF?So@_DE94UY$h68y{JJ~olu zzz{Zi-HKYWS>5t{>p;;{>cRQ`GeG0>OB`PNlh&t*LJWQVll!^r@zXzSd!MR$oMP+& zLKvt}!^^KK5?-o~F-zJR3-mHyRM{a`*Vohpm{wO;VpAn>1g)zC9-6V;`3&~RGfxiv zvCWITLy>RsL5$h+mGK%M=#3Mr+*1XHA8kzr6r{O*Iw)!)tp0WS)uX3O5l*uuxlkoK zTGVmY$(ATP(iTH6uP4zCXGA+Dky`eN!zUqnb%e#mJ9MaodUnjVxrquA%>~W?!y}Fd zcEn4B)i3o^%~9WzlQWzlt_;ued!zVzCxvQ`!!_J{rQsQ1)cMiEVKZEM3$&43y`&ME z$H^bIKe9J72*qu4n)!5%l7)YqRSh84g`hkG@dh@U#}2L9rSee=`d8~}C6&zx74n5} zGfS&?d5c~|5)MmA_uDSmE_Qf0L6v3(ZH7Q8gLZ}}u=4jf{~Fp5=Z6}8FzZEpfevX`=|F{+ zyxETCve=V*1fVK;V4{Gkw8vSJaIvyFz7|l}WuL#%zVTVHu4+eaXynw`?reMQT}ABB zoA2chd6p!LP2Uo9Cn`qqUbn*LS;11;&nD4{>J@Jyys=N-sQ*5SJW-t${noz}?p!l% zI=h2Gdp1b#wKz^b`{?CnUyY2;$)jDifKiuoqxNYYfr}FlMS-w#;#LiqT=#qKnWj>d z;wC*CeH}1~#W`NaWGLS7)BO89hB)qN^}%#citW}x+rH1*D`j-<~ zrn8kX?9hzcM)*PJ=@-&-?;mq)T7m*_n?D?+%*v&mdb%*M;1c-L4Q7&m9Drd1u(Mdf zY-Sr)5B1jOG%Q?LG-E}E13yi;l*22UW-!`{G~?=a_@iU=JmK&GeuljU_uB7C!G|-o zd{NrMPc7w-I$8FRw#FC@#u`Rtk$W3r_jigJt#AdjGu!d5#|@Q$ky0 zM?N_imdRevQ-gvLkks@;=1?&iq9mg`=MvY?&*mpCp*;E~7##drA}bWqK+XXBq?A-G z9?K zxpFIz<<{xKm!s=}7aeN@``o8-Vbc2dv)=}f*m?~V8j`c{r+;sM68 z?T6fy?hHmS*nsi2Z_e!KK_HN?KyAz#P22&}S)|0VdaBFyw7J!hv20~}lAQIvZTV!m zo16@ZzKet5%t_OI=K3}6#*EtIOSuOftVn8)x5oE!*(uF;o=wx5tVPD?MTV@WX#4#2DC>l!MyMNnd{Kqi$wrU_HsLyJkF$}ooD`{vIu>+%8|Yk;SPJQ~j`5nY z6Dy0CW@j@eb3wMLFW;$^iHS_RY4!mFFGrc2{>EwL#VF!^L9M+<+>|HvTf!=*ExrH? zH%wyxsa-$3l%61Ch66$VhU$uv6+h#sIISGD@1(N*YuSrM1EbN=FrW2Z{we|063NO9 zZ$dl;*W~`hh8S`z{sv>9qrwJ|%fum-^QgC<#gilfY9#j}IM~b-naB&h-1GeTVzQZY2A%^)A2@BKBUaxgAt=?O(^FDaoz=g9NX+$dA z`G{94d@zgU-o5fg=_%R1fNM1QMA-^yi#n_~a+%dGb?*Awhg^%(w}a^&t}9TFn5G?p z;bLg?R8wiCGkD}G&8`C6HBj+`<|$;J7c{|t!qz+yp|LBbuu+i9;pt*>Gd76dQTmAI z*lTVpu08UTM|gdG>#wL)6xl5AH*|h zC@{kHP2Gns?ZLYf9f0{_<5th>dzB>Wq{l1OYV+WUY6^1c-Y%Onx>^}}wnX&hNX|Hu zI4HwGqXs`q=+%5@Cb1$d@5Mv+GYVP}e*8eKms2O3uOA~NPP$JzPM}XH+FnN6P#TT# z$~`&m(SK2h5df7ccE5PpO)e}MP=%b{HkVD|iXND7a$RnRmm_HL_8|E4de7Dd|Dl`w zsEn93J8lwF>gkBB{s4l6h;>5eo5rTme07Qu&X(E)x`kO!7hdD@ulYsfwisVCw460D z)A~l&u{{KI`U`HKbd;?K3HkaSuss>?q<21hK?LJNMm_tIE}uGsE@w=8b+)^{KfG+j z-()(HM@$iXn`1-4ByefENNhYw7GL!=wb`(}lvLlPdgai&5mx$1Tp4R-AMZiuwDqgf zQymfEen%cl1(MURg2zfS^f=xxP?}@|DmZjLAVi#BCM;6RE91hVz}4*J_S28y5rOkL zhT9y6LZlBZ+1I<=TMXikI@gQskCHWS_Qtw1Q&&cVbx54>8fUE3`>F~PSD09reQQh} zZ53u8eFBB~mMOxktJ^UwEfzMm$`Uh&ljPQd$;~)yCkr+p{^mnE-3KJ(P*)!NE{Xle`Pg z1*ygu$0^M$0pgpB_|)Mh%k*6Ko< z$zciZVDVnb95OB|P|iKS3!1~lV{fWIaui`cG-4*lni8fC`GWKg1s8c?W#N6A2IyGv z5?vFB?c9E;GqB>-#UQs7K0o%D(+=s8Dtg85vnbJ&7H40wRIb`Xi^RI?=kS@yEQgVT5QArrHRn=&c5+LkKYoCj9drpdil%4oF;p&~@*vzL>(*!WL+OvJ zOAgcz@7r#vMc5vb;O0_j>06K<*QZ8&#mDrG&EXx{jDlDu)DfDTY8o_OJZNdS4RdBw zo8r>pJ1m!$6KG#V9k$eINrYHr%J7Tf$GUpp>mioGV>nOR_OTj9i#6yFvorvZzu&c> zdW{jTy=qs)>o~K|ps>kXkJylcVq=F}TyZp4gMpz1^=<1h_)X-793DPbvv5IS#LmL)WXrjEt{ARGA*_LSTD|@WH8EM@?L8Wy&({^S(w@1Qsa}fTNkf-CB%o9CBcrw#UAd)6IU0*iBe%SsKcwEC5Ky@78rSK%1)k%i{F^DrW?i|o}N@zqwr0ftfC^8$1_j%kzIc$CMW|+EZ(9#dc>dh z(rfWGo_tSfO?{|tRKj8c4m(_N(>JaHK3;V}U zay4HPYW>zhTztjDq1&+M8EK(se%_z1t{v9!PL$o$uTqCsQlM=g=|M}zrT5<49I*z^T+0_ zxw4d9OdM4Cio>D2{ub2Mh9lrVIk{E|ddel`jzyd6_)UMMcieHgj%f&=C>ThTH%%mD z0x^5$<);;R71`)!i^dJMI7}T?e)9J$k|Zo4BlKn`{oMNHrs|_;99-WqZedBW1?GE1NqPi5hXHrzBcy2VU|B;d2%nZ-q!Aq!^d z1HC_rZ$^`1mO}y=_=YX~p|1!shyu&Id@}Fnyq;mwVt>afN>y=)7&LVZxy{kbfVi)X_n=dDqsHTKL}G=jf6Hxt#eomR&SY6bZUj z=kFIp{7Fz=@o8ZfQYKo!XzC_4-1I(0AeiRE46O z^zAoY@IPc->=FnX6_8ec&L3xSf)V)_LEcY3LscK;V@jKUJKCo*PN8*k9qnK8K=&VV z3f@qbw*s-@&r(<3*11>Pty@k$tfntyyNz6u@<=g(aOHb{|KgUI->%;ArFrf5{J8sT zcOzKDVPwJMAa-DZMEG9gscTd6(lGX51^ci$r&>Ox+vm-*e5(BCg8#Uwr)?tMNxs*Q z_kGBg7vue+jRkgrmV_ll{KWOfp`*9o?xU(@j(O+)?T6?(Ipu)(Y@cFf8+OMk8jkUq6j7yTfs>~Mm_z=VtZ9~29MSDa!$LA&%|9hH zpXcU_>L;$NJt`Pd3LT9P|2JNrs(VHLu8%I$jeJbW4LV51vFqQCFqO8tfmY$Iuo?6R z{lcOwrAdQqHGuIIpO#7tsmM3Ezo)qPCY9DKf;6)oh~~estw)pf7U@qWH*J@t_h1Pd zHWRmH{vVzYG3qLJi`8FOWPSScKfWZM74|gZPp6Oa=&D2lwwpa0-oE`?{1N|NrRnfm z;cZyO;VS?XN@XSdPZiV%0vYSw8;(H#Gw%QYew`t&;`x{U&u z-M_HFvyqUxwP$+5gQ#6-D@kZrP!qXy$K0;sP&!kbxjc|38oY^ezdF}9ZNbmGj@DQ? z@hCqhrrdDM$Q+~AKPF?<;PMX^Hb01)7O)+v?DBB6$10p6_{(TJ6mLyjb9GCX^T3h% z`52+|v8|b}Q(o38o%;+K5Ry4cWG?6=TDYdP63!W8rTK1Ppb}aUoyQh1qH1`fcu&20 zMHIoNJn+@dy29VVWF@E=O--H)M|29CLg7{#k5J~Xfgg0QuD^}BV0HJx4hPsg9@%kA zO|e5w@tgvBX#<+w%^2#uog}nv5$EufPRD&Fa0e+T9F&%w(ELtqx977~k8O3KOzT^< zErY$DuVM4iwQM|;BO zXm2u=JYsfd!K9?wVN$>%5Ap@C1_nBA;sQO8yUu^z^%z{{muN!+&**K zEP3zg8RJp<(X-v!%NJ8tb3$w-u(lMQTTuC#&3e<~?qNEy4&0V*5n=h}W81 z7YgTH5WB0DX%3*c(-7KLp~1QDqZj)-w+B+Pt3l(W0`I2NJmOhiu<2JWpF(5p1lglZ zgxW!_XGep6z>vahA<-L|wd|yKKDYaE=ZjRtORG~u>oqqi0M9+hl$P2E^`)r1*A8Et zs0%)E)ghCp7d}YT%QxIRJlB-D49#gZU&~tG^7hp4N~>3(Jn4IjXPeZUaeFxOgcj(a zO06#2ioJiXHk^2ks;EIfE|Yog;={K3CB zTf|o)BBd+8A!CVXjYAH>P(W?$bTOIO-dN~Zkl{n1nIo2s7EXBk&fA5_4|qd^_9lSRWZy?7*qh#RAEko!4FG))SpMqENT8Mynxd z4Fyyhxahtly&!n?4(IHhv|FhAd#146wZT1u0_^*2>4vU{tJ52+;3#|6fOv8}(!i?q zcAtjxMZ=@4J+-FIHtpl{DD4=;-k{v>P0oPW7ke14lKYu=kxK*=6T=Yh`Bv z_zUZ_O!KX4k6tvSN4xaW`EOCCNhtfHpP3Fv@6t#ljl&r(Ua`Wkw8@p^O<;X>+f>dV zwx)VeX&l}Wv9UgB^D*TFj#5WwnKLrhDSx`fBCM#Wcr6WjxwM`d*s&DgZA8T=a`kLY zxaOd3OdC6ma^`w>DT7}AOQ9WhH%Dl| zTc5&DJqEMKX+gW(kvw;?TWhYSV>6K-E(EthHbTMO=Rm9_4K6E=1Ev{U#1p6WqQZnr z{vpH}$=E)!w)0g}0`wLov0^!%ZzjM~dp=Xmn^4<#ZVA918;Dz9Q@F24#^o;3Kn zx6CRbV<4kaF3l1LMpUd=%-vc85-3AWDWk++u*YC{+XmN1t?M?DUO~eTzB>Q;B+mMl z_PB>MfUrS|dH`bvUez?iVG~*Fi3!uzw-OA~3gl_u6zHtPWI8zQmfxr9d860dvp=>R z|8-p}RqM47ogkZgC7siSnn$@lOQ69S{@(kbcHXip&B^oKP@$WbtYUF3?IveuZ7`7E zXJ0-0_3K-3Qj@5Xhme0{x^?Bw+@rm`G9#6;#<9}1yOf;;flj3%`K9ZkI(1LFjjw!3 zR<2CmE%{8o8q)+txe2{gx6OgDmTBLL4U$x^bs7wRZ1AC@XvMJ}*;BK|it~ju?r0{c zSIT_!b=`TMlFQnXeq+N)dge51tctWpxoTtA4nI*&lOqF;4rcsm=k39~uY}nrh7^9m zo9>j9#tr^bra3I)=#ANEth@BNcwDDJy-pfp20SLtLJ=c&uTNxmJKhk&GZOO&vNzx1Et0ldLTKB68~{_v?aSx+(IVQ_M3LZB$ui_t5{^KQJ#Vxr{`U zp{6DdM4`9rcU8oVj-YDyvYao$cKAvkj%2fdRe?Gf3V{l1>48*h=`yHhD=4hG;*$Qc zTBcIRYC@;qV2DZ^Lho%6*-62`fteG8z!6fNG4g#DwKCZK1^uh!Czky-i?SO1hdZwE zBqXUK{xuS6ZLT&<4dn`@lAH&6dIw`K$G`FdKUfXJY`!mC=l4;L)L|(U>aP_Wc88dj zYctkint(hnY_-)*Cz>!{uTomCth6Gi)Kk@w2I*A`Cwx$W+al+wo6#`s1J?K^AMMfB zhV|!eE@UoeB+>vVD#)AVh!_^9XKg~>GNdi{5&yx``q9>=gSPs<+2luH0Wn2GRhu!= zp#J6jAvK;T0_YqX)NYjujhL7G{y^2xGLM`(mP&b3hl4pZ3DhU z=+{5iIPSZa*NAwxY*fKe==Ca#yo2SEUx-a)5=H_J3<_z+DrKoyc=C)VD z&~D5Y-`Z?sF`E@hGsO=A^aiy;`m!nUiB2U)M*kc8U4h!R{8;99A^n)EZ4y z#IS0#rV8*6`OkiYX1zRtp-kG{n6YR}_VmjM|BZjqvMRn}>qRwdjQ(6zakA9l# z-u_`bb<;@MkF9mACmTj86FWK^d09zw=Ppl3=0se`81wR;F#Y&i_1NoTR(zspA}rw1 zim?r~-cH$H+eGELw1+)w726lXLOg(mk7x3nAWmCk$tg?92D=9=`Q|y5T&x$vjv2UI zal!eAWJjN}$cmvNmcnEq8~K=&>rq7xxR!SSRQ~mH#fF~n!nFLCEAD+U07%de-^fLe2l%1(>jC#Q6eF_MM8wi zkAURi+pOgr`zL2@FPym33qKgba%YZI1-!lYI4B#|@vPllpTHc2{(5DReiCbMVXI9( zSsBU4r0xOGpP5*5A!vb|lyt)}N_0b-an2Gyj5$w?~=KG^O?{3 zvd|pmGs>=JS(TBoC1j$bqlr6rc7DOIus2_vToahhgp7KxF1!klt&V4wSVz`kYixjI zFlGRQR6|e?AR3)(ZB?<3B5ny$F~U~kI?8M3D0ga0DdLM=!L~d{%Xf{~@e>ikeX?&n z@JREpWlQ)B+Ut*DJF0FxiL=!yR<%y_TZM|*JC3iYU=2PUo@m~tl&>$OUN7^;rU6*a zPG@4cdUYJdjg&C@dFR`7*iD{*d#jm89{Xa8Pwt4L3xhi_Xv3izNBsI@JKn9Z%C0jU zJhkpH2x#EVFaVBD%a#r?KDKRX>R$}CC2Pnxi{0Pw;3|;F=}Vj4weJqjAFjV=5wEnk z1(-^S)Wz|;?o;Vr96BZyM`eTV!^UrO`s}y`h`h6nEn$>*#Ac3dbuAn>Zi>{w?t+l@ zvM%RsNZw^46tBv1ps%_~r_PHWg!g>6DmH4*nHu1Tk!mq9N9{Xa2JP&*!)7qcXE_ME z+j@1kXvls#_F-v`AriixyVaK1jIGFcmpv60-96j{N6>Fbx66=~<>H2AGyiI9gY0D1 zlilH#Kz+3l2xxsKPaqDbUOvmz*%Wg=c1}PdxQW>m3`{<43|?`>aVI2Dfga!k=Olw8 zSloQ@*EF%Jf4wA{E;=8Zn`tms9g+-)FAW|%uTS`Rg9~joZ=Gs$mA|}!&B5814)$&! zL>~LA1qkG*pl=NfBzlLutSMhXj~yJGRfejl2phHHN^LKUO!?9GQq$3C=SEyuyjxl0 zao~a{z^;GvsKx2zr6P{s^#(0-yYmbN;!#3V6zMe-067{5C%$*WqN~XT`y8{(w)QYT zG^bd&M`Uqoo$udYqkvps=SkebjaY#u9_%-(-@=d6-A01>z1*c9ZINby52RN7c*EU( zt^*G7`C=lTwQf+DWZ5J(v#5$Kcg^&3)-rUD6oOj8-q_D&GF5+u%_}GjwUufTgXf_T zeA@+ZXk(IvyihLN6w8CBNfomB#_0GqZ3rRJN^2j~Y=0uc;LT#6@p z8#7<&q}zQ{znS ziYcO*J5{SCcldLj0DGh|_K#{$Yl_phXF4C=hpL0r4t_2ht9b+js)7qmov}a?i9#1l z5iOV0*|diAqQVAiHKVpR<(C2;lB!=9?Fucw_oq~`{|Q~9zV$lH-ar+UxtE#%X&D*X zS4YptT!oiUUd$xMUXT6y@K+uYVbpLdqdQ%R(36qRpgOkeaD=49-{QSPT0Ho7nE1L; z$qH`06K_V>SW^7vv1kTx{`_>?7Y`3&PP3WEp+lSBMa-Z4f9l}DPB;Gyuxi1j)_lJ+ ztQ+z$dxLW~q$;|#mEs=5$E+r){-*=m zR`>t#$+-PDd&eO8x1q-WK}!QJs7=L?v}Xxq8Ze}NKD;g?71i7GDd*7WXYXw8BR zHfTpbUac{4F(h?t(Mry1Y41z@+1u(;wY$X|V6mC=L?V8r+xqz2u z%h%7)^L0~|)F*F1y`E5xWja3ly#LU>t!Losi%Ek=UK@)Sj-jE>>$DavR<||dctRj( zr$}OkIbt$bkGfHPHaS4^G3vMhyYwp&-nA67DP7EmJ10BEjlqwn=f{^x!-@RieT~XJ z4(4i~$SvJZhy)%y;E{JiH}Z@(W9#tOl`ncz;23_?dx;_&u~yox1%8oc_o>m5wFojmv^k?X|Kl#rkbiVtb`q-L))!{Tyf zJbAQd3c+U5UiWSoe%eP~A(~0We|jZ@zw(5?NiCyuy)-YCeoGvosTT4HCUlG`H024; z{cui}FhR?V_<5ZG9$+V5u#0OL-uM&JCuaXl53=c{UQ(EJIJxHjadA5ZGI(^{SY4Ve zC7ZGy)7{g@W>Rm@g1blrY$7~8+`nQf+oHJNaY{U2`0k6J|HND1@_-=ann(0B4uG7b zC=97{7-0c=eC@8xs=&Xk#yjB{QtojrWbk*x)|61vIU*XYG$nmszx%YCU|3-=X40056m^?zD9FUOeM4bTSY`Nr)cupSjJS_>+s_JlS(`HIv zQNZN$Dq(Bs9c3~zGf6eNTuw|=ti)5?J14f273@`Io@DGEYhn8D!E2i-PTE>D*nRoS z;F*)v(?Jl~X$7Np1aFAl5Gx%xomS2Z7|-s}Us2I0W~YLb>C5fkucKJhhv1wz$7;kq zoZSz}+L}Q{+#0~hN*J^R`K*>o-%s$zZ-?c{&8TEG*wK?)@ZEcxMZz|F#Kv@Pi!PBL zf^Z%LMcm|J9hl9ezeN6wYyKrmeWVX{uN&7M2{5;-Sx@6DD&GrBnAcniJPc1b5g$=Y z+npb}KD$1Xor^`@F7-%UPsn92d`4v$F6@?OZXIHGI^7B%Pv*Xz;K38PrII6Cz>=nNII>s4wCJ! zN#e3OA_`s1Mj6G0_w7%TWP_V*-f0FL5`&_s{i()JAG)yOLOu?9rEI1b%?AbtZ5eOq z@W@SQEExD^y4+}S(3H?P~-XW77pUR9_O(g(6Lc8_>%%RUC6a~GLQkk8_S96deW z>3$oD`bfilFb%depUci^xYja!{p^|2>26Yt*=y{)zA%Sxg1J(7qb($sT?$I^+gG3T z&hn@>&Bwz{wT>t=H*%|yWY&M06T7bdSas|? zr?uV-z@0RwHG@>cM*R0O(C>Fb0+nM93Ef6k(bE2j@ijYdy5i6+2r4O_MYEu;8PU=v zWhi2Z#G}?`bTBh$Z|o$$Px`$&SyYf&e|g3JtA|1JS-m6;?fDvz_O$Z*(Xc0zv;o9* zwQ}G1qbN_nJcr%ep&03QGWQPW*1pcj9GV%pod8C##S)rrvvTTq%!d^kn zUvYTY+V6e{yeIdd9EzxC4MD4P8xiWH>wB;Nit^m;qT_wxk_~l9p+n}XG`wKwi=>a* z{jEWgX7h?}<;{rE{h)cFVjCj0<~PS;qrObVN?W^r?q6R^0l(&gWmwo%+8hO^lesA7 zXowo=xlBIK&D5CRm4FLI=ZTTa7NsR5kSHn94z5nb58W|w*#(cg0}S*0W)CxI-1!uY zx^=#n2>E3P<$V6EFuId7oh`_Alf77Ah)zMr>qQDRDUQi6&+-JYns6-QI}Sl&%^Bd=1pDCsm!$iZuXPN?bC6wCZPu_{2by_ z(%D?v?pytn)4{PufkaqpNW7)RqtYg4W7{BEQNg%d70>#rSfJA0A!2#3JeHuA-1vn* zQNk}o_jwF~wR8bT0ceJ>7!DmwabpkK*UR5%Ja*7Lun&|KR0U0h%JOY5qORBcWF2-n zLEWJuNp3ZlinZ$6j(fC$Rmyii#C0s4cZ0Uv5eV#V9w(gL{(cBd0{Wj~@*9<` z5U==Nk92;K_{x-=Wb)48SW@cAhHjD?IAU;DmDG@l%Oas!mlo?H{d*TSR1P0dFg(g> zvz0F1?j&%0UgpW?!%M}kb7>x)R??Khsy6ny zG)V*%P_ago(8aaI{#aq;hoY)c2r9bITV==Gm2eP)fXfb&&D4qT?(dpm)wqzqu1$AF zWy7X(<#FyrQ&Uv5af1ZCPE+dc$)%8_1o`e3Pe zWh0@7dis~HQ#G{_4q_^x>AgA0VLYN~j4>78n2QEME*B7)4!?ygC&{bZN>EarNN}&9 zSsf^0pEkq`X-Vx$NU_a$bZ<^#%ECG*aq-nrytft=t+nL0UMSY2wg`~cAN<7kB;+_T zH)dv+Uw8^Ee} zGLQ9KX79Udu`%R!8JZFUk^m1h*`=1fvvy!RwE-p%mu;Sxe9Rh}Rkt(@0%S15{KVZt zRW;C(dZ$tOw!%#H&C&b_jt_~E={(PXT2)H%4e`dWEoQuEjITG7i~2=kyG%G3H^;VY zqqiE{Svs@fu%&JRS8$Ef{{*UAB*gvruPeIa*R0;WO=`7ek}xx?`1@wh2k0r(?xBa`dk63lQF$Ik`36>Qo&k? zaa~~Ay4vQ+&3uvTR*pwNOb1IsT|tO|GThNR1b(knUiUPkFD2Xj?n9(pIAW7JYemiX zU+CPmRE2Bd#BR4QPliciEL6R)swuBF?(jC5`oAH%57lX)$d$GnQq6qeR+%L#Z{i zY}7~EOy`EsP_q;+%F77{lf*Sjbw9VyD9KOX)kAL>-LePR;&XdfV4$z|&U&UrY9e8n ztabK#wMMFg$Kn!#O4HV-{b$S=yc>CUCfAd12a5?6g9`VpQy?q0+l$oPj{0pX=1Je* zmESIA*o;P|x6HLf{im-&v3U+1Gwtqb+?weghVjZ@kL)`(^h76c$>;EC{1fcniZiQf zXX_>u8J`$=CCR8Sc{KBCkv+@o=%7&|$mQD3Pf&=F#ua_G-qM~pZ8}Az_FxK$j-J>m z(+A632h8Sb#=ds$2Mrg zlL)0}0_3M(;|fg`6NzjDgUm;*^{}Zb%vaz;4HF=8ch-_ zH4)`A7J)Jn8@C7Vl#oDp2FDW8l#IYrK$in~A(sPPoqm7!9m5aqbSq-Z&!2{Lpe!b& z(lSrCELNQCTvIs@AGX0zO2<-*zF#}%+6zZ>p_uL#*oIN@F2&E4H2e+B#p+6-?!NNK zlVC_k21!_>1BG@E|IALh&1c`*7q|o!9bP<{asMaAB+K;-d8njIZYkzXK0f-eNLUYj zgBVsYV$hPdef1=b#KG{k_NhHq`d&|IOKV8VU^-f3syPoqx|0xgwke1JpR&?5?GQw)ioKWV zv^|CK;}$hLdNLiYWAl5qr4hf%Yy~1cp+20g~2RTvhu zU~9N)iC&n>`@;Jx)GRMwS{hXFJ&m2qHCj*NJI)+@DU%cqQmfi+?mV!o?ZXzi32<2# zJcjX*s9m>hux<#yI&N_0aoeMrKJbkx=R#BtG`cxv4kp0IDrTmCGD zlZd1>UN#h`K7RhSbZ;(5Q?FL8-VzIFNidS9U^t6i1=?XFdkL#=@eI;hM@Y+MTzLT{ zU+*G63G1niJ(SX)tF`?iN)udPKs6uuek>h78p3A>UyLE~V9EGJgC$*qc=?ao=G!1Z z5__)5ZkZiy`@Fr5`w{_@h=m2MrD9~OMmugq+?<^-UkuTPTqJFs-X+ayKAp!VX_G;$ z^lY3L7MoqiH~H_bz`j_N<$FG}x0YI}TYJWX84^~uBC3fCM@32ek!*gM?!D3R@Fnog z9U2vxb9U$z_ZLoyF6Qm!6RNj63a|oa?_}L)5{#9J5oVwJeMQ9)56@t4)T>hfVka56 z?fjj?vL5UH$`6z7MJhZ67vjo*RYr(;;ekxck-SPx1} zDCW)VZn~EH(>Nj<3UU<`L%3u&E^f~+4<`d1NYczObL=+M2)<@_1en~K& zJ#}Jg`PA70Dw#}heaskkl8AQCKgMNaw~UUbU9BqSDumD+)ZInm-K0%L`!YAQttRa9 zYc&MK^fNM1c%&n|y(z!QNdDSKA_LEje=(-a4%&0h43cuWB^Fq?+jX1msB*=wx_%6J z+V*fw#!yO6_D9=|+S4W!H96Ac3EJ&tptwLUleT>4XaZQ+V%#||F)AJoDe3%RZ{{2c z(nB-;BSpmEIiKD7Z+t|OP~&99zrG%o-@0esSEZnpq0la&kTl%o2H3OgJr2wTBalqi zg~ODWOQDN`k_cCt!W=^KFE)$Aa_MNLod^NaKFY5VGy>R)P}JA{kxq-F}r z|55M--unMbmH7XfjQrcYRN((HhOvQu@M~PA{QoKJDWk9Uo5@r=<*Q#0&YKEG>K*3! z3i)|ltj-cf+h$JD^Z48(k~$K=dbgY$#8$^z3x<)B;&6xyNP!?s zKbM|Jx(R38FE7ktbben=edbz*Ad+vW{kZ+%UcO}L75wV5 zUvC_gR-n?y4|COM>2i51UA=)Z^nP}!ClyegZ&O1fOxR=oy!D#+)|AAE$RSkQ)S)qq z&(%K5;28H!OVZIQcLKQ2ZLqU@1G7hrW4pEkeIi@hf-Fqxx+Hn@_C~;HdR))lf;{Vq z^Ri(RzSQ_zs_heH&arCOC6eBq?Uj79LEDdCXixs*&jr>8`5r5eZsX5P0>L*2-v1!U zDCBrq7*#bX@idnk)zZR^PVQ^n1{Kq|kX#piHspLOik^UDRUB3)PYAG*H5^5;HqT`S`mK6&hMba63>|lVx4u+y|uy~>;UK0LiY^XcQ~Q1^9Qe_w2wxARkxXa40RjPUh_ga zqIs>hoz@I_0{Rx;hJ!U91Ibrteyup8JGDXZuMtj-gqsOi5YbTcoV#|L`9aiuo61FA zJ`(qle`LN)=B>#37Od(Qdzi|P_x!+1y6w~#T5SgX|} z!zXyp9d*W`P6YP7&riAh4=OFZzrs_?a_+mqbFQ|IMoob-8m2Mjy0qc+2QN-BtJtEu zni@zNH)t?o&%(dpikGDv@0dZ4;fDnkXA0NOAAdUt67Q#U;h>|hUucN#va>}ASYbT^ zc4HFNRk*}T^xVI(IP_{r?uuor)-8lpNuXO=M0P~@h(WgFCseBrZ+HuywqF)J!KB@t zU2Q5Eo$h7i{xAG4P?2H>f~vr$>kqsR#XX*zPHUWRkdPfBtE?C$6MEOj;~4*e$F?cp zH>$29W_Mu9j=AFZwI26`R#JR&_`Zhv*7~PnJ4B1)^HB+gZQUPK1=(&#NoZD`xZTT4 zKlfMWH+XElT^bFpK6YTPbFz|Ne)};pxxdyx5HfIEU_QbmZ56u4Yu{2rtz1(oTl01N zGputzZ+#f$s%Q7@ep5erVu+Q8uhEIs&o-S;b+al{sMc2cQzbrk>%Wn9<e{n)v7d5 zdEb?>ig2WCe~{9FZY{ynH-~|5+q62bFWc&3E)D~?78k#!P$uKGw$2V!l@XZu`be5= zQLh6ut@qBRN3Z#D?uw%TD|B*Qw&8x3#qDgm8@I9i^Ao_axaC6Cnk7Cw^&s^!D9Xnr zl}}#hP#rsOf!m?S`xX8bK@Z;zfYjoikDupAUd#hSe69w}?$SN2$PJ3E(i#Sqq323K zWJ6tSaU)uvFljkmAxklU_YZtxA|W(|%7glMvsM?~T`+j(?rfZ{0wbHVY1M{>>#{{Z zttOZq`Lx=uaYfRc)BQw8>Tmoq?a>4uNOeNObEDY_8zzo8p(5qFbkU6R2+vIWzDd0#^^=j}(j5U!#$1#D0ex&L)(i zqbeU1{XFks(cGFCqQ`#}wyMQjOYqUx?~_OA-}O0a^6n)Q681Zh=EzGm^0RI)sQ9CC zTcBZBc%=u#66_SG1zN{`4gSOe|y`PW&?)o%dr)2jW8TUHp` zG{6uR-sPpAwp=VRyR5c*X2U@I(e19)&0I6@PeT;JP;?X&JCciC>apF%Q4XjxfsJMR zd}JvRdEmq8`-#1g0h>JeldmU@x%f!wt6lv;20yjc36m$fZV%#I_okhhPJ82)m&IPC zeK@^X>NBH()n-Q!{smd?Vl>9(PReP%Fw2c&O#l!lxo-H~+Dz4Nv@MO-bA{82)6f#! zcvl)-4EC1=-n{CrpalA3liXy8Y9QDtrSp)_BBD?QxTc(`YvvQBs2XZ1~6`P-;8{!A!DNqIEH}`Lz_Q@+^TPil!&{jB>FTsCr(KT%-D$Uchi^XREPlSuo z_Z&?|YIx1-QD`tINHmd9XFnE>u=xP3aDU>rsZt#hYD&PZ&eZ_>DIr#o{Jk%pTT0%|*g)fv|YZ+QerlzV!&kTJu(!v&8 zFyt(Oq+Md?gX8?1mO!{yN9$qUD)_CQFtc1K-Ay)aQT+>94Uh_qOOzCF;0;ccLELqc z$r~e7jn`d{@zOGd%eN@9PK^2xa+0cZmA=N!TitGCbCf|c%4|e$dbzSk#wAW;teQ6@ zTOG`fhaZFgEKMB{c~Z0Jq^KYX(IX+&ZeQHUbG3@%1RvM;GH+#2g+)ZlU;9_RwJ0sK zU3kJ~5~PNQ|5@`=2;0@Nzm)SfbF}*D$6qag3_+U}+|P^RKH@JK>8}&@a|{U4<%^3^ zDm@sd-bGyyu%a>RuUtRuP3H1s&st>}BskV9Md*rNCvE!EbHjSlC!{P*)`DyYMguY; zwasItf7HDl7`aIEkbFKVo93gh-q_Kcoh-FMrSnHvx1Bpfc5E+HKpq7T06Dd522I&U z1wN^O8n!SLvFFl^^D%Hgzw61_Y3MN9$W0_Vtc~@n$o=YQWmGorGgu*nYct>GAtlCL zg3vmkz=+Of*}urZBY>R{nV=Rb|It^W%ETul<5T|-<#Vj?vEtq(td)Rb*i{+&Mpu1I z0=2cB{-#?v;WLOJdA9T;r7;<^=46-)rc;%u?EOFML={q6Z6 zximfOKx_d7yQFN>($uyayu-%u7ur{L2+MfqZIR)JDf-kO8P%BuQrlatV=vKrvpskVw^AlqfU50WNRqp6EExi;JjUD?9vgEs z9GR}1oH_S!7Oq&s$JMo-QXc3{l+m5e>VQvjLN`p%STkD%7q?5Xwi?HG-A5W3-p>c; zgXXbTfRws)?S^GSYWS%&D;2K z4e?$}KKb_=X=hfUT$zKDil^E^56KJ zx<|OqbG#sq^ykXN?Zb#QBz}v$;_bW~bN~1vVFO)4?F;mea}FL?Ytq`Yn&{Y$rjCa~ z$zS;9$c;TT#0%%`b%LO*R0Wbd?{^zR)%=&G4mS*jRkf^VfIz;Pss`?OE{meHYIQFm z>kvnd3t7FP_%2UVQnRw@UrO5wNssFY!|H9xBD5wsM)OE$&zP3b4aVYd`b>`pNm|e5 z`cJ=VtR&g)_DZl=0VcM|@^jKSI#V{9W%o$mi-W1!lNvzWiMgUvg zy(agD52NeKd?bV%y#2c^NdV78_O!&5t)%o*TCE7Rl;MUH;j6EdpOpHMt;c6vpQ zz?WE0=GX2In5c7oMX-|E>4^Rb8~KSZh*{u6!|#y~%ckiZU-By~&RxQ%T2psjd@JoHHKV_=(V+eQoIMKM z2T7n+r6mbv5g$bzXzQU22ssUnDjVDynQ~k z;UA&~Aa%t0XD597?pH76WJ-Sc^2Ctv6T^XMxFcJb6$`hg3EV;SmN3VfLmQJt>sm&r z*Uw3EXM1x&)3h&WbDZY}y^0>Oi_9fLzFm?^osQSLD!a<)*e`m5wec}w|Ev8k%U@!S zjs@ATOGMS72gdi^2OID2^hCta=yyt}PA3)^Qkt#^t5_rhpEu;;jh4k%)%?%zA3v%j zJTMt68`w5s2^~w28R83&L0)tBA zVWq2THehXJt_OlnvfE-pZFt}4u>kyNz|Mn=3i!Paha3L8(= zBCT^#uLIE5=Luw&kAg_R8fNeN0TFD6aeatx&hJ|MTZUUk-QI6{?D*~WRaLxdCvBY1 zokFTyH(p8Z`<1Q~;mTQ7vf9o}+ca;~6k~SM@bhcbPh3$v!i9=pS(3-tfy2t`tUnk? zeJu2_^z<(O$)fp%J_!kRybzf?CzR-ItBsZc^qA+tD}Ek;7STVCkPN~cm!2*@^2^~F z;zIZ$0E%J{=#8}1nJXs6zi#xuKiaOk6?XUwn4miURRSwx6p}Gyx60b=hdJaPJ53@u z66^EhR`HL(<%#>h@KHYdWa9Zm%Tb_XbaLz`-C8yGKmSMO`S!oQH!7$3Dyc30%SHI_ zW$IiGKmW*_US6#JH>#rlBO=9{%5?R=1V{ZQ93p>}&!0d4AE=7ZUK$6DQ8dxZ7ZWFt zcd)4UMs?^<&!GU5ajxjE3de{PH6OhDtMCeX3G(myjQPeyuh4$gKPy|q5p>sNphOi0Z_PTKXXfD(0dOyPa6 zqT+tzsRo%wiK}pshhve{_5~h|7HOg8k5}&2pT~Wuf6j~1#&uK|T30NzLy9}7&X7Ky z-2>Zvn;clJJz`4MFdz@{uC_?3Tth})U;^%Qf1~>I-WOtH zA{pnR@M^?g;3IWO<=_4LQZd<*A^jzLvSGYj!#TPevmll(^{JD!?o+3&e9%x;(w(6| zfhZSQ^1Xaj1B_r7g_SJpL%u?(?@gwskuF zZ{-!SnNm@=D@hEvHh_3dGgj`Y_RNO!eT`+<eDEWdu>TU+UX!UcHPDHSqS!a0RE$M#BRRS-}O@PJfm zZS9?pG|~>S!bVa@TW?e43YZv62|jo6uA>lN@|;s@Cq;2IHL^331Gk7JcC2ksaHfrW zq`MB^X<9QgGX>@744J~>y}~v;!FV5z?X}A?Z@Jcdz#3TZhFc~$5d?u(iI->yX=1N- z`6$YD>pp3TnzHV&H!yU%WCW&M-)Z`dHy3-&=#$jOf-{7eXV8=fi;JDs zf~-<5t5d9wJ3K|E)Ee2d154mQ98PLz#6+(tOP-zAahfK1!lcu+=f>vqxPNKO%^Cbw z6-X9wD^2_s2>%r2NVecR=3)HK1iV$X{-Aq+3hDYOdeZ2&k%wdBTo$lok4)b#bBF!9 zdXHdObe#JAY*q<~;ej;Ww}q*2jX&Xjw+iw=7M`cVP2c$2!4=nnk5A6=k2nT$b3VSh?U+Ru+lQtC7a%dn9dX;O z>6eG9Fn`;nVrcn=^t@g3_j0l;pO_v1{k&@vosEi#q;uhX$``}Fz>dAH`aV1%;e&7o zZ>z_#!45?!>B$$?+v(iZde$XP^3a)M{PiF8v8U^Vt3o!|BFtS9g*uNwi6 zjzD_heP;#NK|F0@)%K!@)&XetdNl!ri@Xsb&8V&3_~z0c8|Z#y6a$3`xr2^Kbh~zZ zP3%iaZNVEO4cs|S#;mqx1qm@4&vLx$f|T1mk)fHUsy4jBI_=k6327jNG}h}ozw#5@ zD$kZdB(kK}-|p6xy48?;TR;1uoP9h4x|})1@iyt^3zh2ykzx~XVz3VJMjOM{nIn2_ z>(8lz6tKTTPYwwBdyRz!GkC7G8TRG*85f6Ti4aHQY_VOuTH@#Or9n^`xEpq-3J?M1 zqE_W%RqcgO)Mc1ZSW4m)tR`oAPkXYh`AVgCmo&N z(y5>akXKX^?s?|OizZ^I6N;00#B-taA{nRBhLx-Nfl_PmzIV%nxpX?G*#93#=(@E^{mqBngW{wTQ9m3QV_yDRRj1AKE!2g zrtGPgE^mTb&zZw2nYZU!FdLqP*XaKWND`zEcRkP&{;zEhx_alm;juA>xpthn!BbWj zO+=h0Amj*cewgt4C(St0(meyC(|~!xFE!fA*hN45$F6nw2>Ng$lTJVKA?pr4znpJj z(}RWQh_9|oeX)!3o(+Ww|6BOU>>MiuS>mZN(%cg!e_2TX1B_WofI2|Y`qSL^O#1?T zxq>iEPd=>Sk+oz%2o0}X_s{NkS%pIPM{d!OSNT3-kqMv{^Srfz~q@6SFJ^>?qZ zdM}coldgSYQb5>={-zt9a4NnSL1yx!NB<#E5xb0ycK(}GA;7D!jn&1~E~C?3-u`sI zdoFoss-uCB@!ZxpHGm6;PoCmG!{_Y3m`Ple-+!3Nom!QC3*l0X^*3u%ataPu0&Q;k z$%BQ#{9~(iTOL*x#Nzod5A@3{h0Q@PDl@!|qTR1|tk`lZs zl_IdLx@%+*V6~nEf?Gq(@2~)0^a7=gT^8TDl(mLbsPX48Cyg9DG48*ch;|$yKd&_t z3e=HrHW85gb~VO)hr=!%-8!s2I%}Dd;AdlChJLs*`mto~w&csxf_i)o+=QbwA`;1N zrS%thO6JdFQS2g zsQg5=MfngpGWx4&2I|`B=rPLyh*|TLjz?U9d-$Jgp0O){7v^2zsiw2Hm>aJO?-VGx z5@KPkIgoQa9AL^7N@`+qi-OOwlVhF1dY5R{<7+O|OayXW>2x3LcwE}ED8O0voPV|Q zcYL=Dk-+yPvi=~}@$ma>+o+?n`?qMmRkx=t?2)P>Q@>%D!SU`IVk}hHv?? zJvTo>XRLqS;*@Wt>b@PV)UV{r^vd0QG#&?pMxNTK@Z@>XSs`E;K3r9XZR(-S9p#o0 zB5RIx5m!pHq-fVQZ{>JnY?DqQIkyl(sRB4BL%v8>aT^3y#w}mRi%RIsOGY`q39sog zBqv4THX}77uUA)vL4j$Se8r%S!F6QNH1{YIEC=3P0lbJu8e|B|m*s!t`J?^~lM_ai zKQz>h>a2W3kH`3O_>jKdI%FmBeUYfK2rt-P)J)4B zS)u3NQ-%fA_+Ti89k4p0@S8u_5NeI64-Q_@*2Bmo)0%;-6WpEVJ}4v^Bg{dC5gk*t zfXui_koD34e(L+v&Q<%`!{bjT3Yg3b_wNikgKo346?5cGFW}G%6 zX|NFt7_avY?DujVXP`bYSD@uu_X(p;-;HR_3A4`OmM}z`1#_8DJqmo%f}LscNPFt# z-7r6VXZ2Bh5>?j{F?&dIyWa2%sm^uGTL6ms>)dC~sunDgCV9q~XsDK1)X!rE3odg{ zZK|S?0GQ@K!A%Na6==Rl1fI=q&Fv{_DIl2fUDUz_A5&W}sh;Dv4bOu{$(oy5ce7QA zoYxOjm_U0XR5xEJa@&QBrQovEi=6lUM<}*Wsn>r?6saJD-8Z)*qlUjzX@bKMcP*C@ zP^V8=ZbI8^$)Ot+yScc#Y+|txzdKoPb+Z+?!pbezKCpEGw0if`&0ZYTY0#eWT7TG) zNAyim&abb(JSR!IxE&}{#X7o;DzKrXzBgPn-yv>H<0}+<|5IXT5L7&(KuG`W2ru;E zIB`B-29c9YeaiB*`}>;Vs`vZ1gLw;TRPT(bhtC(c#cD3e&-&h6k22+Ld&&JM9@IXL zz>|7#)lW)Lxa~<8LuCl77@M`u@)AZXLnd$y$-JKn65J zt)W_pXrUTS?_nbXmzUgI=X6;zY|{@k58QVU2qgMi#x)&e?L4s1<^#jCb2sfH+M87e zBC8JUsMC;1{StC?+;+CkC;1y-i`7E^*xFjr+_Ocv435v8yxl08KceF?sWL*hGdj&v zZgb%t(4JpH#oAklLynd2NRLNHz>H53Kgh!Td31_@`wMQeTIb`Ckr8{F3q|TmaNe~g zU>*)$=StldPPMu@&v#0SV4Hv!$^H$l?{}vSmgahPWEE(&L~MG(7B_&H&w2u71)|~e z`&NNV;?8mgT~en?&{-NrP%uMoSMKkv+c~pvz`jF5PCT157u-7iFUL7jjFw70yFt31bo)v&zap2MdtFy5wfD8yUprL{5 zS*qFpt3yx22wIxPUNSK?Af?*bEZx&+EBb`kZQ0g5+F*rOc`f zL|W3QaEeLc^Pf5?ChdRfz}g;K{}J*W%nNQG;o@S$&eW&nui*9@ zL}5R)c?7m%Iu&8CzI=PtCaJNp!$}rHai3VK-JxC!17zYZLNF?aOVfN>po>X95}nl%QbdD zH~gfY(iut7oJsyfO{QYwb?33upF*$mms5D3^;h06;W|UY%bku<1fFjRlniJ;MR}%A zImgUlJ34f)j-CEtHydhi^`ASMn*{S$zo!?GZ)sVr3d2=;D!2XRLss)saAXiCzUo2A zPF+8r*4Xm7tueZ?zfhyQ@8z`Pe!jQCh_T!|fp<~6PwL90$ZUK@qtMaeC!5`2 zyccV+H~(%*j@Q4j7cJ?(4d>qeyXfuzqsy>VNX>lf^oF673>s_^%2sIgg({E+HO#;H!wa=E*WQz&F9Cj@Eaj2{LPFoMh2;RR@6NN_8YBe(gmue z6j6RYtW{_g?pI}Q*DDlCgpgNjn9H#z5f0mVyau$`+A&FPff@wZ?3*Fr#01rdG@ta% zlOKN8X(`txHuhp#yy2Q*57pUs%8fBkkFM5wcXEW(0%p5xPW_C{n}!V`PJy7nA1T~ zK)_|5+K?&M&B#W(KaU$^N8FroGBw||I@580bSa>&{A{SA`Ek>+(%gD_e`u=0={@lc zMnqehRDcmlhQXa2aDq!aMslH4L)T8|F%1d zS)S*u79#`}_XM&<&vRuA9Sd>xhHUV`v+rB7j%cw=kz`*5^9=-IB32o%?Z0H&CB zl!rDxI72&XIcNyNqndrT*#$OI%Vw>o-dK<8_oMU2u|fgBpt zy8h%pY*7b?hcnFQgO#D&%JV3y$jV7O)n-3X*&k?-9%2v~@kGOv&@W6wefo&+d@USR z8$)qrZXhy8p*}|ohaZbSOPJQyhjVI4wU?O#53qn9KOE7-Z%(M^EuvCldy)pKB(w*D zyKfr@V4xQ01xT*kDRDy`_AK59knZ~Nr4O6k$&~?&$+omV3aBhxT4idoz~^UkSFy#D zUdHL00k-+p+NT({NBr;E8QO&k_{1P5?5K#G7UpFL=s&S&HR8y`7VxToBmIkbEH4{w zC#LwWh_giaCC)tq2pWI8Yx2@_8Sl&gN<9u{CgOUD8ctZgpJZr$h=|5ZuFUwYUuo0ApjY)TH1ZxJ$igYt@i{*jaq-N1YIRRJ-9cuylo zAWC=o!W8o<_)-J!e&;s9u6t!5u%ju7{Z7N*Ek)Ei4(-w{hotM9)7WFSh4bsGerXgB zGZs!KS=}X1F*}+J-qbW_Z-8d?{`r!yVaf3bz}i^kuNJ_LFv|GtmWk-X&FNWZJuuP0a{HWG(;&7A02B=2dkP@%IWyJ3n<+-@^SDc# zr6ST>_j}2Y&d{ad+rx|m%kCz_BC`aUtVG-54c*!sz}MnQ zHz6#3y9GPFoa>f;A+i{@*dJKh(?rDg?Iu}SB??A+O_?Vi=FyeKR209~U;GaVWAZ7o zgp=oUM@Gi!i`mAMdfCVuPI!dRdEtGLi$nsQo3Eq=goPAFxOW?sU1f@(3SK|s$sQO; zO1=55)TH|qjj+~kmNHdgR z*=qqaL%cKka)wfwXm1{6F`pp})oY>GMy;QQUA_DS%Qg~mmXNCMY((*~sf4x%F}Lf# zC|5b14e>FvLQC+>N9EKVrO$dRTpst=jnE_lzI`N(`~<@iqEKW=u@WY!8s~VRFrN%4 zUk=aFy?ZzDe=+ygL2-58wkQMwB)Ge~yF(KK!99fFF2UVt+}&Lg+}$;}Ly%yNySp{k zkMsMIBd_Y6dUfj7z4s5Qpo_J4uPt+}G3J0uSC`6%l1>tUhK=X~4b7#&=GDDV{D5+`W-;x#4ZRlSHGH!fc{6Rib$} za*d?={hX!)6enGx{)}{ku3laBJU+Aj!Xv`DpmUPu@Nmins_@@E%hy-EztVp49^Qo= z<(m^M9yy5bLD^lxmtt(iyN;mZnRubeA0}S2w%9WaTt#B@r^}#Rq<#Xx*yj`6DaYwf zNGIc<7&#%~UG3L>w)K>&K#skf9&={08^WQQ} z^p?z*IBGAyjiYX?iC-?rigHTF^b(_8&@D!M+%wBp=^aqp6Kvo*}uER8r`##wCnxMh?0h&bj7r;*QXE+^3)gO=d2g|Ljeq5BH6mk6s3qsKoM=tRuT11f`h1xG^6r%EY zTtJ%1O|sJ!mg}_ENZZa8(S*lQOqUf*ugj|~H@kHwx5aCPuijc2w~+Fj6qpnhTBtLH z#?zs#-Sp1HgG-Vwr)z!F$$Xzdp@E9ZZ#bJ=4kH@_q0p=K@4UJlO}a+|IbgO3rXyYmKu3gaJ}ZZDq) zMeIS0&v=4V;lo!v35i=&`EDAepJ>=lw%oz2e}r}D=q+z5b5lGPiL&^UQ@X%eKzx?m zBd$W5ZFFys4Q1Wzl#yYtzPgYvS95i|GdV*JNyT^v+uxQ|Xu6hTYDPJ$p#_~uY-2Ke z4xi1Nt>KMnYt0{jbk#6H#Wwh%W*?3ZNnb6drb;TQYRKTCQn=o|_s#^vn-2;mK0Zpe zbJ^3kB{8riYZF4F{R{U%2?FQf+4cH%ffT`cS=hmHP`Mo6j~IT7x%Hs?cfKt zhgDDFjkIB7^QgaVj$8aAU7FT_8e1Xv_tvm*a3!@4qLl)`G=W=%a5r9#mls{H2EET1 zfBW5R=Om=1i7wV+SKZsoC277W2hVx`?TQ=+A^vZ0_NMB)?VNR8!C;i}fnv13arjc? z6X$=l&k_G$gUvVFF``mPi)c7blmL(G7t|ugcy_X~~0huqjQ~a|< z63_pxlgDYCrRw>FxI6Bh@+f1DagHDPartQ$>eNO(xCa`}ebMIW&1XKlpPtUdgG|G~ zvkAl1uN}pON`I(Yaq&v@dDGdQ(jH`aN_Odagq(4vkE;2IFcJAVa8tlB3kNwErpHo& zXpK^S<`Kb-b4V9rqqWZM%%AcIbab#SUsdBNR+%gO-STQ6!A>rnE*+kv8iwH9*meXe zZ5_ujjIW|9=Bdv;iA}jqa4vLg(kr_6Vc7|(>NFNLB_?^Eh zfVyjMfxFX?Y**59boD4+y81le9Nn|T9w$lqn3;vMUjA`XacwvITgHmsb?zW7=;BRt z_{?{suL5h!zTwn8=Qo9M%|^r`?IOYETD8z3hUsf!^MW?tZCVTio0s#676wL2&dztM z+Aj3bv@dX4osT}$9a4v#4{r@kIFG$pywPLf|3Ko4{xRuR*lqt-LNywtKPhD(4hEzl zZ1z4!QEw3a@d?zGYUw!2sW<~zf<+2%BNvh5=mk2?PJ~9qQ7)` zbxY37+4UKr>9!$0=Nx@>r^SoQax-(GC5s8_1#vogpME-QJ~I|M7NYYuA|*NSp!^;F z7@t%f*P<6~){`l`4P_d}gG9WN0T&(R#i!4}U&}Hx zqcX@^=#Jc7bp;e2O-(J|^;oG`)Akdr_8P6&6zHb0MJ8sI-@jn4=F}$V;rK=j1QbpQ z?znqQvMQbxofX)Z54YoP6vd-r2M_uf) z70`a|fXl!KEs1{$v`5gjguup(1hJD*i|(Q2#I;kZeYP7wJ{geb&U<&q zSxpR$6{Q=*{<=u{L>=K0|Ny$sos#aJ66q&hF#l*7*Q z9&XM)jOPOIQ1p6?4yWvYvb7THsn035^4x^Ouj}R0IFEu4KFAd96@mD&P-GZP1{ww^G+do7{}gW2ihb`&`^3Vmwp}7dx7i9HxvjO$^_0`~dnyvq_lfQ$Jk>#2F8G~9t6_~hJ|>sT zzpoG0G7I}VjVyAJQxh%b{A=+?!Cqfpk@iNZihaaBDnTCMA^E^~CFR7-45VQplS8jb~`-}982DhQ0>3}XRmar2EyeViEq)+)d{OuDqGC`gOBaFTaqs4CIU9CZ@YNVXMP2_|%TA6=b#>e^bRBrE zA8ssmFNvrqB8oUl%g6+&_`%}&YD5zJj@Vk^3R{~|05W)vO1LcWs{GJqJGk1brPy=V z{rioip`A*ACL$(I2EOlM(fW?M)IAA`zW(hYT}7-YWNdKU@aPM7e7Kc6*dTVXL5W@NXFq*?~X0N{~ZT3V^ZGW1iR5Z zwz$*>@4Ss9t?A0k#RmHg4syqSH@J>>lYrUq_d#V2vM~(xr$m!6w(UQ)5K(lU9@nBw z64J`uS60D< z>$)=o5Zu;%F}`RZT*kfX!Q`FeLyr4b0$rZBuOPnCbYj{`qW+uAZ2d4*qK(8=Y95n^ z8SrJPTa+9&L!lIK%kM}cc-6^s{CxkI)%vkK(O4yE;EyB7kckua+gi9Fo72$RY+5` z$3`Pcb|$`Ab0(kSbvL?#cri3>(~_}?=`MtoEt5@ey}W?tq@1bN3V~NF41ss!_}grj zv_$kE&hfOFJ)xOYa>{WcWwxb-^3K&-cD!fj+nuUwGOJJ2P7ChhX~#Vu zpN;|^ZVcs9*Y2niA0lFX0UKEQiIu8v{eoVn{XTCH7M zj6dyzT2LGM~`# zO$$fkAWhv@qnslN5#Lwz2Mu!xq22EFiWsOd!OCyrYmDGor9vtUQVs$`V{_6Gg}jhw z6Gn`}Hu*J&J z_yp-in=}N(WB1!)Q0I%kLU4!a2doCmlnEauV!|fSzp)i@;z4-&aA-v9?QX;n1)rx; zhtVw<{MjPnqyR44TfJ_9p&UZgt?(%F`(G?BCj!rAykX{GpLfI0Ml2E0i9e)gj?9FZ8Uw#^t!tSg^PPNkN5o%p z;UjcCAs>vUBFn{|Y{%$pT$Zw!V~Oe-1aO;Ae+g@oL@5k&j)ZxPA3CR(SX4o&j;Xd8 zpLhbtKQ`6~kJ4}y(=~MpMG>yh44hR>84PLHDxQse0@dIa0 zDCasEc&*^vn#aty@s6!$h-gibt>gx5G$(D*;quFrt!7@E=)3q0@a^H_wtT3Q;j1ueMiFpi zn(*Q3i7sGxjoD1HmN4fRhH5cR&)j6Ep-DRO>G+sVsyIlCgsOg@#5)7m$AYDyAts0B zMJ5A%lFdWuUE##qN0rKibwiV4O`$kjT9zT7slOZ7A#6Kr;S@_pr&~VVtj6Gfqb4kP zb6qa-o`l+QtC;vss710n%5~4-J?oz6bsH(L!`t{8f&8C!iHDl8!J}{sC5U(;76O*2 z`CE;|vCgr~poEtPyGQE!oz(|^G0AcLlTN4O?^3y9)9P3Kh(dP<$(&!Q&rb~=);rr@ zPTp^#nr(2)myh*YY1}h1qH2C%$q>Q+>A2-%dXoJQJrU4{?3i{V`9ip}B3Q&xJ!wZX z@em-4?~N4`RUjUk5^!XCadp_Mu1*AM58MGoe{@5_W*opsZ;KHzmDfN2RdQUz()j#w zM`R$ASJ$}5pD)^2kRD41$#GIn*XIG-v`BlviQz~Q;BiZ@o6#OC4}XQgpd7rg>9>8X z(LY%Sp*p$$;V|#jGc=i8C&-UmWghEl3=hJntzrEUoiak$6`T~NVN6?LbaP7tBz%%p zmv+Pl&$5|P4NOSf83EOcs^J0Wm_!h*yI zh=BFZ{ZXww#>GbM2qb?77yWg?wezEP@EG{Tadm$sKEAUw@()DR7JR8m9AhKC55_9c zUYQd*e}eboIkaK8&ssXAQ%Qc0{sJqZmhY7MBMzfwt}8Npb?p0;;uM=JiY@BtoXn*d5^QSQhLyTFp5Kz9nKT^)jtY_J#?jJBxHf>T-*6pESrUljTq~_?xwjo$#@gBE@k7^^l~8-YsGwNK<^)?8Sl%3Fj)oZiTCSm|?TtW0^W zK)f{-HG8iEl1Kg>5_wGc91k^yl=s>*-G5`#Fu-)r15!;jt%yZT&RtoCN0r^?MG^yP zKb6Zzo;~pCoiv??*~r`twmN*ys>MRA9+m_2RU${EUG$rcMNdK_`7_r4&}u^As``?i zD@wB{d0TDXZPtEq`VoVft=H1-wQ&E}4`uA!ULs@SrS7x3&W)KWoN8Lu*rp? zU4rBb<>TkURnedRxcgjy6wk+-T;R&46~Ri}OIN<3_-w9GjLq_D^ZThEC>*FZM*WJI z;Ps5(M7Km$35@B`DtY}e^+4OJ@wPe0xO94eE02`2<=6__@plspSY@ax;uLMq|=X z@$#K?{`b3GkeKorxGla4C`ugD$)=$99(apkQxFdy zFM7f%+Wkv%5Z?@aUhxEFGyn;C)KvW;9*PNaLDz04O6p;nX8K28P$M+c32pKoUSD0| zV{WPAj99PxS(0EF`yGebEsjv5w0^+uETWLNmD#6s?y$Z-3WHUqm!Y>g?^oQmPW+r~ zRHJ`hXIU-BDcBX@2%TT@!8I{CX&N9ul{s(ju(R4jZfXKs+l}+hM3r>1@$P688>$rP z_s|=ymt=M0((4bv0$bU|u21MEP>0tZSwFG}F)$A!W@r;Rc(1ox+D0~-`wj{EK~oSB z;$ouHfL?6zFwGP26QhvU|JEM%@4qHe6J*~rHi&g>dgwcWlE z4BWCiz5B1bFLAxidG#a-!RLRq0I2--3GUuQST1fX9F?ZZrM$%-QuPoD2xrMuWT$lV z*2Me6!UM$~F{9VU!N=t=$0ECAt*Y-j{Qe5iD&I|%{lHw!7msgOn#KO`<0CX){>zP6 zCEiG~gWW}~Um-q!A{tXzhtFe6b3|Gx@%;UPtBP>Q|5F+t zBX^PXJIwaBR6$Elo7dtN)MeQus3CR!V0gGOvZ<|C4&=h?K?+;bsU=Dg*K5LWONTdN zE?@1C#@o#nZgdM{0oP1L%yj3~ zXzEKSG)rsH|^5Jx)KP|9_mU547ar~@1pe?kO>VFfTEN3>cs^#|G ziLK%AYmatyY?`Hqa+N(Ba>hKl{*;4Z2KSFZ^Q}dm5Dmfh^>V2b0%*L2<^W532 zbX_bd$VIGZN{=jim^xRXZfL(l|74`7@8EmuBe+U%FSnv$CcbuV! zZA`y_(KFJGcQ)S&@89^M$7YdaGiR9*beGxW{el}{zF(pHcMY;`W_Y7vrdskOIaR?G zA3sqCDE)79@$I6pj~TuhMw0Q6rC@wSMyJg3}(cm8$HesSHIQXfVMal zZ-$X5xEB5e@6BgAZ#DJ~U-SGw?cQ#pzNYQ(_rqHJaE1p}Sb)sqk=LIsJ2gwFiZszq z$jE*|mUCP)`FMFthKuHo>s1n@>!5o@?WD*GuPAN+M!sb;jah!?z9)oIu~)W{mceSs z&pG;L@!2STqJCzb1A%G!1r=uFYLo6Fhy3-C zF%K1nnnAlx`%77#T8Tf@dqdnypD8>PhA9~5;YbtCKW^X=0UXU317@9Ad057N+4aat z)k0B5hO%K+4@=4S_Rs+P<&p~c`Ki=ZR^Opumne1-NIt0yv( zRkx0n)SndrwK3!Pm_8@3&OA(3R?DNhKYD%jCcwE2W({(+&|_#ly>dU_$oU6MzOP_W zU41=UrY}5OFFjG5Po;*2#@=dohJt3{TL6s#`VZQpZ^56?ET9@g>SvLdCO;hlC1{Zx z?wE|tJ%lyYs>GZ2NDZtfFUlwDSpk&^w^?|@i-3T13o*hNp94^`jz8{7sBLBTZw$iaDp2d%)`rA zBHk3mkSP5T7FIkIiuaQG9AY;d?h@sXdxzZ7}*pCjV_zqJF#KP})SJ{Q^Gzd<@bjiLmA;Ogj@Ppv+^!%Y>% zHlJ@Dp{6~M&=<3@#f-=~kSv+YGS?V`6-*)4a&?^82h|0AIpU~h3+p&gAi#F^ql`>< zZTu0AdA!VAzLE%oTXA<_J#f)~#mZ)N@1|C`)NFWWXm@sW39}jz#YppsU{w)94&z=d zy-nRUCih};tU6b@99-t|`4FCv_N=J-C|zZyCV=}$5U&$M)T0H2C!729@h1%)li<5HLbf?f`a$j{nuHF*G@SqxB*BnobIkjj?{A4Z zzjY{%f4g44^-a3xtcq#Nj)CXS69>Hrwe6zoYJ0@lbIVTcPLb4C?e}TXr+Q!~M=m!sa}34c`?mI2^NqPc-f;{W>vLj7p$wtCU`z!(NN2z3 z!)Oc+p6A{GBz;iE33{~6HUCnu-se=^9a)4u)C_^K%`{SSZVA^vZ}e}xbKr%ML@t0>^V5l;LMX@vhe zj1R(1Trn4L7rZJL2)(e#Ecwv<2*ub%FerG1vi{5)6PYKp zGJsM9H1;;lZt@U9?P?7j^H~YQ!?L-D0+L!O9Q zZSWXU0r>aF>YO#5+*4Ey10Kbr+DHd)!I*|B-pgffmr%B@@h0?D8r62}nS2HjG_MfV zFA&5(*On{|6nM?5Y?7*^s*nfKe`z79IJKIzrOe*V6Ip4kRj97xPmT3&l0YX4j^d^E z3mhB84@f3r=xMZGIU@0Rlq+Sn zEu%yXzPdq8qvsN1q23$b+-%z#?gz5q#kug!JE|BHPoD=*zj7bvR>1GD(jU9#MLPp0 z&g%|ov@n{sn<_X~%6OiILNA$oq0mPbXqc(P*&;mEjCUM7XLRG^s7?h&^)P2P5nmi9 z(1&yn{^Me3=e|iL&lsMzS7h^E@xkp}Y78>z#h>}CxR&kii!6(p>6xb-NK;{ft`7x? z35)CeoiS5TXe``glM>(qL>jeE&QvcGY_p`@~w8j&dQOJ`WyX}g~XwhY?o7B#m4A)|LzPkmOJ zaTaUbYguHqSH%3zZKcjPy~U)Q9RdK?;T?69!ts%A_r8s7?Nd9Z7V^gktbsFeG^-QS z?wGEGR3jLY+Gy(9XLSnD{Ftz1*9T3cCtupbmP=RJC%kX@bI@GybXY)#9lHjeRgqLoIt&E+#p z8%nSUrNv`W3u!~HjY1Z1yMk`Yl56(wh^cbCS0%{U=U2p!c5jN+c)}^jz4^+Crcr3C z9Y;x@I==xBd58z1M3o|5cZjhU}-MY>Pn}#{+ebXdOxMyl5x$wbWATUi+PbSiGj-#hD^@ zOUuKOn_yz{#I7HhD}qgAn{H~Sp&c3QpHBfV(5!7mNcoV&4mW$9@2Ex16bw_x$!c6B zpTiam4PaZDYU5FBEw9d)?oDVSwq~j)T6q+1)bKq*UnQs6PS4 z*fbz!H7G)DP>(1#iQ^jzWoR@Xoa+rR7k+flC2+}y%rJ*K?3`J(aSq>W9n}-Ss+K5b zOjtK}7*YExTz7v7OJh}997jhaI;u;f-3?QpKop^+T1KQOO6cfm{8@Oh!rkQ{NI zlIbaEG9w`?%fsJ)HPprG}_-tIPh2?O+FOk2;9L=u8u5EW5Xz+A>TqHEh0d z80?7Sct?zC6s3Q7=azh06jam58evO4Rx%9B1&F8JhAe z^C(iclCd~E9b&ID-l_~TT1+;Mq5XMnE61_=RzTbt! z6L)zJ2{N(>GuJ2VULNow9-~>BP z+vz@f^DZ`u>IX$55ln~4yujh1*@SxQ`Du5=i2hp>U%vMhQy34 z(JZYu7cNjTrYf4-%*o|oehzf_uoy`y7=MZhjf@oixlZ?X};#pLvqrA9ZUxYCFciK`<2Fe@qyNbO&;006f#+3+MI% z$%PNps{|>gRGIni1kDpYe<8(lVAIcF8$iKMLOGS=4Y-br$W zqrs*fi>#Xw@ok9Gq+deQDr!63-MvD|-MGWE4Iu<AF52hab~_rlvA>I&N(wZE zszGdk023`5d~1oW(W+hlJi!?@Zm80Q`uop?%q!DS6yK+y;innQW$|=>hD-`|@JChv zzPfv}Bmh!}TdTAovC}P+jx!BDTf@AxY~U-6vD6O#T-y#k``ykPj)XZ|1&1xd`{SVb zG_}uJLPTx)ke(*b4=oBYG;8(xGeJ)&!JtIzhnV30Pgp)1q1E+)@#i6W z)%OE$+wZpZ@E>Ieqxqh-CxmMlk>kria9n^(?T46$MA|)I?=~L>cz_wNC;XE2#x^P? zN#)&d>=aQ9dV1yW7z{Y)JrzwVcHLF@zuJ&Brl1f)P3yn!(c?P)vZuZ3&U1By?C+?e z#cG;aj+^2oD?M4`3NYydz58ADma8)_!_Q?!7*}}q<)z6@c;V7TWe$0^f)bOHfh9NM z>Y6=`#P6r450Bl}dOq@Cd)c3f^#tm1{cCp8rHvu&vt{w&BNgoGO0-b|dVCa83gjlJ zn$2z-6a&KUg7eQ;l$VwaK*FgO$2?+Ii}M`>)=-n!3uIR^sTkma^7Hof!W{Rzvf|?gRB5IDOK zT+`I7f$z@GMd0j*Cu8y@kBAPfvL%&@*o75Ek`=T#7OEq^Fg6Bee8I9}TGdQSpNbM| z9k3{64N%8b0JI{naT&d)&35-h&SX};-87mw3kNvHl`8FXu#GFRz#&o;t48aEa8 zHR1~~X-vRZwGZ}KGw@MP(V?03k1bjiAH=2iqwnec+>mdaqm(pa-d}|9X1clwcdp$Q zDK8O;_~xY-spZg?kcVVDzSn80uR|zPXLDTTIe}qlw6sSv|CQ{bWkZmgUjPh9KOAxQ z5;B+lNf29qHmq&ugxHAnu88Mo99-m5X!<^ACY7(O#}?(ExAG)jbDun;Te0#Ux1;l# z&ei`5q$7(^S6eQVPj(>ERG~|6xUcyBSO1XPIbOy8}VNWA^eUjq;;p2;?x5 zH-G)dJvi(7$b%pyJxaxS6#?N0EwDkR!Yq@#s2ZfH1CY!;=~#5^)|=1xdpL)uzC2xd zHJi`-S6AC{*tWODr}H$3a%jlk{cw&5Hm34mvwnY1 zpMFm&F4XP_krDFj?PT=LjCoXX1})^5#ms zSpw2Z%I$I7qd06v({8KYt{kJXooouf9ah_o(A=LDiq;f8e|4Jk(1&60lxz1zO6R#- z_fhe+@ONmQv^$Hc^JFz;KcSL#2xW0j3MS>an2UBK@_n+zVRt@8(8Xg9`pvC46@ujh z@E_D2+xz}}m#0(rU|dLzDXpqfYfjAQV8(7frq%vD?9iBH<8=dj+T}t{dM6xbgmNPD zh=V+&py(G)aru?ibhnTF$#vPIb8YFDjH!q-AuEu_w=PB`6h)o`LFP(>=Mi(2@_waWcu{0_f6Ut{35~!un*VE zF^%JgaX6|3sh%gFZ=EdPWNAZ|DPGyMHigLg3~CKB-V>bw9x9tllv zcr>7LGwto%_kVVV2R@(ssDEWso(CuXv-&`|u2}y$f^;c0Tr^AD1NK z4gE7#T7~(Y!hr~x6aK%3##0?Ungx~r`TaKrjK=@}9s-D3&}y>B(>h?g zFJ4+^Jl9|}n#k+PoM_7MjA z4*a4uFjFsSv#-LGwa=?b+YwEEk?B;avylp~B2Td=RzNn%z-OOh>DnCpe{O(z%E|8g zMLO#TqTbE}=#2q-A(uVM$VtT?2BRp~`*9QH!$E65{5hVwOIaC<0R8J-as}?6SUx*$ ztzA~l9N70k8^3MyT-L!g_ofSJ3hQ}bWw9r*U2~*#C+5`PG$Qy!{^3K1ZpaKZ_NKS) zKTl2mnK3VXEwqM4nz(OYtGnE|j-u$B_m^K^jjreN;!z2PdgpIx@+{y`k)IGLuf)jG z0^nXEj-p4%07v$4tM@oZjrc7baq^RnReQ^wk5g=#KR2aq&-W>9*{k?qb7#+1V;m>< zdta;xC5g*Bta6)eO_Gn2I?s$-g0UEw$| zr~3Q8yJHWNq~OQP9J{F?T6_H~=XSdt{ncV09^O?uq8rRB_sd%H_C^6wmHD;v^{BzP zEWt=o2+MYJgwMc61!svmXU1I)Fwjh7IFF&>t>lXXSr>pJz}FXs1&qq7`{ts6)qXrj zPhVq?H3kv7hDXw2SA*70y=d2%Hl@x0Oa$+X_u3l9` zV!c=+b7Mw55iwWS%{z%_`aXv)!cnr`J_6RcXj}qmpllKR;_WR@pWa`nMnsMW<62tc zLTo8Og?nV5`%kh)gPC$s8Gm^72ppD1jVil|;J)SaD!m%`7493Fn)+G%Jq^uff( zJMRB_d{ZgQx-scP-1`7Gcpg$V`NNYTafj7RLnBf`ere`tJ*XXQ<*W}nzAw8U{j@TS z^s&bc`%AuZmx<@0WVrNfCbbL*(6#q~qw_5V=fe(0c(_<6jg)}3;C88p3)xXUWKJ9%?Y0^VgW9O9WbJ>t|! z7kJ2^o6XrZ*F4!?E&R(Ke{26ax)a5=4PFHzx3}13Rl6nbU-UAW z<=ajbXA%z~@5|l~Y1R1ER>yPqhY@RQqhxv1Q!zs!NMlu)EVioj+*`aaa}k1&buf0d z9%w39#EIwXQzP!CB+OJ|0w+3>qxoGO#`9+AYo`9hHt&2FM>4`%)9V=|kz)_O-tpvuc}QU0&4ZV8@aRT!nu6Q6 z@4dt-XDIDnGG-KakOe#W|M>sKo?-|oE)QkN~$9Wuk( z(`FgNE=pGrNCJ1ZUiW@_6JCSJ#neY2U)1aOw-=Y0Jh^4OyrY(R_WeYjdchl_hxR*M ziAqo_i*(xX7;snM)XN(Eg2&A6%G&G~dCNOt53a2=ciBaNX%wgD0`qcKbHERnTk;{& zNr=ufmE$INuQh9DBJYa_{Fe;9a<$t7Ol`-t?F!ZhnU_ldH{d}o+AjVGEcZSf6=J}X*hDIV)XYVo8f49h0u`PR^Tv4~pv zqyM&Py%oX5XWD-S^?cHbGg{)ZF{9}#u@M^lw3BlhTreB?F>h=ve`ntZfqGN zA{M6a$(Rk+^~wW?FoQOCNtpKwO>Bd*g~H*Wi$}PYlkMH zp#0nyY&+2w|B{sfS(QYTVM1w~l# zKC=}l2;xKLOQBd~{5X`( zlC)8*#!F*{A1UhZhcAc{6JV#9ZUr}_mL$o`)qh61o2=OvoVon|lJzKJ&z~&- zY0-){IbrOan@BXER8TUfy-#ij8NlPcA)r}y>me0?~v6gQWRm|L36Z&9WGakEw zg35i6a{i!?-&JVLSNsDN0UDYLn+cWCSL#p~k?>I)zToQ~A+=p>^jTZ!GP=P2y41$+ z@54n*`i7{lg*v!3;I)7LlAJ6Er<0!IyUK3&XXgxed5-Uey@_d#g!gfv50gs#hK8ob zvYQn*Ll0l9IpE))^i=QozCxiRXizZ}lb&$$q{}ljO^=`~R8bdiBGRTSS8K+o`JsDN zwU08NO7dNg15O9{jnSOc32tq94$R3>bxW4~&wy;UGt) zpUsVRidr%kMIb~>xs4ND5VQ!h%>B8L@d|vDS+R3I_1KruSfA{fpQt!ie0mNJZyOl#CjJgg;M0= zd0kA@2Ahq`XleeYout`lo2+zu4)XLkB#yK-CjaXl>(-N>UPceQ{}aWjh>FC~!nlIx zH9MmJ<|6Jao7le6V$T)`H2z$fn&5sCOY85C zfw?$d=n9JYzJCHx)AwdcU@L)ToS z!V$&)`$% z2G#!6)&s?^^X3y!rbc_HGtLmQA-!f|I5{`NRWz{iu$gB0tHejXo^oIdm^GXQ5*Z`n zz9k}6F0MxE2;pvbMOx9#QYX2 z?Q}(wHf6PloZES?qNzDoG|g`5)KkT)1`D;8#mGrC&-OK7gTJ6r@WQ&9PaqGUtUV@RhkDp{C6ncTa8dgU!QU5T1-*IB zV3tHr40V7P;nUzgYuKs%UQUl;uol;CCw*}#{@Znb@zUgl$J!GDnO*hgoU_~ay)*&4 z_`Ad-;S`iQWL&$gF0uK?mtn2ffgalUFUGen+KRS>ZhR($oe+{jnQudPqo+!BD7Ei+ z92C=g?l9ANqv#=BVt=ebbtEGC0b}v?4p9FSN%RX$RX#rk)V|_Iha@FTtB<=%Xr-Cl z8D-0jY~bMRDR$l!Mu zI=H^a^;o^MQCb1eTLtol{k8q-0TQy=7(H{012n0&H9e6{+}ryd0y_ui_sY`n(WAKh z((mzX{8CKZUoYQGQKCe?j#{iP`=H%h+{-8C9j$$e29lNO=|^gP0AX-cR|@WeFP|w3 z@r7St*oj9%!~c267W^S<5d+O9$(a2dvKZLO$;smR>Amk|#zr5+3Esu0@69aCv28^O7Bf_O^TnI-7W{$y&ynf%Peqhh&S?GJCeei0Ti8ns1=C#wslC!< z{w%d6X8*4rctTb=k*`qYk^8vE(-Wi{U0BhFS7@wbxQeuDQq_Su z0}pb@Q5F}s-w=+xNo0cT&{5$l;8*N(c?+QN!F_A@PPS3H@j!dV1N5onrnVC6XxW$I z^dAt!;PPd1K&r}aZB(1{D%)Ci9eU>F);KB#4f~at6mzvbBOC0>GTm_tSKoQnd&($t z_&k#7`sf~Y!oDLChECejW_f76=4C-O1ojk}hl%vo*0sGYYS|fXn1FoEuUlbv=0|C! znlSR1F!O%X8vJs!nB8VlZZ4&GYO_|2kB&Re1MjUbeeHjaM&&-x_RNg5)tK0h<$+o& zZ#w#N)NTC!)Y#s4%ix@cHqZD8>EW^c^+fBs!bID?nX~GsHfI1fXzk{0&BV%*$#>5s zQ~iJo0T#adw=5lHSXLUhOm~-P_8kY3H1KR8&wfIzSOXqf;1KRB6PKqv8Rc zaJhi2QU7&y?ot2YncZ!k|Gt|(K_I_g$wbJXH(j34KTI&r`=9JawyylWLtXH{ z$E^PMVog*>*H}0jn6mjd*?^ArfBZ6fM7b_M5bnf*>37yuiiUr$cQ<_0aI4lqb@vIe z-A^1TWXU+B`HQ7Z;V(%1e};Db-{O4#yKVMF@seYS45;%mb~oNHDB9hr&ODTZK4I^b z6Qd77l(69{e3Fl@6Pzo~Lo%tf3mtP*RXF%7?k^vSn72l395$}Dosc>9JU83215}ll zcx8%A9!*62cKLG&*rQ?uJG!?*i5)lhE(M(f1h~d%+Dvf9Ed72SfV%r{%*~(8@NdeI z-cR=wA}qtKOlA+>+)Z9323VAJJ8tRe!dPwehxcYWoN#aBl zl$)t2`#UZDU#@Cu&8$UhSV}K@oLhorr|>0|f;Lq_)fx{?&wXnhq6`Vg^RX1O=PJRi zIw(q9t3|7-2Rw2YUJ(x$^yTe@n${z`Ls~_*?9^H$ZJei6%fQ9B{0S#MRRxDWJ)#6p z4@cQ+z8=|35$+{VnMrz5+P4#&olQdMAFceSaNl&F(p}pmiaB#-XhUKzMNZyT3wLpk z7;&pR3;O#{8xgwpupa`H(d)LTR89CBk7o16?1^Pg?w(^}j*XLJ`vS`cIl_-F)A<7=p>;o zUVZD1Co3nYb>3Hd^E9TOskOzy&HKa*6UZTzCjOvV+cES=0p}hzb5=UPqfMGmryE`g z*SI-L$MQ8|Vc{L6x**iO?gLK@t+F1_>Xba&om z8niU|lsx_W>RR-s))UF&^R_BYKz*=(%=_qoC$BYlbpJ8yN#E;gq_N6}oR)Yp{ETug zF@ccsS-FL1->d}KvTx@{@5fivdd(t~Nzu=G&qstD7Xj(|-ELj-Q9NnCHCfh=5?uJt zdMAj%FmkB}2u@^G;vZMJWOKOlfrp%tF$pVhk?SNk9gV+-Tp3<_n`nlLkubZVc zGj-tlkH7$9Gk;_%mtQ{voK{r``z?hheiDIAR(UA3XzKU8j<2$pJw)G0!JAU=p^^G+ zG4J4peMr7ry>~h$^jiSfQE~)1^Hdp)JSc;AQ}Ds2{wm0YaM%6x@X+74w^mG%A)8{W zn=)2HNecM^)tWT^&DMpq9p=A7g7po^>-g z6bpIDX-za2A|%e!=|T(De8|kYN?ka}l&Tkc zzG>E*^&31GyS|bf$O2v5N-OC3ytm7GWo9-QUK^`z5&boO^g&1y_icSa!uvV}ljp%9 z2gA#sWO~p!@8X+qL@m~CbM~CqH!fxFgE8bE-Y5ObUo7eU$9$SN9~dir1EnllwbH)| zV<7dpCJ`~xJIj$)61{xEA}=4}`9akgoy6Pdr`sO&!)=YJHh7)j$?=NcRXL>oVVj9D zYO++;$D5=xo;R-w-8PFP05_nmR4_wKhM*=tl54-kR{2qeU2i!^%4&HRst?XbJ(_w^ zsxPkMgnR|?HcXhKby-~}Af(6bryMckJ`sbB!4y0p2+GNxg}9H zD|l6(a5ZA+?UW&*S)hDVT{s$5$U$0Q++mn~cW>`%<;f^vs9mf0>s`^K)jS6uXOsZ$ zc0VP(8TY|p#LJrRCRejU+zzxw6=Ko3_^bUtGOU7Ap3BlN*H|eMkXj8=06HUaI^1a( zzuxq|kCX`apKl8oXf;Z1SLSWsvF%pubB1$$z~WJaR|iq)qUJ(lNq@Dq zn@R~m-$T+;;gDV~7UjDS@sDcN-dlA0RPe)B_FMuMkKixe4EVc*(0}3TAzux#%HLZ=0$n&lryzHC(io!MIp#qAT81Kx zwwid9h;e!W*4v}+Ce96IyvN^O)uBd`0G0DZGL(zgB46u7t0n#_;;!5TwJ zw1Eiz;(IKW9jApI8X7r*itn4LGCLA#i&N}BR7&7yvfO?(c2F|&Ut_?-KlGgtd+Z0mE_Xr6qcq4`v zma~|LZiQ*Yoe5aIq{HDI{Ox`0_C}xx?MO*DOyuM-B;laBT3*$H!zHgRR?tZAV<(Vs z#dn#|RmNUCjuhx=v8IYGs59MINIh%QE)=1(i@r0cwmeh0H^$gZoT_k8eWWdXiyNw# zJ~pZ`HZ1?4!64`UE+_6@k~)bDa#xRxvE~WqWX5h!40umRBY{X#kpvCv>MRSqIrc~% zl#fAi^h)sK1P!K;dl~Q)Zo+XRSV0Y54NTu^6LH7Rd1{nD=z0qzJnQ{PSj27RMNeHc zE8Wjwf&kvqgbN~uQ3I6b)n&F~cB^DVf(x-C)U`yVr|XAbe1C4|a|MYb$-?Z~ap(k~ zCsIB?!%R#vHKTr6IMoW-$oA4eaz1X4MJlnizfBl6U5u3LozrRjlB>w(C+yDrhdW;q zJbdDnO<~>I)~nvFVO6q_v_c-?cje#1wg+7Kwp$`}@O_clK6L7Asmx~UPOyTJ$lJdN z=PI$QFxzCrOVq;_Z{&Xrd$T?=f>MYg8}K#?e83kvhJGCjIpv_H*2PbZcOk9kYnE>lBJMKrMc8>wII!h zoELST{bVandy#y8CR(!IPP5-P-pO_Qcv9kYb@O(k` zw}y_s`m_h<{{nWtR{KA}&L8lUYaBX?-{RSeNMB{z3rou^)(=$1o*cIY^f`HS>%oin znDTJL5D10&TJ;RtNmp{TF;&@JUXay*Cq)nu#IC@h5mk_6JbWAsitw2qN~5Vda}-?@ zJMK6G=7*f?O1XZ=R-txJ(3w1RV;fh4u;#~_b{+~?(CMI8RCP$vnP7v((1WH`RBXs)h-*WkTW@dieohwxlhF>}&0D^5DS zG}o7kE%t91mE~JwrPTSEq5$T?3j&pYBNuPjQRIP=t`e)glBKdMdyh6%rp0^9SRtTR zUoX4-F!tSEcwg!(o0yd>KLtgWMfb$2mf`4jfL|mO?=7}e{hsf>!*4K!oc2Gk{!^wr zIu7{w?1Vh2T}RJ?gql$>=ozxS9Nl9xC}AjyH>~5ijvHqSkLvI!4db(3KFJX3We_VC zZC%uT!)m65WfDo*zpUIs1s+@J>-PW*_4X=z1x(TOk_VB7T|(lI2@#Cxrw5gnoZMXU zgEu!ZzY$~*>Yap?r;O?3JbSPBWsR%e%O-1zOYm#$x7mtwio}nq&Kx6IFltH4tdn^& zUE%=3`Ml+j=PX&leW(nV#Z$d=F7geEuB=A zt*ybq|DLU@M8k;u#KMl4FG0T*TQsj^m1QXkB((&%W1msn9$d&ii%2w)6DMDajy#@dP~ex?m$s3{6dcJ#+Cz26s-K(_Aa73vfO{-eFMW>R`%_Ay#O&&vRx zgheOv;bQ+)88`W$Da>!}#O`uNOZ_j9Rjq!N@k+Y^X>ODl7ydhnK@-VWT}1=;1(tIr z&-+(0u>&%zld=%h44#Jccw}aOXCb6*Dlx98MO-=&R1WZ7bF`72tbqqBz6qwxM=nUtlsno= zFDZ!5-xpJH0`wxA1GNiOBTs+a$q5 z2E=S9JW=q&Np^>5{x>?sSmI$cfXLVO4a8z0KhZvmp|Y$b2_+@;tAk>k829y?i#w+; zLxW~CNC+cWzdctnh^HA|8>6^bGQU@Px2nt^2EnkF57NdKqe=-~Roag3JHVkZo6hF1 zTu@aco+;6pR{vHTJzK%EAo>Rhuwt#xGTO)eZ@3V7;?HMXB4EcCLpx?p{bZq2`;9NA zvYMzEbtPraW2LL7BV3L>)1OCtmEj^MFZ?_zGgvK$dF1~#ZPoG3UWixaIOF?LaH6IP za+D>zofz)hfYI;-`QKjNHudPOUw_2q%Hyge<~!{Od%ZHXczbk59fq<`=0u3`w55uj zKsQNFUa3DWNLiwW{z-$x@#%j=gdA7jFjFPW1U8(&$B7dDkrE-;Hv5tXqIDt;+~&=> zXDI|n;I?h0hH^!2J6>|bc4$+uzFA>7ZW!Ruy=2&pHh&oHe(01ms7G1kGJl~K1+dOx z&|woy8(mvnC~-mJFf@`BL+-~vpOepXo+;}3;=a-(w1SWP;#+NGN`aB7_*3i<>OR@P z06;i7bn;oLG6>b7Xg6ee-0wef`wQZ0;bWm#p`(XP!zQs$tFM1}URQLUI#C$M%LX0O zUMw5sA{uLx)FaM9y-Xk_LeSBjdlY07lHV%~a@rYV*{@RkqyB(XN0ROiA-3AX(H`Kf zpo}qXBYjyRtPx6IlAEz#E!u4b zx%tLeoNL}0(A~-+t^{(G_E;}dQb;q>U=o?Q36M!7vpKo9kXX0bLB65!eX74mWSB!h zJo_!hr-@GE7MC$dK}NSP&bD!|OlNrKA`XFI!+M8-%dEa(djMaOW-7L_dcD=+Tf?X2 zPoWMdqrF0Fw@}JXUJqvKv#&DRyF^0hdNAU^V}37fj0^E}BD(N0zwtJIb=I|`n&rG-CBYBqqgm^EWO(9kn!zaeg9{n<8S5>sOb_s>T|GGHusQnS?? zgUX)k<$*$3q(%9jCv7{4d&(}WCwbq^OhqK;n&tmxizBx;W=+sYtxtsF8fUtx3O;f8 zxn4QSsNG(2Iy%XqrTnhFZxW-tRpv2*e*}Y#^Yvl>7U}u?TO_!6#Ed!$-IJYsDiQ0q zNB(2!#OoIk3>?MXa&R0Jd|w7fL@SN|-d)%wM^z>;U-?QFJhb)P1oSu(^GBSR*f_)} zvU}2`X=aV_zf)W&n<)Q>|D%F)=$C47N2yK|g0Nn)OM(AF+x-_^VxhYp9s>K)rAW^6 zNB`a@yLXAH3;p$brk+m;#tPaxDt-!uxR$FvtoV(~{?;3V9t7tV_qUC&$>rw3Pf>z* zyh|b~v8<3=MpnqkD<_Y?sPA0@9X-A2OljS-%OfAEy*;<hrn1IFf2``b?9089bG3wB@)icLgFkxZTtNp zpQ#>y+m=NuQi`>TaHb9f^0N49_|s9b&Oej#&c@PfralM{!Fzyr~SDqoYi)>rDID%!o6(& zI~1S8?0|(2%}UY}eD|NrMLN?|7|RQ0Wu#~b69%(=FL1JRQ^Zs?uqyBsHgb%W&qhlQ z%9n8v2+al(zj#c1$_21xUCQuhX-;fIc=I4-ycP|U_5VyrpYLQW@iAQMC258uR#uR< zgN?X_M*fd6to}*&p)7E~N|z^@s#FbthLq!qxQo`E(JoQFDLO6x!ey14Fa*&*Zi|QgeNd?h7lKuJtsf2EC;-bL%+i(vs)-GCsZSn$Y;jfq+Y7P#y~kCrx41)?n<3^*%TOz+=Xrcy&3{cN(AgNiNb?Ux zea)7jD{2}q)`Dukz9bUzrsI}nOY1>lR~+A=79{_^u3*XrGJEn8ZITB_Pfa9}pr1a}(0+6)+~ zn&`abq76{n!^!9seG-ggAh!bNxtIgq?111KoEuSD>2&a;cV2H965jdK(MjFtKbqsa zytIS_C2)5aA-6U0Nw*;S*N^WD;d9W;tnehkrMl|_PxxfpyuX=r;)uweNwtvGy^$8Y zk(0cr!C>e>6rJ#<_JmM7|J4+wI^Is5<37=f)BKokV{v;fPd85*bx+3S;{Xa*nO@j; zUrNSZ#f`a}b2#)Z zeE<<$w}1$C9%=rpm&f1cW`!ThK!k)>an2DGEaY&`fsT(^Y*jyrx2p-T zItorK0z^M_k_$V&^#kOF?FKeL7j69J4R;^TjB}cB{;lA~{vUp%vMMoRH+-Eyb*|*~ zbMh}G+2|9VMpKxP(=EhL{Ecl+KecBiLG-1w9V4S&vS zaM($F$(aFr>RP#(bCr9Vw<$jC8EMg%1!XS!Uacz%K}`)`SjSAQ7YepP3lR~bM7EaX zjf{1fzVAQBcR5(R$ILl@-Li7ae*qD6I~~3on-%gB^GTGKI$zg;a?rujOlRZTBf{>R z$#waXeeOm2;catP&fe#CIE$*jB!3f;f|uA}@_bqvV=Kr5U~yi)u+$>G@7QYqb+(2e z+jMs)xsVdc@9|vGi(duRY#pO6soemD^>1(D-ZqOw4cQ-xZQr;Wc5WexXcNOs1Jaid zNw12z1VcLP_av`$YFv&KPdHl;{{GvJLw7klW+kz#L)x=;Qf z^$)eJmWme7!LUvNsw`(<9Hdghrd`44U-R>^jOwUeKJBzG2p+Nh;?vNDZcZ`Am6+?A z#tPIklL>QV=7ZbM9Z?=(K9usAmi4Z^3r85IJZ>W^KZM*3Sc1x{jYs3g{QFXVvRicf z;q!vNd~{vY9&}j7R(tOzFx{l`7Cx%#6s3)}D2E>b_PDyl?mRF7H)Vzy{@~o4HOr~5 z+=6@-SofUB;xM{sLcbSK~^yC&Q-C z$96M*GyK{3E@=}QD~OOGl1yYUth^Y(OuU@21j7~0Kw#c@xm(6y(~y|x5qGS>Z{iyrz? z^IO0ga+q; zjbkF|$-|j7;+bZaj7sC<->mRfLl^`AYdy#)-Ib5QL=2IwX>HL`x4BNAp}ymW6IZ18 zr$;*b00`ap;0_qjkfZl zu)T75i+yj!*S8DZEc7PXTiV2>iRDfBMhTDFE<|a;cGu@$164{<*le&j_7jTvw=n z24Ugbp>P^%wYHw_Y)3DNc6_a3U2l5okFxYyVZw2pUjtb3fLCP9CTblvh_g?ZVjnKV>x|<;hjJ$9Vo; z3L~iBOoJloyD)B9@XVTllIJ(Df~ndfxdF>4KM# zql8N&6@H2pBT(&SuO|w1oohMw-iI30<*D|is+H57Xrpi2z;PHbpxnc*3t{ij=UUNq zLV=nIMMkbnyy3XSMNwBoYfbnou13p-3%1_R;E{^otKZ)<>&?*!_#elHoc-A|J2DL3 z4I?HX%WgBM)<`&bH_20wPn_>f>tKmDj%;MFG%-xxh>Nrx>E>poV`PxD-H5{SeIS&4 z-ZgPvj{P8fxnkoi8Ya?P(i)76(O$_5ZS1fm8;rzcLi64WEoV?kRM`wf?wG$rcyGJn zlT#0pzQ^Q&g8W(<>d6B>l7@V-Q!GyRfcQ{1QAY#Tto= zcdr!a*Y2En>V%K)1V&6B##$UfVJ;D~BI)w>0%1xTg44STH8)Qg5dfi2Ofs~bFumih zbE|Hnlo5Y?@CfxPL&BW5a%Rb!&o}5Snyb!W)8HC#Z@}gODSERr8-~%(g`#uTb*;@O4FY2JByZvY&W#eSuYwM&g0sSH+eJgDx^Ub4jT@3s#fj`JzTIGNg4-z?Rd#F z9G@vBT$8Boo$jpM?J$kKM*btXOrsb}(L1L%5WF(D%h)Ug;}z}fC|z4myHCsHO2cOX zq{Z#hPHr|HwAE=*)?W)mAG;x*85dRgDm@FYJ1q(6FI50~H_7z=4Qn6y4|_lGWT4{< zj}hTNKAgngluvd(F1nf^s5>ksW~v~|zqCFHc(?2RQs##>fq1;!s<%c&^srGt)50ON z^`P4$qeZ0YcH2tAc*C>%$wEYuf{E~o(&etX#7#AN?=cn~{M6z;$ zkS#}i40HNOlj1 zB2EVMN4OrUM2y-kePR_z&;eY2^OCsZbe5!#2M#B2(jCnOCKtMLjK2ERXew{k0yycg z9&Gx4QcyGL@d#x6d~Kl5BdRS_B3(d~SyEC*t%3!H=zw50mAgYsY zM2|V3#mTB?c44OSa6><1BhSHUW=S0JP6-ayNYUnH%ZEbBC;ca25@;RVK@#08@*rYa`@1}TA4mUt)?88Kct4f**Olq$nS?|`O z#~Yj6-c}j|@5b4cCNlLmKTrt=U81cKS#H3rzF>l47`2{6RcbH1CL&90%ize zY&`>ITvr=k_f-XVQM6I!ZZz)>*$T+4N{La`yW8^28~Rd@Y4*>x=;*4pUw4u(SX~IQ z@&-JDqnusn5RpgKx*uqk!iy7f-#w$S(cG;B%o|U}*vYcm$u9ZGYC=)fMV)z9tu6_o(|bLlZkN0ve-5=*0X7$YfuCsV}gJbykSt|5x&g7dp=|2Zw1P&Z_n6@3Rk4Vxc4k9;ofXk{#xBW%l0t@}`o0bWwbUzi*AHCCh zPd#q>G#ux3+1)aK3?o$k?mRH88Rt+wfr~>^OOA(~>>wXUiYANtVs!R+!kB~s8e8{ehFP=oSnq*zVWUapE)cN zA-IxMGO>#$+N({GQwT zWW94y^=O%c1?%0h2b~>*6pAX*6l5Kb3JKGQCu*^R7k7BV?66-*{Qb=83EOp9BD_jP zm&E^>VgV)|=yPvlufg5zJ$N5Y#@dTqII|EZ!fa~)*W;JBfowc+gf4Q;XD--3EOIhG zBI~q$L6P*w{}&KiC>l`+F5g(FRQ9s^U|B8HN^=BijiQay?XUkvm!VOiMs3c8kuDbr>7s)!AKn>b%t8eOfKRv%6mz zxCmgTP*9?w|LS>7XL$d8{AHJa-x9gmV&!5bde$d?KeDIW1=MW$U>#PY!K*x```P_j z$16ueKgcuPYdd+(<+V$n?;eW<{hALyq&;EWP*yTr-p{E{S&{j+)NEF`O%GmI>+D?`udCbI5AQ|0Z)@LeY3(e;+r z`#U7UTCN9!8N^RQ$BLxhHg7Mq@Nwc0lFdLCgPXvr87AYk5~w4v%Ynmj)3+W~E__IS zSWhI4-Ke|2>XFoBeX8nVqWd#;jp!NSg*=7L3E&J=uz$P&!|b=#(t-RbneLye9k9;w_$bB@niVB?HJ zNhT5}h_v(A17K!wxk1BlQCg;J1Fr#f;vR-$9|5u)z`GUTQI~b?dKXda{%i({4)ve5 z0+&9RPRN(im`0b>pl-pW{78cv8_=K)S$T>~56g=2x(EHjhIc^|`VWwC6AHe6Ps0g_ z<8K*D0D~-g;1hvd`r~ocgXt%lkvd=f>qo(6YXX?Zt&E(DR$|Uc&YvwYfCaJs4uXuT z(=`4l6L4bkszO_Ho$p^t{6bOM{{rJU{U;3|7oXE@E~XOXH)0pS^l=4E?9VSv*^?W} z4W>isc|EpR9IQ+JYgLV21XUG~8;9IV%axS;u}Quw;mAJ0$aP#Z`7Ky=avy0^w+<*vsrO;eD#f^rsU9z6a?_$9h!gbZ=lym zeGS-QUISdQF(59x z75s^epLHZH?Xwr+HZ+*wPV-gt<3BQj%W?joAGFXVL* z^!>!LL7oQ~#x}1CCULv5N#KV8{PnbDuJa|C3^hKsDjpTqLM4@*`iwZ($d+^L%ncvx z`$vrG(k10x=+27&^&Bed@e}7VYtPfZfEnY2I|Tgz{et|Fh6O$ta& z%#<>|GB=SRxyqTIGxlk}J3qkW7Ku|nzTwTYwGrIboANq&jgXX`+|dLak2>{81LARR z#}Ktm3I0JslRp8($cboE7gKR+gklN=xC&LN(q7>po}NQkFIG1RG@yX+Wmb`Nf$bOX zM6XCKvFh(GI@$p1HTwPv5~I?~=Xub$myv}2;Jp=rLW*4>|Cbs@-I>qPK{GFw|F=+}o1Gz?C|ZihSroS)BPbi~3gt9o~N z4SM9&~Rq|4{{L`U+{THBs!I|v%86Ha~Sk-C@rJ z^LvReip__GQq(U2jz5fz-t1U{QmvP>$-CIYF8BKCR&`ZqDb23F$-cQg)i8XtrtzXU zxW637!fAVG-gE6bwe@bU8QG7khU9^ii@1u=SCvJ>)G%x%f#8Tyn;DoA}+a-TZTOZ=xY$pVg zcUm-woM~ihK7n<03xl{0eO@E3?GKXGW!JBF^)J}RdYg=pW}(8doJz+%YiNv^mASxh zWuxsysDB%+>}<1#2#s1npVLDXRP1oJkYPJYtM1FrypYq-K{V^igXQL!9RBHy2HMS5 z{g|iMHR~ff!&3-Ro=9F}8tW$bgq7w}Q2$@v=g0z^Y#4FRRj`6p4UWS|L2-KbWj#6}|r~_=Fcq>KhYfZ+|MIF>DPqyBnK>_dDuzQDkZL)+K=LG53_{cC* zD4TUxX{aG16Wqw4F``hTFk4A?3U5mAsp{aVaTFG~JcO5AMiJ!Kexm4lIPD9tCgP=9 z5Wla(mGC@FeLK1uAkY(~b-wQ56-@0_89l!q9$+xwG-7n#Z=lRs!#mW9zIa968f0&o)KteBE-UR|c;3Cld*YUPN= zfWThKdYXm5F2eyXgRdUHxVzHdLcqHt%SOeGn!I<}ey_D2>=1XKz;TrwrXTl-Cp7SZ zn-v~p+dBj7AG~_~)!oVbYekYIOrW z*}l`a>WYj@j=0dB9m)8CK+BxbQYd&mw?zxHY&LMsG8@R8BHy-E%&J|_@@91@otB#~ z_rO6YrW|K&Ga+lRR;Uc`{#qc9^I9g<%3N-3@Pg-^0mrpS)^g2iUiK5n2|9g&^6n|5 z+Y$;1-Lh%jywXWVToxpI$>7@lRj_7HZsV7S=XKZOR!WUj5Cfx*YU?)WEHO zY^oJm9i0QUycRBYDD@VT(P$#ID6R0=@I(~W;Q5GQb24?2Ib--I|AF}x*lE~!%yR{^ z-iNpQ!oIJCI{>}47-{IIdTw*o)ov`~eEha3P0Ny3c_{Hw_r&io*!qcN>G^i zPTLAQig^1{A+tAnN*7+QG)cU4V`G?0xE#u^Tnto^o~(3a^H{qV=sOqx%#l=#s{)B& z+|wG+W3+tSPTM+0$` z>mL;6jmzn_^45QZS7MIINX#i-&U-&rWP(BIdMkp7E@@~0KgMF_0XZg%hdd&Fwg8Ev zycHE6?1LL1*or$lYB!^~XN~vJn6CgJS1lo0&9dOM{Y4cy4|w;fZu+S)D#l{Hbj41; zs0HoFL2ge05hGjq2*+V77S(5}%pY-*IfqQWMDgHVe@XOb*NnVVe5IW6%31-%EVJrI z6u%xSL$58h^LE3Ze)HG)n^4f{)_RIwDYeq|xovNL|7Mzoy|st`P`D3;Hcza<~)k+}xH)j@Qcd&++?1EWle z6|+?=&_lMO$@<1?@f3-Q>~<*ZiDJA8;Um}l?m9&`xbx_I#pdxIVv(w&+*!42C)By; z^Q+nE=OI?X98$@r(aMo&`q3{Rlinp9<;ID5yXek^Wr#-Ww@~+9`_e>ausISiTDuto zXl(RQ%3V!hn(TvbZUQxS{-~y`cvEh0>y0Veya4E-Pc6RGh2((GeK!3U!y_SEGwO+7 z6N|vk^F{K%Cp&n%COUG~cE`y|Lf zP7?;p+WIHV{)|Lj|3?74TzN2!Gj3;GSo3s}7Ti#OI4}wy1t^!e-N9vF1DNmYoLqQL zNQDbrEiHXz{87fqcoNa?{x(pvN9qK~x^UV>?Zy9AHLr1IeV)@q(3;UD_;TEJ z7)aq!FgD;a7cc*A&kE~?-#Vtocy=F6SwT*jHbiJ{%l;!Cpl2ASz1iB1!PjP3=jjDM2u* zEHjxc%vV8~Rv6pzDpL`zJew22p;kj=Hyhb-U9BNxRm_qrnppj!AryHpRq536;$Ja# z)up)9@^_0pF$$G->JhRQC8AACO(K zmIJD3{u#|v=mQmCB0XoD9@`ocyJB&5NC2HK52@7Vbgfih&tqskzv%W!y6^T0E6F1H zIkKBGV%}1i;M3C=Jq*5C5puqecr7h71~4K3Oo~)egfOO65j}ooKzhi55V4x18@HJv(` zhj&=&L>r=DGQQeexCRYdBd6G z!g~w(hZd;xTt}_=DHkPd#`d;Rt4ukRGoMn$^jRx~mxDja@ z&ngqeoG7E}Xmm1Pu#-1=zqGcjUNs>f&*^D=^{WvgqK@Xi&M6kX7!-P{mV)lO_bXxo z=t98bc<2t3{?jdB>O^+xq)x3aM3kNN2_OAVnE>K#peJTr}k(5%SfDg%higm>hhn+0( zw|!!_qrU8UTOo`b7e*tqG>+{@ErMh#_toJUm-S zCtaa$noFzi?SZd=G5^d;8qU2tmBaNIRw{ldWL+G=)CtAJE^Bx@ zrg#4Occ-|nhNsxD)=iR~p`FvktUmt3bI#U{DXuj_fway-Ij%1%xg)Frqu>0R&oiEF zUWBnZYC6Oox=^KPqCsX+2K;UQfNiTwCmiu;X}&#>INpt^={sk&76SQuaNjHVX>pvF zUZmD;D3-ad+#ZOFZ@g|^KXJYxAN&?ay8Cz@<}x_zSDK;QzZqfV1Y2c2e{3IG#jhHr zcF8ksTMsTbqZt^{5r`rKcVz8~7|LXS?JSbl$D+GU+j)-o)W>#>hpm?v9JCQ?%paYu5OJM#Di;ahu{vuEd=*Kg1fsD3MV)O zcc+4d;O_1Y!JWb#3b#U-gI$BY_WI_U-~8r$@esmabwh;b z0`2yfys2iKi~an(7Py2vg7dcA_<7q%$oXg_k`*ohCYeo3(szf3nN3^AqR|`krKvd< zM@cZ6dR!#-@KxHW&SH8vs7$B@GmF6wthv$e3!QK8OQib77a{5wkkY(5p!Fh@jrHOi z2q1HhKHMXnAZ5!`Qr&R=iQ$t`_@dLVGJ_L|#Gr>2a1X6V?X@!x`_9S>OOdJg%$U)FF|xVLQWt;XDd4d*0dgx7C1K&@dS zbY$IxDKAOL3z23z%LHGOdwyElNS91Xq~zy~^8HTQS>@ zB}@rK6GmM@7zFsBkcr-A2(RgH*N4pMcr!4%sa&|hzx#bww|FGem-$)EMMvMaPGSB< zJmP#7`-k~qWcBpG;{YFkeTG$X2GCj^eX(AIuUQdrPqWn|GOji@Ak7>X>3$c-Z!NO^ zM;C1Blo_1(2I|+v+H6Z}*&w;a0*pm8HqU%t>$9tr-z_)Lk1Kqq0KNU+s>poN z6us(?JgRkEFO6I3&mOiGH^0>UFJy=E)k?*Bcp#HUgKl3C0c!jzH+)ZGYo1%^(Iqt{ z_%HU#I^oBE|LLHTtXD_uU&CE{StI^+2|4?8?H;FuYlKZ@(qVv{*Q4-;Ax1fhaj*+<&tJsya5rfu9)_aiSZB(A6o3#VFwN8q{ z96R6&zx8qDO{4)Xc3C}J;nSsUw7pum<(UgC<)XpL_`Py;VdA$)+BZ{>-k$xbTpnE2 z??c&wasJ@8enC;@pKvnPE_gAk?(_%LMunp_W*w6if{q04@mU=FO_Z3iUpsMy9wvNbqb9b>{BBJ&2bLRe^F2%N z?$A$D+u8Oq=dyN_KB_CdL^ovnhCBE%YJ>FijhUkP4*1X)8yL8`^4>CM^u>T$dzi?h zEX+oc{vtbjt#Q-c1k;!%M86F~C))f@=24qtxkHN>)MroO zciClkkc6g;UAfaNZ#xi*UMz$zYPwA2p^Leq&D!_ri+ZfFp$XvR&aXY{DboOU`$lof zQpq)azh1m;lyAJ+7m!%+)G@PrUeW!DK``1%0JozvZ8cF_=Yu$9HD86h6BxU&l7o8B zQ2(s1CU{0=-_-bKtU6aBeyV8l5R>(IKE;P??nXq$riYOCI?o}denxiK{N@Ti@rzZL zf1%#km_;oOi(~h{XHjH33I@m9b$6_j!l8_wvGFRF9ygaQ6MFcYY}9hMIi7b)__t;{ z&Ku-`n-JSD^%Di4iB6pE4Vsuh+P!$=Z9w}K{}Z_o`}+(&Xsfc@d=KR981HD`7z`8c z58fic6&LOl11E0Y4z9p|sc_bWt&)-NO|o~s%a`wj_@=m=9C0zAF;4F+z%sPd*?eM6 zxJ#vLx{KuEJ2_t7?_fs|LylT*_-S03RL@iFBEN_C@;()sOAayc{gRulJkbYj9f3L} z8btXt4pRb@O|yq2Jd5tU6h}{BdnVwPmpS^4M6v76nG!A{;xDJO@T*@5s7#^GFCDCf zAhdbMAv<6-MYcp)U`&pVB+j21gM)_JX&^f;k}vwx$IT33rXO+<$unUeHTkmH+Ec}S z2~=whF`uMMsos6u;j#OL&jQINxD2_n*#52>X2#{bjVk9)!H^Z{tb;_97iBd~l>|jU zWZ8Fak=5g|ceC@$d?yS#Zs~fi{P0QZe`sdRjZ|b(d4sVMoRR!xw3o*9%!mxSW1$o1 z(P5{Szy7eZ{-B+KUMr7*DF2h=u7!rUv=Pl^;Oqn-&p;`46Jx;TeZKUgQEaPO;?+#y zsQ(>2W9vk#v?$cNZVwqPG~SxeN9{*@@oHCZpXN=$fO`%9g49%FugR%Z=x(vUnbLP zA~+QoyBRJ{&~DsQg>rd02=RdG)}7lff3mrsxquTRN+ZOAq4>4*Jr6pxaS)kiI*_5tT|`KFTRx}(GR3jqY+cE0t*anx|9p*%@{Cprg}rn39PSH=GD*73Zu zl+nigRPF{qKl&8+jc+l5j>At-eDXCG=3n|v)e>_?Xq73hVVu{_x34oaB^D96>$?-C zXI-}sO~qr2HBRvLfRlam<)u>>6aqm*zL8C6t&>}m3S?-bH3EdF;U~3N()@qJmI>j%qKFHg+?uggR~NZpoi?xclON>jv(0ibNPzPp83uH3}-0PoLn&_ zk8ZcoiI`6K4otl(!5uJg;vGog*A=?JYA50g%x!w|I4H4yY>{SJx@n5od(r-wnyH`) zb$+bUdebE#S6_2*7oauDh**@Z9~}7d1P4iyK=PS<7p`ZB5RX!^kP`2_X(i&pEl&1Svj9ID~n?_g_LBwUi~Tv$MHd9KM5#CHwG*mcIWWh zjgMQ^-oj&T^2?`k-m#pvKZ_wSuRep8L-~8$pC^?GJNQ!K*P4Tu<^0eEUX9go{T)QdS$r=Lglx%HUCZfiS*1s*F}!M9%_i@jg1ZT1Wlp6_5?N?Z3; zD)k>6coI#8-sM1#h=?d-=R4hcLt=K_YQ#l~(BYoy~2QjEP7jad$|t^7^)PQ{6OT zxhNRvwMpuFZb|(hZ%E!b_QNC7L{`Vsx_~}gb1!GJ#(<-lfJGWy9QqO0~nr;t=m~&_;CEi0tpmJN;Pwren;a z?RKa4K{i8|hB$eAYnnH-+L{*;4yQTPHh;Y9>Ns`$_?CR{q}u3M>eVpGB(a~zMe5*v z2)d3^LA0J_n(FSgrBCzMBJt<_oXByP;y=T6euy+&cV{PY8H?HP-vN4Cyx-@!Hqg`f z``dm{KdOIkO4buPW^&nsWAXe;g<0lc@ZdE>XIE=dG4u2AOb)1~R8_h;N!BzEt@(F> zy+~e2Bn`-l@y}WpE7hS9thmyM5bBw_zw)y|Tx=Pd*r5)$Eq0zAme?B6tYvQRmtQK%YPk%xCht7IPLYdEmj!yBaFn!7y1oUn&BQSl+oBwFVdqmyZ*FaqYsJX_+#P` z|NKeL{A^=6kH^#gi_F>};Lgx<$o{j`#|CE2j9($PJ}&ddyMCAKDVY$qQ%@6SqZXW| zhc4-+J@84&rPf&96{+I{ITP5VsEJde`-BQ{$QE%dM|I3Kp?UY zS8%FKZMgXa*_n{vROnA9Lw1V%H$sW2_=QyaNa(bjTM0Hc!C**fnm{nTn2*4zjtzu} zbwW2Dd!XV>A+-KE4fD9Hzi+`WrKC{)kL5CD29NpA^$^+=M+=1sfBRg=B z^5p3vR^b|N3}34KKEerz3MHo{_`R)xEROwlbU->&9azZ(B7BC8{UJJ3+Y zt$=G*2c}KOKbwuJ@qZ#|0{&NBzIz26{qnCyEo%%Ie1DBT-7x-la}+NVYd+E%YCCo$ zFWEY(r;5to;IJuz@Y1iWq2KnZd{UY8a3YcZ?L>m>CD|2iW=_%)9Zh}n9i9*qg)t09 zjN&RtLQWw6)(gxJCeKL-g6qlpHDSRr-<|1lvt|L#dOR-$t!n&_l+a$~|IQh|3y1kn z95|Nfe+QCp(*1Yf_Tzs?kcR>PJDK|&=fAVceg8XD`+xb(HZ6zxm+Hd{tyus4x(Hc@P(Z(Xo3Lngd(zl=Z9UPRAuIfr>&SM3xn7 zQ}|dSo%(!bE%Y*C@MB>^q3u{mNgDZAEc$F<>rrscWhdDM@wski>{4s zkueU30Edma9QSSRO9u&O$XY{dUs%nXl2T7{>iEw;_4<1KNyCw=H;OK>_Zewkm4v+r z$5)Npz*fjjVCM3M`&eoHZCsEbaT@foy%d#4i; zg4APup-@7$(!755bPT5zQk^6 zT+&L>uPS$hMf79j>gW=nD-%jKrIp^hiGarplyl(umf0OQ;WN3KMfH{%e+Z?NF^O)S z@Z#4L99zmJ;p>dLHv_#`C+${WT_^_)F0e)I#!FD(qa3>tl-{v6VNg!mA-VE%jJT;( zpX2yG+z1xm_$sa7aR&u)SWN%?EDZzOrJ?enZ(MDg74j{>o9z^fcWQ52>C+v@QMOkW zCk_Rs#>G4AkjQtfdc>J-7}>d~$Q^!Zb~XS~LOC8YW+{^Ml;@~%QdDd8wSi(u;wmU= zYpSR6*3?gVsVlrMa-LEYl;S@peH09AL!f;e%uNkC8{+JgK_mV>wALKP{gZZ661iJc z9L3cP`VgKpQ2r;M-ogVkW4hH5oD|mq`a8Co@@EWUA50-{gb5HIcEbiWq^G6nw9eJL zk^lT>VUxW(<_<`xKS|mA*siC03(e#=*kQN(Gh}LQ$4L1BS;TjTTVz?i%1_A_tBucO zxG9sTk*O-jtr(f}?tJ9d<0;__vJVL#Opb=g<>}KK!4UmXk37$*@sk2}A9(VP3&w~k zrsz}?>Qdf>ip>54C!S6U^T(`Kku}p>Kk!y@3eTqCuzpPg;pj|BAy-ZmTI4&{=e-Qw zNXbbH496XmB6kkN183v}x)>A93U}ibo??`mg@>m%k2a^s$hT;{#eGF;xbGHQo`os_V9YzlE{e3= z>PR89CZTHCrfc^#{R4({yp8Z^R`A|R15Fb_OxDC|nt{N;Ok}pN3r_MYrDyMKBdpxL z(}t&aeRMC7H!#Qzz4UPP%jx-MWEizjlPJx|n$-^z!LC4uT+qRjBLQBjzCr*}*n!*+ z6&1f=%g_B&GevchICC`6UV1&6v+!S%zxby`+^$R6hW7$jQCe#7aNgYfR+5Nmj{bJI ztac{qHdNjM)DPYyO)Xf=FPz29nn{@a z?2zYmMPmO1U`&D(@<&hGHxg^4qBzuHWb`PuY;!1d^!-?Gwva6nvKW89?D< zv5s&VVlDsKSlKM=#Zvg$;6VcXbX{XjKRjO0Yogj*h>U``FOZg2!}dcb*5AzI{LZ#< z*_D=IRH$}%Hg1rA{-&GslROJLOs)Wj>&4d~jg|hMEsokc|AeuGot@Jh@G>lid? z!}og9dc9-*eY&@2*vKq_l{wRmTi+AHs{PIGEvL8MKRe&b6bGVxLTCDuJU(UnuN5Js zFyOv|peZ@xaeDI_S%oBK*An*uVFzy^f!1+ykl@&y2e{@($L8=W=y#4Tq=A^PX@oG7 z+fd|1S7p@^Uy3688Y7|F63zSy&hvRAMxuE$oOC87t3`byFLhNuyIVJTD7%!3c|{`o z94X9lB*tu4LDaanqk2>X`lEQP#(a05AJW zLsQg&5_b(VU<-%cIf9tL7Uy+Y#FS?U4*KpMo+TSUy1bsao|i8R;jN|!%HOK!KLBOx-cCwP&q*IldCLRMLX9t(XNsUA2gBeG_R z6_%pfzMYe1eringTe)~U62TG>&$bb_Xffq`EFtAnncW8|{7unYml0zj+G#^vY{k2Q zN0v5+p&?;_@NP+V(a|!}1v)PPi4CXz;+>KoSlwSykBS>Szo>0f*o>-2e?@ zaek*9V65~9-9Wn%{*DM!u15bdHP=$O8l>*qm&e;Nh|!mm>3$+UN`M<)a*O1Oq1k;~ zrxKaYo+*Qg8uKbbR7#`^b9oXHu}y)P~K{Q+U3rlCakC|V3? zWOfgYuH2f~>R!K-LV!O_Q&2Nm43hBExeqtRr4Jm6X`*EahXcf%zB5hrIM!-GkFnZd zx(mp>a%M(7KEXy>g8WG9NMF?|AP~#pTZNv%J4NV3bT#3H0;3PR2!9LwU4_BE-Ytr` z%<-)_OVIKc-@N5?LZu;WsqszeUFLTp6mPRHb|4uu#h#)=m4T_LQe$KdAH}4Bfa0j* zMHPJj+{ajAX`d$#F3pB^k`c$>bpYOgp5|$$t`IsOnh2gyF`39xMY>e$KbO=hr2twojS_=v~EHl@4vCls*_n27sV)Ae*O^o=K z6EH0VOWSCe7c@h{Lst@emTijh7Hn=LJOLQpozio>ms-g>5oR9rYjMLrbtkYcpL@D1 zhRUldhk2@vO;%f%b?tTgC;c4USoH>rh4s&HtE|-o^gA6Jk&xbZu7&6KHgh=xSYAI{ z)h}K0_SHNiT@-mbfBWa5@Z*&=ew^#(ghoBS>Dgi;zG>^rpIc*lU#$CtjL`mh3D7b~gbIJ`*^p=2)mF?ZTnJ8$2Xg-8YJb1QaqrMg5{*E4&<-0UWt6=Vml^jM=yoSm6I zY5y?ISWw>@4#aX8)+90}F_Ch>Rni6N77oF{vCjYuLY<+ty^6B8{dVLjeTm((P`cd5Ws}0$71jm*a zDUUuKw9;1WlbeiJd(V;$=kf%|2A%iR5Vn$@mD%di6sjgRK={q>>e2bB@N^?XAP)oc zLQRJcaKLL_XBoAVERw0xo}@ss00QP3k)y9muT1$*oh;*xts7=wX@DZ$I9bB7%|8(p zoDPem=2?Im$#1m<^B1er5JmuZ<{U(SfEhZr9xs*hG`?8$>-j=6lmN{%Bx&#rlYGW9 zMMZmxm&~IF5c>{zenC(h1HZ+7LhURr>Xl|!*|L9EWdJv08h?8agA7P9l5dVZ701RH zDl3hjwe_=MS*+>_Bjr!K+lGTlV9g)tOe)pM_A~9^R=a~L#FF~9j36!iRCi#q2r*tD zd1D6)cn3Z3wl+;uy#_D!JKB-VC3=p5s|CWf^G5Y|8TpAq9vc+Gwa@!;e3AB~Sp?=- zMMrKV=es{Es(w|+e@DhaK~Wxd(dDo}y7qO*n4GzJMXyPUD>i7)7x%@7#lS3tjX0wP zdRx<3#ZjP2*`dvG))?#-A`(j1kIM2xe)g~r!Bu}s3e`aVHJO&-Zk4?rs|acUg3|63 z$EqdqAuaPOw$t;Z6+Slf;L>Wzd5aQQ*}LW%gA{NmG{@qZ#$S>D$<7~(MAj7Zt?hzL zIYwlxe-~05U%&FYxZTr%k&jhonaK73w$2~ zP}yOS6!_BIvW`6ZEjKkwMx z!tpT^lLNm45`8|d&;Ulk91gp1bj`7?6nmn*5uJ`%U?W!ys6p%UMdsn%F@8^>?g9Wjc3}qrN+g#$6ZHZU8HtzN@C+jNoRBn zwcFB56Hg?fjw5T1Xs$Yp7-?T;s>#iOpbu-xG@)w_xIA{ui7M50#OB7zwkP9x;3V;1 zJb6x%2qtNBMnLz9A5?T0CGtY`K@o(mm++ePtENwTcy5oGG(4BGdMObVHg7hU109ak zr%Ir>GOkADYzyE0hK@KKvswHyz0%L(+~J;ZU%1lM6t2e)ZZ9OvN|5Ha&t2}r%)CMN z)9Xkm-l}rpO0S`Lakf2%B)lSeQ1a}EKD@31t=QMsSMS{!25`|KBW&(4eW z#V6{PHNT(}t-24m!3H9I<7I+pn2MJ3zKv~6vXF_q?YHDtagGK&lEl0!YB&;xE$=>3 zk<9G=jJ-Y=H_cb$`3*oblP5EM+GL|&(+ilWHcH+30@jp!zM1kob=cHoFVen$tJAKd zC|Q8-rAY$a?&`d|DlYY~aZng@u`?0h#E_sJgTzCg9pGAA?0YKx=woZpl1)`(FXS~f zMb8c`WNN$WCE>qA<8#vgG@$lge%5>~RXCzh^f9{(zOK|kai%`wCnH6WDWVGT-*^!kfjED4IT_*+5`9_^(tE( zpby_WAowo&&mpzK+;^xE-y{2kp1=iPEe8KS6PX%996Cj-DoeA4-ztr(lw+Phb8|Dv z)tRT|!X7{Jy?GAyTNO$F1d`H!JZgIc#7zC=i{gG-Pa-dlj@o@uSAT#1JUood$<<(m zE1^vj7qb6 ziE9r|LD**AJ#H=_g8f7qbTMNZO2bxzX=dQ+@;--c3F&TG-}@c#qcEPief!) zsfHagWQXR+HQOhpoD1E0-M)7hGf+E>0GJKVM8JM2fkm>|f6#(eGTtjE`nTFiND!G% zzx_)`goWLO{-4c-{eOgbi&`VbLtyE0$E~s zImG%Y+D0_tU}XeR*jm)u3g?_o72L8H8Ro8Aj-mbW27lFyE5SJ8?h#nyaX)}u3S7)D z+X6S*>`J

2+P!WSbw5$zL-6SqK-zbGf+H;o-81=qAv*th}#RQ6SSGE=zY#Xid%J zU>0*kYEM3$N!0qi6@G`aQ?8WX)8%N_^5$^0c`hFj{ZIL@ms_;+6}?=g1*8!+trKJh z9C7m_{;Z70xjM_>(q&SZ&ad-&bNLW*zef-RXcdOV5sTFZ)0xtLkth>_5n(=fW8<-*>#*K! zMUJ=~f(@s4y6NAO28d7kh%8&I_s7N+GCRAUc8|1yM1s)Om)ua)!o8KKe6qyBr96ns zbM1@C3KFT~{43^|6tpcZVv9%1?+J5hwA`eBaQ#j-s3SK%r^f92;)7?$+6Cu`zSrM0 z&(*Cxa@jE6!@Z-dK(ye$Ud%kl?49J-29%34!<^hBd3K&{dbiYN=|zjt>O;G}0r6AV znl$6SZdJy4SOd&_tYBVizt&f6e(^s@2#wo+%GBao%YSGMb$6A6@!Ay~473Vt@;)4L zjj5$qfJ6ffypt;2NaiZkBB*^yH1xRQHe}-#Myj=LXO~+am5}efF1tE!#QANe2oP=+ zD0pZC3`+u9?L;r`mmN6$J|p2lqCXIXdd=3XR8s_8`iVyShsP~2RcpQMEVo|W6hEDi z4l5NhD3aH(@TW{80BCq-l+?r!M1Ai?D*WQ*a=@KSsBC(@!t-oY7r9otu5y5n z>Q7k*%1^yT0MVhHwu>|X2*)(4F?EQ#Wt#TK_tvoy_q_tZLNa^W2&+(C4_q$EUknLzTt%O#Scyc#?46AGgv{RVm{;#E-?#Gm z2?xLTZL7VN98LGwp2Vs@%g*%O@Q5T|Nm}?sJnL0obDE*-v6n|axFkrb2y_utc^Wr9 zyw5uT6|m$;q0x9%%j!JgUampnYn|aQ{-Vq>$s=^rC`1Gduc~jCX{@Y~YCJF{9SdL)_%!VlK5vdOnbRl}~I9S<&O-Feon-5oXtUpfm zM|9-$)v;!iLm$6CjN91hgBF&!j$?S8q=2T~sAqOeh1~(opRsIf34PFRv$5o22Li{i zWLoqKon}eVhwVMH)!w{ujFuR0s>eV5rfuzni8&jdlTbn3y2)ein;DFBr>nqdk*4iG{3HpDy_g2^Nw9B85xqkCxqM)9AmYcGvDTc@k%n=;pQuC-47%86aammXT{xAo z)Zp<0Jnj=esK*`CkZeyWXhG*eTMGg#npHm^5DJ}NlYK-`-h0;R$0inzN9tLl+KJc< zq@4@~^hD@FCfEj%_D8PX*qeNWKsBT8OZL)fz13b{t&iO!1Ie7H*O_W)EtpK0-iSVb zsQ5vKdVoLP-S=jR3r3v7&)we!c=w$|+To|L>l=$&j34qZYZBhN^ZJ2Di~Fhamb^DG z{Q$?08>-JvBcGYs>JjDIgQU%YvXCkq!s{+iycDqA=vwxg@NMPuw8kCh*EjrH%N$5+ z^Ei}U9<6}Az}76X&M+IY?T3V1M=2?l%X{j_`#$ob6JL(o36X^88@H>|Sp;g~hHPtV zVh++RCt^cfmc6EBpqUvBT-}Kj3}K=Uj{vV{Te|^!pqoh{dwC#^HP_wx^BWHr6K<8B zpH35KdEqAjXnb_NVbNrb_a5W&COBaj?>k40CqZD-(`2IKQ*>7cjlNy&r#PIy7)DY1 zyaAO^0-Z?8`J2C5`f$vFekG$;gEbC!a@4P`o&(%Zx5ymfSxCH{#rh+UF}$A-FIBSJ zQzv+5$gryyapGmsxjGrm`*I!rMZz$0Y1X<6*CqQ4w`2I^Mh0e|#WlGi=`b;u9%gx; z&q@j5E#wMJ^LJa$Ex+$@I5QhJ88>mLvRsVGH$N8H9@Q=JMl>huHj#Go{HB;SH75KD9N8<7$De&-9qHK4JN&@%{Qs?8=R zt0KV>v3^|PSunt~R#DM!dI53on9aaIOJRzMjiH!ktlXZ$`e=Y3!&eX(?aPLdZ-9}8 zNuQe=oZr*)A;O}=Ihj+!dwD~auRL47&PV!e0kCR^bW@oCwU=Y$;kK)E$OcvSi-j@Y7X0o`sO}D`6#Ki}4O*vo znFWZLN9bmFw&LtJisKGgIamG*p#QO*IFHWG;@l|_!ME6q+~HeS|U;jtUX{!>{rW#jy0pZ6K#O86^whN$oNfi+F(D%F1u7wUPl z2-Q;C6jJX5iKB-j5fNe(XdO=kic1dL;fEYUv39>TUyb=Mle!O5t9$V8&`K9&6WxVsTS z%jRlkxVx0pTpT`V4JJp92wde^GQ6Qfr`+V{&l)<5dei>r8c*cn-A7)z=Ql)p(^3Pv zvXa5!!NGJp{N<@N+aEMN*!RS!txN+H420*I(+xPR)#9t}wCta5U>~wC1jj|e?>!~I zny>8O$5uZOs?Wan^%=uDQTwF6(bMhE@;;Lt_D1s?i|tGMFM1}?W9GHIu_no(keK`B zC<9DUM^p=-A9`Lwx2%X4QG)tf=SrE#Q^7yG0gd)S96W+bVCdwumEr8qiz)6Dry=s& zC*G_U(eeJ!R}5)%h5nvl@G)E!C35{aQ>2_)EJV!kk>RzM<|<=)xEv>E9fu?ZC$1zK z-UtQTlQej+^?+%pc~{L-T{I|Q>L~!^ix$Chi(DU%BwxlUgfFQQlQ^amOcuQ(Y>6=lzt5 zjvfn8L8ZADx4+ncks2{^joQ%eHK98*tOd|1b9SuF?<8_v^WjR7V&UvX1Xcc6@ivv> z*SN`QZc5sv9P%t4L06mv!eX>@TRXHym6aV)9o|Aq%x>iNCtJQSLT`b*rRA<-!|4Zw zbetTbNxg%4n)ufhp;xkdIcfr~8hS&pAtAYNrJ?lqFp6uHgcurKf;C(X4LxaQla+b0husN<8XLX|rJbqjild+x4D# z4ff-7BMGz@E@kv~)R>K4E8fnGkrW4JH11c()PzzR& zP&4{RyHzssRP(HsbU6P5S!GI?fn2$7IC4XAV98tN%1v&K4ib5NSdNC7*}Dn(a(TtF zQP;fgz@zeul0^dn>ALEzJfUeW^QvD5Yw%h+e7>h)bd1GE@h5uPEeI8umc4w}Aa4xy zD`ng*<^z?(NUcU9B$QIb9Pq6zvvCDsI0H{;3!UO3$rk|i&uo7ZNz@y_+>%gBI27W z_*@g6j;CZABd}XM*2>|9r|fqptb=0hG~o6wrz|2}@Ab4YpTTeo(fUQ(XT>DDsE&$7 zDkCRHQOgq=WzaE{Ij~zZBD8dkkX|OcbpkovX}V`HJuN~I{BkpMA4WrGm!C!ilQe(1etnYoMmHhS)>Yt5qt~Zs>N-lzirza%3`vl!;jtdue z=dsdQ>nI&}&(S{9OPD%~OkMcig6yF=Hwkt0^?39@AY1Gc2SEQtz^d%o{kOqps^ni5 zBsvDKEOu;kMas-`9EB8^uL{EDW-;~kcmP&INDANR1DLY z?!g3npXc>X5DwU$9^c5U3Ov9fm;KQYx#}Uf&}vNxWO)dw#g;E|Um@(xbY{6#BoFer zJX(SLrgBRYZ5YBtQ0xdL%oAU{-pCvEqWo2Oe7oXiwN zW}!b!gY)Xf*&kfioT>-v7!I6ZDg4yI`uD-Ud}h(6)R}WqP3X~ta&TlWAf@B>4y=LQ zviFSj`U&h>&*uq35I}U4o@yUKisT0{3kN(3>zwcd#)(@Yqcm5wFZK1Z65bZMfw19n z$1<)F$3(m*f&-h#sCg!PZg4~oX0{ABWP6-j@d^8c!~xT#IsJGrUe)v*z9o=fE-XcBc$QPcCL17&xYzN3$7>sg7c_Ny?d0IEBx{1d z^hn}(I$OeDbiK%dc$y2SD4TRIQnwX<4{ApnXMoTyr9h3Jb$zw#xqFvH?UQMvLDMa- zl{B$%bf-!q`Q)kbD^j0FTInhPh}9R=0^GjP*J|}SYRh+hft{wqpq_;A*O<5V;~8L{ zQ%~%6*GNqkets*qrdrM8GePIjKEk_PQVG?wnwCJDJ;VUpj16K<5Boq~u&8ry)TPsU zZ$^uoEG7YTxf@a2i?@7}cakP_c9Zrk6#T*wC7m)0B@NySdrjntyFQC-XuQ1V>^Bfe zi^~!(8UyueIJEW>i*8qmLR{;O)_YO-EL{DXYn{YASamdf`C&OeTbRztwYKb8o`8L!8w>@YP(Z#VaRK4T zy`dADTIkBs9g**ssdIXhn%C~t`)AHNawRBfHr7{XZr01vy;(Y**vHV2n~H{eF!kT} zW}p}BfBdv3HOapu=2lfP2{}e;J0LZJElIxymGV6-rqth{Lben$C+X7IVZE1!iz;n< zqg%2e<@?G6v&Z8Kbb=Jw_JQNu>DfqdpmR)=8bxNV_;wTJ%^(@J9r)Lfp!yu~f#*yo zGpdbQ-pgCFo!;vMW!(>Y8p#cbt)*1OEExB=w7+Y8iAX&6xSF0=c`2dm?rfF11u{GH zj~x2bztUCM7eQ0UV`+@-KH!*CdPFS5wWAp)yrOkZPugIo`O({j`WGm5K|LvhKGO3x zS!ABhn%Bq(lw2rOm{ z((O5o?cP;mMY=8{-~)Wb+2EE1t&^X2wi+R*tNj7IrFr@lDOf{;9pk&ruV2AroYeH!8OaqA&C#zIY&pN@;#}<0 zyF9W;HE~-O(@tnw?MQ~G9})z>S)QSeS8bnQ#(a4L&o)wA_LAtZ&AyqXNw|^r>>$m~ zEPSJ`mwK{szp7H3=BeUhokrp7D*j=(XU{0)!Pk=Yd;MAXXWieHLY&Fw{0FxO*__N7 zmN24bY{tz007B*^!PwNP6o>Ads&REuqFkIKEcU5t1iSEz(UI^WVw(h2!?PNT4H35 zs8=48dEIB+W5y^Q1gYGyD6es*j6pbeI-fI_6Mcz@npY+JE~Fbb3doDX2*i#Dv?NS{M4J~kSULcIU=70P9+2sVrW)bYzAb#Y zJ+c9>l!ApV6ex#*%mFKY#_aXIL!>Ek>TYP|@;AJzOLMqWnZ>DM%!RBvec>8sDASwZ zb-7bTdKSHV&^8+MnbX7HQb=Cj$qxtPMmY|e)dyyO>ct=;HM@gubV$keepnPIRUy7@_|^@h?s@_X+r1g`lF z^M;qe@1izXSaO{`;Z8mB-F26s=^`6GNkJmbDB5HAOG~g@FU$bDbvHZJYZoHreA{Q@ z^5m2~M9&GIHyWuN?Ef(TTi{_q{bf(7{@E3UO49JqlueOfC zr#GH0c5TfI!CZI5!M6Nxk3Qvl!QScxwfX{veqOs|!t-v9r704$ zpDJP{SgYEmPTrX@ROuWJ9vKq3C)qsm$ZzMi9bT}G$@x)tZ$tCXUV7LFS54i5;AHL0 z?u3Q@EW`_RGeRfJBngHVx;I0TpDu}63ei$kD1v9zf#aA&U)U8K#=)Bv^rO1{v5X3! zwN)837jxYEoa#CBPD#ODIc%D*)P4F_Me5~m!Soqr6Gn!L6?~tx z#1wTytPm^`1xy~>9DCGG$6k*0+Qy#j>kU@{48lCM+Q1XEf(~dPr4xk4SAqD(ciZ-vbN863}jv=qFepQ<@0#AOb!034*S}&FIdWU znpAS*o1@xO+B3dc%gFTWJ!SXcPF@->JHSRbr@T!tWyKvHXVccb+Hd{DV`Px|X7VKS zh`*wtM%KhmRWyp@m9pWYAnsJsbeGY~*3^U7N1;>i$x_Ve;&@h2M)o(zCb+?AgzEjGxHv&rka5@_YZfmU=){OSc%|4z=tY@3ukJ_tZzoS@Tkkuy@mvY}?_6lPtR!GKp4hgl&zYLG zdNRdh9O?jD0kkKpQpt;UGS2M4nLe(415g2!o_;SQ=CrtpTc7h`*HEay>I<9d92__ zPoj7?maF`uXz&)6I1fkTYFB|e{NejkKr#-55T@*Cj+_-IW{zf>MTVV@~0+W~Kt=D+$uv57X);Ks#++%HSpaq#%jG{;7`EtIM!FDcrah*9QlHT>%!QyNNR->$%MySz{Uy#Tq z*PImGQ5Em6fktUQV{mT)x*TMQ-l;442UAEsYHhkJDU4;?Q#DH+m-dysgm*L$vo!_GcBDBMiMlK z>!IPRhUogp&GF8ymNDb?oxVAhE(hBuvuO8iZ(~W+k`J6r02Pwv#XczVt9_8c(Jv@6 zvC-^-+-B>I88H1Jr?L2X2I?NmN|!b>3!VA*igbsIGyE_M)H1s-0pq((_e`=QOnLnl z8<$@`HJZSJeCxlL<{`Aw-pgmNM~AK%o~M&0F6D+Rhf#N{kIofDXvOWo8W4d+&l%+# za5s>Sx;vru9Bn;lX3<+-j0pU+?L zUhfb43)gaDcFvr8X6`e?!^;~)KQw!sH;k_=HOoVd%4s@a%pVtiW=sE?W& zwAvK_@*iEu?)gI^FbozG2)g6ITfI_E*%EZa^QqRmTV@28ez92;{>I@z`5I7kI-rSn zb~2qTM>R3t-7*gMs(y<&My2w1!7%XDS+Dj_`pLdQ&HFIAamdKHH!@d@V{7w3HKqUU zznGw(o10N3W77PaV&FqFHwsvuE56E7(O&Ur%{SNpmZ5lfl&&=m9swFVRLPdM-+AyhD?nL%|^t-8>^ z{cbq1Q}nY$-2a>>9wiHtdWxCh$8VPRAnTRRE0j&Y6V*@Ju@h6|&wvD$q!9i)8m;;a zapGc8IOM{pI;&Hajh*~mP3Vg6N#fk8Gk?bH4z6Jmtp9R3dLQfi)J zEk27bOC7!Vw;)@+K9YX@5qM*bb+lHO{zt2STh|}vMg?C1+*4Rsf;z4P@^w&j_}@Q` zNynZyA8db5n22c+ghQq;U0(jAH}XR^)- z=ssEGt=;PTr5Ct3`$-G;uk^ypvpaR3WEHRM6PEoPV!NeOA`KVG~Qym`(54djx1z|$&awsensFD zt%q*%u{QLCd}&!s`H~D`7Zlgb5&D>s_YaHw{MYd-W3Fr_?PkRH*xvEm+2)imm#wyc zBHG#oYS1jge14!A*|T@p_qg&4qC24Fd@iW_yr1>w0dUf~S@4TU zAm+hZ(HBXI=A|!9zE|bv@2G`u1>UJuEc+dSj0t48u#@~ik$^FR=R=0g=;PF2V zr>nIPz4CO?2_k;t0x-uOwp8`dd$T*(_;h_*sI5*F2U;_!Z{fScpjp|46&Z@>Dg2hl ztBUVcXv0)_A&a<0H{%8v7_2!9c{ZE$@QVS?*BM0i_r^aSaEK{6#CSu$LOE%D4XAYW zC(n;h_QoeroHZH_M6WquF-dc}n3!yH$cvk+_n7)7{%;V7kD>phuEHdji=N|r(YH`J zr--b}8wuIEbR8pW?U*~_$jm*ZZ{Ag5Vzxu`(GwQR4iy4l$Jcrgi59O6R{T2L_~}Wi zKoEqrR`~W@b@IZHD5EwiDQ#m9KPoT(c|9kt#l@`nXm5QE;34H`Yj?|nXj>x<9Q~(f ztoo+5SYE*^C#_rxdi3Oz{yAOhT!&ze4@k5Zj>*FL*^|I# zx}HgSv?W|cuuXC7PLgq>b7c-Y&qfgKL03K>!yB8XL8p3y^JKS-;f+Xf*>lYL2L<1J z4BfM1Q3^@cxGT}-)|+Gq9Rd9s+rrW<|9$Rl4wVIG=MeJfmQOdLiL4J}?rl=vKTF0J zC4vgJ-q!5Tp}{_Ep=R)xPfbwcPmlV^3BE}mnuCuRf?ZjnKJrW11m5quQ~J@5_~m|h z*Bto#@qJgX@e5OP#v{5hj5URKZIP!n&#Xnl1rVAPMH!@p4*HQ@&&#sWkBMV~71mR7 zi_bUj@XQ*QN_8gLjuyhj0bj-*;U9w9G~SR;ITo^2zd_mTM3@4$}gguCnwt zfw8po5xqJp1zs>d&j;8WX0&Q9EWCu)En5Kx1BE`(oS%BmdlkF!#20AHi-L)X2_MzX z@P#z{S=fAS5M$Zo6pj+Q9pSwx;M`(|*oPiEj)<36?mc0xk-;cvItF zWrhbG(@mZ$afxC4m3-}l^_f7c1;0b}fRM^9%sA3&>OCqhd#OGPgjB63yeqrNvkHY7)`YN;Pds^SghN*Q= zrla23o+w2d>VzfH&xAS;N?T!8W*(&2*5^=6W+P^8RcdS=E*z6DPKfLXV`Dpqe-flSnMP3C@(n594l z&YOmEv^AQbS;GYL>SriG82T4v#mK4ess}MWCRc(N@~e<0p&ItK{H*pai+@M75Gl)7 zlPHau;@08S+0^|R2D$vZQUPyoq6F%Das>t4_V&plJOtGXZR&@F@jr#9?b_#8t2Wul##L{%(j+NT;HNmts$KY*~ z9p10k1bvD31K8jTy!a}Za2>m6KyY?DmEGt637P;XBU8_G;1(PVFbVL7_Mi5#HeiHR zzXZG&810m*^tN!C{MIfpJGpL>h+(^D1lJ$qBJ;rf@zzDqhg2_3J4kHNSiTf!!oWrs z+8spa;(L`hANSt7QRR4T0(oOM&b9Jc<=VuFqsXPLrWpba1$a8ocQB0seE;IZ{GJfz z_xAme76qZ`+o*zVQk1jnDk`XKT&ut5nY`KGI^C`;^?r$A^-p#!%^W z$rSD2Yi4Iy;U!6U!B%JRhSh)PSZ)|Mehhx1ibeEutEmcJX$X1kt7rd{@E^g*@Bh1* zx8{Tf-_86wO_bHjfnZPP{JWb`-00)9l)OqxE5dNJ+W!5y<@Xf&{6}dKR4*pZf;x|1 zgG5gU^LJ!HjuQOE_=C_=O|oSamBCSfa&^{VkJi|t{$u3Du;6|w7u4Q*N}&93qhI~*m+l=Q~Ore=O? zx3c@v6-!PirQ22R@h$84b?bj;mN%m4L7zXr=qHo4{cC4xYHt47EG0UNADcj_U`wZ3 zXomHkvRaDc*Z9d_3es-m?cHx4IM%Ef?n7hDtaN!VpKxVN&SJ2=@bm&ez#p~zVOSal2Xm%>JG{r_w0;=|M; z@xjT;25N|^E+mJWi7LVn-LALUP3>#sf0p9K1$nrxk z!6K&dzq-PN*-8bbguPF{1eqOSKUr9?EtT-cYiD$WGq1-%wu8`EqT<*Cnt!{bd1x%Z ze!)@Y<#93iW1`B{ZtCq5%}RL1PF$)E+-M2Jwh|Uoem@VddZS93tQ@j-9w$4bt%1fb z;k*?ho4j5oYF5@ia3F(cM%ex|t?@pW)q5+q0U}9by|;eem|rk2`lN35uvjWK`l)}W z)P9=AX^#46tY$<4v}r{a9?0saEkpkA%<)qO**kIN{z+_~hz3)lzm&fmrV4EO&Rt1H zc3^GQ@E~LL-rhDqo3ghgVtdQw2Wl0j$$xEc;SZ6OKc(iU`crPQH>b5r(aljM+O$`B zC5@ItRKK~Sv_539uwb#OhPI!|V3-j;DNTfEl%ia0>4om6sj}nppKiSxn?S>$>GnAh zZOi!w$}^j7kl>O}bmyGr2ao*i0WyXh^!H^_PjdQQUVv$tU!+E~gk`;*rqw|H-u~?1 zb#D&K5(bBAis_kmSmpl~C@~k~i4Y6N#QC$M3M^v#1X#a5X`{t}_9~Vb+`~&#lOSvDb@$-6HQn$^Ow<3$Zp$0Y zzw`rVgxv3o#!J8bQssUh2=br>X*bKi5eP!d*LBpdAXS*Q|Eq4 zhzFs)wsiSxDpsX#pj+=tSSoNrzxeyb&LEj5ZozHnh7*$hmDL{~v*F13u+21w;LsF+ z@o?UCbS3ggbF8^d{mFa{_+7GFl6wfplfi~&h0$B$WL#5q+^o08)g_~1)yEr0A|=Rf zwk`?XILg*RnI+LGyl6%i(Iz1Qf}>;tVT!Hk!y(mBimuAD?p>vou@3)4Qzw*Rf80aW zd}ChVm}i!sLXf^LWjFgnFyR?ts$;@qPH^7Z4;h;)68BZEx9^Nvz}E~+vnT9f2g*Uw zLqnYx-tuk`v%KnFoYMCv=bS41MU#r0ianfe@Oe`=&|+yJ$4pRZt3+FyqB*+^(Lxkl zHWA_G*ccK|>Hl`bTzTrfS^l?WM^-GGkssOcE2wd36=B*pET6OBmdiZ~Yz0x>Hu2!w zQs0nv-d^V+7!pjQ{k$QU6~~fS2Qq{b%T{3U3(a

(T0=l4$w!Z?w7~D_}Il|2F8JdDLb~@A5nw(sl+LQGI++CKXmwGqcwsYicrju&MK^H)BiY zzP%JQVy5XzE6~Qs=R_zQivUcn`tb)*+UMP1DlsvgL=`joU@YpzSGFLC9iH>TeyqSq z)B=zQ6JE8XyqPFId2f;$r};lUxfjYWVyhH9=opWeCjG;dB`|_~%6HK(zan>8l*|Ud z@tUC&JAa{;LmNOMaE?6smsIv(?H$B{F?8OR;dr$xhW$XV%2GJAR<*z$}q@v9i zU74-tq_&Q{4_K|(MUB=BkQ^?YchQQmujR9q)dcR%&C%6y!oMjGpr*Yu)5biDXYQ7( z*hzIg;Xx<8=W{Y9Ha47#v1x_1F~ir$<`#Ti7w=-ZYSdja9@&ptj=n(l&}91%y+_xn zMHr#);Xf-d9y>t*+6Hr6Z&WUw zt{tKkxq0qkVd|Xkdw{BcjJG@WGf1?Sa(X`NL)ww>l{D%7^vk6yT>GBWd($9~3`=%CQfHLdCElp(l?sCD+sOtiAryl!-Zcm<9C1A4 zUqknsfs6n2z=d5^!X4wNCCXK?`o;4pMw&E%>^m1(c}B0cMzY-XhwXIoCR4%v)?{mA z+{W-(sk@aH8?YrQbKj}KiM1L13&~S#;%n?~4KOEFwA5Z8g5UjUIaxIaLEU!Dj$^OXK5<6n%6uXOzU)Us$J?cts9S(}k~S zuFgFyo`6OPpeY_!u_ifQn7AtzN@j|RX1t2FC%c@Cf&K)bUtS-VVoaE}4!lQ;tS`gm zZ7`Xv)UNNe`D8aNcx14i(12b)3@^{hJBWkqR*)KU zNgD~(AxbBo6TRBrC>=GOn-)iRPq&#{DH9Libd&=jjM8pl8=LZO7HoYvB17j2nCqprrnc;<=jG&Ev0i-O3 zlhKN6M$OT$%4M-_88HqHB)T@P*Vz!V$;1;tV4oBDtA5EBHyQj}*kNI5udUvI1sk6| z#Ho?_k&=+;l0kQx7Q?G=s&eOcpLYe(Sb)C2#jsGO2shWO4kS(wqwa7JooqCEnL}C% zv$D0DuZKH0aI7O9$UTL&1e7s(2owg-@?6yDAxCl5X81!1u}gZ2n~%JY_zMgc91El@ zJxj|Ouqie)=%G-c_`btlf1K;Za0M&p%`WNODBYb4Y_LX>d} z%69EKoTt-JoJc?ucU3e-Sg@zTLpG&k&?TB^0#Nwq^2OS}K8xJMKPjHQoWwYr#KYxz zn?E>ON>NklOS#oWBawa9NTd@RZ7BmaFC=5)r=P_u&)2c$N+u7KCyq9qr_A?5$a;Wt zGV4~}aPeam=>A-nYVNQ_dqIKiiS1{zH#GL>vy!g3sVDj!5T{nFl?9Y7ejBa>29Ieu zv9q1rL(XT41;$H4+wWy-sw_;`NIhwZ-P6WWxpAX?pB} zW|wy9Jxy7YQWrlT2vc7f6ZKkGu9v2I--oAdxYpiIf)$;ls%H|^=Oy%!Z5RG@$5%ye zV<9X({sc~9Vadn>{$8C(GT9v8hkc^R( z2#oDnb}Etssfj6G^Y5hMr8j{qwM%Pi$OaqSzI^P|O@yRT`<(UY*{isHe)G9vlgjd3 zYaK@NqVBQSji^0sETXdQ{N-x;;2>VkcDdwrJf3%5+ZX0BLuCLbO6B-313`TQ!K!L1 zS)EydPvTUxY;XVFrAU<&Q1;4j-aJ)Py~>QnV?6CbikODsEO{c3nA$5}JsS%A_ik9G zRCG6Lwk$S}F0)9{5_d+h!+jO9wK3h|%rVVR<1Y2YEC*ii{oiAHb&?OKEd|)D!IUrD zMhbPj@7G!X64~$>`Uqd2?Pm2Ha+2!rDJ}L#>6H$Cu_^12amVd^HeB;sBXY2}^%eK= zdxWUt%WSemq{J_ONM`JXy}d^b4TSD}Z&Ig2Eq28u?zwkP!IbldtKca9=8IB}{L3r< z^SMn3w;R&Xtb^IX&Rg6W+I#`L^0hmk9y7LgD>CG5;Wf}?eqC60CGRb9ea~PC^EGj+{wIoFlwXebZ`FG+Z0C47f8fP);p-vkQL5nK`71?mIILKsHR<| z3|(yONJ+C@lObv8-UN!qEL6#dZqCxpf#1-H62^4(w$p`spsw?TRaA>T`f`SE(vs4k zN_C*l#oyP|Iev%0x}BK^HN9#Z>Sky%wRU93WMNWm_^XK z`bn|HD%EvLrti#Skq3%U>&OjT3^rwST(BCav=TE%JyAYw_=A*sP59qA%scgl$iL#a z!`4LD?XMOx)L1E;wKZ_#)fpNj9Cs2@QqX$p2~bLZ+UtKUaDm7+&&VMCgVftGcj$Uu zL*$@^=bA){1G1Tg90B2dCfP$xAr%E$;x-Fb=(A#{JWi7Q!N$>KHYDa|JO+U`Uzv`Z z!uuo*+hg1T^PisOILMxYA`SlhaAwzC4sbD}LM23LUouR!eT6M1_7T~fHxnmUVx-yx zM8mPDr!5=C9#{EZ$8}86>2#wUFgdKRPi)NLVV01cEqz31mH21tQ`VIl#QHq~|Dsgn z{QPaCJPtV()s?W+OncYV=IL#A;}!)sxISVjtBbaLeLXa__T05!eoW}cVOEjPM=wS) zoF`XAqk2<9YG!z>IFGH^HQ^LW>|aIKxUa@38QcJ7!V+%qWgNS|z%m0EwnyMUB1K_z zJQS`nzI|U(=n6$&3y7V*B_CY*L)zZt6hpJFoA)M^eD4VO*{r}J)!9FAE(msjs9>?~ z_LPJ}mJD;lIVA+zJx+^2)Dj%;?cN7=taFXW5AK|-t|3s%|9W-wV7I|2eEFfhTSSEq zF7hmi^t(1fVpEYqEBq|_7W)EWl%Y4DS}_=L!$ZPiOjMI5s{XlrGD}`?l=(jaheO=o z(BHPAw6w`FF3yzwh8L-8xfE8r-9VL$5WFT{&1nWFO<_nK+Su4|zw4qz2T~wbZ~-<} zIU@ROL|jI8B7TgJa%r&cIa7N$6Dt+L<3+)|_jjsbb+ z!U9Yb>`spjrxTf~vo9=4-0DuEM|J>siU9*}zw%$Sq=A!Xj+3R zBB$FbFc7A>pL0}1=0%`q=y`rRPlks9aE{)Ia>@_02Xw34sT?u0G6HzM4RE;OPHhP#={(%vPWxIU z10^1NRwhvBv1H1@m}6K==MXl?vCGZ>g+lqVh z?bfp!B_>`5+zs#{DS;<>oRgMEehUYn)rpEtPECHTmc=bO-%*pB(d8X&^JOr5lV4G8 z8&pBLNPIFW^=PB~ELj*$pUZOnJ#_wJwENZB^5w;@D%-M-rym=3Bq8fNJLJvHvgSk`mOz-lumn!m#CzPLY z*#0_rY%cM!^iimk?)GynrD^)@$qIuDS~AHT-8S9An|I3BL!S3X4{JW^h_Q85G zOAA4E!hOfTH~XjoI{&k?pT<1lg0!g~ZabB~ACxc8dAZ7Hu^XXUO(x(_2baCq^AL0! zvX9|04mS3SBg1GqVDXXXiUhYYZMlla91IRlY~0Pz_$>9$KV9T*@vvDk0d+LiXw4td z5;J_d``&E)CH_vx1;2H6 zRM5W@UB9eBgq?}nd~*+_v@&@Zi(XLr)bY&Mo6J<#)@|N02hXUd?h|VVe!$+WL?w|X z3JL70AuLs*DXB2YACf81vla$m)L_+6Dwe6}6r zz&XlBsR0z3Yojk>5L2<5hi@BBJD|TOYDX`Gb^~Ci=avaPS>C7u`Bkx$lMkjteK<>O z*s3DN2$B<%Bqi6B=-v^sbuC|Fw(7X$wue#e)bFlTQ5H_Y3RsVzVAA^X^$K}I?x%1( z<;)^pXnx;Kpvjem%}93}>^2q4X9FzYP4XhgtRVe-<%Z#nrRfX4g7h}Z0&iDi3I)Zq z8w0UE`dIP!5LK^wWqSLk=#RUVD84|ak0~vv?NvJp)JUOTRvWu3u_*i2#jzNZvux{N zJ#1ZJQ^1I1yht$=pfnuiFnsIEtq{)i$!hoHVxI4k=oUs8#J;*gDU<2>{#?$gVio<&J!mG&P`JImVyHQmZZP3uha2X)Ce-Z#i$<4?DumP0 zfj2kM`%6+neX;G&W=we>43M8ukUCZf#`cqf&Q;bJj!7mlRZ*~;B}epcQWxvKgp|TA zw{6Qt_@+btsM|W1nm$E~RRrq@EO?c8>H~)op%v?8X41mNCORT@n2h6nG3rUG+WN2V z%&JrC7J|4wEUwF-Q9osyp;@9GV@UjJoH&YR-jPT&(FTpEPe&M2mCpQFmKlQGxD1~v~P%A)z-Tm!MZ}K6%@d^opsRh(EPpc z_+zu0=zB;dsR|}|N`8sFYey@H$7%fqZj)n0y7E^2n9DnqC3`2m5B^w7ecDh(OO#u4eNk0$$ne+fGLuXC>Rkt#vk0@{M*I77 zVPkpnKEmB=hO!SdIj`f=T|XNwrV{KO8!b~{um$Ymo2Qs`|H=nUibD8D;Ns3ZR&g~> zOqn|D=7=vrbE&0VbrNvcrhVuW9m7?hn}bqZWgvkfXhy{l+B;=9^Ft_}Lzg!>)8w{! zrXWQXt$4$*9P^0^vgK~3j^9r|L;LQD3xF}eWycMwc*2qW1Mh>&`W0jg6rO@`D#njB zomHg%4I!hVB0w12Kk!>ZYF^VtLjS++=o{}zkxi}*h!cj7JnZ;k24 zQQkdiv5d?X$^R`)?Hcue>rV^I{@;q${~t_8#ump9krH+rrWCtbX!hsc1X_>5qGDIP zzoUW3WmrW`qu0W`iZ6O$*Sbh$l%x;);Sg`F=8aXL#yR348o0S~P`aXl%#k%bObX?l zt8P{72&q1P_@Xx!RhVAOO)SZsO^TNtGUoDof5AR78wsjpu`@+)WA~TlcPr%#c=`MO zW|H|!K7UN!;?*wF>#5oi{+|!Eco#cNCR~0qyZ*584}4C)0;@NCE@W83JS}`2dOtbt z`;t-ncsOF=_)u;fgUNRwP8cm&sn(Fb@?{5)6=TIAe6gD|@};?Zh678Lwar@pd;fNa z7W+Q4qZiSmjj^#SZJE{ZgMta4iMyG4*w#d(ji*wDQMr4g8B6s_Ys%?ImbnEpF{e@Y zJpzY-hKuU-;TumPx7O@|`s&uT3#iFPRZwgmuplAUVx}%Cz(Zs;P&86_b#!A&f4%G!%)1mbxPuwGJDLA95VN#jk(a1L&cV$?n=+K z44vE!@XN@|#mQ6R<>Zrts*2cza$A9fViOP?xoL*1WLaB3yl>;8$3@>Mz_v1Q3sy5t zP*R>7M^<6H#4ehPH0uogt9_V#!4fNRO{dv*6E1VXCp1&&=((lW*f+XEB=DGy&mV0^IsJi1@lV%_8gZ!JO^TQqkA+Fy`9wfh!M+@)HEH(;x z6Z7VJ#|v{ehKIyk1@Y7m0+YN01GZfP9r|0YqSm5TkY4%>OUTA0r+kmL@a$oAQoq-+I|#gVFxz(Ws{c7S0xFg-EeR0cxk56f{pA!Svfw#0RqN4J zvp9HgO5%>*XWMcG)hiCZjo+NqR;{cHq_eB^b*VpO<8zpPHFkLguQMf>_)t7i#pq#& zRRR?;RCvR=nJt$}nQAfAVwDXKD7U3btxc#!C{mf2m|SVd|H<0*zU=0(b;Xqdn+1re zeCB7>Yg|pNKcVdO$!@jS6+jbm9T;ZmcHfGNFaJ;Zu&qzpC&6Vudm5t-cZYI>b5C1< zBnAY)=Yo)Xp_Wv!(R*Gmb$<-=V!bxSbmyDKOS{$Apf7y5$G4HH#`h`Za@a?Fr;kn1 zm}9ZuJS+ly5Pi#A&5k;y`C^xUJuZR!!7j7K{(i(l8@oI=h;#-dp=|GPqhU${Sr=K| zm)8)6A3CGkQ)3V2s)+Rs%wsoZf<9yUlRBih)^HCj>&Mp_20~k9_QhF`a*nqe>g{G= zWsNL@*ee0$DtvukZFb&QlHze+_~*S%7(4b!$R$w5UcEMSzIx6fE}FHIbHgCRvDwTC zsAk{*c~?>8V>jKBRgf$tYe$Q@STo_*2QXJlWJnv`pv3n!f)-Y8bB2OU>zg z;Frm=nzFy&z4tyd|6#pNC+mZ*1y=f7qpr{Q#mFdp^L1gv80FYpXG*lN&Swtvld$jky7kmSv*Dvuk8cp zbBz7*|6`H-+u7%xF3dlvR=Acz)`9g2Fn__ta{e#mE4~rEyhW8Y z)6<3l@A33+q7FbAuZzTpPFveS?LOg zdfbU)KknR2ejY5#$1A4dBS1Pn*Goqb=UKEeFJ|H~iHG&<@aC$^Zx1}|VDzqH%H7!9 z_BR08@yS&N3lj#`oiXd{A4Zm$pYi+0`&QPA;Lygi?Vnr8$+rJVIAGj@{J-3_E_^E} ztZ*9kP9GRraN8_T<<6@OwE`^-G#_9B|H>`dGilBA$qkQD4HwFl+LT&z1#q?{;G>96 zRakK$EGxY(sFfaIq5@Pr%!u2gE{LSqcYws;76d5gYF%t9#&Tp*vUlQ&q)1~Vr(z1P z4E%~Z-@j5H`e9XRcaa}MF6M<@L>;bf=9SeF&SqmC;4RV)t$E7Wc4mNFplMmvF{`-G zpHC@-#>Q5;#!KPeVL3f%k53hh>($_oZRPaDb2*DS8JY?$Dg}5k#4HwN*lVb|EDW_1xXbAAQzXwp%Lf>Bq?rYvJ5fr-ffA*g z5$n6QQ)$#%{-fZp#-muA9%k#}xd}c4<%V8n0J5Hu#}I2EW4;36)$I-DtE^hF7+fbY z<+~{Bjk$}xHM;#&#;wCQ|QF2EMZcb|H z_hx6Pck{)|?v8*GcV<|&(-6>(n~T~p8#8$G&Ki*5f2&fHE8R@f)4mdj3rvTMDroIR^l05@q5KnNHk+!CY zP2wJ!Z$idy)?$T*D+EtRlc?ByEMJ-Qi43l63R=FRe&`!$7HsQG$eOewG!xkG`Z}P) zTPCLn!Akh1CmuT{Y4Xn96X)J)&qeF#%GYJ}mCzAYD>S=3=&?~l$e6Z7!$nXTIqW6% zibne%azx)GJfSJD5iOEBHxiosU~ZYK4I^SCsJ5ocRW*1V$m0qeEdllKzE=jg%o4Q4 z**DFH0jHq+GVhwb@D#9VepTV9{f9E}<6Ye-HoV!rpd5b;TDlo~4(_BeZD$v|YA4+) zhXr#6E=kAeXzHW=Oi1g)Ph_7nFc}V_Ci!**)$u+qJ~w0g%xi{9-Le+kr%1qMEjHN9 z>c$o6Dzx>Cy1mA8dq3z7ywzt5;S(orQ|U_cJ}O^ICGETCHFq&xo4xbRN#lzs3pF`k zs0ko(2Zy#Sw!v0fn zie}=QNp+q3-WHAckitS(I^^^l6Xyz1=NEu6z$}3P;7ImC%R$j2H@Ayp(|X9f^#S%l zVhoE0-sz&$@L+a0Ce~R~?sKeF;O4Y_m!a4Fon^nv#+L&s5kQWAc5!oC&MBn!S{@cx z+OTsbXA8f4T_l%Mu_%@J{$U-Va&Ticv*@3?r;zE^cMdu@ej|yHkeJiWCroQRgst-z z`HBsq1PEL#Ou5Z(e}!C%wMRx^#Gb<5vX%mZdKD-3<_s>kC(od#pU63>0&h4ImRjfp zA%6q9x@uN#MORxyb3YXbqkyvd8}1yp*2F;J6p6A z2D?yuE6y~i{xZa1c%$tbIe(U$UqHw0^iQN@rsc6?x%Q3^Y|$LZKvoVP8_d}kPP@%} zPL*#+zck}nz{@q!FETq5C69mpO1Xbua5~iJWJ)ke9MI+GHYNP>;P{oDBa_ywoJ34g z$sI16Kt?_8Ry$Z2{wm<}QXX%^P73#uSC_cFU+IQ-@YzPKTF0WeW>HawXXa^V|J_ei38PPqVi_6@rO)ZfMa06? z@y<@?xgl5Gf-=N}aq(s|4Tvqf7=Fd-#~xss^{?VDiQOb_V(vp*zt&vQatx@?T znr+E&{J!W`tghVPdWlYPz+;EROF{1-Rf%BAF^ge#X&c9Z-+`6jb%n75rV0Oh(6Dy^ zN4l|tu+x(FvHx%?T;ZgWXZd*+>}y>|s~f(_$nuATf;YP+LG-h$sY5w_5>|?~B38De zdi9d>Sc}#>LAOld8eZ|1+M1wI5em7Vvvl{4JHOFJ8GsY^E16Z{6uEU-0X@1@z9qsS zF*q%dx6~1<4!pf1gN2pXPnVKqWx6IdQVV(qim( zVrV!myiJq76W`%^y0+*I%dm!DTxPSHzn9~JZEjGv5>)R#(?N;@E5QD*~ z88oI`wtKId*54nPK~L2#=u(0nxG#7Tz76t}Ho+{1rDv-G*6|?Xl7zq^BtxGO9I=`H zj*zhjm5=QEb4LdXUbn3;%<&vm2qx#_wZA^b0p7-mV-jWXIYdpT_jfSts&lX;i?th{Gcx9bkBq68Q3Mj?Z|d zegu3+xz#X54-Si2p6m2;QLV4w<2P5}l4@{Xy5XDW&MuZT_$0<@_=!!J*2vov=Io2O zlsI4^)!PwzEoVP4b~DgCZ*=Y^tHGj&%4lu;LgAZ&6+MmEo$+9@ksEAt-U}A!b{1+r z9LOos8i19W!<(5b`E#=D1J|KZe<$IhJb!SS{0t}O$PjLPQcn038y)MLZ{0G0=tYff z{wDsEMyJ4mlixjWYUz3KS3Spg?PN?^m+P|Fy!I!CL9QlltmSyD_yxV=x!drQWRR{F zkBG%$ig?d zOWbWCE=pmFk00r(woqj^t4VmlgnqkX-HVb*aBj0j&${B9i{3(R!v!nSTt_!AZ61`9 zsJ8Um8N=^rMfQNcd{f_6Z*K9fGI+~Mu&O*dl1~-e-6nM%AoCrc!2@$Z(4!rk)Fuxl zsQIhF7(^L8wDu8NS2i#oMY{3@cEWgZF8GtWb4c6JYLPj&iqp#Fk}yiR__14F3Nf0M z@v?9;i1VzC9gvCwK{M6HmPuLqR5{XstAyu?Sn=@5a4;vK$^OP&}o46prTaU{SD>A|rn> z`c%52zWLt4l5UWaR$oJOgu2dTxEADWNsf(EJiVM{=*P#~)HjfeQPo4&XEONND^bRr zIGlSXEDvfn= z=l09vde?6!SGDp(qr(yA`*#-+ta^w#Z#?~bCklGB5%Xy{gVOg1#5JKYyPxW7zqX@} zygL#6iKWgISOORv_Htb~J3RL`9X5Ge<@vkL7#Ku>l#*g7bZv-SAK04|i=gRYTRCP| z_u=!|)b7R09BXodYEKZc7~)yZj@Jv0d&r*!3eCZ;7KinVghjUru$3$ zOw3qpiLPZKVro0Xd*Pl9GJ9xK%0Rt`)yeMIX~*EFEDy+N*#W;=`CXR1SBjR0$-(iN zeyXSKa{;Dq)({89luAcAm!Btdkh+*n>O)KRhot&lN6uq3x`GIH%=M#YIp_DyZE2)B z(m{JOS53*Dl;`Opd;Exx!eVw}dEX_Mwm`R0f^Ey%{<$Fzi{CuHp3XRQHC8UuSs#{^ z7$17rb^Ug{4!G*6T&P?;O4D}Aa3|?cJ9x29dWC~U$1n09C*NK3!7KS~OZA{Sf_wh- zNPc(bWwWQz{A>(MOHQ4K=^@HPzG|nEv3Jm$0gsVj%I10SGXGy@nm58&{*be(&+Aj) zDvq!{K?Wy0zGV?c@uCAzpxmAHm3or)g8NZa(6u(=o0u5c&~SuxUtoxUnM0Lk_jOxp z;-nAVn8Z0}*cEn1bMP_Gme@;$PZ^5qqSs)bAzHD;Q2YfoD1FuQDPg*ZAN?NouJ?}B zn=}t)%aQyL)@;Ly#_YR#@SC114`zm+>E3s~v-^yab-39W_0*>Kwsy2oM0T&O0 zH^EVh0stZlxRuAb0Up#Hj*MXYGXeV+v?<9v@8$sC9A%SSp%jkQNEFs`QLj!;3#@}5 zM!Q7Jmb;SV3TGI_z~+V3o9@OSQY=BM>EFQLt=SY-0iR&bfp6d76fYCt&3+K_tnvXC z4b|-?CM12+TWI?;zB=F8^lCl6{nmqHRm_?36`==utS6<7mF?d;N7@<-KQZ3=N{QY# zjof%u9zznTravVPTEBzK&bIKCW-CUVW$wFVQ}K0uCPe49v5TbrB(de#h8|YrhFGcA ze+R`D1_9e{o3WZi4?sl^kr6gh>Rb8(mKoF6oPI{Qro8;=f53>I-;zW4AH2dkjBr4>$MuNx_6^*FLH$aUMsq?#*dv=E^Ur)n(e zMQAzOWKu|(#2g}z#EU;_AP?af?A#c4Tj0xPN9o3U-l>^tf!;!`RCMJ11B#`%S=tYN zb5z-y6?h9(%-_F!_H;+D`*UM>xFXyWJh5SZ+zdtjzSGi6js>OcQBEa0C;Jr>5JNtT zGEE8cuuUCB0qVWl?y9`Y*~(!Zqbr+GU!s~}qp>z9Q_N1YbX=Axh&VICZq;WpXOl`b0eZU`=F4_2EaD@aeu9Lu2EX z_S=N4EJGzuCrHVn(dOI1&eM*uSsG4`($3b`t4YH(H*1?_YQ8^@hezr9d@O58YazQ$ z%YArwyqUv?m{_cXbo6K6-yYVpf}`~yT(LO-XeV&j zFy+JzS>Q3KO)Gj3aU(TSrUX`^_CGj9>PuI@z3LaaRN}8m6qyazc?*c57`O=#nJD>9 zZR|;|t!iR_<5GKIV)ystFfhYhxGpCa~Zat6oWA41Do-T4QJQCLs- zu|&+e^|I)`aSDGRI<#kOwtZ#KQzFyDFSM&eA*r4?PGu{KDZR$+xsH)U#+?bd>cWm> z8n=T$P~SGy@+!fyVUX5+E~x&!u{9&=<4F*H{3Or#Ije@5_~N59)i4URljD`5;+c?_ zfs9tIpw}Ia)``aXc-+<1zZwl(5>gG!_R#>idh?8)PSj=Z^4Asb++?};vvR)H+C=3R z<3x^-2PtZVLbnrg)X&B=Zl-5|*)jCgl8@RlJpA1%M_M+8pdcMj;zi+fpI`?0r3gdp z5+;+ooC>aw_qyhMOtTM%=RubFb1v8d_ng?FCBM@brZ~6PyScv2FG@fX#k~i?`?0ek zwTgYlfxgFP*T(+BI#CVTsl7WdYqvy;luhJ6Sv!zhNHqGyU@CKmQ(z+pKt2!K#j-*x zX0t7e01bjH3v4t@vo10Z2@X^%Ile79!ycfMQV4&BmZZt8cc>HS(BKsJ1fGoEDxT)N zN(d|L1vA|>ENLk}CJ8bV0VKQRN?DC-2;<||ex;rd4UBfAH|2O4 z!{Uubzvmigew64=v+U(qFV#uqYPKcjpa>!$I0-^uOj7VC)rvJKJwNLymh#*<*bRwK z)ui}CX8rSnwYSfv)+`e08|u*(ILhg>RN)S6I0~E_b8}!+aJfRji*Uy>-s$VhzkvKD zFJ%YB^V@gY)<-){Zo4r(F@NL(?+#IkhSBrKPJxX#`wC)fS;H2R$EBK!F2x*}Zf?vx z8Ji~tAKva9FYwG(**H)=Q1X4w+YT2htw&Sm)k!c-@t+$Qd?6VGXYp6zew<&B1p{Ts ziEl;gdEJgWrI80H_GA5wO{Wi3Y#^J`BAxe0vvnn1#=2GE0zc7vzf<4w9nQUxnF=oI zs5cShoG6Gv+vXw0K7j&fc}CgQ?W3f3YEW<2RM(sKa*O5JIyNABE!a)@d?uhH2~?+@ zrZdiPqUL&rNN?;0-Np#&+_%@ngpj&TwKW`YJAofg0uTe@8DTp+x2yq9RKksG+q>Z{ zh7US-h@XaMx7X__#nf9-NhaynJzj@GaViyEscy$U@j$!A!%hgr_b5|1OBMyTDyJZV z%e14|e9h^sSUvCkdktJ%wy(xK-vAXDmiJM65U3Buz&t96nT5}B@Tg--(DYT)Z;n27 z6{7jk4at-gQ2`ukWH?)zo}T42AZ1c*mNrbVRpLcOkX7yN?ZyYH`9|yPv7X}`&FlMH zF{eYJSZ2KCZih_I^T}KVk2Z<2SYY1mpDHcP!ujNJk^XISL38c?&?xR!yHQ2) z4!pcFgj|yDP&)sIFk77J`>@eSf9!;aa(yXq>&xM&1qG?4&x?MOFdfe~q5e_=kK1M7 zw_`oKOFf^EW39~cV|}2a_;e*NTTH;TW>!CI=J#X1?y+{g1Ht6=@f(iO?Y0&)dDdSZ z3hVA)rn`2)Ew~$XCp4^;IJ6XOZ7~fk-Aua_q<bCnDpZ%P8 z4A`aSP%5>TnXpo*$9Gd$?HsxbaUD`^Ta&YXpC7#b^3oUTuy?K{hO$a^zqg-07}Nip zY+qx3ShT;1TEcRa2G_TuWAr3;6jaq3J{Vq8cD zW}9zcsVf-NdK5Zwns`3kzFB39W#FI-$;LLO0W9R7NaSgK^BM;exK*Mq5LJX_CCzL9us( z7rmzt*3V6kKRi8#>}BUJZBXvjmqq&He5|`$UwgR?)Z5zjF&e{RLCV56SL=2m$<*_b z83~-N2A}H^_%AI0S660X{a!`Qlg+I?A~_K$Lw}&6@HrD$#KYN_;DbV-oy)BZFKFva zvbNaD9rTw`-|Bq!SxeMsj&ES(B8@vD>Yw&|#Qx@UD#2$f2IcGULP8lbP(PAk!NcKF z#Jx`H?(q0VZ;DnT;=6Y$A7?bs4`+IWn31*I{nwdtR&MMG@4!k*b+(`W$#~?XK>zh{ z7{wQ`m$Sx?1@cs&*>E&z8Azx#=DqyL5U)9Pun?3cR`3d6z0Wr{L(Lp*g5CT+N$&9^6b*Uy#dQt|79kJ$@YIy?tFOtSGu zSR?$syeQ`4h53!CbEJMOujGA6Af|*ahFnytCN7K)b}Y~P+a1g*a5kP4;)gdC3<)`j zz;fey_A42R3g_}NveI4WR6mlDyZNL?x1hzO7&3Mi*X6i_=FN>8fVoKHeWmT9L@v=> zO_QIJnY&|~&ceXJTd-_5JQYik0q<60Or`B!LOBpKJHwdZGSGFh(e`C(8y>oRd0#}r zK0#T^GgYSI6ZS`6J7?0Zr2Xwfqw;vV$>23!USV2NVMGID_v_S7HeFAASWj1?JXR{R zMIV&wz2Rhy;vM>X`u1-L>f=>6Vgf=#3KbcuK0dh(QJ;0dWQShiZKd>huK5&G00e4c zbziZbde)e@^UD5rWeJ8nIbwEtm^0hWJ{aBv(RZ&i@2LKbNE|*3&Xghleg=M= zk$iFt8}5SEo*-308C=9HsRDKnUs2L9X^x>fGsTQFNoNx3(;$(RFy=nD?4zX~xDN}_ zY3rOF9CVwzlOOutW-q?1gcEgmzl&Ft8pa%7)I9szs;adiOCLxs46HXU*yB7t)+Uo3 z5h$$PP4ogRl6VYT87wQUUJl5TeyTFQ&0GK|{V;TZW@oBe zp5F*CFcrMZFz?QHLx6M$`o8~sD06YUcH%`s$sO)S1-%{M#aay>+~F-FE_6*~-O)_e zY|>IMJ5%?U1Gl${MiaRa78TBqPb$fdj25BT$h%yyHN(1wGvR0sa3z@@wjxDxuggxb zQ{Q)cn@Krj1rFxJU&(Rv_|i8tTX6+qH^AAH+Aa^=^)=b!-PdwE3Hn?MBaX(o2sM* zdD8FZ^R39zO63d-x=5y;vNpSLl%gMu7rao4UHyGChF4xAhOK7=(h+?TtjX3Y@_y0l zJ*TfS-cBd&VmH|hdQoqI2C7tOJ(nKe66hU$8@S%Btz3>nJKLswD#Vk_iv5XpJWhyP zR{e+Xykugs+s67m5zO5mxOrBQJ&&-ft*N}bL6~Sl4uSo-3Hh{=1%eDTnMVr3Nr+15 z#C$x88|)!9x#So}C0z>He=E+l1k)0K9M3(5NpY3fa!@sTAUTs%h8bL1kOfyYa5LKf7xyqFuB!>0oW8b$TsCjJ7;5Ww5{;uvufV#OrVC*_`* z(?zksrRvK?Qc=K5F$1zOK!7;%uc1j)=CqP(7;R~N(UPP&e2Bu=B2pJw<=?aB)nIZp zC~72Kibo%TOug+C@PNowRB=375mlkDn6+N=29iPGyfd#h zdO8!Q3rZRYs{gEsj<-@3zq%ZaAi!DeLN_)L;g66JqgBqVCZJ0sbWL$2uq5)?!QuP) z@b2Sse$Df3UPH}JAj#N4>!|IQE4@zVSYsMl*1c~;UpEdokX_Pwb#xH9N~D98(J+-P zPOefX+CpdC*#ACiuu#P&B*t3!;C(_5dIpn~Nm_hv8%ucCC*qw;m(A|x#{uvAs9TTa zth}shfjXCWci#4*A{7n0pWOZ4)yHaM4ri9KL;KC#IXQU|B|~wqB%mGXM6`qxJZ)(e7R?S9Ccf7*tBtmS zg&M`j4;;=79DBKj4$UG3sFEty3XQT5(#c!D7DiiEd=rsBLP zxY_HL%X!4K>K%GIs9;WyCJNv4;nTXZBk%w2YI4^ovXpKu6#;+H8!TFg!%!s0k7&0Q zuunDpp6GR_aAO1t+~-$-IUM(hl)`0CGw`FDZHmH(nCI^Ey>z@Ohd7dwQ&VZV)bdVh z8Pt=Z;2e*Pv}tyxCZaY7)ye9K8FZ6=g$X?djr6t+#*fr}`Qd|=&l zJy7l?7XNRYV!P@Jd-l=aj#m2RDe233ta*j-y-c5FtwS;({9BTE&`w+3HQb^Y1*)ql zP9$mwbLSz%K~$}T4E)gTsLlb=TYsy0N0g6LtYU9*fCJ?NU1U{w%HC0EYqr+N1sjU? zVAlo@eW7J4AC?NN{c4Y~*O}w@ZjOxOph{v2)SlZ_9^=Xj%b-?ghCu)RQ5PGKzO$Wf ziBDe}5oR7CYgTuGkeLw-#R--F+FEzodrz==uHw$|Wu}(C|2HzAU;koR9QyWH^sZ1H z9e`87ARRA><;xWfDaX{T%C|kf)Edn}%gvfVcX~w;2o>F2quUf*<~atW#`KJ}&`046 z#8n49)jCMiyIJRp^0)b`=?jaNrnw0$BdgId-$U>7PM_S98kFPXk$-J=xwM)~5f>rXl=a2MXX9wkeiQfp zwk_DQ)OhyK;~Z?Fen{mL1x~xaar48IX18wEMF%A(sZeJeZ7%vTs0Xxy~o_ z?h2avtLwTtk*o={euYuNn5{EE$*C~$!f2kQ9uKG63)o-0kyS&zZuaeoq9RWQlfXyr zcy3Hgz&=PNF4CevveE>KI?rEul9Q&nsxJFw8B(9IQV71JF$c{EpvhD`s5m2meMas|ZA{>f) zH&d@t)@(^u;P`bjUk0}p-OFyr%R^^(Q;{Asu1~?Up<31NjsLjyn?jRYlN_aDg(ZQxT~P}`B)FJ8D5=J649NW}5Alkwxh+}d@z=%rH6 z`J((Vd8`SoU&6%5&>sxcFLwmAq#eS<)Zb+AUl@0WKH}fF%@|r#gT)}eiGY=6;e5{V zXXrggq(c#s3Q{v7L*JNT#Jp?2_#p+R$QvhSNLsH`)Zc?-)6uh>BWbIQl)%|ruOJOO&TKi_Z{(e)&So{-75V{i*@`SAxu??|5JL{)p$!U>OJA(|x!?nE3y&6s9ym(*F0K`ah+Gi9N-` z1WY0S)#`t*bqj+8xBmaWD0~%xjPU=hA*Awu7XSLyN&4@O{kNX}%ftXBpM>teH}vmv zHPAD082^_gM4+bFHK(b%I?l~IAtI6c_OLM)Vn?Of4?p#XfQ+3b|8J2XdqB^afqTts zoJKRO7uWGp?*1zmOIzKDEJ|QsH6geKBVg>p4}YyC-Ql~2=zTqe!9X1~-GkBgqI&1* zUo}g+JYKC7E{O@_`(}N7*X5CeWd{J0>;(FfTl(0qcQz}F4+o5xz=U&)TC?4u#>wWc z&X=cpyYq#UK(<}brSXDeiLFobpOHci+t(YrQM!*}9Ofe%IWL!$uN8m`k>wwk$`?-J z*NS*)^M9}p4UNa}h^n>^y)KPDRS3aGlf(u6s0lMiZ}8YG-}9@N3&AcOHu@t(k|SuC z>AudMO)lH4HhcW#clPN83Bb$13BWw1lrv~ah7_Ph7qMrOR5XK4GAFXz-zqm&(|n)v zQw0lE$Lkw?w@Fu0RNt$6ukd}L3yU{vpE~@TW7Ww1PBpAr{r>h|cYXc6Y({G*jUeYCToien7j5v`q4zkGoBi{;)y$tAcSF}sX zNj)C+N#p|@wq-hW>kZf6Q(eoX+(1fZKCmrw7va=YpIiRu>Lp_7^hZ6^VA>lS6so(` z;nv}4*6pT>48RvZ*Hk)_#t9dblt3*>5v!zwsNj;kaoUvmP4Jw<)T0Aj5%ma1CG`oR ze5O$(%}uC$W`Y%ukOv=cKD6fZq{mI+)$`w0- zJ#NYG#o)rHeY^6AtG0mi{7(A9gHFM~#n~MG2CO{`mNP7q9MjxIZ?Nl$^LtOdG3bpv z;J$ew2n_J9%CEV+X}`lZDA5rj+k$wtPyKW0vtD*bP8g$IRB z6i@M~xA|`6<%B}l5EG8pOG3KKzf9Ly^erq9)zxyoP|N*os0q@samH!QCo~fj-T`5 zq^WKt7D0x~Z^Z9HR&-3CU8KPr(IEfO3rMsrM3G1f zmd0iT%7|rrPq^u)tJ}ultnb2+lf{DI#YhD{x3o!WFsUw|Qc3L=rfktvGI zSin*Fsor)7vq`QX;*I=tzb{pr#n+c%&)WbwE<30BT*J~Lyrd9$LtLNlO|%MhK&oaa zE)O4Kd<;?DDxlJsz3V<7_+iiVfJbMKn#7|_C2q;uzJ4(0l%exJc*3ABD!3AI1`66) z0~~S`3a8v+E(C{@r`d5HY4T`SlYRl9=Gv6iN3~=Mfg!sduiUzi5;G=1s5=K0NL5uT zOu{4BbbH&hPW;@K)M5NgmhKKT7ypc~iQaVId)Yk~FS@hi+k2!asrAVu2PR~yGV0Yv zrh?E;@x<~X7TH*mqYd#GLhf)I*Tsp_lW2?ew-CK&6U^7Z#;FL0OofJ}mtQgWmsML4 zyqCV5+XeTzs=J^zUw>+J{bq#d4=0v)yXuCwg0Gh##Vv<*{jknHDdRp-)46BCmQ!)u z==_PORRcYjO7s$bvThu3!%0?I;bD69Q-Qr&875T4yif>X?_ef(*@;EXJZLb9tHjRO zTpO#Hk-J}2S|q%^3!81nE(1gz+r%3E6lS!haBezB!S;f&6{~RKgI`W9vYykAGgHOG zF{T}d^9cP|LB;KOM;SYd@Qf?aQqEQ|%13l{{B!YNp+C)9b|jSh&W!~+PC>LcTFW6PL+WG@{&upO z)@Imp*vmDybQ13t02{hNug#HReUbTmv_P;l6qJA3KvVgRz2wG$s5KGsQ@d3Mfkz_bNn3G70IDAJ{O^1I$i+fWC!5%b^r0& zFbW?{%uk^hCu%(fF#RxoRf40(3E1ycw&tTAno>zQuNfHy8dr9y#ND~|DXV2uhfQ*; zBlKx&@ev2GS&J7I^r+!IOlGs+nbIEsVzzU;C3#o76a~)c{p}h?ge|uc54vAZT>3`Q zYlEwo{-olng36_I)VWG%LLStUZ!b;4W=0}e&qxFbo)1K=sVr*t=DF;cwY$`{@fu%C zYHq9-atWQ@gS^X#nt7)Z51aplt;~7uRFh0U_F@}JvMmYA8Q9_D$GC9|_c8;l_(=O5 z{#s@;LY5=FLumL5%!Vdno!KS>DV){!GVK&%4x;vN6^efE8m{@mceWu7Y|uNTaE8G#!_B6>oz9N&%lRt6hzQ zahV@~n-bo07PvD38?=9$k&qGo%o%GJ;1NY1iI3r$G0R5+KMz=%FFVDgy#3c1J!6PW z4-uUwHKpWB>9)W!MBc|n2{xat3D9P_ZZ14Po(I`#P1qgQU=C|~f1|p7O}P*j+-7xl zi%1Yqtqxg$+*ohhqSxQGZd`Enfp>fIC8)?);}c}7Oa5a?lYpV=(}|NLPU(aA)ta*< zSNK@5W5@uy5~i!SH$w;M{N2)=#&UJUhAiGV<39(f%a_z2ouFEU(OZ(>BT)%=XqBYx ziTEI#7Y%UQl_M!=mqRX`54j3@#Z`|X=EefH{RtJX9lz{;z6TeI%DD0gVS#&F1G*;T zt6GCb8>RFFN~-~hCui?nYX!*T+oFlIMn_(U5C@BmQCa>O+-h~_dwu?jS&QOs!hRKh z*MQb6v5NTZ*y3LdeDru;9bhK{u2DX>Ax8VL5e1 zUUBdfG(itXG|Hu#-P-O7SwdtZEjxaD^P4g1wjyBQtfA%zr7f7JLtsWKoqSMcD{lWt zCmJv4@)=;ujTc<32L2L-H{M9&#INU=L4`^!(*igNj4gdV;^s?n*e@$$6Bvr#ufRcV z=;q0-QJN9oFuojRCJd+#6OraiYkL<=Pp26;L0@9W84A?4lNRjBOy=uTRy!X!a%xDk zVa;Vi4BheZrLdXk-fJknsMPa~G9oCXCdkNnr75gf zjqp{wX+;hyo7TcKG5vERZd_kIdHv*=YW?;R``GAdRLd~$D^aD!eFyf>g|13Lwg-(c zMiYUePd2Pla!J&$tn<9vii~YB=H4BP+&R1tm1V`QmLjLPxNDpnBnB!*pf>?bzr~2X zNT}snA&4e*^%Z#RzBBQM%Cv@bzHo8hm89d?4hPEfQyx_n6q!nhav6Cm9m;5QeZP!F z&iyH<^q-KE_gQg)dRMd|=Zx?t*}Xg|djtiC;knIX6trfZ&gO?Cguo1?22e-TrxC4F zuM3aX?~-ZQ)kV214)h_uj%O-X?UISR;r$svty}8;K zxj(If&F^poqs7(f({9%(^5O0{ARA$9?sf(C%|2S(aQNoVO4rS($;>Bv?@pPPw$qC@ zIn9nU;6Ic49g=Lg(s{_nTpmlr&+g^GRyiTZ`%M}^SphLS7b6+XcDZHn0rb?YR z@Yfq)V@s5(MKnVcGZYarpXvEg9_VZ7WVy`GDqHGcc&4iFmC1hxt4`ys1f-5vx@6DB z6kkr7IA@328n(&@uwg>(^9GD}hBtY-nsbdgNDwENNrIGjEtP(VsO11;7cZuwFpH#H zJ;M-&P{W{S|DjycWE2^=C(F8yC2o?Fl~BMRkGkHL(|1esd<0Z#qfQnQ0gc@(1#PM+ z@}<=a>fndSa~0^EaP_o&hjq-*wzegKt8S&55+X*El%+{JQvBmGENbdLY-OvtSu3|> zjM4{c$IMYqfRe-y%kPBzkV zS}`QHHCkZciO$j}H;@HUx%U~AO&X9>0&Ih`de)cn)`Yx%Cx1qY?@woa6bxOf(;(yq zy!tHCd5GVPh1iMKAdI!AAkq!drhPXsy{t3JZ^H1hS?h?(jF%a1JogmaFd9=~8&8Q9 zuKSc-+*Bj8njf$-iy7=hEa-kpA}r^_f3kuSlul8zTaSH&(g6PU`F>bo z#w5F?MCE>Smdu)`8_QCWWjrFLe}W<9fm3<)hYtAq0U27s0u0|{%#WfxyjagAt4AL& z%t~!@|7HVLmu{(HP9?xS1D4PQqu@pMSIP+{+lt&v_hPNr$pmpXv6egyJMsu7{Ht zc1q%$!ZTu7*z2%b*lE<->4GJc6ZUVk9E^q&&~GM2$X8WI5psm%Nau~O5hY0uA*`lu z-{O?R5MeGwF&72^&8vZjJitXK;Ik*-hDW@}UM?4V*kP!-mVPnmL|>A{d)7kjGLK|o zmwZ(dU-)!7VtY6AY9x%f*xuQvc`3iNCwUc1N$mtUUbe0GrOFj*Ei~3YC6GYM9f%rG zGAH!Zl8PZ~*i=6As?p14-xGyD3S#v!vrN5)_rIbGUBsu-*cKk^1>o=kz9|-0(GTR( zI34lk7_=zV+62Q%W2#$nnUbsa)Kk9S-ml5fn+Q<+s(;hV+t(EOJpY>5=XINR!B-Vvb*0S-IhmSSRCc$~#r5CxL%PMSHU;QEo=r6BcCdc0@-a@@ABtsnW@`7&|_~^7HbhULwAmQG2+wQt<#-@Rh3Y@oQz_ zc3v($t`*|{3E;oPw2VlqQ9|sSbomIuszXKI>hBVY%91G}yM(t2%|28(s1cNOZ4Ta$ z*jSptdo(r@;OGfxi1}=@z_I@efV2K!j~6^ga=uMn>bq1`{~mfno6l&lck(q$zP|Er znLh-SNC;7AREf+Mp%UH4brp2{mlgn&)mexjU5Kv7^e(+~*4$Wi1ILKeFp3$PQdOFB z0nFf&mKu$4#hLwunj^#(Fm^d0_0NXqQ<1Xw0(ppsK=kQ$EvbQFbc+vjRH>w09CF@Yk(l5Bc`feBwGVa6I=q0W~bJ_;dgsdC7Is8dE6{#Y0FFId~I?T`|zL* zLQhtHFb+A9oK>uch%;oBRd$AZ$l%Z5gcp(-XP|$nd3+Zg67P>2%PODZPzYsy=aVE8 zs3RARpzYod^&i4q0~Bgjfazxv)ec7A)ieD>3ce>RwV73Yu$XQ-pR>pUA36oR@DaW} zUR7C89Rx7{f^u1OWY7p4|7XpQ^;nCm!}upbbS8-SA@&xc=~%46+g$IJjUXAIf3h^V zdyEpJQCyAg#-}O1+zJK=9J$)=Myg~D=#Wk~8Z`;-k z>?*S==2DtttcNRx$H;iO2ZRiv2H)cec$WNt?_ty$a>}K*ySeud%b$&vD>t+3gH0_N ziymu@_Rd9Q7`u5*uQUM`n%n54#O^L)PWg7rWui*D{&0`MN0V1ex>z2iXnO$2+3rHd z2B0kCLo@KlvL#v2f~g^LXI>gl<|p#c3O*)#FKT?GJ4aVIhK6;N&Y~UkcyJj`B?@q9t2e%mQK>)=h>n)67WfSPBcNv0 z6bR;4ZhTWANK~5dUenvzOZ1hEnW?2-libJaH}P`7P%X(h_xpsy+deINiXwM|Gh0dh z{pc7|^l0?qEVFKnYmv@e2>>S$amwWV_^dcCm5QX?;mJSEuI`|?&88vHmT$GBH0cRn zXX4^?87beF$V8=sW$px2P)SO?xsw@qE_?8dju>Lo_YD<2=*42sW=i6aM`F;WVodK1i*cj2F<81}_cVMDO5-hfK8R#-wcGn?hT=Y=sRb%j zFoSO2&3IplWC3U@7a0)Ps`9s;-oDX9BptGB+5@YE=r`RE3H*p$^(f(uWhIbG#`W>-^ghf z+6Kt|h7-2F9Qx8wB>wHNAJAGTHfX}vs6yE4a{#Mv zE_~uMqqK5OvVR22MXKL_IU(Z4jnk0wb;_534FBVU6gK9x4lktmb_cKa_{4iiM2_dV z^@og+k}$iB$6VqS-RoLJCX7s^{*M^Uu8?FE+~WY7MSex}*Yo(hsLAY?Q`^x))!%lf zfbU$RTfk+!C;g{jya>!FY$c+|N=XmT4yYf|-t*1>1gnE*fJXkV-gB+JO;{}zVir?V zE0-{0%yl{;O?R3aB2uc`D9PjeT79SDag`e*`x2*3z={Isq|$I8JR$cjx1`9u1c{{% zg`=%Cs3VS2&7Ko|IrZ+a<8ZKK6HG(A@?;nf-(>J@c#U)Rdb@t&FGQh-mV6~?)v^-K zA>Y`aU1zs$au8qS`Yl(w@FG77T-(X;IFM~20swTK27hR`n-l-bk$ohKcI5V?72xQm z`M~v#NxrWI$XN61`HeJIgsAd7$1ige5yx+xOIyag&JBv8k!c&5J%2MxMOT!|LQHOJ z`&iS|j^Uj&n|^A&A*Lwl=HI@^W>#xDRUTuvu)Q82OEnlo&K9ka%d%GOCm&-vc77@v zx-j5hc#m!?dmtff)2KH?zGcU$q_3l$<+_Fy+Kin4Jy;YVKH(BowHsA+8Z~;zPU872 zkQ$tXE2&qWGSvOS)7&_VN|YLAYL)&9CadgkBWEa#7u8`g$t6D<9X79W;)P>^Erk5FRR?ft$JB6ww zBC)8IBuxkC1FcHD0^A^zZ=onLfAOH{{t&jj5eU@zWmSdryu9DP2Aem%ZD9pQKHQPg z#K0+o(Ii>3vvss4Q4vR4OJDeGWo;Lnp7g_{zWN9d51^aTd@^=NcX-4Tu7QEWW)@7s z8}ewl#X>S^dd@c4S!Wo3o(=5=_hH)^%Zc*Z89f&0;C{0(-KL91=K)%qMJN9tWuXzj z?7|duhvaPLq_*Q@^>7H~PgRP;vG`Ti`zkkN@%h6X^1(>yvwK{RC(HA3bGc`iSW{Fr zdXrc0I#43_c&exZ#r1R=(<1dBUwoa}c4yRpi-4cFN?OZCMR8IxDu>-%(()$th~i#! zmFRJ5YKhQ~19bNPxSjI;@zx79=Rj>cL>>MT@a2cH7uUU`pq|VZnUrI_1~n*_U>_NJh%`k%~3@cY{DErer{v<1bY zH=B9dBe29ZEMU9{=0j$svOZXRoBKV_fz%0;6-L3zUh4lK}|&JBBqk z2Y>tGQv`f&H0E^FXl;Um%V20-Y~*G|Bk%r*EBMB-xz-6fdYPgef{sf zLVgE4snWy+R$Q@=J)DVm*%s-Hxs>LZ67IJ`%qra^lA9N|w}>ke&t%f{7B@a=6L0^~|KKx;VSwuBC~$YdxmE8&*2iDC@7C z6Pa#ws*{tbY{{r>HfXSG%3t$sbW>pC^d7%gmzcB47p;t;VIE--QYkCVs8%CaS=n&L zr)W=Bb~|*5H6|bJc5R(-Yu9Tw{$L}Ka|vnPXEN9GweS6WrxoIdqYT1Hp30-7NX?=k zmnJ0>c+~JwdGIf9D^mTvIeG#|-i@E_jlwfB;$wDFC_+RkOZ3&d1@S8jRI4(pXIlnw z1oIS)Qewj#`idMC%erQ@xRfNdBZC4;j#uXH7#djV=&mZ*{3ggr#Sfi*$hhoWyc-0S z>nG&kWD&2CXby>2A~N5S!i7JB5NK!sI{2A5zd@<*;MOwbVi~852bcHb4Y{#mI%}%W za}^3A3|7}XPaL}Thw|m@=V}}0Lws~;_6`t62tnsq@Nw5?x-bts z-mRkGzAI}%jhYg6v4e{BK&zT?4+gU-wBAv~gI)8X{*elaaIh$$%yxKyXmhIVKJD66 z%;__AVoj(im6pNh_M&6=d6qF7XH%b2!`{#!TduwD7b>TWb63BKi7X7AR7(2OK}_zV zw&K1^*5nEhRy>2(keOWqwD(K}E%eGz;mgMw@Bl$61a0~pd~_&S#GEeem00ImTRUF2 zqe9BV18HkpHv;g5)#bCr@J6iz37f-;<7)=I#Z=sz*E-&rzC8K%*TsD!bSo;CPDa<# zKD;iFaiNFRdQSC;H?`tb&>c?75W!!r%l7*t``#bzFK+fUS?jfN+0Q<#hM&Hj+=Jbw8RVPycctYC#I{9&q;`sc#i z*!!pXfqBU7x1gKfu2W-rJ}dE@RdlzJlCm50_i3^qqI`z>U`&8*ViccXZyLUMh%M~c zt{%c(IuPo+jcq0R9{e}+W_PUw8JThvi_}wa^x(p5iFJ2XO2&_@6c&r+x>M?I6qrKm zDk~v795T3zwZtq^V`H08?F*d0i<6k*2V^R<6wBU4(&~w2Q%vdU%9cns>U+h5`Zcml zI%t>;A2jr}^9?W4NBmTVAI4dJIOV5NlZS<=?2>~sSe{k_e^TQfN2jH~=8t9{oEht`Iwg&-6(?Q{dRtrOiT%SHP9&mQyX#Nt>t0d`d4h^nBx|0UPFrlP;#^%(1YU#&3yq zMqGzWY&kkU6Ep$|OUp^2*f5!d-0!k9AD+Qd+!_q>zFIjh!Q#lDpgFTD%-}NZYS1Zr z?+1hx-E^gPu;v4ASJDFnXg8B*C$CT^TIPFA=JR}JLnfjlT@^n^`EvfSe*}g0ib>|} zxsocCwIOoMiQ$xW$9I&4b1%mMVlA~zGs4kf1l@_T6Rxw=B3~*dJ$Oa za@{TKOtXR-ljCxCXWg+!C9Ryiyb?x!RD0N|-c8*>w8r_@i9)D#U!XqdL0Bb%iBJS} zA(Lx_f=Rs0yi;3Nq*U=C)mC+(&?GwBZjwbyr9s0C+$H^2O@~l|s{V$(TB4kXrY|d) zJaP4fwKe;>M8irkM4Jy*dq&>Vox&tOUJcZrfjngZt@+0G^n=S9oUfd#Ej|n{oUMH1 z@xpg~*gP)8x_wvX1BHdMKS`Id>|i;b7TnW?+JpGFMSt73@#fiL2SHS`N18WD7^f;N zYB3e%<B~RM~I*loVo3w1}Wc*#E*8-jK{l*K}yl%uz z<8b9DgsAvsf6J7+^lI8N)v81p=x|} zis#D>;cl}KGF}jzR3wnG_0)Rw=6xlBP3Z3P4l3YiHHJ$MV+3!6;wX4nisk7Di#$|@ zC8AJi=^41`HbAdZT1v602XpZVYI*d6|rU0`4|K`>_w(WZq--^ ztFAh(uxN4<5j;wGcXO;UT(pw$B$+>MxJA8+XG+Uw|JcW9CSq{1TVF&;|6mpg=<;9^ zeW>^Qi829O6i!nNNuD-pEpMs9n?mRF=sfaHf}*$^rl@9Ora25DGvnzcZmd#*6YcEo zpM?08F$Sh87YR(Fa(a;;o>(i^kXF5db3d7hhik!RmB|E3yoITa!#MsC4CxCdko4JDVVre^I2 z<=cYe@|-}!z%Q&yC95kQ=R-qB4HYW5;I2}`mQ8hCM?vr3y>xjdo%GJL$WI5fcIy;{ zVJGH}h06o+HUAL9rlzv|?*#=l6<{}h`5ksXT0@SlPD({o(D`N?%YH@CljbljLv0g`oG5Pf*`GVz8pK;b}k^Dfh;V@O`Te!5Qv1&E#TV zbW1EAZVkKZHQ1A+;qK8Op)bo3o1i+uZhZj%l18C<*-#d*Q_pZs$)TGwg)X9*)&e*G zo2VCRN$*OTfPS_c1i}2{pn&RsAaPJ&!nv7{2x(qtJ)~R$W4z;y4ut1E07ptXfvr6z zGSr8$YX|361!-)95xZPJq*-XBF)ZMGA9Dx!im&RZS_yY+A5DOh>CyXjn~rdb67|&5 zgSeB_7nfT}vGrH4YU(A2K6WhEx0Kv(G&JST>?d;x_2Cx~V#m`x*4hV4cf(7~a~8HA zwWJn3FG<<{kVkds{n4_7QP=`;)tt(DD+iza!&32jjyzMVE|OQzYp{!>JaH8Ku6H=j&s-SKb@wU2``Fy7G z;C=N4W_;&kG!9~Uwo!EDko*x&^^1FX787W9(>izM!lEeG*TN~~@jV@>z9;+nwZ|Mw zyJd?>DeJ2b#zdVPL@clBXlS}16G0DTw;koI^sP*vtlIsH^LZ<$zpUcJaNhC@&S#C1$%D z_`^b+5jt4vC28LDVq99nGTS}{SY5{KbkmV|nm>r6dkA`m3i#7s8zeshRbS&a6@6yU zyJp6*%eIcPsicaskNN))xZ|KIA|T$;#Lr9@`mMoC+7br&IhCa z6hVa-lVQV5XB=hHTTtA1GYSllLDpusZz8pb9sM{)j03>qVfJO_wvQsEV0p)@-dZYM!l!$B#@LXIcu zmGz5%4y3gJqP1l9#U)dxa*Cc;uGSU;HnUI}ee!g&M#pvO5fOJN>m|-qV9vZ>n^Q7% ziEYHXo#sfORy7s4H?$`q+)&QU#+!Ey&9?C)Ydh{zZ6(14G`^-u=MEaVy)ka%xX)kk zCy^|Wa=+fYnM6CLs*Dq5wQs~ug~$O+PDB_(3yn|bL%{qh@{&~y?d{7!&HWKsV<)-0 zttOQ)k>vr$PwlUH>C?%1=lsilRJdl#-gllgc*zuD{xkekxy11EPU*m>r&sdMLf>l7 zxH+u2Y-7y0-Qmco!JMziYs8XAa3D^wb9zXUTt(K+U)>AD>G^PL|s#2k4)Nr zWQfudRVs}?#QgmksW@?5^o*bFjc?j5#VT1=K8NqKVP&o7oqtcC{xbXHX`WWH&rt+$_ z>2*#=(2mP708G5GzaX88g09c0Eec496C-gTZd{ST%H^Cw#38ZO^46SeK)o! zC!t|YgTg`-SPf--J}}^1d=6s)7c!gq<7sdE7RaF--fH(5vR~Ja^R#GLj8q?(B=t7w za41#>qeChn2$}iOmA+I%-%P2KP(ZZfZbH#9C3YkY>qbsVTej*!FEF}l!dQfgcQ81} zq056F$HBD{msq)?6&M~QxEGp}Vu{vw-RYdfA^CEpop=a}?&|&(+zu9X21*WRlLeH? zlCGVS6Kaoz!4h?FX0d&#v#h3#yzjH6K&%?nD!b6PUHu~!3EQt~#s7ak25wncabxKw znVMU}O$@^)wj=n$i6Z{$(Ci}GMj?ztWxGu`QTYqs%V z>`?11h)@J)17E8RZtS}2$#(*IoXrHLE#TMs>E!js(8G6Bb0+@WsJ^yJIuHIFs$r{~ z$19EI{Ru55{)mahk!ijl7y8>Yevtedfa^4ilI14oa{0b2X2222f3+imAOf;eeSW5N zSDJ1!h=ky~@`_F{A zlxL_<;?X16AN~D_bV~_K=^j)Qc@i`fBe82dZO&9sU9+%RcwdXB!xFb<@gMj)9!V00 zNG2!Dirp`RapN~j2Gf2QRIVjf4drJKFr(gDh5wn4%BPvN{qSQQdxh72J)%GL;4)br z7>V-u47?AZJdph$ovJYpAHfFR6Ha0I$t#BnZJkwPJl$!JuYQLsH~LT1)G6t}(&aTL zGLceJq4e#^k+1ts*`h~uUzXWX-Osd15Ig|sds9%tf~g#K-{0fg+8N+Zz&o_fV(9fU zd-FGzR_v(i5w1R29u6WxL{AjvB(A!O*4*HCkju5 z$g)((4LA5#ggRw#(O@Bqd@t$y7fbzIiTt;-$EU}eFaO!{4y0Fo>M{79;6`(`Tr#W9 zo4=FfrVh$~M!och*M|Nhrl&@RK@+~Jn^G_6h94y12VBKG7V|dTAFg(}%h>qXKPdLL z>yLBnRbz-v|rE`&C;$Nvo1$7wje?(ggCQM-vg}i=)edhhcH8c|U824vs-&Big|2fX&p~WjBF%{$+YuMlv_3lf)KR)ZZ z;}_g?`ryK+Ov@~ptg2{5^f~GgIfo-y3H46pQCw(6>114u-&rOktBR+310 zO?>6UD0U1Fq80bP0f_lCl5yg=wTf%P{+AX&&$vZBtaEQDBY#1=-nT^DF9XCzv4_=C z89QbMM8l|{6uhA+`-~@mNB4U{e0Q*4Bt}NJ#xXl?yOQ*Vpf?BFfA$3xd8rmxW=b#2 zHKe<+<7da^2w$D08%CpyY0dU#Qp~k%=P;7r@a9)8rBZA@Ql6BgSGLFhmcoVj#^WUh z!#iOxLB7B!`0)^^T!9A3MDKgnK5l$F0KXXX`OD_Bb_p#m1mpnq@mJg>6^!a}r7BfH-G142K?SsOHf$O5ry*5^I{y->Rm z3K_GTiNb(3rCNG8_w2~~4w4N(rGl4?E4XtmRVNr+k6e@STt^obN#}K|P0bGvL&d52 z0;rlIwjh~n#B=@c!v%Ny21`EI#YV&|1BL&D-mO+rwTGd!;d@33d~13mCF2@Myu z)Z#TZb8}%-QM;;I$0Lqlst~O|=q<{moI=TxH6tV>p|4L#Ohb!vrNefODp@ns=dZl9 zXYqU)KyDd)>Ix+2A^N{&wJjR`&+M~ToiswM|G($Og&J57qyZih9zwJ^6(+I+EOCy@ zh5pTR^A($-L~-*yCsIK!C2wAPQu{Y`t@8NzRh#SR+b*aP2vB^`6_%Wc0~9dks#`2L@s~2CoY5+EU#?3bsfG7CLsz!_%}guEnBdL z-aLN8->xnF0sD*k;l1SUJAeDO14+@S%>)YFjnI)y^Z6cBukZIgl0&SX0cn(eLY9y8 zz}9-;19o0@p?&zXTh)e|W*!`WzDurWaE|6|F(5Jxav4T)NKBtD_y1n@8s+j$9I%KlV9aHjCocp0OX0kQ?Qp7J_9!Y(O2w0zNce;@MYG+U6P7Azy z6rhD5GwdpAT;Q7Wu&wquzTzDsCVym2@HAFvi$`~{@=9FnWso6u;tFgpy%^tBu-;40 zP32A(rT6k*)9hYgB2l+-d_eg4`CANn9J+$5qAU1;?6XI04(`RHR?_l(>U`=d%lOVv zrfK$`d_TtKdaBnGBd0+!<6a4n!0wxB-Y_ng%^OwisW%-^qbpnOu|qDJxn%VdB!Fh7 z4RVJeImpFE)S5WH9K&A3T6+k4^)RQiX^?la16Ri;`D6#$`I$(wC>jiLRxgknt)AMy zTLfB)%W1&7$6*3Obip<~sk#nrpBJu)yXWvdC%6aFTNBiTX6X!9Hb#4P);v&n@h8Da znz*w7m`F>v^?Hi880}fNEbXSM7K4nPBx}uKULK0?tHuV_N*C{@TV&9)<|PgnTLV*d zt9I;Sudl4;(&Ygt+e1;22-S1qOC6c3ShQ>46V{Ai2JK_J270)5x+;UM>axA5Ql?8w zk2pu@i*#(?-g0H83?C^e8Tvhe?{7iQMKXLeV-e)2wrRuliEO}*k;Y89u?Y^h>m9Qd zw>3wX?8+K=KBBt>Q#@#NzYa9^HAeO8N$*`do1^)t9h86*s!XyE9W3DR-b2|EUZ>N& zQxaksvu@&Xfo{M(VUQ`79mTkhmq5cKhhJFuCN&#eYlfr8@c|^CgJ3A#7GT<&$1;e+ znZ;9SDHfUH&dahb7WGa%UxHm9(Cdrod99 zX{swq3~{GwbbC*9m`UOt7UrR)yYgLK0~aU)clhT@C+h`=M0B{`^cgIznlpO3x}B^a z1m5m`?qF}Sl)gR5N?{YN_P(g<_V60#>?LjDOaXzcT-u7AfE;Q|h6)>x0xiTlO>C=*caxpY)S41Oy7}mp>DI5tG$PM*BM> z?Np-a<{vCzyIZUX64-PuU3S*}%HT=8jI>=(vgDbZBc6&r)b9o8o<1BUDBLqzXpQ!u z9e3MyDz=^o3#}iB^1-#;(Hqv8oK4{S#uzl)JreP`Z~H9dVn+7zgwljCg0su`e>6L-IL)7SAMy6hT9- zYNS#xudoTO5elC&T~E3&C^2+21z$M>PhMWf zJ)2m3u}sYFAbec$JaKR&Y=CrXyE%pP75+3QM?`jq&Oi>vQ9Y3zhwJha<41U^nzb01 zlbi?Z@pB%G~DeLT_AO;PX~+XK1H&EJcx>D1$Dt7{L1sc53C>kQ*PUiWHx zWfFc~JP>8MDhYFIy(6gW8af(&$#=B9UE~=Lw0QZH>50?QfUAm(-&@B3GTiSOpU<-K z_f!m)P8+FkMyvLk1ds5bzC=ma3*(W$^I&|n>vH{?$jmh~mBD*(7K1V?v+wNihW_x$ z2CnK@ru&^*bP{1&Op;2_M+9Ws<`uSBN_`r2=%9lv&gCwb7eQWjQ@UYv`*`!kh9~oM zV~q!xljzu!E7C`!t0dKk_R`bAz0AwSw>eX3y7#>5J9E_~^FryK9;I}15cm4iW*x^> z%%M*95zLXH7CzeCu}8M-gCmix&t9)4+AlCbb=CCCGuwd5r`vCW)@i?_4DaI@QZdr~ zY{B}_`=k&z#t&)9zI4b*G#xgdo~+If)gZ*cJuWg6>R7ou1=lto94{R04r4 zSya7zVycgmE@#dh3m3$K4A<7uzP>NhA)$;Ge0WD)Gb0RBCMG zkWuw?dx+Sx7hL!46%J9QLoySdGo}f*3;0KyY(8W2UU?0AK6|%71at{E4U|H;_MDRo zOP#TS$4IW)U3GpfJWX_V2nrSNOtv|OD0A@xoXOFsV-6fu@gm8asB*pD!Zz4rfPlX? zKF!CD7M@t7Rq%oH9xU4eeq@2ODbc~4AGatgLLt62e8iRl``OVi+j#{>uh_Pn5T=8+ zZo0g?T4+OJ#h5Hl2 z+2%8Etr_J0A@dZ<`;bYBgnF*MNaF@HWt5>!M{rfD_0}OTo29brPV_dr)_(l~`0cHD zG!1i##b*DkUyUA%A-U_8$%=_5ss#1G+Y`~xI`S_Tj+*Hptd0%0N?HFq` zZm&*Ved1$Sgm@3&79Y6@$g_I9EN)VAQvCrG*&O$?x+;Zt(=|@!o1IWzZ3&w-ui+h? zDfn9KUkq`Iqi1Tt#-l@@$cp<_qt^a;O?P4LMoL2)KN#g)SMZ%MY z(s4|(Wb*3%&7%A^nv&NP=yVcZD%9mYfvJ%sdgf|#>{!K;8lbFaKw-LX?D?d~w-L=d z?eQm681<*ngHD@yYF#>7qp4oA+oN(CW^06H8!H+;aF0^M)OPEs(0g1Z9YN$>4MRvX zF|TY@>4mu_qJ;T8=cpHRe7v|cEw2WPGhcRld%NBAE*C3=FHs+ow)tqeeyP3ZtY|JE zUG?m`pmnm(SCc*$dJErmZCQsf#4uWDDK{nVAk_d{xtcff&&Wc;g>_pbLot!{T{aeP z;#e`1v_^}ayU3sj5^ksBa54+{mT=^NkrnJgK~r=(%^Q8r-1#Q@sNn9b&28Un@D!zw zsS~_o_kzC)igd0kBxe_}=9t$N`iU9yo9D1g{bi^rsM3w#i-jK2vaFh{%mSb)q_+TX z3!~kJY!K3Sy5IhG?sk&TzGCRiO+jR^RoNKP2f+^e3;wjP+QYrt0^%V%%|6FbQs>P)b%LXh> z{^=9!_zs=9m3>8_F;9qh8R7#_qJ{mYAf(n&cM`YYoU_`HV{o?7$?PbY#fQf-ul&Mu zgMx_AhpWQky+9mG1=2Sbe*fZJG896wHwZGFW$rY1>O=d(73QlWBp%>ws;6p)vk?W? z8t)E?&8yDWI5w;ZHUYMxZx%_1o-BZ=$N4I&_wFWv0{Dd;!y6CtMF$C2U~ZS~%dJjO zw%(yKqU<}frLg@IKZ|gElWCo(YLSYBJUsss%8Ry@V;xLzA3L`T|1*mi*In` z^Ied}9`D!(Neo)HUC0%XXfz;`3pilseBt+$*5u5AKOeWxrq}3Fic`#Ja(BnPKdjn! zR%|9#ne7AT{bOmxov%QVG0r=Bbv%;KK$cfRFao{;w2!Jxdy6#T@D#yq8v+kPOsp0nLcxpwu)+TQ<-9!?{W14&dVZ`mqTYhWbO7otavqiINhk)`iSW8+xpb4 zaB0~?RmQXOxU8solkkw`-LRQ04A!TvdD`67i+z2j3UcC0Zm<>l`VB4128-8wSzi^i z3LpDUzt`G}=q~SXU#(>6yDrlz>AadNIvj8~ZL2*rN`?IpDHuxv z+6Z!u{h;Z7CG8M#_xetq`ijrj)%R6JOsamj6A+FPchd6q>S?z2hpcBMz9ZUZmIv1L zAVvydqOXa}+OuwEitGKBoQ(HU0vA=$7=~o&NOLtDcYjbncgzclhRNSllyowX9$Wv#vq+BHwCnf98 zUm3-4yKOGjYV4n{=1yR8y~-(D^?`c8$6te=`$64;W$Gd8?!p5cQ}ao`d)Yyil=3vK zPd2!&Av5l|S}No_Hd61GE#O1pz}+qI!Z&Y#n92d;_B>?#_Pof}e8G~$b=4bt9DeJh zhsScjE{A@bsk|LFuOqyC^T4!spfMS7=|#1vfg@I+aqnHNKE=;*|I}28Li2YqiLmWH zH!A3G_@amhE50Glgjs6^_GpaM8*E7g^iai+O_A3fK9`goqZM+1beqi;P0Evc$9D|0 z;g0T-FY1O?&0X!>Al#@Zz~`*6o!GZa@qOltH{7&Eh+y4`M&q`Ibx6Ql>HNcGavL)iZ{XI}@hZQ*$FOuUk-_t-a;5-l*Q|-&%Ve z@?MDjO$b{uMmuvoLC_N@7Kb~Ra7RE!xg%cVYZ$#a9Q7?jHsf27SS*7(cl;YPxxPFJ zGH6^>!kj8?7;copab}}0N?p5-aGWoa1{`L>;GUhHo14nbrTnx{XaE8n9k(m>m9x&Z z3B=5hPAjHEAmU`{&Iz(oJpeL9@#4{zgs;L75hY*a4ZzzXL<1*}@6=GV&{w408)lf_ zj*?#;$@H{oyK-a8OweBLP3AF06~DR4mX`cf6&`e#*)qXs%Y$V4*jEW7Cczymls1j; z8%@f_)f8 zN}!Q~0?Ww>Qn5j#^i*Tzx?CMu@-<}CxRdKp3sAN+8Jn1;$aRJmh>?gdQuo8kK&t*e zwh6;1y>jL~0cYmgjyib;|8%?ZPJ8J@ws5z^^|45_UR5s2mjkJmufteh+@!;NcI)5P znSWqOBJL^sB88`>RU!pT?1Hj5-EI;~=4vTfgvvI+k25;StROdyC1F-CF-)XgqRk3l zKA$ra9F+B2!Ah zRK7T9rvfi~vi_s;dc^9_{WrSwkOu~jYqOECQG8Cewkk_7T8jD{WDR>wbqoHxpx(jk zFP`{p#xe3-G?TT-Miz+ociL+k;d`tj<>P5tc-d~kXwq!7q#f-&jf2;g9S=z}A3{O} zvV<&}VJ*KEdm(V z2?-=e`&oVv(fL1cR@)))KgPH-E_KQ&ud@SxdG{Cw1jnpRJXt0N+S@slyYC7#G-GD zRSo7FBLgC-;ii5U>n1`5HZa(<@Pqq9y|69ya;8u2cQXiuw$|O^>RQcyl?iCKy}Kdf zexS8^y{Y#kcRoLN{kBgaGs1Zfb;AM1%oAcJ$`%byR^`aZP@UQn(w3fj7dLQfAqc9x zoUh}<1$ZP+9A7=wJEaluH>jL>U{y7zf<<{p<87qW>KHJg_*2b0@;(|@ROZ|D){9Z)U$1bZNWntl=&Hm#!>MxueBNWWXlBJg^rySZEttuP7ecy)^pA8 zk+k+Wb!faD12Q_lE0nq@k@su)g+R^*pt?f33Iwi2(!zQ-Q6uk?cK0<5SfBD_mls4 zYfPIgZoBK-+RBbMQUxBoN!|X23b(Q2X4wS+c z&)Bz5^jGF$(6<{Is*W=g2XoiM`UJQA^PaqZFfK^&&I zmjTCly4EzJDu`mFfb-2}hg{Kq{Uq-@LKz~Q5f}y?;j2!H)+-@o^M25I=ayCQ3UjEB z>m|j&c;r&OTdvDP-GITXWiE)YT32!y%VZN0)xOGlIN7Obx_V+Scn;8I|M190Pi$NH-5L_skwA;? z{Aj|c7cWJ04gl5gmm!DzFj+`G3{T3_ot6*sIJb9uBB+<#d((>FhAB()_(`DMeM-VZ zi<+h*vyavg5tN}b+IN&%b$S)Xgxq055FK6ZPv=*R$)c_zzew~LYn~0~uo?>Q4(LFO zs^{#QrQZqo65!T+P{K`QwAWvU(Cmt?$d4cH>B0=p&Y(XVqRx93V~a@>FEfxfYNYFk z0icwQSH=JheUEyW|F)$0jh_3orrF}fNf-+t4V zqi8uAjc9gw-Qcx6ASclGNO&$)=}n zot~{b$0l=4(8&5WM?5Z1tpFMyaiFUXVui7kTyY*{G8f&UKzW`Gh?T+M7Bl z-G(Hc%q~*8uDZZHx$D0dz0+@`OCR)vKicZOQa+eA*&y~hHI^c3HYOO?J|Z#iWhKhK z<;fm5>$!=QJ3B?UJySrfGrT2O(cJ0{w=Q#8R$4)mark6ui0w0*y4No;G(tl4@tpQ? zg7Pmi1X9u&KPIyivj-b0g)cT0w%ZRNkGg|`qMJ{oaA|=kRcQo0#j=dMFh=-0x{5_Q zvjj?#Y#5lD^8|t^wZZ^&Ntx$GOooc3I}QoqaqFOUrY09)7vLMpDFg+)Vrr4dwD$vyoSU-;jp2NO&e!*AT z(cqus1d%NvPOx9O|J?q85@(rSV~oGr@16r=#`H-%DHSmiRzAB|T1F_imma*d)MvaO zM={3i`Q5q!-Sv#uwG?8#a9T`wmPH3OYB0*{7C+79x`}GzE+Ua68x{pVCh%o{D7V?A z_&rROoWq|RFN){B(THw>ECWAjMyi$j6)kRM;|+a^_&s{D`)lQ|=4%VFt6iFPlq(9$ zGb4oxa2wkc~zqlTwEa z8Sr4qbhYs*JoU{j{tiW-$NaX%Q2@}QNUOQ5Y`t|5gkb(3V=NFPhn$RG(eQ1&S&#si_ zu|$v!r}C=67`>!wq$9R7bAK-iN@6XI^0TVpy{bwtUGoa8`4TW!dZhcI^7pjMum#(B znO&xc%}x~y$iTaBy3@)YwzQLeq=!eQ@!>oE;Sy7z_XRMkMh9Mhk#R5nc>b9!CAJ~g zg?R|UAe@0GJI`bsG%!~;Uu8r6k3A$M1*hMyLINY;I3}7pOH6?o;wjqb0~-OW1=kb# znPR6X4rsB^er$r}n$(d^^AsYsQ=6&qA7y>h#g2-IESm7Zdu%(SZM1v>ei7NmuykGR z)`Lc}ADeo3S9<}bJKRwt-T_T+@Gr&$vW=h5$6jIaR^G&98CDe+eyGr*#wNXRo=J_O zB;s|uz>Vgw+`s?bRp@etH;E^coMH?{SF9Y-hMkk>dM%XvP+q{nZB;`7&Ren{f5Gr2 z!F>_N*(pKo8Il~Q09)|LFB~fgzhC>);Y%~NZ}II9H$F*R5)RRT=Tn2bO>39ut@8AK ztNNqt7lZI~J9i@<$7*Y@=UrTZJd-LW)@BcCwtY8U)}jhG<=>`stI9D7&Q`}O z&ulb9nxF`EF*SsR1F65n_xwyYJ8o|P{%6JLrc*0e*5cR2C(hNw?)-B1^a&18j2eA` zvG9Y#r^?N&-^N#@l&|Y^yFzAQ@(As+!Ap( zr#&qp%ki6j>^6zdC&+lSHCp*IO(&Zs@MuKdeH@AJ{@83a^~W01qeZM$JewCO2nSrT zThwh)>U~YB*B-Agd=joOz|)0_k^aWF_k+^ZI1=IV`T1jBks=k}c3%H6N4{ykhi}xE z=yO)KAz@EU?@e{yFtJb?tnkL+HMH3;Y}7z>zbF`?k7jwK;n}$7KicxvG!7TfwB!3+ z?r$XdzV;N=>1>bCaJ$0{YzeldU7Y&me3a_dF1LUlCQ9G5XNAr?>CyCN<;}Mv^grdNwcuUGpk`HCr+I zV7=fd*S0P4*|&Y3@X|Ias7>mp#e~v&$?~kg9Af?=lTX#G1)Z6;@lOw8EK|` zirLro)+LOMh(n0$^iDWHt9gG5Y`9Mu@Bis3un9K+F1pevO%bE62XAK&wn&Et>Kk8# zT~a!uHuCE&4%|0C`IEJabN~Kc#m(F*We#lSAIj*TemfShe~Tmuc3JL+y<1dMIf!oO zAD5RA>G*yC?^}t5PCfl2@IC!suKoA)7a8kQhpR<2U|^@BqNHZ=XM3b{T+#`}5B!+& zM*~>ag-8xGb~UP#jx;D{#%~Gu{^R@7E(c2dM6Ngm^~2uIVhhiQHoRw2=t(dIuXdwV zCv4kb%5Phyl|gIT0<&F>&9OKJ1To##7s7`ugOr5THTrNsmR8NpNR$FOPKjH(jk-;+~hEh8d^ z?K@vRL_MceMUi5$kNQp*C52A(KV*Y;R9S9>qnEbLK;vZ<)96F=qCM00rvZvmP}$2O zK9t2Q%>2r1RocJ`uh~}x^+iJJG6E$3iu|uAy6$XdM8VJM)YzDhUG72AOMP7`Xk5-( z-H2GhCLR+CqHbHF_5!W}PN7nw4a_+N3?xf8eNK#WF zPhcB;Cur5VsUT>@)mg4of*=K7Q0W$r|JKu!OHVjAj2uf

HpBumD8A%1# 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 OABwVSGNrHIef%Hh#gStG literal 0 HcmV?d00001 diff --git a/docs/overrides/public/admin-settings-federation.png b/docs/overrides/public/admin-settings-federation.png index 215861b791609b46bc8be4c16f99800893277c30..de321fdd2642c2f97c680cb122f66f1b32272832 100644 GIT binary patch literal 122978 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 z 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

t-$Y3l*5a;!kucq9kQGRDB>5)UpciDeh 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 literal 97674 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 g2JYkQJcMukq#4(bj-r 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. + +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 @@ "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 @@ 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 @@ "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 @@ "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 @@ 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 @@ "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 @@ "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 @@ 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 @@ "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 @@ "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 @@ "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 @@ "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 @@ "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 @@ 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 @@ "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 @@ 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 @@ 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 @@ 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 @@ "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 @@ "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 @@ "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 @@ "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 @@ "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 @@ 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 @@ 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 @@ "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 @@ "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 @@ 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 @@ 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 @@ "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 @@ 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 @@ "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 @@ "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 @@ "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 @@ 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 @@ "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 @@ "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 @@ "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 @@ 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 @@ "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 @@ 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 @@ "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 @@ 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 @@ "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 @@ "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 @@ "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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ "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 @@ 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 @@ "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 @@ "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 @@ // 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 @@ 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!
} + /> + + } + + ); +}