mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-12-10 07:08:08 -06:00
[feature] Allow exposing allows, implement /api/v1/domain_blocks and /api/v1/domain_allows (#4169)
- adds config flags `instance-expose-allowlist` and `instance-expose-allowlist-web` to allow instance admins to expose their allowlist via the web + api. - renames `instance-expose-suspended` and `instance-expose-suspended-web` to `instance-expose-blocklist` and `instance-expose-blocklist-web`. - deprecates the `suspended` filter on `/api/v1/instance/peers` endpoint and adds `blocked` and `allowed` filters - adds the `flat` query param to `/api/v1/instance/peers` to allow forcing return of a flat list of domains - implements `/api/v1/instance/domain_blocks` and `/api/v1/instance/domain_allows` endpoints with or without auth depending on config - rejigs the instance about page to include a general section on domain permissions, with block and allow subsections (and appropriate links) Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/3847 Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4150 Prerequisite to https://codeberg.org/superseriousbusiness/gotosocial/issues/3711 Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4169 Co-authored-by: tobi <tobi.smethurst@protonmail.com> Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This commit is contained in:
parent
3a29a59e55
commit
ec4d4d0115
23 changed files with 986 additions and 271 deletions
|
|
@ -49,7 +49,10 @@ func fieldtag(field, tag string) string {
|
|||
//
|
||||
// Please note that if you update this struct's fields or tags, you
|
||||
// will need to regenerate the global Getter/Setter helpers by running:
|
||||
// `go run ./internal/config/gen/ -out ./internal/config/helpers.gen.go`
|
||||
// `go run ./internal/config/gen/ -out ./internal/config/helpers.gen.go`.
|
||||
//
|
||||
// You will need to have gofumpt installed in order for this to work:
|
||||
// https://github.com/mvdan/gofumpt.
|
||||
type Configuration struct {
|
||||
LogLevel string `name:"log-level" usage:"Log level to run at: [trace, debug, info, warn, fatal]"`
|
||||
LogTimestampFormat string `name:"log-timestamp-format" usage:"Format to use for the log timestamp, as supported by Go's time.Layout"`
|
||||
|
|
@ -88,8 +91,10 @@ type Configuration struct {
|
|||
InstanceFederationMode string `name:"instance-federation-mode" usage:"Set instance federation mode."`
|
||||
InstanceFederationSpamFilter bool `name:"instance-federation-spam-filter" usage:"Enable basic spam filter heuristics for messages coming from other instances, and drop messages identified as spam"`
|
||||
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"`
|
||||
InstanceExposeSuspendedWeb bool `name:"instance-expose-suspended-web" usage:"Expose list of suspended instances as webpage on /about/suspended"`
|
||||
InstanceExposeBlocklist bool `name:"instance-expose-blocklist" usage:"Expose list of blocked domains via web UI, and allow unauthenticated users to query /api/v1/instance/peers?filter=blocked and /api/v1/instance/domain_blocks"`
|
||||
InstanceExposeBlocklistWeb bool `name:"instance-expose-blocklist-web" usage:"Expose list of explicitly blocked domains as webpage on /about/domain_blocks"`
|
||||
InstanceExposeAllowlist bool `name:"instance-expose-allowlist" usage:"Expose list of allowed domains via web UI, and allow unauthenticated users to query /api/v1/instance/peers?filter=allowed and /api/v1/instance/domain_allows"`
|
||||
InstanceExposeAllowlistWeb bool `name:"instance-expose-allowlist-web" usage:"Expose list of explicitly allowed domains as webpage on /about/domain_allows"`
|
||||
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."`
|
||||
InstanceInjectMastodonVersion bool `name:"instance-inject-mastodon-version" usage:"This injects a Mastodon compatible version in /api/v1/instance to help Mastodon clients that use that version for feature detection"`
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ var Defaults = Configuration{
|
|||
InstanceFederationMode: InstanceFederationModeDefault,
|
||||
InstanceFederationSpamFilter: false,
|
||||
InstanceExposePeers: false,
|
||||
InstanceExposeSuspended: false,
|
||||
InstanceExposeSuspendedWeb: false,
|
||||
InstanceExposeBlocklist: false,
|
||||
InstanceExposeBlocklistWeb: false,
|
||||
InstanceDeliverToSharedInboxes: true,
|
||||
InstanceLanguages: make(language.Languages, 0),
|
||||
InstanceSubscriptionsProcessFrom: "23:00", // 11pm,
|
||||
|
|
|
|||
|
|
@ -63,8 +63,10 @@ func (cfg *Configuration) RegisterFlags(flags *pflag.FlagSet) {
|
|||
flags.String("instance-federation-mode", cfg.InstanceFederationMode, "Set instance federation mode.")
|
||||
flags.Bool("instance-federation-spam-filter", cfg.InstanceFederationSpamFilter, "Enable basic spam filter heuristics for messages coming from other instances, and drop messages identified as spam")
|
||||
flags.Bool("instance-expose-peers", cfg.InstanceExposePeers, "Allow unauthenticated users to query /api/v1/instance/peers?filter=open")
|
||||
flags.Bool("instance-expose-suspended", cfg.InstanceExposeSuspended, "Expose suspended instances via web UI, and allow unauthenticated users to query /api/v1/instance/peers?filter=suspended")
|
||||
flags.Bool("instance-expose-suspended-web", cfg.InstanceExposeSuspendedWeb, "Expose list of suspended instances as webpage on /about/suspended")
|
||||
flags.Bool("instance-expose-blocklist", cfg.InstanceExposeBlocklist, "Expose list of blocked domains via web UI, and allow unauthenticated users to query /api/v1/instance/peers?filter=blocked and /api/v1/instance/domain_blocks")
|
||||
flags.Bool("instance-expose-blocklist-web", cfg.InstanceExposeBlocklistWeb, "Expose list of explicitly blocked domains as webpage on /about/domain_blocks")
|
||||
flags.Bool("instance-expose-allowlist", cfg.InstanceExposeAllowlist, "Expose list of allowed domains via web UI, and allow unauthenticated users to query /api/v1/instance/peers?filter=allowed and /api/v1/instance/domain_allows")
|
||||
flags.Bool("instance-expose-allowlist-web", cfg.InstanceExposeAllowlistWeb, "Expose list of explicitly allowed domains as webpage on /about/domain_allows")
|
||||
flags.Bool("instance-expose-public-timeline", cfg.InstanceExposePublicTimeline, "Allow unauthenticated users to query /api/v1/timelines/public")
|
||||
flags.Bool("instance-deliver-to-shared-inboxes", cfg.InstanceDeliverToSharedInboxes, "Deliver federated messages to shared inboxes, if they're available.")
|
||||
flags.Bool("instance-inject-mastodon-version", cfg.InstanceInjectMastodonVersion, "This injects a Mastodon compatible version in /api/v1/instance to help Mastodon clients that use that version for feature detection")
|
||||
|
|
@ -79,7 +81,7 @@ func (cfg *Configuration) RegisterFlags(flags *pflag.FlagSet) {
|
|||
flags.Int("accounts-registration-backlog-limit", cfg.AccountsRegistrationBacklogLimit, "Limit how big the 'accounts pending approval' queue can grow before registration is closed. 0 or less = no limit.")
|
||||
flags.Bool("accounts-allow-custom-css", cfg.AccountsAllowCustomCSS, "Allow accounts to enable custom CSS for their profile pages and statuses.")
|
||||
flags.Int("accounts-custom-css-length", cfg.AccountsCustomCSSLength, "Maximum permitted length (characters) of custom CSS for accounts.")
|
||||
flags.Int("accounts-max-profile-fields", cfg.AccountsMaxProfileFields, "Maximum amount of profile fields an account can have.")
|
||||
flags.Int("accounts-max-profile-fields", cfg.AccountsMaxProfileFields, "Maximum number of profile fields allowed for each account.")
|
||||
flags.Int("media-description-min-chars", cfg.MediaDescriptionMinChars, "Min required chars for an image description")
|
||||
flags.Int("media-description-max-chars", cfg.MediaDescriptionMaxChars, "Max permitted chars for an image description")
|
||||
flags.Int("media-remote-cache-days", cfg.MediaRemoteCacheDays, "Number of days to locally cache media from remote instances. If set to 0, remote media will be kept indefinitely.")
|
||||
|
|
@ -207,7 +209,7 @@ func (cfg *Configuration) RegisterFlags(flags *pflag.FlagSet) {
|
|||
}
|
||||
|
||||
func (cfg *Configuration) MarshalMap() map[string]any {
|
||||
cfgmap := make(map[string]any, 182)
|
||||
cfgmap := make(map[string]any, 184)
|
||||
cfgmap["log-level"] = cfg.LogLevel
|
||||
cfgmap["log-timestamp-format"] = cfg.LogTimestampFormat
|
||||
cfgmap["log-db-queries"] = cfg.LogDbQueries
|
||||
|
|
@ -242,8 +244,10 @@ func (cfg *Configuration) MarshalMap() map[string]any {
|
|||
cfgmap["instance-federation-mode"] = cfg.InstanceFederationMode
|
||||
cfgmap["instance-federation-spam-filter"] = cfg.InstanceFederationSpamFilter
|
||||
cfgmap["instance-expose-peers"] = cfg.InstanceExposePeers
|
||||
cfgmap["instance-expose-suspended"] = cfg.InstanceExposeSuspended
|
||||
cfgmap["instance-expose-suspended-web"] = cfg.InstanceExposeSuspendedWeb
|
||||
cfgmap["instance-expose-blocklist"] = cfg.InstanceExposeBlocklist
|
||||
cfgmap["instance-expose-blocklist-web"] = cfg.InstanceExposeBlocklistWeb
|
||||
cfgmap["instance-expose-allowlist"] = cfg.InstanceExposeAllowlist
|
||||
cfgmap["instance-expose-allowlist-web"] = cfg.InstanceExposeAllowlistWeb
|
||||
cfgmap["instance-expose-public-timeline"] = cfg.InstanceExposePublicTimeline
|
||||
cfgmap["instance-deliver-to-shared-inboxes"] = cfg.InstanceDeliverToSharedInboxes
|
||||
cfgmap["instance-inject-mastodon-version"] = cfg.InstanceInjectMastodonVersion
|
||||
|
|
@ -674,19 +678,35 @@ func (cfg *Configuration) UnmarshalMap(cfgmap map[string]any) error {
|
|||
}
|
||||
}
|
||||
|
||||
if ival, ok := cfgmap["instance-expose-suspended"]; ok {
|
||||
if ival, ok := cfgmap["instance-expose-blocklist"]; ok {
|
||||
var err error
|
||||
cfg.InstanceExposeSuspended, err = cast.ToBoolE(ival)
|
||||
cfg.InstanceExposeBlocklist, err = cast.ToBoolE(ival)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error casting %#v -> bool for 'instance-expose-suspended': %w", ival, err)
|
||||
return fmt.Errorf("error casting %#v -> bool for 'instance-expose-blocklist': %w", ival, err)
|
||||
}
|
||||
}
|
||||
|
||||
if ival, ok := cfgmap["instance-expose-suspended-web"]; ok {
|
||||
if ival, ok := cfgmap["instance-expose-blocklist-web"]; ok {
|
||||
var err error
|
||||
cfg.InstanceExposeSuspendedWeb, err = cast.ToBoolE(ival)
|
||||
cfg.InstanceExposeBlocklistWeb, err = cast.ToBoolE(ival)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error casting %#v -> bool for 'instance-expose-suspended-web': %w", ival, err)
|
||||
return fmt.Errorf("error casting %#v -> bool for 'instance-expose-blocklist-web': %w", ival, err)
|
||||
}
|
||||
}
|
||||
|
||||
if ival, ok := cfgmap["instance-expose-allowlist"]; ok {
|
||||
var err error
|
||||
cfg.InstanceExposeAllowlist, err = cast.ToBoolE(ival)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error casting %#v -> bool for 'instance-expose-allowlist': %w", ival, err)
|
||||
}
|
||||
}
|
||||
|
||||
if ival, ok := cfgmap["instance-expose-allowlist-web"]; ok {
|
||||
var err error
|
||||
cfg.InstanceExposeAllowlistWeb, err = cast.ToBoolE(ival)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error casting %#v -> bool for 'instance-expose-allowlist-web': %w", ival, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2742,55 +2762,105 @@ func GetInstanceExposePeers() bool { return global.GetInstanceExposePeers() }
|
|||
// SetInstanceExposePeers safely sets the value for global configuration 'InstanceExposePeers' field
|
||||
func SetInstanceExposePeers(v bool) { global.SetInstanceExposePeers(v) }
|
||||
|
||||
// InstanceExposeSuspendedFlag returns the flag name for the 'InstanceExposeSuspended' field
|
||||
func InstanceExposeSuspendedFlag() string { return "instance-expose-suspended" }
|
||||
// InstanceExposeBlocklistFlag returns the flag name for the 'InstanceExposeBlocklist' field
|
||||
func InstanceExposeBlocklistFlag() string { return "instance-expose-blocklist" }
|
||||
|
||||
// GetInstanceExposeSuspended safely fetches the Configuration value for state's 'InstanceExposeSuspended' field
|
||||
func (st *ConfigState) GetInstanceExposeSuspended() (v bool) {
|
||||
// GetInstanceExposeBlocklist safely fetches the Configuration value for state's 'InstanceExposeBlocklist' field
|
||||
func (st *ConfigState) GetInstanceExposeBlocklist() (v bool) {
|
||||
st.mutex.RLock()
|
||||
v = st.config.InstanceExposeSuspended
|
||||
v = st.config.InstanceExposeBlocklist
|
||||
st.mutex.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
// SetInstanceExposeSuspended safely sets the Configuration value for state's 'InstanceExposeSuspended' field
|
||||
func (st *ConfigState) SetInstanceExposeSuspended(v bool) {
|
||||
// SetInstanceExposeBlocklist safely sets the Configuration value for state's 'InstanceExposeBlocklist' field
|
||||
func (st *ConfigState) SetInstanceExposeBlocklist(v bool) {
|
||||
st.mutex.Lock()
|
||||
defer st.mutex.Unlock()
|
||||
st.config.InstanceExposeSuspended = v
|
||||
st.config.InstanceExposeBlocklist = v
|
||||
st.reloadToViper()
|
||||
}
|
||||
|
||||
// GetInstanceExposeSuspended safely fetches the value for global configuration 'InstanceExposeSuspended' field
|
||||
func GetInstanceExposeSuspended() bool { return global.GetInstanceExposeSuspended() }
|
||||
// GetInstanceExposeBlocklist safely fetches the value for global configuration 'InstanceExposeBlocklist' field
|
||||
func GetInstanceExposeBlocklist() bool { return global.GetInstanceExposeBlocklist() }
|
||||
|
||||
// SetInstanceExposeSuspended safely sets the value for global configuration 'InstanceExposeSuspended' field
|
||||
func SetInstanceExposeSuspended(v bool) { global.SetInstanceExposeSuspended(v) }
|
||||
// SetInstanceExposeBlocklist safely sets the value for global configuration 'InstanceExposeBlocklist' field
|
||||
func SetInstanceExposeBlocklist(v bool) { global.SetInstanceExposeBlocklist(v) }
|
||||
|
||||
// InstanceExposeSuspendedWebFlag returns the flag name for the 'InstanceExposeSuspendedWeb' field
|
||||
func InstanceExposeSuspendedWebFlag() string { return "instance-expose-suspended-web" }
|
||||
// InstanceExposeBlocklistWebFlag returns the flag name for the 'InstanceExposeBlocklistWeb' field
|
||||
func InstanceExposeBlocklistWebFlag() string { return "instance-expose-blocklist-web" }
|
||||
|
||||
// GetInstanceExposeSuspendedWeb safely fetches the Configuration value for state's 'InstanceExposeSuspendedWeb' field
|
||||
func (st *ConfigState) GetInstanceExposeSuspendedWeb() (v bool) {
|
||||
// GetInstanceExposeBlocklistWeb safely fetches the Configuration value for state's 'InstanceExposeBlocklistWeb' field
|
||||
func (st *ConfigState) GetInstanceExposeBlocklistWeb() (v bool) {
|
||||
st.mutex.RLock()
|
||||
v = st.config.InstanceExposeSuspendedWeb
|
||||
v = st.config.InstanceExposeBlocklistWeb
|
||||
st.mutex.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
// SetInstanceExposeSuspendedWeb safely sets the Configuration value for state's 'InstanceExposeSuspendedWeb' field
|
||||
func (st *ConfigState) SetInstanceExposeSuspendedWeb(v bool) {
|
||||
// SetInstanceExposeBlocklistWeb safely sets the Configuration value for state's 'InstanceExposeBlocklistWeb' field
|
||||
func (st *ConfigState) SetInstanceExposeBlocklistWeb(v bool) {
|
||||
st.mutex.Lock()
|
||||
defer st.mutex.Unlock()
|
||||
st.config.InstanceExposeSuspendedWeb = v
|
||||
st.config.InstanceExposeBlocklistWeb = v
|
||||
st.reloadToViper()
|
||||
}
|
||||
|
||||
// GetInstanceExposeSuspendedWeb safely fetches the value for global configuration 'InstanceExposeSuspendedWeb' field
|
||||
func GetInstanceExposeSuspendedWeb() bool { return global.GetInstanceExposeSuspendedWeb() }
|
||||
// GetInstanceExposeBlocklistWeb safely fetches the value for global configuration 'InstanceExposeBlocklistWeb' field
|
||||
func GetInstanceExposeBlocklistWeb() bool { return global.GetInstanceExposeBlocklistWeb() }
|
||||
|
||||
// SetInstanceExposeSuspendedWeb safely sets the value for global configuration 'InstanceExposeSuspendedWeb' field
|
||||
func SetInstanceExposeSuspendedWeb(v bool) { global.SetInstanceExposeSuspendedWeb(v) }
|
||||
// SetInstanceExposeBlocklistWeb safely sets the value for global configuration 'InstanceExposeBlocklistWeb' field
|
||||
func SetInstanceExposeBlocklistWeb(v bool) { global.SetInstanceExposeBlocklistWeb(v) }
|
||||
|
||||
// InstanceExposeAllowlistFlag returns the flag name for the 'InstanceExposeAllowlist' field
|
||||
func InstanceExposeAllowlistFlag() string { return "instance-expose-allowlist" }
|
||||
|
||||
// GetInstanceExposeAllowlist safely fetches the Configuration value for state's 'InstanceExposeAllowlist' field
|
||||
func (st *ConfigState) GetInstanceExposeAllowlist() (v bool) {
|
||||
st.mutex.RLock()
|
||||
v = st.config.InstanceExposeAllowlist
|
||||
st.mutex.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
// SetInstanceExposeAllowlist safely sets the Configuration value for state's 'InstanceExposeAllowlist' field
|
||||
func (st *ConfigState) SetInstanceExposeAllowlist(v bool) {
|
||||
st.mutex.Lock()
|
||||
defer st.mutex.Unlock()
|
||||
st.config.InstanceExposeAllowlist = v
|
||||
st.reloadToViper()
|
||||
}
|
||||
|
||||
// GetInstanceExposeAllowlist safely fetches the value for global configuration 'InstanceExposeAllowlist' field
|
||||
func GetInstanceExposeAllowlist() bool { return global.GetInstanceExposeAllowlist() }
|
||||
|
||||
// SetInstanceExposeAllowlist safely sets the value for global configuration 'InstanceExposeAllowlist' field
|
||||
func SetInstanceExposeAllowlist(v bool) { global.SetInstanceExposeAllowlist(v) }
|
||||
|
||||
// InstanceExposeAllowlistWebFlag returns the flag name for the 'InstanceExposeAllowlistWeb' field
|
||||
func InstanceExposeAllowlistWebFlag() string { return "instance-expose-allowlist-web" }
|
||||
|
||||
// GetInstanceExposeAllowlistWeb safely fetches the Configuration value for state's 'InstanceExposeAllowlistWeb' field
|
||||
func (st *ConfigState) GetInstanceExposeAllowlistWeb() (v bool) {
|
||||
st.mutex.RLock()
|
||||
v = st.config.InstanceExposeAllowlistWeb
|
||||
st.mutex.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
// SetInstanceExposeAllowlistWeb safely sets the Configuration value for state's 'InstanceExposeAllowlistWeb' field
|
||||
func (st *ConfigState) SetInstanceExposeAllowlistWeb(v bool) {
|
||||
st.mutex.Lock()
|
||||
defer st.mutex.Unlock()
|
||||
st.config.InstanceExposeAllowlistWeb = v
|
||||
st.reloadToViper()
|
||||
}
|
||||
|
||||
// GetInstanceExposeAllowlistWeb safely fetches the value for global configuration 'InstanceExposeAllowlistWeb' field
|
||||
func GetInstanceExposeAllowlistWeb() bool { return global.GetInstanceExposeAllowlistWeb() }
|
||||
|
||||
// SetInstanceExposeAllowlistWeb safely sets the value for global configuration 'InstanceExposeAllowlistWeb' field
|
||||
func SetInstanceExposeAllowlistWeb(v bool) { global.SetInstanceExposeAllowlistWeb(v) }
|
||||
|
||||
// InstanceExposePublicTimelineFlag returns the flag name for the 'InstanceExposePublicTimeline' field
|
||||
func InstanceExposePublicTimelineFlag() string { return "instance-expose-public-timeline" }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue