mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 13:32:25 -05:00 
			
		
		
		
	[bugfix] Check interaction policies properly on incoming Likes (#3416)
This commit is contained in:
		
					parent
					
						
							
								cb9008fb41
							
						
					
				
			
			
				commit
				
					
						1c895f314c
					
				
			
		
					 4 changed files with 84 additions and 14 deletions
				
			
		|  | @ -213,7 +213,7 @@ var Start action.GTSAction = func(ctx context.Context) error { | ||||||
| 	visFilter := visibility.NewFilter(state) | 	visFilter := visibility.NewFilter(state) | ||||||
| 	intFilter := interaction.NewFilter(state) | 	intFilter := interaction.NewFilter(state) | ||||||
| 	spamFilter := spam.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) | 	transportController := transport.NewController(state, federatingDB, &federation.Clock{}, client) | ||||||
| 	federator := federation.NewFederator( | 	federator := federation.NewFederator( | ||||||
| 		state, | 		state, | ||||||
|  |  | ||||||
|  | @ -445,42 +445,106 @@ func (f *federatingDB) activityFollow(ctx context.Context, asType vocab.Type, re | ||||||
| 	LIKE HANDLERS | 	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) | 	like, ok := asType.(vocab.ActivityStreamsLike) | ||||||
| 	if !ok { | 	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) | 	fave, err := f.converter.ASLikeToFave(ctx, like) | ||||||
| 	if err != nil { | 	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 { | 	// Ensure requester not trying to | ||||||
| 		return fmt.Errorf( | 	// Like on someone else's behalf. | ||||||
| 			"activityLike: requestingAccount %s is not Like actor account %s", | 	if fave.AccountID != requestingAcct.ID { | ||||||
| 			requestingAccount.URI, fave.Account.URI, | 		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.ID = id.NewULID() | ||||||
|  | 	fave.PendingApproval = &pendingApproval | ||||||
|  | 	fave.PreApproved = preApproved | ||||||
| 
 | 
 | ||||||
| 	if err := f.state.DB.PutStatusFave(ctx, fave); err != nil { | 	if err := f.state.DB.PutStatusFave(ctx, fave); err != nil { | ||||||
| 		if errors.Is(err, db.ErrAlreadyExists) { | 		if errors.Is(err, db.ErrAlreadyExists) { | ||||||
| 			// The Like already exists in the database, which | 			// The fave already exists in the | ||||||
| 			// means we've already handled side effects. We can | 			// database, which means we've already | ||||||
| 			// just return nil here and be done with it. | 			// handled side effects. We can just | ||||||
|  | 			// return nil here and be done with it. | ||||||
| 			return nil | 			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{ | 	f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{ | ||||||
| 		APObjectType:   ap.ActivityLike, | 		APObjectType:   ap.ActivityLike, | ||||||
| 		APActivityType: ap.ActivityCreate, | 		APActivityType: ap.ActivityCreate, | ||||||
| 		GTSModel:       fave, | 		GTSModel:       fave, | ||||||
| 		Receiving:      receivingAccount, | 		Receiving:      receivingAcct, | ||||||
| 		Requesting:     requestingAccount, | 		Requesting:     requestingAcct, | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	return nil | 	return nil | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| 	"github.com/superseriousbusiness/activity/pub" | 	"github.com/superseriousbusiness/activity/pub" | ||||||
| 	"github.com/superseriousbusiness/activity/streams/vocab" | 	"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/spam" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/filter/visibility" | 	"github.com/superseriousbusiness/gotosocial/internal/filter/visibility" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/state" | 	"github.com/superseriousbusiness/gotosocial/internal/state" | ||||||
|  | @ -58,6 +59,7 @@ type federatingDB struct { | ||||||
| 	state      *state.State | 	state      *state.State | ||||||
| 	converter  *typeutils.Converter | 	converter  *typeutils.Converter | ||||||
| 	visFilter  *visibility.Filter | 	visFilter  *visibility.Filter | ||||||
|  | 	intFilter  *interaction.Filter | ||||||
| 	spamFilter *spam.Filter | 	spamFilter *spam.Filter | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -67,12 +69,14 @@ func New( | ||||||
| 	state *state.State, | 	state *state.State, | ||||||
| 	converter *typeutils.Converter, | 	converter *typeutils.Converter, | ||||||
| 	visFilter *visibility.Filter, | 	visFilter *visibility.Filter, | ||||||
|  | 	intFilter *interaction.Filter, | ||||||
| 	spamFilter *spam.Filter, | 	spamFilter *spam.Filter, | ||||||
| ) DB { | ) DB { | ||||||
| 	fdb := federatingDB{ | 	fdb := federatingDB{ | ||||||
| 		state:      state, | 		state:      state, | ||||||
| 		converter:  converter, | 		converter:  converter, | ||||||
| 		visFilter:  visFilter, | 		visFilter:  visFilter, | ||||||
|  | 		intFilter:  intFilter, | ||||||
| 		spamFilter: spamFilter, | 		spamFilter: spamFilter, | ||||||
| 	} | 	} | ||||||
| 	return &fdb | 	return &fdb | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ package testrig | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/federation/federatingdb" | 	"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/spam" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/filter/visibility" | 	"github.com/superseriousbusiness/gotosocial/internal/filter/visibility" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/state" | 	"github.com/superseriousbusiness/gotosocial/internal/state" | ||||||
|  | @ -31,6 +32,7 @@ func NewTestFederatingDB(state *state.State) federatingdb.DB { | ||||||
| 		state, | 		state, | ||||||
| 		typeutils.NewConverter(state), | 		typeutils.NewConverter(state), | ||||||
| 		visibility.NewFilter(state), | 		visibility.NewFilter(state), | ||||||
|  | 		interaction.NewFilter(state), | ||||||
| 		spam.NewFilter(state), | 		spam.NewFilter(state), | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue