[feature] Allow editing domain blocks/allows, fix comment import

This commit is contained in:
tobi 2025-04-04 17:12:02 +02:00
commit e856d09f8e
13 changed files with 320 additions and 181 deletions

View file

@ -34,7 +34,7 @@ type Domain struct {
SilencedAt string `json:"silenced_at,omitempty"`
// If the domain is blocked, what's the publicly-stated reason for the block.
// example: they smell
PublicComment string `form:"public_comment" json:"public_comment,omitempty"`
PublicComment *string `form:"public_comment" json:"public_comment,omitempty"`
}
// DomainPermission represents a permission applied to one domain (explicit block/allow).
@ -48,10 +48,10 @@ type DomainPermission struct {
ID string `json:"id,omitempty"`
// Obfuscate the domain name when serving this domain permission entry publicly.
// example: false
Obfuscate bool `json:"obfuscate,omitempty"`
Obfuscate *bool `json:"obfuscate,omitempty"`
// Private comment for this permission entry, visible to this instance's admins only.
// example: they are poopoo
PrivateComment string `json:"private_comment,omitempty"`
PrivateComment *string `json:"private_comment,omitempty"`
// If applicable, the ID of the subscription that caused this domain permission entry to be created.
// example: 01FBW25TF5J67JW3HFHZCSD23K
SubscriptionID string `json:"subscription_id,omitempty"`

View file

@ -29,6 +29,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/util"
)
// DomainPermissionCreate creates an instance-level permission
@ -197,14 +198,14 @@ func (p *Processor) DomainPermissionsImport(
}
defer file.Close()
// Parse file as slice of domain blocks.
domainPerms := make([]*apimodel.DomainPermission, 0)
if err := json.NewDecoder(file).Decode(&domainPerms); err != nil {
// Parse file as slice of domain permissions.
apiDomainPerms := make([]*apimodel.DomainPermission, 0)
if err := json.NewDecoder(file).Decode(&apiDomainPerms); err != nil {
err = gtserror.Newf("error parsing attachment as domain permissions: %w", err)
return nil, gtserror.NewErrorBadRequest(err, err.Error())
}
count := len(domainPerms)
count := len(apiDomainPerms)
if count == 0 {
err = gtserror.New("error importing domain permissions: 0 entries provided")
return nil, gtserror.NewErrorBadRequest(err, err.Error())
@ -214,52 +215,97 @@ func (p *Processor) DomainPermissionsImport(
// between successes and errors so that the caller can
// try failed imports again if desired.
multiStatusEntries := make([]apimodel.MultiStatusEntry, 0, count)
for _, domainPerm := range domainPerms {
var (
domain = domainPerm.Domain.Domain
obfuscate = domainPerm.Obfuscate
publicComment = domainPerm.PublicComment
privateComment = domainPerm.PrivateComment
subscriptionID = "" // No sub ID for imports.
errWithCode gtserror.WithCode
for _, apiDomainPerm := range apiDomainPerms {
multiStatusEntries = append(
multiStatusEntries,
p.importOrUpdateDomainPerm(
ctx,
permissionType,
account,
apiDomainPerm,
),
)
domainPerm, _, errWithCode = p.DomainPermissionCreate(
ctx,
permissionType,
account,
domain,
obfuscate,
publicComment,
privateComment,
subscriptionID,
)
var entry *apimodel.MultiStatusEntry
if errWithCode != nil {
entry = &apimodel.MultiStatusEntry{
// Use the failed domain entry as the resource value.
Resource: domain,
Message: errWithCode.Safe(),
Status: errWithCode.Code(),
}
} else {
entry = &apimodel.MultiStatusEntry{
// Use successfully created API model domain block as the resource value.
Resource: domainPerm,
Message: http.StatusText(http.StatusOK),
Status: http.StatusOK,
}
}
multiStatusEntries = append(multiStatusEntries, *entry)
}
return apimodel.NewMultiStatus(multiStatusEntries), nil
}
func (p *Processor) importOrUpdateDomainPerm(
ctx context.Context,
permType gtsmodel.DomainPermissionType,
account *gtsmodel.Account,
apiDomainPerm *apimodel.DomainPermission,
) apimodel.MultiStatusEntry {
var (
domain = apiDomainPerm.Domain.Domain
obfuscate = apiDomainPerm.Obfuscate
publicComment = apiDomainPerm.PublicComment
privateComment = apiDomainPerm.PrivateComment
subscriptionID = "" // No sub ID for imports.
)
// Check if this domain
// perm already exists.
var (
domainPerm gtsmodel.DomainPermission
err error
)
if permType == gtsmodel.DomainPermissionBlock {
domainPerm, err = p.state.DB.GetDomainBlock(ctx, domain)
} else {
domainPerm, err = p.state.DB.GetDomainAllow(ctx, domain)
}
if err != nil && !errors.Is(err, db.ErrNoEntries) {
// Real db error.
return apimodel.MultiStatusEntry{
Resource: domain,
Message: "db error checking for existence of domain permission",
Status: http.StatusInternalServerError,
}
}
var errWithCode gtserror.WithCode
if domainPerm != nil {
// Permission already exists, update it.
apiDomainPerm, errWithCode = p.DomainPermissionUpdate(
ctx,
permType,
domainPerm.GetID(),
obfuscate,
publicComment,
privateComment,
nil,
)
} else {
// Permission didn't exist yet, create it.
apiDomainPerm, _, errWithCode = p.DomainPermissionCreate(
ctx,
permType,
account,
domain,
util.PtrOrZero(obfuscate),
util.PtrOrZero(publicComment),
util.PtrOrZero(privateComment),
subscriptionID,
)
}
if errWithCode != nil {
return apimodel.MultiStatusEntry{
Resource: domain,
Message: errWithCode.Safe(),
Status: errWithCode.Code(),
}
}
return apimodel.MultiStatusEntry{
Resource: apiDomainPerm,
Message: http.StatusText(http.StatusOK),
Status: http.StatusOK,
}
}
// DomainPermissionsGet returns all existing domain
// permissions of the requested type. If export is
// true, the format will be suitable for writing out

View file

@ -108,7 +108,7 @@ func (p *Processor) InstancePeersGet(ctx context.Context, includeSuspended bool,
domains = append(domains, &apimodel.Domain{
Domain: d,
SuspendedAt: util.FormatISO8601(domainBlock.CreatedAt),
PublicComment: domainBlock.PublicComment,
PublicComment: &domainBlock.PublicComment,
})
}
}

View file

@ -742,8 +742,8 @@ func permsFromJSON(
}
// Set remaining fields.
perm.SetPublicComment(apiPerm.PublicComment)
perm.SetObfuscate(&apiPerm.Obfuscate)
perm.SetPublicComment(util.PtrOrZero(apiPerm.PublicComment))
perm.SetObfuscate(util.Ptr(util.PtrOrZero(apiPerm.Obfuscate)))
// We're done.
perms = append(perms, perm)

View file

@ -2182,7 +2182,7 @@ func (c *Converter) DomainPermToAPIDomainPerm(
domainPerm := &apimodel.DomainPermission{
Domain: apimodel.Domain{
Domain: domain,
PublicComment: d.GetPublicComment(),
PublicComment: util.Ptr(d.GetPublicComment()),
},
}
@ -2193,8 +2193,8 @@ func (c *Converter) DomainPermToAPIDomainPerm(
}
domainPerm.ID = d.GetID()
domainPerm.Obfuscate = util.PtrOrZero(d.GetObfuscate())
domainPerm.PrivateComment = d.GetPrivateComment()
domainPerm.Obfuscate = d.GetObfuscate()
domainPerm.PrivateComment = util.Ptr(d.GetPrivateComment())
domainPerm.SubscriptionID = d.GetSubscriptionID()
domainPerm.CreatedBy = d.GetCreatedByAccountID()
if createdAt := d.GetCreatedAt(); !createdAt.IsZero() {