summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/gtsmodel/domainallow.go4
-rw-r--r--internal/gtsmodel/domainblock.go4
-rw-r--r--internal/gtsmodel/domainpermission.go4
-rw-r--r--internal/gtsmodel/domainpermissiondraft.go4
-rw-r--r--internal/gtsmodel/domainpermissionexclude.go1
-rw-r--r--internal/subscriptions/domainperms.go94
-rw-r--r--internal/subscriptions/subscriptions_test.go132
7 files changed, 225 insertions, 18 deletions
diff --git a/internal/gtsmodel/domainallow.go b/internal/gtsmodel/domainallow.go
index 7b947333b..3a7ca8774 100644
--- a/internal/gtsmodel/domainallow.go
+++ b/internal/gtsmodel/domainallow.go
@@ -104,3 +104,7 @@ func (d *DomainAllow) SetSubscriptionID(i string) {
func (d *DomainAllow) GetType() DomainPermissionType {
return DomainPermissionAllow
}
+
+func (d *DomainAllow) IsOrphan() bool {
+ return d.SubscriptionID == ""
+}
diff --git a/internal/gtsmodel/domainblock.go b/internal/gtsmodel/domainblock.go
index e99fea301..4a0e1c5b7 100644
--- a/internal/gtsmodel/domainblock.go
+++ b/internal/gtsmodel/domainblock.go
@@ -104,3 +104,7 @@ func (d *DomainBlock) SetSubscriptionID(i string) {
func (d *DomainBlock) GetType() DomainPermissionType {
return DomainPermissionBlock
}
+
+func (d *DomainBlock) IsOrphan() bool {
+ return d.SubscriptionID == ""
+}
diff --git a/internal/gtsmodel/domainpermission.go b/internal/gtsmodel/domainpermission.go
index f1db4de59..b08036a91 100644
--- a/internal/gtsmodel/domainpermission.go
+++ b/internal/gtsmodel/domainpermission.go
@@ -43,6 +43,10 @@ type DomainPermission interface {
GetSubscriptionID() string
SetSubscriptionID(i string)
GetType() DomainPermissionType
+
+ // Return true if this DomainPermission
+ // does not have a subscription id set.
+ IsOrphan() bool
}
// Domain permission type.
diff --git a/internal/gtsmodel/domainpermissiondraft.go b/internal/gtsmodel/domainpermissiondraft.go
index 0829dca16..d233df6f9 100644
--- a/internal/gtsmodel/domainpermissiondraft.go
+++ b/internal/gtsmodel/domainpermissiondraft.go
@@ -104,3 +104,7 @@ func (d *DomainPermissionDraft) SetSubscriptionID(i string) {
func (d *DomainPermissionDraft) GetType() DomainPermissionType {
return d.PermissionType
}
+
+func (d *DomainPermissionDraft) IsOrphan() bool {
+ return d.SubscriptionID == ""
+}
diff --git a/internal/gtsmodel/domainpermissionexclude.go b/internal/gtsmodel/domainpermissionexclude.go
index 2a0925ba7..10492a5c1 100644
--- a/internal/gtsmodel/domainpermissionexclude.go
+++ b/internal/gtsmodel/domainpermissionexclude.go
@@ -90,3 +90,4 @@ func (d *DomainPermissionExclude) SetObfuscate(_ *bool) {}
func (d *DomainPermissionExclude) GetSubscriptionID() string { return "" }
func (d *DomainPermissionExclude) SetSubscriptionID(_ string) {}
func (d *DomainPermissionExclude) GetType() DomainPermissionType { return DomainPermissionUnknown }
+func (d *DomainPermissionExclude) IsOrphan() bool { return true }
diff --git a/internal/subscriptions/domainperms.go b/internal/subscriptions/domainperms.go
index dc4224899..ee4730023 100644
--- a/internal/subscriptions/domainperms.go
+++ b/internal/subscriptions/domainperms.go
@@ -317,7 +317,7 @@ func (s *Subscriptions) ProcessDomainPermissionSubscription(
// Iterate through wantedPerms and
// create (or dry create) each one.
for _, wantedPerm := range wantedPerms {
- l = l.WithField("domain", wantedPerm.GetDomain())
+ l := l.WithField("domain", wantedPerm.GetDomain())
created, err := s.processDomainPermission(
ctx, l,
wantedPerm,
@@ -486,26 +486,53 @@ func (s *Subscriptions) processDomainPermission(
// 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)
+ case existingPerm.IsOrphan():
+ // Perm already exists, but it's not managed
+ // by a subscription, ie., it's an orphan.
+ if !*permSub.AdoptOrphans {
+ l.Debug("permission exists as an orphan that we shouldn't adopt, skipping")
+ return false, nil
}
+ // Orphan is adoptable, so adopt
+ // it by rewriting some fields.
+ //
+ // TODO: preserve previous private
+ // + public comment in some way.
+ l.Debug("adopting orphan permission")
+ err = s.adoptPerm(
+ ctx,
+ existingPerm,
+ permSub,
+ wantedPerm.GetObfuscate(),
+ permSub.URI,
+ wantedPerm.GetPublicComment(),
+ )
+
+ case existingPerm.GetSubscriptionID() != permSub.ID:
+ // Perm already exists, and is managed
+ // by a lower-priority subscription.
+ // Take it for ourselves.
+ //
+ // TODO: preserve previous private
+ // + public comment in some way.
+ l.Debug("taking over permission from lower-priority subscription")
+ err = s.adoptPerm(
+ ctx,
+ existingPerm,
+ permSub,
+ wantedPerm.GetObfuscate(),
+ permSub.URI,
+ wantedPerm.GetPublicComment(),
+ )
+
default:
- // Perm exists but we should leave it alone.
- l.Debug("domain is covered by a higher-priority subscription, skipping")
+ // Perm exists and is managed by us.
+ //
+ // TODO: update public/private comment
+ // from latest version if it's changed.
+ l.Debug("permission already exists and is managed by this subscription, skipping")
+ return false, nil
}
if err != nil && !errors.Is(err, db.ErrAlreadyExists) {
@@ -829,3 +856,34 @@ func (s *Subscriptions) existingCovered(
return
}
+
+func (s *Subscriptions) adoptPerm(
+ ctx context.Context,
+ perm gtsmodel.DomainPermission,
+ permSub *gtsmodel.DomainPermissionSubscription,
+ obfuscate *bool,
+ privateComment string,
+ publicComment string,
+) error {
+ // Set to our sub ID + this subs's
+ // account as we're managing it now.
+ perm.SetSubscriptionID(permSub.ID)
+ perm.SetCreatedByAccountID(permSub.CreatedByAccount.ID)
+ perm.SetCreatedByAccount(permSub.CreatedByAccount)
+
+ // Set new metadata on the perm.
+ perm.SetObfuscate(obfuscate)
+ perm.SetPrivateComment(privateComment)
+ perm.SetPublicComment(publicComment)
+
+ // Update the perm in the db.
+ var err error
+ switch p := perm.(type) {
+ case *gtsmodel.DomainBlock:
+ err = s.state.DB.UpdateDomainBlock(ctx, p)
+ case *gtsmodel.DomainAllow:
+ err = s.state.DB.UpdateDomainAllow(ctx, p)
+ }
+
+ return err
+}
diff --git a/internal/subscriptions/subscriptions_test.go b/internal/subscriptions/subscriptions_test.go
index 1f6e437fb..6c47fed21 100644
--- a/internal/subscriptions/subscriptions_test.go
+++ b/internal/subscriptions/subscriptions_test.go
@@ -533,6 +533,138 @@ func (suite *SubscriptionsTestSuite) TestDomainBlocksWrongContentTypePlain() {
suite.Equal(`fetch successful but parsed zero usable results`, permSub.Error)
}
+func (suite *SubscriptionsTestSuite) TestAdoption() {
+ var (
+ ctx = context.Background()
+ testStructs = testrig.SetupTestStructs(rMediaPath, rTemplatePath)
+ testAccount = suite.testAccounts["admin_account"]
+ subscriptions = subscriptions.New(
+ testStructs.State,
+ testStructs.TransportController,
+ testStructs.TypeConverter,
+ )
+
+ // A subscription for a plain list
+ // of baddies, which adopts orphans.
+ testSubscription = &gtsmodel.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,
+ }
+
+ // A lower-priority subscription
+ // than the one we're testing.
+ existingSubscription = &gtsmodel.DomainPermissionSubscription{
+ ID: "01JHX2ENFM8YGGR9Q9J5S66KSB",
+ Priority: 128,
+ Title: "lower prio subscription",
+ PermissionType: gtsmodel.DomainPermissionBlock,
+ AsDraft: util.Ptr(false),
+ AdoptOrphans: util.Ptr(false),
+ CreatedByAccountID: testAccount.ID,
+ CreatedByAccount: testAccount,
+ URI: "https://whatever.example.org/lowerprios.txt",
+ ContentType: gtsmodel.DomainPermSubContentTypePlain,
+ }
+
+ // Orphan block which also exists
+ // on the list of testSubscription.
+ existingBlock1 = &gtsmodel.DomainBlock{
+ ID: "01JHX2V5WN250TKB6FQ1M3QE1H",
+ Domain: "bumfaces.net",
+ CreatedByAccount: testAccount,
+ CreatedByAccountID: testAccount.ID,
+ }
+
+ // Block managed by existingSubscription which
+ // also exists on the list of testSubscription.
+ existingBlock2 = &gtsmodel.DomainBlock{
+ ID: "01JHX3EZAYG3KKC56C1YTKBRK7",
+ Domain: "peepee.poopoo",
+ CreatedByAccount: testAccount,
+ CreatedByAccountID: testAccount.ID,
+ SubscriptionID: existingSubscription.ID,
+ }
+
+ // Already existing block
+ // managed by testSubscription.
+ existingBlock3 = &gtsmodel.DomainBlock{
+ ID: "01JHX3N1AGYT72BR3TWDCZKYGE",
+ Domain: "nothanks.com",
+ CreatedByAccount: testAccount,
+ CreatedByAccountID: testAccount.ID,
+ SubscriptionID: testSubscription.ID,
+ }
+ )
+ defer testrig.TearDownTestStructs(testStructs)
+
+ // Store test subscription.
+ if err := testStructs.State.DB.PutDomainPermissionSubscription(
+ ctx, testSubscription,
+ ); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // Store the lower-priority subscription.
+ if err := testStructs.State.DB.PutDomainPermissionSubscription(
+ ctx, existingSubscription,
+ ); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // Store the existing blocks.
+ for _, block := range []*gtsmodel.DomainBlock{
+ existingBlock1,
+ existingBlock2,
+ existingBlock3,
+ } {
+ if err := testStructs.State.DB.CreateDomainBlock(
+ ctx, block,
+ ); err != nil {
+ suite.FailNow(err.Error())
+ }
+ }
+
+ // Process all subscriptions.
+ subscriptions.ProcessDomainPermissionSubscriptions(ctx, testSubscription.PermissionType)
+
+ var err error
+
+ // existingBlock1 should now be adopted by
+ // testSubscription, as it previously an orphan.
+ if existingBlock1, err = testStructs.State.DB.GetDomainBlockByID(
+ ctx, existingBlock1.ID,
+ ); err != nil {
+ suite.FailNow(err.Error())
+ }
+ suite.Equal(testSubscription.ID, existingBlock1.SubscriptionID)
+
+ // existingBlock2 should now be
+ // managed by testSubscription.
+ if existingBlock2, err = testStructs.State.DB.GetDomainBlockByID(
+ ctx, existingBlock2.ID,
+ ); err != nil {
+ suite.FailNow(err.Error())
+ }
+ suite.Equal(testSubscription.ID, existingBlock2.SubscriptionID)
+
+ // existingBlock3 should still be
+ // managed by testSubscription.
+ if existingBlock3, err = testStructs.State.DB.GetDomainBlockByID(
+ ctx, existingBlock3.ID,
+ ); err != nil {
+ suite.FailNow(err.Error())
+ }
+ suite.Equal(testSubscription.ID, existingBlock3.SubscriptionID)
+}
+
func TestSubscriptionTestSuite(t *testing.T) {
suite.Run(t, new(SubscriptionsTestSuite))
}