preoptimization is the root of all evil, I like evil
This commit is contained in:
parent
3402b67441
commit
72ac29fad7
2 changed files with 64 additions and 15 deletions
|
@ -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
|
||||||
|
sessions.id AS session_id,
|
||||||
|
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)
|
.fetch_optional(pool)
|
||||||
.await?)
|
.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 {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue