forked from Ruderverein-Donau-Linz/rowt
192 lines
4.8 KiB
Rust
192 lines
4.8 KiB
Rust
use std::{cmp::Ordering, fmt::Display, ops::DerefMut};
|
|
|
|
use super::{activity::ActivityBuilder, user::AdminUser};
|
|
use serde::{Deserialize, Serialize};
|
|
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
|
|
|
|
#[derive(FromRow, Serialize, Clone, Deserialize, Debug)]
|
|
pub struct Role {
|
|
pub(crate) id: i64,
|
|
pub(crate) name: String,
|
|
pub(crate) formatted_name: Option<String>,
|
|
pub(crate) desc: Option<String>,
|
|
pub(crate) hide_in_lists: bool,
|
|
pub(crate) cluster: Option<String>,
|
|
}
|
|
|
|
// Implement PartialEq to compare roles based only on id
|
|
impl PartialEq for Role {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.id == other.id
|
|
}
|
|
}
|
|
|
|
// Implement Eq to indicate that equality is reflexive
|
|
impl Eq for Role {}
|
|
|
|
// Implement PartialOrd if you need to sort or compare roles
|
|
impl PartialOrd for Role {
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
Some(self.id.cmp(&other.id))
|
|
}
|
|
}
|
|
|
|
// Implement Ord if you need total ordering (for sorting)
|
|
impl Ord for Role {
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
self.id.cmp(&other.id)
|
|
}
|
|
}
|
|
|
|
impl Display for Role {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
if let Some(formatted_name) = &self.formatted_name {
|
|
write!(f, "{}", formatted_name)
|
|
} else {
|
|
write!(f, "{}", self.name)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Role {
|
|
pub async fn all(db: &SqlitePool) -> Vec<Role> {
|
|
sqlx::query_as!(
|
|
Role,
|
|
"SELECT id, name, formatted_name, desc, hide_in_lists, cluster FROM role"
|
|
)
|
|
.fetch_all(db)
|
|
.await
|
|
.unwrap()
|
|
}
|
|
|
|
pub async fn all_cluster(db: &SqlitePool, cluster: &str) -> Vec<Role> {
|
|
sqlx::query_as!(
|
|
Role,
|
|
r#"SELECT id,
|
|
CASE WHEN formatted_name IS NOT NULL AND formatted_name != ''
|
|
THEN formatted_name
|
|
ELSE name
|
|
END AS "name!: String",
|
|
'' as formatted_name,
|
|
desc,
|
|
hide_in_lists,
|
|
cluster
|
|
FROM role
|
|
WHERE cluster = ?"#,
|
|
cluster
|
|
)
|
|
.fetch_all(db)
|
|
.await
|
|
.unwrap()
|
|
}
|
|
|
|
pub async fn find_by_id(db: &SqlitePool, name: i32) -> Option<Self> {
|
|
sqlx::query_as!(
|
|
Self,
|
|
"
|
|
SELECT id, name, formatted_name, desc, hide_in_lists, cluster
|
|
FROM role
|
|
WHERE id like ?
|
|
",
|
|
name
|
|
)
|
|
.fetch_one(db)
|
|
.await
|
|
.ok()
|
|
}
|
|
pub async fn find_by_id_tx(db: &mut Transaction<'_, Sqlite>, name: i32) -> Option<Self> {
|
|
sqlx::query_as!(
|
|
Self,
|
|
"
|
|
SELECT id, name, formatted_name, desc, hide_in_lists, cluster
|
|
FROM role
|
|
WHERE id like ?
|
|
",
|
|
name
|
|
)
|
|
.fetch_one(db.deref_mut())
|
|
.await
|
|
.ok()
|
|
}
|
|
|
|
pub async fn find_by_name(db: &SqlitePool, name: &str) -> Option<Self> {
|
|
sqlx::query_as!(
|
|
Self,
|
|
"
|
|
SELECT id, name, formatted_name, desc, hide_in_lists, cluster
|
|
FROM role
|
|
WHERE name like ?
|
|
",
|
|
name
|
|
)
|
|
.fetch_one(db)
|
|
.await
|
|
.ok()
|
|
}
|
|
|
|
pub async fn find_by_name_tx(db: &mut Transaction<'_, Sqlite>, name: &str) -> Option<Self> {
|
|
sqlx::query_as!(
|
|
Self,
|
|
"
|
|
SELECT id, name, formatted_name, desc, hide_in_lists, cluster
|
|
FROM role
|
|
WHERE name like ?
|
|
",
|
|
name
|
|
)
|
|
.fetch_one(db.deref_mut())
|
|
.await
|
|
.ok()
|
|
}
|
|
|
|
pub async fn update(
|
|
&self,
|
|
db: &SqlitePool,
|
|
updated_by: &AdminUser,
|
|
formatted_name: &str,
|
|
desc: &str,
|
|
) -> Result<(), String> {
|
|
sqlx::query!(
|
|
"UPDATE role SET formatted_name=?, desc=? WHERE id=?",
|
|
formatted_name,
|
|
desc,
|
|
self.id
|
|
)
|
|
.execute(db)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
|
|
ActivityBuilder::new(&format!(
|
|
"{updated_by} hat Rolle {self} von {self:#?} auf FORMATTED_NAME={formatted_name}, DESC={desc} aktualisiert."
|
|
)).role(self).save(db).await;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn names_from_role(&self, db: &SqlitePool) -> Vec<String> {
|
|
let query = format!(
|
|
"SELECT u.name
|
|
FROM user u
|
|
JOIN user_role ur ON u.id = ur.user_id
|
|
JOIN role r ON ur.role_id = r.id
|
|
WHERE r.id = {} AND deleted=0;",
|
|
self.id
|
|
);
|
|
|
|
sqlx::query_scalar(&query).fetch_all(db).await.unwrap()
|
|
}
|
|
|
|
pub async fn mails_from_role(&self, db: &SqlitePool) -> Vec<String> {
|
|
let query = format!(
|
|
"SELECT u.mail
|
|
FROM user u
|
|
JOIN user_role ur ON u.id = ur.user_id
|
|
JOIN role r ON ur.role_id = r.id
|
|
WHERE r.id = {} AND deleted=0;",
|
|
self.id
|
|
);
|
|
|
|
sqlx::query_scalar(&query).fetch_all(db).await.unwrap()
|
|
}
|
|
}
|