forked from Ruderverein-Donau-Linz/rowt
		
	send welcome mail to new members
This commit is contained in:
		@@ -14,6 +14,58 @@ use super::{family::Family, log::Log, role::Role, user::User};
 | 
			
		||||
pub struct Mail {}
 | 
			
		||||
 | 
			
		||||
impl Mail {
 | 
			
		||||
    pub async fn send_single(
 | 
			
		||||
        db: &SqlitePool,
 | 
			
		||||
        to: &str,
 | 
			
		||||
        subject: &str,
 | 
			
		||||
        body: String,
 | 
			
		||||
        smtp_pw: &str,
 | 
			
		||||
    ) {
 | 
			
		||||
        let mut email = Message::builder()
 | 
			
		||||
            .from(
 | 
			
		||||
                "ASKÖ Ruderverein Donau Linz <no-reply@rudernlinz.at>"
 | 
			
		||||
                    .parse()
 | 
			
		||||
                    .unwrap(),
 | 
			
		||||
            )
 | 
			
		||||
            .reply_to(
 | 
			
		||||
                "ASKÖ Ruderverein Donau Linz <info@rudernlinz.at>"
 | 
			
		||||
                    .parse()
 | 
			
		||||
                    .unwrap(),
 | 
			
		||||
            )
 | 
			
		||||
            .to("ASKÖ Ruderverein Donau Linz <no-reply@rudernlinz.at>"
 | 
			
		||||
                .parse()
 | 
			
		||||
                .unwrap());
 | 
			
		||||
        let splitted = to.split(',');
 | 
			
		||||
        for single_rec in splitted {
 | 
			
		||||
            match single_rec.parse() {
 | 
			
		||||
                Ok(new_bcc_mail) => email = email.bcc(new_bcc_mail),
 | 
			
		||||
                Err(_) => {
 | 
			
		||||
                    Log::create(
 | 
			
		||||
                        db,
 | 
			
		||||
                        format!("Mail not sent to {single_rec}, because it could not be parsed"),
 | 
			
		||||
                    )
 | 
			
		||||
                    .await;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let email = email
 | 
			
		||||
            .subject(subject)
 | 
			
		||||
            .header(ContentType::TEXT_PLAIN)
 | 
			
		||||
            .body(body)
 | 
			
		||||
            .unwrap();
 | 
			
		||||
 | 
			
		||||
        let creds = Credentials::new("no-reply@rudernlinz.at".to_owned(), smtp_pw.into());
 | 
			
		||||
 | 
			
		||||
        let mailer = SmtpTransport::relay("mail.your-server.de")
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .credentials(creds)
 | 
			
		||||
            .build();
 | 
			
		||||
 | 
			
		||||
        // Send the email
 | 
			
		||||
        mailer.send(&email).unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn send(db: &SqlitePool, data: MailToSend<'_>, smtp_pw: String) -> bool {
 | 
			
		||||
        let mut email = Message::builder()
 | 
			
		||||
            .from(
 | 
			
		||||
 
 | 
			
		||||
@@ -69,6 +69,18 @@ impl Notification {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn create_for_role(
 | 
			
		||||
        db: &SqlitePool,
 | 
			
		||||
        role: &Role,
 | 
			
		||||
        message: &str,
 | 
			
		||||
        category: &str,
 | 
			
		||||
        link: Option<&str>,
 | 
			
		||||
    ) {
 | 
			
		||||
        let mut tx = db.begin().await.unwrap();
 | 
			
		||||
        Self::create_for_role_tx(&mut tx, role, message, category, link).await;
 | 
			
		||||
        tx.commit().await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn for_user(db: &SqlitePool, user: &User) -> Vec<Self> {
 | 
			
		||||
        let rows = sqlx::query!(
 | 
			
		||||
            "
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,10 @@ use rocket::{
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
 | 
			
		||||
 | 
			
		||||
use super::{family::Family, log::Log, role::Role, tripdetails::TripDetails, Day};
 | 
			
		||||
use super::{
 | 
			
		||||
    family::Family, log::Log, mail::Mail, notification::Notification, role::Role,
 | 
			
		||||
    tripdetails::TripDetails, Day,
 | 
			
		||||
};
 | 
			
		||||
use crate::tera::admin::user::UserEditForm;
 | 
			
		||||
 | 
			
		||||
const RENNRUDERBEITRAG: i32 = 11000;
 | 
			
		||||
@@ -137,6 +140,69 @@ impl Fee {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl User {
 | 
			
		||||
    pub async fn send_welcome_email(&self, db: &SqlitePool, smtp_pw: &str) -> Result<(), String> {
 | 
			
		||||
        if !self.has_role(db, "Donau Linz").await {
 | 
			
		||||
            return Err(format!(
 | 
			
		||||
                "Could not send welcome mail, because user {} is not in Donau Linz group",
 | 
			
		||||
                self.name
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let Some(mail) = &self.mail else {
 | 
			
		||||
            return Err(format!(
 | 
			
		||||
                "Could not send welcome mail, because user {} has no email address",
 | 
			
		||||
                self.name
 | 
			
		||||
            ));
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        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 und it@rudernlinz.at 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 mich (Philipp Hofer) bitte daran, deinen Fingerabdruck zu registrieren, damit du eigenständig Zugang zum Bootshaus erhältst.
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
        Log::create(
 | 
			
		||||
            db,
 | 
			
		||||
            format!("Willkommensemail wurde an {} versandt", self.name),
 | 
			
		||||
        )
 | 
			
		||||
        .await;
 | 
			
		||||
 | 
			
		||||
        let coxes = Role::find_by_name(db, "cox").await.unwrap();
 | 
			
		||||
        Notification::create_for_role(
 | 
			
		||||
            db,
 | 
			
		||||
            &coxes,
 | 
			
		||||
            &format!(
 | 
			
		||||
                "Liebe Steuerberechtigte, seit {} gibt es ein neues Mitglied: {}",
 | 
			
		||||
                self.member_since_date.clone().unwrap(),
 | 
			
		||||
                self.name
 | 
			
		||||
            ),
 | 
			
		||||
            "Neues Vereinsmitglied",
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
        .await;
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn fee(&self, db: &SqlitePool) -> Option<Fee> {
 | 
			
		||||
        if !self.has_role(db, "Donau Linz").await {
 | 
			
		||||
            return None;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,17 @@
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
 | 
			
		||||
use crate::model::{
 | 
			
		||||
    family::Family,
 | 
			
		||||
    log::Log,
 | 
			
		||||
    logbook::Logbook,
 | 
			
		||||
    role::Role,
 | 
			
		||||
    user::{
 | 
			
		||||
        AdminUser, User, UserWithDetails, UserWithMembershipPdf, UserWithRolesAndMembershipPdf,
 | 
			
		||||
        VorstandUser,
 | 
			
		||||
use crate::{
 | 
			
		||||
    model::{
 | 
			
		||||
        family::Family,
 | 
			
		||||
        log::Log,
 | 
			
		||||
        logbook::Logbook,
 | 
			
		||||
        role::Role,
 | 
			
		||||
        user::{
 | 
			
		||||
            AdminUser, User, UserWithDetails, UserWithMembershipPdf, UserWithRolesAndMembershipPdf,
 | 
			
		||||
            VorstandUser,
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    tera::Config,
 | 
			
		||||
};
 | 
			
		||||
use futures::future::join_all;
 | 
			
		||||
use rocket::{
 | 
			
		||||
@@ -202,6 +205,26 @@ async fn fees_paid(
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[get("/user/<user>/send-welcome-mail")]
 | 
			
		||||
async fn send_welcome_mail(
 | 
			
		||||
    db: &State<SqlitePool>,
 | 
			
		||||
    _admin: AdminUser,
 | 
			
		||||
    config: &State<Config>,
 | 
			
		||||
    user: i32,
 | 
			
		||||
) -> Flash<Redirect> {
 | 
			
		||||
    let Some(user) = User::find_by_id(db, user).await else {
 | 
			
		||||
        return Flash::error(Redirect::to("/admin/user"), "User does not exist");
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    match user.send_welcome_email(db, &config.smtp_pw).await {
 | 
			
		||||
        Ok(()) => Flash::success(
 | 
			
		||||
            Redirect::to("/admin/user"),
 | 
			
		||||
            format!("Willkommens-Email wurde an {} versandt.", user.name),
 | 
			
		||||
        ),
 | 
			
		||||
        Err(e) => Flash::error(Redirect::to("/admin/user"), e),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[get("/user/<user>/reset-pw")]
 | 
			
		||||
async fn resetpw(db: &State<SqlitePool>, _admin: AdminUser, user: i32) -> Flash<Redirect> {
 | 
			
		||||
    let user = User::find_by_id(db, user).await;
 | 
			
		||||
@@ -332,6 +355,7 @@ pub fn routes() -> Vec<Route> {
 | 
			
		||||
        fees,
 | 
			
		||||
        fees_paid,
 | 
			
		||||
        scheckbuch,
 | 
			
		||||
        download_membership_pdf
 | 
			
		||||
        download_membership_pdf,
 | 
			
		||||
        send_welcome_mail
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,10 @@
 | 
			
		||||
                                    <a class="block mt-1 font-normal text-primary-600 dark:text-primary-200 hover:text-primary-900 dark:hover:text-primary-300 underline"
 | 
			
		||||
                                       href="/admin/user/{{ user.id }}/reset-pw">Passwort zurücksetzen</a>
 | 
			
		||||
                                {% endif %}
 | 
			
		||||
				{% if not user.last_access and "Donau Linz" in user.roles and "admin" in loggedin_user.roles %}
 | 
			
		||||
                                    <a class="block mt-1 font-normal text-primary-600 dark:text-primary-200 hover:text-primary-900 dark:hover:text-primary-300 underline"
 | 
			
		||||
                                       href="/admin/user/{{ user.id }}/send-welcome-mail">Willkommensmail verschicken</a>
 | 
			
		||||
			    {% endif %}
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-3">
 | 
			
		||||
                                {% for role in roles %}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user