feat: will trigger login if no cookie is found
Some checks are pending
ci/woodpecker/push/test Pipeline is pending

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2023-11-30 10:07:27 +01:00
parent f586d157b1
commit 1b8924e7f6
Signed by: kjuulh
GPG Key ID: 57B6E1465221F912

View File

@ -2,8 +2,8 @@ use std::fmt::Display;
use axum::extract::{FromRef, FromRequestParts, Query, State}; use axum::extract::{FromRef, FromRequestParts, Query, State};
use axum::http::request::Parts; use axum::http::request::Parts;
use axum::http::StatusCode; use axum::http::{HeaderMap, StatusCode, Uri};
use axum::response::{ErrorResponse, IntoResponse, Redirect}; use axum::response::{ErrorResponse, IntoResponse, Redirect, Response};
use axum::routing::get; use axum::routing::get;
use axum::{async_trait, Json, RequestPartsExt, Router}; use axum::{async_trait, Json, RequestPartsExt, Router};
@ -97,13 +97,21 @@ pub struct UserFromSession {
pub static COOKIE_NAME: &str = "SESSION"; pub static COOKIE_NAME: &str = "SESSION";
pub struct AuthRedirect((HeaderMap, String));
impl IntoResponse for AuthRedirect {
fn into_response(self) -> Response {
(self.0 .0, Redirect::temporary(&self.0 .1.as_str())).into_response()
}
}
#[async_trait] #[async_trait]
impl<S> FromRequestParts<S> for UserFromSession impl<S> FromRequestParts<S> for UserFromSession
where where
AuthService: FromRef<S>, AuthService: FromRef<S>,
S: Send + Sync, S: Send + Sync,
{ {
type Rejection = (StatusCode, &'static str); type Rejection = AuthRedirect;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> { async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
let auth_service = AuthService::from_ref(state); let auth_service = AuthService::from_ref(state);
@ -114,16 +122,21 @@ where
let basic: Option<TypedHeader<Authorization<Basic>>> = parts.extract().await.unwrap(); let basic: Option<TypedHeader<Authorization<Basic>>> = parts.extract().await.unwrap();
if let Some(basic) = basic { if let Some(basic) = basic {
let token = auth_service let token = match auth_service
.login_token(basic.username(), basic.password()) .login_token(basic.username(), basic.password())
.await .await
.into_response() .into_response()
.map_err(|_| { {
( Ok(login) => login,
StatusCode::INTERNAL_SERVER_ERROR, Err(e) => {
"could not get token from basic", tracing::info!("did not find a basic login token, will trigger login");
) let (headers, url) = auth_service
})?; .login(Some(parts.uri.to_string()))
.await
.expect("to be able to request login");
return Err(AuthRedirect((headers, url.to_string())));
}
};
return Ok(UserFromSession { return Ok(UserFromSession {
user: User { user: User {
@ -134,24 +147,32 @@ where
}); });
} }
return Err(anyhow::anyhow!("No session was found")) tracing::info!("did not find a cookie, will trigger login");
.into_response() let (headers, url) = auth_service
.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "did not find a cookie"))?; .login(Some(parts.uri.to_string()))
.await
.expect("to be able to request login");
return Err(AuthRedirect((headers, url.to_string())));
} }
let session_cookie = session_cookie.unwrap(); let session_cookie = session_cookie.unwrap();
// continue to decode the session cookie // continue to decode the session cookie
let user = auth_service let user = match auth_service
.get_user_from_session(session_cookie) .get_user_from_session(session_cookie)
.await .await
.into_response() .into_response()
.map_err(|_| { {
( Ok(user) => user,
StatusCode::INTERNAL_SERVER_ERROR, Err(_) => {
"failed to decode session cookie", tracing::info!("could not get user from session, will trigger login");
) let (headers, url) = auth_service
})?; .login(Some(parts.uri.to_string()))
.await
.expect("to be able to request login");
return Err(AuthRedirect((headers, url.to_string())));
}
};
Ok(UserFromSession { user }) Ok(UserFromSession { user })
} }