mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-11-26 01:13:33 -06:00
[feature] add instance-expose-public-timeline flag (#1039)
* Add instance-expose-public-timeline flag Adds a config flag that allows unauthenticated access to /api/v1/timelines/public. Defaults to false to replicate existing behaviour. * Update structure following review * Add comment * Fix linting
This commit is contained in:
parent
8f2d3ca664
commit
d120743e8b
11 changed files with 71 additions and 22 deletions
|
|
@ -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"
|
||||
)
|
||||
|
|
@ -110,7 +111,17 @@ import (
|
|||
// '400':
|
||||
// description: bad request
|
||||
func (m *Module) PublicTimelineGETHandler(c *gin.Context) {
|
||||
authed, err := oauth.Authed(c, true, true, true, true)
|
||||
var authed *oauth.Auth
|
||||
var err error
|
||||
|
||||
if config.GetInstanceExposePublicTimeline() {
|
||||
// If the public timeline is allowed to be exposed, still check if we
|
||||
// can extract various authentication properties, but don't require them.
|
||||
authed, err = oauth.Authed(c, false, false, false, false)
|
||||
} else {
|
||||
authed, err = oauth.Authed(c, true, true, true, true)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
api.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -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."`
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue