move todos to gitlab; write tests for /cox/remove/<id>; Closes #9

This commit is contained in:
philipp 2023-07-31 13:34:02 +02:00
parent c4100e6c68
commit bbb78cbc44
3 changed files with 115 additions and 123 deletions

109
README.md
View File

@ -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
´cd frontend´
´npm install´
@ -82,7 +5,6 @@ user_details
# Notes / Bugfixes
## Frontend
- [] add UI for `trip_type`
- [] 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!)
@ -90,34 +12,3 @@ user_details
# Nice to have
## Frontend
- [] 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

View File

@ -154,7 +154,7 @@ FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM trip WHERE i
.await
.unwrap(); //Okay, as trip can only be created with proper DB backing
let Some(trip_details_id) = trip_details.id else {
return Err(TripUpdateError::TripDetailsDoesNotExist); //TODO: Remove?
return Err(TripUpdateError::TripDetailsDoesNotExist); //TODO: Remove?
};
sqlx::query!(
@ -176,7 +176,7 @@ FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM trip WHERE i
db: &SqlitePool,
cox: &CoxUser,
planned_event: &PlannedEvent,
) {
) -> bool {
sqlx::query!(
"DELETE FROM trip WHERE cox_id = ? AND planned_event_id = ?",
cox.id,
@ -184,7 +184,9 @@ FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM trip WHERE i
)
.execute(db)
.await
.unwrap(); //TODO: handle case where cox is not registered
.unwrap()
.rows_affected()
> 0
}
pub(crate) async fn delete(

View File

@ -129,18 +129,20 @@ async fn remove_trip(db: &State<SqlitePool>, trip_id: i64, cox: CoxUser) -> Flas
#[get("/remove/<planned_event_id>")]
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 {
Trip::delete_by_planned_event(db, &cox, &planned_event).await;
if Trip::delete_by_planned_event(db, &cox, &planned_event).await {
Log::create(
db,
format!(
"Cox {} deleted registration for planned_event.id={}",
cox.name, planned_event_id
),
)
.await;
Log::create(
db,
format!(
"Cox {} deleted registration for planned_event.id={}",
cox.name, planned_event_id
),
)
.await;
Flash::success(Redirect::to("/"), "Erfolgreich abgemeldet!")
Flash::success(Redirect::to("/"), "Erfolgreich abgemeldet!")
} else {
Flash::error(Redirect::to("/"), "Steuermann hilft nicht aus...")
}
} else {
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");
}
#[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...");
}
}