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, pub admin: bool, } #[derive(Debug)] pub struct UpdateUser { pub email: Option, pub password: Option, pub admin: Option, } impl User { pub async fn insert( transaction: &mut sqlx::Transaction<'_, Postgres>, email: &str, password: &str, ) -> Result { 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 { 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 { 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 { 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 { 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.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, 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) } }