Fix update account, db tests

This commit is contained in:
eraden 2022-06-04 16:05:18 +02:00
parent 4087b2c3ee
commit a0b9720991
5 changed files with 405 additions and 35 deletions

View File

@ -232,9 +232,9 @@ mod test {
let hash: String = fake::faker::internet::en::Password(10..20).fake(); let hash: String = fake::faker::internet::en::Password(10..20).fake();
db.send(CreateAccount { db.send(CreateAccount {
email: model::Email::new(email), email: Email::new(email),
login: model::Login::new(login), login: Login::new(login),
pass_hash: model::PassHash::new(hash), pass_hash: PassHash::new(hash),
role: Role::Admin, role: Role::Admin,
}) })
.await .await
@ -250,7 +250,7 @@ mod test {
.database_mut() .database_mut()
.set_url("postgres://postgres@localhost/bazzar_test"); .set_url("postgres://postgres@localhost/bazzar_test");
let db = crate::Database::build(config).await.start(); let db = Database::build(config).await.start();
// account // account
let account = test_create_account(db.clone()).await; let account = test_create_account(db.clone()).await;
@ -286,7 +286,7 @@ mod test {
assert_eq!( assert_eq!(
address, address,
model::AccountAddress { model::AccountAddress {
id: model::AddressId::new(1), id: address.id,
name: model::Name::new(name.clone()), name: model::Name::new(name.clone()),
email: model::Email::new(email.clone()), email: model::Email::new(email.clone()),
phone: model::Phone::new(phone.clone()), phone: model::Phone::new(phone.clone()),

View File

@ -16,6 +16,8 @@ pub enum Error {
NotExists, NotExists,
#[error("Failed to load all accounts")] #[error("Failed to load all accounts")]
All, All,
#[error("Can't update account")]
CantUpdate,
} }
#[derive(actix::Message)] #[derive(actix::Message)]
@ -90,11 +92,12 @@ pub(crate) async fn update_account(msg: UpdateAccount, db: PgPool) -> Result<Ful
Some(hash) => sqlx::query_as( Some(hash) => sqlx::query_as(
r#" r#"
UPDATE accounts UPDATE accounts
SET login = $2 AND email = $3 AND role = $4 AND pass_hash = $5 AND state = $6 SET login = $2, email = $3, role = $4, pass_hash = $5, state = $6
WHERE id = $1 WHERE id = $1
RETURNING id, email, login, pass_hash, role, customer_id, state RETURNING id, email, login, pass_hash, role, customer_id, state
"#, "#,
) )
.bind(msg.id)
.bind(msg.login) .bind(msg.login)
.bind(msg.email) .bind(msg.email)
.bind(msg.role) .bind(msg.role)
@ -103,11 +106,12 @@ RETURNING id, email, login, pass_hash, role, customer_id, state
None => sqlx::query_as( None => sqlx::query_as(
r#" r#"
UPDATE accounts UPDATE accounts
SET login = $2 AND email = $3 AND role = $4 AND pass_hash = $5 SET login = $2, email = $3, role = $4, state = $5
WHERE id = $1 WHERE id = $1
RETURNING id, email, login, pass_hash, role, customer_id, state RETURNING id, email, login, pass_hash, role, customer_id, state
"#, "#,
) )
.bind(msg.id)
.bind(msg.login) .bind(msg.login)
.bind(msg.email) .bind(msg.email)
.bind(msg.role) .bind(msg.role)
@ -117,7 +121,7 @@ RETURNING id, email, login, pass_hash, role, customer_id, state
.await .await
.map_err(|e| { .map_err(|e| {
log::error!("{e:?}"); log::error!("{e:?}");
super::Error::Account(Error::CantCreate) super::Error::Account(Error::CantUpdate)
}) })
} }
@ -191,3 +195,271 @@ WHERE login = $1 AND email = $2
super::Error::Account(Error::CantCreate) super::Error::Account(Error::CantCreate)
}) })
} }
#[cfg(test)]
mod tests {
use actix::Addr;
use config::UpdateConfig;
use fake::Fake;
use model::*;
use crate::*;
pub struct NoOpts;
impl UpdateConfig for NoOpts {}
async fn test_create_account(
db: Addr<Database>,
login: Option<String>,
email: Option<String>,
hash: Option<String>,
) -> FullAccount {
use fake::faker::internet::en;
let login: String = login.unwrap_or_else(|| en::Username().fake());
let email: String = email.unwrap_or_else(|| en::FreeEmail().fake());
let hash: String = hash.unwrap_or_else(|| en::Password(10..20).fake());
db.send(CreateAccount {
email: Email::new(email),
login: Login::new(login),
pass_hash: PassHash::new(hash),
role: Role::Admin,
})
.await
.unwrap()
.unwrap()
}
#[actix::test]
async fn create_account() {
let config = config::default_load(&mut NoOpts);
config
.lock()
.database_mut()
.set_url("postgres://postgres@localhost/bazzar_test");
let db = Database::build(config).await.start();
let login: String = fake::faker::internet::en::Username().fake();
let email: String = fake::faker::internet::en::FreeEmail().fake();
let hash: String = fake::faker::internet::en::Password(10..20).fake();
let account: FullAccount = db
.send(CreateAccount {
email: Email::new(&email),
login: Login::new(&login),
pass_hash: PassHash::new(&hash),
role: Role::Admin,
})
.await
.unwrap()
.unwrap();
let expected = FullAccount {
login: Login::new(login),
email: Email::new(email),
pass_hash: PassHash::new(&hash),
role: Role::Admin,
customer_id: account.customer_id,
id: account.id,
state: AccountState::Active,
};
assert_eq!(account, expected);
}
#[actix::test]
async fn all_accounts() {
let config = config::default_load(&mut NoOpts);
config
.lock()
.database_mut()
.set_url("postgres://postgres@localhost/bazzar_test");
let db = Database::build(config).await.start();
test_create_account(db.clone(), None, None, None).await;
test_create_account(db.clone(), None, None, None).await;
test_create_account(db.clone(), None, None, None).await;
let v: Vec<FullAccount> = db.send(AllAccounts).await.unwrap().unwrap();
assert!(v.len() >= 3);
}
#[actix::test]
async fn update_account_without_pass() {
let config = config::default_load(&mut NoOpts);
config
.lock()
.database_mut()
.set_url("postgres://postgres@localhost/bazzar_test");
let db = Database::build(config).await.start();
let original_login: String = fake::faker::internet::en::Username().fake();
let original_email: String = fake::faker::internet::en::FreeEmail().fake();
let original_hash: String = fake::faker::internet::en::Password(10..20).fake();
let original_account = test_create_account(
db.clone(),
Some(original_login.clone()),
Some(original_email.clone()),
Some(original_hash.clone()),
)
.await;
let updated_login: String = fake::faker::internet::en::Username().fake();
let updated_email: String = fake::faker::internet::en::FreeEmail().fake();
let updated_account: FullAccount = db
.send(UpdateAccount {
id: original_account.id,
email: Email::new(updated_email.clone()),
login: Login::new(updated_login.clone()),
pass_hash: None,
role: Role::Admin,
state: AccountState::Active,
})
.await
.unwrap()
.unwrap();
let expected = FullAccount {
id: original_account.id,
email: Email::new(updated_email),
login: Login::new(updated_login),
pass_hash: PassHash::new(original_hash),
role: Role::Admin,
customer_id: original_account.customer_id,
state: AccountState::Active,
};
assert_ne!(original_account, expected);
assert_eq!(updated_account, expected);
}
#[actix::test]
async fn update_account_with_pass() {
let config = config::default_load(&mut NoOpts);
config
.lock()
.database_mut()
.set_url("postgres://postgres@localhost/bazzar_test");
let db = Database::build(config).await.start();
let original_login: String = fake::faker::internet::en::Username().fake();
let original_email: String = fake::faker::internet::en::FreeEmail().fake();
let original_hash: String = fake::faker::internet::en::Password(10..20).fake();
let original_account = test_create_account(
db.clone(),
Some(original_login.clone()),
Some(original_email.clone()),
Some(original_hash.clone()),
)
.await;
let updated_login: String = fake::faker::internet::en::Username().fake();
let updated_email: String = fake::faker::internet::en::FreeEmail().fake();
let updated_hash: String = fake::faker::internet::en::Password(10..20).fake();
let updated_account: FullAccount = db
.send(UpdateAccount {
id: original_account.id,
email: Email::new(updated_email.clone()),
login: Login::new(updated_login.clone()),
pass_hash: Some(PassHash::new(updated_hash.clone())),
role: Role::Admin,
state: AccountState::Active,
})
.await
.unwrap()
.unwrap();
let expected = FullAccount {
id: original_account.id,
email: Email::new(updated_email),
login: Login::new(updated_login),
pass_hash: PassHash::new(updated_hash),
role: Role::Admin,
customer_id: original_account.customer_id,
state: AccountState::Active,
};
assert_ne!(original_account, expected);
assert_eq!(updated_account, expected);
}
#[actix::test]
async fn find() {
let config = config::default_load(&mut NoOpts);
config
.lock()
.database_mut()
.set_url("postgres://postgres@localhost/bazzar_test");
let db = Database::build(config).await.start();
let account = test_create_account(db.clone(), None, None, None).await;
let res: FullAccount = db
.send(FindAccount {
account_id: account.id,
})
.await
.unwrap()
.unwrap();
assert_eq!(account, res);
}
#[actix::test]
async fn find_identity_email() {
let config = config::default_load(&mut NoOpts);
config
.lock()
.database_mut()
.set_url("postgres://postgres@localhost/bazzar_test");
let db = Database::build(config).await.start();
let account = test_create_account(db.clone(), None, None, None).await;
let res: FullAccount = db
.send(AccountByIdentity {
email: Some(account.email.clone()),
login: None,
})
.await
.unwrap()
.unwrap();
assert_eq!(account, res);
}
#[actix::test]
async fn find_identity_login() {
let config = config::default_load(&mut NoOpts);
config
.lock()
.database_mut()
.set_url("postgres://postgres@localhost/bazzar_test");
let db = Database::build(config).await.start();
let account = test_create_account(db.clone(), None, None, None).await;
let res: FullAccount = db
.send(AccountByIdentity {
login: Some(account.login.clone()),
email: None,
})
.await
.unwrap()
.unwrap();
assert_eq!(account, res);
}
}

View File

@ -12,6 +12,24 @@ pub enum Error {
Jti, Jti,
} }
/// Find token by JTI field
///
/// # Examples
///
/// ```
/// use actix::Addr;
/// use database_manager::{Database, TokenByJti};
///
/// async fn find(db: Addr<Database>) {
/// match db.send(TokenByJti {
/// jti: uuid::Uuid::new_v4()
/// }).await {
/// Ok(Ok(token)) => { println!("{:?}", token); }
/// Ok(Err(db_err)) => { println!("{:?}", db_err); }
/// Err(actor_err) => { println!("{:?}", actor_err); }
/// }
/// }
/// ```
#[derive(Message)] #[derive(Message)]
#[rtype(result = "Result<Token>")] #[rtype(result = "Result<Token>")]
pub struct TokenByJti { pub struct TokenByJti {
@ -107,3 +125,83 @@ RETURNING id, customer_id, role, issuer, subject, audience, expiration_time, not
crate::Error::Token(Error::Create) crate::Error::Token(Error::Create)
}) })
} }
#[cfg(test)]
mod tests {
use actix::Addr;
use fake::*;
use model::*;
use uuid::Uuid;
use crate::*;
async fn test_create_account(db: Addr<Database>) -> FullAccount {
use fake::faker::internet::en;
let login: String = en::Username().fake();
let email: String = en::FreeEmail().fake();
let hash: String = en::Password(10..20).fake();
db.send(CreateAccount {
email: Email::new(email),
login: Login::new(login),
pass_hash: PassHash::new(hash),
role: Role::Admin,
})
.await
.unwrap()
.unwrap()
}
async fn test_create_token(
db: Addr<Database>,
customer_id: Option<uuid::Uuid>,
role: Option<Role>,
subject: Option<AccountId>,
audience: Option<Audience>,
expiration_time: Option<chrono::NaiveDateTime>,
) -> Token {
let customer_id = customer_id.unwrap_or_else(|| uuid::Uuid::new_v4());
let role = role.unwrap_or_else(|| Role::Admin);
let subject = match subject {
Some(id) => id,
_ => test_create_account(db.clone()).await.id,
};
let audience = audience.unwrap_or_else(|| Audience::Web);
let expiration_time = expiration_time
.unwrap_or_else(|| (chrono::Utc::now() + chrono::Duration::days(60)).naive_utc());
db.send(CreateExtendedToken {
customer_id,
role,
subject,
audience,
expiration_time,
})
.await
.unwrap()
.unwrap()
}
#[actix::test]
async fn create_account() {
let config = config::default_load(&mut NoOpts);
config
.lock()
.database_mut()
.set_url("postgres://postgres@localhost/bazzar_test");
let db = Database::build(config).await.start();
let account = test_create_account(db.clone()).await;
db.send(CreateToken {
customer_id: uuid::Uuid::new_v4(),
role: Role::Admin,
subject: account.id,
audience: Default::default(),
})
.await
.unwrap()
.unwrap();
}
}

View File

@ -146,7 +146,7 @@ pub enum OrderStatus {
#[cfg_attr(feature = "dummy", derive(fake::Dummy))] #[cfg_attr(feature = "dummy", derive(fake::Dummy))]
#[cfg_attr(feature = "db", derive(sqlx::Type))] #[cfg_attr(feature = "db", derive(sqlx::Type))]
#[cfg_attr(feature = "db", sqlx(rename_all = "snake_case"))] #[cfg_attr(feature = "db", sqlx(rename_all = "snake_case"))]
#[derive(Copy, Clone, Debug, Hash, Display, Deserialize, Serialize, PartialEq)] #[derive(Copy, Clone, Debug, Hash, PartialEq, Display, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum Role { pub enum Role {
#[display(fmt = "Adminitrator")] #[display(fmt = "Adminitrator")]
@ -330,7 +330,7 @@ impl TryFrom<i32> for Quantity {
#[cfg_attr(feature = "db", derive(sqlx::Type))] #[cfg_attr(feature = "db", derive(sqlx::Type))]
#[cfg_attr(feature = "db", sqlx(transparent))] #[cfg_attr(feature = "db", sqlx(transparent))]
#[derive(Deserialize, Serialize, Debug, Clone, Deref, From, Display)] #[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Deref, From, Display)]
#[serde(transparent)] #[serde(transparent)]
pub struct Login(String); pub struct Login(String);
@ -691,7 +691,7 @@ impl PasswordConfirmation {
#[cfg_attr(feature = "db", derive(sqlx::Type))] #[cfg_attr(feature = "db", derive(sqlx::Type))]
#[cfg_attr(feature = "db", sqlx(transparent))] #[cfg_attr(feature = "db", sqlx(transparent))]
#[derive(Serialize, Deserialize, Debug, Deref, From, Display)] #[derive(Serialize, Deserialize, Debug, PartialEq, Deref, From, Display)]
#[serde(transparent)] #[serde(transparent)]
pub struct PassHash(String); pub struct PassHash(String);
@ -718,7 +718,7 @@ pub struct AccountId(RecordId);
#[cfg_attr(feature = "dummy", derive(fake::Dummy))] #[cfg_attr(feature = "dummy", derive(fake::Dummy))]
#[cfg_attr(feature = "db", derive(sqlx::FromRow))] #[cfg_attr(feature = "db", derive(sqlx::FromRow))]
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct FullAccount { pub struct FullAccount {
pub id: AccountId, pub id: AccountId,
pub email: Email, pub email: Email,

View File

@ -195,27 +195,27 @@ impl<'a> Urls<'a> {
} }
// Admin // Admin
pub fn admin_landing(self) -> Url { // pub fn admin_landing(self) -> Url {
self.base_url() // self.base_url()
.add_path_part("admin") // .add_path_part("admin")
.add_path_part("landing") // .add_path_part("landing")
} // }
//
pub fn admin_dashboard(self) -> Url { // pub fn admin_dashboard(self) -> Url {
self.base_url() // self.base_url()
.add_path_part("admin") // .add_path_part("admin")
.add_path_part("dashboard") // .add_path_part("dashboard")
} // }
//
pub fn admin_products(self) -> Url { // pub fn admin_products(self) -> Url {
self.base_url() // self.base_url()
.add_path_part("admin") // .add_path_part("admin")
.add_path_part("products") // .add_path_part("products")
} // }
//
pub fn admin_product(self) -> Url { // pub fn admin_product(self) -> Url {
self.base_url() // self.base_url()
.add_path_part("admin") // .add_path_part("admin")
.add_path_part("product") // .add_path_part("product")
} // }
} }