[feature] make account sign-up / backlog limits configurable (#3768)

This commit is contained in:
tobi 2025-02-10 15:46:36 +01:00 committed by GitHub
commit 787bdc1488
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 151 additions and 36 deletions

View file

@ -92,10 +92,12 @@ type Configuration struct {
InstanceSubscriptionsProcessEvery time.Duration `name:"instance-subscriptions-process-every" usage:"Period to elapse between instance subscriptions processing jobs, starting from instance-subscriptions-process-from."`
InstanceStatsMode string `name:"instance-stats-mode" usage:"Allows you to customize the way stats are served to crawlers: one of '', 'serve', 'zero', 'baffle'. Home page stats remain unchanged."`
AccountsRegistrationOpen bool `name:"accounts-registration-open" usage:"Allow anyone to submit an account signup request. If false, server will be invite-only."`
AccountsReasonRequired bool `name:"accounts-reason-required" usage:"Do new account signups require a reason to be submitted on registration?"`
AccountsAllowCustomCSS bool `name:"accounts-allow-custom-css" usage:"Allow accounts to enable custom CSS for their profile pages and statuses."`
AccountsCustomCSSLength int `name:"accounts-custom-css-length" usage:"Maximum permitted length (characters) of custom CSS for accounts."`
AccountsRegistrationOpen bool `name:"accounts-registration-open" usage:"Allow anyone to submit an account signup request. If false, server will be invite-only."`
AccountsReasonRequired bool `name:"accounts-reason-required" usage:"Do new account signups require a reason to be submitted on registration?"`
AccountsRegistrationDailyLimit int `name:"accounts-registration-daily-limit" usage:"Limit amount of approved account sign-ups allowed per 24hrs before registration is closed. 0 or less = no limit."`
AccountsRegistrationBacklogLimit int `name:"accounts-registration-backlog-limit" usage:"Limit how big the 'accounts pending approval' queue can grow before registration is closed. 0 or less = no limit."`
AccountsAllowCustomCSS bool `name:"accounts-allow-custom-css" usage:"Allow accounts to enable custom CSS for their profile pages and statuses."`
AccountsCustomCSSLength int `name:"accounts-custom-css-length" usage:"Maximum permitted length (characters) of custom CSS for accounts."`
MediaDescriptionMinChars int `name:"media-description-min-chars" usage:"Min required chars for an image description"`
MediaDescriptionMaxChars int `name:"media-description-max-chars" usage:"Max permitted chars for an image description"`

View file

@ -68,10 +68,12 @@ var Defaults = Configuration{
InstanceSubscriptionsProcessFrom: "23:00", // 11pm,
InstanceSubscriptionsProcessEvery: 24 * time.Hour, // 1/day.
AccountsRegistrationOpen: false,
AccountsReasonRequired: true,
AccountsAllowCustomCSS: false,
AccountsCustomCSSLength: 10000,
AccountsRegistrationOpen: false,
AccountsReasonRequired: true,
AccountsRegistrationDailyLimit: 10,
AccountsRegistrationBacklogLimit: 20,
AccountsAllowCustomCSS: false,
AccountsCustomCSSLength: 10000,
MediaDescriptionMinChars: 0,
MediaDescriptionMaxChars: 1500,

View file

@ -1132,6 +1132,56 @@ func GetAccountsReasonRequired() bool { return global.GetAccountsReasonRequired(
// SetAccountsReasonRequired safely sets the value for global configuration 'AccountsReasonRequired' field
func SetAccountsReasonRequired(v bool) { global.SetAccountsReasonRequired(v) }
// GetAccountsRegistrationDailyLimit safely fetches the Configuration value for state's 'AccountsRegistrationDailyLimit' field
func (st *ConfigState) GetAccountsRegistrationDailyLimit() (v int) {
st.mutex.RLock()
v = st.config.AccountsRegistrationDailyLimit
st.mutex.RUnlock()
return
}
// SetAccountsRegistrationDailyLimit safely sets the Configuration value for state's 'AccountsRegistrationDailyLimit' field
func (st *ConfigState) SetAccountsRegistrationDailyLimit(v int) {
st.mutex.Lock()
defer st.mutex.Unlock()
st.config.AccountsRegistrationDailyLimit = v
st.reloadToViper()
}
// AccountsRegistrationDailyLimitFlag returns the flag name for the 'AccountsRegistrationDailyLimit' field
func AccountsRegistrationDailyLimitFlag() string { return "accounts-registration-daily-limit" }
// GetAccountsRegistrationDailyLimit safely fetches the value for global configuration 'AccountsRegistrationDailyLimit' field
func GetAccountsRegistrationDailyLimit() int { return global.GetAccountsRegistrationDailyLimit() }
// SetAccountsRegistrationDailyLimit safely sets the value for global configuration 'AccountsRegistrationDailyLimit' field
func SetAccountsRegistrationDailyLimit(v int) { global.SetAccountsRegistrationDailyLimit(v) }
// GetAccountsRegistrationBacklogLimit safely fetches the Configuration value for state's 'AccountsRegistrationBacklogLimit' field
func (st *ConfigState) GetAccountsRegistrationBacklogLimit() (v int) {
st.mutex.RLock()
v = st.config.AccountsRegistrationBacklogLimit
st.mutex.RUnlock()
return
}
// SetAccountsRegistrationBacklogLimit safely sets the Configuration value for state's 'AccountsRegistrationBacklogLimit' field
func (st *ConfigState) SetAccountsRegistrationBacklogLimit(v int) {
st.mutex.Lock()
defer st.mutex.Unlock()
st.config.AccountsRegistrationBacklogLimit = v
st.reloadToViper()
}
// AccountsRegistrationBacklogLimitFlag returns the flag name for the 'AccountsRegistrationBacklogLimit' field
func AccountsRegistrationBacklogLimitFlag() string { return "accounts-registration-backlog-limit" }
// GetAccountsRegistrationBacklogLimit safely fetches the value for global configuration 'AccountsRegistrationBacklogLimit' field
func GetAccountsRegistrationBacklogLimit() int { return global.GetAccountsRegistrationBacklogLimit() }
// SetAccountsRegistrationBacklogLimit safely sets the value for global configuration 'AccountsRegistrationBacklogLimit' field
func SetAccountsRegistrationBacklogLimit(v int) { global.SetAccountsRegistrationBacklogLimit(v) }
// GetAccountsAllowCustomCSS safely fetches the Configuration value for state's 'AccountsAllowCustomCSS' field
func (st *ConfigState) GetAccountsAllowCustomCSS() (v bool) {
st.mutex.RLock()

View file

@ -44,34 +44,43 @@ func (p *Processor) Create(
app *gtsmodel.Application,
form *apimodel.AccountCreateRequest,
) (*gtsmodel.User, gtserror.WithCode) {
const (
usersPerDay = 10
regBacklog = 20
var (
usersPerDay = config.GetAccountsRegistrationDailyLimit()
regBacklog = config.GetAccountsRegistrationBacklogLimit()
)
// Ensure no more than usersPerDay
// If usersPerDay limit is in place,
// ensure no more than usersPerDay
// have registered in the last 24h.
newUsersCount, err := p.state.DB.CountApprovedSignupsSince(ctx, time.Now().Add(-24*time.Hour))
if err != nil {
err := fmt.Errorf("db error counting new users: %w", err)
return nil, gtserror.NewErrorInternalError(err)
if usersPerDay > 0 {
newUsersCount, err := p.state.DB.CountApprovedSignupsSince(ctx, time.Now().Add(-24*time.Hour))
if err != nil {
err := fmt.Errorf("db error counting new users: %w", err)
return nil, gtserror.NewErrorInternalError(err)
}
if newUsersCount >= usersPerDay {
err := fmt.Errorf("this instance has hit its limit of new sign-ups for today (%d); you can try again tomorrow", usersPerDay)
return nil, gtserror.NewErrorUnprocessableEntity(err, err.Error())
}
}
if newUsersCount >= usersPerDay {
err := fmt.Errorf("this instance has hit its limit of new sign-ups for today; you can try again tomorrow")
return nil, gtserror.NewErrorUnprocessableEntity(err, err.Error())
}
// If registration backlog limit is
// in place, ensure backlog isn't full.
if regBacklog > 0 {
backlogLen, err := p.state.DB.CountUnhandledSignups(ctx)
if err != nil {
err := fmt.Errorf("db error counting registration backlog length: %w", err)
return nil, gtserror.NewErrorInternalError(err)
}
// Ensure the new users backlog isn't full.
backlogLen, err := p.state.DB.CountUnhandledSignups(ctx)
if err != nil {
err := fmt.Errorf("db error counting registration backlog length: %w", err)
return nil, gtserror.NewErrorInternalError(err)
}
if backlogLen >= regBacklog {
err := fmt.Errorf("this instance's sign-up backlog is currently full; you must wait until pending sign-ups are handled by the admin(s)")
return nil, gtserror.NewErrorUnprocessableEntity(err, err.Error())
if backlogLen >= regBacklog {
err := fmt.Errorf(
"this instance's sign-up backlog is currently full (%d sign-ups pending approval); "+
"you must wait until some pending sign-ups are handled by the admin(s)", regBacklog,
)
return nil, gtserror.NewErrorUnprocessableEntity(err, err.Error())
}
}
emailAvailable, err := p.state.DB.IsEmailAvailable(ctx, form.Email)