use glacier::handler::BoxFuture;
use glacier::prelude::*;
use crate::models::{Session, User};
#[derive(Clone)]
pub struct Current {
pub user: User,
pub session: Session,
}
pub fn current_user(ctx: &Context) -> Option<&User> {
ctx.extensions().get::<Current>().map(|current| ¤t.user)
}
pub struct Authentication;
impl Middleware for Authentication {
fn handle(&self, mut ctx: Context, next: Next) -> BoxFuture<Response> {
Box::pin(async move {
let token = glacier::auth::bearer_token(&ctx).map(str::to_owned);
if let Some(token) = token
&& let Ok(Some(session)) = Session::find_by_token(&token).await
&& let Some(user) = session.user.get().cloned()
{
ctx.extensions_mut().insert(Current { user, session });
}
next.run(ctx).await
})
}
}
pub struct RequireAuthentication;
impl Middleware for RequireAuthentication {
fn handle(&self, ctx: Context, next: Next) -> BoxFuture<Response> {
Box::pin(async move {
if ctx.extensions().get::<Current>().is_some() {
return next.run(ctx).await;
}
Error::new(StatusCode::UNAUTHORIZED, "sign in first").into_response()
})
}
}
pub async fn start_session(ctx: &Context, user: &User) -> glacier::Result<String> {
let user_agent = ctx.header("user-agent").map(str::to_owned);
Session::start(user.id, user_agent).await
}
pub async fn end_session(ctx: &Context) -> glacier::Result<()> {
if let Some(current) = ctx.extensions().get::<Current>() {
current.session.clone().destroy().await?;
}
Ok(())
}