gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit da8954858afb4d5a3a2faf55e77d7da3be0ea3db
parent fcb9c0bb8bed51ffb856b8e47f4e047ddd75eb67
Author: tobi <31960611+tsmethurst@users.noreply.github.com>
Date:   Thu, 24 Nov 2022 13:54:49 +0100

[bugfix] Prevent future statuses entering timelines (#1134)

* [bugfix] Prevent future statuses entering timeline
Statuses created more than 5 minutes into the future are now rejected in the visibility package.

* Come on buddy
Diffstat:
Minternal/visibility/filter_test.go | 2+-
Minternal/visibility/statushometimelineable.go | 16+++++++++++++---
Minternal/visibility/statushometimelineable_test.go | 40++++++++++++++++++++++++++++++++++++++++
Minternal/visibility/statuspublictimelineable.go | 16+++++++++++++---
Minternal/visibility/statusvisible.go | 8++------
5 files changed, 69 insertions(+), 13 deletions(-)

diff --git a/internal/visibility/filter_test.go b/internal/visibility/filter_test.go @@ -60,8 +60,8 @@ func (suite *FilterStandardTestSuite) SetupSuite() { } func (suite *FilterStandardTestSuite) SetupTest() { - testrig.InitTestLog() testrig.InitTestConfig() + testrig.InitTestLog() suite.db = testrig.NewTestDB() suite.filter = visibility.NewFilter(suite.db) diff --git a/internal/visibility/statushometimelineable.go b/internal/visibility/statushometimelineable.go @@ -21,17 +21,27 @@ package visibility import ( "context" "fmt" + "time" "codeberg.org/gruf/go-kv" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/internal/id" "github.com/superseriousbusiness/gotosocial/internal/log" ) func (f *filter) StatusHometimelineable(ctx context.Context, targetStatus *gtsmodel.Status, timelineOwnerAccount *gtsmodel.Account) (bool, error) { - l := log.WithFields(kv.Fields{ + l := log.WithFields(kv.Fields{{"statusID", targetStatus.ID}}...) - {"statusID", targetStatus.ID}, - }...) + // don't timeline statuses more than 5 min in the future + maxID, err := id.NewULIDFromTime(time.Now().Add(5 * time.Minute)) + if err != nil { + return false, err + } + + if targetStatus.ID > maxID { + l.Debug("status not hometimelineable because it's from more than 5 minutes in the future") + return false, nil + } // status owner should always be able to see their own status in their timeline so we can return early if this is the case if targetStatus.AccountID == timelineOwnerAccount.ID { diff --git a/internal/visibility/statushometimelineable_test.go b/internal/visibility/statushometimelineable_test.go @@ -21,10 +21,12 @@ package visibility_test import ( "context" "testing" + "time" "github.com/stretchr/testify/suite" "github.com/superseriousbusiness/gotosocial/internal/ap" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/internal/id" "github.com/superseriousbusiness/gotosocial/testrig" ) @@ -65,6 +67,44 @@ func (suite *StatusStatusHometimelineableTestSuite) TestNotFollowingStatusHometi suite.False(timelineable) } +func (suite *StatusStatusHometimelineableTestSuite) TestStatusTooNewNotTimelineable() { + testStatus := &gtsmodel.Status{} + *testStatus = *suite.testStatuses["local_account_1_status_1"] + + var err error + testStatus.ID, err = id.NewULIDFromTime(time.Now().Add(10 * time.Minute)) + if err != nil { + suite.FailNow(err.Error()) + } + + testAccount := suite.testAccounts["local_account_1"] + ctx := context.Background() + + timelineable, err := suite.filter.StatusHometimelineable(ctx, testStatus, testAccount) + suite.NoError(err) + + suite.False(timelineable) +} + +func (suite *StatusStatusHometimelineableTestSuite) TestStatusNotTooNewTimelineable() { + testStatus := &gtsmodel.Status{} + *testStatus = *suite.testStatuses["local_account_1_status_1"] + + var err error + testStatus.ID, err = id.NewULIDFromTime(time.Now().Add(4 * time.Minute)) + if err != nil { + suite.FailNow(err.Error()) + } + + testAccount := suite.testAccounts["local_account_1"] + ctx := context.Background() + + timelineable, err := suite.filter.StatusHometimelineable(ctx, testStatus, testAccount) + suite.NoError(err) + + suite.True(timelineable) +} + func (suite *StatusStatusHometimelineableTestSuite) TestChainReplyFollowersOnly() { ctx := context.Background() diff --git a/internal/visibility/statuspublictimelineable.go b/internal/visibility/statuspublictimelineable.go @@ -21,17 +21,27 @@ package visibility import ( "context" "fmt" + "time" "codeberg.org/gruf/go-kv" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/internal/id" "github.com/superseriousbusiness/gotosocial/internal/log" ) func (f *filter) StatusPublictimelineable(ctx context.Context, targetStatus *gtsmodel.Status, timelineOwnerAccount *gtsmodel.Account) (bool, error) { - l := log.WithFields(kv.Fields{ + l := log.WithFields(kv.Fields{{"statusID", targetStatus.ID}}...) - {"statusID", targetStatus.ID}, - }...) + // don't timeline statuses more than 5 min in the future + maxID, err := id.NewULIDFromTime(time.Now().Add(5 * time.Minute)) + if err != nil { + return false, err + } + + if targetStatus.ID > maxID { + l.Debug("status not hometimelineable because it's from more than 5 minutes in the future") + return false, nil + } // Don't timeline boosted statuses if targetStatus.BoostOfID != "" { diff --git a/internal/visibility/statusvisible.go b/internal/visibility/statusvisible.go @@ -29,14 +29,10 @@ import ( ) func (f *filter) StatusVisible(ctx context.Context, targetStatus *gtsmodel.Status, requestingAccount *gtsmodel.Account) (bool, error) { - const getBoosted = true - - l := log.WithFields(kv.Fields{ - - {"statusID", targetStatus.ID}, - }...) + l := log.WithFields(kv.Fields{{"statusID", targetStatus.ID}}...) // Fetch any relevant accounts for the target status + const getBoosted = true relevantAccounts, err := f.relevantAccounts(ctx, targetStatus, getBoosted) if err != nil { l.Debugf("error pulling relevant accounts for status %s: %s", targetStatus.ID, err)