diff options
author | 2023-11-27 14:14:28 +0100 | |
---|---|---|
committer | 2023-11-27 13:14:28 +0000 | |
commit | e4e0a5e3f66f38e17a8abdafbeac251c75323b0e (patch) | |
tree | 6dc6211acd78df9fa3b933f19ab3275c187a5106 /internal | |
parent | [chore]: Bump golang.org/x/net from 0.17.0 to 0.18.0 (#2390) (diff) | |
download | gotosocial-e4e0a5e3f66f38e17a8abdafbeac251c75323b0e.tar.xz |
[bugfix] Add Actor to outgoing poll vote Create; other fixes (#2384)
Diffstat (limited to 'internal')
-rw-r--r-- | internal/processing/workers/federate.go | 7 | ||||
-rw-r--r-- | internal/typeutils/converter_test.go | 2 | ||||
-rw-r--r-- | internal/typeutils/internaltoas.go | 37 | ||||
-rw-r--r-- | internal/typeutils/internaltoas_test.go | 42 | ||||
-rw-r--r-- | internal/typeutils/wrap.go | 38 |
5 files changed, 76 insertions, 50 deletions
diff --git a/internal/processing/workers/federate.go b/internal/processing/workers/federate.go index 44432998d..aacb8dcc8 100644 --- a/internal/processing/workers/federate.go +++ b/internal/processing/workers/federate.go @@ -194,14 +194,13 @@ func (f *federate) CreatePollVote(ctx context.Context, poll *gtsmodel.Poll, vote return err } - // Convert votes to AS PollOptionable implementing type. - notes, err := f.converter.PollVoteToASOptions(ctx, vote) + // Convert vote to AS Create with vote choices as Objects. + create, err := f.converter.PollVoteToASCreate(ctx, vote) if err != nil { return gtserror.Newf("error converting to notes: %w", err) } - // Send a Create activity with PollOptionables via the Actor's outbox. - create := typeutils.WrapPollOptionablesInCreate(notes...) + // Send the Create via the Actor's outbox. if _, err := f.FederatingActor().Send(ctx, outboxIRI, create); err != nil { return gtserror.Newf("error sending Create activity via outbox %s: %w", outboxIRI, err) } diff --git a/internal/typeutils/converter_test.go b/internal/typeutils/converter_test.go index 0195a6889..8a0dcd0fd 100644 --- a/internal/typeutils/converter_test.go +++ b/internal/typeutils/converter_test.go @@ -480,6 +480,7 @@ type TypeUtilsTestSuite struct { testEmojis map[string]*gtsmodel.Emoji testReports map[string]*gtsmodel.Report testMentions map[string]*gtsmodel.Mention + testPollVotes map[string]*gtsmodel.PollVote typeconverter *typeutils.Converter } @@ -502,6 +503,7 @@ func (suite *TypeUtilsTestSuite) SetupTest() { suite.testEmojis = testrig.NewTestEmojis() suite.testReports = testrig.NewTestReports() suite.testMentions = testrig.NewTestMentions() + suite.testPollVotes = testrig.NewTestPollVotes() suite.typeconverter = typeutils.NewConverter(&suite.state) testrig.StandardDBSetup(suite.db, nil) diff --git a/internal/typeutils/internaltoas.go b/internal/typeutils/internaltoas.go index ff502296b..0ffad6fc1 100644 --- a/internal/typeutils/internaltoas.go +++ b/internal/typeutils/internaltoas.go @@ -1659,7 +1659,17 @@ func (c *Converter) ReportToASFlag(ctx context.Context, r *gtsmodel.Report) (voc return flag, nil } -func (c *Converter) PollVoteToASOptions(ctx context.Context, vote *gtsmodel.PollVote) ([]ap.PollOptionable, error) { +// PollVoteToASCreate converts a vote on a poll into a Create +// activity, suitable for federation, with each choice in the +// vote appended as a Note to the Create's Object field. +func (c *Converter) PollVoteToASCreate( + ctx context.Context, + vote *gtsmodel.PollVote, +) (vocab.ActivityStreamsCreate, error) { + if len(vote.Choices) == 0 { + panic("no vote.Choices") + } + // Ensure the vote is fully populated (this fetches author). if err := c.state.DB.PopulatePollVote(ctx, vote); err != nil { return nil, gtserror.Newf("error populating vote from db: %w", err) @@ -1694,11 +1704,22 @@ func (c *Converter) PollVoteToASOptions(ctx context.Context, vote *gtsmodel.Poll return nil, gtserror.Newf("invalid account uri: %w", err) } - // Preallocate the return slice of notes. - notes := make([]ap.PollOptionable, len(vote.Choices)) + // Allocate Create activity and address 'To' poll author. + create := streams.NewActivityStreamsCreate() + ap.AppendTo(create, pollAuthorIRI) + + // Create ID formatted as: {$voterIRI}/activity#vote/{$statusIRI}. + id := author.URI + "/activity#vote/" + poll.Status.URI + ap.MustSet(ap.SetJSONLDIdStr, ap.WithJSONLDId(create), id) + + // Set Create actor appropriately. + ap.AppendActor(create, authorIRI) + + // Set publish time for activity. + ap.SetPublished(create, vote.CreatedAt) - for i, choice := range vote.Choices { - // Create new note to represent vote. + // Parse each choice to a Note and add it to the Create. + for _, choice := range vote.Choices { note := streams.NewActivityStreamsNote() // For AP IRI generate from author URI + poll ID + vote choice. @@ -1715,9 +1736,9 @@ func (c *Converter) PollVoteToASOptions(ctx context.Context, vote *gtsmodel.Poll ap.AppendInReplyTo(note, statusIRI) ap.AppendTo(note, pollAuthorIRI) - // Set note in return slice. - notes[i] = note + // Append this note as Create Object. + appendStatusableToActivity(create, note, false) } - return notes, nil + return create, nil } diff --git a/internal/typeutils/internaltoas_test.go b/internal/typeutils/internaltoas_test.go index 878040dcc..0e0607279 100644 --- a/internal/typeutils/internaltoas_test.go +++ b/internal/typeutils/internaltoas_test.go @@ -879,6 +879,48 @@ func (suite *InternalToASTestSuite) TestPinnedStatusesToASOneItem() { }`, string(bytes)) } +func (suite *InternalToASTestSuite) TestPollVoteToASCreate() { + vote := suite.testPollVotes["remote_account_1_status_2_poll_vote_local_account_1"] + + create, err := suite.typeconverter.PollVoteToASCreate(context.Background(), vote) + if err != nil { + suite.FailNow(err.Error()) + } + + createI, err := ap.Serialize(create) + suite.NoError(err) + + bytes, err := json.MarshalIndent(createI, "", " ") + suite.NoError(err) + + suite.Equal(`{ + "@context": "https://www.w3.org/ns/activitystreams", + "actor": "http://localhost:8080/users/the_mighty_zork", + "id": "http://localhost:8080/users/the_mighty_zork/activity#vote/http://fossbros-anonymous.io/users/foss_satan/statuses/01HEN2QRFA8H3C6QPN7RD4KSR6", + "object": [ + { + "attributedTo": "http://localhost:8080/users/the_mighty_zork", + "id": "http://localhost:8080/users/the_mighty_zork#01HEN2R65468ZG657C4ZPHJ4EX/votes/1", + "inReplyTo": "http://fossbros-anonymous.io/users/foss_satan/statuses/01HEN2QRFA8H3C6QPN7RD4KSR6", + "name": "tissues", + "to": "http://fossbros-anonymous.io/users/foss_satan", + "type": "Note" + }, + { + "attributedTo": "http://localhost:8080/users/the_mighty_zork", + "id": "http://localhost:8080/users/the_mighty_zork#01HEN2R65468ZG657C4ZPHJ4EX/votes/2", + "inReplyTo": "http://fossbros-anonymous.io/users/foss_satan/statuses/01HEN2QRFA8H3C6QPN7RD4KSR6", + "name": "financial times", + "to": "http://fossbros-anonymous.io/users/foss_satan", + "type": "Note" + } + ], + "published": "2021-09-11T11:45:37+02:00", + "to": "http://fossbros-anonymous.io/users/foss_satan", + "type": "Create" +}`, string(bytes)) +} + func TestInternalToASTestSuite(t *testing.T) { suite.Run(t, new(InternalToASTestSuite)) } diff --git a/internal/typeutils/wrap.go b/internal/typeutils/wrap.go index 5deca0e5b..5892e0a66 100644 --- a/internal/typeutils/wrap.go +++ b/internal/typeutils/wrap.go @@ -19,7 +19,6 @@ package typeutils import ( "net/url" - "time" "github.com/superseriousbusiness/activity/pub" "github.com/superseriousbusiness/activity/streams" @@ -91,43 +90,6 @@ func WrapStatusableInCreate(status ap.Statusable, iriOnly bool) vocab.ActivitySt return create } -func WrapPollOptionablesInCreate(options ...ap.PollOptionable) vocab.ActivityStreamsCreate { - if len(options) == 0 { - panic("no options") - } - - // Extract attributedTo IRI from any option. - attribTos := ap.GetAttributedTo(options[0]) - if len(attribTos) != 1 { - panic("invalid attributedTo count") - } - - // Extract target status IRI from any option. - replyTos := ap.GetInReplyTo(options[0]) - if len(replyTos) != 1 { - panic("invalid inReplyTo count") - } - - // Allocate create activity and copy over 'To' property. - create := streams.NewActivityStreamsCreate() - ap.AppendTo(create, ap.GetTo(options[0])...) - - // Activity ID formatted as: {$statusIRI}/activity#vote/{$voterIRI}. - id := replyTos[0].String() + "/activity#vote/" + attribTos[0].String() - ap.MustSet(ap.SetJSONLDIdStr, ap.WithJSONLDId(create), id) - - // Set a current publish time for activity. - ap.SetPublished(create, time.Now()) - - // Append each poll option as object to activity. - for _, option := range options { - status, _ := ap.ToStatusable(option) - appendStatusableToActivity(create, status, false) - } - - return create -} - func WrapStatusableInUpdate(status ap.Statusable, iriOnly bool) vocab.ActivityStreamsUpdate { update := streams.NewActivityStreamsUpdate() wrapStatusableInActivity(update, status, iriOnly) |