forked from Ruderverein-Donau-Linz/rowt
move todos to gitlab; write tests for /cox/remove/<id>; Closes #9
This commit is contained in:
parent
c4100e6c68
commit
bbb78cbc44
109
README.md
109
README.md
@ -1,80 +1,3 @@
|
|||||||
# Backend
|
|
||||||
- [] **Create missing backend tests (see below)**
|
|
||||||
- [] trip_details -> is_locked (default: false)
|
|
||||||
- [] ics for registered trips
|
|
||||||
|
|
||||||
## New large features
|
|
||||||
### Logbuch
|
|
||||||
- Only layout + tests missing :-)
|
|
||||||
|
|
||||||
### Guest-Scheckbuch
|
|
||||||
- guest_trip
|
|
||||||
- guest_user_id
|
|
||||||
- amount_trips
|
|
||||||
- paid_to_user_id
|
|
||||||
- guest_trip_logbook
|
|
||||||
- guest_trip_id
|
|
||||||
- logbook_id
|
|
||||||
|
|
||||||
### Bootsreservierungen
|
|
||||||
- Confirmation required?
|
|
||||||
- How long in advance is it possible?
|
|
||||||
- Default reservations for some regular events (A+F, USI, ...)?
|
|
||||||
|
|
||||||
### Notifications
|
|
||||||
- notifcations
|
|
||||||
- id
|
|
||||||
- message
|
|
||||||
- category
|
|
||||||
- created_at
|
|
||||||
- confirmed_at: Option<Datetime>
|
|
||||||
- user_id
|
|
||||||
- link
|
|
||||||
- ideas
|
|
||||||
- created an event at the same datetime as you
|
|
||||||
|
|
||||||
### Schnupper-Pipeline
|
|
||||||
- Mail-Adressen von Interessierten dauerhaft entgegennehmen
|
|
||||||
- Termin ausgemacht -> Interessierte kontaktieren
|
|
||||||
- X Personen können teilnehmen (bis zu 3(?) pro Person erlauben (Familie)?)
|
|
||||||
- Automatisch Bestätigung bei Anmeldung schicken, mit Detail-Infos
|
|
||||||
- Ein paar Tage vorher Erinnerungs-Mail ausschicken
|
|
||||||
- Anmeldungen können manuell wieder gelöscht werden
|
|
||||||
- Es gibt Liste mit aktuellen Anmeldungen
|
|
||||||
|
|
||||||
### Ergochallenge
|
|
||||||
- Bilder + Dateneingabe
|
|
||||||
- Automatische Mail senden
|
|
||||||
|
|
||||||
## Backlog (i.e. don't work on this now)
|
|
||||||
### Sync w/ nextcloud
|
|
||||||
- remove most fields (names, ...) from users and add uid
|
|
||||||
- create user_nextcloud table; to be re-created every day(?)
|
|
||||||
|
|
||||||
user
|
|
||||||
- UID
|
|
||||||
- pw
|
|
||||||
- last_access
|
|
||||||
|
|
||||||
user_details
|
|
||||||
- UID
|
|
||||||
- fn (formatted name)
|
|
||||||
- is_cox (if CATEGORIES = {Steuerleute, Bootsführer})
|
|
||||||
- is_admin (if CATEGORIES = Admin)
|
|
||||||
- is_guest (if person not in nextcloud)
|
|
||||||
|
|
||||||
### Misc
|
|
||||||
- [] Don't show events if time > 1h(?) ago
|
|
||||||
- [] exactly same time -> deny registration
|
|
||||||
- [] automatically add regular planned trip
|
|
||||||
- [] same day+time: aggregate stats (x people, of which y cox and z rower)
|
|
||||||
- [] Lock trip; noone can register anymore
|
|
||||||
- [] on delete cascade doesn't work; e.g. created planned_event/trip + delete it -> trip_details entry still there!
|
|
||||||
- [] allow users to add u2f key
|
|
||||||
- [] Möglichkeiten für Bootseinteilungen bei planned_events anzeigen
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Frontend Process
|
# Frontend Process
|
||||||
´cd frontend´
|
´cd frontend´
|
||||||
´npm install´
|
´npm install´
|
||||||
@ -82,7 +5,6 @@ user_details
|
|||||||
|
|
||||||
# Notes / Bugfixes
|
# Notes / Bugfixes
|
||||||
## Frontend
|
## Frontend
|
||||||
- [] add UI for `trip_type`
|
|
||||||
- [] support esc to close sidebar
|
- [] support esc to close sidebar
|
||||||
- [] after an hour(?) of inactivity -> show large popup w/ "maybe old data (ignore) (reload page)" (ignore bc maybe use is actively doing something -> don't throw input away!)
|
- [] after an hour(?) of inactivity -> show large popup w/ "maybe old data (ignore) (reload page)" (ignore bc maybe use is actively doing something -> don't throw input away!)
|
||||||
|
|
||||||
@ -90,34 +12,3 @@ user_details
|
|||||||
# Nice to have
|
# Nice to have
|
||||||
## Frontend
|
## Frontend
|
||||||
- [] my trips for cox
|
- [] my trips for cox
|
||||||
|
|
||||||
# Missing backend tests
|
|
||||||
|
|
||||||
- [x] (index) GET /
|
|
||||||
- [x] (faq) GET /faq
|
|
||||||
- [x] (cal) GET /cal
|
|
||||||
- [x] (FileServer: svelte/build) GET /<path..>
|
|
||||||
- [x] (join) GET /join/<trip_details_id>
|
|
||||||
- [x] (remove) GET /remove/<trip_details_id>
|
|
||||||
- [x] (create) POST /cox/trip
|
|
||||||
- [x] (update) POST /cox/trip/<trip_id>
|
|
||||||
- [x] (join) GET /cox/join/<planned_event_id>
|
|
||||||
- [ ] (remove) GET /cox/remove/<planned_event_id>
|
|
||||||
- [ ] (remove_trip) GET /cox/remove/trip/<trip_id>
|
|
||||||
- [ ] (index) GET /auth/
|
|
||||||
- [ ] (login) POST /auth/
|
|
||||||
- [ ] (logout) GET /auth/logout
|
|
||||||
- [ ] (updatepw) POST /auth/set-pw
|
|
||||||
- [ ] (setpw) GET /auth/set-pw/<userid>
|
|
||||||
- [ ] (rss) GET /admin/rss?<key>
|
|
||||||
- [ ] (index) GET /admin/user
|
|
||||||
- [ ] (update) POST /admin/user
|
|
||||||
- [ ] (create) POST /admin/planned-event
|
|
||||||
- [ ] (update) PUT /admin/planned-event
|
|
||||||
- [ ] (create) POST /admin/user/new
|
|
||||||
- [ ] (delete) GET /admin/user/<user>/delete
|
|
||||||
- [ ] (resetpw) GET /admin/user/<user>/reset-pw
|
|
||||||
- [ ] (delete) GET /admin/planned-event/<id>/delete
|
|
||||||
- [ ] (FileServer: static/) GET /public/<path..> [10]
|
|
||||||
- [ ] (login) POST /api/login/
|
|
||||||
- [ ] /tera/admin/boat.rs
|
|
||||||
|
@ -176,7 +176,7 @@ FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM trip WHERE i
|
|||||||
db: &SqlitePool,
|
db: &SqlitePool,
|
||||||
cox: &CoxUser,
|
cox: &CoxUser,
|
||||||
planned_event: &PlannedEvent,
|
planned_event: &PlannedEvent,
|
||||||
) {
|
) -> bool {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"DELETE FROM trip WHERE cox_id = ? AND planned_event_id = ?",
|
"DELETE FROM trip WHERE cox_id = ? AND planned_event_id = ?",
|
||||||
cox.id,
|
cox.id,
|
||||||
@ -184,7 +184,9 @@ FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM trip WHERE i
|
|||||||
)
|
)
|
||||||
.execute(db)
|
.execute(db)
|
||||||
.await
|
.await
|
||||||
.unwrap(); //TODO: handle case where cox is not registered
|
.unwrap()
|
||||||
|
.rows_affected()
|
||||||
|
> 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn delete(
|
pub(crate) async fn delete(
|
||||||
|
103
src/tera/cox.rs
103
src/tera/cox.rs
@ -129,8 +129,7 @@ async fn remove_trip(db: &State<SqlitePool>, trip_id: i64, cox: CoxUser) -> Flas
|
|||||||
#[get("/remove/<planned_event_id>")]
|
#[get("/remove/<planned_event_id>")]
|
||||||
async fn remove(db: &State<SqlitePool>, planned_event_id: i64, cox: CoxUser) -> Flash<Redirect> {
|
async fn remove(db: &State<SqlitePool>, planned_event_id: i64, cox: CoxUser) -> Flash<Redirect> {
|
||||||
if let Some(planned_event) = PlannedEvent::find_by_id(db, planned_event_id).await {
|
if let Some(planned_event) = PlannedEvent::find_by_id(db, planned_event_id).await {
|
||||||
Trip::delete_by_planned_event(db, &cox, &planned_event).await;
|
if Trip::delete_by_planned_event(db, &cox, &planned_event).await {
|
||||||
|
|
||||||
Log::create(
|
Log::create(
|
||||||
db,
|
db,
|
||||||
format!(
|
format!(
|
||||||
@ -141,6 +140,9 @@ async fn remove(db: &State<SqlitePool>, planned_event_id: i64, cox: CoxUser) ->
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
Flash::success(Redirect::to("/"), "Erfolgreich abgemeldet!")
|
Flash::success(Redirect::to("/"), "Erfolgreich abgemeldet!")
|
||||||
|
} else {
|
||||||
|
Flash::error(Redirect::to("/"), "Steuermann hilft nicht aus...")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Flash::error(Redirect::to("/"), "Planned_event does not exist.")
|
Flash::error(Redirect::to("/"), "Planned_event does not exist.")
|
||||||
}
|
}
|
||||||
@ -425,4 +427,101 @@ mod test {
|
|||||||
|
|
||||||
assert_eq!(flash_cookie.value(), "5:errorEvent gibt's nicht");
|
assert_eq!(flash_cookie.value(), "5:errorEvent gibt's nicht");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[sqlx::test]
|
||||||
|
fn test_remove() {
|
||||||
|
let db = testdb!();
|
||||||
|
|
||||||
|
let rocket = rocket::build().manage(db.clone());
|
||||||
|
let rocket = crate::tera::config(rocket);
|
||||||
|
|
||||||
|
let client = Client::tracked(rocket).await.unwrap();
|
||||||
|
let login = client
|
||||||
|
.post("/auth")
|
||||||
|
.header(ContentType::Form) // Set the content type to form
|
||||||
|
.body("name=cox&password=cox"); // Add the form data to the request body;
|
||||||
|
login.dispatch().await;
|
||||||
|
|
||||||
|
let req = client.get("/cox/join/1");
|
||||||
|
let response = req.dispatch().await;
|
||||||
|
|
||||||
|
let flash_cookie = response
|
||||||
|
.cookies()
|
||||||
|
.get("_flash")
|
||||||
|
.expect("Expected flash cookie");
|
||||||
|
|
||||||
|
assert_eq!(flash_cookie.value(), "7:successDanke für's helfen!");
|
||||||
|
|
||||||
|
let req = client.get("/cox/join/1");
|
||||||
|
let response = req.dispatch().await;
|
||||||
|
|
||||||
|
let req = client.get("/cox/remove/1");
|
||||||
|
let response = req.dispatch().await;
|
||||||
|
|
||||||
|
assert_eq!(response.status(), Status::SeeOther);
|
||||||
|
assert_eq!(response.headers().get("Location").next(), Some("/"));
|
||||||
|
|
||||||
|
let flash_cookie = response
|
||||||
|
.cookies()
|
||||||
|
.get("_flash")
|
||||||
|
.expect("Expected flash cookie");
|
||||||
|
|
||||||
|
assert_eq!(flash_cookie.value(), "7:successErfolgreich abgemeldet!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[sqlx::test]
|
||||||
|
fn test_remove_wrong_id() {
|
||||||
|
let db = testdb!();
|
||||||
|
|
||||||
|
let rocket = rocket::build().manage(db.clone());
|
||||||
|
let rocket = crate::tera::config(rocket);
|
||||||
|
|
||||||
|
let client = Client::tracked(rocket).await.unwrap();
|
||||||
|
let login = client
|
||||||
|
.post("/auth")
|
||||||
|
.header(ContentType::Form) // Set the content type to form
|
||||||
|
.body("name=cox&password=cox"); // Add the form data to the request body;
|
||||||
|
login.dispatch().await;
|
||||||
|
|
||||||
|
let req = client.get("/cox/remove/999");
|
||||||
|
let response = req.dispatch().await;
|
||||||
|
|
||||||
|
assert_eq!(response.status(), Status::SeeOther);
|
||||||
|
assert_eq!(response.headers().get("Location").next(), Some("/"));
|
||||||
|
|
||||||
|
let flash_cookie = response
|
||||||
|
.cookies()
|
||||||
|
.get("_flash")
|
||||||
|
.expect("Expected flash cookie");
|
||||||
|
|
||||||
|
assert_eq!(flash_cookie.value(), "5:errorPlanned_event does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[sqlx::test]
|
||||||
|
fn test_remove_cox_not_participating() {
|
||||||
|
let db = testdb!();
|
||||||
|
|
||||||
|
let rocket = rocket::build().manage(db.clone());
|
||||||
|
let rocket = crate::tera::config(rocket);
|
||||||
|
|
||||||
|
let client = Client::tracked(rocket).await.unwrap();
|
||||||
|
let login = client
|
||||||
|
.post("/auth")
|
||||||
|
.header(ContentType::Form) // Set the content type to form
|
||||||
|
.body("name=cox&password=cox"); // Add the form data to the request body;
|
||||||
|
login.dispatch().await;
|
||||||
|
|
||||||
|
let req = client.get("/cox/remove/1");
|
||||||
|
let response = req.dispatch().await;
|
||||||
|
|
||||||
|
assert_eq!(response.status(), Status::SeeOther);
|
||||||
|
assert_eq!(response.headers().get("Location").next(), Some("/"));
|
||||||
|
|
||||||
|
let flash_cookie = response
|
||||||
|
.cookies()
|
||||||
|
.get("_flash")
|
||||||
|
.expect("Expected flash cookie");
|
||||||
|
|
||||||
|
assert_eq!(flash_cookie.value(), "5:errorSteuermann hilft nicht aus...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user