refactor and implement user

This commit is contained in:
2023-08-29 21:34:00 +02:00
parent 57f97b0b7d
commit efcac1edc0
9 changed files with 1509 additions and 1344 deletions

View File

@@ -1,5 +1,175 @@
mod error;
mod models;
mod sqlite;
use axum::{extract::State, http::header::HeaderValue, middleware::Next, response::IntoResponse};
use error::{Error, RequestError, StartError};
use hyper::Request;
use uuid::Uuid;
use std::fmt;
pub mod error;
pub mod models;
pub mod routing;
pub mod sqlite;
mod html;
mod view;
pub use error::{Error, RequestError, StartError};
#[derive(Clone)]
pub enum AuthConfig {
Enabled,
Disabled { assume_user: String },
}
#[derive(Clone)]
pub struct AppState {
pub database_pool: sqlite::Pool<sqlite::Sqlite>,
pub client_state: ClientState,
pub auth_config: AuthConfig,
}
#[derive(Clone)]
pub struct Context {
user: models::user::User,
}
impl Context {
fn build(user: models::user::User) -> Self {
Self { user }
}
}
#[derive(Clone)]
pub struct ClientState {
pub active_category_id: Option<Uuid>,
pub edit_item: Option<Uuid>,
pub trip_edit_attribute: Option<models::trips::TripAttribute>,
pub trip_type_edit: Option<Uuid>,
}
impl ClientState {
pub fn new() -> Self {
ClientState {
active_category_id: None,
edit_item: None,
trip_edit_attribute: None,
trip_type_edit: None,
}
}
}
impl Default for ClientState {
fn default() -> Self {
Self::new()
}
}
struct UriPath(String);
impl fmt::Display for UriPath {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl<'a> Into<&'a str> for &'a UriPath {
fn into(self) -> &'a str {
self.0.as_str()
}
}
#[derive(PartialEq, Eq)]
pub enum TopLevelPage {
Inventory,
Trips,
}
impl TopLevelPage {
fn id(&self) -> &'static str {
match self {
Self::Inventory => "inventory",
Self::Trips => "trips",
}
}
fn path(&self) -> UriPath {
UriPath(
match self {
Self::Inventory => "/inventory/",
Self::Trips => "/trips/",
}
.to_string(),
)
}
fn name(&self) -> &'static str {
match self {
Self::Inventory => "Inventory",
Self::Trips => "Trips",
}
}
}
enum HtmxEvents {
TripItemEdited,
}
impl From<HtmxEvents> for HeaderValue {
fn from(val: HtmxEvents) -> Self {
HeaderValue::from_static(val.to_str())
}
}
impl HtmxEvents {
fn to_str(&self) -> &'static str {
match self {
Self::TripItemEdited => "TripItemEdited",
}
}
}
async fn authorize<B>(
State(state): State<AppState>,
mut request: Request<B>,
next: Next<B>,
) -> Result<impl IntoResponse, Error> {
let current_user = match state.auth_config {
AuthConfig::Disabled { assume_user } => {
match models::user::User::find_by_name(&state.database_pool, &assume_user).await? {
Some(user) => user,
None => {
return Err(Error::Request(RequestError::AuthenticationUserNotFound {
username: assume_user,
}))
}
}
}
AuthConfig::Enabled => {
let Some(username) = request.headers().get("x-auth-username") else {
return Err(Error::Request(RequestError::AuthenticationHeaderMissing));
};
let username = username
.to_str()
.map_err(|error| {
Error::Request(RequestError::AuthenticationHeaderInvalid {
message: error.to_string(),
})
})?
.to_string();
match models::user::User::find_by_name(&state.database_pool, &username).await? {
Some(user) => user,
None => {
return Err(Error::Request(RequestError::AuthenticationUserNotFound {
username,
}))
}
}
}
};
request.extensions_mut().insert(current_user);
Ok(next.run(request).await)
}