diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2024-09-29 02:02:41 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2024-09-29 02:04:01 -0400 |
| commit | 6c054c5b8d43a818ccfa9087960dc19b286e6bb7 (patch) | |
| tree | c1eff6f13a1ac3ba102fcfa22de9f25ed30546d0 /src/login | |
| parent | 0b1cb80dd0b0f90c4892de7e7a2d18a076ecbdf2 (diff) | |
Reimplement the logout machinery in terms of token IDs, not token secrets.
This (a) reduces the amount of passing secrets around that's needed, and (b) allows tests to log out in a more straightforwards manner.
Ish. The fixtures are a mess, but so is the nomenclature. Fix the latter and the former will probably follow.
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) + )); } |
