forked from
slices.network/quickslice
Auto-indexing service and GraphQL API for AT Protocol Records
1/// OAuth scope validation
2import gleam/list
3import gleam/result
4import gleam/string
5import lib/oauth/scopes/parse_error
6import lib/oauth/scopes/parser
7import lib/oauth/scopes/types.{type Scope}
8import lib/oauth/types/error.{type OAuthError, InvalidScope}
9
10/// Validate scope string format and parse into structured scopes
11pub fn validate_scope_format(
12 scope_string: String,
13) -> Result(List(Scope), OAuthError) {
14 parser.parse_scopes(scope_string)
15 |> result.map_error(fn(e) { InvalidScope(parse_error.to_string(e)) })
16}
17
18/// Validate that all requested scopes are in the supported scopes list
19pub fn validate_scopes_supported(
20 requested: String,
21 supported: List(String),
22) -> Result(List(Scope), OAuthError) {
23 // First validate format
24 use parsed <- result.try(validate_scope_format(requested))
25
26 // Extract requested scope tokens
27 let requested_tokens =
28 requested
29 |> string.split(" ")
30 |> list.map(string.trim)
31 |> list.filter(fn(s) { !string.is_empty(s) })
32
33 // Find any unsupported scope
34 let unsupported =
35 list.find(requested_tokens, fn(token) { !list.contains(supported, token) })
36
37 case unsupported {
38 Ok(scope) -> Error(InvalidScope("Unsupported scope: " <> scope))
39 Error(Nil) -> Ok(parsed)
40 }
41}