From 82cc3b8054f4b126b422d946ea694d282a41cd78 Mon Sep 17 00:00:00 2001 From: Toby Vincent Date: Tue, 7 May 2024 19:04:46 -0500 Subject: feat(api): return user resource in location header --- src/api.rs | 4 ++-- src/api/error.rs | 4 ++++ src/api/users.rs | 27 +++++++++++++++++++++------ src/auth/claims.rs | 3 +-- 4 files changed, 28 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/api.rs b/src/api.rs index 6013a98..3641697 100644 --- a/src/api.rs +++ b/src/api.rs @@ -19,8 +19,8 @@ pub async fn healthcheck() -> &'static str { "success" } -pub async fn fallback(uri: axum::http::Uri) -> self::error::Error { - self::error::Error::RouteNotFound(uri) +pub async fn fallback(uri: axum::http::Uri) -> error::Error { + error::Error::RouteNotFound(uri) } #[cfg(test)] diff --git a/src/api/error.rs b/src/api/error.rs index 10b5468..bc75d41 100644 --- a/src/api/error.rs +++ b/src/api/error.rs @@ -18,6 +18,9 @@ pub enum Error { #[error("Failed to parse header: {0} (wrong token type?)")] Header(axum_extra::typed_header::TypedHeaderRejection), + #[error("Failed to parse header: {0}")] + HeaderValue(#[from] axum::http::header::InvalidHeaderValue), + #[error("Invalid user token")] InvalidToken, @@ -72,6 +75,7 @@ impl axum::response::IntoResponse for Error { Self::HeaderNotFound(_) => StatusCode::BAD_REQUEST, Self::EmailInvalid(_) | Self::Header(_) => StatusCode::UNPROCESSABLE_ENTITY, Self::AuthRequest(_) | Self::Sqlx(_) => StatusCode::INTERNAL_SERVER_ERROR, + Self::HeaderValue(_) => StatusCode::INTERNAL_SERVER_ERROR, Self::Auth(err) => return err.into_response(), }; diff --git a/src/api/users.rs b/src/api/users.rs index d4e5d57..bfbc0d6 100644 --- a/src/api/users.rs +++ b/src/api/users.rs @@ -2,7 +2,8 @@ use std::str::FromStr; use axum::{ extract::{Path, State}, - response::IntoResponse, + http::header::LOCATION, + response::{IntoResponse, IntoResponseParts}, Json, }; use axum_extra::routing::Resource; @@ -32,6 +33,20 @@ pub struct User { pub updated_at: OffsetDateTime, } +impl IntoResponseParts for User { + type Error = Error; + + fn into_response_parts( + self, + mut res: axum::response::ResponseParts, + ) -> Result { + res.headers_mut() + .append(LOCATION, format!("/users/{}", self.id).try_into()?); + + Ok(res) + } +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Registration { pub name: String, @@ -59,16 +74,16 @@ pub async fn create( .await?; // TODO: Move this into a micro service, possibly behind a feature flag. - crate::auth::credentials::create( - State(pool.clone()), + let (status, (access, refresh)) = crate::auth::credentials::create( + State(pool), Json(Credential { id: user.id, password, }), ) - .await - .map(|(status, claims)| (status, claims, Json(user))) - .map_err(Into::into) + .await?; + + Ok((status, user, access, refresh)) } pub async fn show( diff --git a/src/auth/claims.rs b/src/auth/claims.rs index 6940844..9087598 100644 --- a/src/auth/claims.rs +++ b/src/auth/claims.rs @@ -4,7 +4,6 @@ use axum::{ http::{ header::{AUTHORIZATION, SET_COOKIE}, request::Parts, - HeaderValue, }, response::{IntoResponse, IntoResponseParts}, RequestPartsExt, @@ -181,7 +180,7 @@ impl IntoResponseParts for RefreshClaims { ) -> Result { res.headers_mut().append( AUTHORIZATION, - HeaderValue::try_from(format!("Bearer {}", JWT.encode(&self)?))?, + format!("Bearer {}", JWT.encode(&self)?).try_into()?, ); Ok(res) -- cgit v1.2.3-70-g09d2