allow moving scheckbuch -> regular
This commit is contained in:
parent
c47b1988b2
commit
9aab07422d
BIN
db.sqlite-journal
Normal file
BIN
db.sqlite-journal
Normal file
Binary file not shown.
70
src/lib.rs
70
src/lib.rs
@ -1,5 +1,7 @@
|
|||||||
#![allow(clippy::blocks_in_conditions)]
|
#![allow(clippy::blocks_in_conditions)]
|
||||||
|
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
pub mod model;
|
pub mod model;
|
||||||
|
|
||||||
#[cfg(feature = "rowing-tera")]
|
#[cfg(feature = "rowing-tera")]
|
||||||
@ -22,6 +24,74 @@ pub(crate) const FOERDERND: i64 = 8500;
|
|||||||
pub(crate) const SCHECKBUCH: i64 = 3000;
|
pub(crate) const SCHECKBUCH: i64 = 3000;
|
||||||
pub(crate) const EINSCHREIBGEBUEHR: i64 = 3000;
|
pub(crate) const EINSCHREIBGEBUEHR: i64 = 3000;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct NonEmptyString(String);
|
||||||
|
|
||||||
|
impl NonEmptyString {
|
||||||
|
pub fn new(s: String) -> Option<Self> {
|
||||||
|
if s.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(NonEmptyString(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_str(&self) -> &str {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_string(self) -> String {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement Deref to allow automatic dereferencing to &str
|
||||||
|
impl Deref for NonEmptyString {
|
||||||
|
type Target = str;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This allows &NonEmptyString to be converted to &str
|
||||||
|
impl AsRef<str> for NonEmptyString {
|
||||||
|
fn as_ref(&self) -> &str {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This allows NonEmptyString to be converted to String with .into()
|
||||||
|
impl From<NonEmptyString> for String {
|
||||||
|
fn from(s: NonEmptyString) -> Self {
|
||||||
|
s.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&str> for NonEmptyString {
|
||||||
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||||
|
if s.is_empty() {
|
||||||
|
Err("String cannot be empty")
|
||||||
|
} else {
|
||||||
|
Ok(NonEmptyString(s.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<String> for NonEmptyString {
|
||||||
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||||
|
if s.is_empty() {
|
||||||
|
Err("String cannot be empty")
|
||||||
|
} else {
|
||||||
|
Ok(NonEmptyString(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! testdb {
|
macro_rules! testdb {
|
||||||
|
@ -42,12 +42,20 @@ impl User {
|
|||||||
db: &SqlitePool,
|
db: &SqlitePool,
|
||||||
updated_by: &ManageUserUser,
|
updated_by: &ManageUserUser,
|
||||||
new_phone: &str,
|
new_phone: &str,
|
||||||
) -> Result<(), String> {
|
) {
|
||||||
let new_phone = new_phone.trim();
|
let new_phone = new_phone.trim();
|
||||||
|
|
||||||
let query = if new_phone.is_empty() {
|
let query = if new_phone.is_empty() {
|
||||||
|
if self.phone.is_none() {
|
||||||
|
return; // nothing to do
|
||||||
|
}
|
||||||
sqlx::query!("UPDATE user SET phone = NULL where id = ?", self.id)
|
sqlx::query!("UPDATE user SET phone = NULL where id = ?", self.id)
|
||||||
} else {
|
} else {
|
||||||
|
if let Some(old_phone) = &self.phone {
|
||||||
|
if old_phone == new_phone {
|
||||||
|
return; //nothing to do
|
||||||
|
}
|
||||||
|
}
|
||||||
sqlx::query!("UPDATE user SET phone = ? where id = ?", new_phone, self.id)
|
sqlx::query!("UPDATE user SET phone = ? where id = ?", new_phone, self.id)
|
||||||
};
|
};
|
||||||
query.execute(db).await.unwrap(); //Okay, because we can only create a User of a valid id
|
query.execute(db).await.unwrap(); //Okay, because we can only create a User of a valid id
|
||||||
@ -58,8 +66,6 @@ impl User {
|
|||||||
None => format!("{updated_by} has added a phone number for {self}: {new_phone}")
|
None => format!("{updated_by} has added a phone number for {self}: {new_phone}")
|
||||||
};
|
};
|
||||||
Log::create(db, msg).await;
|
Log::create(db, msg).await;
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn update_address(
|
pub(crate) async fn update_address(
|
||||||
@ -67,12 +73,20 @@ impl User {
|
|||||||
db: &SqlitePool,
|
db: &SqlitePool,
|
||||||
updated_by: &ManageUserUser,
|
updated_by: &ManageUserUser,
|
||||||
new_address: &str,
|
new_address: &str,
|
||||||
) -> Result<(), String> {
|
) {
|
||||||
let new_address = new_address.trim();
|
let new_address = new_address.trim();
|
||||||
|
|
||||||
let query = if new_address.is_empty() {
|
let query = if new_address.is_empty() {
|
||||||
|
if !self.address.is_none() {
|
||||||
|
return; // nothing to do
|
||||||
|
}
|
||||||
sqlx::query!("UPDATE user SET address = NULL where id = ?", self.id)
|
sqlx::query!("UPDATE user SET address = NULL where id = ?", self.id)
|
||||||
} else {
|
} else {
|
||||||
|
if let Some(old_address) = &self.address {
|
||||||
|
if old_address == new_address {
|
||||||
|
return; //nothing to do
|
||||||
|
}
|
||||||
|
}
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"UPDATE user SET address = ? where id = ?",
|
"UPDATE user SET address = ? where id = ?",
|
||||||
new_address,
|
new_address,
|
||||||
@ -87,8 +101,6 @@ impl User {
|
|||||||
None => format!("{updated_by} has added an address for {self}: {new_address}")
|
None => format!("{updated_by} has added an address for {self}: {new_address}")
|
||||||
};
|
};
|
||||||
Log::create(db, msg).await;
|
Log::create(db, msg).await;
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn update_nickname(
|
pub(crate) async fn update_nickname(
|
||||||
@ -313,6 +325,9 @@ impl User {
|
|||||||
if self.has_membership_pdf(db).await {
|
if self.has_membership_pdf(db).await {
|
||||||
return Err(format!("User {self} hat bereits eine Beitrittserklärung."));
|
return Err(format!("User {self} hat bereits eine Beitrittserklärung."));
|
||||||
}
|
}
|
||||||
|
if membership_pdf.len() == 0 {
|
||||||
|
return Err(format!("Keine Beitrittserklärung mitgeschickt."));
|
||||||
|
}
|
||||||
|
|
||||||
let mut stream = membership_pdf.open().await.unwrap();
|
let mut stream = membership_pdf.open().await.unwrap();
|
||||||
let mut buffer = Vec::new();
|
let mut buffer = Vec::new();
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use super::ScheckbuchUser;
|
use super::ScheckbuchUser;
|
||||||
use crate::model::{
|
use crate::model::{
|
||||||
logbook::{Logbook, LogbookWithBoatAndRowers},
|
logbook::{Logbook, LogbookWithBoatAndRowers},
|
||||||
role::Role,
|
|
||||||
user::User,
|
user::User,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
use std::{
|
use std::{fmt::Display, ops::DerefMut};
|
||||||
fmt::Display,
|
|
||||||
ops::{Deref, DerefMut},
|
|
||||||
};
|
|
||||||
|
|
||||||
use argon2::{password_hash::SaltString, Argon2, PasswordHasher};
|
use argon2::{password_hash::SaltString, Argon2, PasswordHasher};
|
||||||
use chrono::{Datelike, Local, NaiveDate};
|
use chrono::{Datelike, Local, NaiveDate};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use rocket::async_trait;
|
||||||
use rocket::{
|
use rocket::{
|
||||||
async_trait,
|
|
||||||
http::{Cookie, Status},
|
http::{Cookie, Status},
|
||||||
request::{self, FromRequest, Outcome},
|
request::{FromRequest, Outcome},
|
||||||
time::{Duration, OffsetDateTime},
|
time::{Duration, OffsetDateTime},
|
||||||
tokio::io::AsyncReadExt,
|
tokio::io::AsyncReadExt,
|
||||||
Request,
|
Request,
|
||||||
@ -35,6 +32,7 @@ use scheckbuch::ScheckbuchUser;
|
|||||||
mod basic;
|
mod basic;
|
||||||
mod fee;
|
mod fee;
|
||||||
pub(crate) mod member;
|
pub(crate) mod member;
|
||||||
|
pub(crate) mod regular;
|
||||||
pub(crate) mod scheckbuch;
|
pub(crate) mod scheckbuch;
|
||||||
|
|
||||||
#[derive(FromRow, Serialize, Deserialize, Clone, Debug, Eq, Hash, PartialEq)]
|
#[derive(FromRow, Serialize, Deserialize, Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
@ -119,10 +117,7 @@ impl User {
|
|||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.has_role(db, "Donau Linz").await {
|
if self.has_role(db, "schnupperant").await {
|
||||||
self.send_welcome_mail_full_member(db, mail, smtp_pw)
|
|
||||||
.await?;
|
|
||||||
} else if self.has_role(db, "schnupperant").await {
|
|
||||||
self.send_welcome_mail_schnupper(db, mail, smtp_pw).await?;
|
self.send_welcome_mail_schnupper(db, mail, smtp_pw).await?;
|
||||||
} else if let Some(scheckbuch) = ScheckbuchUser::new(db, self).await {
|
} else if let Some(scheckbuch) = ScheckbuchUser::new(db, self).await {
|
||||||
scheckbuch.notify(db, mail, smtp_pw).await?;
|
scheckbuch.notify(db, mail, smtp_pw).await?;
|
||||||
@ -182,57 +177,6 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_welcome_mail_full_member(
|
|
||||||
&self,
|
|
||||||
db: &SqlitePool,
|
|
||||||
mail: &str,
|
|
||||||
smtp_pw: &str,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
// 2 things to do:
|
|
||||||
// 1. Send mail to user
|
|
||||||
Mail::send_single(
|
|
||||||
db,
|
|
||||||
mail,
|
|
||||||
"Willkommen im ASKÖ Ruderverein Donau Linz!",
|
|
||||||
format!(
|
|
||||||
"Hallo {0},
|
|
||||||
|
|
||||||
herzlich willkommen im ASKÖ Ruderverein Donau Linz! Wir freuen uns sehr, dich als neues Mitglied in unserem Verein begrüßen zu dürfen.
|
|
||||||
|
|
||||||
Um dir den Einstieg zu erleichtern, findest du in unserem Handbuch alle wichtigen Informationen über unseren Verein: https://rudernlinz.at/book. Bei weiteren Fragen stehen dir die Adressen info@rudernlinz.at (für allgemeine Fragen) und it@rudernlinz.at (bei technischen Fragen) jederzeit zur Verfügung.
|
|
||||||
|
|
||||||
Du kannst auch gerne unserer Signal-Gruppe beitreten, um auf dem Laufenden zu bleiben und dich mit anderen Mitgliedern auszutauschen: https://signal.group/#CjQKICFrq6zSsRHxrucS3jEcQn6lknEXacAykwwLV3vNLKxPEhA17jxz7cpjfu3JZokLq1TH
|
|
||||||
|
|
||||||
Für die Organisation unserer Ausfahrten nutzen wir app.rudernlinz.at. Logge dich einfach mit deinem Namen ('{0}' ohne Anführungszeichen) ein, beim ersten Mal kannst du das Passwortfeld leer lassen. Unter 'Geplante Ausfahrten' kannst du dich jederzeit zu den Ausfahrten anmelden.
|
|
||||||
|
|
||||||
Beim nächsten Treffen im Verein, erinnere jemand vom Vorstand (https://rudernlinz.at/unser-verein/vorstand/) bitte daran, deinen Fingerabdruck zu registrieren, damit du Zugang zum Bootshaus erhältst.
|
|
||||||
|
|
||||||
Damit du dich noch mehr verbunden fühlst (:-)), haben wir im Bootshaus ein WLAN für Vereinsmitglieder 'ASKÖ Ruderverein Donau Linz' eingerichtet. Das Passwort dafür lautet 'donau1921' (ohne Anführungszeichen). Bitte gib das Passwort an keine vereinsfremden Personen weiter.
|
|
||||||
|
|
||||||
Wir freuen uns darauf, dich bald am Wasser zu sehen und gemeinsam tolle Erfahrungen zu sammeln!
|
|
||||||
|
|
||||||
Riemen- & Dollenbruch
|
|
||||||
ASKÖ Ruderverein Donau Linz", self.name),
|
|
||||||
smtp_pw,
|
|
||||||
).await?;
|
|
||||||
|
|
||||||
// 2. Notify all coxes
|
|
||||||
Notification::create_for_steering_people(
|
|
||||||
db,
|
|
||||||
&format!(
|
|
||||||
"Liebe Steuerberechtigte, seit {} gibt es ein neues Mitglied: {}",
|
|
||||||
self.member_since_date.clone().unwrap(),
|
|
||||||
self.name
|
|
||||||
),
|
|
||||||
"Neues Vereinsmitglied",
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn amount_boats(&self, db: &SqlitePool) -> i64 {
|
pub async fn amount_boats(&self, db: &SqlitePool) -> i64 {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"SELECT COUNT(*) as count FROM boat WHERE owner = ?",
|
"SELECT COUNT(*) as count FROM boat WHERE owner = ?",
|
||||||
@ -904,7 +848,7 @@ ASKÖ Ruderverein Donau Linz", self.name),
|
|||||||
impl<'r> FromRequest<'r> for User {
|
impl<'r> FromRequest<'r> for User {
|
||||||
type Error = LoginError;
|
type Error = LoginError;
|
||||||
|
|
||||||
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
|
async fn from_request(req: &'r Request<'_>) -> rocket::request::Outcome<Self, Self::Error> {
|
||||||
match req.cookies().get_private("loggedin_user") {
|
match req.cookies().get_private("loggedin_user") {
|
||||||
Some(user_id) => match user_id.value().parse::<i32>() {
|
Some(user_id) => match user_id.value().parse::<i32>() {
|
||||||
Ok(user_id) => {
|
Ok(user_id) => {
|
||||||
@ -939,7 +883,7 @@ macro_rules! special_user {
|
|||||||
pub(crate) user: User,
|
pub(crate) user: User,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for $name {
|
impl std::ops::Deref for $name {
|
||||||
type Target = User;
|
type Target = User;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.user
|
&self.user
|
||||||
@ -953,20 +897,20 @@ macro_rules! special_user {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<'r> FromRequest<'r> for $name {
|
impl<'r> rocket::request::FromRequest<'r> for $name {
|
||||||
type Error = LoginError;
|
type Error = crate::model::user::LoginError;
|
||||||
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
|
async fn from_request(req: &'r rocket::request::Request<'_>) -> rocket::request::Outcome<Self, Self::Error> {
|
||||||
let db = req.rocket().state::<SqlitePool>().unwrap();
|
let db = req.rocket().state::<SqlitePool>().unwrap();
|
||||||
match User::from_request(req).await {
|
match User::from_request(req).await {
|
||||||
Outcome::Success(user) => {
|
rocket::request::Outcome::Success(user) => {
|
||||||
if special_user!(@check_roles user, db, $($role)*) {
|
if special_user!(@check_roles user, db, $($role)*) {
|
||||||
Outcome::Success($name { user })
|
rocket::request::Outcome::Success($name { user })
|
||||||
} else {
|
} else {
|
||||||
Outcome::Forward(Status::Forbidden)
|
rocket::request::Outcome::Forward(rocket::http::Status::Forbidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Outcome::Error(f) => Outcome::Error(f),
|
rocket::request::Outcome::Error(f) => rocket::request::Outcome::Error(f),
|
||||||
Outcome::Forward(f) => Outcome::Forward(f),
|
rocket::request::Outcome::Forward(f) => rocket::request::Outcome::Forward(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
73
src/model/user/regular.rs
Normal file
73
src/model/user/regular.rs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
use super::User;
|
||||||
|
use crate::{
|
||||||
|
model::{mail::Mail, notification::Notification},
|
||||||
|
special_user,
|
||||||
|
};
|
||||||
|
use rocket::async_trait;
|
||||||
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
|
special_user!(RegularUser, +"Donau Linz", -"Unterstützend", -"Förderndes Mitglied");
|
||||||
|
|
||||||
|
impl RegularUser {
|
||||||
|
pub(crate) async fn notify(&self, db: &SqlitePool, smtp_pw: &str) -> Result<(), String> {
|
||||||
|
self.notify_coxes_about_new_regular(db).await;
|
||||||
|
self.send_welcome_mail_to_user(db, smtp_pw).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send_welcome_mail_to_user(
|
||||||
|
&self,
|
||||||
|
db: &SqlitePool,
|
||||||
|
smtp_pw: &str,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let Some(mail) = &self.mail else {
|
||||||
|
return Err(format!(
|
||||||
|
"Couldn't send welcome mail, as the user {self} has no mail..."
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
Mail::send_single(
|
||||||
|
db,
|
||||||
|
mail,
|
||||||
|
"Willkommen im ASKÖ Ruderverein Donau Linz!",
|
||||||
|
format!(
|
||||||
|
"Hallo {0},
|
||||||
|
|
||||||
|
herzlich willkommen im ASKÖ Ruderverein Donau Linz! Wir freuen uns sehr, dich als neues Mitglied in unserem Verein begrüßen zu dürfen.
|
||||||
|
|
||||||
|
Um dir den Einstieg zu erleichtern, findest du in unserem Handbuch alle wichtigen Informationen über unseren Verein: https://rudernlinz.at/book. Bei weiteren Fragen stehen dir die Adressen info@rudernlinz.at (für allgemeine Fragen) und it@rudernlinz.at (bei technischen Fragen) jederzeit zur Verfügung.
|
||||||
|
|
||||||
|
Du kannst auch gerne unserer Signal-Gruppe beitreten, um auf dem Laufenden zu bleiben und dich mit anderen Mitgliedern auszutauschen: https://signal.group/#CjQKICFrq6zSsRHxrucS3jEcQn6lknEXacAykwwLV3vNLKxPEhA17jxz7cpjfu3JZokLq1TH
|
||||||
|
|
||||||
|
Für die Organisation unserer Ausfahrten nutzen wir app.rudernlinz.at. Logge dich einfach mit deinem Namen ('{0}' ohne Anführungszeichen) ein, beim ersten Mal kannst du das Passwortfeld leer lassen. Unter 'Geplante Ausfahrten' kannst du dich jederzeit zu den Ausfahrten anmelden.
|
||||||
|
|
||||||
|
Beim nächsten Treffen im Verein, erinnere jemand vom Vorstand (https://rudernlinz.at/unser-verein/vorstand/) bitte daran, deinen Fingerabdruck zu registrieren, damit du Zugang zum Bootshaus erhältst.
|
||||||
|
|
||||||
|
Damit du dich noch mehr verbunden fühlst (:-)), haben wir im Bootshaus ein WLAN für Vereinsmitglieder 'ASKÖ Ruderverein Donau Linz' eingerichtet. Das Passwort dafür lautet 'donau1921' (ohne Anführungszeichen). Bitte gib das Passwort an keine vereinsfremden Personen weiter.
|
||||||
|
|
||||||
|
Wir freuen uns darauf, dich bald am Wasser zu sehen und gemeinsam tolle Erfahrungen zu sammeln!
|
||||||
|
|
||||||
|
Riemen- & Dollenbruch
|
||||||
|
ASKÖ Ruderverein Donau Linz", self.name),
|
||||||
|
smtp_pw,
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn notify_coxes_about_new_regular(&self, db: &SqlitePool) {
|
||||||
|
Notification::create_for_steering_people(
|
||||||
|
db,
|
||||||
|
&format!(
|
||||||
|
"Liebe Steuerberechtigte, seit {} gibt es ein neues Mitglied: {}",
|
||||||
|
self.member_since_date.clone().unwrap(),
|
||||||
|
self.name
|
||||||
|
),
|
||||||
|
"Neues Vereinsmitglied",
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
use super::member::Member;
|
use super::regular::RegularUser;
|
||||||
use super::{ManageUserUser, User};
|
use super::{ManageUserUser, User};
|
||||||
use crate::model::role::Role;
|
use crate::model::role::Role;
|
||||||
use crate::model::user::LoginError;
|
use crate::NonEmptyString;
|
||||||
use crate::tera::admin::user::ScheckToRegularForm;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
model::{mail::Mail, notification::Notification},
|
model::{mail::Mail, notification::Notification},
|
||||||
special_user, SCHECKBUCH,
|
special_user, SCHECKBUCH,
|
||||||
@ -10,13 +9,7 @@ use crate::{
|
|||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use rocket::async_trait;
|
use rocket::async_trait;
|
||||||
use rocket::fs::TempFile;
|
use rocket::fs::TempFile;
|
||||||
use rocket::http::Status;
|
|
||||||
use rocket::request;
|
|
||||||
use rocket::request::FromRequest;
|
|
||||||
use rocket::request::Outcome;
|
|
||||||
use rocket::Request;
|
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
special_user!(ScheckbuchUser, +"scheckbuch");
|
special_user!(ScheckbuchUser, +"scheckbuch");
|
||||||
|
|
||||||
@ -24,11 +17,12 @@ impl ScheckbuchUser {
|
|||||||
pub(crate) async fn convert_to_regular_user(
|
pub(crate) async fn convert_to_regular_user(
|
||||||
self,
|
self,
|
||||||
db: &SqlitePool,
|
db: &SqlitePool,
|
||||||
|
smtp_pw: &str,
|
||||||
changed_by: &ManageUserUser,
|
changed_by: &ManageUserUser,
|
||||||
member_since: &NaiveDate,
|
member_since: &NaiveDate,
|
||||||
birthdate: &NaiveDate,
|
birthdate: &NaiveDate,
|
||||||
phone: &str,
|
phone: NonEmptyString,
|
||||||
address: &str,
|
address: NonEmptyString,
|
||||||
membership_pdf: &TempFile<'_>,
|
membership_pdf: &TempFile<'_>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
// Set data
|
// Set data
|
||||||
@ -36,9 +30,9 @@ impl ScheckbuchUser {
|
|||||||
self.user
|
self.user
|
||||||
.update_member_since(db, changed_by, member_since)
|
.update_member_since(db, changed_by, member_since)
|
||||||
.await;
|
.await;
|
||||||
self.user.update_phone(db, changed_by, phone).await?;
|
|
||||||
self.user.update_address(db, changed_by, address).await?;
|
self.user.update_phone(db, changed_by, &phone).await;
|
||||||
self.user.update_address(db, changed_by, address).await?;
|
self.user.update_address(db, changed_by, &address).await;
|
||||||
self.user
|
self.user
|
||||||
.add_membership_pdf(db, changed_by, membership_pdf)
|
.add_membership_pdf(db, changed_by, membership_pdf)
|
||||||
.await?;
|
.await?;
|
||||||
@ -50,25 +44,13 @@ impl ScheckbuchUser {
|
|||||||
self.user.add_role(db, changed_by, ®ular).await?;
|
self.user.add_role(db, changed_by, ®ular).await?;
|
||||||
|
|
||||||
// Notify
|
// Notify
|
||||||
todo!() // Continue here
|
let regular = RegularUser::new(db, &self.user).await.unwrap();
|
||||||
|
regular.notify(db, smtp_pw).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
//async fn from(user: User, db: &SqlitePool, mail: &str, smtp_pw: &str) -> Result<(), String> {
|
// TODO: make private
|
||||||
// if user.has_role(db, "scheckbuch").await {
|
|
||||||
// return Err("User is already a scheckbuch".into());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // TODO: do we allow e.g. DonauLinz to scheckbuch?
|
|
||||||
|
|
||||||
// let scheckbuch = Role::find_by_name(db, "scheckbuch").await.unwrap();
|
|
||||||
// user.add_role(db, &scheckbuch).await.unwrap();
|
|
||||||
|
|
||||||
// // TODO: remove all other `membership_type` roles
|
|
||||||
// let new_user = Self::new(db, &user).await.unwrap();
|
|
||||||
|
|
||||||
// new_user.notify(db, mail, smtp_pw).await
|
|
||||||
//}
|
|
||||||
|
|
||||||
pub(crate) async fn notify(
|
pub(crate) async fn notify(
|
||||||
&self,
|
&self,
|
||||||
db: &SqlitePool,
|
db: &SqlitePool,
|
||||||
|
@ -390,13 +390,11 @@ async fn update_phone(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
match user.update_phone(db, &admin, &data.phone).await {
|
user.update_phone(db, &admin, &data.phone).await;
|
||||||
Ok(_) => Flash::success(
|
Flash::success(
|
||||||
Redirect::to(format!("/admin/user/{}", user.id)),
|
Redirect::to(format!("/admin/user/{}", user.id)),
|
||||||
"Telefonnummer erfolgreich geändert",
|
"Telefonnummer erfolgreich geändert",
|
||||||
),
|
)
|
||||||
Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", user.id)), e),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromForm, Debug)]
|
#[derive(FromForm, Debug)]
|
||||||
@ -418,13 +416,12 @@ async fn update_address(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
match user.update_address(db, &admin, &data.address).await {
|
user.update_address(db, &admin, &data.address).await;
|
||||||
Ok(_) => Flash::success(
|
|
||||||
Redirect::to(format!("/admin/user/{}", user.id)),
|
Flash::success(
|
||||||
"Adresse erfolgreich geändert",
|
Redirect::to(format!("/admin/user/{}", user.id)),
|
||||||
),
|
"Adresse erfolgreich geändert",
|
||||||
Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", user.id)), e),
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromForm, Debug)]
|
#[derive(FromForm, Debug)]
|
||||||
@ -831,6 +828,7 @@ async fn scheckbook_to_regular(
|
|||||||
db: &State<SqlitePool>,
|
db: &State<SqlitePool>,
|
||||||
data: Form<ScheckToRegularForm<'_>>,
|
data: Form<ScheckToRegularForm<'_>>,
|
||||||
admin: ManageUserUser,
|
admin: ManageUserUser,
|
||||||
|
config: &State<Config>,
|
||||||
id: i32,
|
id: i32,
|
||||||
) -> Flash<Redirect> {
|
) -> Flash<Redirect> {
|
||||||
let Some(user) = User::find_by_id(db, id).await else {
|
let Some(user) = User::find_by_id(db, id).await else {
|
||||||
@ -842,13 +840,19 @@ async fn scheckbook_to_regular(
|
|||||||
let Ok(birthdate) = NaiveDate::parse_from_str(&data.birthdate, "%Y-%m-%d") else {
|
let Ok(birthdate) = NaiveDate::parse_from_str(&data.birthdate, "%Y-%m-%d") else {
|
||||||
return Flash::error(
|
return Flash::error(
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
Redirect::to(format!("/admin/user/{id}")),
|
||||||
format!("Datum {} ist nicht im YYYY-MM-DD Format", &data.birthdate),
|
format!(
|
||||||
|
"Geburtsdatum {} ist nicht im YYYY-MM-DD Format",
|
||||||
|
&data.birthdate
|
||||||
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
let Ok(member_since) = NaiveDate::parse_from_str(&data.member_since, "%Y-%m-%d") else {
|
let Ok(member_since) = NaiveDate::parse_from_str(&data.member_since, "%Y-%m-%d") else {
|
||||||
return Flash::error(
|
return Flash::error(
|
||||||
Redirect::to(format!("/admin/user/{id}")),
|
Redirect::to(format!("/admin/user/{id}")),
|
||||||
format!("Datum {} ist nicht im YYYY-MM-DD Format", &data.birthdate),
|
format!(
|
||||||
|
"Beitrittsdatum {} ist nicht im YYYY-MM-DD Format",
|
||||||
|
&data.birthdate
|
||||||
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -859,14 +863,28 @@ async fn scheckbook_to_regular(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let Ok(phone) = data.phone.clone().try_into() else {
|
||||||
|
return Flash::error(
|
||||||
|
Redirect::to(format!("/admin/user/{id}")),
|
||||||
|
"Vereinsmitglied braucht eine Telefonnummer",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
let Ok(address) = data.address.clone().try_into() else {
|
||||||
|
return Flash::error(
|
||||||
|
Redirect::to(format!("/admin/user/{id}")),
|
||||||
|
"Vereinsmitglied braucht eine Adresse",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
match user
|
match user
|
||||||
.convert_to_regular_user(
|
.convert_to_regular_user(
|
||||||
db,
|
db,
|
||||||
|
&config.smtp_pw,
|
||||||
&admin,
|
&admin,
|
||||||
&member_since,
|
&member_since,
|
||||||
&birthdate,
|
&birthdate,
|
||||||
&data.phone,
|
phone,
|
||||||
&data.address,
|
address,
|
||||||
&data.membership_pdf,
|
&data.membership_pdf,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
Loading…
x
Reference in New Issue
Block a user