preoptimization is the root of all evil, I like evil

This commit is contained in:
Hamcha 2023-07-01 20:52:00 +02:00
parent 3402b67441
commit 72ac29fad7
Signed by: hamcha
GPG key ID: 1669C533B8CF6D89
2 changed files with 64 additions and 15 deletions

View file

@ -67,11 +67,58 @@ impl Session {
}) })
} }
pub async fn find(pool: &Pool<Postgres>, id: Uuid) -> Result<Option<Self>> { pub async fn find(pool: &Pool<Postgres>, session_id: Uuid) -> Result<Option<(Self, User)>> {
Ok(sqlx::query_as("SELECT * FROM sessions WHERE id = $1") let record = sqlx::query!(
.bind(id) "SELECT
.fetch_optional(pool) sessions.id AS session_id,
.await?) sessions.actor AS session_actor,
sessions.secret,
sessions.created_at AS session_created_at,
sessions.expires_at,
users.id AS user_id,
users.name,
users.email,
users.display_name,
users.bio,
users.roles,
users.created_at AS user_created_at,
users.modified_at,
users.deleted_at
FROM
sessions
JOIN
users ON sessions.actor = users.id
WHERE
sessions.id = $1",
session_id
)
.fetch_optional(pool)
.await?;
match record {
None => Ok(None),
Some(record) => Ok(Some((
Self {
id: record.session_id,
actor: record.session_actor,
secret: record.secret,
created_at: record.session_created_at,
expires_at: record.expires_at,
},
User {
id: record.user_id,
name: record.name,
email: record.email,
password: None,
display_name: record.display_name,
bio: record.bio,
roles: record.roles,
created_at: record.user_created_at,
modified_at: record.modified_at,
deleted_at: record.deleted_at,
},
))),
}
} }
pub async fn refresh(self: Self, pool: &Pool<Postgres>, duration: Duration) -> Result<Self> { pub async fn refresh(self: Self, pool: &Pool<Postgres>, duration: Duration) -> Result<Self> {
@ -116,14 +163,16 @@ impl Session {
} }
} }
pub struct RequireSession(pub Session, pub User);
#[async_trait] #[async_trait]
impl FromRequestParts<Arc<AppState>> for Session { impl FromRequestParts<Arc<AppState>> for RequireSession {
type Rejection = AppError<'static>; type Rejection = AppError<'static>;
async fn from_request_parts( async fn from_request_parts(
parts: &mut Parts, parts: &mut Parts,
state: &Arc<AppState>, state: &Arc<AppState>,
) -> Result<Self, Self::Rejection> { ) -> Result<RequireSession, Self::Rejection> {
if let Some(cookie) = parts.headers.get(COOKIE) { if let Some(cookie) = parts.headers.get(COOKIE) {
let cookie_str = cookie.to_str()?; let cookie_str = cookie.to_str()?;
let cookie = Cookie::parse(cookie_str)?; let cookie = Cookie::parse(cookie_str)?;
@ -133,7 +182,7 @@ impl FromRequestParts<Arc<AppState>> for Session {
match Session::find(&state.database, session_id).await? { match Session::find(&state.database, session_id).await? {
None => Err(INVALID_SESSION), None => Err(INVALID_SESSION),
Some(session) => { Some((session, user)) => {
println!("{:?}<{:?}", session.expires_at, Utc::now().naive_utc()); println!("{:?}<{:?}", session.expires_at, Utc::now().naive_utc());
if session.secret != session_secret { if session.secret != session_secret {
return Err(INVALID_SESSION); return Err(INVALID_SESSION);
@ -141,7 +190,7 @@ impl FromRequestParts<Arc<AppState>> for Session {
if session.expires_at < Utc::now().naive_utc() { if session.expires_at < Utc::now().naive_utc() {
return Err(INVALID_SESSION); return Err(INVALID_SESSION);
} }
Ok(session) Ok(RequireSession(session, user))
} }
} }
} else { } else {

View file

@ -11,7 +11,11 @@ use serde_json::json;
use std::sync::Arc; use std::sync::Arc;
use crate::{ use crate::{
auth::{hash::verify, session::Session, user::User}, auth::{
hash::verify,
session::{RequireSession, Session},
user::User,
},
error::AppError, error::AppError,
state::AppState, state::AppState,
}; };
@ -72,10 +76,6 @@ pub async fn login(
Ok(response) Ok(response)
} }
pub async fn me( pub async fn me(RequireSession(_, user): RequireSession) -> Result<String, AppError<'static>> {
State(state): State<Arc<AppState>>,
session: Session,
) -> Result<String, AppError<'static>> {
let user = session.user(&state.database).await?;
Ok(user.name) Ok(user.name)
} }