gotosocial/internal/federation/federatingdb/move_test.go
tobi 1bcdf1da3b
[feature] Process incoming Move activity (#2724)
* [feature] Process incoming account Move activity

* fix targetAcct typo

* put move origin account on fMsg

* shift more move functionality back to the worker fn

* simplify error logic
2024-03-12 14:34:08 +00:00

201 lines
6.6 KiB
Go

// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package federatingdb_test
import (
"encoding/json"
"testing"
"time"
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/activity/streams"
"github.com/superseriousbusiness/activity/streams/vocab"
"github.com/superseriousbusiness/gotosocial/internal/ap"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/messages"
)
type MoveTestSuite struct {
FederatingDBTestSuite
}
func (suite *MoveTestSuite) move(
receivingAcct *gtsmodel.Account,
requestingAcct *gtsmodel.Account,
moveStr string,
) error {
ctx := createTestContext(receivingAcct, requestingAcct)
rawMove := make(map[string]interface{})
if err := json.Unmarshal([]byte(moveStr), &rawMove); err != nil {
suite.FailNow(err.Error())
}
t, err := streams.ToType(ctx, rawMove)
if err != nil {
suite.FailNow(err.Error())
}
move, ok := t.(vocab.ActivityStreamsMove)
if !ok {
suite.FailNow("", "couldn't cast %T to Move", t)
}
return suite.federatingDB.Move(ctx, move)
}
func (suite *MoveTestSuite) TestMove() {
var (
receivingAcct = suite.testAccounts["local_account_1"]
requestingAcct = suite.testAccounts["remote_account_1"]
moveStr1 = `{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "http://fossbros-anonymous.io/users/foss_satan/moves/01HR9FDFCAGM7JYPMWNTFRDQE9",
"actor": "http://fossbros-anonymous.io/users/foss_satan",
"type": "Move",
"object": "http://fossbros-anonymous.io/users/foss_satan",
"target": "https://turnip.farm/users/turniplover6969",
"to": "http://fossbros-anonymous.io/users/foss_satan/followers"
}`
)
// Trigger the move.
suite.move(receivingAcct, requestingAcct, moveStr1)
// Should be a message heading to the processor.
var msg messages.FromFediAPI
select {
case msg = <-suite.fromFederator:
// Fine.
case <-time.After(5 * time.Second):
suite.FailNow("", "timeout waiting for suite.fromFederator")
}
suite.Equal(ap.ObjectProfile, msg.APObjectType)
suite.Equal(ap.ActivityMove, msg.APActivityType)
// Stub Move should be on the message.
move, ok := msg.GTSModel.(*gtsmodel.Move)
if !ok {
suite.FailNow("", "could not cast %T to *gtsmodel.Move", msg.GTSModel)
}
suite.Equal("http://fossbros-anonymous.io/users/foss_satan", move.OriginURI)
suite.Equal("https://turnip.farm/users/turniplover6969", move.TargetURI)
// Trigger the same move again.
suite.move(receivingAcct, requestingAcct, moveStr1)
// Should be a message heading to the processor
// since this is just a straight up retry.
select {
case msg = <-suite.fromFederator:
// Fine.
case <-time.After(5 * time.Second):
suite.FailNow("", "timeout waiting for suite.fromFederator")
}
suite.Equal(ap.ObjectProfile, msg.APObjectType)
suite.Equal(ap.ActivityMove, msg.APActivityType)
// Same as the first Move, but with a different ID.
moveStr2 := `{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "http://fossbros-anonymous.io/users/foss_satan/moves/01HR9XWDD25CKXHW82MYD1GDAR",
"actor": "http://fossbros-anonymous.io/users/foss_satan",
"type": "Move",
"object": "http://fossbros-anonymous.io/users/foss_satan",
"target": "https://turnip.farm/users/turniplover6969",
"to": "http://fossbros-anonymous.io/users/foss_satan/followers"
}`
// Trigger the move.
suite.move(receivingAcct, requestingAcct, moveStr2)
// Should be a message heading to the processor
// since this is just a retry with a different ID.
select {
case msg = <-suite.fromFederator:
// Fine.
case <-time.After(5 * time.Second):
suite.FailNow("", "timeout waiting for suite.fromFederator")
}
suite.Equal(ap.ObjectProfile, msg.APObjectType)
suite.Equal(ap.ActivityMove, msg.APActivityType)
}
func (suite *MoveTestSuite) TestBadMoves() {
var (
receivingAcct = suite.testAccounts["local_account_1"]
requestingAcct = suite.testAccounts["remote_account_1"]
)
type testStruct struct {
moveStr string
err string
}
for _, t := range []testStruct{
{
// Move signed by someone else.
moveStr: `{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "http://fossbros-anonymous.io/users/foss_satan/moves/01HR9FDFCAGM7JYPMWNTFRDQE9",
"actor": "http://fossbros-anonymous.io/users/someone_else",
"type": "Move",
"object": "http://fossbros-anonymous.io/users/foss_satan",
"target": "https://turnip.farm/users/turniplover6969",
"to": "http://fossbros-anonymous.io/users/foss_satan/followers"
}`,
err: "Move was signed by http://fossbros-anonymous.io/users/foss_satan but actor was http://fossbros-anonymous.io/users/someone_else",
},
{
// Actor and object not the same.
moveStr: `{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "http://fossbros-anonymous.io/users/foss_satan/moves/01HR9FDFCAGM7JYPMWNTFRDQE9",
"actor": "http://fossbros-anonymous.io/users/foss_satan",
"type": "Move",
"object": "http://fossbros-anonymous.io/users/someone_else",
"target": "https://turnip.farm/users/turniplover6969",
"to": "http://fossbros-anonymous.io/users/foss_satan/followers"
}`,
err: "Move was signed by http://fossbros-anonymous.io/users/foss_satan but object was http://fossbros-anonymous.io/users/someone_else",
},
{
// Object and target the same.
moveStr: `{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "http://fossbros-anonymous.io/users/foss_satan/moves/01HR9FDFCAGM7JYPMWNTFRDQE9",
"actor": "http://fossbros-anonymous.io/users/foss_satan",
"type": "Move",
"object": "http://fossbros-anonymous.io/users/foss_satan",
"target": "http://fossbros-anonymous.io/users/foss_satan",
"to": "http://fossbros-anonymous.io/users/foss_satan/followers"
}`,
err: "Move target and origin were the same (http://fossbros-anonymous.io/users/foss_satan)",
},
} {
// Trigger the move.
err := suite.move(receivingAcct, requestingAcct, t.moveStr)
if t.err != "" {
suite.EqualError(err, t.err)
}
}
}
func TestMoveTestSuite(t *testing.T) {
suite.Run(t, &MoveTestSuite{})
}