update-deps #88

Merged
philipp merged 7 commits from update-deps into staging 2023-11-27 11:59:03 +01:00
10 changed files with 544 additions and 321 deletions

686
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@ rocket = { version = "0.5.0", features = ["secrets"]}
rocket_dyn_templates = {version = "0.1.0", features = [ "tera" ], optional = true } rocket_dyn_templates = {version = "0.1.0", features = [ "tera" ], optional = true }
log = "0.4" log = "0.4"
env_logger = "0.10" env_logger = "0.10"
sqlx = { version = "0.6", features = ["sqlite", "runtime-tokio-rustls", "macros", "chrono", "time"] } sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio-rustls", "macros", "chrono", "time"] }
argon2 = "0.5" argon2 = "0.5"
serde = { version = "1.0", features = [ "derive" ]} serde = { version = "1.0", features = [ "derive" ]}
serde_json = "1.0" serde_json = "1.0"

View File

@ -16,8 +16,9 @@ async fn rocket() -> _ {
env_logger::init(); env_logger::init();
let mut connection_options = SqliteConnectOptions::from_str("sqlite://db.sqlite").unwrap(); let connection_options = SqliteConnectOptions::from_str("sqlite://db.sqlite")
connection_options.log_statements(log::LevelFilter::Debug); .unwrap()
.log_statements(log::LevelFilter::Debug);
let db: SqlitePool = PoolOptions::new() let db: SqlitePool = PoolOptions::new()
.connect_with(connection_options) .connect_with(connection_options)
.await .await

View File

@ -1,3 +1,5 @@
use std::ops::DerefMut;
use rocket::serde::{Deserialize, Serialize}; use rocket::serde::{Deserialize, Serialize};
use rocket::FromForm; use rocket::FromForm;
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
@ -75,7 +77,7 @@ impl Boat {
} }
pub async fn find_by_id_tx(db: &mut Transaction<'_, Sqlite>, id: i32) -> Option<Self> { pub async fn find_by_id_tx(db: &mut Transaction<'_, Sqlite>, id: i32) -> Option<Self> {
sqlx::query_as!(Self, "SELECT * FROM boat WHERE id like ?", id) sqlx::query_as!(Self, "SELECT * FROM boat WHERE id like ?", id)
.fetch_one(db) .fetch_one(db.deref_mut())
.await .await
.ok() .ok()
} }

View File

@ -1,3 +1,5 @@
use std::ops::DerefMut;
use chrono::{DateTime, Local, NaiveDateTime, TimeZone, Utc}; use chrono::{DateTime, Local, NaiveDateTime, TimeZone, Utc};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
@ -17,7 +19,7 @@ impl Log {
} }
pub async fn create_with_tx(db: &mut Transaction<'_, Sqlite>, msg: String) -> bool { pub async fn create_with_tx(db: &mut Transaction<'_, Sqlite>, msg: String) -> bool {
sqlx::query!("INSERT INTO log(msg) VALUES (?)", msg,) sqlx::query!("INSERT INTO log(msg) VALUES (?)", msg,)
.execute(db) .execute(db.deref_mut())
.await .await
.is_ok() .is_ok()
} }

View File

@ -1,3 +1,5 @@
use std::ops::DerefMut;
use chrono::{Datelike, NaiveDateTime, Utc}; use chrono::{Datelike, NaiveDateTime, Utc};
use rocket::FromForm; use rocket::FromForm;
use serde::Serialize; use serde::Serialize;
@ -160,7 +162,7 @@ impl Logbook {
", ",
id id
) )
.fetch_one(db) .fetch_one(db.deref_mut())
.await .await
.ok() .ok()
} }
@ -289,7 +291,7 @@ ORDER BY departure DESC
log.comments, log.comments,
log.logtype log.logtype
) )
.fetch_one(&mut tx) .fetch_one(tx.deref_mut())
.await.unwrap().id; .await.unwrap().id;
let logbook = Logbook::find_by_id_tx(&mut tx, inserted_row as i32) let logbook = Logbook::find_by_id_tx(&mut tx, inserted_row as i32)
@ -363,7 +365,7 @@ ORDER BY departure DESC
log.comments, log.comments,
log.logtype log.logtype
) )
.fetch_one(&mut tx) .fetch_one(tx.deref_mut())
.await.unwrap(); .await.unwrap();
for rower in &log.rowers { for rower in &log.rowers {
@ -398,7 +400,7 @@ ORDER BY departure DESC
async fn remove_rowers(&self, db: &mut Transaction<'_, Sqlite>) { async fn remove_rowers(&self, db: &mut Transaction<'_, Sqlite>) {
sqlx::query!("DELETE FROM rower WHERE logbook_id=?", self.id) sqlx::query!("DELETE FROM rower WHERE logbook_id=?", self.id)
.execute(db) .execute(db.deref_mut())
.await .await
.unwrap(); .unwrap();
} }
@ -495,7 +497,7 @@ ORDER BY departure DESC
log.arrival, log.arrival,
self.id self.id
) )
.execute(db) .execute(db.deref_mut())
.await.unwrap(); //TODO: fixme .await.unwrap(); //TODO: fixme
Ok(()) Ok(())

View File

@ -45,6 +45,59 @@ pub struct Registration {
pub is_real_guest: bool, pub is_real_guest: bool,
} }
impl Registration {
pub async fn all_rower(db: &SqlitePool, trip_details_id: i64) -> Vec<Registration> {
sqlx::query!(
r#"
SELECT
(SELECT name FROM user WHERE user_trip.user_id = user.id) as "name?",
user_note,
user_id,
(SELECT created_at FROM user WHERE user_trip.user_id = user.id) as registered_at,
(SELECT is_guest FROM user WHERE user_trip.user_id = user.id) as is_guest
FROM user_trip WHERE trip_details_id = ?
"#,
trip_details_id,
)
.fetch_all(db)
.await
.unwrap()
.into_iter()
.map(|r| Registration {
name: r.name.or(r.user_note).unwrap(), //Ok, either name or user_note needs to be set
registered_at: r.registered_at,
is_guest: r.is_guest,
is_real_guest: r.user_id == None,
})
.collect()
}
pub async fn all_cox(db: &SqlitePool, trip_details_id: i64) -> Vec<Registration> {
//TODO: switch to join
sqlx::query!(
"
SELECT
(SELECT name FROM user WHERE cox_id = id) as name,
(SELECT created_at FROM user WHERE cox_id = id) as registered_at,
(SELECT is_guest FROM user WHERE cox_id = id) as is_guest
FROM trip WHERE planned_event_id = ?
",
trip_details_id
)
.fetch_all(db)
.await
.unwrap()
.into_iter()
.map(|r| Registration {
name: r.name,
registered_at: r.registered_at,
is_guest: r.is_guest,
is_real_guest: false,
})
.collect() //Okay, as PlannedEvent can only be created with proper DB backing
}
}
impl PlannedEvent { impl PlannedEvent {
pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option<Self> { pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option<Self> {
sqlx::query_as!( sqlx::query_as!(
@ -91,7 +144,7 @@ WHERE day=?",
let mut ret = Vec::new(); let mut ret = Vec::new();
for event in events { for event in events {
let cox = event.get_all_cox(db).await; let cox = Registration::all_cox(db, event.trip_details_id).await;
let mut trip_type = None; let mut trip_type = None;
if let Some(trip_type_id) = event.trip_type_id { if let Some(trip_type_id) = event.trip_type_id {
trip_type = TripType::find_by_id(db, trip_type_id).await; trip_type = TripType::find_by_id(db, trip_type_id).await;
@ -99,7 +152,7 @@ WHERE day=?",
ret.push(PlannedEventWithUserAndTriptype { ret.push(PlannedEventWithUserAndTriptype {
cox_needed: event.planned_amount_cox > cox.len() as i64, cox_needed: event.planned_amount_cox > cox.len() as i64,
cox, cox,
rower: event.get_all_rower(db).await, rower: Registration::all_rower(db, event.trip_details_id).await,
planned_event: event, planned_event: event,
trip_type, trip_type,
}); });
@ -119,61 +172,6 @@ INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id",
.unwrap() //TODO: fixme .unwrap() //TODO: fixme
} }
async fn get_all_cox(&self, db: &SqlitePool) -> Vec<Registration> {
//TODO: switch to join
sqlx::query!(
"
SELECT
(SELECT name FROM user WHERE cox_id = id) as name,
(SELECT created_at FROM user WHERE cox_id = id) as registered_at,
(SELECT is_guest FROM user WHERE cox_id = id) as is_guest,
0 as is_real_guest
FROM trip WHERE planned_event_id = ?
",
self.id
)
.fetch_all(db)
.await
.unwrap()
.into_iter()
.map(|r| Registration {
name: r.name,
registered_at: r.registered_at,
is_guest: r.is_guest,
is_real_guest: r.is_real_guest == 1,
})
.collect() //Okay, as PlannedEvent can only be created with proper DB backing
}
async fn get_all_rower(&self, db: &SqlitePool) -> Vec<Registration> {
//TODO: switch to join
sqlx::query!(
"
SELECT
CASE
WHEN user_id IS NOT NULL THEN (SELECT name FROM user WHERE user_trip.user_id = user.id)
ELSE user_note
END as name,
user_id IS NULL as is_real_guest,
(SELECT created_at FROM user WHERE user_trip.user_id = user.id) as registered_at,
(SELECT is_guest FROM user WHERE user_trip.user_id = user.id) as is_guest
FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM planned_event WHERE id = ?)
",
self.id
)
.fetch_all(db)
.await
.unwrap()
.into_iter()
.map(|r| Registration {
name: r.name.unwrap(),
registered_at: r.registered_at,
is_guest: r.is_guest,
is_real_guest: r.is_real_guest == 1,
})
.collect()
}
//TODO: add tests //TODO: add tests
pub async fn is_rower_registered(&self, db: &SqlitePool, user: &User) -> bool { pub async fn is_rower_registered(&self, db: &SqlitePool, user: &User) -> bool {
let is_rower = sqlx::query!( let is_rower = sqlx::query!(

View File

@ -1,3 +1,5 @@
use std::ops::DerefMut;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
@ -37,7 +39,7 @@ WHERE id in (SELECT rower_id FROM rower WHERE logbook_id=?)
logbook_id, logbook_id,
rower_id rower_id
) )
.execute(db) .execute(db.deref_mut())
.await .await
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;

View File

@ -117,7 +117,7 @@ WHERE day=?
trip_type = TripType::find_by_id(db, trip_type_id).await; trip_type = TripType::find_by_id(db, trip_type_id).await;
} }
ret.push(TripWithUserAndType { ret.push(TripWithUserAndType {
rower: trip.get_all_rower(db).await, rower: Registration::all_rower(db, trip.trip_details_id.unwrap()).await,
trip, trip,
trip_type, trip_type,
}); });
@ -125,33 +125,6 @@ WHERE day=?
ret ret
} }
async fn get_all_rower(&self, db: &SqlitePool) -> Vec<Registration> {
sqlx::query!(
"
SELECT
CASE
WHEN user_id IS NOT NULL THEN (SELECT name FROM user WHERE user_trip.user_id = user.id)
ELSE user_note
END as name,
user_id IS NULL as is_real_guest,
(SELECT created_at FROM user WHERE user_trip.user_id = user.id) as registered_at,
(SELECT is_guest FROM user WHERE user_trip.user_id = user.id) as is_guest
FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM trip WHERE id = ?)",
self.id
)
.fetch_all(db)
.await
.unwrap()
.into_iter()
.map(|r| Registration {
name: r.name.unwrap(),
registered_at: r.registered_at,
is_guest: r.is_guest,
is_real_guest: r.is_real_guest == 1,
})
.collect()
}
/// Cox decides to update own trip. /// Cox decides to update own trip.
pub async fn update_own( pub async fn update_own(
db: &SqlitePool, db: &SqlitePool,
@ -232,7 +205,7 @@ FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM trip WHERE i
db: &SqlitePool, db: &SqlitePool,
user: &CoxUser, user: &CoxUser,
) -> Result<(), TripDeleteError> { ) -> Result<(), TripDeleteError> {
let registered_rower = self.get_all_rower(db).await; let registered_rower = Registration::all_rower(db, self.trip_details_id.unwrap()).await;
if !registered_rower.is_empty() { if !registered_rower.is_empty() {
return Err(TripDeleteError::SomebodyAlreadyRegistered); return Err(TripDeleteError::SomebodyAlreadyRegistered);
} }

View File

@ -1,4 +1,4 @@
use std::ops::Deref; use std::ops::{Deref, DerefMut};
use argon2::{password_hash::SaltString, Argon2, PasswordHasher}; use argon2::{password_hash::SaltString, Argon2, PasswordHasher};
use chrono::{Datelike, Local, NaiveDate}; use chrono::{Datelike, Local, NaiveDate};
@ -89,7 +89,6 @@ impl User {
.await .await
.unwrap() .unwrap()
.rowed_km .rowed_km
.unwrap()
} }
pub async fn find_by_id(db: &SqlitePool, id: i32) -> Option<Self> { pub async fn find_by_id(db: &SqlitePool, id: i32) -> Option<Self> {
@ -117,7 +116,7 @@ WHERE id like ?
", ",
id id
) )
.fetch_one(db) .fetch_one(db.deref_mut())
.await .await
.ok() .ok()
} }