feat: identity: update_username service

This commit is contained in:
Aravinth Manivannan 2024-05-17 23:58:58 +05:30
parent 8085f5e54b
commit 2d1fb4fd1c
Signed by: realaravinth
GPG key ID: F8F50389936984FF
4 changed files with 191 additions and 0 deletions

View file

@ -0,0 +1,76 @@
// 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)
);
}
}

View file

@ -0,0 +1,17 @@
// 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 }
}
}

View file

@ -0,0 +1,16 @@
// 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>;
}

View file

@ -0,0 +1,82 @@
// 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)
);
}
}
}