Compare commits
1 Commits
staging
...
e43b7d333f
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e43b7d333f |
@@ -17,9 +17,6 @@ jobs:
|
||||
- name: Run Test DB Script
|
||||
run: ./test_db.sh
|
||||
|
||||
- name: Test
|
||||
run: npm --version
|
||||
|
||||
- name: Cache Cargo dependencies
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
@@ -28,15 +25,15 @@ jobs:
|
||||
cargo build
|
||||
cd frontend && npm install && npm run build
|
||||
- name: Frontend tests
|
||||
run: cd frontend && npx playwright install && npx playwright test --workers 1 --reporter html,line
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report
|
||||
path: frontend/playwright-report/
|
||||
retention-days: 30
|
||||
run: cd frontend && npx playwright install && npx playwright test --workers 1 --reporter line
|
||||
- name: Backend tests
|
||||
run: cargo test --verbose
|
||||
#- uses: actions/upload-artifact@v3
|
||||
# if: always()
|
||||
# with:
|
||||
# name: playwright-report
|
||||
# path: frontend/playwright-report/
|
||||
# retention-days: 30
|
||||
|
||||
deploy-staging:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -66,16 +63,16 @@ jobs:
|
||||
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
|
||||
scp -C target/$CARGO_TARGET/release/rot $SSH_USER@$SSH_HOST:/root/rowing-staging/rot-updating
|
||||
scp -C target/$CARGO_TARGET/release/rot $SSH_USER@$SSH_HOST:/home/rowing-staging/rot-updating
|
||||
|
||||
scp -C staging-diff.sql $SSH_USER@$SSH_HOST:/root/rowing-staging/
|
||||
scp -C -r static $SSH_USER@$SSH_HOST:/root/rowing-staging/
|
||||
scp -C -r templates $SSH_USER@$SSH_HOST:/root/rowing-staging/
|
||||
scp -C -r svelte $SSH_USER@$SSH_HOST:/root/rowing-staging/
|
||||
ssh $SSH_USER@$SSH_HOST 'sudo systemctl stop rowing-staging'
|
||||
ssh $SSH_USER@$SSH_HOST 'rm -f /root/rowing-staging/db.sqlite && cp /root/rowing-prod/db.sqlite /root/rowing-staging/db.sqlite && mkdir -p /root/rowing-staging/svelte/build && mkdir -p /root/rowing-staging/data-ergo/thirty && mkdir -p /root/rowing-staging/data-ergo/dozen && sqlite3 /root/rowing-staging/db.sqlite < /root/rowing-staging/staging-diff.sql'
|
||||
ssh $SSH_USER@$SSH_HOST 'mv /root/rowing-staging/rot-updating /root/rowing-staging/rot'
|
||||
ssh $SSH_USER@$SSH_HOST 'sudo systemctl start rowing-staging'
|
||||
scp -C staging-diff.sql $SSH_USER@$SSH_HOST:/home/rowing-staging/
|
||||
scp -C -r static $SSH_USER@$SSH_HOST:/home/rowing-staging/
|
||||
scp -C -r templates $SSH_USER@$SSH_HOST:/home/rowing-staging/
|
||||
scp -C -r svelte $SSH_USER@$SSH_HOST:/home/rowing-staging/
|
||||
ssh $SSH_USER@$SSH_HOST 'sudo systemctl stop rotstaging'
|
||||
ssh $SSH_USER@$SSH_HOST 'rm /home/rowing-staging/db.sqlite && cp /home/rowing/db.sqlite /home/rowing-staging/db.sqlite && mkdir -p /home/rowing-staging/svelte/build && mkdir -p /home/rowing-staging/data-ergo/thirty && mkdir -p /home/rowing-staging/data-ergo/dozen && sqlite3 /home/rowing-staging/db.sqlite < /home/rowing-staging/staging-diff.sql'
|
||||
ssh $SSH_USER@$SSH_HOST 'mv /home/rowing-staging/rot-updating /home/rowing-staging/rot'
|
||||
ssh $SSH_USER@$SSH_HOST 'sudo systemctl start rotstaging'
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
SSH_HOST: ${{ secrets.SSH_HOST }}
|
||||
@@ -109,14 +106,14 @@ jobs:
|
||||
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
|
||||
scp -C target/$CARGO_TARGET/release/rot $SSH_USER@$SSH_HOST:/root/rowing-prod/rot-updating
|
||||
scp -C -r static $SSH_USER@$SSH_HOST:/root/rowing-prod/
|
||||
scp -C -r templates $SSH_USER@$SSH_HOST:/root/rowing-prod/
|
||||
scp -C -r svelte $SSH_USER@$SSH_HOST:/root/rowing-prod/
|
||||
ssh $SSH_USER@$SSH_HOST 'mkdir -p /root/rowing-prod/svelte/build && mkdir -p /root/rowing-prod/data-ergo/thirty && mkdir -p /root/rowing-prod/data-ergo/dozen'
|
||||
ssh $SSH_USER@$SSH_HOST 'sudo systemctl stop rowing-prod'
|
||||
ssh $SSH_USER@$SSH_HOST 'mv /root/rowing-prod/rot-updating /root/rowing-prod/rot'
|
||||
ssh $SSH_USER@$SSH_HOST 'sudo systemctl start rowing-prod'
|
||||
scp -C target/$CARGO_TARGET/release/rot $SSH_USER@$SSH_HOST:/home/rowing/rot-updating
|
||||
scp -C -r static $SSH_USER@$SSH_HOST:/home/rowing/
|
||||
scp -C -r templates $SSH_USER@$SSH_HOST:/home/rowing/
|
||||
scp -C -r svelte $SSH_USER@$SSH_HOST:/home/rowing/
|
||||
ssh $SSH_USER@$SSH_HOST 'mkdir -p /home/rowing/svelte/build && mkdir -p /home/rowing/data-ergo/thirty && mkdir -p /home/rowing/data-ergo/dozen'
|
||||
ssh $SSH_USER@$SSH_HOST 'sudo systemctl stop rot'
|
||||
ssh $SSH_USER@$SSH_HOST 'mv /home/rowing/rot-updating /home/rowing/rot'
|
||||
ssh $SSH_USER@$SSH_HOST 'sudo systemctl start rot'
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
SSH_HOST: ${{ secrets.SSH_HOST }}
|
||||
|
652
Cargo.lock
generated
652
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
2
fd
2
fd
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
scp root@app.rudernlinz.at:/root/rowing-prod/db.sqlite db.sqlite
|
||||
scp root@128.140.64.118:/home/rowing/db.sqlite db.sqlite
|
||||
#sqlite3 db.sqlite < seeds.sql
|
||||
|
||||
|
@@ -413,7 +413,6 @@ function initNewChoice(select: HTMLInputElement) {
|
||||
steering_person.setAttribute("required", "required");
|
||||
}
|
||||
const choice = new Choices(select, {
|
||||
searchResultLimit: 100,
|
||||
searchFields: ["label", "value", "customProperties.searchableText"],
|
||||
removeItemButton: true,
|
||||
loadingText: "Wird geladen...",
|
||||
|
@@ -16,7 +16,7 @@
|
||||
"postcss": "^8.4.21",
|
||||
"sass": "^1.60.0",
|
||||
"tailwindcss": "^3.3.1",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript": "^4.9.5",
|
||||
"vite": "^4.2.0",
|
||||
"vite-plugin-static-copy": "^0.13.1"
|
||||
},
|
||||
|
6
package-lock.json
generated
6
package-lock.json
generated
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "rowt",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
@@ -8,7 +8,7 @@ use crate::model::{
|
||||
notification::Notification,
|
||||
role::Role,
|
||||
};
|
||||
use chrono::{Datelike, Local, NaiveDate};
|
||||
use chrono::NaiveDate;
|
||||
use rocket::{fs::TempFile, tokio::io::AsyncReadExt};
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
@@ -342,33 +342,12 @@ impl User {
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
ActivityBuilder::new(&format!("{updated_by} hat {self} zum normalen Mitglied gemacht (keine Steuerperson/Bootsführer mehr)"))
|
||||
ActivityBuilder::new(&format!("{updated_by} hat {self} zum normalen Mitglied gemacht (keine Steuerperson/Schiffsführer mehr)"))
|
||||
.user(self)
|
||||
.save(db)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
(old, new) if old == Some(bootsfuehrer.clone()) && new == Some(cox.clone()) => {
|
||||
self.remove_role(db, updated_by, &bootsfuehrer).await?;
|
||||
self.add_role(db, updated_by, &cox).await?;
|
||||
Notification::create_for_role(
|
||||
db,
|
||||
&member,
|
||||
&format!(
|
||||
"Lieber Vorstand, {self} ist ab sofort kein Bootsführer:in mehr, sondern 'nur' mehr eine Steuerperson."
|
||||
),
|
||||
"Bootsführer--",
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
ActivityBuilder::new(&format!(
|
||||
"{updated_by} hat {self} zur Steuerperson gemacht (kein Bootsführer mehr)"
|
||||
))
|
||||
.user(self)
|
||||
.save(db)
|
||||
.await;
|
||||
}
|
||||
(old, new) => return Err(format!("Not allowed to change from {old:?} to {new:?}")),
|
||||
};
|
||||
|
||||
@@ -529,13 +508,6 @@ impl User {
|
||||
}
|
||||
|
||||
pub(crate) async fn remove_membership_pdf(&self, db: &SqlitePool, updated_by: &ManageUserUser) {
|
||||
ActivityBuilder::new(&format!(
|
||||
"{updated_by} hat die Beitrittserklärung vom Beutzer gelöscht."
|
||||
))
|
||||
.user(self)
|
||||
.save(db)
|
||||
.await;
|
||||
|
||||
sqlx::query!(
|
||||
"UPDATE user SET membership_pdf = null where id = ?",
|
||||
self.id
|
||||
@@ -578,32 +550,4 @@ impl User {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn has_to_pay_einschreibgebuehr_this_year(&self, db: &SqlitePool) -> bool {
|
||||
if !self.has_role(db, "schnupperant").await {
|
||||
if let Some(member_since_date) = &self.member_since_date {
|
||||
if let Ok(member_since_date) =
|
||||
NaiveDate::parse_from_str(member_since_date, "%Y-%m-%d")
|
||||
{
|
||||
if member_since_date.year() == Local::now().year()
|
||||
&& !self.has_role(db, "no-einschreibgebuehr").await
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
pub(crate) fn has_to_pay_only_half(&self) -> bool {
|
||||
if let Some(member_since_date) = &self.member_since_date {
|
||||
if let Ok(member_since_date) = NaiveDate::parse_from_str(member_since_date, "%Y-%m-%d")
|
||||
{
|
||||
let halfprice_startdate =
|
||||
NaiveDate::from_ymd_opt(Local::now().year(), 7, 1).unwrap();
|
||||
return member_since_date >= halfprice_startdate;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,10 @@
|
||||
use super::User;
|
||||
use crate::{
|
||||
model::family::Family, BOAT_STORAGE, DUAL_MEMBERSHIP, EINSCHREIBGEBUEHR, FAMILY_THREE_OR_MORE,
|
||||
FAMILY_TWO, FOERDERND, REGULAR, RENNRUDERBEITRAG, SCHECKBUCH, STUDENT_OR_PUPIL, TRIAL_ROWING,
|
||||
TRIAL_ROWING_REDUCED, UNTERSTUETZEND,
|
||||
BOAT_STORAGE, DUAL_MEMBERSHIP, EINSCHREIBGEBUEHR, FAMILY_THREE_OR_MORE, FAMILY_TWO, FOERDERND,
|
||||
REGULAR, RENNRUDERBEITRAG, SCHECKBUCH, STUDENT_OR_PUPIL, TRIAL_ROWING, TRIAL_ROWING_REDUCED,
|
||||
UNTERSTUETZEND, model::family::Family,
|
||||
};
|
||||
use chrono::{Datelike, Local, NaiveDate};
|
||||
use serde::Serialize;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
@@ -80,52 +81,30 @@ impl User {
|
||||
let mut fee = Fee::new();
|
||||
|
||||
if let Some(family) = Family::find_by_opt_id(db, self.family_id).await {
|
||||
let mut einschreibgebuehr = false;
|
||||
let mut half_price = true;
|
||||
for member in family.members(db).await {
|
||||
fee.add_person(&member);
|
||||
if member.has_role(db, "paid").await {
|
||||
fee.paid();
|
||||
}
|
||||
fee.merge(member.fee_without_families(db, true).await);
|
||||
if member.has_to_pay_einschreibgebuehr_this_year(db).await {
|
||||
einschreibgebuehr = true;
|
||||
}
|
||||
if !member.has_to_pay_only_half() {
|
||||
half_price = false;
|
||||
}
|
||||
fee.merge(member.fee_without_families(db).await);
|
||||
}
|
||||
if family.amount_family_members(db).await > 2 {
|
||||
if half_price {
|
||||
fee.add(
|
||||
"Familie 3+ Personen (Halbpreis)".into(),
|
||||
FAMILY_THREE_OR_MORE / 2,
|
||||
);
|
||||
} else {
|
||||
fee.add("Familie 3+ Personen".into(), FAMILY_THREE_OR_MORE);
|
||||
}
|
||||
fee.add("Familie 3+ Personen".into(), FAMILY_THREE_OR_MORE);
|
||||
} else {
|
||||
if half_price {
|
||||
fee.add("Familie 2 Personen (Halbpreis)".into(), FAMILY_TWO / 2);
|
||||
} else {
|
||||
fee.add("Familie 2 Personen".into(), FAMILY_TWO);
|
||||
}
|
||||
}
|
||||
if einschreibgebuehr {
|
||||
fee.add("Einschreibgebühr (Familie)".into(), EINSCHREIBGEBUEHR);
|
||||
fee.add("Familie 2 Personen".into(), FAMILY_TWO);
|
||||
}
|
||||
} else {
|
||||
fee.add_person(self);
|
||||
if self.has_role(db, "paid").await {
|
||||
fee.paid();
|
||||
}
|
||||
fee.merge(self.fee_without_families(db, false).await);
|
||||
fee.merge(self.fee_without_families(db).await);
|
||||
}
|
||||
|
||||
Some(fee)
|
||||
}
|
||||
|
||||
async fn fee_without_families(&self, db: &SqlitePool, entry_fee_paid_with_family: bool) -> Fee {
|
||||
async fn fee_without_families(&self, db: &SqlitePool) -> Fee {
|
||||
let mut fee = Fee::new();
|
||||
|
||||
if !self.has_role(db, "Donau Linz").await
|
||||
@@ -146,24 +125,38 @@ impl User {
|
||||
|
||||
let amount_boats = self.amount_boats(db).await;
|
||||
if amount_boats > 0 {
|
||||
if self.has_to_pay_only_half() {
|
||||
fee.add(
|
||||
format!("{}x Bootsplatz (Halbpreis)", amount_boats),
|
||||
amount_boats * BOAT_STORAGE / 2,
|
||||
);
|
||||
} else {
|
||||
fee.add(
|
||||
format!("{}x Bootsplatz", amount_boats),
|
||||
amount_boats * BOAT_STORAGE,
|
||||
);
|
||||
fee.add(
|
||||
format!("{}x Bootsplatz", amount_boats),
|
||||
amount_boats * BOAT_STORAGE,
|
||||
);
|
||||
}
|
||||
|
||||
if !self.has_role(db, "schnupperant").await {
|
||||
if let Some(member_since_date) = &self.member_since_date {
|
||||
if let Ok(member_since_date) =
|
||||
NaiveDate::parse_from_str(member_since_date, "%Y-%m-%d")
|
||||
{
|
||||
if member_since_date.year() == Local::now().year()
|
||||
&& !self.has_role(db, "no-einschreibgebuehr").await
|
||||
{
|
||||
fee.add("Einschreibgebühr".into(), EINSCHREIBGEBUEHR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.has_to_pay_einschreibgebuehr_this_year(db).await && !entry_fee_paid_with_family {
|
||||
fee.add("Einschreibgebühr".into(), EINSCHREIBGEBUEHR);
|
||||
}
|
||||
|
||||
let halfprice = self.has_to_pay_only_half();
|
||||
let halfprice = if let Some(member_since_date) = &self.member_since_date {
|
||||
match NaiveDate::parse_from_str(member_since_date, "%Y-%m-%d") {
|
||||
Ok(member_since_date) => {
|
||||
let halfprice_startdate =
|
||||
NaiveDate::from_ymd_opt(Local::now().year(), 7, 1).unwrap();
|
||||
member_since_date >= halfprice_startdate
|
||||
}
|
||||
Err(_) => false,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if self.has_role(db, "schnupperant").await {
|
||||
if self.has_role(db, "Student").await || self.has_role(db, "Schüler").await {
|
||||
|
@@ -102,13 +102,6 @@ impl UserWithDetails {
|
||||
user,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn allowed_to_row(&self) -> bool {
|
||||
self.roles.contains(&"Donau Linz".into())
|
||||
|| self.roles.contains(&"Förderndes Mitglied".into())
|
||||
|| self.roles.contains(&"scheckbuch".into())
|
||||
|| self.user.name == "Externe Steuerperson"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -431,7 +424,7 @@ WHERE family_id IS NULL;
|
||||
"
|
||||
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, phone, address, family_id, user_token
|
||||
FROM user
|
||||
WHERE deleted = 0 AND (SELECT COUNT(*) FROM user_role WHERE user_id=user.id AND role_id in (SELECT id FROM role WHERE name = 'cox' or name = 'Bootsführer')) > 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
|
||||
"
|
||||
)
|
||||
@@ -795,7 +788,6 @@ macro_rules! special_user {
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[allow(dead_code)]
|
||||
pub fn into_inner(self) -> User {
|
||||
self.user
|
||||
}
|
||||
@@ -857,10 +849,9 @@ special_user!(ErgoUser, +"ergo");
|
||||
special_user!(SteeringUser, +"cox", +"Bootsführer");
|
||||
special_user!(AdminUser, +"admin");
|
||||
special_user!(AllowedForPlannedTripsUser, +"Donau Linz", +"scheckbuch", +"Förderndes Mitglied");
|
||||
special_user!(DonauLinzUser, +"Donau Linz", +"Förderndes Mitglied", -"Unterstützend"); // TODO:
|
||||
special_user!(DonauLinzUser, +"Donau Linz", -"Unterstützend", -"Förderndes Mitglied"); // TODO:
|
||||
// remove ->
|
||||
// RegularUser
|
||||
special_user!(ErgoAdminUser, +"ergo-admin", +"admin");
|
||||
special_user!(SchnupperBetreuerUser, +"schnupper-betreuer");
|
||||
special_user!(VorstandUser, +"admin", +"Vorstand");
|
||||
special_user!(EventUser, +"manage_events");
|
||||
|
@@ -40,7 +40,7 @@ async fn index(
|
||||
let allowed_to_edit = AllowedToUpdateBoathouse::new(db, &admin.user)
|
||||
.await
|
||||
.is_some();
|
||||
context.insert("allowed_to_edit", &allowed_to_edit);
|
||||
context.insert("allowed_to_edit", &boathouse);
|
||||
|
||||
context.insert(
|
||||
"loggedin_user",
|
||||
|
115
src/tera/ergo.rs
115
src/tera/ergo.rs
@@ -1,7 +1,8 @@
|
||||
use std::env;
|
||||
|
||||
use chrono::{Datelike, Utc};
|
||||
use chrono::Utc;
|
||||
use rocket::{
|
||||
FromForm, Route, State,
|
||||
form::Form,
|
||||
fs::TempFile,
|
||||
get,
|
||||
@@ -9,19 +10,18 @@ use rocket::{
|
||||
post,
|
||||
request::FlashMessage,
|
||||
response::{Flash, Redirect},
|
||||
routes, FromForm, Route, State,
|
||||
routes,
|
||||
};
|
||||
use rocket_dyn_templates::{context, Template};
|
||||
use rocket_dyn_templates::{Template, context};
|
||||
use serde::Serialize;
|
||||
use sqlx::SqlitePool;
|
||||
use tera::Context;
|
||||
|
||||
use crate::model::{
|
||||
activity::ActivityBuilder,
|
||||
log::Log,
|
||||
notification::Notification,
|
||||
role::Role,
|
||||
user::{AdminUser, ErgoAdminUser, User, UserWithDetails},
|
||||
user::{AdminUser, User, UserWithDetails},
|
||||
};
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -59,7 +59,7 @@ async fn send(db: &State<SqlitePool>, _user: AdminUser) -> Template {
|
||||
}
|
||||
|
||||
#[get("/reset")]
|
||||
async fn reset(db: &State<SqlitePool>, _user: ErgoAdminUser) -> Flash<Redirect> {
|
||||
async fn reset(db: &State<SqlitePool>, _user: AdminUser) -> Flash<Redirect> {
|
||||
sqlx::query!("UPDATE user SET dirty_thirty = NULL, dirty_dozen = NULL;")
|
||||
.execute(db.inner())
|
||||
.await
|
||||
@@ -74,7 +74,7 @@ async fn reset(db: &State<SqlitePool>, _user: ErgoAdminUser) -> Flash<Redirect>
|
||||
#[get("/<challenge>/user/<user_id>/new?<new>")]
|
||||
async fn update(
|
||||
db: &State<SqlitePool>,
|
||||
_admin: ErgoAdminUser,
|
||||
_admin: AdminUser,
|
||||
challenge: &str,
|
||||
user_id: i64,
|
||||
new: &str,
|
||||
@@ -146,61 +146,47 @@ pub struct UserAdd {
|
||||
sex: String,
|
||||
}
|
||||
|
||||
#[post("/set-data", data = "<data>")]
|
||||
async fn new_user(db: &State<SqlitePool>, data: Form<UserAdd>, user: User) -> Flash<Redirect> {
|
||||
if user.has_role(db, "ergo").await {
|
||||
return Flash::error(Redirect::to("/ergo"), "Du hast deine Daten schon eingegeben. Wenn du sie updaten willst, melde dich bitte bei info@rudernlinz.at");
|
||||
}
|
||||
|
||||
// check data
|
||||
if data.birthyear < 1900 || data.birthyear > chrono::Utc::now().year() - 5 {
|
||||
return Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Geburtsjahr...");
|
||||
}
|
||||
if data.weight < 20 || data.weight > 200 {
|
||||
return Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Gewicht...");
|
||||
}
|
||||
if &data.sex != "f" && &data.sex != "m" {
|
||||
return Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Geschlecht...");
|
||||
}
|
||||
|
||||
// set data
|
||||
user.update_ergo(db, data.birthyear, data.weight, &data.sex)
|
||||
.await;
|
||||
|
||||
// inform all other `ergo` users
|
||||
let ergo = Role::find_by_name(db, "ergo").await.unwrap();
|
||||
Notification::create_for_role(
|
||||
db,
|
||||
&ergo,
|
||||
&format!("{} nimmt heuer an der Ergochallenge teil 💪", user.name),
|
||||
"Ergo Challenge",
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
// add to `ergo` group
|
||||
sqlx::query!(
|
||||
"INSERT INTO user_role(user_id, role_id) VALUES (?, ?)",
|
||||
user.id,
|
||||
ergo.id
|
||||
)
|
||||
.execute(db.inner())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
ActivityBuilder::new(&format!(
|
||||
"{user} nimmt an der Ergo-Challenge teil und hat gerade die Daten eingegeben."
|
||||
))
|
||||
.user(&user)
|
||||
.save(db)
|
||||
.await;
|
||||
|
||||
Flash::success(
|
||||
Redirect::to("/ergo"),
|
||||
"Du hast deine Daten erfolgreich eingegeben. Viel Spaß beim Schwitzen :-)",
|
||||
)
|
||||
}
|
||||
//#[post("/set-data", data = "<data>")]
|
||||
//async fn new_user(db: &State<SqlitePool>, data: Form<UserAdd>, user: User) -> Flash<Redirect> {
|
||||
// if user.has_role(db, "ergo").await {
|
||||
// return Flash::error(Redirect::to("/ergo"), "Du hast deine Daten schon eingegeben. Wenn du sie updaten willst, melde dich bitte bei it@rudernlinz.at");
|
||||
// }
|
||||
//
|
||||
// // check data
|
||||
// if data.birthyear < 1900 || data.birthyear > chrono::Utc::now().year() - 5 {
|
||||
// return Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Geburtsjahr...");
|
||||
// }
|
||||
// if data.weight < 20 || data.weight > 200 {
|
||||
// return Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Gewicht...");
|
||||
// }
|
||||
// if &data.sex != "f" && &data.sex != "m" {
|
||||
// return Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Geschlecht...");
|
||||
// }
|
||||
//
|
||||
// // set data
|
||||
// user.update_ergo(db, data.birthyear, data.weight, &data.sex)
|
||||
// .await;
|
||||
//
|
||||
// // inform all other `ergo` users
|
||||
// let ergo = Role::find_by_name(db, "ergo").await.unwrap();
|
||||
// Notification::create_for_role(
|
||||
// db,
|
||||
// &ergo,
|
||||
// &format!("{} nimmt heuer an der Ergochallenge teil 💪", user.name),
|
||||
// "Ergo Challenge",
|
||||
// None,
|
||||
// None,
|
||||
// )
|
||||
// .await;
|
||||
//
|
||||
// // add to `ergo` group
|
||||
// user.add_role(db, &ergo).await.unwrap();
|
||||
//
|
||||
// Flash::success(
|
||||
// Redirect::to("/ergo"),
|
||||
// "Du hast deine Daten erfolgreich eingegeben. Viel Spaß beim Schwitzen :-)",
|
||||
// )
|
||||
//}
|
||||
|
||||
#[derive(FromForm, Debug)]
|
||||
pub struct ErgoToAdd<'a> {
|
||||
@@ -373,7 +359,10 @@ async fn new_dozen(
|
||||
}
|
||||
|
||||
pub fn routes() -> Vec<Route> {
|
||||
routes![index, new_thirty, new_dozen, send, reset, update, new_user]
|
||||
routes![
|
||||
index, new_thirty, new_dozen, send, reset, update,
|
||||
// new_user
|
||||
]
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
119
src/tera/log.rs
119
src/tera/log.rs
@@ -47,46 +47,12 @@ impl<'r> FromRequest<'r> for KioskCookie {
|
||||
}
|
||||
|
||||
#[get("/", rank = 2)]
|
||||
async fn index_loggedin(
|
||||
async fn index(
|
||||
db: &State<SqlitePool>,
|
||||
flash: Option<FlashMessage<'_>>,
|
||||
user: DonauLinzUser,
|
||||
) -> Template {
|
||||
let mut context = Context::new();
|
||||
|
||||
let boats = Boat::for_user(db, &user).await;
|
||||
context.insert("boats", &boats);
|
||||
|
||||
context.insert(
|
||||
"loggedin_user",
|
||||
&UserWithDetails::from_user(user.into_inner(), db).await,
|
||||
);
|
||||
|
||||
let context = index(db, flash, context).await;
|
||||
Template::render("log", context.into_json())
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
async fn index_kiosk(
|
||||
db: &State<SqlitePool>,
|
||||
flash: Option<FlashMessage<'_>>,
|
||||
_kiosk: KioskCookie,
|
||||
) -> Template {
|
||||
let mut context = Context::new();
|
||||
|
||||
let boats = Boat::all(db).await;
|
||||
context.insert("boats", &boats);
|
||||
|
||||
context.insert("show_kiosk_header", &true);
|
||||
|
||||
let context = index(db, flash, context).await;
|
||||
Template::render("kiosk", context.into_json())
|
||||
}
|
||||
|
||||
async fn index(db: &SqlitePool, flash: Option<FlashMessage<'_>>, mut context: Context) -> Context {
|
||||
if let Some(msg) = flash {
|
||||
context.insert("flash", &msg.into_inner());
|
||||
}
|
||||
|
||||
let mut coxes: Vec<UserWithDetails> = futures::future::join_all(
|
||||
User::cox(db)
|
||||
@@ -95,7 +61,9 @@ async fn index(db: &SqlitePool, flash: Option<FlashMessage<'_>>, mut context: Co
|
||||
.map(|user| UserWithDetails::from_user(user, db)),
|
||||
)
|
||||
.await;
|
||||
coxes.retain(|u| u.roles.contains(&"Donau Linz".into()));
|
||||
coxes.retain(|u| {
|
||||
u.roles.contains(&"Donau Linz".into()) || u.roles.contains(&"scheckbuch".into())
|
||||
});
|
||||
|
||||
let mut users: Vec<UserWithDetails> = futures::future::join_all(
|
||||
User::all(db)
|
||||
@@ -104,13 +72,23 @@ async fn index(db: &SqlitePool, flash: Option<FlashMessage<'_>>, mut context: Co
|
||||
.map(|user| UserWithDetails::from_user(user, db)),
|
||||
)
|
||||
.await;
|
||||
users.retain(|u| u.allowed_to_row());
|
||||
users.retain(|u| {
|
||||
u.roles.contains(&"Donau Linz".into())
|
||||
|| u.roles.contains(&"scheckbuch".into())
|
||||
|| u.user.name == "Externe Steuerperson"
|
||||
});
|
||||
|
||||
let logtypes = LogType::all(db).await;
|
||||
let distances = Distance::all(db).await;
|
||||
|
||||
let on_water = Logbook::on_water(db).await;
|
||||
|
||||
let mut context = Context::new();
|
||||
if let Some(msg) = flash {
|
||||
context.insert("flash", &msg.into_inner());
|
||||
}
|
||||
|
||||
context.insert("boats", &boats);
|
||||
context.insert("planned_trips", &Trip::get_for_today(db).await);
|
||||
context.insert(
|
||||
"reservations",
|
||||
@@ -119,10 +97,14 @@ async fn index(db: &SqlitePool, flash: Option<FlashMessage<'_>>, mut context: Co
|
||||
context.insert("coxes", &coxes);
|
||||
context.insert("users", &users);
|
||||
context.insert("logtypes", &logtypes);
|
||||
context.insert(
|
||||
"loggedin_user",
|
||||
&UserWithDetails::from_user(user.into_inner(), db).await,
|
||||
);
|
||||
context.insert("on_water", &on_water);
|
||||
context.insert("distances", &distances);
|
||||
|
||||
context
|
||||
Template::render("log", context.into_json())
|
||||
}
|
||||
|
||||
#[get("/show", rank = 3)]
|
||||
@@ -197,6 +179,63 @@ async fn new_kiosk(
|
||||
Redirect::to("/log")
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
async fn kiosk(
|
||||
db: &State<SqlitePool>,
|
||||
flash: Option<FlashMessage<'_>>,
|
||||
_kiosk: KioskCookie,
|
||||
) -> Template {
|
||||
let boats = Boat::all(db).await;
|
||||
let mut coxes: Vec<UserWithDetails> = futures::future::join_all(
|
||||
User::cox(db)
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|user| UserWithDetails::from_user(user, db)),
|
||||
)
|
||||
.await;
|
||||
|
||||
coxes.retain(|u| {
|
||||
u.roles.contains(&"Donau Linz".into()) || u.roles.contains(&"scheckbuch".into())
|
||||
});
|
||||
|
||||
let mut users: Vec<UserWithDetails> = futures::future::join_all(
|
||||
User::all(db)
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|user| UserWithDetails::from_user(user, db)),
|
||||
)
|
||||
.await;
|
||||
|
||||
users.retain(|u| {
|
||||
u.roles.contains(&"Donau Linz".into()) || u.roles.contains(&"scheckbuch".into())
|
||||
});
|
||||
|
||||
let logtypes = LogType::all(db).await;
|
||||
let distances = Distance::all(db).await;
|
||||
|
||||
let on_water = Logbook::on_water(db).await;
|
||||
|
||||
let mut context = Context::new();
|
||||
if let Some(msg) = flash {
|
||||
context.insert("flash", &msg.into_inner());
|
||||
}
|
||||
|
||||
context.insert("planned_trips", &Trip::get_for_today(db).await);
|
||||
context.insert("boats", &boats);
|
||||
context.insert(
|
||||
"reservations",
|
||||
&BoatReservation::all_future_with_groups(db).await,
|
||||
);
|
||||
context.insert("coxes", &coxes);
|
||||
context.insert("users", &users);
|
||||
context.insert("logtypes", &logtypes);
|
||||
context.insert("on_water", &on_water);
|
||||
context.insert("distances", &distances);
|
||||
context.insert("show_kiosk_header", &true);
|
||||
|
||||
Template::render("kiosk", context.into_json())
|
||||
}
|
||||
|
||||
async fn create_logbook(
|
||||
db: &SqlitePool,
|
||||
data: Form<LogToAdd>,
|
||||
@@ -529,11 +568,11 @@ async fn delete_kiosk(
|
||||
|
||||
pub fn routes() -> Vec<Route> {
|
||||
routes![
|
||||
index_loggedin,
|
||||
index_kiosk,
|
||||
index,
|
||||
create,
|
||||
create_kiosk,
|
||||
home,
|
||||
kiosk,
|
||||
home_kiosk,
|
||||
new_kiosk,
|
||||
show,
|
||||
|
@@ -2,7 +2,7 @@ use std::{fs::OpenOptions, io::Write};
|
||||
|
||||
use chrono::{Datelike, Local};
|
||||
use rocket::{
|
||||
catch, catchers,
|
||||
Build, Data, FromForm, Request, Rocket, State, catch, catchers,
|
||||
fairing::{AdHoc, Fairing, Info, Kind},
|
||||
form::Form,
|
||||
fs::FileServer,
|
||||
@@ -13,7 +13,6 @@ use rocket::{
|
||||
response::{Flash, Redirect},
|
||||
routes,
|
||||
time::{Duration, OffsetDateTime},
|
||||
Build, Data, FromForm, Request, Rocket, State,
|
||||
};
|
||||
use rocket_dyn_templates::Template;
|
||||
use serde::Deserialize;
|
||||
@@ -21,6 +20,7 @@ use sqlx::SqlitePool;
|
||||
use tera::Context;
|
||||
|
||||
use crate::{
|
||||
SCHECKBUCH,
|
||||
model::{
|
||||
logbook::Logbook,
|
||||
notification::Notification,
|
||||
@@ -28,7 +28,6 @@ use crate::{
|
||||
role::Role,
|
||||
user::{User, UserWithDetails},
|
||||
},
|
||||
SCHECKBUCH,
|
||||
};
|
||||
|
||||
pub(crate) mod admin;
|
||||
@@ -331,11 +330,13 @@ mod test {
|
||||
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
|
||||
assert!(response
|
||||
.into_string()
|
||||
.await
|
||||
.unwrap()
|
||||
.contains("Ruderassistent"));
|
||||
assert!(
|
||||
response
|
||||
.into_string()
|
||||
.await
|
||||
.unwrap()
|
||||
.contains("Ruderassistent")
|
||||
);
|
||||
}
|
||||
|
||||
#[sqlx::test]
|
||||
|
@@ -15,7 +15,10 @@
|
||||
class="link-primary">Überblick der Challenges</a>
|
||||
</li>
|
||||
<li class="py-1">
|
||||
Eintragung ist jederzeit möglich, wenn du sie auch an die offizielle Liste schicken willst, kannst du das <a href="https://data.ergochallenge.at/" target="_blank" style="text-decoration: underline">hier</a> machen
|
||||
Eintragung ist jederzeit möglich, alle Daten die bis Sonntag 23:59 hier hochgeladen wurden, werden gesammelt an die Ister Ergo Challenge geschickt
|
||||
<li class="py-1">
|
||||
Montag → gemeinsames Training; bitte um <a href="/planned" class="link-primary">Anmeldung</a>, damit jeder einen Ergo hat
|
||||
</li>
|
||||
<li class="py-1">
|
||||
<a href="https://data.ergochallenge.at"
|
||||
target="_blank"
|
||||
@@ -191,7 +194,7 @@
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
{% if "admin" in loggedin_user.roles or "ergo-admin" in loggedin_user.roles %}
|
||||
{% if "admin" in loggedin_user.roles %}
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow grid gap-3">
|
||||
<h2 class="h2">Update</h2>
|
||||
<details class="p-2">
|
||||
@@ -230,14 +233,6 @@
|
||||
</ol>
|
||||
</div>
|
||||
</details>
|
||||
<div class="mt-3 text-right">
|
||||
<a href="/ergo/reset"
|
||||
class="w-28 btn btn-alert"
|
||||
onclick="return confirm('Willst du wirklich alle Ergo-Eingaben löschen?');">
|
||||
{% include "includes/delete-icon" %}
|
||||
Einträge löschen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
Reference in New Issue
Block a user