Merge pull request 'add schnupper management' (#254) from staging into main
Reviewed-on: #254
This commit is contained in:
commit
754f746094
@ -842,6 +842,43 @@ impl<'r> FromRequest<'r> for DonauLinzUser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct SchnupperBetreuerUser(pub(crate) User);
|
||||||
|
|
||||||
|
impl From<SchnupperBetreuerUser> for User {
|
||||||
|
fn from(val: SchnupperBetreuerUser) -> Self {
|
||||||
|
val.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for SchnupperBetreuerUser {
|
||||||
|
type Target = User;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<'r> FromRequest<'r> for SchnupperBetreuerUser {
|
||||||
|
type Error = LoginError;
|
||||||
|
|
||||||
|
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
|
||||||
|
let db = req.rocket().state::<SqlitePool>().unwrap();
|
||||||
|
match User::from_request(req).await {
|
||||||
|
Outcome::Success(user) => {
|
||||||
|
if user.has_role(db, "schnupper-betreuer").await {
|
||||||
|
Outcome::Success(SchnupperBetreuerUser(user))
|
||||||
|
} else {
|
||||||
|
Outcome::Forward(Status::Forbidden)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Outcome::Error(f) => Outcome::Error(f),
|
||||||
|
Outcome::Forward(f) => Outcome::Forward(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct VorstandUser(pub(crate) User);
|
pub struct VorstandUser(pub(crate) User);
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ use crate::{
|
|||||||
pub mod boat;
|
pub mod boat;
|
||||||
pub mod mail;
|
pub mod mail;
|
||||||
pub mod planned_event;
|
pub mod planned_event;
|
||||||
|
pub mod schnupper;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
|
||||||
#[get("/rss?<key>")]
|
#[get("/rss?<key>")]
|
||||||
@ -74,6 +75,7 @@ async fn list(db: &State<SqlitePool>, _admin: AdminUser, list_form: Form<ListFor
|
|||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
let mut ret = Vec::new();
|
let mut ret = Vec::new();
|
||||||
ret.append(&mut user::routes());
|
ret.append(&mut user::routes());
|
||||||
|
ret.append(&mut schnupper::routes());
|
||||||
ret.append(&mut boat::routes());
|
ret.append(&mut boat::routes());
|
||||||
ret.append(&mut mail::routes());
|
ret.append(&mut mail::routes());
|
||||||
ret.append(&mut planned_event::routes());
|
ret.append(&mut planned_event::routes());
|
||||||
|
60
src/tera/admin/schnupper.rs
Normal file
60
src/tera/admin/schnupper.rs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
use crate::model::{
|
||||||
|
role::Role,
|
||||||
|
user::{SchnupperBetreuerUser, User, UserWithRoles},
|
||||||
|
};
|
||||||
|
use futures::future::join_all;
|
||||||
|
use rocket::{
|
||||||
|
get,
|
||||||
|
http::Status,
|
||||||
|
request::{FlashMessage, FromRequest, Outcome},
|
||||||
|
routes, Request, Route, State,
|
||||||
|
};
|
||||||
|
use rocket_dyn_templates::{tera::Context, Template};
|
||||||
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
|
// Custom request guard to extract the Referer header
|
||||||
|
struct Referer(String);
|
||||||
|
|
||||||
|
#[rocket::async_trait]
|
||||||
|
impl<'r> FromRequest<'r> for Referer {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
||||||
|
match request.headers().get_one("Referer") {
|
||||||
|
Some(referer) => Outcome::Success(Referer(referer.to_string())),
|
||||||
|
None => Outcome::Error((Status::BadRequest, ())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/schnupper")]
|
||||||
|
async fn index(
|
||||||
|
db: &State<SqlitePool>,
|
||||||
|
user: SchnupperBetreuerUser,
|
||||||
|
flash: Option<FlashMessage<'_>>,
|
||||||
|
) -> Template {
|
||||||
|
let schnupperant = Role::find_by_name(db, "schnupperant").await.unwrap();
|
||||||
|
|
||||||
|
let user_futures: Vec<_> = User::all_with_role(db, &schnupperant)
|
||||||
|
.await
|
||||||
|
.into_iter()
|
||||||
|
.map(|u| async move { UserWithRoles::from_user(u, db).await })
|
||||||
|
.collect();
|
||||||
|
let users: Vec<UserWithRoles> = join_all(user_futures).await;
|
||||||
|
|
||||||
|
let mut context = Context::new();
|
||||||
|
if let Some(msg) = flash {
|
||||||
|
context.insert("flash", &msg.into_inner());
|
||||||
|
}
|
||||||
|
context.insert("schnupperanten", &users);
|
||||||
|
context.insert(
|
||||||
|
"loggedin_user",
|
||||||
|
&UserWithRoles::from_user(user.into(), db).await,
|
||||||
|
);
|
||||||
|
|
||||||
|
Template::render("admin/schnupper/index", context.into_json())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn routes() -> Vec<Route> {
|
||||||
|
routes![index]
|
||||||
|
}
|
19
templates/admin/schnupper/index.html.tera
Normal file
19
templates/admin/schnupper/index.html.tera
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{% import "includes/macros" as macros %}
|
||||||
|
{% extends "base" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="max-w-screen-lg w-full">
|
||||||
|
{% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %}
|
||||||
|
<h1 class="h1">Schnupper Verwaltung</h1>
|
||||||
|
<div class="grid gap-3">
|
||||||
|
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
||||||
|
role="alert">
|
||||||
|
<h2 class="h2">Angemeldete Personen: {{ schnupperanten | length }}</h2>
|
||||||
|
<div class="text-sm p-3">
|
||||||
|
<ol class="ms-2" style="list-style: number;">
|
||||||
|
{% for user in schnupperanten %}<li class="py-1">{{ user.name }} ({{ user.mail }} | {{ user.notes }})</li>{% endfor %}
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -79,6 +79,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if "schnupper-betreuer" in loggedin_user.roles %}
|
||||||
|
<div class="grid gap-3">
|
||||||
|
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
||||||
|
role="alert">
|
||||||
|
<h2 class="h2">Schnupper-Betreuer</h2>
|
||||||
|
<div class="text-sm p-3">
|
||||||
|
<ul class="list-disc ms-2">
|
||||||
|
<li class="py-1">
|
||||||
|
<a href="/admin/schnupper" class="link-primary">Schnuppern</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% if "Vorstand" in loggedin_user.roles %}
|
{% if "Vorstand" in loggedin_user.roles %}
|
||||||
<div class="grid gap-3">
|
<div class="grid gap-3">
|
||||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
||||||
|
Loading…
Reference in New Issue
Block a user