feat: conditionally render login or homepage

image-uploads
Jef Roosens 2025-01-11 21:53:46 +01:00
parent 902de85131
commit 48b3191117
No known key found for this signature in database
GPG Key ID: 21FD3D77D56BAF49
2 changed files with 43 additions and 33 deletions

View File

@ -13,37 +13,41 @@ use axum_extra::extract::{
use serde::Deserialize; use serde::Deserialize;
use tera::Context; use tera::Context;
use crate::db::{Session, User}; use crate::db::{DbError, DbPool, Session, User};
use super::{error::AppError, render_view}; use super::{error::AppError, render_view};
pub fn logged_in_user(pool: &DbPool, headers: &HeaderMap) -> Result<Option<User>, DbError> {
let jar = CookieJar::from_headers(headers);
if let Some(session_id) = jar
.get("session_id")
.and_then(|c| c.value().parse::<u64>().ok())
{
Session::user_from_id(pool, session_id)
} else {
Ok(None)
}
}
pub async fn auth_middleware( pub async fn auth_middleware(
State(ctx): State<crate::Context>, State(ctx): State<crate::Context>,
mut req: Request, mut req: Request,
next: Next, next: Next,
) -> Response { ) -> Response {
let jar = CookieJar::from_headers(req.headers()); match logged_in_user(&ctx.pool, req.headers()) {
Ok(Some(user)) => {
req.extensions_mut().insert(user);
if let Some(session_id) = jar next.run(req).await
.get("session_id")
.and_then(|c| c.value().parse::<u64>().ok())
{
match Session::user_from_id(&ctx.pool, session_id) {
Ok(Some(user)) => {
req.extensions_mut().insert(user);
next.run(req).await
}
Ok(None) => StatusCode::UNAUTHORIZED.into_response(),
Err(err) => AppError::Db(err).into_response(),
} }
} else { Ok(None) => StatusCode::UNAUTHORIZED.into_response(),
StatusCode::UNAUTHORIZED.into_response() Err(err) => AppError::Db(err).into_response(),
} }
} }
pub fn app() -> Router<crate::Context> { pub fn app() -> Router<crate::Context> {
Router::new().route("/login", get(get_login).post(post_login)) Router::new().route("/login", post(post_login))
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -52,23 +56,10 @@ struct Login {
password: String, password: String,
} }
async fn get_login(
State(ctx): State<crate::Context>,
headers: HeaderMap,
) -> Result<Html<String>, AppError> {
let context = Context::new();
Ok(Html(render_view(
&ctx.tera,
"views/login.html",
&context,
&headers,
)?))
}
async fn post_login( async fn post_login(
State(ctx): State<crate::Context>, State(ctx): State<crate::Context>,
jar: CookieJar, jar: CookieJar,
headers: HeaderMap,
Form(login): Form<Login>, Form(login): Form<Login>,
) -> Result<(CookieJar, Html<String>), AppError> { ) -> Result<(CookieJar, Html<String>), AppError> {
if let Some(user) = User::by_username(&ctx.pool, &login.username)? { if let Some(user) = User::by_username(&ctx.pool, &login.username)? {
@ -84,7 +75,7 @@ async fn post_login(
.same_site(SameSite::Lax) .same_site(SameSite::Lax)
.build(), .build(),
), ),
Html(String::new()), super::render_home(ctx, &headers).await?,
)) ))
} else { } else {
Err(AppError::Unauthorized) Err(AppError::Unauthorized)

View File

@ -74,7 +74,7 @@ pub fn app(ctx: crate::Context, static_dir: &str) -> axum::Router {
)) ))
} }
async fn get_index(State(ctx): State<crate::Context>, headers: HeaderMap) -> Result<Html<String>> { pub async fn render_home(ctx: crate::Context, headers: &HeaderMap) -> Result<Html<String>> {
let plants = tokio::task::spawn_blocking(move || Plant::all(&ctx.pool)) let plants = tokio::task::spawn_blocking(move || Plant::all(&ctx.pool))
.await .await
.unwrap()?; .unwrap()?;
@ -85,6 +85,25 @@ async fn get_index(State(ctx): State<crate::Context>, headers: HeaderMap) -> Res
&ctx.tera, &ctx.tera,
"views/index.html", "views/index.html",
&context, &context,
headers,
)?))
}
pub fn render_login(ctx: crate::Context, headers: &HeaderMap) -> Result<Html<String>> {
let context = Context::new();
Ok(Html(render_view(
&ctx.tera,
"views/login.html",
&context,
&headers, &headers,
)?)) )?))
} }
async fn get_index(State(ctx): State<crate::Context>, headers: HeaderMap) -> Result<Html<String>> {
if auth::logged_in_user(&ctx.pool, &headers)?.is_some() {
render_home(ctx, &headers).await
} else {
render_login(ctx, &headers)
}
}