-
Notifications
You must be signed in to change notification settings - Fork 304
Open
Description
Feature Request
Problem Statement
Currently, security scopes in #[utoipa::path] and #[openapi] macros only accept string literals:
#[utoipa::path(
security(
("bearerAuth" = ["accessor:read", "accessor:write"])
)
)]This approach has limitations:
- No compile-time validation of scope values
- Prone to typos that are only caught at runtime
- Cannot leverage Rust's type system for better organization and safety
Proposed Solution
Allow security scopes to accept any type that implements Display:
enum Scope {
Accessor,
Read,
}
impl Display for Scope {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Format as needed, e.g., "accessor:read"
write!(f, "{}:{}", self.resource().to_lowercase(), self.action().to_lowercase())
}
}
#[utoipa::path(
security(
("bearerAuth" = [Scope::Accessor(Action::Read)])
)
)]Benefits
- Type Safety: Compile-time validation of security scopes
- Better Organization: Scopes can be defined as enums/structs with clear semantics
- IDE Support: Autocomplete and refactoring tools work better with types
- Maintainability: Centralized scope definitions that are easier to update
- Backwards Compatible: String literals would still work
Implementation Approach
The existing LitStrOrExpr enum in utoipa-gen/src/lib.rs can be reused for this purpose. The main changes would be:
- Update
SecurityRequirementsAttrIteminsecurity_requirement.rsto useLitStrOrExprfor scopes - Modify parsing logic to accept both literals and expressions
- Update
ToTokensimplementation to call.to_string()on expressions
Example Use Cases
// Enum-based scopes with Display
enum Resource { User, Post, Comment }
enum Action { Read, Write, Delete }
struct Scope(Resource, Action);
impl Display for Scope { /* ... */ }
#[utoipa::path(
security(
("oauth2" = [Scope(Resource::User, Action::Read)])
)
)]
// Or simpler enum
enum SimpleScope {
UserRead,
UserWrite,
AdminAll,
}
impl Display for SimpleScope { /* ... */ }
#[utoipa::path(
security(
("bearerAuth" = [SimpleScope::UserRead, SimpleScope::UserWrite])
)
)]I'm willing to implement this feature and submit a PR if there's interest in accepting it.
Metadata
Metadata
Assignees
Labels
No labels