Skip to content

Commit

Permalink
[bugfix] Visibility fixes (#687)
Browse files Browse the repository at this point in the history
* test self boost

* only CC to public when necessary
  • Loading branch information
tsmethurst authored Jul 4, 2022
1 parent c6d1b82 commit 4a69651
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 43 deletions.
124 changes: 94 additions & 30 deletions internal/api/client/status/statusboost_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"testing"

"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/api/client/status"
"github.com/superseriousbusiness/gotosocial/internal/api/model"
Expand Down Expand Up @@ -72,36 +71,101 @@ func (suite *StatusBoostTestSuite) TestPostBoost() {
result := recorder.Result()
defer result.Body.Close()
b, err := ioutil.ReadAll(result.Body)
assert.NoError(suite.T(), err)
suite.NoError(err)

statusReply := &model.Status{}
err = json.Unmarshal(b, statusReply)
assert.NoError(suite.T(), err)

assert.False(suite.T(), statusReply.Sensitive)
assert.Equal(suite.T(), model.VisibilityPublic, statusReply.Visibility)

assert.Equal(suite.T(), targetStatus.ContentWarning, statusReply.SpoilerText)
assert.Equal(suite.T(), targetStatus.Content, statusReply.Content)
assert.Equal(suite.T(), "the_mighty_zork", statusReply.Account.Username)
assert.Len(suite.T(), statusReply.MediaAttachments, 0)
assert.Len(suite.T(), statusReply.Mentions, 0)
assert.Len(suite.T(), statusReply.Emojis, 0)
assert.Len(suite.T(), statusReply.Tags, 0)

assert.NotNil(suite.T(), statusReply.Application)
assert.Equal(suite.T(), "really cool gts application", statusReply.Application.Name)

assert.NotNil(suite.T(), statusReply.Reblog)
assert.Equal(suite.T(), 1, statusReply.Reblog.ReblogsCount)
assert.Equal(suite.T(), 1, statusReply.Reblog.FavouritesCount)
assert.Equal(suite.T(), targetStatus.Content, statusReply.Reblog.Content)
assert.Equal(suite.T(), targetStatus.ContentWarning, statusReply.Reblog.SpoilerText)
assert.Equal(suite.T(), targetStatus.AccountID, statusReply.Reblog.Account.ID)
assert.Len(suite.T(), statusReply.Reblog.MediaAttachments, 1)
assert.Len(suite.T(), statusReply.Reblog.Tags, 1)
assert.Len(suite.T(), statusReply.Reblog.Emojis, 1)
assert.Equal(suite.T(), "superseriousbusiness", statusReply.Reblog.Application.Name)
suite.NoError(err)

suite.False(statusReply.Sensitive)
suite.Equal(model.VisibilityPublic, statusReply.Visibility)

suite.Equal(targetStatus.ContentWarning, statusReply.SpoilerText)
suite.Equal(targetStatus.Content, statusReply.Content)
suite.Equal("the_mighty_zork", statusReply.Account.Username)
suite.Len(statusReply.MediaAttachments, 0)
suite.Len(statusReply.Mentions, 0)
suite.Len(statusReply.Emojis, 0)
suite.Len(statusReply.Tags, 0)

suite.NotNil(statusReply.Application)
suite.Equal("really cool gts application", statusReply.Application.Name)

suite.NotNil(statusReply.Reblog)
suite.Equal(1, statusReply.Reblog.ReblogsCount)
suite.Equal(1, statusReply.Reblog.FavouritesCount)
suite.Equal(targetStatus.Content, statusReply.Reblog.Content)
suite.Equal(targetStatus.ContentWarning, statusReply.Reblog.SpoilerText)
suite.Equal(targetStatus.AccountID, statusReply.Reblog.Account.ID)
suite.Len(statusReply.Reblog.MediaAttachments, 1)
suite.Len(statusReply.Reblog.Tags, 1)
suite.Len(statusReply.Reblog.Emojis, 1)
suite.Equal("superseriousbusiness", statusReply.Reblog.Application.Name)
}

func (suite *StatusBoostTestSuite) TestPostBoostOwnFollowersOnly() {
t := suite.testTokens["local_account_1"]
oauthToken := oauth.DBTokenToToken(t)

testStatus := suite.testStatuses["local_account_1_status_5"]
testAccount := suite.testAccounts["local_account_1"]
testUser := suite.testUsers["local_account_1"]

recorder := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(recorder)
ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"])
ctx.Set(oauth.SessionAuthorizedToken, oauthToken)
ctx.Set(oauth.SessionAuthorizedUser, testUser)
ctx.Set(oauth.SessionAuthorizedAccount, testAccount)
ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080%s", strings.Replace(status.ReblogPath, ":id", testStatus.ID, 1)), nil)
ctx.Request.Header.Set("accept", "application/json")

ctx.Params = gin.Params{
gin.Param{
Key: status.IDKey,
Value: testStatus.ID,
},
}

suite.statusModule.StatusBoostPOSTHandler(ctx)

// check response
suite.EqualValues(http.StatusOK, recorder.Code)

result := recorder.Result()
defer result.Body.Close()
b, err := ioutil.ReadAll(result.Body)
suite.NoError(err)

responseStatus := &model.Status{}
err = json.Unmarshal(b, responseStatus)
suite.NoError(err)

suite.False(responseStatus.Sensitive)
suite.Equal(suite.tc.VisToAPIVis(context.Background(), testStatus.Visibility), responseStatus.Visibility)

suite.Equal(testStatus.ContentWarning, responseStatus.SpoilerText)
suite.Equal(testStatus.Content, responseStatus.Content)
suite.Equal("the_mighty_zork", responseStatus.Account.Username)
suite.Len(responseStatus.MediaAttachments, 0)
suite.Len(responseStatus.Mentions, 0)
suite.Len(responseStatus.Emojis, 0)
suite.Len(responseStatus.Tags, 0)

suite.NotNil(responseStatus.Application)
suite.Equal("really cool gts application", responseStatus.Application.Name)

suite.NotNil(responseStatus.Reblog)
suite.Equal(1, responseStatus.Reblog.ReblogsCount)
suite.Equal(0, responseStatus.Reblog.FavouritesCount)
suite.Equal(testStatus.Content, responseStatus.Reblog.Content)
suite.Equal(testStatus.ContentWarning, responseStatus.Reblog.SpoilerText)
suite.Equal(testStatus.AccountID, responseStatus.Reblog.Account.ID)
suite.Equal(suite.tc.VisToAPIVis(context.Background(), testStatus.Visibility), responseStatus.Reblog.Visibility)
suite.Empty(responseStatus.Reblog.MediaAttachments)
suite.Empty(responseStatus.Reblog.Tags)
suite.Empty(responseStatus.Reblog.Emojis)
suite.Equal("really cool gts application", responseStatus.Reblog.Application.Name)
}

// try to boost a status that's not boostable
Expand Down Expand Up @@ -139,8 +203,8 @@ func (suite *StatusBoostTestSuite) TestPostUnboostable() {
result := recorder.Result()
defer result.Body.Close()
b, err := ioutil.ReadAll(result.Body)
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), `{"error":"Forbidden"}`, string(b))
suite.NoError(err)
suite.Equal(`{"error":"Forbidden"}`, string(b))
}

// try to boost a status that's not visible to the user
Expand Down
18 changes: 11 additions & 7 deletions internal/typeutils/internaltoas.go
Original file line number Diff line number Diff line change
Expand Up @@ -815,19 +815,23 @@ func (c *converter) BoostToAS(ctx context.Context, boostWrapperStatus *gtsmodel.
announce.SetActivityStreamsTo(toProp)

// set the cc
boostedURI, err := url.Parse(boostedAccount.URI)
ccProp := streams.NewActivityStreamsCcProperty()
boostedAccountURI, err := url.Parse(boostedAccount.URI)
if err != nil {
return nil, fmt.Errorf("BoostToAS: error parsing uri %s: %s", boostedAccount.URI, err)
}
ccProp.AppendIRI(boostedAccountURI)

publicURI, err := url.Parse(pub.PublicActivityPubIRI)
if err != nil {
return nil, fmt.Errorf("BoostToAS: error parsing uri %s: %s", pub.PublicActivityPubIRI, err)
// maybe CC it to public depending on the boosted status visibility
switch boostWrapperStatus.BoostOf.Visibility {
case gtsmodel.VisibilityPublic, gtsmodel.VisibilityUnlocked:
publicURI, err := url.Parse(pub.PublicActivityPubIRI)
if err != nil {
return nil, fmt.Errorf("BoostToAS: error parsing uri %s: %s", pub.PublicActivityPubIRI, err)
}
ccProp.AppendIRI(publicURI)
}

ccProp := streams.NewActivityStreamsCcProperty()
ccProp.AppendIRI(boostedURI)
ccProp.AppendIRI(publicURI)
announce.SetActivityStreamsCc(ccProp)

return announce, nil
Expand Down
38 changes: 32 additions & 6 deletions internal/typeutils/internaltoas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ import (
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/activity/streams"
"github.com/superseriousbusiness/gotosocial/testrig"
)

type InternalToASTestSuite struct {
Expand Down Expand Up @@ -60,7 +60,7 @@ func (suite *InternalToASTestSuite) TestOutboxToASCollection() {
suite.NoError(err)

ser, err := streams.Serialize(collection)
assert.NoError(suite.T(), err)
suite.NoError(err)

bytes, err := json.Marshal(ser)
suite.NoError(err)
Expand All @@ -86,7 +86,7 @@ func (suite *InternalToASTestSuite) TestStatusToAS() {
suite.NoError(err)

ser, err := streams.Serialize(asStatus)
assert.NoError(suite.T(), err)
suite.NoError(err)

bytes, err := json.Marshal(ser)
suite.NoError(err)
Expand All @@ -105,7 +105,7 @@ func (suite *InternalToASTestSuite) TestStatusToASWithMentions() {
suite.NoError(err)

ser, err := streams.Serialize(asStatus)
assert.NoError(suite.T(), err)
suite.NoError(err)

bytes, err := json.Marshal(ser)
suite.NoError(err)
Expand All @@ -122,7 +122,7 @@ func (suite *InternalToASTestSuite) TestStatusToASNotSensitive() {
suite.NoError(err)

ser, err := streams.Serialize(asStatus)
assert.NoError(suite.T(), err)
suite.NoError(err)

bytes, err := json.Marshal(ser)
suite.NoError(err)
Expand All @@ -142,7 +142,7 @@ func (suite *InternalToASTestSuite) TestStatusesToASOutboxPage() {
suite.NoError(err)

ser, err := streams.Serialize(page)
assert.NoError(suite.T(), err)
suite.NoError(err)

bytes, err := json.Marshal(ser)
suite.NoError(err)
Expand Down Expand Up @@ -184,6 +184,32 @@ func (suite *InternalToASTestSuite) TestStatusesToASOutboxPage() {
suite.Equal(`{"@context":"https://www.w3.org/ns/activitystreams","id":"http://localhost:8080/users/admin/outbox?page=true","next":"http://localhost:8080/users/admin/outbox?page=true\u0026max_id=01F8MH75CBF9JFX4ZAD54N0W0R","orderedItems":[{"actor":"http://localhost:8080/users/admin","cc":"http://localhost:8080/users/admin/followers","id":"http://localhost:8080/users/admin/statuses/01F8MHAAY43M6RJ473VQFCVH37/activity","object":"http://localhost:8080/users/admin/statuses/01F8MHAAY43M6RJ473VQFCVH37","published":"2021-10-20T12:36:45Z","to":"https://www.w3.org/ns/activitystreams#Public","type":"Create"},{"actor":"http://localhost:8080/users/admin","cc":"http://localhost:8080/users/admin/followers","id":"http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R/activity","object":"http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R","published":"2021-10-20T11:36:45Z","to":"https://www.w3.org/ns/activitystreams#Public","type":"Create"}],"partOf":"http://localhost:8080/users/admin/outbox","prev":"http://localhost:8080/users/admin/outbox?page=true\u0026min_id=01F8MHAAY43M6RJ473VQFCVH37","type":"OrderedCollectionPage"}`, string(bytes))
}

func (suite *InternalToASTestSuite) TestSelfBoostFollowersOnlyToAS() {
ctx := context.Background()

testStatus := suite.testStatuses["local_account_1_status_5"]
testAccount := suite.testAccounts["local_account_1"]

boostWrapperStatus, err := suite.typeconverter.StatusToBoost(ctx, testStatus, testAccount)
suite.NoError(err)
suite.NotNil(boostWrapperStatus)

boostWrapperStatus.ID = "01G74JJ1KS331G2JXHRMZCE0ER"
boostWrapperStatus.URI = "http://localhost:8080/users/the_mighty_zork/statuses/01G74JJ1KS331G2JXHRMZCE0ER"
boostWrapperStatus.CreatedAt = testrig.TimeMustParse("2022-06-09T13:12:00Z")

asBoost, err := suite.typeconverter.BoostToAS(ctx, boostWrapperStatus, testAccount, testAccount)
suite.NoError(err)

ser, err := streams.Serialize(asBoost)
suite.NoError(err)

bytes, err := json.Marshal(ser)
suite.NoError(err)

suite.Equal(`{"@context":"https://www.w3.org/ns/activitystreams","actor":"http://localhost:8080/users/the_mighty_zork","cc":"http://localhost:8080/users/the_mighty_zork","id":"http://localhost:8080/users/the_mighty_zork/statuses/01G74JJ1KS331G2JXHRMZCE0ER","object":"http://localhost:8080/users/the_mighty_zork/statuses/01FCTA44PW9H1TB328S9AQXKDS","published":"2022-06-09T13:12:00Z","to":"http://localhost:8080/users/the_mighty_zork/followers","type":"Announce"}`, string(bytes))
}

func TestInternalToASTestSuite(t *testing.T) {
suite.Run(t, new(InternalToASTestSuite))
}

0 comments on commit 4a69651

Please sign in to comment.