modo/auth/apikey/types.rs
1use serde::Serialize;
2
3/// Input for [`super::ApiKeyStore::create`].
4///
5/// All fields except `expires_at` are required. Pass `None` for
6/// `expires_at` to create a non-expiring key.
7pub struct CreateKeyRequest {
8 /// Tenant this key belongs to. Required.
9 pub tenant_id: String,
10 /// Human-readable name for the key.
11 pub name: String,
12 /// Scopes this key grants. Framework stores, app defines meaning.
13 pub scopes: Vec<String>,
14 /// Expiration timestamp (ISO 8601). `None` for lifetime tokens.
15 pub expires_at: Option<String>,
16}
17
18/// One-time result from [`super::ApiKeyStore::create`].
19///
20/// Contains the raw token that must be shown to the user exactly once.
21/// The raw token is not retrievable after creation.
22#[derive(Debug, Clone, Serialize)]
23pub struct ApiKeyCreated {
24 /// ULID primary key.
25 pub id: String,
26 /// Full raw token. Show once, never retrievable after creation.
27 pub raw_token: String,
28 /// Human-readable name.
29 pub name: String,
30 /// Scopes this key grants.
31 pub scopes: Vec<String>,
32 /// Tenant this key belongs to.
33 pub tenant_id: String,
34 /// Expiration timestamp (ISO 8601), or `None` for lifetime.
35 pub expires_at: Option<String>,
36 /// Creation timestamp (ISO 8601).
37 pub created_at: String,
38}
39
40/// Public metadata extracted by [`super::ApiKeyLayer`] middleware.
41///
42/// Available as an axum extractor in handlers (implements
43/// [`FromRequestParts`](axum::extract::FromRequestParts) and
44/// [`OptionalFromRequestParts`](axum::extract::OptionalFromRequestParts)).
45/// Does not contain the key hash or revocation timestamp.
46#[derive(Debug, Clone, Serialize)]
47pub struct ApiKeyMeta {
48 /// ULID primary key.
49 pub id: String,
50 /// Tenant this key belongs to.
51 pub tenant_id: String,
52 /// Human-readable name.
53 pub name: String,
54 /// Scopes this key grants.
55 pub scopes: Vec<String>,
56 /// Expiration timestamp (ISO 8601), or `None` for lifetime.
57 pub expires_at: Option<String>,
58 /// Last time this key was used (ISO 8601).
59 pub last_used_at: Option<String>,
60 /// Creation timestamp (ISO 8601).
61 pub created_at: String,
62}
63
64/// Full stored record used by [`super::ApiKeyBackend`] implementations.
65///
66/// Contains the hash and revocation fields that are stripped when
67/// converting to [`ApiKeyMeta`] via [`into_meta`](Self::into_meta).
68#[derive(Clone)]
69pub struct ApiKeyRecord {
70 /// ULID primary key.
71 pub id: String,
72 /// `hex(sha256(secret))`.
73 pub key_hash: String,
74 /// Tenant this key belongs to.
75 pub tenant_id: String,
76 /// Human-readable name.
77 pub name: String,
78 /// Scopes as `Vec<String>` (serialized as JSON in DB).
79 pub scopes: Vec<String>,
80 /// Expiration timestamp (ISO 8601), or `None` for lifetime.
81 pub expires_at: Option<String>,
82 /// Last use timestamp (ISO 8601).
83 pub last_used_at: Option<String>,
84 /// Creation timestamp (ISO 8601).
85 pub created_at: String,
86 /// Revocation timestamp (ISO 8601), or `None` if active.
87 pub revoked_at: Option<String>,
88}
89
90impl ApiKeyRecord {
91 /// Convert to public metadata, stripping hash and revocation fields.
92 pub fn into_meta(self) -> ApiKeyMeta {
93 ApiKeyMeta {
94 id: self.id,
95 tenant_id: self.tenant_id,
96 name: self.name,
97 scopes: self.scopes,
98 expires_at: self.expires_at,
99 last_used_at: self.last_used_at,
100 created_at: self.created_at,
101 }
102 }
103}