72 lines
1.7 KiB
Rust
72 lines
1.7 KiB
Rust
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<Context> {
|
|
Router::new()
|
|
.route("/{username}/login.json", post(post_login))
|
|
.route("/{username}/logout.json", post(post_logout))
|
|
}
|
|
|
|
async fn post_login(
|
|
State(ctx): State<Context>,
|
|
Path(username): Path<String>,
|
|
jar: CookieJar,
|
|
TypedHeader(auth): TypedHeader<Authorization<Basic>>,
|
|
) -> AppResult<CookieJar> {
|
|
// 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<Context>,
|
|
Path(username): Path<String>,
|
|
jar: CookieJar,
|
|
) -> AppResult<CookieJar> {
|
|
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)
|
|
}
|
|
}
|