Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] add instance-expose-public-timeline flag #1039

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/configuration/instance.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ instance-expose-peers: false
# Default: false
instance-expose-suspended: false

# Bool. Allow unauthenticated users to make queries to /api/v1/timelines/public in order
# to see a list of public posts on this server. Even if set to 'false', then authenticated
# users (members of the instance) will still be able to query the endpoint.
# Options: [true, false]
# Default: false
instance-expose-public-timeline: false

# Bool. This flag tweaks whether GoToSocial will deliver ActivityPub messages
# to the shared inbox of a recipient, if one is available, instead of delivering
# each message to each actor who should receive a message individually.
Expand Down
7 changes: 7 additions & 0 deletions example/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,13 @@ instance-expose-peers: false
# Default: false
instance-expose-suspended: false

# Bool. Allow unauthenticated users to make queries to /api/v1/timelines/public in order
# to see a list of public posts on this server. Even if set to 'false', then authenticated
# users (members of the instance) will still be able to query the endpoint.
# Options: [true, false]
# Default: false
instance-expose-public-timeline: false

# Bool. This flag tweaks whether GoToSocial will deliver ActivityPub messages
# to the shared inbox of a recipient, if one is available, instead of delivering
# each message to each actor who should receive a message individually.
Expand Down
13 changes: 9 additions & 4 deletions internal/api/client/timeline/public.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

"github.com/gin-gonic/gin"
"github.com/superseriousbusiness/gotosocial/internal/api"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
Expand Down Expand Up @@ -110,10 +111,14 @@ import (
// '400':
// description: bad request
func (m *Module) PublicTimelineGETHandler(c *gin.Context) {
authed, err := oauth.Authed(c, true, true, true, true)
if err != nil {
api.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGet)
return
authed := &oauth.Auth{}
if !config.GetInstanceExposePublicTimeline() {
sargant marked this conversation as resolved.
Show resolved Hide resolved
var err error
authed, err = oauth.Authed(c, true, true, true, true)
if err != nil {
api.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGet)
return
}
}

if _, err := api.NegotiateAccept(c, api.JSONAcceptHeaders...); err != nil {
Expand Down
1 change: 1 addition & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type Configuration struct {

InstanceExposePeers bool `name:"instance-expose-peers" usage:"Allow unauthenticated users to query /api/v1/instance/peers?filter=open"`
InstanceExposeSuspended bool `name:"instance-expose-suspended" usage:"Expose suspended instances via web UI, and allow unauthenticated users to query /api/v1/instance/peers?filter=suspended"`
InstanceExposePublicTimeline bool `name:"instance-expose-public-timeline" usage:"Allow unauthenticated users to query /api/v1/timelines/public"`
InstanceDeliverToSharedInboxes bool `name:"instance-deliver-to-shared-inboxes" usage:"Deliver federated messages to shared inboxes, if they're available."`

AccountsRegistrationOpen bool `name:"accounts-registration-open" usage:"Allow anyone to submit an account signup request. If false, server will be invite-only."`
Expand Down
26 changes: 26 additions & 0 deletions internal/config/helpers.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,31 @@ func GetInstanceExposeSuspended() bool { return global.GetInstanceExposeSuspende
// SetInstanceExposeSuspended safely sets the value for global configuration 'InstanceExposeSuspended' field
func SetInstanceExposeSuspended(v bool) { global.SetInstanceExposeSuspended(v) }

// GetInstanceExposePublicTimeline safely fetches the Configuration value for state's 'InstanceExposePublicTimeline' field
func (st *ConfigState) GetInstanceExposePublicTimeline() (v bool) {
st.mutex.Lock()
v = st.config.InstanceExposePublicTimeline
st.mutex.Unlock()
return
}

// SetInstanceExposePublicTimeline safely sets the Configuration value for state's 'InstanceExposePublicTimeline' field
func (st *ConfigState) SetInstanceExposePublicTimeline(v bool) {
st.mutex.Lock()
defer st.mutex.Unlock()
st.config.InstanceExposePublicTimeline = v
st.reloadToViper()
}

// InstanceExposePublicTimelineFlag returns the flag name for the 'InstanceExposePublicTimeline' field
func InstanceExposePublicTimelineFlag() string { return "instance-expose-public-timeline" }

// GetInstanceExposePublicTimeline safely fetches the value for global configuration 'InstanceExposePublicTimeline' field
func GetInstanceExposePublicTimeline() bool { return global.GetInstanceExposePublicTimeline() }

// SetInstanceExposePublicTimeline safely sets the value for global configuration 'InstanceExposePublicTimeline' field
func SetInstanceExposePublicTimeline(v bool) { global.SetInstanceExposePublicTimeline(v) }

// GetInstanceDeliverToSharedInboxes safely fetches the Configuration value for state's 'InstanceDeliverToSharedInboxes' field
func (st *ConfigState) GetInstanceDeliverToSharedInboxes() (v bool) {
st.mutex.Lock()
Expand Down Expand Up @@ -1869,3 +1894,4 @@ func GetAdvancedRateLimitRequests() int { return global.GetAdvancedRateLimitRequ

// SetAdvancedRateLimitRequests safely sets the value for global configuration 'AdvancedRateLimitRequests' field
func SetAdvancedRateLimitRequests(v int) { global.SetAdvancedRateLimitRequests(v) }

2 changes: 1 addition & 1 deletion internal/db/bundb/timeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func (t *timelineDB) GetHomeTimeline(ctx context.Context, accountID string, maxI
return statuses, nil
}

func (t *timelineDB) GetPublicTimeline(ctx context.Context, accountID string, maxID string, sinceID string, minID string, limit int, local bool) ([]*gtsmodel.Status, db.Error) {
func (t *timelineDB) GetPublicTimeline(ctx context.Context, maxID string, sinceID string, minID string, limit int, local bool) ([]*gtsmodel.Status, db.Error) {
// Ensure reasonable
if limit < 0 {
limit = 0
Expand Down
8 changes: 2 additions & 6 deletions internal/db/bundb/timeline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,19 @@ type TimelineTestSuite struct {
}

func (suite *TimelineTestSuite) TestGetPublicTimeline() {
viewingAccount := suite.testAccounts["local_account_1"]

s, err := suite.db.GetPublicTimeline(context.Background(), viewingAccount.ID, "", "", "", 20, false)
s, err := suite.db.GetPublicTimeline(context.Background(), "", "", "", 20, false)
suite.NoError(err)

suite.Len(s, 6)
}

func (suite *TimelineTestSuite) TestGetPublicTimelineWithFutureStatus() {
viewingAccount := suite.testAccounts["local_account_1"]

futureStatus := getFutureStatus()
if err := suite.db.Put(context.Background(), futureStatus); err != nil {
suite.FailNow(err.Error())
}

s, err := suite.db.GetPublicTimeline(context.Background(), viewingAccount.ID, "", "", "", 20, false)
s, err := suite.db.GetPublicTimeline(context.Background(), "", "", "", 20, false)
suite.NoError(err)

suite.Len(s, 6)
Expand Down
2 changes: 1 addition & 1 deletion internal/db/timeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type Timeline interface {
// It will use the given filters and try to return as many statuses as possible up to the limit.
//
// Statuses should be returned in descending order of when they were created (newest first).
GetPublicTimeline(ctx context.Context, accountID string, maxID string, sinceID string, minID string, limit int, local bool) ([]*gtsmodel.Status, Error)
GetPublicTimeline(ctx context.Context, maxID string, sinceID string, minID string, limit int, local bool) ([]*gtsmodel.Status, Error)

// GetFavedTimeline fetches the account's FAVED timeline -- ie., posts and replies that the requesting account has faved.
// It will use the given filters and try to return as many statuses as possible up to the limit.
Expand Down
2 changes: 1 addition & 1 deletion internal/processing/statustimeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ func (p *processor) HomeTimelineGet(ctx context.Context, authed *oauth.Auth, max
}

func (p *processor) PublicTimelineGet(ctx context.Context, authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) (*apimodel.PageableResponse, gtserror.WithCode) {
statuses, err := p.db.GetPublicTimeline(ctx, authed.Account.ID, maxID, sinceID, minID, limit, local)
statuses, err := p.db.GetPublicTimeline(ctx, maxID, sinceID, minID, limit, local)
if err != nil {
if err == db.ErrNoEntries {
// there are just no entries left
Expand Down
Loading