libfw_core/claims.rs
1//! Bearer-token claims and permissions.
2//!
3//! `libfw` never *issues* tokens; it only parses and validates them. A token
4//! verifier (JWT library, external validation service, …) is expected to
5//! produce a [`TokenClaims`] which is then checked against the requested
6//! path and [`Permission`] by a [`Validator`](crate::auth::Validator).
7
8use serde::{Deserialize, Serialize};
9
10/// Permission dimension of a token.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12#[serde(rename_all = "lowercase")]
13pub enum Permission {
14 /// May download / read files.
15 Read,
16 /// May upload / write files.
17 Write,
18}
19
20impl std::fmt::Display for Permission {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 match self {
23 Permission::Read => write!(f, "read"),
24 Permission::Write => write!(f, "write"),
25 }
26 }
27}
28
29/// Parsed, verified token payload used for fine-grained authorization.
30///
31/// All fields except `sub` are optional so that minimal tokens remain
32/// usable (validation is performed by the [`Validator`](crate::auth::Validator)).
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
34pub struct TokenClaims {
35 /// Subject — the user or client the token belongs to.
36 pub sub: String,
37 /// Unix timestamp (seconds) at which the token expires.
38 #[serde(default)]
39 pub exp: Option<i64>,
40 /// Permissions granted to this token. Empty means "no permissions".
41 #[serde(default)]
42 pub permissions: Vec<Permission>,
43 /// Path prefixes the token may access. Empty means "no paths allowed".
44 #[serde(default)]
45 pub allowed_paths: Vec<String>,
46}
47
48impl TokenClaims {
49 /// Returns true if `now` (unix seconds) is past `exp`.
50 pub fn is_expired(&self, now: i64) -> bool {
51 self.exp.is_some_and(|exp| now >= exp)
52 }
53
54 /// Returns true if this token grants `perm`.
55 pub fn has_permission(&self, perm: Permission) -> bool {
56 self.permissions.contains(&perm)
57 }
58}