forked from Ruderverein-Donau-Linz/rowt
final touches
This commit is contained in:
parent
a95445c53c
commit
6e54b29288
21
Cargo.lock
generated
21
Cargo.lock
generated
@ -1185,6 +1185,15 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "keccak"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768"
|
||||||
|
dependencies = [
|
||||||
|
"cpufeatures",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kernel32-sys"
|
name = "kernel32-sys"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@ -2071,11 +2080,13 @@ name = "rot"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"hex",
|
||||||
"rocket",
|
"rocket",
|
||||||
"rocket_dyn_templates",
|
"rocket_dyn_templates",
|
||||||
"sea-orm",
|
"sea-orm",
|
||||||
"sea-orm-migration",
|
"sea-orm-migration",
|
||||||
"serde",
|
"serde",
|
||||||
|
"sha3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2377,6 +2388,16 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha3"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
"keccak",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sharded-slab"
|
name = "sharded-slab"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
@ -9,7 +9,8 @@ edition = "2021"
|
|||||||
sea-orm = { version = "^0", features = [ "sqlx-sqlite", "runtime-tokio-rustls", "macros" ] }
|
sea-orm = { version = "^0", features = [ "sqlx-sqlite", "runtime-tokio-rustls", "macros" ] }
|
||||||
sea-orm-migration = { version = "0.11", features = [ "runtime-tokio-rustls", "sqlx-sqlite" ] }
|
sea-orm-migration = { version = "0.11", features = [ "runtime-tokio-rustls", "sqlx-sqlite" ] }
|
||||||
serde = { version = "1.0", features = [ "derive" ]}
|
serde = { version = "1.0", features = [ "derive" ]}
|
||||||
rocket = "0.5.0-rc.2"
|
rocket = { version = "0.5.0-rc.2", features = ["secrets"]}
|
||||||
rocket_dyn_templates = { version = "0.1.0-rc.2", features= ["tera"] }
|
rocket_dyn_templates = { version = "0.1.0-rc.2", features= ["tera"] }
|
||||||
chrono = { version = "0.4", features = ["serde"]}
|
chrono = { version = "0.4", features = ["serde"]}
|
||||||
|
sha3 = "0.10"
|
||||||
|
hex = "0.4"
|
||||||
|
@ -19,6 +19,7 @@ impl MigrationTrait for Migration {
|
|||||||
.primary_key(),
|
.primary_key(),
|
||||||
)
|
)
|
||||||
.col(ColumnDef::new(User::Name).string().not_null().unique_key())
|
.col(ColumnDef::new(User::Name).string().not_null().unique_key())
|
||||||
|
.col(ColumnDef::new(User::Pw).string())
|
||||||
.col(
|
.col(
|
||||||
ColumnDef::new(User::IsCox)
|
ColumnDef::new(User::IsCox)
|
||||||
.boolean()
|
.boolean()
|
||||||
@ -49,6 +50,7 @@ pub enum User {
|
|||||||
Table,
|
Table,
|
||||||
Id,
|
Id,
|
||||||
Name,
|
Name,
|
||||||
|
Pw,
|
||||||
IsCox,
|
IsCox,
|
||||||
IsAdmin,
|
IsAdmin,
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use sea_orm::{DatabaseConnection, ModelTrait};
|
use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use super::{day, trip, user};
|
use super::{day, trip, user};
|
||||||
@ -10,16 +10,8 @@ pub struct TripWithUser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TripWithUser {
|
impl TripWithUser {
|
||||||
async fn new(trip: trip::Model, db: &DatabaseConnection) -> Self {
|
fn new(trip: trip::Model, user: user::Model) -> Self {
|
||||||
Self {
|
Self { trip, user }
|
||||||
trip: trip.clone(),
|
|
||||||
user: trip
|
|
||||||
.find_related(user::Entity)
|
|
||||||
.one(db)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,8 +24,17 @@ pub struct DayWithTrips {
|
|||||||
impl DayWithTrips {
|
impl DayWithTrips {
|
||||||
pub async fn new(day: day::Model, db: &DatabaseConnection) -> Self {
|
pub async fn new(day: day::Model, db: &DatabaseConnection) -> Self {
|
||||||
let mut trips = Vec::new();
|
let mut trips = Vec::new();
|
||||||
for trip in day.find_related(trip::Entity).all(db).await.unwrap() {
|
|
||||||
trips.push(TripWithUser::new(trip, db).await);
|
let trips_with_users: Vec<(trip::Model, Option<user::Model>)> = trip::Entity::find()
|
||||||
|
.filter(trip::Column::Day.eq(day.day))
|
||||||
|
.find_also_related(user::Entity)
|
||||||
|
.all(db)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
println!("{:#?}", trips_with_users);
|
||||||
|
|
||||||
|
for (trip, users) in trips_with_users {
|
||||||
|
trips.push(TripWithUser::new(trip, users.unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Self { day, trips }
|
Self { day, trips }
|
||||||
|
@ -14,6 +14,7 @@ pub struct Model {
|
|||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub pw: Option<String>,
|
||||||
pub is_cox: bool,
|
pub is_cox: bool,
|
||||||
pub is_admin: bool,
|
pub is_admin: bool,
|
||||||
}
|
}
|
||||||
@ -53,7 +54,7 @@ impl<'r> FromRequest<'r> for Model {
|
|||||||
type Error = UserError;
|
type Error = UserError;
|
||||||
|
|
||||||
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
|
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
|
||||||
match req.cookies().get("name") {
|
match req.cookies().get_private("name") {
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
let db = req.guard::<&'r State<DatabaseConnection>>();
|
let db = req.guard::<&'r State<DatabaseConnection>>();
|
||||||
let name = name.value();
|
let name = name.value();
|
||||||
@ -70,7 +71,7 @@ impl<'r> FromRequest<'r> for AdminUser {
|
|||||||
type Error = UserError;
|
type Error = UserError;
|
||||||
|
|
||||||
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
|
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
|
||||||
match req.cookies().get("name") {
|
match req.cookies().get_private("name") {
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
let db = req.guard::<&'r State<DatabaseConnection>>();
|
let db = req.guard::<&'r State<DatabaseConnection>>();
|
||||||
let name = name.value();
|
let name = name.value();
|
||||||
|
@ -14,6 +14,7 @@ use rocket::{
|
|||||||
};
|
};
|
||||||
use rocket_dyn_templates::{context, Template};
|
use rocket_dyn_templates::{context, Template};
|
||||||
use sea_orm::{Database, DatabaseConnection};
|
use sea_orm::{Database, DatabaseConnection};
|
||||||
|
use sha3::{Digest, Sha3_256};
|
||||||
|
|
||||||
use super::models::{all::DayWithTrips, day, user};
|
use super::models::{all::DayWithTrips, day, user};
|
||||||
|
|
||||||
@ -35,17 +36,18 @@ impl Deref for NaiveDateForm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/?<all>")]
|
||||||
async fn index(db: &State<DatabaseConnection>, user: user::Model) -> Template {
|
async fn index(db: &State<DatabaseConnection>, user: user::Model, all: Option<String>) -> Template {
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
|
|
||||||
let mut show_next_n_days = 6;
|
let mut show_next_n_days = 6;
|
||||||
|
if let Some(_) = all {
|
||||||
if user.is_cox {
|
if user.is_cox {
|
||||||
let end_of_year = NaiveDate::from_ymd_opt(Local::now().year(), 5, 31).unwrap();
|
let end_of_year = NaiveDate::from_ymd_opt(Local::now().year(), 12, 31).unwrap();
|
||||||
show_next_n_days = end_of_year
|
show_next_n_days = end_of_year
|
||||||
.signed_duration_since(Local::now().date_naive())
|
.signed_duration_since(Local::now().date_naive())
|
||||||
.num_days()
|
.num_days();
|
||||||
+ 1;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..show_next_n_days {
|
for i in 0..show_next_n_days {
|
||||||
@ -65,17 +67,45 @@ fn name() -> Template {
|
|||||||
#[derive(FromForm)]
|
#[derive(FromForm)]
|
||||||
struct NameForm {
|
struct NameForm {
|
||||||
name: String,
|
name: String,
|
||||||
|
pw: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[put("/name", data = "<name>")]
|
#[put("/name", data = "<name>")]
|
||||||
fn savename(name: Form<NameForm>, cookies: &CookieJar) -> Redirect {
|
async fn savename(
|
||||||
cookies.add(Cookie::new("name", name.name.clone()));
|
name: Form<NameForm>,
|
||||||
|
cookies: &CookieJar<'_>,
|
||||||
|
db: &State<DatabaseConnection>,
|
||||||
|
) -> Redirect {
|
||||||
|
let user = user::Model::find_or_create_user(&name.name, db.inner()).await;
|
||||||
|
match user.pw {
|
||||||
|
Some(pw) => {
|
||||||
|
match &name.pw {
|
||||||
|
Some(entered_pw) => {
|
||||||
|
let mut hasher = Sha3_256::new();
|
||||||
|
hasher.update(entered_pw);
|
||||||
|
let entered_pw = hasher.finalize();
|
||||||
|
|
||||||
|
if hex::encode(entered_pw) == pw {
|
||||||
|
cookies.add_private(Cookie::new("name", name.name.clone()));
|
||||||
|
} else {
|
||||||
|
Redirect::to("/"); // Wrong PW
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
Redirect::to("/"); // No PW supplied
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
cookies.add_private(Cookie::new("name", name.name.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
Redirect::to("/")
|
Redirect::to("/")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/logout")]
|
#[get("/logout")]
|
||||||
fn logout(cookies: &CookieJar) -> Redirect {
|
fn logout(cookies: &CookieJar) -> Redirect {
|
||||||
cookies.remove(Cookie::new("name", ""));
|
cookies.remove_private(Cookie::new("name", ""));
|
||||||
Redirect::to("/")
|
Redirect::to("/")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use rocket::{form::Form, response::Redirect, Route, State};
|
use rocket::{form::Form, response::Redirect, Route, State};
|
||||||
use rocket_dyn_templates::{context, Template};
|
use rocket_dyn_templates::{context, Template};
|
||||||
use sea_orm::{ActiveModelTrait, DatabaseConnection, EntityTrait, Set};
|
use sea_orm::{ActiveModelTrait, DatabaseConnection, EntityTrait, Set};
|
||||||
|
use sha3::{Digest, Sha3_256};
|
||||||
|
|
||||||
use crate::models::{day, user};
|
use crate::models::user;
|
||||||
|
|
||||||
use super::NaiveDateForm;
|
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
async fn index(db: &State<DatabaseConnection>, user: user::AdminUser) -> Template {
|
async fn index(db: &State<DatabaseConnection>, user: user::AdminUser) -> Template {
|
||||||
@ -15,6 +14,7 @@ async fn index(db: &State<DatabaseConnection>, user: user::AdminUser) -> Templat
|
|||||||
|
|
||||||
#[derive(FromForm)]
|
#[derive(FromForm)]
|
||||||
struct UserEditForm {
|
struct UserEditForm {
|
||||||
|
pw: Option<String>,
|
||||||
is_cox: bool,
|
is_cox: bool,
|
||||||
is_admin: bool,
|
is_admin: bool,
|
||||||
}
|
}
|
||||||
@ -26,12 +26,22 @@ async fn update(
|
|||||||
data: Form<UserEditForm>,
|
data: Form<UserEditForm>,
|
||||||
_user: user::AdminUser,
|
_user: user::AdminUser,
|
||||||
) -> Redirect {
|
) -> Redirect {
|
||||||
let new_user = user::ActiveModel {
|
let mut new_user = user::ActiveModel {
|
||||||
id: Set(id),
|
id: Set(id),
|
||||||
is_cox: Set(data.is_cox),
|
is_cox: Set(data.is_cox),
|
||||||
is_admin: Set(data.is_admin),
|
is_admin: Set(data.is_admin),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
if let Some(pw) = &data.pw {
|
||||||
|
if pw != "" {
|
||||||
|
let mut hasher = Sha3_256::new();
|
||||||
|
hasher.update(pw);
|
||||||
|
let entered_pw = hasher.finalize();
|
||||||
|
|
||||||
|
let pw = hex::encode(entered_pw);
|
||||||
|
new_user.pw = Set(Some(pw));
|
||||||
|
}
|
||||||
|
}
|
||||||
new_user.update(db.inner()).await.unwrap();
|
new_user.update(db.inner()).await.unwrap();
|
||||||
|
|
||||||
Redirect::to("/user")
|
Redirect::to("/user")
|
||||||
|
@ -83,5 +83,9 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
{% if user.is_cox %}
|
||||||
|
<a class="button" href="/?all">Alle heurigen Ausfahrten anzeigen</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
||||||
|
@ -3,8 +3,13 @@
|
|||||||
|
|
||||||
<form action="/name" method="post">
|
<form action="/name" method="post">
|
||||||
<input type="hidden" name="_method" value="put" />
|
<input type="hidden" name="_method" value="put" />
|
||||||
|
|
||||||
<label for="name">Bitte deinen Namen eingeben</label>
|
<label for="name">Bitte deinen Namen eingeben</label>
|
||||||
<input type="text" id="name" name="name"/>
|
<input type="text" id="name" name="name"/>
|
||||||
|
|
||||||
|
<label for="pw">(Optional) Passwort eingeben</label>
|
||||||
|
<input type="password" id="pw" name="pw"/>
|
||||||
|
|
||||||
<input type="submit" value="Weiter"/>
|
<input type="submit" value="Weiter"/>
|
||||||
</form>
|
</form>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
|
<th>Pw</th>
|
||||||
<th>Cox</th>
|
<th>Cox</th>
|
||||||
<th>Admin</th>
|
<th>Admin</th>
|
||||||
<th>Action</th>
|
<th>Action</th>
|
||||||
@ -16,6 +17,12 @@
|
|||||||
<form action="/user/{{ user.id }}" method="post">
|
<form action="/user/{{ user.id }}" method="post">
|
||||||
<input type="hidden" name="_method" value="put" />
|
<input type="hidden" name="_method" value="put" />
|
||||||
<td>{{user.name}}</td>
|
<td>{{user.name}}</td>
|
||||||
|
<td>
|
||||||
|
{% if user.pw %}
|
||||||
|
<input type="checkbox" checked disabled>
|
||||||
|
{% endif %}
|
||||||
|
<input type="password" name="pw" />
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="checkbox" name="is_cox" {% if user.is_cox %} checked="true"{% endif %}
|
<input type="checkbox" name="is_cox" {% if user.is_cox %} checked="true"{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user