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..d6f24cde1 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 == "" +} \ No newline at end of file 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..519345aba 100644 --- a/internal/subscriptions/domainperms.go +++ b/internal/subscriptions/domainperms.go @@ -486,26 +486,52 @@ 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") } if err != nil && !errors.Is(err, db.ErrAlreadyExists) { @@ -829,3 +855,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 +}