[bugfix] Check interaction policies properly on incoming Likes (#3416)

This commit is contained in:
tobi
2024-10-11 15:21:56 +02:00
committed by GitHub
parent cb9008fb41
commit 1c895f314c
4 changed files with 84 additions and 14 deletions

View File

@@ -445,42 +445,106 @@ func (f *federatingDB) activityFollow(ctx context.Context, asType vocab.Type, re
LIKE HANDLERS
*/
func (f *federatingDB) activityLike(ctx context.Context, asType vocab.Type, receivingAccount *gtsmodel.Account, requestingAccount *gtsmodel.Account) error {
func (f *federatingDB) activityLike(
ctx context.Context,
asType vocab.Type,
receivingAcct *gtsmodel.Account,
requestingAcct *gtsmodel.Account,
) error {
like, ok := asType.(vocab.ActivityStreamsLike)
if !ok {
return errors.New("activityLike: could not convert type to like")
err := gtserror.Newf("could not convert asType %T to ActivityStreamsLike", asType)
return gtserror.SetMalformed(err)
}
fave, err := f.converter.ASLikeToFave(ctx, like)
if err != nil {
return fmt.Errorf("activityLike: could not convert Like to fave: %w", err)
return gtserror.Newf("could not convert Like to fave: %w", err)
}
if fave.AccountID != requestingAccount.ID {
return fmt.Errorf(
"activityLike: requestingAccount %s is not Like actor account %s",
requestingAccount.URI, fave.Account.URI,
// Ensure requester not trying to
// Like on someone else's behalf.
if fave.AccountID != requestingAcct.ID {
text := fmt.Sprintf(
"requestingAcct %s is not Like actor account %s",
requestingAcct.URI, fave.Account.URI,
)
return gtserror.NewErrorForbidden(errors.New(text), text)
}
if !*fave.Status.Local {
// Only process likes of local statuses.
// TODO: process for remote statuses as well.
return nil
}
// Ensure valid Like target for requester.
policyResult, err := f.intFilter.StatusLikeable(ctx,
requestingAcct,
fave.Status,
)
if err != nil {
err := gtserror.Newf("error seeing if status %s is likeable: %w", fave.Status.ID, err)
return gtserror.NewErrorInternalError(err)
}
if policyResult.Forbidden() {
const errText = "requester does not have permission to Like this status"
err := gtserror.New(errText)
return gtserror.NewErrorForbidden(err, errText)
}
// Derive pendingApproval
// and preapproved status.
var (
pendingApproval bool
preApproved bool
)
switch {
case policyResult.WithApproval():
// Requester allowed to do
// this pending approval.
pendingApproval = true
case policyResult.MatchedOnCollection():
// Requester allowed to do this,
// but matched on collection.
// Preapprove Like and have the
// processor send out an Accept.
pendingApproval = true
preApproved = true
case policyResult.Permitted():
// Requester straight up
// permitted to do this,
// no need for Accept.
pendingApproval = false
}
// Set appropriate fields
// on fave and store it.
fave.ID = id.NewULID()
fave.PendingApproval = &pendingApproval
fave.PreApproved = preApproved
if err := f.state.DB.PutStatusFave(ctx, fave); err != nil {
if errors.Is(err, db.ErrAlreadyExists) {
// The Like already exists in the database, which
// means we've already handled side effects. We can
// just return nil here and be done with it.
// The fave already exists in the
// database, which means we've already
// handled side effects. We can just
// return nil here and be done with it.
return nil
}
return fmt.Errorf("activityLike: database error inserting fave: %w", err)
return gtserror.Newf("db error inserting fave: %w", err)
}
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
APObjectType: ap.ActivityLike,
APActivityType: ap.ActivityCreate,
GTSModel: fave,
Receiving: receivingAccount,
Requesting: requestingAccount,
Receiving: receivingAcct,
Requesting: requestingAcct,
})
return nil