diff options
| author | Joel Klinghed <the_jk@spawned.biz> | 2024-12-29 22:40:12 +0100 |
|---|---|---|
| committer | Joel Klinghed <the_jk@spawned.biz> | 2024-12-29 22:40:12 +0100 |
| commit | 776406684bdc591a4c97b58b8d28f689881c285e (patch) | |
| tree | 7551fcc2d10eb4d75314b2ad93bce6c328481413 /server/src/auth.rs | |
| parent | 7bc8e8b7262a3f3abe3222b3b434838e85cdb2bb (diff) | |
Add openapi generation using utoipa
Diffstat (limited to 'server/src/auth.rs')
| -rw-r--r-- | server/src/auth.rs | 80 |
1 files changed, 63 insertions, 17 deletions
diff --git a/server/src/auth.rs b/server/src/auth.rs index 31e18a0..4e66448 100644 --- a/server/src/auth.rs +++ b/server/src/auth.rs @@ -12,10 +12,31 @@ use std::collections::BTreeMap; use std::sync::Mutex; use std::time::Instant; use time::Duration; +use utoipa::openapi::security::{ApiKey, ApiKeyValue, SecurityScheme}; +use utoipa::{Modify, OpenApi, ToSchema}; use crate::api_model; -#[derive(FromForm)] +#[derive(OpenApi)] +#[openapi( + paths(login, logout, status,), + modifiers(&AuthApiAddon), +)] +pub struct AuthApi; + +pub struct AuthApiAddon; + +impl Modify for AuthApiAddon { + fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) { + let components = openapi.components.as_mut().unwrap(); + components.add_security_scheme( + "session", + SecurityScheme::ApiKey(ApiKey::Cookie(ApiKeyValue::new(SESSION_COOKIE))), + ) + } +} + +#[derive(FromForm, ToSchema)] struct Login<'r> { username: &'r str, password: &'r str, @@ -49,6 +70,14 @@ pub enum SessionError { } const SESSION_COOKIE: &str = "s"; +const STATUS_OK: api_model::StatusResponse = api_model::StatusResponse { + ok: true, + error: None, +}; +const STATUS_UNAUTHORIZED: api_model::StatusResponse = api_model::StatusResponse { + ok: false, + error: Some("Unauthorized"), +}; fn validate(sessions: &State<Sessions>, session: &Session, request: &Request<'_>) -> bool { match request.client_ip() { @@ -123,6 +152,17 @@ fn new_session( } } +#[utoipa::path( + responses( + (status = 200, description = "Login successful", body = api_model::StatusResponse, + example = json!(STATUS_OK)), + (status = 401, description = "Login failed", body = api_model::StatusResponse, + example = json!(STATUS_UNAUTHORIZED)), + ), + security( + (), + ), +)] #[post("/login", data = "<login>")] fn login( auth_config: &State<AuthConfig>, @@ -142,15 +182,20 @@ fn login( .build(); cookies.add_private(cookie); - Ok(Json(api_model::StatusResponse { - ok: true, - error: None, - })) + Ok(Json(STATUS_OK)) } else { Err(Unauthorized("Unknown username or password")) } } +#[utoipa::path( + responses( + (status = 200, description = "Logout successful", body = api_model::StatusResponse, example = json!(STATUS_OK)), + ), + security( + ("session" = []), + ), +)] #[get("/logout")] fn logout( session: Session, @@ -169,26 +214,27 @@ fn logout( cookies.remove_private(cookie); - Json(api_model::StatusResponse { - ok: true, - error: None, - }) + Json(STATUS_OK) } +#[utoipa::path( + responses( + (status = 200, description = "Current status", body = api_model::StatusResponse, example = json!(STATUS_OK)), + (status = 401, description = "Not authorized", body = api_model::StatusResponse, example = json!(STATUS_UNAUTHORIZED)), + ), + security( + (), + ("session" = []), + ), +)] #[get("/status")] fn status(_session: Session) -> Json<api_model::StatusResponse> { - Json(api_model::StatusResponse { - ok: true, - error: None, - }) + Json(STATUS_OK) } #[catch(401)] fn unauthorized() -> Json<api_model::StatusResponse> { - Json(api_model::StatusResponse { - ok: false, - error: Some("Unauthorized".to_string()), - }) + Json(STATUS_UNAUTHORIZED) } pub fn stage(basepath: String) -> AdHoc { |
