Merge branch 'main' of ssh://git.hofer.link:2222/Ruderverein-Donau-Linz/rowt

This commit is contained in:
philipp 2024-03-31 13:07:06 +02:00
commit 974b4aeb48
14 changed files with 231 additions and 119 deletions

118
Cargo.lock generated
View File

@ -174,18 +174,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
] ]
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.78" version = "0.1.79"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
] ]
[[package]] [[package]]
@ -214,15 +214,15 @@ dependencies = [
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.69" version = "0.3.71"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
dependencies = [ dependencies = [
"addr2line", "addr2line",
"cc", "cc",
@ -239,6 +239,12 @@ version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "base64"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51"
[[package]] [[package]]
name = "base64ct" name = "base64ct"
version = "1.6.0" version = "1.6.0"
@ -314,9 +320,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.5.0" version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
[[package]] [[package]]
name = "cc" name = "cc"
@ -332,9 +338,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.35" version = "0.4.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e"
dependencies = [ dependencies = [
"android-tzdata", "android-tzdata",
"iana-time-zone", "iana-time-zone",
@ -402,12 +408,12 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]] [[package]]
name = "cookie" name = "cookie"
version = "0.18.0" version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cd91cf61412820176e137621345ee43b3f4423e589e7ae4e50d601d93e35ef8" checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
dependencies = [ dependencies = [
"aes-gcm", "aes-gcm",
"base64", "base64 0.22.0",
"hkdf", "hkdf",
"percent-encoding", "percent-encoding",
"rand", "rand",
@ -597,7 +603,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"proc-macro2-diagnostics", "proc-macro2-diagnostics",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
] ]
[[package]] [[package]]
@ -629,11 +635,11 @@ dependencies = [
[[package]] [[package]]
name = "email-encoding" name = "email-encoding"
version = "0.2.0" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbfb21b9878cf7a348dcb8559109aabc0ec40d69924bd706fa5149846c4fef75" checksum = "a87260449b06739ee78d6281c68d2a0ff3e3af64a78df63d3a1aeb3c06997c8a"
dependencies = [ dependencies = [
"base64", "base64 0.22.0",
"memchr", "memchr",
] ]
@ -710,9 +716,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "2.0.1" version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984"
[[package]] [[package]]
name = "figment" name = "figment"
@ -863,7 +869,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
] ]
[[package]] [[package]]
@ -962,7 +968,7 @@ dependencies = [
"bstr", "bstr",
"log", "log",
"regex-automata 0.4.6", "regex-automata 0.4.6",
"regex-syntax 0.8.2", "regex-syntax 0.8.3",
] ]
[[package]] [[package]]
@ -1203,9 +1209,9 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.2.5" version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown",
@ -1269,9 +1275,9 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.10" version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]] [[package]]
name = "js-sys" name = "js-sys"
@ -1313,11 +1319,11 @@ dependencies = [
[[package]] [[package]]
name = "lettre" name = "lettre"
version = "0.11.4" version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357ff5edb6d8326473a64c82cf41ddf78ab116f89668c50c4fac1b321e5e80f4" checksum = "8305b122b8ccc64e437b0de101851f9f00aade5886246e85f341c1d9a15a91b7"
dependencies = [ dependencies = [
"base64", "base64 0.22.0",
"chumsky", "chumsky",
"email-encoding", "email-encoding",
"email_address", "email_address",
@ -1653,7 +1659,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
] ]
[[package]] [[package]]
@ -1759,7 +1765,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"proc-macro2-diagnostics", "proc-macro2-diagnostics",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
] ]
[[package]] [[package]]
@ -1808,7 +1814,7 @@ dependencies = [
"pest_meta", "pest_meta",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
] ]
[[package]] [[package]]
@ -1940,7 +1946,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
"version_check", "version_check",
"yansi", "yansi",
] ]
@ -2031,19 +2037,19 @@ checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
] ]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.10.3" version = "1.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
"regex-automata 0.4.6", "regex-automata 0.4.6",
"regex-syntax 0.8.2", "regex-syntax 0.8.3",
] ]
[[package]] [[package]]
@ -2063,7 +2069,7 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
"regex-syntax 0.8.2", "regex-syntax 0.8.3",
] ]
[[package]] [[package]]
@ -2074,9 +2080,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.8.2" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]] [[package]]
name = "ring" name = "ring"
@ -2142,7 +2148,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"rocket_http", "rocket_http",
"syn 2.0.53", "syn 2.0.55",
"unicode-xid", "unicode-xid",
"version_check", "version_check",
] ]
@ -2265,7 +2271,7 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
dependencies = [ dependencies = [
"base64", "base64 0.21.7",
] ]
[[package]] [[package]]
@ -2370,14 +2376,14 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.114" version = "1.0.115"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -2623,7 +2629,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418"
dependencies = [ dependencies = [
"atoi", "atoi",
"base64", "base64 0.21.7",
"bitflags 2.5.0", "bitflags 2.5.0",
"byteorder", "byteorder",
"bytes", "bytes",
@ -2667,7 +2673,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e"
dependencies = [ dependencies = [
"atoi", "atoi",
"base64", "base64 0.21.7",
"bitflags 2.5.0", "bitflags 2.5.0",
"byteorder", "byteorder",
"chrono", "chrono",
@ -2786,9 +2792,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.53" version = "2.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2846,7 +2852,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
] ]
[[package]] [[package]]
@ -2931,7 +2937,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
] ]
[[package]] [[package]]
@ -3019,7 +3025,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
] ]
[[package]] [[package]]
@ -3296,7 +3302,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3318,7 +3324,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3561,7 +3567,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.53", "syn 2.0.55",
] ]
[[package]] [[package]]

View File

@ -7,7 +7,7 @@ test("cox can create and delete trip", async ({ page }) => {
await page.getByPlaceholder("Name").press("Tab"); await page.getByPlaceholder("Name").press("Tab");
await page.getByPlaceholder("Passwort").fill("cox"); await page.getByPlaceholder("Passwort").fill("cox");
await page.getByPlaceholder("Passwort").press("Enter"); await page.getByPlaceholder("Passwort").press("Enter");
await page.locator('a').filter({ hasText: /^Geplante Ausfahrten$/ }).click(); await page.locator('li').filter({ hasText: 'Geplante Ausfahrten' }).getByRole('link').click();
await page.locator(".relative").first().click(); await page.locator(".relative").first().click();
await page.locator("#sidebar #planned_starting_time").click(); await page.locator("#sidebar #planned_starting_time").click();
await page.locator("#sidebar #planned_starting_time").fill("18:00"); await page.locator("#sidebar #planned_starting_time").fill("18:00");
@ -38,7 +38,7 @@ test.describe("cox can edit trips", () => {
await page.getByPlaceholder("Name").press("Tab"); await page.getByPlaceholder("Name").press("Tab");
await page.getByPlaceholder("Passwort").fill("cox"); await page.getByPlaceholder("Passwort").fill("cox");
await page.getByPlaceholder("Passwort").press("Enter"); await page.getByPlaceholder("Passwort").press("Enter");
await page.locator('a').filter({ hasText: /^Geplante Ausfahrten$/ }).click(); await page.locator('li').filter({ hasText: 'Geplante Ausfahrten' }).getByRole('link').click();
await page.locator(".relative").first().click(); await page.locator(".relative").first().click();
await page.locator("#sidebar #planned_starting_time").click(); await page.locator("#sidebar #planned_starting_time").click();
await page.locator("#sidebar #planned_starting_time").fill("18:00"); await page.locator("#sidebar #planned_starting_time").fill("18:00");

View File

@ -5,6 +5,8 @@ use rocket::FromForm;
use sqlx::{FromRow, SqlitePool}; use sqlx::{FromRow, SqlitePool};
use super::log::Log; use super::log::Log;
use super::notification::Notification;
use super::role::Role;
#[derive(FromRow, Debug, Serialize, Deserialize)] #[derive(FromRow, Debug, Serialize, Deserialize)]
pub struct BoatDamage { pub struct BoatDamage {
@ -124,35 +126,125 @@ ORDER BY created_at DESC
.execute(db) .execute(db)
.await .await
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
let technicals =
User::all_with_role(db, &Role::find_by_name(db, "tech").await.unwrap()).await;
for technical in technicals {
if technical.id as i32 != boatdamage.user_id_created {
Notification::create(
db,
&technical,
&format!(
"{} hat einen neuen Bootschaden für Boot '{}' angelegt: {}",
User::find_by_id(db, boatdamage.user_id_created)
.await
.unwrap()
.name,
Boat::find_by_id(db, boatdamage.boat_id as i32)
.await
.unwrap()
.name,
boatdamage.desc
),
"Neuer Bootsschaden angelegt",
None,
)
.await;
}
}
Notification::create(
db,
&User::find_by_id(db, boatdamage.user_id_created)
.await
.unwrap(),
&format!(
"Du hat einen neuen Bootschaden für Boot '{}' angelegt: {}",
Boat::find_by_id(db, boatdamage.boat_id as i32)
.await
.unwrap()
.name,
boatdamage.desc
),
"Neuer Bootsschaden angelegt",
None,
)
.await;
Ok(()) Ok(())
} }
pub async fn fixed(&self, db: &SqlitePool, boat: BoatDamageFixed<'_>) -> Result<(), String> { pub async fn fixed(
Log::create(db, format!("Fixed boat damage: {boat:?}")).await; &self,
db: &SqlitePool,
boat_damage: BoatDamageFixed<'_>,
) -> Result<(), String> {
Log::create(db, format!("Fixed boat damage: {boat_damage:?}")).await;
let boat = Boat::find_by_id(db, self.boat_id as i32).await.unwrap();
sqlx::query!( sqlx::query!(
"UPDATE boat_damage SET desc=?, user_id_fixed=?, fixed_at=CURRENT_TIMESTAMP WHERE id=?", "UPDATE boat_damage SET desc=?, user_id_fixed=?, fixed_at=CURRENT_TIMESTAMP WHERE id=?",
boat.desc, boat_damage.desc,
boat.user_id_fixed, boat_damage.user_id_fixed,
self.id self.id
) )
.execute(db) .execute(db)
.await .await
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
let user = User::find_by_id(db, boat.user_id_fixed).await.unwrap(); let user = User::find_by_id(db, boat_damage.user_id_fixed)
.await
.unwrap();
if user.has_role(db, "tech").await { if user.has_role(db, "tech").await {
return self return self
.verified( .verified(
db, db,
BoatDamageVerified { BoatDamageVerified {
desc: boat.desc, desc: boat_damage.desc,
user_id_verified: user.id as i32, user_id_verified: user.id as i32,
}, },
) )
.await; .await;
} }
let technicals =
User::all_with_role(db, &Role::find_by_name(db, "tech").await.unwrap()).await;
for technical in technicals {
if technical.id as i32 != boat_damage.user_id_fixed {
Notification::create(
db,
&technical,
&format!(
"{} hat den Bootschaden '{}' beim Boot '{}' repariert. Könntest du das bei Gelegenheit verifizieren?",
User::find_by_id(db, boat_damage.user_id_fixed)
.await
.unwrap()
.name,
boat_damage.desc,
boat.name,
),
"Bootsschaden repariert",
None,
)
.await;
}
}
Notification::create(
db,
&User::find_by_id(db, boat_damage.user_id_fixed)
.await
.unwrap(),
&format!(
"Du hat den Bootschaden '{}' beim Boot '{}' repariert. Danke für deine Hilfe!",
boat_damage.desc, boat.name,
),
"Bootsschaden repariert",
None,
)
.await;
Ok(()) Ok(())
} }

View File

@ -75,7 +75,7 @@ GROUP BY family.id;"
} }
pub async fn members(&self, db: &SqlitePool) -> Vec<User> { pub async fn members(&self, db: &SqlitePool) -> Vec<User> {
sqlx::query_as!(User, "SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, membership_pdf FROM user WHERE family_id = ?", self.id) sqlx::query_as!(User, "SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id FROM user WHERE family_id = ?", self.id)
.fetch_all(db) .fetch_all(db)
.await .await
.unwrap() .unwrap()

View File

@ -531,7 +531,7 @@ ORDER BY departure DESC
db, db,
&user, &user,
&format!( &format!(
"Ausfahrt am {}.{}.{} nach {} ({} km)", "Ausfahrt am {}.{}.{}; Ziel: {} ({} km)",
dep.day(), dep.day(),
dep.month(), dep.month(),
dep.year(), dep.year(),

View File

@ -58,7 +58,7 @@ impl Notification {
pub async fn for_user(db: &SqlitePool, user: &User) -> Vec<Self> { pub async fn for_user(db: &SqlitePool, user: &User) -> Vec<Self> {
sqlx::query_as!( sqlx::query_as!(
Self, Self,
"SELECT * FROM notification WHERE user_id = ?", "SELECT * FROM notification WHERE user_id = ? ORDER BY created_at DESC",
user.id user.id
) )
.fetch_all(db) .fetch_all(db)

View File

@ -16,7 +16,7 @@ impl Rower {
sqlx::query_as!( sqlx::query_as!(
User, User,
" "
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, membership_pdf SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id
FROM user FROM user
WHERE id in (SELECT rower_id FROM rower WHERE logbook_id=?) WHERE id in (SELECT rower_id FROM rower WHERE logbook_id=?)
", ",

View File

@ -138,7 +138,7 @@ ORDER BY day;",
pub(crate) async fn user_allowed_to_change(&self, db: &SqlitePool, user: &User) -> bool { pub(crate) async fn user_allowed_to_change(&self, db: &SqlitePool, user: &User) -> bool {
if self.belongs_to_event(db).await { if self.belongs_to_event(db).await {
user.has_role(db, "admin").await user.has_role(db, "planned_event").await
} else { } else {
self.user_is_cox(db, user).await != CoxAtTrip::No self.user_is_cox(db, user).await != CoxAtTrip::No
} }

View File

@ -26,7 +26,7 @@ const REGULAR: i32 = 22000;
const UNTERSTUETZEND: i32 = 2500; const UNTERSTUETZEND: i32 = 2500;
const FOERDERND: i32 = 8500; const FOERDERND: i32 = 8500;
#[derive(FromRow, Serialize, Deserialize, Clone)] #[derive(FromRow, Serialize, Deserialize, Clone, Debug)]
pub struct User { pub struct User {
pub id: i64, pub id: i64,
pub name: String, pub name: String,
@ -44,30 +44,6 @@ pub struct User {
pub phone: Option<String>, pub phone: Option<String>,
pub address: Option<String>, pub address: Option<String>,
pub family_id: Option<i64>, pub family_id: Option<i64>,
pub membership_pdf: Option<Vec<u8>>,
}
impl std::fmt::Debug for User {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("User")
.field("id", &self.id)
.field("name", &self.name)
.field("dob", &self.dob)
.field("weight", &self.weight)
.field("sex", &self.sex)
.field("deleted", &self.deleted)
.field("last_access", &self.last_access)
.field("member_since_date", &self.member_since_date)
.field("birthdate", &self.birthdate)
.field("mail", &self.mail)
.field("nickname", &self.nickname)
.field("notes", &self.notes)
.field("phone", &self.phone)
.field("address", &self.address)
.field("family_id", &self.family_id)
// Note that membership_pdf is intentionally omitted here
.finish()
}
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
@ -310,7 +286,7 @@ impl User {
sqlx::query_as!( sqlx::query_as!(
Self, Self,
" "
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, membership_pdf SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id
FROM user FROM user
WHERE id like ? WHERE id like ?
", ",
@ -325,7 +301,7 @@ WHERE id like ?
sqlx::query_as!( sqlx::query_as!(
Self, Self,
" "
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, membership_pdf SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id
FROM user FROM user
WHERE id like ? WHERE id like ?
", ",
@ -340,7 +316,7 @@ WHERE id like ?
sqlx::query_as!( sqlx::query_as!(
Self, Self,
" "
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, membership_pdf SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id
FROM user FROM user
WHERE name like ? WHERE name like ?
", ",
@ -382,7 +358,7 @@ WHERE name like ?
sqlx::query_as!( sqlx::query_as!(
Self, Self,
" "
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, membership_pdf SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id
FROM user FROM user
WHERE deleted = 0 WHERE deleted = 0
ORDER BY last_access DESC ORDER BY last_access DESC
@ -397,7 +373,7 @@ ORDER BY last_access DESC
sqlx::query_as!( sqlx::query_as!(
Self, Self,
" "
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, membership_pdf SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id
FROM user u FROM user u
JOIN user_role ur ON u.id = ur.user_id JOIN user_role ur ON u.id = ur.user_id
WHERE ur.role_id = ? AND deleted = 0 WHERE ur.role_id = ? AND deleted = 0
@ -413,14 +389,14 @@ ORDER BY name;
sqlx::query_as!( sqlx::query_as!(
Self, Self,
" "
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, membership_pdf FROM user SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id FROM user
WHERE family_id IS NOT NULL WHERE family_id IS NOT NULL
GROUP BY family_id GROUP BY family_id
UNION UNION
-- Select users with a null family_id, without grouping -- Select users with a null family_id, without grouping
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, membership_pdf FROM user SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id FROM user
WHERE family_id IS NULL; WHERE family_id IS NULL;
" "
) )
@ -433,7 +409,7 @@ WHERE family_id IS NULL;
sqlx::query_as!( sqlx::query_as!(
Self, Self,
" "
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, membership_pdf SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id
FROM user FROM user
WHERE deleted = 0 AND dob != '' and weight != '' and sex != '' WHERE deleted = 0 AND dob != '' and weight != '' and sex != ''
ORDER BY name ORDER BY name
@ -448,7 +424,7 @@ ORDER BY name
sqlx::query_as!( sqlx::query_as!(
Self, Self,
" "
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, membership_pdf SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id
FROM user FROM user
WHERE deleted = 0 AND (SELECT COUNT(*) FROM user_role WHERE user_id=user.id AND role_id = (SELECT id FROM role WHERE name = 'cox')) > 0 WHERE deleted = 0 AND (SELECT COUNT(*) FROM user_role WHERE user_id=user.id AND role_id = (SELECT id FROM role WHERE name = 'cox')) > 0
ORDER BY last_access DESC ORDER BY last_access DESC
@ -473,7 +449,9 @@ ORDER BY last_access DESC
family_id = Some(Family::insert(db).await) family_id = Some(Family::insert(db).await)
} }
if self.membership_pdf.is_none() { let user_with_membershippdf = UserWithMembershipPdf::from(db, self.clone()).await;
if user_with_membershippdf.membership_pdf.is_none() {
if let Some(membership_pdf) = data.membership_pdf { if let Some(membership_pdf) = data.membership_pdf {
let mut stream = membership_pdf.open().await.unwrap(); let mut stream = membership_pdf.open().await.unwrap();
let mut buffer = Vec::new(); let mut buffer = Vec::new();
@ -982,6 +960,29 @@ impl Deref for PlannedEventUser {
} }
} }
#[derive(FromRow, Serialize, Deserialize, Clone, Debug)]
pub struct UserWithMembershipPdf {
#[serde(flatten)]
pub user: User,
pub membership_pdf: Option<Vec<u8>>,
}
impl UserWithMembershipPdf {
pub(crate) async fn from(db: &SqlitePool, user: User) -> Self {
let membership_pdf: Option<Vec<u8>> =
sqlx::query_scalar!("SELECT membership_pdf FROM user WHERE id = $1", user.id)
.fetch_optional(db)
.await
.unwrap()
.unwrap();
Self {
user,
membership_pdf,
}
}
}
#[async_trait] #[async_trait]
impl<'r> FromRequest<'r> for PlannedEventUser { impl<'r> FromRequest<'r> for PlannedEventUser {
type Error = LoginError; type Error = LoginError;

View File

@ -11,7 +11,7 @@ impl UserTrip {
user: &User, user: &User,
trip_details: &TripDetails, trip_details: &TripDetails,
user_note: Option<String>, user_note: Option<String>,
) -> Result<(), UserTripError> { ) -> Result<String, UserTripError> {
if trip_details.is_full(db).await { if trip_details.is_full(db).await {
return Err(UserTripError::EventAlreadyFull); return Err(UserTripError::EventAlreadyFull);
} }
@ -81,7 +81,7 @@ impl UserTrip {
.await; .await;
} }
Ok(()) Ok(name_newly_registered_person)
} }
pub async fn delete( pub async fn delete(

View File

@ -5,7 +5,7 @@ use crate::model::{
log::Log, log::Log,
logbook::Logbook, logbook::Logbook,
role::Role, role::Role,
user::{AdminUser, User, UserWithRoles, VorstandUser}, user::{AdminUser, User, UserWithMembershipPdf, UserWithRoles, VorstandUser},
}; };
use futures::future::join_all; use futures::future::join_all;
use rocket::{ use rocket::{
@ -280,6 +280,7 @@ async fn download_membership_pdf(
user: i32, user: i32,
) -> (ContentType, Vec<u8>) { ) -> (ContentType, Vec<u8>) {
let user = User::find_by_id(db, user).await.unwrap(); let user = User::find_by_id(db, user).await.unwrap();
let user = UserWithMembershipPdf::from(db, user).await;
Log::create( Log::create(
db, db,
format!( format!(

View File

@ -63,15 +63,25 @@ async fn join(
}; };
match UserTrip::create(db, &user, &trip_details, user_note).await { match UserTrip::create(db, &user, &trip_details, user_note).await {
Ok(_) => { Ok(registered_user) => {
Log::create( if registered_user == user.name {
db, Log::create(
format!( db,
"User {} registered for trip_details.id={}", format!(
user.name, trip_details_id "User {} registered for trip_details.id={}",
), user.name, trip_details_id
) ),
.await; )
.await;
}else{
Log::create(
db,
format!(
"User {} registered the guest '{}' for trip_details.id={}",
user.name, registered_user, trip_details_id
),
).await;
}
Flash::success(Redirect::to("/planned"), "Erfolgreich angemeldet!") Flash::success(Redirect::to("/planned"), "Erfolgreich angemeldet!")
} }
Err(UserTripError::EventAlreadyFull) => { Err(UserTripError::EventAlreadyFull) => {

View File

@ -7,7 +7,7 @@
justify-content: space-around; justify-content: space-around;
padding: 0; padding: 0;
list-style: none"> list-style: none">
<li style="display: inline-block;">22.04. | Christian Gusenbauer | Boot: Linz + kleiner Hänger</li> <li style="display: inline-block;">30.03. | Manuela Firmötz | Boot: Urfahr</li>
</ul> </ul>
</div> </div>
</div> </div>
@ -50,7 +50,8 @@
</a> </a>
<div class="hidden"> <div class="hidden">
<div id="mobile-menu"> <div id="mobile-menu">
<a href="/log" class="block w-100 py-2 hover:text-primary-600">Ausfahrt eintragen</a> <a href="/planned" class="block w-100 py-2 hover:text-primary-600">Geplante Ausfahrten</a>
<a href="/log" class="block w-100 py-2 hover:text-primary-600 border-t">Ausfahrt eintragen</a>
<a href="/log/show" <a href="/log/show"
class="block w-100 py-2 hover:text-primary-600 border-t">Logbuch</a> class="block w-100 py-2 hover:text-primary-600 border-t">Logbuch</a>
{% if "admin" in loggedin_user.roles or "Vorstand" in loggedin_user.roles %} {% if "admin" in loggedin_user.roles or "Vorstand" in loggedin_user.roles %}

View File

@ -176,4 +176,5 @@
</div> </div>
</div> </div>
</div> </div>
{% endblock content %} </div>
{% endblock content %}