Files
rowt/src/scheduled/yearly_role_cleanup.rs
Philipp Hofer 3148d744e6
Some checks failed
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
yearly cleanup of roles; fixes #941
2025-11-21 10:32:59 +01:00

159 lines
5.2 KiB
Rust

use crate::model::{notification::Notification, role::Role};
use sqlx::SqlitePool;
pub async fn cleanup_roles(db: &SqlitePool) -> Result<(), String> {
log::info!("Starting yearly role cleanup...");
let mut tx = db.begin().await.map_err(|e| e.to_string())?;
// Find all roles to remove
let paid_role = Role::find_by_name_tx(&mut tx, "paid")
.await
.ok_or("Role 'paid' not found")?;
let schueler_role = Role::find_by_name_tx(&mut tx, "Schüler")
.await
.ok_or("Role 'Schüler' not found")?;
let student_role = Role::find_by_name_tx(&mut tx, "Student")
.await
.ok_or("Role 'Student' not found")?;
let no_einschreibgebuehr_role = Role::find_by_name_tx(&mut tx, "no-einschreibgebuehr")
.await
.ok_or("Role 'no-einschreibgebuehr' not found")?;
let half_rennrudern_role = Role::find_by_name_tx(&mut tx, "half-rennrudern")
.await
.ok_or("Role 'half-rennrudern' not found")?;
let participated_schnupperkurs_role =
Role::find_by_name_tx(&mut tx, "participated_schnupperkurs")
.await
.ok_or("Role 'participated_schnupperkurs' not found")?;
// Find scheckbuch role (needed to exclude users from "paid" removal -> they have still paid
// for the scheckbuch)
let scheckbuch_role = Role::find_by_name_tx(&mut tx, "scheckbuch")
.await
.ok_or("Role 'scheckbuch' not found")?;
// Remove "paid" role from all users EXCEPT those with scheckbuch role
let paid_removed = sqlx::query!(
"DELETE FROM user_role
WHERE role_id = ?
AND user_id NOT IN (
SELECT user_id FROM user_role WHERE role_id = ?
)",
paid_role.id,
scheckbuch_role.id
)
.execute(&mut *tx)
.await
.map_err(|e| e.to_string())?
.rows_affected();
// Remove other roles from all users
let schueler_removed =
sqlx::query!("DELETE FROM user_role WHERE role_id = ?", schueler_role.id)
.execute(&mut *tx)
.await
.map_err(|e| e.to_string())?
.rows_affected();
let student_removed = sqlx::query!("DELETE FROM user_role WHERE role_id = ?", student_role.id)
.execute(&mut *tx)
.await
.map_err(|e| e.to_string())?
.rows_affected();
let no_einschreibgebuehr_removed = sqlx::query!(
"DELETE FROM user_role WHERE role_id = ?",
no_einschreibgebuehr_role.id
)
.execute(&mut *tx)
.await
.map_err(|e| e.to_string())?
.rows_affected();
let half_rennrudern_removed = sqlx::query!(
"DELETE FROM user_role WHERE role_id = ?",
half_rennrudern_role.id
)
.execute(&mut *tx)
.await
.map_err(|e| e.to_string())?
.rows_affected();
let participated_schnupperkurs_removed = sqlx::query!(
"DELETE FROM user_role WHERE role_id = ?",
participated_schnupperkurs_role.id
)
.execute(&mut *tx)
.await
.map_err(|e| e.to_string())?
.rows_affected();
// Send notifications to admins and Vorstand
let admin_role = Role::find_by_name_tx(&mut tx, "admin")
.await
.ok_or("Role 'admin' not found")?;
let vorstand_role = Role::find_by_name_tx(&mut tx, "Vorstand")
.await
.ok_or("Role 'Vorstand' not found")?;
let notification_message_admin = format!(
"Jährliche Rollenbereinigung abgeschlossen. Die folgenden Rollen wurden entfernt: \
paid ({} Benutzer, außer Scheckbuch-Mitglieder), \
Schüler/Student ({}/{} Benutzer), \
no-einschreibgebuehr ({} Benutzer), \
half-rennrudern ({} Benutzer), \
participated_schnupperkurs ({} Benutzer). \
Die aktualisierten Gebühren können unter https://app.rudernlinz.at/admin/user/fees eingesehen werden.",
paid_removed,
schueler_removed,
student_removed,
no_einschreibgebuehr_removed,
half_rennrudern_removed,
participated_schnupperkurs_removed
);
let notification_message_vorstand = format!(
"Jährliche Rollenbereinigung abgeschlossen. \
Die aktualisierten Gebühren können unter https://app.rudernlinz.at/admin/user/fees eingesehen werden.",
);
// Notify admins
Notification::create_for_role_tx(
&mut tx,
&admin_role,
&notification_message_admin,
"Systembenachrichtigung",
Some("https://app.rudernlinz.at/admin/user/fees"),
None,
)
.await;
// Notify Vorstand
Notification::create_for_role_tx(
&mut tx,
&vorstand_role,
&notification_message_vorstand,
"Systembenachrichtigung",
Some("https://app.rudernlinz.at/admin/user/fees"),
None,
)
.await;
// Commit transaction
tx.commit().await.map_err(|e| e.to_string())?;
log::info!(
"Yearly role cleanup completed successfully: \
paid={}, Schüler={}, Student={}, no-einschreibgebuehr={}, \
half-rennrudern={}, participated_schnupperkurs={} removals",
paid_removed,
schueler_removed,
student_removed,
no_einschreibgebuehr_removed,
half_rennrudern_removed,
participated_schnupperkurs_removed
);
Ok(())
}