Skip to content

Commit 0e5c9b3

Browse files
committed
feat: add bot_optional and user_optional scopes to app manifest
Support optional OAuth scopes for both bot and user tokens in the manifest schema via `oauth_config.scopes.bot_optional` and `oauth_config.scopes.user_optional` properties.
1 parent 783ac1a commit 0e5c9b3

2 files changed

Lines changed: 60 additions & 2 deletions

File tree

internal/shared/types/app_manifest.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,10 @@ type ManifestInteractivity struct {
239239

240240
// ManifestScopes
241241
type ManifestScopes struct {
242-
Bot []string `json:"bot,omitempty" yaml:"bot,flow,omitempty"`
243-
User []string `json:"user,omitempty" yaml:"user,flow,omitempty"`
242+
Bot []string `json:"bot,omitempty" yaml:"bot,flow,omitempty"`
243+
BotOptional []string `json:"bot_optional,omitempty" yaml:"bot_optional,flow,omitempty"`
244+
User []string `json:"user,omitempty" yaml:"user,flow,omitempty"`
245+
UserOptional []string `json:"user_optional,omitempty" yaml:"user_optional,flow,omitempty"`
244246
}
245247

246248
// ManifestShortcutsItem

internal/shared/types/app_manifest_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,62 @@ func Test_AppManifest_AppSettings_IncomingWebhooks(t *testing.T) {
336336
}
337337
}
338338

339+
func Test_AppManifest_OAuthConfig_Scopes(t *testing.T) {
340+
tests := map[string]struct {
341+
oauthConfig *OAuthConfig
342+
expectedJSON string
343+
}{
344+
"undefined scopes are omitted": {
345+
oauthConfig: &OAuthConfig{},
346+
expectedJSON: `{}`,
347+
},
348+
"empty scopes are included": {
349+
oauthConfig: &OAuthConfig{Scopes: &ManifestScopes{}},
350+
expectedJSON: `{"scopes":{}}`,
351+
},
352+
"bot scopes are included": {
353+
oauthConfig: &OAuthConfig{Scopes: &ManifestScopes{
354+
Bot: []string{"chat:write", "channels:read"},
355+
}},
356+
expectedJSON: `{"scopes":{"bot":["chat:write","channels:read"]}}`,
357+
},
358+
"user scopes are included": {
359+
oauthConfig: &OAuthConfig{Scopes: &ManifestScopes{
360+
User: []string{"users:read"},
361+
}},
362+
expectedJSON: `{"scopes":{"user":["users:read"]}}`,
363+
},
364+
"bot optional scopes are included": {
365+
oauthConfig: &OAuthConfig{Scopes: &ManifestScopes{
366+
BotOptional: []string{"channels:history"},
367+
}},
368+
expectedJSON: `{"scopes":{"bot_optional":["channels:history"]}}`,
369+
},
370+
"user optional scopes are included": {
371+
oauthConfig: &OAuthConfig{Scopes: &ManifestScopes{
372+
UserOptional: []string{"users:read.email"},
373+
}},
374+
expectedJSON: `{"scopes":{"user_optional":["users:read.email"]}}`,
375+
},
376+
"all scope types are included": {
377+
oauthConfig: &OAuthConfig{Scopes: &ManifestScopes{
378+
Bot: []string{"chat:write"},
379+
BotOptional: []string{"channels:history"},
380+
User: []string{"users:read"},
381+
UserOptional: []string{"users:read.email"},
382+
}},
383+
expectedJSON: `{"scopes":{"bot":["chat:write"],"bot_optional":["channels:history"],"user":["users:read"],"user_optional":["users:read.email"]}}`,
384+
},
385+
}
386+
for name, tc := range tests {
387+
t.Run(name, func(t *testing.T) {
388+
actualJSON, err := json.Marshal(tc.oauthConfig)
389+
require.NoError(t, err)
390+
assert.Equal(t, tc.expectedJSON, string(actualJSON))
391+
})
392+
}
393+
}
394+
339395
func Test_AppManifest_AppSettings_FunctionRuntime(t *testing.T) {
340396
tests := map[string]struct {
341397
settings *AppSettings

0 commit comments

Comments
 (0)