diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2024-09-04 00:28:35 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2024-09-04 00:28:35 -0400 |
| commit | 2965a788cfcf4a0386cb8832e0d96491bf54c1d3 (patch) | |
| tree | 096b00f64b092396e99d04ebe124fa15d734f6c1 /src/login/extract/login.rs | |
| parent | 289e99ba977ebe6c4599141bc368c17f9905ffcc (diff) | |
Display a different / page depending on whether the current identity is valid or not.
This is mostly a proof of concept for the implementation of form login implemented in previous commits, but it _is_ useful as it controls whether the / page shows login, or shows logout.
From here, chat is next!
Diffstat (limited to 'src/login/extract/login.rs')
| -rw-r--r-- | src/login/extract/login.rs | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/src/login/extract/login.rs b/src/login/extract/login.rs new file mode 100644 index 0000000..f49933a --- /dev/null +++ b/src/login/extract/login.rs @@ -0,0 +1,61 @@ +use axum::{ + extract::{FromRequestParts, State}, + http::{request::Parts, StatusCode}, + response::{IntoResponse, Response}, +}; +use sqlx::sqlite::SqlitePool; + +use crate::{ + error::InternalError, + login::{ + extract::IdentityToken, + repo::{logins::Login, tokens::Provider as _}, + }, +}; + +#[async_trait::async_trait] +impl FromRequestParts<SqlitePool> for Login { + type Rejection = LoginError<InternalError>; + + async fn from_request_parts( + parts: &mut Parts, + state: &SqlitePool, + ) -> Result<Self, Self::Rejection> { + let identity_token = IdentityToken::from_request_parts(parts, state).await?; + + let token = identity_token.token().ok_or(LoginError::Forbidden)?; + + let db = State::<SqlitePool>::from_request_parts(parts, state).await?; + let mut tx = db.begin().await?; + let login = tx.tokens().validate(token).await?; + tx.commit().await?; + + login.ok_or(LoginError::Forbidden) + } +} + +pub enum LoginError<E> { + Failure(E), + Forbidden, +} + +impl<E> IntoResponse for LoginError<E> +where + E: IntoResponse, +{ + fn into_response(self) -> Response { + match self { + Self::Forbidden => (StatusCode::FORBIDDEN, "forbidden").into_response(), + Self::Failure(e) => e.into_response(), + } + } +} + +impl<E> From<E> for LoginError<InternalError> +where + E: Into<InternalError>, +{ + fn from(err: E) -> Self { + Self::Failure(err.into()) + } +} |
