332 lines
9.4 KiB
Rust
332 lines
9.4 KiB
Rust
use chrono::{DateTime, Utc};
|
|
use sqlx::{Execute, PgPool};
|
|
|
|
use super::{Area, Function, Role};
|
|
|
|
#[derive(Clone)]
|
|
pub struct User {
|
|
pub id: i32,
|
|
pub name: String,
|
|
pub email: String,
|
|
pub password: String,
|
|
pub salt: String,
|
|
pub role: Role,
|
|
pub function: Function,
|
|
pub area_id: i32,
|
|
pub area: Option<Area>,
|
|
pub locked: bool,
|
|
pub last_login: Option<DateTime<Utc>>,
|
|
pub receive_notifications: bool,
|
|
}
|
|
|
|
impl User {
|
|
pub async fn create(
|
|
pool: &PgPool,
|
|
name: &str,
|
|
email: &str,
|
|
password: &str,
|
|
salt: &str,
|
|
role: Role,
|
|
function: Function,
|
|
area_id: i32,
|
|
) -> anyhow::Result<i32> {
|
|
let created = sqlx::query!(
|
|
r#"
|
|
INSERT INTO user_ (name, email, password, salt, role, function, areaId)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
RETURNING id;
|
|
"#,
|
|
name,
|
|
email,
|
|
password,
|
|
salt,
|
|
role as Role,
|
|
function as Function,
|
|
area_id
|
|
)
|
|
.fetch_one(pool)
|
|
.await;
|
|
|
|
match created {
|
|
Ok(result) => Ok(result.id),
|
|
Err(err) => Err(err.into()),
|
|
}
|
|
}
|
|
|
|
pub async fn read_by_id(pool: &PgPool, id: i32) -> anyhow::Result<User> {
|
|
let record = sqlx::query!(
|
|
r#"
|
|
SELECT id,
|
|
name,
|
|
email,
|
|
password,
|
|
salt,
|
|
role AS "role: Role",
|
|
function AS "function: Function",
|
|
areaId,
|
|
locked,
|
|
lastLogin,
|
|
receiveNotifications
|
|
FROM user_
|
|
WHERE id = $1;
|
|
"#,
|
|
id,
|
|
)
|
|
.fetch_one(pool)
|
|
.await?;
|
|
|
|
let user = User {
|
|
id: record.id,
|
|
name: record.name,
|
|
email: record.email,
|
|
password: record.password,
|
|
salt: record.salt,
|
|
role: record.role,
|
|
function: record.function,
|
|
area_id: record.areaid,
|
|
area: None,
|
|
locked: record.locked,
|
|
last_login: record.lastlogin,
|
|
receive_notifications: record.receivenotifications,
|
|
};
|
|
|
|
Ok(user)
|
|
}
|
|
|
|
pub async fn read_for_login(pool: &PgPool, email: &str) -> anyhow::Result<Option<User>> {
|
|
let record = sqlx::query!(
|
|
r#"
|
|
SELECT id,
|
|
name,
|
|
email,
|
|
password,
|
|
salt,
|
|
role AS "role: Role",
|
|
function AS "function: Function",
|
|
areaId,
|
|
locked,
|
|
lastLogin,
|
|
receiveNotifications
|
|
FROM user_
|
|
WHERE email = $1;
|
|
"#,
|
|
email,
|
|
)
|
|
.fetch_optional(pool)
|
|
.await?;
|
|
|
|
let result = match record {
|
|
Some(record) => Some(User {
|
|
id: record.id,
|
|
name: record.name,
|
|
email: record.email,
|
|
password: record.password,
|
|
salt: record.salt,
|
|
role: record.role,
|
|
function: record.function,
|
|
area_id: record.areaid,
|
|
area: None,
|
|
locked: record.locked,
|
|
last_login: record.lastlogin,
|
|
receive_notifications: record.receivenotifications,
|
|
}),
|
|
None => None,
|
|
};
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
pub async fn read_all(pool: &PgPool) -> anyhow::Result<Vec<User>> {
|
|
let records = sqlx::query!(
|
|
r#"
|
|
SELECT id,
|
|
name,
|
|
email,
|
|
password,
|
|
salt,
|
|
role AS "role: Role",
|
|
function AS "function: Function",
|
|
areaId,
|
|
locked,
|
|
lastLogin,
|
|
receiveNotifications
|
|
FROM user_;
|
|
"#,
|
|
)
|
|
.fetch_all(pool)
|
|
.await?;
|
|
|
|
let result = records
|
|
.iter()
|
|
.map(|record| User {
|
|
id: record.id,
|
|
name: record.name.clone(),
|
|
email: record.email.clone(),
|
|
password: record.password.clone(),
|
|
salt: record.salt.clone(),
|
|
role: record.role.clone(),
|
|
function: record.function.clone(),
|
|
area_id: record.areaid,
|
|
area: None,
|
|
locked: record.locked,
|
|
last_login: record.lastlogin,
|
|
receive_notifications: record.receivenotifications,
|
|
})
|
|
.collect();
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
pub async fn read_all_including_area(pool: &PgPool) -> anyhow::Result<Vec<User>> {
|
|
let records = sqlx::query!(
|
|
r#"
|
|
SELECT
|
|
user_.id AS userId,
|
|
user_.name,
|
|
user_.email,
|
|
user_.password,
|
|
user_.salt,
|
|
user_.role AS "role: Role",
|
|
user_.function AS "function: Function",
|
|
user_.areaId,
|
|
user_.locked,
|
|
user_.lastLogin,
|
|
user_.receiveNotifications,
|
|
area.id,
|
|
area.name AS areaName
|
|
FROM user_
|
|
JOIN area ON user_.areaId = area.id
|
|
"#
|
|
)
|
|
.fetch_all(pool)
|
|
.await?;
|
|
|
|
let results = records
|
|
.iter()
|
|
.map(|record| User {
|
|
id: record.userid,
|
|
name: record.name.clone(),
|
|
email: record.email.clone(),
|
|
password: record.password.clone(),
|
|
salt: record.salt.clone(),
|
|
role: record.role.clone(),
|
|
function: record.function.clone(),
|
|
area_id: record.areaid,
|
|
area: Some(Area {
|
|
id: record.areaid,
|
|
name: record.areaname.clone(),
|
|
}),
|
|
locked: record.locked,
|
|
last_login: record.lastlogin,
|
|
receive_notifications: record.receivenotifications,
|
|
})
|
|
.collect();
|
|
|
|
Ok(results)
|
|
}
|
|
|
|
pub async fn read_all_by_area(pool: &PgPool, area_id: i32) -> anyhow::Result<Vec<User>> {
|
|
let records = sqlx::query!(
|
|
r#"
|
|
SELECT id,
|
|
name,
|
|
email,
|
|
password,
|
|
salt,
|
|
role AS "role: Role",
|
|
function AS "function: Function",
|
|
areaId,
|
|
locked,
|
|
lastLogin,
|
|
receiveNotifications
|
|
FROM user_
|
|
WHERE areaId = $1;
|
|
"#,
|
|
area_id
|
|
)
|
|
.fetch_all(pool)
|
|
.await?;
|
|
|
|
let result = records
|
|
.iter()
|
|
.map(|record| User {
|
|
id: record.id,
|
|
name: record.name.clone(),
|
|
email: record.email.clone(),
|
|
password: record.password.clone(),
|
|
salt: record.salt.clone(),
|
|
role: record.role.clone(),
|
|
function: record.function.clone(),
|
|
area_id: record.areaid,
|
|
area: None,
|
|
locked: record.locked,
|
|
last_login: record.lastlogin,
|
|
receive_notifications: record.receivenotifications,
|
|
})
|
|
.collect();
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
pub async fn update(
|
|
pool: &PgPool,
|
|
id: i32,
|
|
email: Option<&str>,
|
|
name: Option<&str>,
|
|
role: Option<Role>,
|
|
function: Option<Function>,
|
|
area_id: Option<i32>,
|
|
locked: Option<bool>
|
|
) -> anyhow::Result<()> {
|
|
let mut query_builder = sqlx::QueryBuilder::new("UPDATE user_ SET ");
|
|
let mut separated = query_builder.separated(", ");
|
|
|
|
if let Some(email) = email {
|
|
separated.push("email = ");
|
|
separated.push_bind_unseparated(email);
|
|
}
|
|
|
|
if let Some(name) = name {
|
|
separated.push("name = ");
|
|
separated.push_bind_unseparated(name);
|
|
}
|
|
|
|
if let Some(role) = role {
|
|
separated.push("role = ");
|
|
separated.push_bind_unseparated(role as Role);
|
|
}
|
|
|
|
if let Some(function) = function {
|
|
separated.push("function = ");
|
|
separated.push_bind_unseparated(function as Function);
|
|
}
|
|
|
|
if let Some(area_id) = area_id {
|
|
separated.push("areaId = ");
|
|
separated.push_bind_unseparated(area_id);
|
|
}
|
|
|
|
if let Some(locked) = locked {
|
|
separated.push("locked = ");
|
|
separated.push_bind_unseparated(locked);
|
|
}
|
|
|
|
query_builder.push(" WHERE id = ");
|
|
query_builder.push_bind(id);
|
|
query_builder.push(";");
|
|
|
|
query_builder.build()
|
|
.execute(pool)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn delete(pool: &PgPool, id: i32) -> anyhow::Result<()> {
|
|
sqlx::query!("DELETE FROM user_ WHERE id = $1", id)
|
|
.execute(pool)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
}
|