diff --git a/readme.md b/readme.md index 3373daa..0ce8728 100644 --- a/readme.md +++ b/readme.md @@ -266,5 +266,4 @@ This project turns Ollama into: # TODO - open api doc for bearer token -- endpoint for creating token -- verify bearer token +- db diff --git a/src/databases/postgres/api_key.rs b/src/databases/postgres/api_key.rs new file mode 100644 index 0000000..649705b --- /dev/null +++ b/src/databases/postgres/api_key.rs @@ -0,0 +1,17 @@ +use sqlx::PgPool; +use uuid::Uuid; + +pub async fn update_last_access(pool: &PgPool, api_key_id: Uuid) -> Result<(), sqlx::Error> { + sqlx::query!( + r#" + UPDATE auth.api_key + SET last_used_at = now() + WHERE id = $1 + "#, + api_key_id + ) + .execute(pool) + .await?; + + Ok(()) +} diff --git a/src/databases/postgres/mod.rs b/src/databases/postgres/mod.rs index ddbb824..35cb129 100644 --- a/src/databases/postgres/mod.rs +++ b/src/databases/postgres/mod.rs @@ -1,2 +1,3 @@ +pub mod api_key; pub mod pool; pub mod user_repository; diff --git a/src/middlewares/auth/apikey.rs b/src/middlewares/auth/apikey.rs index 0c66985..bb95981 100644 --- a/src/middlewares/auth/apikey.rs +++ b/src/middlewares/auth/apikey.rs @@ -3,4 +3,5 @@ use uuid::Uuid; #[derive(Clone, Debug)] pub struct ApiKeyClaims { pub sub: Uuid, + pub api_key_id: Uuid, } diff --git a/src/middlewares/auth/middleware.rs b/src/middlewares/auth/middleware.rs index 7b211e6..5c941a2 100644 --- a/src/middlewares/auth/middleware.rs +++ b/src/middlewares/auth/middleware.rs @@ -5,7 +5,9 @@ use axum::{ response::{IntoResponse, Response}, }; -use crate::databases::postgres::user_repository::ensure_user_exists; +use crate::databases::postgres::{ + api_key::update_last_access, user_repository::ensure_user_exists, +}; use crate::middlewares::auth::apikey::ApiKeyClaims; use crate::middlewares::auth::keycloak::{KeycloakClaims, get_jwks, refresh_jwks, validate_token}; use crate::state::app_state::AppState; @@ -125,7 +127,7 @@ async fn try_api_key( let row = sqlx::query!( r#" - SELECT u.id AS user_id + SELECT u.id AS user_id, ak.id as key_id FROM auth.api_key ak JOIN auth.user u ON u.id = ak.created_by WHERE ak.key_hash = $1 @@ -147,7 +149,10 @@ async fn try_api_key( state, request, next, - Auth::ApiKey(ApiKeyClaims { sub: row.user_id }), + Auth::ApiKey(ApiKeyClaims { + sub: row.user_id, + api_key_id: row.key_id, + }), ) .await } @@ -161,12 +166,24 @@ async fn handle_auth( next: Next, auth: Auth, ) -> Result { - ensure_user_exists(&state.postgres, auth.user_id()) - .await - .map_err(|e| { - tracing::error!("ensure_user_exists failed: {e}"); - StatusCode::INTERNAL_SERVER_ERROR - })?; + match &auth { + Auth::Jwt(_) => { + ensure_user_exists(&state.postgres, auth.user_id()) + .await + .map_err(|e| { + tracing::error!("ensure_user_exists failed: {e}"); + StatusCode::INTERNAL_SERVER_ERROR + })?; + } + Auth::ApiKey(key) => { + update_last_access(&state.postgres, key.api_key_id) + .await + .map_err(|e| { + tracing::error!("update_last_access failed: {e}"); + StatusCode::INTERNAL_SERVER_ERROR + })?; + } + } request.extensions_mut().insert(auth); Ok(next.run(request).await)