161 lines
4.1 KiB
Rust

use sqlx::{PgPool, Postgres};
use crate::model::member::Roles;
use super::Member as DbMember;
#[derive(validator::Validate)]
pub struct User {
pub user_id: uuid::Uuid,
#[validate(email)]
pub email: String,
pub password: Option<String>,
pub admin: bool,
}
#[derive(Debug)]
pub struct UpdateUser {
pub email: Option<String>,
pub password: Option<String>,
pub admin: Option<bool>,
}
impl User {
pub async fn insert(
transaction: &mut sqlx::Transaction<'_, Postgres>,
email: &str,
password: &str,
) -> Result<uuid::Uuid, sqlx::Error> {
let user_id = uuid::Uuid::new_v4();
sqlx::query!(
"
INSERT INTO users (
user_id, email, password, admin
)
VALUES (
$1, $2, $3, $4
);
",
&user_id,
email,
password,
false
)
.execute(&mut **transaction)
.await?;
Ok(user_id)
}
pub async fn get_from_email(transaction: &PgPool, email: String) -> Result<Self, sqlx::Error> {
let user = sqlx::query_as!(Self, "SELECT * FROM users WHERE email = $1", email)
.fetch_one(transaction)
.await?;
Ok(user)
}
pub async fn get(transaction: &PgPool, user_id: uuid::Uuid) -> Result<Self, sqlx::Error> {
let user = sqlx::query_as!(Self, "SELECT * FROM users WHERE user_id = $1", user_id)
.fetch_one(transaction)
.await?;
Ok(user)
}
pub async fn get_password(&self, pool: &PgPool) -> Result<String, sqlx::Error> {
let password = sqlx::query_scalar!(
"
SELECT password FROM users WHERE user_id = $1
",
self.user_id,
)
.fetch_one(pool)
.await?;
Ok(password)
}
pub async fn update(
&self,
transaction: &mut sqlx::Transaction<'_, Postgres>,
update_user: UpdateUser,
) -> Result<(), sqlx::Error> {
sqlx::query!(
"
UPDATE users
SET email = coalesce($1, email),
password = coalesce($2, password)
WHERE user_id = $3;
",
update_user.email,
update_user.password,
self.user_id
)
.execute(&mut **transaction)
.await?;
Ok(())
}
}
#[derive(Debug)]
pub struct UserMember {
user_id: uuid::Uuid,
member_id: String,
}
impl UserMember {
pub async fn insert_many(
transaction: &mut sqlx::Transaction<'_, Postgres>,
user_ids: &[uuid::Uuid],
member_ids: &[String],
) -> Result<(), sqlx::Error> {
sqlx::query!(
"
INSERT INTO users_members (
user_id, member_id
)
SELECT * FROM UNNEST($1::uuid[], $2::varchar[])
",
&user_ids[..],
&member_ids[..]
)
.execute(&mut **transaction)
.await?;
Ok(())
}
pub async fn get_roles(pool: &PgPool, user_id: &uuid::Uuid) -> Result<Roles, sqlx::Error> {
let roles = sqlx::query_scalar!(
"
SELECT roles FROM users_members INNER JOIN members ON users_members.member_id = members.member_id AND users_members.user_id = $1;
",
user_id
).fetch_all(pool).await?;
let roles: Vec<Roles> = roles.into_iter().map(|r| r.into()).collect();
let roles = roles
.into_iter()
.fold(Roles::empty(), |acc, flag| acc | flag);
Ok(roles)
}
pub async fn get_members_from_user(
pool: &PgPool,
user_id: &uuid::Uuid,
) -> Result<Vec<DbMember>, sqlx::Error> {
let members = sqlx::query_as!(DbMember,
"
SELECT members.* FROM users_members INNER JOIN members ON users_members.member_id = members.member_id AND users_members.user_id = $1;
",
user_id
).fetch_all(pool).await?;
Ok(members)
}
}