mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-28 13:52:25 -05:00 
			
		
		
		
	[feature] Add config option to expose custom emojis without auth (#4233)
# Description > If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements. > > If this is a documentation change, please briefly describe what you've changed and why. Does as it says on the tin! Should make things a bit easier for clients that don't provide an access token to the custom emojis endpoint. Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/2430 ## Checklist Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]` If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want). - [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md). - [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat. - [x] I/we have not leveraged AI to create the proposed changes. - [x] I/we have performed a self-review of added code. - [x] I/we have written code that is legible and maintainable by others. - [x] I/we have commented the added code, particularly in hard-to-understand areas. - [x] I/we have made any necessary changes to documentation. - [ ] I/we have added tests that cover new code. - [x] I/we have run tests and they pass locally with the changes. - [x] I/we have run `go fmt ./...` and `golangci-lint run`. Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4233 Reviewed-by: Daenney <daenney@noreply.codeberg.org> Co-authored-by: tobi <tobi.smethurst@protonmail.com> Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This commit is contained in:
		
					parent
					
						
							
								be6d80c020
							
						
					
				
			
			
				commit
				
					
						43f1c6d872
					
				
			
		
					 11 changed files with 95 additions and 9 deletions
				
			
		|  | @ -3752,6 +3752,7 @@ info: | |||
|         read:applications: grants read access to user-managed applications | ||||
|         read:blocks: grants read access to blocks | ||||
|         read:bookmarks: grants read access to bookmarks | ||||
|         read:custom_emojis: grants read access to custom emojis | ||||
|         read:favourites: grants read access to accounts | ||||
|         read:filters: grants read access to filters | ||||
|         read:follows: grants read access to follows | ||||
|  | @ -8126,6 +8127,7 @@ paths: | |||
|                 - conversations | ||||
|     /api/v1/custom_emojis: | ||||
|         get: | ||||
|             description: If the instance config setting `instance-expose-custom-emojis` is `true` then authentication is not required. | ||||
|             operationId: customEmojisGet | ||||
|             produces: | ||||
|                 - application/json | ||||
|  | @ -8143,7 +8145,8 @@ paths: | |||
|                 "500": | ||||
|                     description: internal server error | ||||
|             security: | ||||
|                 - OAuth2 Bearer: [] | ||||
|                 - OAuth2 Bearer: | ||||
|                     - read:custom_emojis | ||||
|             summary: Get an array of custom emojis available on the instance. | ||||
|             tags: | ||||
|                 - custom_emojis | ||||
|  | @ -13588,6 +13591,7 @@ securityDefinitions: | |||
|             read:applications: grants read access to user-managed applications | ||||
|             read:blocks: grants read access to blocks | ||||
|             read:bookmarks: grants read access to bookmarks | ||||
|             read:custom_emojis: grants read access to custom emojis | ||||
|             read:favourites: grants read access to accounts | ||||
|             read:filters: grants read access to filters | ||||
|             read:follows: grants read access to follows | ||||
|  |  | |||
|  | @ -139,6 +139,21 @@ instance-expose-blocklist-web: false | |||
| # Default: false | ||||
| instance-expose-public-timeline: false | ||||
| 
 | ||||
| # Bool. Allow unauthenticated access to /api/v1/custom_emojis, which | ||||
| # exposes the list of custom emojis available to users on this server. | ||||
| # | ||||
| # Setting this to 'true' may alleviate issues with clients that do not | ||||
| # provide an access token in their requests to the emojis endpoint, but | ||||
| # it also means that anyone can look at what emojis are installed on your | ||||
| # instance, which may present privacy / safety issues. | ||||
| # | ||||
| # Even if set to 'false', authenticated users (ie., instance members) | ||||
| # will still be able to query the endpoint using an access token. | ||||
| # | ||||
| # Options: [true, false] | ||||
| # Default: false | ||||
| instance-expose-custom-emojis: 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. | ||||
|  |  | |||
|  | @ -41,6 +41,7 @@ | |||
| //   - read:applications: grants read access to user-managed applications | ||||
| //   - read:blocks: grants read access to blocks | ||||
| //   - read:bookmarks: grants read access to bookmarks | ||||
| //   - read:custom_emojis: grants read access to custom emojis | ||||
| //   - read:favourites: grants read access to accounts | ||||
| //   - read:filters: grants read access to filters | ||||
| //   - read:follows: grants read access to follows | ||||
|  | @ -99,6 +100,7 @@ | |||
| //	      read:applications: grants read access to user-managed applications | ||||
| //	      read:blocks: grants read access to blocks | ||||
| //	      read:bookmarks: grants read access to bookmarks | ||||
| //	      read:custom_emojis: grants read access to custom emojis | ||||
| //	      read:favourites: grants read access to accounts | ||||
| //	      read:filters: grants read access to filters | ||||
| //	      read:follows: grants read access to follows | ||||
|  |  | |||
|  | @ -425,6 +425,21 @@ instance-expose-blocklist-web: false | |||
| # Default: false | ||||
| instance-expose-public-timeline: false | ||||
| 
 | ||||
| # Bool. Allow unauthenticated access to /api/v1/custom_emojis, which | ||||
| # exposes the list of custom emojis available to users on this server. | ||||
| # | ||||
| # Setting this to 'true' may alleviate issues with clients that do not | ||||
| # provide an access token in their requests to the emojis endpoint, but | ||||
| # it also means that anyone can look at what emojis are installed on your | ||||
| # instance, which may present privacy / safety issues. | ||||
| # | ||||
| # Even if set to 'false', authenticated users (ie., instance members) | ||||
| # will still be able to query the endpoint using an access token. | ||||
| # | ||||
| # Options: [true, false] | ||||
| # Default: false | ||||
| instance-expose-custom-emojis: 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. | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ import ( | |||
| 	"net/http" | ||||
| 
 | ||||
| 	apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util" | ||||
| 	"code.superseriousbusiness.org/gotosocial/internal/config" | ||||
| 	"code.superseriousbusiness.org/gotosocial/internal/gtserror" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | @ -29,6 +30,8 @@ import ( | |||
| // | ||||
| // Get an array of custom emojis available on the instance. | ||||
| // | ||||
| // If the instance config setting `instance-expose-custom-emojis` is `true` then authentication is not required. | ||||
| // | ||||
| //	--- | ||||
| //	tags: | ||||
| //	- custom_emojis | ||||
|  | @ -37,7 +40,8 @@ import ( | |||
| //	- application/json | ||||
| // | ||||
| //	security: | ||||
| //	- OAuth2 Bearer: [] | ||||
| //	- OAuth2 Bearer: | ||||
| //		- read:custom_emojis | ||||
| // | ||||
| //	responses: | ||||
| //		'200': | ||||
|  | @ -53,12 +57,16 @@ import ( | |||
| //		'500': | ||||
| //			description: internal server error | ||||
| func (m *Module) CustomEmojisGETHandler(c *gin.Context) { | ||||
| 	_, errWithCode := apiutil.TokenAuth(c, | ||||
| 		true, true, true, true, | ||||
| 	) | ||||
| 	if errWithCode != nil { | ||||
| 		apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) | ||||
| 		return | ||||
| 	// If custom emojis are not exposed to unauthed | ||||
| 	// callers, fail if a token was not provided. | ||||
| 	if !config.GetInstanceExposeCustomEmojis() { | ||||
| 		if _, errWithCode := apiutil.TokenAuth(c, | ||||
| 			true, true, true, true, | ||||
| 			apiutil.ScopeReadCustomEmojis, | ||||
| 		); errWithCode != nil { | ||||
| 			apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil { | ||||
|  |  | |||
|  | @ -31,6 +31,7 @@ const ( | |||
| 	scopeBlocks        = "blocks" | ||||
| 	scopeBookmarks     = "bookmarks" | ||||
| 	scopeConversations = "conversations" | ||||
| 	scopeCustomEmojis  = "custom_emojis" | ||||
| 	scopeDomainAllows  = "domain_allows" | ||||
| 	scopeDomainBlocks  = "domain_blocks" | ||||
| 	scopeFavourites    = "favourites" | ||||
|  | @ -65,6 +66,7 @@ const ( | |||
| 	ScopeReadBookmarks          Scope = ScopeRead + ":" + scopeBookmarks | ||||
| 	ScopeWriteBookmarks         Scope = ScopeWrite + ":" + scopeBookmarks | ||||
| 	ScopeWriteConversations     Scope = ScopeWrite + ":" + scopeConversations | ||||
| 	ScopeReadCustomEmojis       Scope = ScopeRead + ":" + scopeCustomEmojis | ||||
| 	ScopeReadFavourites         Scope = ScopeRead + ":" + scopeFavourites | ||||
| 	ScopeWriteFavourites        Scope = ScopeWrite + ":" + scopeFavourites | ||||
| 	ScopeReadFilters            Scope = ScopeRead + ":" + scopeFilters | ||||
|  |  | |||
|  | @ -96,6 +96,7 @@ type Configuration struct { | |||
| 	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"` | ||||
| 	InstanceExposeCustomEmojis        bool               `name:"instance-expose-custom-emojis" usage:"Allow unauthenticated access to /api/v1/custom_emojis"` | ||||
| 	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"` | ||||
| 	InstanceLanguages                 language.Languages `name:"instance-languages" usage:"BCP47 language tags for the instance. Used to indicate the preferred languages of instance residents (in order from most-preferred to least-preferred)."` | ||||
|  |  | |||
|  | @ -63,6 +63,7 @@ var Defaults = Configuration{ | |||
| 	InstanceExposePeers:               false, | ||||
| 	InstanceExposeBlocklist:           false, | ||||
| 	InstanceExposeBlocklistWeb:        false, | ||||
| 	InstanceExposeCustomEmojis:        false, | ||||
| 	InstanceDeliverToSharedInboxes:    true, | ||||
| 	InstanceLanguages:                 make(language.Languages, 0), | ||||
| 	InstanceSubscriptionsProcessFrom:  "23:00",        // 11pm, | ||||
|  |  | |||
|  | @ -68,6 +68,7 @@ func (cfg *Configuration) RegisterFlags(flags *pflag.FlagSet) { | |||
| 	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-expose-custom-emojis", cfg.InstanceExposeCustomEmojis, "Allow unauthenticated access to /api/v1/custom_emojis") | ||||
| 	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") | ||||
| 	flags.StringSlice("instance-languages", cfg.InstanceLanguages.Strings(), "BCP47 language tags for the instance. Used to indicate the preferred languages of instance residents (in order from most-preferred to least-preferred).") | ||||
|  | @ -212,7 +213,7 @@ func (cfg *Configuration) RegisterFlags(flags *pflag.FlagSet) { | |||
| } | ||||
| 
 | ||||
| func (cfg *Configuration) MarshalMap() map[string]any { | ||||
| 	cfgmap := make(map[string]any, 186) | ||||
| 	cfgmap := make(map[string]any, 188) | ||||
| 	cfgmap["log-level"] = cfg.LogLevel | ||||
| 	cfgmap["log-timestamp-format"] = cfg.LogTimestampFormat | ||||
| 	cfgmap["log-db-queries"] = cfg.LogDbQueries | ||||
|  | @ -252,6 +253,7 @@ func (cfg *Configuration) MarshalMap() map[string]any { | |||
| 	cfgmap["instance-expose-allowlist"] = cfg.InstanceExposeAllowlist | ||||
| 	cfgmap["instance-expose-allowlist-web"] = cfg.InstanceExposeAllowlistWeb | ||||
| 	cfgmap["instance-expose-public-timeline"] = cfg.InstanceExposePublicTimeline | ||||
| 	cfgmap["instance-expose-custom-emojis"] = cfg.InstanceExposeCustomEmojis | ||||
| 	cfgmap["instance-deliver-to-shared-inboxes"] = cfg.InstanceDeliverToSharedInboxes | ||||
| 	cfgmap["instance-inject-mastodon-version"] = cfg.InstanceInjectMastodonVersion | ||||
| 	cfgmap["instance-languages"] = cfg.InstanceLanguages.Strings() | ||||
|  | @ -724,6 +726,14 @@ func (cfg *Configuration) UnmarshalMap(cfgmap map[string]any) error { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if ival, ok := cfgmap["instance-expose-custom-emojis"]; ok { | ||||
| 		var err error | ||||
| 		cfg.InstanceExposeCustomEmojis, err = cast.ToBoolE(ival) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("error casting %#v -> bool for 'instance-expose-custom-emojis': %w", ival, err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if ival, ok := cfgmap["instance-deliver-to-shared-inboxes"]; ok { | ||||
| 		var err error | ||||
| 		cfg.InstanceDeliverToSharedInboxes, err = cast.ToBoolE(ival) | ||||
|  | @ -2917,6 +2927,31 @@ func GetInstanceExposePublicTimeline() bool { return global.GetInstanceExposePub | |||
| // SetInstanceExposePublicTimeline safely sets the value for global configuration 'InstanceExposePublicTimeline' field | ||||
| func SetInstanceExposePublicTimeline(v bool) { global.SetInstanceExposePublicTimeline(v) } | ||||
| 
 | ||||
| // InstanceExposeCustomEmojisFlag returns the flag name for the 'InstanceExposeCustomEmojis' field | ||||
| func InstanceExposeCustomEmojisFlag() string { return "instance-expose-custom-emojis" } | ||||
| 
 | ||||
| // GetInstanceExposeCustomEmojis safely fetches the Configuration value for state's 'InstanceExposeCustomEmojis' field | ||||
| func (st *ConfigState) GetInstanceExposeCustomEmojis() (v bool) { | ||||
| 	st.mutex.RLock() | ||||
| 	v = st.config.InstanceExposeCustomEmojis | ||||
| 	st.mutex.RUnlock() | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // SetInstanceExposeCustomEmojis safely sets the Configuration value for state's 'InstanceExposeCustomEmojis' field | ||||
| func (st *ConfigState) SetInstanceExposeCustomEmojis(v bool) { | ||||
| 	st.mutex.Lock() | ||||
| 	defer st.mutex.Unlock() | ||||
| 	st.config.InstanceExposeCustomEmojis = v | ||||
| 	st.reloadToViper() | ||||
| } | ||||
| 
 | ||||
| // GetInstanceExposeCustomEmojis safely fetches the value for global configuration 'InstanceExposeCustomEmojis' field | ||||
| func GetInstanceExposeCustomEmojis() bool { return global.GetInstanceExposeCustomEmojis() } | ||||
| 
 | ||||
| // SetInstanceExposeCustomEmojis safely sets the value for global configuration 'InstanceExposeCustomEmojis' field | ||||
| func SetInstanceExposeCustomEmojis(v bool) { global.SetInstanceExposeCustomEmojis(v) } | ||||
| 
 | ||||
| // InstanceDeliverToSharedInboxesFlag returns the flag name for the 'InstanceDeliverToSharedInboxes' field | ||||
| func InstanceDeliverToSharedInboxesFlag() string { return "instance-deliver-to-shared-inboxes" } | ||||
| 
 | ||||
|  |  | |||
|  | @ -114,6 +114,7 @@ EXPECT=$(cat << "EOF" | |||
|     "instance-expose-allowlist-web": true, | ||||
|     "instance-expose-blocklist": true, | ||||
|     "instance-expose-blocklist-web": true, | ||||
|     "instance-expose-custom-emojis": true, | ||||
|     "instance-expose-peers": true, | ||||
|     "instance-expose-public-timeline": true, | ||||
|     "instance-federation-mode": "allowlist", | ||||
|  | @ -246,6 +247,7 @@ GTS_INSTANCE_EXPOSE_BLOCKLIST=true \ | |||
| GTS_INSTANCE_EXPOSE_BLOCKLIST_WEB=true \ | ||||
| GTS_INSTANCE_EXPOSE_ALLOWLIST=true \ | ||||
| GTS_INSTANCE_EXPOSE_ALLOWLIST_WEB=true \ | ||||
| GTS_INSTANCE_EXPOSE_CUSTOM_EMOJIS=true \ | ||||
| GTS_INSTANCE_EXPOSE_PUBLIC_TIMELINE=true \ | ||||
| GTS_INSTANCE_FEDERATION_MODE='allowlist' \ | ||||
| GTS_INSTANCE_FEDERATION_SPAM_FILTER=true \ | ||||
|  |  | |||
|  | @ -92,6 +92,7 @@ func testDefaults() config.Configuration { | |||
| 		InstanceExposeBlocklistWeb:     true, | ||||
| 		InstanceExposeAllowlist:        true, | ||||
| 		InstanceExposeAllowlistWeb:     true, | ||||
| 		InstanceExposeCustomEmojis:     true, | ||||
| 		InstanceDeliverToSharedInboxes: true, | ||||
| 		InstanceLanguages: language.Languages{ | ||||
| 			{ | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue