diff options
author | 2023-09-21 12:12:04 +0200 | |
---|---|---|
committer | 2023-09-21 12:12:04 +0200 | |
commit | 183eaa5b298235acb8f25ba8f18b98e31471d965 (patch) | |
tree | 55f42887edeb5206122d92eb30e0eedf145a3615 /internal/processing/admin/domainpermission_test.go | |
parent | [docs] Add a note on cluster support (#2214) (diff) | |
download | gotosocial-183eaa5b298235acb8f25ba8f18b98e31471d965.tar.xz |
[feature] Implement explicit domain allows + allowlist federation mode (#2200)
* love like winter! wohoah, wohoah
* domain allow side effects
* tests! logging! unallow!
* document federation modes
* linty linterson
* test
* further adventures in documentation
* finish up domain block documentation (i think)
* change wording a wee little bit
* docs, example
* consolidate shared domainPermission code
* call mode once
* fetch federation mode within domain blocked func
* read domain perm import in streaming manner
* don't use pointer to slice for domain perms
* don't bother copying blocks + allows before deleting
* admonish!
* change wording just a scooch
* update docs
Diffstat (limited to 'internal/processing/admin/domainpermission_test.go')
-rw-r--r-- | internal/processing/admin/domainpermission_test.go | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/internal/processing/admin/domainpermission_test.go b/internal/processing/admin/domainpermission_test.go new file mode 100644 index 000000000..b6de226c1 --- /dev/null +++ b/internal/processing/admin/domainpermission_test.go @@ -0,0 +1,280 @@ +// 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 <http://www.gnu.org/licenses/>. + +package admin_test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/suite" + apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" + "github.com/superseriousbusiness/gotosocial/internal/config" + "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/testrig" +) + +type DomainBlockTestSuite struct { + AdminStandardTestSuite +} + +type domainPermAction struct { + // 'create' or 'delete' + // the domain permission. + createOrDelete string + + // Type of permission + // to create or delete. + permissionType gtsmodel.DomainPermissionType + + // Domain to target + // with the permission. + domain string + + // Expected result of this + // permission action on each + // account on the target domain. + // Eg., suite.Zero(account.SuspendedAt) + expected func(*gtsmodel.Account) bool +} + +type domainPermTest struct { + // Federation mode under which to + // run this test. This is important + // because it may effect which side + // effects are taken, if any. + instanceFederationMode string + + // Series of actions to run as part + // of this test. After each action, + // expected will be called. This + // allows testers to run multiple + // actions in a row and check that + // the results after each action are + // what they expected, in light of + // previous actions. + actions []domainPermAction +} + +// run a domainPermTest by running each of +// its actions in turn and checking results. +func (suite *DomainBlockTestSuite) runDomainPermTest(t domainPermTest) { + config.SetInstanceFederationMode(t.instanceFederationMode) + + for _, action := range t.actions { + // Run the desired action. + var actionID string + switch action.createOrDelete { + case "create": + _, actionID = suite.createDomainPerm(action.permissionType, action.domain) + case "delete": + _, actionID = suite.deleteDomainPerm(action.permissionType, action.domain) + default: + panic("createOrDelete was not 'create' or 'delete'") + } + + // Let the action finish. + suite.awaitAction(actionID) + + // Check expected results + // against each account. + accounts, err := suite.db.GetInstanceAccounts( + context.Background(), + action.domain, + "", 0, + ) + if err != nil { + suite.FailNow("", "error getting instance accounts for %s: %v", action.domain, err) + } + + for _, account := range accounts { + if !action.expected(account) { + suite.T().FailNow() + } + } + } +} + +// create given permissionType with default values. +func (suite *DomainBlockTestSuite) createDomainPerm( + permissionType gtsmodel.DomainPermissionType, + domain string, +) (*apimodel.DomainPermission, string) { + ctx := context.Background() + + apiPerm, actionID, errWithCode := suite.adminProcessor.DomainPermissionCreate( + ctx, + permissionType, + suite.testAccounts["admin_account"], + domain, + false, + "", + "", + "", + ) + suite.NoError(errWithCode) + suite.NotNil(apiPerm) + suite.NotEmpty(actionID) + + return apiPerm, actionID +} + +// delete given permission type. +func (suite *DomainBlockTestSuite) deleteDomainPerm( + permissionType gtsmodel.DomainPermissionType, + domain string, +) (*apimodel.DomainPermission, string) { + var ( + ctx = context.Background() + domainPermission gtsmodel.DomainPermission + ) + + // To delete the permission, + // first get it from the db. + switch permissionType { + case gtsmodel.DomainPermissionBlock: + domainPermission, _ = suite.db.GetDomainBlock(ctx, domain) + case gtsmodel.DomainPermissionAllow: + domainPermission, _ = suite.db.GetDomainAllow(ctx, domain) + default: + panic("unrecognized permission type") + } + + if domainPermission == nil { + suite.FailNow("domain permission was nil") + } + + // Now use the ID to delete it. + apiPerm, actionID, errWithCode := suite.adminProcessor.DomainPermissionDelete( + ctx, + permissionType, + suite.testAccounts["admin_account"], + domainPermission.GetID(), + ) + suite.NoError(errWithCode) + suite.NotNil(apiPerm) + suite.NotEmpty(actionID) + + return apiPerm, actionID +} + +// waits for given actionID to be completed. +func (suite *DomainBlockTestSuite) awaitAction(actionID string) { + ctx := context.Background() + + if !testrig.WaitFor(func() bool { + return suite.adminProcessor.Actions().TotalRunning() == 0 + }) { + suite.FailNow("timed out waiting for admin action(s) to finish") + } + + // Ensure action marked as + // completed in the database. + adminAction, err := suite.db.GetAdminAction(ctx, actionID) + if err != nil { + suite.FailNow(err.Error()) + } + + suite.NotZero(adminAction.CompletedAt) + suite.Empty(adminAction.Errors) +} + +func (suite *DomainBlockTestSuite) TestBlockAndUnblockDomain() { + const domain = "fossbros-anonymous.io" + + suite.runDomainPermTest(domainPermTest{ + instanceFederationMode: config.InstanceFederationModeBlocklist, + actions: []domainPermAction{ + { + createOrDelete: "create", + permissionType: gtsmodel.DomainPermissionBlock, + domain: domain, + expected: func(account *gtsmodel.Account) bool { + // Domain was blocked, so each + // account should now be suspended. + return suite.NotZero(account.SuspendedAt) + }, + }, + { + createOrDelete: "delete", + permissionType: gtsmodel.DomainPermissionBlock, + domain: domain, + expected: func(account *gtsmodel.Account) bool { + // Domain was unblocked, so each + // account should now be unsuspended. + return suite.Zero(account.SuspendedAt) + }, + }, + }, + }) +} + +func (suite *DomainBlockTestSuite) TestBlockAndAllowDomain() { + const domain = "fossbros-anonymous.io" + + suite.runDomainPermTest(domainPermTest{ + instanceFederationMode: config.InstanceFederationModeBlocklist, + actions: []domainPermAction{ + { + createOrDelete: "create", + permissionType: gtsmodel.DomainPermissionBlock, + domain: domain, + expected: func(account *gtsmodel.Account) bool { + // Domain was blocked, so each + // account should now be suspended. + return suite.NotZero(account.SuspendedAt) + }, + }, + { + createOrDelete: "create", + permissionType: gtsmodel.DomainPermissionAllow, + domain: domain, + expected: func(account *gtsmodel.Account) bool { + // Domain was explicitly allowed, so each + // account should now be unsuspended, since + // the allow supercedes the block. + return suite.Zero(account.SuspendedAt) + }, + }, + { + createOrDelete: "delete", + permissionType: gtsmodel.DomainPermissionAllow, + domain: domain, + expected: func(account *gtsmodel.Account) bool { + // Deleting the allow now, while there's + // still a block in place, should cause + // the block to take effect again. + return suite.NotZero(account.SuspendedAt) + }, + }, + { + createOrDelete: "delete", + permissionType: gtsmodel.DomainPermissionBlock, + domain: domain, + expected: func(account *gtsmodel.Account) bool { + // Deleting the block now should + // unsuspend the accounts again. + return suite.Zero(account.SuspendedAt) + }, + }, + }, + }) +} + +func TestDomainBlockTestSuite(t *testing.T) { + suite.Run(t, new(DomainBlockTestSuite)) +} |