use axum::{ Json, extract::{Extension, State}, http::StatusCode, }; use base64::{Engine as _, engine::general_purpose}; use rand::RngCore; use rand::rngs::OsRng; use crate::dto::api::{CreateApiKeyRequest, CreateApiKeyResponse}; use crate::middlewares::auth::middleware::Auth; use crate::state::app_state::AppState; use crate::utils::crypto::hash_key; fn generate_api_key() -> String { let mut bytes = [0u8; 32]; OsRng.fill_bytes(&mut bytes); general_purpose::URL_SAFE_NO_PAD.encode(bytes) } pub async fn create_api_key( State(state): State, Extension(claims): Extension, Json(body): Json, ) -> Result, StatusCode> { if matches!(claims, Auth::ApiKey(_)) { return Err(StatusCode::FORBIDDEN); } let raw_key = generate_api_key(); let key_hash = hash_key(&raw_key); dbg!(&claims); sqlx::query!( r#" INSERT INTO auth.api_key (key_hash, name, created_by, scopes) VALUES ($1, $2, $3, $4) "#, key_hash, body.name, claims.user_id(), &body.scopes ) .execute(&state.postgres) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; Ok(Json(CreateApiKeyResponse { api_key: raw_key })) }