371 lines
23 KiB
Go
371 lines
23 KiB
Go
package middleware
|
|
|
|
import (
|
|
"fmt"
|
|
"maps"
|
|
"slices"
|
|
"sync"
|
|
|
|
"github.com/QuantumNous/new-api/service"
|
|
"github.com/QuantumNous/new-api/service/authz"
|
|
)
|
|
|
|
type accessTokenRuleKind int
|
|
|
|
const (
|
|
// accessTokenRuleScope requires the token to carry scope.
|
|
accessTokenRuleScope accessTokenRuleKind = iota + 1
|
|
// accessTokenRuleAny accepts every valid scoped token; the handler applies
|
|
// its own checks.
|
|
accessTokenRuleAny
|
|
// accessTokenRuleSession rejects every access token, legacy ones included.
|
|
accessTokenRuleSession
|
|
)
|
|
|
|
type accessTokenRouteRule struct {
|
|
kind accessTokenRuleKind
|
|
scope string
|
|
}
|
|
|
|
var (
|
|
accessTokenAnyRule = accessTokenRouteRule{kind: accessTokenRuleAny}
|
|
accessTokenSessionRule = accessTokenRouteRule{kind: accessTokenRuleSession}
|
|
)
|
|
|
|
func accessTokenScopeRule(scope string) accessTokenRouteRule {
|
|
return accessTokenRouteRule{kind: accessTokenRuleScope, scope: scope}
|
|
}
|
|
|
|
// accessTokenRouteRules declares the token rule of every dashboard route that
|
|
// is not guarded by RequirePermission, keyed by method and gin full path.
|
|
// Casbin-guarded routes declare themselves through
|
|
// DeclareAccessTokenPermissionRoute when they are registered.
|
|
var accessTokenRouteRules = map[string]accessTokenRouteRule{
|
|
// router/api-router.go: top level
|
|
"GET /api/models": accessTokenScopeRule("profile:read"),
|
|
"GET /api/status/test": accessTokenScopeRule("log:read"),
|
|
"GET /api/pricing": accessTokenAnyRule,
|
|
"GET /api/perf-metrics/summary": accessTokenAnyRule,
|
|
"GET /api/perf-metrics": accessTokenAnyRule,
|
|
"GET /api/rankings": accessTokenAnyRule,
|
|
"POST /api/oauth/state": accessTokenSessionRule,
|
|
"POST /api/oauth/email/bind/start": accessTokenScopeRule("account_security:write"),
|
|
"POST /api/oauth/email/bind/resend": accessTokenScopeRule("account_security:write"),
|
|
"POST /api/oauth/email/bind": accessTokenScopeRule("account_security:write"),
|
|
"POST /api/oauth/wechat/bind": accessTokenScopeRule("account_security:write"),
|
|
"POST /api/oauth/telegram/bind/start": accessTokenSessionRule,
|
|
"GET /api/oauth/:provider": accessTokenSessionRule,
|
|
"GET /api/verify/methods": accessTokenAnyRule,
|
|
"POST /api/verify": accessTokenAnyRule,
|
|
|
|
// router/api-router.go: /api/user (self)
|
|
"GET /api/user/sessions": accessTokenSessionRule,
|
|
"DELETE /api/user/sessions/:sid": accessTokenSessionRule,
|
|
"POST /api/user/sessions/revoke-others": accessTokenSessionRule,
|
|
"GET /api/user/self/groups": accessTokenScopeRule("profile:read"),
|
|
"GET /api/user/self": accessTokenScopeRule("profile:read"),
|
|
"GET /api/user/models": accessTokenScopeRule("profile:read"),
|
|
"PUT /api/user/self": accessTokenScopeRule("profile:write"),
|
|
"DELETE /api/user/self": accessTokenScopeRule("account_security:write"),
|
|
"GET /api/user/access_tokens": accessTokenSessionRule,
|
|
"GET /api/user/access_tokens/catalog": accessTokenSessionRule,
|
|
"GET /api/user/access_tokens/scopes": accessTokenSessionRule,
|
|
"POST /api/user/access_tokens": accessTokenSessionRule,
|
|
"PATCH /api/user/access_tokens/:id": accessTokenSessionRule,
|
|
"DELETE /api/user/access_tokens/:id": accessTokenSessionRule,
|
|
"DELETE /api/user/access_tokens/legacy": accessTokenSessionRule,
|
|
"GET /api/user/passkey": accessTokenScopeRule("account_security:read"),
|
|
"POST /api/user/passkey/register/begin": accessTokenScopeRule("account_security:write"),
|
|
"POST /api/user/passkey/register/finish": accessTokenScopeRule("account_security:write"),
|
|
"POST /api/user/passkey/verify/begin": accessTokenAnyRule,
|
|
"POST /api/user/passkey/verify/finish": accessTokenAnyRule,
|
|
"DELETE /api/user/passkey": accessTokenScopeRule("account_security:write"),
|
|
"GET /api/user/aff": accessTokenScopeRule("wallet:read"),
|
|
"GET /api/user/topup/info": accessTokenScopeRule("wallet:read"),
|
|
"GET /api/user/topup/self": accessTokenScopeRule("wallet:read"),
|
|
"POST /api/user/topup": accessTokenScopeRule("wallet:write"),
|
|
"POST /api/user/pay": accessTokenScopeRule("wallet:write"),
|
|
"POST /api/user/amount": accessTokenScopeRule("wallet:read"),
|
|
"POST /api/user/stripe/pay": accessTokenScopeRule("wallet:write"),
|
|
"POST /api/user/stripe/amount": accessTokenScopeRule("wallet:read"),
|
|
"POST /api/user/creem/pay": accessTokenScopeRule("wallet:write"),
|
|
"POST /api/user/waffo/amount": accessTokenScopeRule("wallet:read"),
|
|
"POST /api/user/waffo/pay": accessTokenScopeRule("wallet:write"),
|
|
"POST /api/user/waffo-pancake/amount": accessTokenScopeRule("wallet:read"),
|
|
"POST /api/user/waffo-pancake/pay": accessTokenScopeRule("wallet:write"),
|
|
"POST /api/user/aff_transfer": accessTokenScopeRule("wallet:write"),
|
|
"PUT /api/user/setting": accessTokenScopeRule("profile:write"),
|
|
"GET /api/user/2fa/status": accessTokenScopeRule("account_security:read"),
|
|
"POST /api/user/2fa/setup": accessTokenScopeRule("account_security:write"),
|
|
"POST /api/user/2fa/enable": accessTokenScopeRule("account_security:write"),
|
|
"POST /api/user/2fa/disable": accessTokenScopeRule("account_security:write"),
|
|
"POST /api/user/2fa/backup_codes": accessTokenScopeRule("account_security:write"),
|
|
"GET /api/user/checkin": accessTokenScopeRule("wallet:read"),
|
|
"POST /api/user/checkin": accessTokenScopeRule("wallet:write"),
|
|
"GET /api/user/oauth/bindings": accessTokenScopeRule("account_security:read"),
|
|
"DELETE /api/user/oauth/bindings/:provider_id": accessTokenScopeRule("account_security:write"),
|
|
|
|
// router/api-router.go: /api/user (admin)
|
|
"GET /api/user/": accessTokenScopeRule("user:read"),
|
|
"GET /api/user/topup": accessTokenScopeRule("billing:read"),
|
|
"POST /api/user/topup/complete": accessTokenScopeRule("billing:write"),
|
|
"GET /api/user/search": accessTokenScopeRule("user:read"),
|
|
"GET /api/user/:id/oauth/bindings": accessTokenScopeRule("user:read"),
|
|
"DELETE /api/user/:id/oauth/bindings/:provider_id": accessTokenScopeRule("user:write"),
|
|
"DELETE /api/user/:id/bindings/:binding_type": accessTokenScopeRule("user:write"),
|
|
"GET /api/user/:id": accessTokenScopeRule("user:read"),
|
|
"POST /api/user/": accessTokenScopeRule("user:write"),
|
|
"POST /api/user/manage": accessTokenScopeRule("user:write"),
|
|
"PUT /api/user/": accessTokenScopeRule("user:write"),
|
|
"DELETE /api/user/:id": accessTokenScopeRule("user:write"),
|
|
"DELETE /api/user/:id/reset_passkey": accessTokenScopeRule("user:write"),
|
|
"GET /api/user/2fa/stats": accessTokenScopeRule("user:read"),
|
|
"DELETE /api/user/:id/2fa": accessTokenScopeRule("user:write"),
|
|
|
|
// router/api-router.go: /api/subscription
|
|
"GET /api/subscription/plans": accessTokenScopeRule("wallet:read"),
|
|
"GET /api/subscription/self": accessTokenScopeRule("wallet:read"),
|
|
"PUT /api/subscription/self/preference": accessTokenScopeRule("wallet:write"),
|
|
"POST /api/subscription/balance/pay": accessTokenScopeRule("wallet:write"),
|
|
"POST /api/subscription/epay/pay": accessTokenScopeRule("wallet:write"),
|
|
"POST /api/subscription/stripe/pay": accessTokenScopeRule("wallet:write"),
|
|
"POST /api/subscription/creem/pay": accessTokenScopeRule("wallet:write"),
|
|
"POST /api/subscription/waffo-pancake/pay": accessTokenScopeRule("wallet:write"),
|
|
"GET /api/subscription/admin/plans": accessTokenScopeRule("billing:read"),
|
|
"POST /api/subscription/admin/plans": accessTokenScopeRule("billing:write"),
|
|
"PUT /api/subscription/admin/plans/:id": accessTokenScopeRule("billing:write"),
|
|
"PATCH /api/subscription/admin/plans/:id": accessTokenScopeRule("billing:write"),
|
|
"POST /api/subscription/admin/bind": accessTokenScopeRule("billing:write"),
|
|
"POST /api/subscription/admin/plans/:id/subscriptions/reset": accessTokenScopeRule("billing:write"),
|
|
"GET /api/subscription/admin/users/:id/subscriptions": accessTokenScopeRule("billing:read"),
|
|
"POST /api/subscription/admin/users/:id/subscriptions": accessTokenScopeRule("billing:write"),
|
|
"POST /api/subscription/admin/users/:id/subscriptions/reset": accessTokenScopeRule("billing:write"),
|
|
"POST /api/subscription/admin/user_subscriptions/:id/invalidate": accessTokenScopeRule("billing:write"),
|
|
"DELETE /api/subscription/admin/user_subscriptions/:id": accessTokenScopeRule("billing:write"),
|
|
|
|
// router/api-router.go: /api/option
|
|
"GET /api/option/": accessTokenScopeRule("option:read"),
|
|
"GET /api/option/request_policy": accessTokenScopeRule("option:read"),
|
|
"PATCH /api/option/request_policy": accessTokenScopeRule("option:write"),
|
|
"PUT /api/option/": accessTokenScopeRule("option:write"),
|
|
"PUT /api/option/passkey/domains": accessTokenScopeRule("option:write"),
|
|
"GET /api/option/model_pricing": accessTokenScopeRule("option:read"),
|
|
"PATCH /api/option/model_pricing": accessTokenScopeRule("option:write"),
|
|
"POST /api/option/model_pricing/convert": accessTokenScopeRule("option:read"),
|
|
"POST /api/option/model_pricing/preview": accessTokenScopeRule("option:read"),
|
|
"POST /api/option/payment_compliance": accessTokenSessionRule,
|
|
"GET /api/option/channel_affinity_cache": accessTokenScopeRule("option:read"),
|
|
"DELETE /api/option/channel_affinity_cache": accessTokenScopeRule("option:write"),
|
|
"POST /api/option/rest_model_ratio": accessTokenScopeRule("option:write"),
|
|
"GET /api/option/waffo-pancake/catalog": accessTokenScopeRule("option:read"),
|
|
"POST /api/option/waffo-pancake/pair": accessTokenScopeRule("option:write"),
|
|
"POST /api/option/waffo-pancake/save": accessTokenScopeRule("option:write"),
|
|
"POST /api/option/waffo-pancake/subscription-product": accessTokenScopeRule("option:write"),
|
|
"GET /api/option/waffo-pancake/subscription-product-options": accessTokenScopeRule("option:read"),
|
|
|
|
// router/api-router.go: /api/custom-oauth-provider, /api/ratio_sync
|
|
"POST /api/custom-oauth-provider/discovery": accessTokenScopeRule("option:write"),
|
|
"GET /api/custom-oauth-provider/": accessTokenScopeRule("option:read"),
|
|
"GET /api/custom-oauth-provider/:id": accessTokenScopeRule("option:read"),
|
|
"POST /api/custom-oauth-provider/": accessTokenScopeRule("option:write"),
|
|
"PUT /api/custom-oauth-provider/:id": accessTokenScopeRule("option:write"),
|
|
"DELETE /api/custom-oauth-provider/:id": accessTokenScopeRule("option:write"),
|
|
"GET /api/ratio_sync/channels": accessTokenScopeRule("option:read"),
|
|
"POST /api/ratio_sync/fetch": accessTokenScopeRule("option:write"),
|
|
|
|
// router/api-router.go: /api/performance, /api/system-task, /api/system-info
|
|
"GET /api/performance/stats": accessTokenScopeRule("ops:read"),
|
|
"DELETE /api/performance/disk_cache": accessTokenScopeRule("ops:write"),
|
|
"POST /api/performance/reset_stats": accessTokenScopeRule("ops:write"),
|
|
"POST /api/performance/gc": accessTokenScopeRule("ops:write"),
|
|
"GET /api/performance/logs": accessTokenScopeRule("ops:read"),
|
|
"DELETE /api/performance/logs": accessTokenScopeRule("ops:write"),
|
|
"POST /api/system-task/log-cleanup": accessTokenScopeRule("ops:write"),
|
|
"GET /api/system-task/list": accessTokenScopeRule("ops:read"),
|
|
"DELETE /api/system-task/history": accessTokenScopeRule("ops:write"),
|
|
"GET /api/system-task/current": accessTokenScopeRule("ops:read"),
|
|
"GET /api/system-task/:task_id": accessTokenScopeRule("ops:read"),
|
|
"GET /api/system-info/instances": accessTokenScopeRule("ops:read"),
|
|
"DELETE /api/system-info/stale-instances": accessTokenScopeRule("ops:write"),
|
|
"DELETE /api/system-info/instances/:node_name": accessTokenScopeRule("ops:write"),
|
|
|
|
// router/api-router.go: /api/plugin/task
|
|
"GET /api/plugin/task": accessTokenScopeRule("plugin:read"),
|
|
"POST /api/plugin/task": accessTokenScopeRule("plugin:write"),
|
|
"PUT /api/plugin/task": accessTokenScopeRule("plugin:write"),
|
|
"GET /api/plugin/task/runtime/status": accessTokenScopeRule("plugin:read"),
|
|
"GET /api/plugin/task/marketplace/sources": accessTokenScopeRule("plugin:read"),
|
|
"PUT /api/plugin/task/marketplace/sources": accessTokenScopeRule("plugin:write"),
|
|
"GET /api/plugin/task/:key": accessTokenScopeRule("plugin:read"),
|
|
"GET /api/plugin/task/:key/icon": accessTokenScopeRule("plugin:read"),
|
|
"GET /api/plugin/task/:key/versions": accessTokenScopeRule("plugin:read"),
|
|
"POST /api/plugin/task/:key/activate": accessTokenScopeRule("plugin:write"),
|
|
"POST /api/plugin/task/:key/status": accessTokenScopeRule("plugin:write"),
|
|
"POST /api/plugin/task/:key/dryrun": accessTokenScopeRule("plugin:write"),
|
|
"DELETE /api/plugin/task/:key/versions/:version": accessTokenScopeRule("plugin:write"),
|
|
|
|
// router/channel-router.go: the key route is RootAuth, not Casbin-guarded.
|
|
"POST /api/channel/:id/key": accessTokenScopeRule(service.AccessTokenScopeOf(authz.ChannelSecretView)),
|
|
|
|
// router/authz-router.go
|
|
"GET /api/authz/catalog": accessTokenScopeRule("user:read"),
|
|
|
|
// router/api-router.go: /api/token
|
|
"GET /api/token/": accessTokenScopeRule("api_key:read"),
|
|
"GET /api/token/search": accessTokenScopeRule("api_key:read"),
|
|
"GET /api/token/auto-groups": accessTokenScopeRule("api_key:read"),
|
|
"GET /api/token/:id": accessTokenScopeRule("api_key:read"),
|
|
"POST /api/token/:id/key": accessTokenScopeRule("api_key:reveal"),
|
|
"POST /api/token/": accessTokenScopeRule("api_key:write"),
|
|
"PUT /api/token/": accessTokenScopeRule("api_key:write"),
|
|
"DELETE /api/token/:id": accessTokenScopeRule("api_key:write"),
|
|
"POST /api/token/batch": accessTokenScopeRule("api_key:write"),
|
|
"POST /api/token/batch/keys": accessTokenScopeRule("api_key:reveal"),
|
|
|
|
// router/api-router.go: /api/redemption
|
|
"GET /api/redemption/": accessTokenScopeRule("redemption:read"),
|
|
"GET /api/redemption/search": accessTokenScopeRule("redemption:read"),
|
|
"GET /api/redemption/:id": accessTokenScopeRule("redemption:read"),
|
|
"POST /api/redemption/": accessTokenScopeRule("redemption:write"),
|
|
"POST /api/redemption/batch": accessTokenScopeRule("redemption:write"),
|
|
"PUT /api/redemption/": accessTokenScopeRule("redemption:write"),
|
|
"DELETE /api/redemption/invalid": accessTokenScopeRule("redemption:write"),
|
|
"DELETE /api/redemption/:id": accessTokenScopeRule("redemption:write"),
|
|
|
|
// router/api-router.go: /api/audit, /api/log, /api/data
|
|
"GET /api/audit/self": accessTokenScopeRule("usage:read"),
|
|
"GET /api/log/": accessTokenScopeRule("log:read"),
|
|
"GET /api/log/stat": accessTokenScopeRule("log:read"),
|
|
"GET /api/log/self/stat": accessTokenScopeRule("usage:read"),
|
|
"GET /api/log/channel_affinity_usage_cache": accessTokenScopeRule("log:read"),
|
|
"GET /api/log/search": accessTokenScopeRule("log:read"),
|
|
"GET /api/log/self": accessTokenScopeRule("usage:read"),
|
|
"GET /api/log/self/search": accessTokenScopeRule("usage:read"),
|
|
"GET /api/log/export": accessTokenScopeRule("log:read"),
|
|
"GET /api/log/self/export": accessTokenScopeRule("usage:read"),
|
|
"GET /api/data/": accessTokenScopeRule("log:read"),
|
|
"GET /api/data/users": accessTokenScopeRule("log:read"),
|
|
"GET /api/data/self": accessTokenScopeRule("usage:read"),
|
|
"GET /api/data/flow": accessTokenScopeRule("log:read"),
|
|
"GET /api/data/flow/self": accessTokenScopeRule("usage:read"),
|
|
|
|
// router/api-router.go: /api/group, /api/prefill_group
|
|
"GET /api/group/": accessTokenScopeRule("group:read"),
|
|
"GET /api/prefill_group/": accessTokenScopeRule("group:read"),
|
|
"POST /api/prefill_group/": accessTokenScopeRule("group:write"),
|
|
"PUT /api/prefill_group/": accessTokenScopeRule("group:write"),
|
|
"DELETE /api/prefill_group/:id": accessTokenScopeRule("group:write"),
|
|
|
|
// router/api-router.go: /api/mj, /api/task
|
|
"GET /api/mj/self": accessTokenScopeRule("usage:read"),
|
|
"GET /api/mj/": accessTokenScopeRule("log:read"),
|
|
"GET /api/task/self": accessTokenScopeRule("usage:read"),
|
|
"GET /api/task": accessTokenScopeRule("log:read"),
|
|
"GET /api/task/:task_id/artifacts": accessTokenScopeRule("usage:read"),
|
|
|
|
// router/api-router.go: /api/vendors, /api/models (admin)
|
|
"POST /api/vendors/operations/preview": accessTokenScopeRule("model:read"),
|
|
"POST /api/vendors/operations": accessTokenScopeRule("model:write"),
|
|
"GET /api/vendors/": accessTokenScopeRule("model:read"),
|
|
"GET /api/vendors/search": accessTokenScopeRule("model:read"),
|
|
"GET /api/vendors/:id": accessTokenScopeRule("model:read"),
|
|
"POST /api/vendors/": accessTokenScopeRule("model:write"),
|
|
"PUT /api/vendors/": accessTokenScopeRule("model:write"),
|
|
"DELETE /api/vendors/:id": accessTokenScopeRule("model:write"),
|
|
"GET /api/models/sync_upstream/preview": accessTokenScopeRule("model:read"),
|
|
"POST /api/models/sync_upstream": accessTokenScopeRule("model:write"),
|
|
"POST /api/models/delete": accessTokenScopeRule("model:write"),
|
|
"GET /api/models/missing": accessTokenScopeRule("model:read"),
|
|
"GET /api/models/": accessTokenScopeRule("model:read"),
|
|
"GET /api/models/search": accessTokenScopeRule("model:read"),
|
|
"GET /api/models/:id": accessTokenScopeRule("model:read"),
|
|
"POST /api/models/": accessTokenScopeRule("model:write"),
|
|
"PUT /api/models/": accessTokenScopeRule("model:write"),
|
|
"DELETE /api/models/:id": accessTokenScopeRule("model:write"),
|
|
|
|
// router/api-router.go: /api/deployments
|
|
"GET /api/deployments/settings": accessTokenScopeRule("deployment:read"),
|
|
"POST /api/deployments/settings/test-connection": accessTokenScopeRule("deployment:write"),
|
|
"GET /api/deployments/": accessTokenScopeRule("deployment:read"),
|
|
"GET /api/deployments/search": accessTokenScopeRule("deployment:read"),
|
|
"POST /api/deployments/test-connection": accessTokenScopeRule("deployment:write"),
|
|
"GET /api/deployments/hardware-types": accessTokenScopeRule("deployment:read"),
|
|
"GET /api/deployments/locations": accessTokenScopeRule("deployment:read"),
|
|
"GET /api/deployments/available-replicas": accessTokenScopeRule("deployment:read"),
|
|
"POST /api/deployments/price-estimation": accessTokenScopeRule("deployment:read"),
|
|
"GET /api/deployments/check-name": accessTokenScopeRule("deployment:read"),
|
|
"POST /api/deployments/": accessTokenScopeRule("deployment:write"),
|
|
"GET /api/deployments/:id": accessTokenScopeRule("deployment:read"),
|
|
"GET /api/deployments/:id/logs": accessTokenScopeRule("deployment:read"),
|
|
"GET /api/deployments/:id/containers": accessTokenScopeRule("deployment:read"),
|
|
"GET /api/deployments/:id/containers/:container_id": accessTokenScopeRule("deployment:read"),
|
|
"PUT /api/deployments/:id": accessTokenScopeRule("deployment:write"),
|
|
"PUT /api/deployments/:id/name": accessTokenScopeRule("deployment:write"),
|
|
"POST /api/deployments/:id/extend": accessTokenScopeRule("deployment:write"),
|
|
"DELETE /api/deployments/:id": accessTokenScopeRule("deployment:write"),
|
|
|
|
// router/relay-router.go
|
|
"POST /pg/chat/completions": accessTokenSessionRule,
|
|
}
|
|
|
|
var (
|
|
permissionRouteRulesMu sync.RWMutex
|
|
permissionRouteRules = map[string]accessTokenRouteRule{}
|
|
)
|
|
|
|
// DeclareAccessTokenPermissionRoute records that the Casbin permission guarding
|
|
// a route is also the token scope it requires. It runs while routes are
|
|
// registered and panics on conflicting declarations.
|
|
func DeclareAccessTokenPermissionRoute(method, fullPath string, permission authz.Permission) {
|
|
key := method + " " + fullPath
|
|
rule := accessTokenScopeRule(service.AccessTokenScopeOf(permission))
|
|
if _, ok := accessTokenRouteRules[key]; ok {
|
|
panic(fmt.Sprintf("access token route %s is declared twice", key))
|
|
}
|
|
permissionRouteRulesMu.Lock()
|
|
defer permissionRouteRulesMu.Unlock()
|
|
if existing, ok := permissionRouteRules[key]; ok && existing != rule {
|
|
panic(fmt.Sprintf("access token route %s is declared with %s and %s", key, existing.scope, rule.scope))
|
|
}
|
|
permissionRouteRules[key] = rule
|
|
}
|
|
|
|
// AccessTokenRouteRule returns the rule for "METHOD /full/path".
|
|
func AccessTokenRouteRule(key string) (accessTokenRouteRule, bool) {
|
|
if rule, ok := accessTokenRouteRules[key]; ok {
|
|
return rule, true
|
|
}
|
|
permissionRouteRulesMu.RLock()
|
|
defer permissionRouteRulesMu.RUnlock()
|
|
rule, ok := permissionRouteRules[key]
|
|
return rule, ok
|
|
}
|
|
|
|
// AccessTokenRouteRuleKeys lists every declared route key, sorted.
|
|
func AccessTokenRouteRuleKeys() []string {
|
|
permissionRouteRulesMu.RLock()
|
|
keys := slices.Collect(maps.Keys(permissionRouteRules))
|
|
permissionRouteRulesMu.RUnlock()
|
|
keys = slices.AppendSeq(keys, maps.Keys(accessTokenRouteRules))
|
|
slices.Sort(keys)
|
|
return keys
|
|
}
|
|
|
|
// Scope returns the token scope the rule requires, or "" for any/session rules.
|
|
func (rule accessTokenRouteRule) Scope() string {
|
|
return rule.scope
|
|
}
|
|
|
|
// Kind names the rule category: "scope", "any" or "session".
|
|
func (rule accessTokenRouteRule) Kind() string {
|
|
switch rule.kind {
|
|
case accessTokenRuleScope:
|
|
return "scope"
|
|
case accessTokenRuleAny:
|
|
return "any"
|
|
case accessTokenRuleSession:
|
|
return "session"
|
|
}
|
|
return ""
|
|
}
|