1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/// The `ScopeMatcher` trait defines how to match a user's scope token
/// against a required scope token. This abstraction allows for flexible
/// matching logic, including support for different delimiters and wildcards.
/// A flexible implementation of the `ScopeMatcher` trait that supports
/// multipart scope token matching with common delimiters and wildcards.
///
/// This matcher is designed to handle both two-part and three-part
/// scope formats, such as:
/// - `read:users`
/// - `user_service:user:read`
///
/// It supports the following features:
/// - Matching with delimiters: `:`, `.`, `@`, and `/`
/// - Partial or full wildcard matching using `*`
/// - Graceful fallback to exact match or global wildcard
///
/// # Matching Examples
/// - `"user_service:user:read"` matches `"user_service:user:read"`
/// - `"user_service:*:read"` matches `"user_service:user:read"`
/// - `"*:*:read"` matches `"user_service:user:read"`
/// - `"read:users"` matches `"read:users"`
///
/// This makes it suitable for hybrid authorization systems that mix
/// service-level and resource-level scopes.
///
/// ## Note:
/// Both user and required tokens must use the same delimiter to match.
;
/// Parses a scope string into a list of individual scope tokens,
/// separated by whitespace (as per OAuth2/RFC conventions).
///
/// # Example
/// ```code
/// let scopes = parse_scope_string("read:users write:posts");
/// assert_eq!(scopes, vec!["read:users", "write:posts"]);
/// ```
/// Checks if a required scope is authorized by any of the user's scopes
/// using the given `ScopeMatcher` implementation.
///
/// # Arguments
/// - `user_scope_str`: space-delimited string of scopes from the user (e.g. from claims or roles)
/// - `required_token`: the scope token required for the action (e.g. `"read:users"`)
///
/// # Returns
/// - `true` if at least one user scope matches the required scope using the matcher.
///
/// # Example
/// ```bash
/// let authorized = authorize_with_matcher::<FlexibleMatcher>("read:users write:posts", "read:users");
/// assert!(authorized);
/// ```