Skip to main content

ironflow_api/routes/api_keys/
list.rs

1//! `GET /api/v1/api-keys` -- List API keys for the authenticated user.
2
3use axum::extract::State;
4use axum::response::IntoResponse;
5use chrono::{DateTime, Utc};
6use ironflow_auth::extractor::AuthenticatedUser;
7use ironflow_store::entities::ApiKeyScope;
8use serde::Serialize;
9use uuid::Uuid;
10
11use crate::error::ApiError;
12use crate::response::ok;
13use crate::state::AppState;
14
15/// API key summary (never includes the hash or raw key).
16#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
17#[derive(Debug, Serialize)]
18pub struct ApiKeyResponse {
19    /// API key ID.
20    pub id: Uuid,
21    /// Key name.
22    pub name: String,
23    /// First characters for identification.
24    pub key_prefix: String,
25    /// Granted scopes.
26    pub scopes: Vec<ApiKeyScope>,
27    /// Whether the key is active.
28    pub is_active: bool,
29    /// Expiration date.
30    pub expires_at: Option<DateTime<Utc>>,
31    /// Last used date.
32    pub last_used_at: Option<DateTime<Utc>>,
33    /// Creation date.
34    pub created_at: DateTime<Utc>,
35}
36
37/// List all API keys for the authenticated user.
38#[cfg_attr(
39    feature = "openapi",
40    utoipa::path(
41        get,
42        path = "/api/v1/api-keys",
43        tags = ["api-keys"],
44        responses(
45            (status = 200, description = "List of API keys", body = Vec<ApiKeyResponse>),
46            (status = 401, description = "Unauthorized")
47        ),
48        security(("Bearer" = []))
49    )
50)]
51pub async fn list_api_keys(
52    user: AuthenticatedUser,
53    State(state): State<AppState>,
54) -> Result<impl IntoResponse, ApiError> {
55    let keys = state
56        .api_key_store
57        .list_api_keys_by_user(user.user_id)
58        .await
59        .map_err(ApiError::from)?;
60
61    let responses: Vec<ApiKeyResponse> = keys
62        .into_iter()
63        .map(|k| ApiKeyResponse {
64            id: k.id,
65            name: k.name,
66            key_prefix: k.key_prefix,
67            scopes: k.scopes,
68            is_active: k.is_active,
69            expires_at: k.expires_at,
70            last_used_at: k.last_used_at,
71            created_at: k.created_at,
72        })
73        .collect();
74
75    Ok(ok(responses))
76}