summaryrefslogtreecommitdiffstats
path: root/src/api/users.rs
diff options
context:
space:
mode:
authorToby Vincent <tobyv@tobyvin.dev>2024-04-15 19:30:02 -0500
committerToby Vincent <tobyv@tobyvin.dev>2024-04-15 19:30:02 -0500
commit4eea9d6ab134bdd05506dc85145e72ab186bf2ad (patch)
tree96ce61ace570cbaf57cda99beccc362200cc324f /src/api/users.rs
parentf39bcb529672bd23d128b1fefa0a9a68bd78a7c3 (diff)
feat(api): add logout endpoint to unset token
Diffstat (limited to 'src/api/users.rs')
-rw-r--r--src/api/users.rs43
1 files changed, 41 insertions, 2 deletions
diff --git a/src/api/users.rs b/src/api/users.rs
index 6ed79f2..3ac72d9 100644
--- a/src/api/users.rs
+++ b/src/api/users.rs
@@ -7,6 +7,7 @@ use axum::{
Json, Router,
};
use axum_extra::{
+ extract::{cookie::Cookie, CookieJar},
headers::{authorization::Basic, Authorization},
routing::Resource,
typed_header::TypedHeaderRejection,
@@ -25,9 +26,12 @@ use crate::{
use super::error::Error;
pub fn router() -> Router<AppState> {
+ let users = Resource::named("users").create(create).show(show);
+
axum::Router::new()
.route("/users/login", get(login))
- .merge(Resource::named("users").create(create).show(show))
+ .route("/users/logout", get(logout))
+ .merge(users)
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, FromRow)]
@@ -71,6 +75,10 @@ pub async fn login(
.map_err(Into::into)
}
+pub async fn logout(claims: AccessClaims, jar: CookieJar) -> Result<CookieJar, Error> {
+ Ok(jar.remove(Cookie::try_from(claims)?))
+}
+
pub async fn create(
State(state): State<AppState>,
Json(RegisterSchema {
@@ -141,7 +149,7 @@ mod tests {
Router,
};
- use axum_extra::headers::authorization::Credentials;
+ use axum_extra::headers::{authorization::Credentials, Header, HeaderMapExt, SetCookie};
use http_body_util::BodyExt;
use sqlx::PgPool;
use tower::ServiceExt;
@@ -375,4 +383,35 @@ mod tests {
Ok(())
}
+
+ #[sqlx::test(fixtures(path = "../../fixtures", scripts("users")))]
+ async fn test_logout_ok(pool: PgPool) -> TestResult {
+ setup_test_env();
+
+ let router = Router::new().merge(router()).with_state(AppState { pool });
+
+ let request = Request::builder()
+ .uri("/users/logout")
+ .method("GET")
+ .header(COOKIE, HeaderValue::try_from(AccessClaims::new(USER_ID))?)
+ .body(Body::empty())?;
+
+ let response = router.oneshot(request).await?;
+
+ assert_eq!(StatusCode::OK, response.status());
+
+ if let Some(set_cookie) = response.headers().typed_get::<SetCookie>() {
+ let mut values = Vec::new();
+ set_cookie.encode(&mut values);
+ for value in values {
+ let cookie: Cookie = value.to_str()?.parse().unwrap();
+ if cookie.name() == "token" {
+ assert_eq!(cookie.value(), "");
+ assert_eq!(cookie.max_age(), Some(time::Duration::ZERO));
+ }
+ }
+ }
+
+ Ok(())
+ }
}