use axum::{ extract::{Path, State}, routing::post, Router, }; use axum_extra::{ extract::{ cookie::{Cookie, Expiration}, CookieJar, }, headers::{authorization::Basic, Authorization}, TypedHeader, }; use crate::{ gpodder::AuthRepository, server::{ error::{AppError, AppResult}, gpodder::SESSION_ID_COOKIE, Context, }, }; pub fn router() -> Router { Router::new() .route("/{username}/login.json", post(post_login)) .route("/{username}/logout.json", post(post_logout)) } async fn post_login( State(ctx): State, Path(username): Path, jar: CookieJar, TypedHeader(auth): TypedHeader>, ) -> AppResult { // These should be the same according to the spec if username != auth.username() { return Err(AppError::BadRequest); } let (session_id, _) = tokio::task::spawn_blocking(move || { ctx.repo.create_session(auth.username(), auth.password()) }) .await .unwrap()?; Ok(jar.add( Cookie::build((SESSION_ID_COOKIE, session_id.to_string())).expires(Expiration::Session), )) } async fn post_logout( State(ctx): State, Path(username): Path, jar: CookieJar, ) -> AppResult { if let Some(session_id) = jar.get(SESSION_ID_COOKIE) { let session_id: i64 = session_id .value() .parse() .map_err(|_| AppError::BadRequest)?; tokio::task::spawn_blocking(move || ctx.repo.remove_session(&username, session_id)) .await .unwrap()?; Ok(jar.remove(SESSION_ID_COOKIE)) } else { Ok(jar) } }