fix: update_user: delete module. Difficult to maintain consistency in
denormalized views
This commit is contained in:
parent
33022dc4ea
commit
b4e56cc9a1
10 changed files with 72 additions and 199 deletions
45
src/identity/application/services/events.rs
Normal file
45
src/identity/application/services/events.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use cqrs_es::DomainEvent;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::login::events::*;
|
||||
use super::register_user::events::*;
|
||||
use super::set_user_admin::events::*;
|
||||
use super::update_email::events::*;
|
||||
use super::update_password::events::*;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum UserEvent {
|
||||
UserRegistered(UserRegisteredEvent),
|
||||
UserDeleted,
|
||||
Loggedin(LoginEvent),
|
||||
PasswordUpdated(PasswordUpdatedEvent),
|
||||
EmailUpdated(EmailUpdatedEvent),
|
||||
UserVerified,
|
||||
UserPromotedToAdmin(UserPromotedToAdminEvent),
|
||||
}
|
||||
|
||||
//TODO: define password type that takes string and converts to hash
|
||||
|
||||
impl DomainEvent for UserEvent {
|
||||
fn event_version(&self) -> String {
|
||||
"1.0".to_string()
|
||||
}
|
||||
|
||||
fn event_type(&self) -> String {
|
||||
let e: &str = match self {
|
||||
UserEvent::UserRegistered { .. } => "UserRegisteredAccount",
|
||||
UserEvent::UserDeleted => "UserDeletedAccount",
|
||||
UserEvent::Loggedin { .. } => "UserLoggedIn",
|
||||
UserEvent::PasswordUpdated { .. } => "UserUpdatedAccountPassword",
|
||||
UserEvent::EmailUpdated { .. } => "UserUpdatedAccountEmail",
|
||||
UserEvent::UserVerified => "UserIsVerified",
|
||||
UserEvent::UserPromotedToAdmin { .. } => "UserPromotedToAdmin",
|
||||
};
|
||||
|
||||
e.to_string()
|
||||
}
|
||||
}
|
|
@ -2,8 +2,33 @@
|
|||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
mod create_user;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
mod delete_user;
|
||||
mod login;
|
||||
mod register_user;
|
||||
mod update_email;
|
||||
mod update_password;
|
||||
mod update_user;
|
||||
//mod resend_verification_email
|
||||
pub mod errors;
|
||||
pub mod events;
|
||||
mod mark_user_verified;
|
||||
mod set_user_admin;
|
||||
|
||||
use delete_user::command::*;
|
||||
use login::command::*;
|
||||
use register_user::command::*;
|
||||
use set_user_admin::command::*;
|
||||
use update_email::command::*;
|
||||
use update_password::command::*;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum UserCommand {
|
||||
RegisterUser(RegisterUserCommand),
|
||||
DeleteUser(DeleteUserCommand),
|
||||
Login(LoginCommand),
|
||||
UpdatePassword(UpdatePasswordCommand),
|
||||
UpdateEmail(UpdateEmailCommand),
|
||||
SetVerified,
|
||||
SetAdmin(SetAdminCommand),
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
mod command;
|
||||
mod error;
|
||||
mod service;
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,76 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use derive_getters::Getters;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Getters)]
|
||||
pub struct UpdateUsernameCommand {
|
||||
new_username: String,
|
||||
}
|
||||
|
||||
impl UpdateUsernameCommand {
|
||||
pub fn new(
|
||||
new_username: String,
|
||||
supplied_password: String,
|
||||
actual_password_hash: &str,
|
||||
config: &argon2_creds::Config,
|
||||
) -> IdentityCommandResult<Self> {
|
||||
if !argon2_creds::Config::verify(actual_password_hash, &supplied_password).unwrap() {
|
||||
return Err(IdentityCommandError::WrongPassword);
|
||||
}
|
||||
let new_username = config.username(&new_username)?;
|
||||
Ok(Self { new_username })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_cmd() {
|
||||
let config = argon2_creds::Config::default();
|
||||
let password = "adsfasdfasd";
|
||||
let new_username = "realaravinth";
|
||||
let hashed_password = config.password(password).unwrap();
|
||||
assert_eq!(
|
||||
UpdateUsernameCommand::new(
|
||||
new_username.into(),
|
||||
password.into(),
|
||||
&hashed_password,
|
||||
&config
|
||||
)
|
||||
.unwrap()
|
||||
.new_username,
|
||||
new_username
|
||||
);
|
||||
|
||||
// username is not valid
|
||||
assert!(matches!(
|
||||
UpdateUsernameCommand::new(
|
||||
"username".into(),
|
||||
password.into(),
|
||||
&hashed_password,
|
||||
&config,
|
||||
)
|
||||
.err(),
|
||||
Some(IdentityCommandError::BadUsername(_))
|
||||
));
|
||||
|
||||
// wrong password
|
||||
assert_eq!(
|
||||
UpdateUsernameCommand::new(
|
||||
new_username.into(),
|
||||
new_username.into(),
|
||||
&hashed_password,
|
||||
&config,
|
||||
)
|
||||
.err(),
|
||||
Some(IdentityCommandError::WrongPassword)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use derive_getters::Getters;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Getters, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct UsernameUpdatedEvent {
|
||||
username: String,
|
||||
}
|
||||
|
||||
impl UsernameUpdatedEvent {
|
||||
pub fn new(username: String) -> Self {
|
||||
Self { username }
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pub mod command;
|
||||
pub mod events;
|
||||
pub mod service;
|
||||
use super::errors::*;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait UpdateUsernameUseCase {
|
||||
async fn update_username(
|
||||
&self,
|
||||
cmd: command::UpdateUsernameCommand,
|
||||
) -> IdentityResult<events::UsernameUpdatedEvent>;
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use super::*;
|
||||
use derive_builder::Builder;
|
||||
|
||||
use super::*;
|
||||
use crate::identity::application::port::output::db::username_exists::*;
|
||||
|
||||
#[derive(Builder)]
|
||||
pub struct UpdateUsernameService {
|
||||
db_username_exists_adapter: UsernameExistsOutDBPortObj,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl UpdateUsernameUseCase for UpdateUsernameService {
|
||||
async fn update_username(
|
||||
&self,
|
||||
cmd: command::UpdateUsernameCommand,
|
||||
//) -> errors::ProcessAuthorizationServiceResult<String>;
|
||||
) -> IdentityResult<events::UsernameUpdatedEvent> {
|
||||
if self
|
||||
.db_username_exists_adapter
|
||||
.username_exists(cmd.new_username())
|
||||
.await
|
||||
.unwrap()
|
||||
{
|
||||
return Err(IdentityError::UsernameExists);
|
||||
}
|
||||
|
||||
Ok(events::UsernameUpdatedEvent::new(cmd.new_username().into()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::tests::bdd::*;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_service() {
|
||||
let new_username = "realaravinth";
|
||||
let password = "password";
|
||||
let config = argon2_creds::Config::default();
|
||||
let hashed_password = config.password(password).unwrap();
|
||||
|
||||
let cmd = command::UpdateUsernameCommand::new(
|
||||
new_username.into(),
|
||||
password.into(),
|
||||
&hashed_password,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let s = UpdateUsernameServiceBuilder::default()
|
||||
.db_username_exists_adapter(mock_username_exists_db_port(
|
||||
IS_CALLED_ONLY_ONCE,
|
||||
RETURNS_FALSE,
|
||||
))
|
||||
.build()
|
||||
.unwrap();
|
||||
let res = s.update_username(cmd.clone()).await.unwrap();
|
||||
assert_eq!(res.username(), cmd.new_username());
|
||||
}
|
||||
|
||||
{
|
||||
let s = UpdateUsernameServiceBuilder::default()
|
||||
.db_username_exists_adapter(mock_username_exists_db_port(
|
||||
IS_CALLED_ONLY_ONCE,
|
||||
RETURNS_TRUE,
|
||||
))
|
||||
.build()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
s.update_username(cmd.clone()).await.err(),
|
||||
Some(IdentityError::UsernameExists)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue