diff options
Diffstat (limited to 'src/login')
| -rw-r--r-- | src/login/app.rs | 11 | ||||
| -rw-r--r-- | src/login/routes.rs | 17 | ||||
| -rw-r--r-- | src/login/routes/test/logout.rs | 30 |
3 files changed, 36 insertions, 22 deletions
diff --git a/src/login/app.rs b/src/login/app.rs index b8916a8..182c62c 100644 --- a/src/login/app.rs +++ b/src/login/app.rs @@ -120,16 +120,13 @@ impl<'a> Logins<'a> { Ok(()) } - pub async fn logout(&self, secret: &IdentitySecret) -> Result<(), ValidateError> { + pub async fn logout(&self, token: &token::Id) -> Result<(), ValidateError> { let mut tx = self.db.begin().await?; - let token = tx - .tokens() - .revoke(secret) - .await - .not_found(|| ValidateError::InvalidToken)?; + tx.tokens().revoke(token).await?; tx.commit().await?; - self.logins.broadcast(&types::TokenRevoked::from(token)); + self.logins + .broadcast(&types::TokenRevoked::from(token.clone())); Ok(()) } diff --git a/src/login/routes.rs b/src/login/routes.rs index 4664063..8d9e938 100644 --- a/src/login/routes.rs +++ b/src/login/routes.rs @@ -78,27 +78,32 @@ struct LogoutRequest {} async fn on_logout( State(app): State<App>, + RequestedAt(now): RequestedAt, identity: IdentityToken, // This forces the only valid request to be `{}`, and not the infinite // variation allowed when there's no body extractor. Json(LogoutRequest {}): Json<LogoutRequest>, ) -> Result<(IdentityToken, StatusCode), LogoutError> { if let Some(secret) = identity.secret() { - app.logins().logout(&secret).await.map_err(LogoutError)?; + let (token, _) = app.logins().validate(&secret, &now).await?; + app.logins().logout(&token).await?; } let identity = identity.clear(); Ok((identity, StatusCode::NO_CONTENT)) } -#[derive(Debug)] -struct LogoutError(app::ValidateError); +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +enum LogoutError { + ValidateError(#[from] app::ValidateError), + DatabaseError(#[from] sqlx::Error), +} impl IntoResponse for LogoutError { fn into_response(self) -> Response { - let Self(error) = self; - match error { - error @ app::ValidateError::InvalidToken => { + match self { + error @ Self::ValidateError(app::ValidateError::InvalidToken) => { (StatusCode::UNAUTHORIZED, error.to_string()).into_response() } other => Internal::from(other).into_response(), diff --git a/src/login/routes/test/logout.rs b/src/login/routes/test/logout.rs index 05594be..20b0d55 100644 --- a/src/login/routes/test/logout.rs +++ b/src/login/routes/test/logout.rs @@ -22,6 +22,7 @@ async fn successful() { let (response_identity, response_status) = routes::on_logout( State(app.clone()), + fixtures::now(), identity.clone(), Json(routes::LogoutRequest {}), ) @@ -57,10 +58,14 @@ async fn no_identity() { // Call the endpoint let identity = fixtures::identity::not_logged_in(); - let (identity, status) = - routes::on_logout(State(app), identity, Json(routes::LogoutRequest {})) - .await - .expect("logged out with no token"); + let (identity, status) = routes::on_logout( + State(app), + fixtures::now(), + identity, + Json(routes::LogoutRequest {}), + ) + .await + .expect("logged out with no token"); // Verify the return value's basic structure @@ -77,12 +82,19 @@ async fn invalid_token() { // Call the endpoint let identity = fixtures::identity::fictitious(); - let routes::LogoutError(error) = - routes::on_logout(State(app), identity, Json(routes::LogoutRequest {})) - .await - .expect_err("logged out with an invalid token"); + let error = routes::on_logout( + State(app), + fixtures::now(), + identity, + Json(routes::LogoutRequest {}), + ) + .await + .expect_err("logged out with an invalid token"); // Verify the return value's basic structure - assert!(matches!(error, app::ValidateError::InvalidToken)); + assert!(matches!( + error, + routes::LogoutError::ValidateError(app::ValidateError::InvalidToken) + )); } |
