make station select w/ cookies
This commit is contained in:
parent
9a347d429b
commit
9c0e3e4fa7
24
Cargo.lock
generated
24
Cargo.lock
generated
@ -133,6 +133,29 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-extra"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45bf463831f5131b7d3c756525b305d40f1185b688565648a92e1392ca35713d"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum-core",
|
||||
"bytes",
|
||||
"cookie",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"mime",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
"serde",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.74"
|
||||
@ -1971,6 +1994,7 @@ name = "stationslauf"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum-extra",
|
||||
"chrono",
|
||||
"dotenv",
|
||||
"maud",
|
||||
|
@ -5,6 +5,7 @@ edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
axum = "0.8"
|
||||
axum-extra = { version = "0.10", features = [ "cookie" ]}
|
||||
chrono = { version = "0.4", features = ["serde"]}
|
||||
dotenv = "0.15"
|
||||
maud = { version = "0.27", features = ["axum"] }
|
||||
|
@ -11,7 +11,7 @@
|
||||
- [x] Route_station
|
||||
- [x] Team
|
||||
- [ ] Rating view
|
||||
- [ ] auth for stations -> cookie?
|
||||
- [ ] auth for stations -> private cookie for pw
|
||||
- [ ] Highscore list
|
||||
|
||||
## Fancy features
|
||||
|
129
src/station.rs
129
src/station.rs
@ -1,11 +1,25 @@
|
||||
use crate::{partials, Station};
|
||||
use axum::{extract::State, response::IntoResponse, routing::get, Router};
|
||||
use maud::{html, Markup};
|
||||
use crate::{err, partials, succ, Station};
|
||||
use axum::{
|
||||
extract::State,
|
||||
response::{IntoResponse, Redirect},
|
||||
routing::get,
|
||||
Router,
|
||||
};
|
||||
use axum_extra::extract::CookieJar;
|
||||
use maud::{html, Markup, PreEscaped};
|
||||
use sqlx::SqlitePool;
|
||||
use std::sync::Arc;
|
||||
use tower_sessions::Session;
|
||||
use tower_sessions::{cookie::Cookie, Session};
|
||||
|
||||
async fn station_picker(State(db): State<Arc<SqlitePool>>, session: Session) -> Markup {
|
||||
async fn station_picker(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
session: Session,
|
||||
jar: CookieJar,
|
||||
) -> Result<(CookieJar, Markup), (CookieJar, impl IntoResponse)> {
|
||||
let (jar, current_station_cookie) = get_station_cookie(&db, jar).await;
|
||||
if let Some(station) = current_station_cookie {
|
||||
return Err((jar, Redirect::to(&format!("/s/{}", station.id))));
|
||||
} else {
|
||||
let stations = Station::all(&db).await;
|
||||
let content = html! {
|
||||
h1 { "Wähle deine Station" }
|
||||
@ -19,21 +33,118 @@ async fn station_picker(State(db): State<Arc<SqlitePool>>, session: Session) ->
|
||||
}
|
||||
|
||||
};
|
||||
Ok((jar, partials::page(content, session, false).await))
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_station_cookie(db: &SqlitePool, jar: CookieJar) -> (CookieJar, Option<Station>) {
|
||||
let Some(station_id) = jar.get("station_id") else {
|
||||
return (jar, None); // No station_id cookie
|
||||
};
|
||||
|
||||
let station_id = match station_id.value().parse::<i64>() {
|
||||
Ok(number) => number,
|
||||
Err(_) => {
|
||||
// got some cookie which isn't a i64 -> destroy and start over again
|
||||
let jar = jar.remove(Cookie::from("station_id"));
|
||||
return (jar, None);
|
||||
}
|
||||
};
|
||||
|
||||
let Some(station) = Station::find_by_id(db, station_id).await else {
|
||||
// got some cookie with an i64 which is no valid station_id -> destroy and start over again
|
||||
let jar = jar.remove(Cookie::from("station_id"));
|
||||
return (jar, None);
|
||||
};
|
||||
|
||||
(jar, Some(station))
|
||||
}
|
||||
|
||||
async fn decide_between_stations(
|
||||
cookie: &Station,
|
||||
trying_to_access: &Station,
|
||||
session: Session,
|
||||
) -> Markup {
|
||||
let content = html! {
|
||||
h1 { "Wähle deine Station" }
|
||||
ul {
|
||||
li {
|
||||
"Die neu aufgerufene "
|
||||
(PreEscaped("→ "))
|
||||
a href=(format!("/s/{}", trying_to_access.id)) {
|
||||
button { (trying_to_access.name) }
|
||||
}
|
||||
}
|
||||
li {
|
||||
"Die Alte "
|
||||
(PreEscaped("→ "))
|
||||
a href=(format!("/s/{}", cookie.id)) {
|
||||
button { (cookie.name) }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
partials::page(content, session, false).await
|
||||
}
|
||||
|
||||
async fn view(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
session: Session,
|
||||
jar: CookieJar,
|
||||
axum::extract::Path(id): axum::extract::Path<i64>,
|
||||
) -> Markup {
|
||||
//let Some(route) = Route::find_by_id(&db, id).await else {
|
||||
//}
|
||||
todo!()
|
||||
) -> Result<(CookieJar, Markup), (CookieJar, impl IntoResponse)> {
|
||||
let (mut jar, current_station_cookie) = get_station_cookie(&db, jar).await;
|
||||
if current_station_cookie.is_none() {
|
||||
jar = jar.add(Cookie::new("station_id", id.to_string()));
|
||||
}
|
||||
if let Some(current_station_cookie) = current_station_cookie {
|
||||
if current_station_cookie.id != id {
|
||||
// user has a cookie, which is a different station than she is trying to access
|
||||
if let Some(station) = Station::find_by_id(&db, id).await {
|
||||
jar = jar.remove(Cookie::from("station_id"));
|
||||
// trying to access valid station id
|
||||
err!(session, "Du hast versucht eine neue Station zu öffnen obwohl du bereits eine andere Station offen hattest. Welche möchtest du nun verwenden?");
|
||||
return Ok((
|
||||
jar,
|
||||
decide_between_stations(¤t_station_cookie, &station, session).await,
|
||||
));
|
||||
} else {
|
||||
// user trying to access _in_valid station id -> make her aware + redirect to old
|
||||
err!(session, "Du hast versucht eine Station öffnen, die es nicht gibt. Nachdem du vorher schonmal eine andere Station (die es gibt) geöffnet hattest, bist du nun zu dieser weitergeleitet worden. Wenn du das nicht willst, logg dich bitte aus.");
|
||||
return Err((
|
||||
jar,
|
||||
Redirect::to(&format!("/s/{}", current_station_cookie.id)),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
let station = Station::find_by_id(&db, id).await.unwrap();
|
||||
let content = html! {
|
||||
nav {
|
||||
ul {
|
||||
li { strong { (format!("Station {}", station.name)) } }
|
||||
}
|
||||
ul {
|
||||
li { a href="/s/station-logout" { "Logout" } }
|
||||
}
|
||||
}
|
||||
h1 { "test" }
|
||||
};
|
||||
|
||||
Ok((jar, partials::page(content, session, false).await))
|
||||
}
|
||||
|
||||
async fn logout(session: Session, mut jar: CookieJar) -> (CookieJar, impl IntoResponse) {
|
||||
jar = jar.remove(Cookie::from("station_id"));
|
||||
|
||||
succ!(session, "Erfolgreich ausgeloggt!");
|
||||
|
||||
(jar, Redirect::to("/s"))
|
||||
}
|
||||
|
||||
pub(super) fn routes() -> Router<Arc<SqlitePool>> {
|
||||
Router::new()
|
||||
.route("/", get(station_picker))
|
||||
.route("/{id}", get(view))
|
||||
.route("/station-logout", get(logout))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user