diff options
| author | 2025-05-20 11:47:40 +0200 | |
|---|---|---|
| committer | 2025-05-20 11:47:40 +0200 | |
| commit | ec4d4d01150ae979896496651bc64e4148d94a06 (patch) | |
| tree | 3ce9426b450659f573ef00465a1646d44e58b99d /internal/processing | |
| parent | [bugfix] fix case of failed timeline preload causing lockups (#4182) (diff) | |
| download | gotosocial-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')
| -rw-r--r-- | internal/processing/instance.go | 145 |
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) { |
