diff options
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()) + } +} |
