This commit is contained in:
2023-08-29 21:34:01 +02:00
parent ec6b6090fc
commit 5eee5309ad
13 changed files with 66 additions and 75 deletions

View File

@@ -6,7 +6,7 @@ use super::models;
use super::{AppState, Error, RequestError};
#[derive(Clone)]
pub enum AuthConfig {
pub enum Config {
Enabled,
Disabled { assume_user: String },
}
@@ -17,7 +17,7 @@ pub async fn authorize<B>(
next: Next<B>,
) -> Result<impl IntoResponse, Error> {
let current_user = match state.auth_config {
AuthConfig::Disabled { assume_user } => {
Config::Disabled { assume_user } => {
match models::user::User::find_by_name(&state.database_pool, &assume_user).await? {
Some(user) => user,
None => {
@@ -27,7 +27,7 @@ pub async fn authorize<B>(
}
}
}
AuthConfig::Enabled => {
Config::Enabled => {
let Some(username) = request.headers().get("x-auth-username") else {
return Err(Error::Request(RequestError::AuthenticationHeaderMissing));
};

View File

@@ -88,7 +88,7 @@ impl IntoResponse for Error {
Self::Model(ref model_error) => match model_error {
models::Error::Database(_) => (
StatusCode::INTERNAL_SERVER_ERROR,
view::ErrorPage::build(&format!("{}", self)),
view::ErrorPage::build(&self.to_string()),
),
models::Error::Query(error) => match error {
models::QueryError::NotFound { description } => {
@@ -96,7 +96,7 @@ impl IntoResponse for Error {
}
_ => (
StatusCode::BAD_REQUEST,
view::ErrorPage::build(&format!("{}", error)),
view::ErrorPage::build(&error.to_string()),
),
},
},
@@ -107,25 +107,22 @@ impl IntoResponse for Error {
),
RequestError::RefererInvalid { message } => (
StatusCode::BAD_REQUEST,
view::ErrorPage::build(&format!("referer could not be converted: {}", message)),
view::ErrorPage::build(&format!("referer could not be converted: {message}")),
),
RequestError::EmptyFormElement { name } => (
StatusCode::UNPROCESSABLE_ENTITY,
view::ErrorPage::build(&format!("empty form element: {}", name)),
view::ErrorPage::build(&format!("empty form element: {name}")),
),
RequestError::NotFound { message } => (
StatusCode::NOT_FOUND,
view::ErrorPage::build(&format!("not found: {}", message)),
view::ErrorPage::build(&format!("not found: {message}")),
),
RequestError::AuthenticationUserNotFound { username: _ } => (
StatusCode::BAD_REQUEST,
view::ErrorPage::build(&request_error.to_string()),
),
RequestError::AuthenticationHeaderMissing => (
StatusCode::UNAUTHORIZED,
view::ErrorPage::build(&request_error.to_string()),
),
RequestError::AuthenticationHeaderInvalid { message: _ } => (
RequestError::AuthenticationHeaderMissing
| RequestError::AuthenticationHeaderInvalid { message: _ } => (
StatusCode::UNAUTHORIZED,
view::ErrorPage::build(&request_error.to_string()),
),

View File

@@ -47,6 +47,5 @@ impl From<RequestHeaders> for HeaderName {
pub fn is_htmx(headers: &HeaderMap) -> bool {
headers
.get::<HeaderName>(RequestHeaders::HtmxRequest.into())
.map(|value| value == "true")
.unwrap_or(false)
.map_or(false, |value| value == "true")
}

View File

@@ -17,7 +17,7 @@ pub use error::{CommandError, Error, RequestError, StartError};
pub struct AppState {
pub database_pool: sqlite::Pool<sqlite::Sqlite>,
pub client_state: ClientState,
pub auth_config: auth::AuthConfig,
pub auth_config: auth::Config,
}
#[derive(Clone)]
@@ -64,9 +64,9 @@ impl fmt::Display for UriPath {
}
}
impl<'a> From<&'a UriPath> for &'a str {
fn from(val: &'a UriPath) -> Self {
val.0.as_str()
impl<'a> Into<&'a str> for &'a UriPath {
fn into(self) -> &'a str {
self.0.as_str()
}
}

View File

@@ -95,9 +95,9 @@ async fn main() -> MainResult {
database_pool,
client_state: ClientState::new(),
auth_config: if let Some(assume_user) = serve_args.disable_auth_and_assume_user {
auth::AuthConfig::Disabled { assume_user }
auth::Config::Disabled { assume_user }
} else {
auth::AuthConfig::Enabled
auth::Config::Enabled
},
};

View File

@@ -77,8 +77,8 @@ pub enum Error {
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Database(error) => write!(f, "{}", error),
Self::Query(error) => write!(f, "{}", error),
Self::Database(error) => write!(f, "{error}"),
Self::Query(error) => write!(f, "{error}"),
}
}
}
@@ -125,23 +125,17 @@ impl From<sqlx::Error> for Error {
description: "item with unique constraint already exists".to_string(),
}),
_ => Error::Database(DatabaseError::Sql {
description: format!(
"got error with unknown code: {}",
sqlite_error
),
description: format!("got error with unknown code: {sqlite_error}"),
}),
}
} else {
Error::Database(DatabaseError::Sql {
description: format!(
"got error without code: {}",
sqlite_error
),
description: format!("got error without code: {sqlite_error}"),
})
}
}
_ => Error::Database(DatabaseError::Sql {
description: format!("got unknown error: {}", value),
description: format!("got unknown error: {value}"),
}),
}
}

View File

@@ -29,7 +29,7 @@ impl Inventory {
.collect::<Result<Vec<Category>, Error>>()?;
for category in &mut categories {
category.populate_items(ctx, pool).await?;
category.populate_items(&ctx, &pool).await?;
}
Ok(Self { categories })
@@ -384,7 +384,7 @@ impl InventoryItem {
.map_ok(|row| {
// convert to i64 because that the default integer type, but looks
// like COALESCE return i32?
row.weight as i64
i64::from(row.weight)
})
.await?;
@@ -451,7 +451,7 @@ impl Item {
.map_ok(|row| {
// convert to i64 because that the default integer type, but looks
// like COALESCE return i32?
row.weight as i64
i64::from(row.weight)
})
.await?)
}

View File

@@ -199,7 +199,7 @@ impl TripCategory {
items: None,
},
items: None,
})
});
}
};
@@ -245,6 +245,7 @@ impl TripCategory {
}
}
// TODO refactor the bools into an enum
#[derive(Debug)]
pub struct TripItem {
pub item: inventory::Item,
@@ -673,7 +674,7 @@ impl Trip {
user_id,
)
.fetch_one(pool)
.map_ok(|row| row.total_weight.unwrap() as i64)
.map_ok(|row| i64::from(row.total_weight.unwrap()))
.await?;
Ok(weight)

View File

@@ -1,5 +1,5 @@
use maud::{html, Markup};
pub fn concat(a: Markup, b: Markup) -> Markup {
pub fn concat(a: &Markup, b: &Markup) -> Markup {
html!((a)(b))
}

View File

@@ -113,15 +113,13 @@ pub async fn icon() -> impl IntoResponse {
}
pub async fn debug(headers: HeaderMap) -> impl IntoResponse {
{
let mut out = String::new();
for (key, value) in headers.iter() {
out.push_str(&format!("{}: {}\n", key, value.to_str().unwrap()));
}
out
let mut out = String::new();
for (key, value) in headers.iter() {
out.push_str(&format!("{}: {}\n", key, value.to_str().unwrap()));
}
out
}
pub async fn inventory_active(
Extension(current_user): Extension<models::user::User>,
State(mut state): State<AppState>,
@@ -255,12 +253,12 @@ pub async fn inventory_item_delete(
let ctx = Context::build(current_user);
let deleted = models::inventory::InventoryItem::delete(&ctx, &state.database_pool, id).await?;
if !deleted {
if deleted {
Ok(Redirect::to(get_referer(&headers)?))
} else {
Err(Error::Request(RequestError::NotFound {
message: format!("item with id {id} not found"),
}))
} else {
Ok(Redirect::to(get_referer(&headers)?))
}
}
@@ -286,7 +284,7 @@ pub async fn inventory_item_edit(
)
.await?;
Ok(Redirect::to(&format!("/inventory/category/{id}/", id = id)))
Ok(Redirect::to(&format!("/inventory/category/{id}/")))
}
pub async fn inventory_item_cancel(
@@ -385,7 +383,7 @@ pub async fn trip(
&ctx,
&view::trip::Trip::build(
&trip,
state.client_state.trip_edit_attribute,
state.client_state.trip_edit_attribute.as_ref(),
active_category,
),
Some(&TopLevelPage::Trips),
@@ -401,12 +399,12 @@ pub async fn trip_type_remove(
let found =
models::trips::Trip::trip_type_remove(&ctx, &state.database_pool, trip_id, type_id).await?;
if !found {
if found {
Ok(Redirect::to(&format!("/trips/{trip_id}/")))
} else {
Err(Error::Request(RequestError::NotFound {
message: format!("type {type_id} is not active for trip {trip_id}"),
}))
} else {
Ok(Redirect::to(&format!("/trips/{trip_id}/")))
}
}
@@ -441,7 +439,7 @@ pub async fn trip_comment_set(
message: format!("trip with id {trip_id} not found"),
}))
} else {
Ok(Redirect::to(&format!("/trips/{id}/", id = trip_id)))
Ok(Redirect::to(&format!("/trips/{trip_id}/")))
}
}
@@ -452,10 +450,12 @@ pub async fn trip_edit_attribute(
Form(trip_update): Form<TripUpdate>,
) -> Result<Redirect, Error> {
let ctx = Context::build(current_user);
if attribute == models::trips::TripAttribute::Name && trip_update.new_value.is_empty() {
return Err(Error::Request(RequestError::EmptyFormElement {
name: "name".to_string(),
}));
if attribute == models::trips::TripAttribute::Name {
if trip_update.new_value.is_empty() {
return Err(Error::Request(RequestError::EmptyFormElement {
name: "name".to_string(),
}));
}
}
models::trips::Trip::set_attribute(
&ctx,
@@ -477,7 +477,7 @@ pub async fn trip_item_set_state(
key: models::trips::TripItemStateKey,
value: bool,
) -> Result<(), Error> {
models::trips::TripItem::set_state(ctx, &state.database_pool, trip_id, item_id, key, value)
models::trips::TripItem::set_state(&ctx, &state.database_pool, trip_id, item_id, key, value)
.await?;
Ok(())
}
@@ -500,7 +500,7 @@ pub async fn trip_row(
trip_id,
&item,
models::inventory::InventoryItem::get_category_max_weight(
ctx,
&ctx,
&state.database_pool,
item.item.category_id,
)
@@ -523,7 +523,7 @@ pub async fn trip_row(
// TODO biggest_category_weight?
let category_row = view::trip::TripCategoryListRow::build(trip_id, &category, true, 0, true);
Ok(html::concat(item_row, category_row))
Ok(html::concat(&item_row, &category_row))
}
pub async fn trip_item_set_pick(
@@ -841,7 +841,7 @@ pub async fn trip_state_set(
if htmx::is_htmx(&headers) {
Ok(view::trip::TripInfoStateRow::build(&new_state).into_response())
} else {
Ok(Redirect::to(&format!("/trips/{id}/", id = trip_id)).into_response())
Ok(Redirect::to(&format!("/trips/{trip_id}/")).into_response())
}
}
pub async fn trips_types(
@@ -899,12 +899,12 @@ pub async fn trips_types_edit_name(
)
.await?;
if !exists {
if exists {
Ok(Redirect::to("/trips/types/"))
} else {
Err(Error::Request(RequestError::NotFound {
message: format!("trip type with id {trip_type_id} not found"),
}))
} else {
Ok(Redirect::to("/trips/types/"))
}
}

View File

@@ -570,7 +570,7 @@ impl InventoryItem {
}
tr ."h-10" ."even:bg-gray-100" ."hover:bg-gray-100" ."h-full" {
td ."border" ."p-2" { "Description" }
td ."border" ."p-2" { (item.description.clone().unwrap_or("".to_string())) }
td ."border" ."p-2" { (item.description.clone().unwrap_or(String::new())) }
}
tr ."h-10" ."even:bg-gray-100" ."hover:bg-gray-100" ."h-full" {
td ."border" ."p-2" { "Weight" }

View File

@@ -13,7 +13,7 @@ use crate::TopLevelPage;
impl Root {
pub fn build(context: &Context, body: &Markup, active_page: Option<&TopLevelPage>) -> Markup {
let menu_item = |item: TopLevelPage, active_page: Option<&TopLevelPage>| {
let active = active_page.map(|page| *page == item).unwrap_or(false);
let active = active_page.map_or(false, |page| *page == item);
html!(
a
href=(item.path())

View File

@@ -219,7 +219,7 @@ pub struct Trip;
impl Trip {
pub fn build(
trip: &models::trips::Trip,
trip_edit_attribute: Option<models::trips::TripAttribute>,
trip_edit_attribute: Option<&models::trips::TripAttribute>,
active_category: Option<&models::trips::TripCategory>,
) -> Markup {
html!(
@@ -253,7 +253,7 @@ impl Trip {
}
}
div ."flex" ."flex-row" ."items-center" ."gap-x-3" {
@if trip_edit_attribute.as_ref().map_or(false, |a| *a == models::trips::TripAttribute::Name) {
@if trip_edit_attribute.map_or(false, |a| *a == models::trips::TripAttribute::Name) {
form
id="edit-trip"
action=(format!("edit/{}/submit", to_variant_name(&models::trips::TripAttribute::Name).unwrap()))
@@ -597,7 +597,7 @@ pub struct TripInfo;
impl TripInfo {
pub fn build(
trip_edit_attribute: Option<models::trips::TripAttribute>,
trip_edit_attribute: Option<&models::trips::TripAttribute>,
trip: &models::trips::Trip,
) -> Markup {
html!(
@@ -613,31 +613,31 @@ impl TripInfo {
(TripInfoRow::build("Location",
trip.location.as_ref(),
&models::trips::TripAttribute::Location,
trip_edit_attribute.as_ref(),
trip_edit_attribute,
InputType::Text,
))
(TripInfoRow::build("Start date",
Some(trip.date_start),
&models::trips::TripAttribute::DateStart,
trip_edit_attribute.as_ref(),
trip_edit_attribute,
InputType::Date,
))
(TripInfoRow::build("End date",
Some(trip.date_end),
&models::trips::TripAttribute::DateEnd,
trip_edit_attribute.as_ref(),
trip_edit_attribute,
InputType::Date,
))
(TripInfoRow::build("Temp (min)",
trip.temp_min,
&models::trips::TripAttribute::TempMin,
trip_edit_attribute.as_ref(),
trip_edit_attribute,
InputType::Number,
))
(TripInfoRow::build("Temp (max)",
trip.temp_max,
&models::trips::TripAttribute::TempMax,
trip_edit_attribute.as_ref(),
trip_edit_attribute,
InputType::Number,
))
(TripInfoStateRow::build(&trip.state))