Skip to content

Commit

Permalink
[bugfix] Check interaction policies properly on incoming Likes (#3416)
Browse files Browse the repository at this point in the history
  • Loading branch information
tsmethurst authored Oct 11, 2024
1 parent cb9008f commit 1c895f3
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 14 deletions.
2 changes: 1 addition & 1 deletion cmd/gotosocial/action/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
90 changes: 77 additions & 13 deletions internal/federation/federatingdb/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions internal/federation/federatingdb/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -58,6 +59,7 @@ type federatingDB struct {
state *state.State
converter *typeutils.Converter
visFilter *visibility.Filter
intFilter *interaction.Filter
spamFilter *spam.Filter
}

Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions testrig/federatingdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -31,6 +32,7 @@ func NewTestFederatingDB(state *state.State) federatingdb.DB {
state,
typeutils.NewConverter(state),
visibility.NewFilter(state),
interaction.NewFilter(state),
spam.NewFilter(state),
)
}

0 comments on commit 1c895f3

Please sign in to comment.