2022-05-06 16:02:38 +02:00
|
|
|
#[cfg(feature = "dummy")]
|
|
|
|
use fake::Fake;
|
2022-05-06 11:47:18 +02:00
|
|
|
use model::{AccountId, AccountState, Email, FullAccount, Login, PassHash, Role};
|
2022-04-15 17:04:23 +02:00
|
|
|
use sqlx::PgPool;
|
|
|
|
|
2022-04-18 22:07:52 +02:00
|
|
|
use super::Result;
|
2022-05-06 16:02:38 +02:00
|
|
|
use crate::db_async_handler;
|
2022-04-15 17:04:23 +02:00
|
|
|
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
|
|
pub enum Error {
|
|
|
|
#[error("Can't create account")]
|
|
|
|
CantCreate,
|
|
|
|
#[error("Can't find account does to lack of identity")]
|
|
|
|
NoIdentity,
|
|
|
|
#[error("Account does not exists")]
|
|
|
|
NotExists,
|
2022-04-16 06:58:48 +02:00
|
|
|
#[error("Failed to load all accounts")]
|
|
|
|
All,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(actix::Message)]
|
|
|
|
#[rtype(result = "Result<Vec<FullAccount>>")]
|
|
|
|
pub struct AllAccounts;
|
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
db_async_handler!(AllAccounts, all_accounts, Vec<FullAccount>);
|
2022-04-16 06:58:48 +02:00
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
pub(crate) async fn all_accounts(_msg: AllAccounts, pool: PgPool) -> Result<Vec<FullAccount>> {
|
2022-04-16 06:58:48 +02:00
|
|
|
sqlx::query_as(
|
|
|
|
r#"
|
2022-04-19 16:49:30 +02:00
|
|
|
SELECT id, email, login, pass_hash, role, customer_id, state
|
2022-04-16 06:58:48 +02:00
|
|
|
FROM accounts
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.fetch_all(&pool)
|
|
|
|
.await
|
|
|
|
.map_err(|e| {
|
|
|
|
log::error!("{e:?}");
|
|
|
|
super::Error::Account(Error::All)
|
|
|
|
})
|
2022-04-15 17:04:23 +02:00
|
|
|
}
|
|
|
|
|
2022-05-06 16:02:38 +02:00
|
|
|
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
2022-04-15 17:04:23 +02:00
|
|
|
#[derive(actix::Message)]
|
|
|
|
#[rtype(result = "Result<FullAccount>")]
|
|
|
|
pub struct CreateAccount {
|
2022-05-06 16:02:38 +02:00
|
|
|
#[cfg_attr(feature = "dummy", dummy("fake::faker::internet::en::FreeEmail"))]
|
2022-04-15 17:04:23 +02:00
|
|
|
pub email: Email,
|
2022-05-06 16:02:38 +02:00
|
|
|
#[cfg_attr(feature = "dummy", dummy("fake::faker::internet::en::Username"))]
|
2022-04-15 17:04:23 +02:00
|
|
|
pub login: Login,
|
|
|
|
pub pass_hash: PassHash,
|
|
|
|
pub role: Role,
|
|
|
|
}
|
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
db_async_handler!(CreateAccount, create_account, FullAccount);
|
2022-04-15 17:04:23 +02:00
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
pub(crate) async fn create_account(msg: CreateAccount, db: PgPool) -> Result<FullAccount> {
|
2022-04-15 17:04:23 +02:00
|
|
|
sqlx::query_as(
|
|
|
|
r#"
|
|
|
|
INSERT INTO accounts (login, email, role, pass_hash)
|
|
|
|
VALUES ($1, $2, $3, $4)
|
2022-04-19 16:49:30 +02:00
|
|
|
RETURNING id, email, login, pass_hash, role, customer_id, state
|
2022-04-18 08:22:51 +02:00
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.bind(msg.login)
|
|
|
|
.bind(msg.email)
|
|
|
|
.bind(msg.role)
|
|
|
|
.bind(msg.pass_hash)
|
|
|
|
.fetch_one(&db)
|
|
|
|
.await
|
|
|
|
.map_err(|e| {
|
|
|
|
log::error!("{e:?}");
|
|
|
|
super::Error::Account(Error::CantCreate)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-05-06 16:02:38 +02:00
|
|
|
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
2022-04-18 08:22:51 +02:00
|
|
|
#[derive(actix::Message)]
|
|
|
|
#[rtype(result = "Result<FullAccount>")]
|
|
|
|
pub struct UpdateAccount {
|
|
|
|
pub id: AccountId,
|
|
|
|
pub email: Email,
|
|
|
|
pub login: Login,
|
2022-04-19 16:49:30 +02:00
|
|
|
pub pass_hash: Option<PassHash>,
|
2022-04-18 08:22:51 +02:00
|
|
|
pub role: Role,
|
2022-04-19 16:49:30 +02:00
|
|
|
pub state: AccountState,
|
2022-04-18 08:22:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
db_async_handler!(UpdateAccount, update_account, FullAccount);
|
|
|
|
|
|
|
|
pub(crate) async fn update_account(msg: UpdateAccount, db: PgPool) -> Result<FullAccount> {
|
2022-04-19 16:49:30 +02:00
|
|
|
match msg.pass_hash {
|
|
|
|
Some(hash) => sqlx::query_as(
|
|
|
|
r#"
|
|
|
|
UPDATE accounts
|
|
|
|
SET login = $2 AND email = $3 AND role = $4 AND pass_hash = $5 AND state = $6
|
|
|
|
WHERE id = $1
|
|
|
|
RETURNING id, email, login, pass_hash, role, customer_id, state
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.bind(msg.login)
|
|
|
|
.bind(msg.email)
|
|
|
|
.bind(msg.role)
|
|
|
|
.bind(hash)
|
|
|
|
.bind(msg.state),
|
|
|
|
None => sqlx::query_as(
|
|
|
|
r#"
|
2022-04-18 08:22:51 +02:00
|
|
|
UPDATE accounts
|
|
|
|
SET login = $2 AND email = $3 AND role = $4 AND pass_hash = $5
|
|
|
|
WHERE id = $1
|
2022-04-19 16:49:30 +02:00
|
|
|
RETURNING id, email, login, pass_hash, role, customer_id, state
|
2022-04-15 17:04:23 +02:00
|
|
|
"#,
|
2022-04-19 16:49:30 +02:00
|
|
|
)
|
|
|
|
.bind(msg.login)
|
|
|
|
.bind(msg.email)
|
|
|
|
.bind(msg.role)
|
|
|
|
.bind(msg.state),
|
|
|
|
}
|
2022-04-15 17:04:23 +02:00
|
|
|
.fetch_one(&db)
|
|
|
|
.await
|
|
|
|
.map_err(|e| {
|
|
|
|
log::error!("{e:?}");
|
|
|
|
super::Error::Account(Error::CantCreate)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(actix::Message)]
|
|
|
|
#[rtype(result = "Result<FullAccount>")]
|
|
|
|
pub struct FindAccount {
|
|
|
|
pub account_id: AccountId,
|
|
|
|
}
|
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
db_async_handler!(FindAccount, find_account, FullAccount);
|
2022-04-15 17:04:23 +02:00
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
pub(crate) async fn find_account(msg: FindAccount, db: PgPool) -> Result<FullAccount> {
|
2022-04-15 17:04:23 +02:00
|
|
|
sqlx::query_as(
|
|
|
|
r#"
|
2022-04-19 16:49:30 +02:00
|
|
|
SELECT id, email, login, pass_hash, role, customer_id, state
|
2022-04-15 17:04:23 +02:00
|
|
|
FROM accounts
|
|
|
|
WHERE id = $1
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.bind(msg.account_id)
|
|
|
|
.fetch_one(&db)
|
|
|
|
.await
|
|
|
|
.map_err(|e| {
|
|
|
|
log::error!("{e:?}");
|
|
|
|
super::Error::Account(Error::NotExists)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(actix::Message)]
|
|
|
|
#[rtype(result = "Result<FullAccount>")]
|
|
|
|
pub struct AccountByIdentity {
|
|
|
|
pub login: Option<Login>,
|
|
|
|
pub email: Option<Email>,
|
|
|
|
}
|
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
db_async_handler!(AccountByIdentity, account_by_identity, FullAccount);
|
2022-04-15 17:04:23 +02:00
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
pub(crate) async fn account_by_identity(msg: AccountByIdentity, db: PgPool) -> Result<FullAccount> {
|
2022-04-15 17:04:23 +02:00
|
|
|
match (msg.login, msg.email) {
|
|
|
|
(Some(login), None) => sqlx::query_as(
|
|
|
|
r#"
|
2022-04-19 16:49:30 +02:00
|
|
|
SELECT id, email, login, pass_hash, role, customer_id, state
|
2022-04-15 17:04:23 +02:00
|
|
|
FROM accounts
|
|
|
|
WHERE login = $1
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.bind(login),
|
|
|
|
(None, Some(email)) => sqlx::query_as(
|
|
|
|
r#"
|
2022-04-19 16:49:30 +02:00
|
|
|
SELECT id, email, login, pass_hash, role, customer_id, state
|
2022-04-15 17:04:23 +02:00
|
|
|
FROM accounts
|
|
|
|
WHERE email = $1
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.bind(email),
|
|
|
|
(Some(login), Some(email)) => sqlx::query_as(
|
|
|
|
r#"
|
2022-04-19 16:49:30 +02:00
|
|
|
SELECT id, email, login, pass_hash, role, customer_id, state
|
2022-04-15 17:04:23 +02:00
|
|
|
FROM accounts
|
|
|
|
WHERE login = $1 AND email = $2
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.bind(login)
|
|
|
|
.bind(email),
|
|
|
|
_ => return Err(super::Error::Account(Error::NoIdentity)),
|
|
|
|
}
|
|
|
|
.fetch_one(&db)
|
|
|
|
.await
|
|
|
|
.map_err(|e| {
|
|
|
|
log::error!("{e:?}");
|
|
|
|
super::Error::Account(Error::CantCreate)
|
|
|
|
})
|
|
|
|
}
|