diff options
| author | ojacobson <ojacobson@noreply.codeberg.org> | 2025-08-26 04:32:42 +0200 |
|---|---|---|
| committer | ojacobson <ojacobson@noreply.codeberg.org> | 2025-08-26 04:32:42 +0200 |
| commit | 25914826e0f256789d943cd25375b2444130ce01 (patch) | |
| tree | 44ce77c5af10f2b90308ab31e9b383975ebfd280 /src/user/handlers | |
| parent | 53944ef14af4d37c08464cb1bb9f3a8f09277194 (diff) | |
| parent | f6a79204c2ce9a15d7909c1c389417e0b7351cad (diff) | |
Remove unused response bodies from a number of API endpoints.
This removes the response body from the following methods:
* `POST /api/setup`
* `POST /api/auth/login`
* `POST /api/invite/:id`
* `POST /api/password`
The bodies returned from these methods were something of a rough guess as to what might be useful. Actual client development has shown that we don't use _any_ of the data from any of these API responses, so let's not tie ourselves to future compatibility by continuing to send them. We can add a body to a bodyless method a _lot_ more easily than we can change the body of a method that already returns one, after all.
These changes are not backwards compatible for clients which care about the existing bodies. To my knowledge, there are no such clients; the included client definitely doesn't care.
## Internals
Not only does this change stop returning bodies at the API surface, but it also stops retrieving and returning values used internally to construct those responses, simplifying the code a bit in the process.
One side effect of this is that tests that need to log in a user now need to manually verify the returned token secret, to convert it back into a user, whereas the previous versions returned both a token secret and a user during password login. I don't love the increase in the size of the tests, but I think it's the right tradeoff (and this change is code net-negative anyways).
Merges no-content into main.
Diffstat (limited to 'src/user/handlers')
| -rw-r--r-- | src/user/handlers/login/mod.rs | 8 | ||||
| -rw-r--r-- | src/user/handlers/login/test.rs | 7 | ||||
| -rw-r--r-- | src/user/handlers/logout/mod.rs | 6 | ||||
| -rw-r--r-- | src/user/handlers/logout/test.rs | 13 | ||||
| -rw-r--r-- | src/user/handlers/password/mod.rs | 8 | ||||
| -rw-r--r-- | src/user/handlers/password/test.rs | 20 |
6 files changed, 35 insertions, 27 deletions
diff --git a/src/user/handlers/login/mod.rs b/src/user/handlers/login/mod.rs index da88885..d3e0e8c 100644 --- a/src/user/handlers/login/mod.rs +++ b/src/user/handlers/login/mod.rs @@ -7,11 +7,11 @@ use axum::{ use crate::{ app::App, clock::RequestedAt, + empty::Empty, error::Internal, name::Name, password::Password, token::{app, extract::IdentityCookie}, - user::User, }; #[cfg(test)] @@ -22,14 +22,14 @@ pub async fn handler( RequestedAt(now): RequestedAt, identity: IdentityCookie, Json(request): Json<Request>, -) -> Result<(IdentityCookie, Json<User>), Error> { - let (user, secret) = app +) -> Result<(IdentityCookie, Empty), Error> { + let secret = app .tokens() .login(&request.name, &request.password, &now) .await .map_err(Error)?; let identity = identity.set(secret); - Ok((identity, Json(user))) + Ok((identity, Empty)) } #[derive(serde::Deserialize)] diff --git a/src/user/handlers/login/test.rs b/src/user/handlers/login/test.rs index b8f24f6..bdd1957 100644 --- a/src/user/handlers/login/test.rs +++ b/src/user/handlers/login/test.rs @@ -1,6 +1,6 @@ use axum::extract::{Json, State}; -use crate::{test::fixtures, token::app}; +use crate::{empty::Empty, test::fixtures, token::app}; #[tokio::test] async fn correct_credentials() { @@ -17,14 +17,13 @@ async fn correct_credentials() { name: name.clone(), password, }; - let (identity, Json(response)) = + let (identity, Empty) = super::handler(State(app.clone()), logged_in_at, identity, Json(request)) .await .expect("logged in with valid credentials"); // Verify the return value's basic structure - assert_eq!(name, response.name); let secret = identity .secret() .expect("logged in with valid credentials issues an identity cookie"); @@ -38,7 +37,7 @@ async fn correct_credentials() { .await .expect("identity secret is valid"); - assert_eq!(response, validated_login); + assert_eq!(name, validated_login.name); } #[tokio::test] diff --git a/src/user/handlers/logout/mod.rs b/src/user/handlers/logout/mod.rs index 45a376a..4450e4c 100644 --- a/src/user/handlers/logout/mod.rs +++ b/src/user/handlers/logout/mod.rs @@ -1,12 +1,12 @@ use axum::{ extract::{Json, State}, - http::StatusCode, response::{IntoResponse, Response}, }; use crate::{ app::App, clock::RequestedAt, + empty::Empty, error::{Internal, Unauthorized}, token::{app, extract::IdentityCookie}, }; @@ -19,14 +19,14 @@ pub async fn handler( RequestedAt(now): RequestedAt, identity: IdentityCookie, Json(_): Json<Request>, -) -> Result<(IdentityCookie, StatusCode), Error> { +) -> Result<(IdentityCookie, Empty), Error> { if let Some(secret) = identity.secret() { let (token, _) = app.tokens().validate(&secret, &now).await?; app.tokens().logout(&token).await?; } let identity = identity.clear(); - Ok((identity, StatusCode::NO_CONTENT)) + Ok((identity, Empty)) } // This forces the only valid request to be `{}`, and not the infinite diff --git a/src/user/handlers/logout/test.rs b/src/user/handlers/logout/test.rs index 8dc4636..7151ddf 100644 --- a/src/user/handlers/logout/test.rs +++ b/src/user/handlers/logout/test.rs @@ -1,9 +1,6 @@ -use axum::{ - extract::{Json, State}, - http::StatusCode, -}; +use axum::extract::{Json, State}; -use crate::{test::fixtures, token::app}; +use crate::{empty::Empty, test::fixtures, token::app}; #[tokio::test] async fn successful() { @@ -17,7 +14,7 @@ async fn successful() { // Call the endpoint - let (response_identity, response_status) = super::handler( + let (response_identity, Empty) = super::handler( State(app.clone()), fixtures::now(), identity.clone(), @@ -29,7 +26,6 @@ async fn successful() { // Verify the return value's basic structure assert!(response_identity.secret().is_none()); - assert_eq!(StatusCode::NO_CONTENT, response_status); // Verify the semantics let error = app @@ -49,14 +45,13 @@ async fn no_identity() { // Call the endpoint let identity = fixtures::cookie::not_logged_in(); - let (identity, status) = super::handler(State(app), fixtures::now(), identity, Json::default()) + let (identity, Empty) = super::handler(State(app), fixtures::now(), identity, Json::default()) .await .expect("logged out with no token succeeds"); // Verify the return value's basic structure assert!(identity.secret().is_none()); - assert_eq!(StatusCode::NO_CONTENT, status); } #[tokio::test] diff --git a/src/user/handlers/password/mod.rs b/src/user/handlers/password/mod.rs index c327e87..5e69c1c 100644 --- a/src/user/handlers/password/mod.rs +++ b/src/user/handlers/password/mod.rs @@ -7,13 +7,13 @@ use axum::{ use crate::{ app::App, clock::RequestedAt, + empty::Empty, error::Internal, password::Password, token::{ app, extract::{Identity, IdentityCookie}, }, - user::User, }; #[cfg(test)] @@ -25,14 +25,14 @@ pub async fn handler( identity: Identity, cookie: IdentityCookie, Json(request): Json<Request>, -) -> Result<(IdentityCookie, Json<User>), Error> { - let (login, secret) = app +) -> Result<(IdentityCookie, Empty), Error> { + let secret = app .tokens() .change_password(&identity.user, &request.password, &request.to, &now) .await .map_err(Error)?; let cookie = cookie.set(secret); - Ok((cookie, Json(login))) + Ok((cookie, Empty)) } #[derive(serde::Deserialize)] diff --git a/src/user/handlers/password/test.rs b/src/user/handlers/password/test.rs index 42e41d8..ffa12f3 100644 --- a/src/user/handlers/password/test.rs +++ b/src/user/handlers/password/test.rs @@ -1,6 +1,7 @@ use axum::extract::{Json, State}; use crate::{ + empty::Empty, test::fixtures, token::app::{LoginError, ValidateError}, }; @@ -20,7 +21,7 @@ async fn password_change() { password: password.clone(), to: to.clone(), }; - let (new_cookie, Json(response)) = super::handler( + let (new_cookie, Empty) = super::handler( State(app.clone()), fixtures::now(), identity.clone(), @@ -34,7 +35,15 @@ async fn password_change() { assert_ne!(cookie.secret(), new_cookie.secret()); // Verify that we're still ourselves - assert_eq!(identity.user, response); + let new_secret = new_cookie + .secret() + .expect("we should have a secret after changing our password"); + let (_, login) = app + .tokens() + .validate(&new_secret, &fixtures::now()) + .await + .expect("the newly-issued secret should be valid"); + assert_eq!(identity.user, login); // Verify that our original token is no longer valid let validate_err = app @@ -58,10 +67,15 @@ async fn password_change() { assert!(matches!(login_err, LoginError::Rejected)); // Verify that our new password is valid - let (login, _) = app + let secret = app .tokens() .login(&name, &to, &fixtures::now()) .await .expect("logging in with the new password should succeed"); + let (_, login) = app + .tokens() + .validate(&secret, &fixtures::now()) + .await + .expect("validating a newly-issued token secret succeeds"); assert_eq!(identity.user, login); } |
