[bugfix] Check interaction policies properly on incoming Likes (#3416)
This commit is contained in:
parent
cb9008fb41
commit
1c895f314c
|
@ -213,7 +213,7 @@ var Start action.GTSAction = func(ctx context.Context) error {
|
|||
visFilter := visibility.NewFilter(state)
|
||||
intFilter := interaction.NewFilter(state)
|
||||
spamFilter := spam.NewFilter(state)
|
||||
federatingDB := federatingdb.New(state, typeConverter, visFilter, spamFilter)
|
||||
federatingDB := federatingdb.New(state, typeConverter, visFilter, intFilter, spamFilter)
|
||||
transportController := transport.NewController(state, federatingDB, &federation.Clock{}, client)
|
||||
federator := federation.NewFederator(
|
||||
state,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
|
||||
"github.com/superseriousbusiness/activity/pub"
|
||||
"github.com/superseriousbusiness/activity/streams/vocab"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/filter/interaction"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/filter/spam"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/filter/visibility"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||
|
@ -58,6 +59,7 @@ type federatingDB struct {
|
|||
state *state.State
|
||||
converter *typeutils.Converter
|
||||
visFilter *visibility.Filter
|
||||
intFilter *interaction.Filter
|
||||
spamFilter *spam.Filter
|
||||
}
|
||||
|
||||
|
@ -67,12 +69,14 @@ func New(
|
|||
state *state.State,
|
||||
converter *typeutils.Converter,
|
||||
visFilter *visibility.Filter,
|
||||
intFilter *interaction.Filter,
|
||||
spamFilter *spam.Filter,
|
||||
) DB {
|
||||
fdb := federatingDB{
|
||||
state: state,
|
||||
converter: converter,
|
||||
visFilter: visFilter,
|
||||
intFilter: intFilter,
|
||||
spamFilter: spamFilter,
|
||||
}
|
||||
return &fdb
|
||||
|
|
|
@ -19,6 +19,7 @@ package testrig
|
|||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/federation/federatingdb"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/filter/interaction"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/filter/spam"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/filter/visibility"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||
|
@ -31,6 +32,7 @@ func NewTestFederatingDB(state *state.State) federatingdb.DB {
|
|||
state,
|
||||
typeutils.NewConverter(state),
|
||||
visibility.NewFilter(state),
|
||||
interaction.NewFilter(state),
|
||||
spam.NewFilter(state),
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue