Skip to content

Commit

Permalink
Add session middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
manuelmauro committed Mar 13, 2024
1 parent e9ae2f4 commit 797aac7
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 127 deletions.
2 changes: 1 addition & 1 deletion src/app/extractor/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pub mod authorization_header;
pub mod session_cookie;
pub mod session_user;
91 changes: 0 additions & 91 deletions src/app/extractor/session_cookie.rs

This file was deleted.

33 changes: 33 additions & 0 deletions src/app/extractor/session_user.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use axum::{
async_trait,
extract::FromRequestParts,
http::{self, request::Parts, StatusCode},
};
use serde::{Deserialize, Serialize};
use tower_sessions::Session;

const USER_ID: &str = "user_id";

#[derive(Debug, Default, Deserialize, Serialize)]
pub struct SessionUser {
pub id: String,
}

#[async_trait]
impl<S> FromRequestParts<S> for SessionUser
where
S: Send + Sync,
{
type Rejection = (http::StatusCode, &'static str);

async fn from_request_parts(req: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
let session = Session::from_request_parts(req, state).await?;
let user_id: String = session
.get(USER_ID)
.await
.unwrap()
.ok_or((StatusCode::UNAUTHORIZED, "User not authenticated"))?;

Ok(SessionUser { id: user_id })
}
}
19 changes: 13 additions & 6 deletions src/app/session_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::fmt::Debug;
use async_trait::async_trait;
use bb8_redis::RedisConnectionManager;
use redis::AsyncCommands;
use time::OffsetDateTime;
use tower_sessions::{
session::{Id, Record},
session_store, SessionStore,
Expand Down Expand Up @@ -52,11 +53,6 @@ impl RedisStore<bb8::Pool<RedisConnectionManager>> {
#[async_trait]
impl SessionStore for RedisStore<bb8::Pool<RedisConnectionManager>> {
async fn save(&self, record: &Record) -> session_store::Result<()> {
// TODO: Implement expiration
// let expire = Some(Expiration::EXAT(OffsetDateTime::unix_timestamp(
// record.expiry_date,
// )));

self.client
.get()
.await
Expand All @@ -70,6 +66,17 @@ impl SessionStore for RedisStore<bb8::Pool<RedisConnectionManager>> {
.await
.map_err(RedisStoreError::Redis)?;

self.client
.get()
.await
.unwrap()
.expire_at(
record.id.to_string(),
OffsetDateTime::unix_timestamp(record.expiry_date),
)
.await
.map_err(RedisStoreError::Redis)?;

Ok(())
}

Expand All @@ -81,7 +88,7 @@ impl SessionStore for RedisStore<bb8::Pool<RedisConnectionManager>> {
.unwrap()
.get::<String, Option<Vec<u8>>>(session_id.to_string())
.await
.map_err(|e| RedisStoreError::Redis(e))?;
.map_err(RedisStoreError::Redis)?;

if let Some(data) = data {
Ok(Some(
Expand Down
16 changes: 10 additions & 6 deletions src/app/ui/admin/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ use axum::{
response::{IntoResponse, Redirect},
};

use crate::app::extractor::session_cookie::SessionCookie;
use crate::app::extractor::session_user::SessionUser;

#[derive(Template)]
#[template(path = "admin_dashboard.html")]
struct AdminDashboardTemplate;
struct AdminDashboardTemplate {
user: String,
}

#[tracing::instrument(name = "Admin dashboard", skip(cookie))]
pub async fn admin_dashboard(cookie: Option<SessionCookie>) -> impl IntoResponse {
if let Some(_session) = cookie {
#[tracing::instrument(name = "Admin dashboard", skip(session))]
pub async fn admin_dashboard(session: Option<SessionUser>) -> impl IntoResponse {
if let Some(user) = session {
Response::builder()
.status(StatusCode::OK)
.body(Body::from(AdminDashboardTemplate.render().unwrap()))
.body(Body::from(
AdminDashboardTemplate { user: user.id }.render().unwrap(),
))
.unwrap()
} else {
Redirect::temporary("/login").into_response()
Expand Down
41 changes: 19 additions & 22 deletions src/app/ui/login/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@ use axum::{
response::IntoResponse,
Json,
};
use axum_extra::extract::{cookie::Cookie, PrivateCookieJar};
use secrecy::Secret;
use tower_sessions::Session;

use super::schema;
use crate::app::{
api::user::auth::{validate_credentials, Credentials},
extractor::authorization_header::ApiToken,
AppState,
};

Expand All @@ -31,14 +30,14 @@ pub async fn login_form() -> impl IntoResponse {

#[tracing::instrument(
name = "Login",
skip(jar, state, body),
skip(session, state, body),
fields(username=tracing::field::Empty, user_id=tracing::field::Empty)
)]
pub async fn login(
jar: PrivateCookieJar,
session: Session,
State(state): State<AppState>,
Json(body): Json<schema::LoginRequestBody>,
) -> (PrivateCookieJar, impl IntoResponse) {
) -> impl IntoResponse {
let credentials = Credentials {
username: body.username,
password: Secret::new(body.password),
Expand All @@ -47,25 +46,23 @@ pub async fn login(

match validate_credentials(credentials, &state.db).await {
Ok(user_id) => {
let updated_jar = jar.add(Cookie::new("session", ApiToken { user_id }.to_jwt(&state)));
session.insert("user_id", user_id).await.unwrap();
session.cycle_id().await.unwrap();
session.save().await.unwrap();

tracing::Span::current().record("user_id", &tracing::field::display(&user_id));
(
updated_jar,
Response::builder()
.status(StatusCode::OK)
.header("HX-Redirect", "/app")
.body(Body::empty())
.unwrap(),
)
}
Err(_) => (
jar,

Response::builder()
.status(StatusCode::OK)
.body(Body::from(
IncorrectUsernameOrPasswordTemplate.render().unwrap(),
))
.unwrap(),
),
.header("HX-Redirect", "/app")
.body(Body::empty())
.unwrap()
}
Err(_) => Response::builder()
.status(StatusCode::OK)
.body(Body::from(
IncorrectUsernameOrPasswordTemplate.render().unwrap(),
))
.unwrap(),
}
}
2 changes: 1 addition & 1 deletion templates/admin_dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ <h1 class="text-3xl font-bold tracking-tight text-gray-900">Newsletter</h1>
<main>
<div class="mx-auto max-w-7xl py-6 sm:px-6 lg:px-8">
<!-- Your content -->
<p>Welcome to our newsletter!</p>
<p>Hi {{ user }}! Welcome to our newsletter!</p>
</div>
</main>
</div>
Expand Down

0 comments on commit 797aac7

Please sign in to comment.