feat: implement auth middleware
This commit is contained in:
parent
a65b647f65
commit
df741c931b
8 changed files with 211 additions and 6 deletions
|
|
@ -1,6 +1,7 @@
|
|||
mod comment;
|
||||
mod event;
|
||||
mod plant;
|
||||
mod session;
|
||||
mod user;
|
||||
|
||||
use r2d2_sqlite::{rusqlite, SqliteConnectionManager};
|
||||
|
|
@ -10,6 +11,8 @@ use std::{error::Error, fmt};
|
|||
pub use comment::{Comment, NewComment};
|
||||
pub use event::{Event, EventType, NewEvent, EVENT_TYPES};
|
||||
pub use plant::{NewPlant, Plant};
|
||||
pub use session::Session;
|
||||
pub use user::{NewUser, User};
|
||||
|
||||
pub type DbPool = r2d2::Pool<SqliteConnectionManager>;
|
||||
|
||||
|
|
|
|||
19
src/db/session.rs
Normal file
19
src/db/session.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
use super::{DbError, DbPool, User};
|
||||
|
||||
pub struct Session {
|
||||
id: u64,
|
||||
user_id: i32,
|
||||
}
|
||||
|
||||
impl Session {
|
||||
pub fn user_from_id(pool: &DbPool, id: u64) -> Result<Option<super::User>, DbError> {
|
||||
let conn = pool.get()?;
|
||||
|
||||
let mut stmt = conn.prepare("select users.* from sessions inner join users on sessions.user_id = users.id where sessions.id = $1")?;
|
||||
match stmt.query_row((id,), User::from_row) {
|
||||
Ok(user) => Ok(Some(user)),
|
||||
Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),
|
||||
Err(err) => Err(DbError::Db(err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use super::{DbError, DbPool};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct User {
|
||||
id: i32,
|
||||
username: String,
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@ use r2d2_sqlite::SqliteConnectionManager;
|
|||
use tera::Tera;
|
||||
use tower_http::compression::CompressionLayer;
|
||||
|
||||
const MIGRATIONS: [&str; 4] = [
|
||||
const MIGRATIONS: [&str; 5] = [
|
||||
include_str!("migrations/000_initial.sql"),
|
||||
include_str!("migrations/001_plants.sql"),
|
||||
include_str!("migrations/002_comments.sql"),
|
||||
include_str!("migrations/003_events.sql"),
|
||||
include_str!("migrations/004_auth.sql"),
|
||||
];
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
|
|||
36
src/server/auth.rs
Normal file
36
src/server/auth.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
use axum::{
|
||||
extract::{Request, State},
|
||||
http::StatusCode,
|
||||
middleware::Next,
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use axum_extra::extract::CookieJar;
|
||||
|
||||
use crate::db::Session;
|
||||
|
||||
use super::error::AppError;
|
||||
|
||||
pub async fn auth_middleware(
|
||||
State(ctx): State<crate::Context>,
|
||||
mut req: Request,
|
||||
next: Next,
|
||||
) -> Response {
|
||||
let jar = CookieJar::from_headers(req.headers());
|
||||
|
||||
if let Some(session_id) = jar
|
||||
.get("session_id")
|
||||
.and_then(|c| c.value().parse::<u64>().ok())
|
||||
{
|
||||
match Session::user_from_id(&ctx.pool, session_id) {
|
||||
Ok(Some(user)) => {
|
||||
req.extensions_mut().insert(user);
|
||||
|
||||
next.run(req).await
|
||||
}
|
||||
Ok(None) => StatusCode::UNAUTHORIZED.into_response(),
|
||||
Err(err) => AppError::Db(err).into_response(),
|
||||
}
|
||||
} else {
|
||||
StatusCode::UNAUTHORIZED.into_response()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
mod auth;
|
||||
mod comments;
|
||||
mod error;
|
||||
mod events;
|
||||
|
|
@ -6,6 +7,7 @@ mod plants;
|
|||
use axum::{
|
||||
extract::State,
|
||||
http::{header::VARY, HeaderMap, HeaderValue},
|
||||
middleware,
|
||||
response::Html,
|
||||
routing::get,
|
||||
Router,
|
||||
|
|
@ -50,10 +52,14 @@ pub fn render_view(
|
|||
|
||||
pub fn app(ctx: crate::Context, static_dir: &str) -> axum::Router {
|
||||
let router = Router::new()
|
||||
.route("/", get(get_index))
|
||||
.nest("/plants", plants::app())
|
||||
.nest("/comments", comments::app())
|
||||
.nest("/events", events::app())
|
||||
.layer(middleware::from_fn_with_state(
|
||||
ctx.clone(),
|
||||
auth::auth_middleware,
|
||||
))
|
||||
.route("/", get(get_index))
|
||||
.nest_service("/static", ServeDir::new(static_dir))
|
||||
.with_state(ctx.clone());
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue