summaryrefslogtreecommitdiff
path: root/internal/processing/instance.go
diff options
context:
space:
mode:
authorLibravatar tobi <tobi.smethurst@protonmail.com>2025-05-20 11:47:40 +0200
committerLibravatar kim <gruf@noreply.codeberg.org>2025-05-20 11:47:40 +0200
commitec4d4d01150ae979896496651bc64e4148d94a06 (patch)
tree3ce9426b450659f573ef00465a1646d44e58b99d /internal/processing/instance.go
parent[bugfix] fix case of failed timeline preload causing lockups (#4182) (diff)
downloadgotosocial-ec4d4d01150ae979896496651bc64e4148d94a06.tar.xz
[feature] Allow exposing allows, implement `/api/v1/domain_blocks` and `/api/v1/domain_allows` (#4169)
- adds config flags `instance-expose-allowlist` and `instance-expose-allowlist-web` to allow instance admins to expose their allowlist via the web + api. - renames `instance-expose-suspended` and `instance-expose-suspended-web` to `instance-expose-blocklist` and `instance-expose-blocklist-web`. - deprecates the `suspended` filter on `/api/v1/instance/peers` endpoint and adds `blocked` and `allowed` filters - adds the `flat` query param to `/api/v1/instance/peers` to allow forcing return of a flat list of domains - implements `/api/v1/instance/domain_blocks` and `/api/v1/instance/domain_allows` endpoints with or without auth depending on config - rejigs the instance about page to include a general section on domain permissions, with block and allow subsections (and appropriate links) Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/3847 Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4150 Prerequisite to https://codeberg.org/superseriousbusiness/gotosocial/issues/3711 Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4169 Co-authored-by: tobi <tobi.smethurst@protonmail.com> Co-committed-by: tobi <tobi.smethurst@protonmail.com>
Diffstat (limited to 'internal/processing/instance.go')
-rw-r--r--internal/processing/instance.go145
1 files changed, 102 insertions, 43 deletions
diff --git a/internal/processing/instance.go b/internal/processing/instance.go
index 87fe1e3ef..e1a3785e9 100644
--- a/internal/processing/instance.go
+++ b/internal/processing/instance.go
@@ -19,8 +19,10 @@ package processing
import (
"context"
+ "errors"
"fmt"
- "sort"
+ "slices"
+ "strings"
apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model"
"code.superseriousbusiness.org/gotosocial/internal/config"
@@ -31,6 +33,7 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/text"
"code.superseriousbusiness.org/gotosocial/internal/typeutils"
"code.superseriousbusiness.org/gotosocial/internal/util"
+ "code.superseriousbusiness.org/gotosocial/internal/util/xslices"
"code.superseriousbusiness.org/gotosocial/internal/validate"
)
@@ -62,70 +65,126 @@ func (p *Processor) InstanceGetV2(ctx context.Context) (*apimodel.InstanceV2, gt
return ai, nil
}
-func (p *Processor) InstancePeersGet(ctx context.Context, includeSuspended bool, includeOpen bool, flat bool) (interface{}, gtserror.WithCode) {
- domains := []*apimodel.Domain{}
+func (p *Processor) InstancePeersGet(
+ ctx context.Context,
+ includeBlocked bool,
+ includeAllowed bool,
+ includeOpen bool,
+ flatten bool,
+ includeSeverity bool,
+) (any, gtserror.WithCode) {
+ var (
+ domainPerms []gtsmodel.DomainPermission
+ apiDomains []*apimodel.Domain
+ )
+
+ if includeBlocked {
+ blocks, err := p.state.DB.GetDomainBlocks(ctx)
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
+ err := gtserror.Newf("db error getting domain blocks: %w", err)
+ return nil, gtserror.NewErrorInternalError(err)
+ }
- if includeOpen {
- instances, err := p.state.DB.GetInstancePeers(ctx, false)
- if err != nil && err != db.ErrNoEntries {
- err = fmt.Errorf("error selecting instance peers: %s", err)
+ for _, block := range blocks {
+ domainPerms = append(domainPerms, block)
+ }
+
+ } else if includeAllowed {
+ allows, err := p.state.DB.GetDomainAllows(ctx)
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
+ err := gtserror.Newf("db error getting domain allows: %w", err)
return nil, gtserror.NewErrorInternalError(err)
}
- for _, i := range instances {
- // Domain may be in Punycode,
- // de-punify it just in case.
- d, err := util.DePunify(i.Domain)
- if err != nil {
- log.Errorf(ctx, "couldn't depunify domain %s: %s", i.Domain, err)
- continue
- }
+ for _, allow := range allows {
+ domainPerms = append(domainPerms, allow)
+ }
+ }
- domains = append(domains, &apimodel.Domain{Domain: d})
+ for _, domainPerm := range domainPerms {
+ // Domain may be in Punycode,
+ // de-punify it just in case.
+ domain := domainPerm.GetDomain()
+ depunied, err := util.DePunify(domain)
+ if err != nil {
+ log.Errorf(ctx, "couldn't depunify domain %s: %v", domain, err)
+ continue
}
+
+ if util.PtrOrZero(domainPerm.GetObfuscate()) {
+ // Obfuscate the de-punified version.
+ depunied = obfuscate(depunied)
+ }
+
+ apiDomain := &apimodel.Domain{
+ Domain: depunied,
+ Comment: util.Ptr(domainPerm.GetPublicComment()),
+ }
+
+ if domainPerm.GetType() == gtsmodel.DomainPermissionBlock {
+ const severity = "suspend"
+ apiDomain.Severity = severity
+ suspendedAt := domainPerm.GetCreatedAt()
+ apiDomain.SuspendedAt = util.FormatISO8601(suspendedAt)
+ }
+
+ apiDomains = append(apiDomains, apiDomain)
}
- if includeSuspended {
- domainBlocks := []*gtsmodel.DomainBlock{}
- if err := p.state.DB.GetAll(ctx, &domainBlocks); err != nil && err != db.ErrNoEntries {
+ if includeOpen {
+ instances, err := p.state.DB.GetInstancePeers(ctx, false)
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
+ err = gtserror.Newf("db error getting instance peers: %w", err)
return nil, gtserror.NewErrorInternalError(err)
}
- for _, domainBlock := range domainBlocks {
+ for _, instance := range instances {
// Domain may be in Punycode,
// de-punify it just in case.
- d, err := util.DePunify(domainBlock.Domain)
+ domain := instance.Domain
+ depunied, err := util.DePunify(domain)
if err != nil {
- log.Errorf(ctx, "couldn't depunify domain %s: %s", domainBlock.Domain, err)
+ log.Errorf(ctx, "couldn't depunify domain %s: %v", domain, err)
continue
}
- if *domainBlock.Obfuscate {
- // Obfuscate the de-punified version.
- d = obfuscate(d)
- }
-
- domains = append(domains, &apimodel.Domain{
- Domain: d,
- SuspendedAt: util.FormatISO8601(domainBlock.CreatedAt),
- Comment: &domainBlock.PublicComment,
- })
+ apiDomains = append(
+ apiDomains,
+ &apimodel.Domain{
+ Domain: depunied,
+ },
+ )
}
}
- sort.Slice(domains, func(i, j int) bool {
- return domains[i].Domain < domains[j].Domain
- })
-
- if flat {
- flattened := []string{}
- for _, d := range domains {
- flattened = append(flattened, d.Domain)
- }
- return flattened, nil
+ // Sort a-z.
+ slices.SortFunc(
+ apiDomains,
+ func(a, b *apimodel.Domain) int {
+ return strings.Compare(a.Domain, b.Domain)
+ },
+ )
+
+ // Deduplicate.
+ apiDomains = xslices.DeduplicateFunc(
+ apiDomains,
+ func(v *apimodel.Domain) string {
+ return v.Domain
+ },
+ )
+
+ if flatten {
+ // Return just the domains.
+ return xslices.Gather(
+ []string{},
+ apiDomains,
+ func(v *apimodel.Domain) string {
+ return v.Domain
+ },
+ ), nil
}
- return domains, nil
+ return apiDomains, nil
}
func (p *Processor) InstanceGetRules(ctx context.Context) ([]apimodel.InstanceRule, gtserror.WithCode) {