diff options
-rw-r--r-- | src/routes.rs | 1 | ||||
-rw-r--r-- | src/routes/login.rs | 45 |
2 files changed, 46 insertions, 0 deletions
diff --git a/src/routes.rs b/src/routes.rs index c83a3ee..e2f5587 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -21,6 +21,7 @@ pub fn init_router(state: Arc<AppState>) -> axum::Router { .typed_get(user::UserUuid::get) .typed_post(register::Register::post) .typed_post(login::Login::post) + .typed_get(login::Logout::get) .fallback(fallback) .with_state(state) } diff --git a/src/routes/login.rs b/src/routes/login.rs index a3c52f8..2441a21 100644 --- a/src/routes/login.rs +++ b/src/routes/login.rs @@ -66,6 +66,30 @@ impl Login { } } +#[derive(Debug, Deserialize, TypedPath)] +#[typed_path("/api/logout")] +pub struct Logout; + +impl Logout { + #[tracing::instrument] + pub async fn get(self) -> impl IntoResponse { + let cookie = Cookie::build(("token", "")) + .path("/") + .max_age(time::Duration::hours(-1)) + .same_site(SameSite::Lax) + .http_only(true) + .build(); + + let mut response = Json(json!({"status": "success"})).into_response(); + + response + .headers_mut() + .insert(SET_COOKIE, cookie.to_string().parse().unwrap()); + + response + } +} + #[cfg(test)] mod tests { use super::*; @@ -137,4 +161,25 @@ mod tests { Ok(()) } + + #[sqlx::test] + async fn test_logout(pool: PgPool) -> TestResult { + let state = Arc::new(AppState { + pool, + jwt_secret: JWT_SECRET.to_string(), + jwt_max_age: JWT_MAX_AGE, + }); + let router = init_router(state.clone()); + + let request = Request::builder() + .uri("/api/logout") + .method("GET") + .body(Body::empty())?; + + let response = router.oneshot(request).await?; + + assert_eq!(StatusCode::OK, response.status()); + + Ok(()) + } } |