Skip to content

Commit cfa10aa

Browse files
feat(user): implement force password reset (#3572)
1 parent bebaf41 commit cfa10aa

File tree

9 files changed

+165
-11
lines changed

9 files changed

+165
-11
lines changed

crates/api_models/src/user/dashboard_metadata.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ pub enum SetMetaDataRequest {
2424
ConfigureWoocom,
2525
SetupWoocomWebhook,
2626
IsMultipleConfiguration,
27+
#[serde(skip)]
28+
IsChangePasswordRequired,
2729
}
2830

2931
#[derive(Debug, serde::Deserialize, serde::Serialize)]
@@ -110,6 +112,7 @@ pub enum GetMetaDataRequest {
110112
ConfigureWoocom,
111113
SetupWoocomWebhook,
112114
IsMultipleConfiguration,
115+
IsChangePasswordRequired,
113116
}
114117

115118
#[derive(Debug, serde::Deserialize, serde::Serialize)]
@@ -146,4 +149,5 @@ pub enum GetMetaDataResponse {
146149
ConfigureWoocom(bool),
147150
SetupWoocomWebhook(bool),
148151
IsMultipleConfiguration(bool),
152+
IsChangePasswordRequired(bool),
149153
}

crates/diesel_models/src/enums.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,4 +498,5 @@ pub enum DashboardMetadata {
498498
ConfigureWoocom,
499499
SetupWoocomWebhook,
500500
IsMultipleConfiguration,
501+
IsChangePasswordRequired,
501502
}

crates/diesel_models/src/query/dashboard_metadata.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ impl DashboardMetadata {
105105
.await
106106
}
107107

108-
pub async fn delete_user_scoped_dashboard_metadata_by_merchant_id(
108+
pub async fn delete_all_user_scoped_dashboard_metadata_by_merchant_id(
109109
conn: &PgPooledConn,
110110
user_id: String,
111111
merchant_id: String,
@@ -118,4 +118,20 @@ impl DashboardMetadata {
118118
)
119119
.await
120120
}
121+
122+
pub async fn delete_user_scoped_dashboard_metadata_by_merchant_id_data_key(
123+
conn: &PgPooledConn,
124+
user_id: String,
125+
merchant_id: String,
126+
data_key: enums::DashboardMetadata,
127+
) -> StorageResult<Self> {
128+
generics::generic_delete_one_with_result::<<Self as HasTable>::Table, _, _>(
129+
conn,
130+
dsl::user_id
131+
.eq(user_id)
132+
.and(dsl::merchant_id.eq(merchant_id))
133+
.and(dsl::data_key.eq(data_key)),
134+
)
135+
.await
136+
}
121137
}

crates/router/src/core/user.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ use error_stack::ResultExt;
88
use masking::ExposeInterface;
99
#[cfg(feature = "email")]
1010
use router_env::env;
11-
#[cfg(feature = "email")]
1211
use router_env::logger;
12+
#[cfg(not(feature = "email"))]
13+
use user_api::dashboard_metadata::SetMetaDataRequest;
1314

1415
use super::errors::{StorageErrorExt, UserErrors, UserResponse, UserResult};
1516
#[cfg(feature = "email")]
@@ -310,6 +311,20 @@ pub async fn change_password(
310311
.await
311312
.change_context(UserErrors::InternalServerError)?;
312313

314+
#[cfg(not(feature = "email"))]
315+
{
316+
state
317+
.store
318+
.delete_user_scoped_dashboard_metadata_by_merchant_id_data_key(
319+
&user_from_token.user_id,
320+
&user_from_token.merchant_id,
321+
diesel_models::enums::DashboardMetadata::IsChangePasswordRequired,
322+
)
323+
.await
324+
.map_err(|e| logger::error!("Error while deleting dashboard metadata {}", e))
325+
.ok();
326+
}
327+
313328
Ok(ApplicationResponse::StatusOk)
314329
}
315330

@@ -483,8 +498,8 @@ pub async fn invite_user(
483498
.insert_user_role(UserRoleNew {
484499
user_id: new_user.get_user_id().to_owned(),
485500
merchant_id: user_from_token.merchant_id.clone(),
486-
role_id: request.role_id,
487-
org_id: user_from_token.org_id,
501+
role_id: request.role_id.clone(),
502+
org_id: user_from_token.org_id.clone(),
488503
status: invitation_status,
489504
created_by: user_from_token.user_id.clone(),
490505
last_modified_by: user_from_token.user_id,
@@ -523,6 +538,20 @@ pub async fn invite_user(
523538
#[cfg(not(feature = "email"))]
524539
{
525540
is_email_sent = false;
541+
let invited_user_token = auth::UserFromToken {
542+
user_id: new_user.get_user_id(),
543+
merchant_id: user_from_token.merchant_id,
544+
org_id: user_from_token.org_id,
545+
role_id: request.role_id,
546+
};
547+
548+
let set_metadata_request = SetMetaDataRequest::IsChangePasswordRequired;
549+
dashboard_metadata::set_metadata(
550+
state.clone(),
551+
invited_user_token,
552+
set_metadata_request,
553+
)
554+
.await?;
526555
}
527556

528557
Ok(ApplicationResponse::Json(user_api::InviteUserResponse {
@@ -706,6 +735,17 @@ async fn handle_new_user_invitation(
706735
#[cfg(not(feature = "email"))]
707736
{
708737
is_email_sent = false;
738+
739+
let invited_user_token = auth::UserFromToken {
740+
user_id: new_user.get_user_id(),
741+
merchant_id: user_from_token.merchant_id.clone(),
742+
org_id: user_from_token.org_id.clone(),
743+
role_id: request.role_id.clone(),
744+
};
745+
746+
let set_metadata_request = SetMetaDataRequest::IsChangePasswordRequired;
747+
dashboard_metadata::set_metadata(state.clone(), invited_user_token, set_metadata_request)
748+
.await?;
709749
}
710750

711751
Ok(InviteMultipleUserResponse {

crates/router/src/core/user/dashboard_metadata.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ fn parse_set_request(data_enum: api::SetMetaDataRequest) -> UserResult<types::Me
105105
api::SetMetaDataRequest::IsMultipleConfiguration => {
106106
Ok(types::MetaData::IsMultipleConfiguration(true))
107107
}
108+
api::SetMetaDataRequest::IsChangePasswordRequired => {
109+
Ok(types::MetaData::IsChangePasswordRequired(true))
110+
}
108111
}
109112
}
110113

@@ -131,6 +134,7 @@ fn parse_get_request(data_enum: api::GetMetaDataRequest) -> DBEnum {
131134
api::GetMetaDataRequest::ConfigureWoocom => DBEnum::ConfigureWoocom,
132135
api::GetMetaDataRequest::SetupWoocomWebhook => DBEnum::SetupWoocomWebhook,
133136
api::GetMetaDataRequest::IsMultipleConfiguration => DBEnum::IsMultipleConfiguration,
137+
api::GetMetaDataRequest::IsChangePasswordRequired => DBEnum::IsChangePasswordRequired,
134138
}
135139
}
136140

@@ -207,6 +211,9 @@ fn into_response(
207211
DBEnum::IsMultipleConfiguration => Ok(api::GetMetaDataResponse::IsMultipleConfiguration(
208212
data.is_some(),
209213
)),
214+
DBEnum::IsChangePasswordRequired => Ok(api::GetMetaDataResponse::IsChangePasswordRequired(
215+
data.is_some(),
216+
)),
210217
}
211218
}
212219

@@ -520,6 +527,17 @@ async fn insert_metadata(
520527
)
521528
.await
522529
}
530+
types::MetaData::IsChangePasswordRequired(data) => {
531+
utils::insert_user_scoped_metadata_to_db(
532+
state,
533+
user.user_id,
534+
user.merchant_id,
535+
user.org_id,
536+
metadata_key,
537+
data,
538+
)
539+
.await
540+
}
523541
}
524542
}
525543

crates/router/src/db/dashboard_metadata.rs

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub trait DashboardMetadataInterface {
1414
&self,
1515
metadata: storage::DashboardMetadataNew,
1616
) -> CustomResult<storage::DashboardMetadata, errors::StorageError>;
17+
1718
async fn update_metadata(
1819
&self,
1920
user_id: Option<String>,
@@ -30,18 +31,26 @@ pub trait DashboardMetadataInterface {
3031
org_id: &str,
3132
data_keys: Vec<enums::DashboardMetadata>,
3233
) -> CustomResult<Vec<storage::DashboardMetadata>, errors::StorageError>;
34+
3335
async fn find_merchant_scoped_dashboard_metadata(
3436
&self,
3537
merchant_id: &str,
3638
org_id: &str,
3739
data_keys: Vec<enums::DashboardMetadata>,
3840
) -> CustomResult<Vec<storage::DashboardMetadata>, errors::StorageError>;
3941

40-
async fn delete_user_scoped_dashboard_metadata_by_merchant_id(
42+
async fn delete_all_user_scoped_dashboard_metadata_by_merchant_id(
4143
&self,
4244
user_id: &str,
4345
merchant_id: &str,
4446
) -> CustomResult<bool, errors::StorageError>;
47+
48+
async fn delete_user_scoped_dashboard_metadata_by_merchant_id_data_key(
49+
&self,
50+
user_id: &str,
51+
merchant_id: &str,
52+
data_key: enums::DashboardMetadata,
53+
) -> CustomResult<storage::DashboardMetadata, errors::StorageError>;
4554
}
4655

4756
#[async_trait::async_trait]
@@ -117,16 +126,34 @@ impl DashboardMetadataInterface for Store {
117126
.map_err(Into::into)
118127
.into_report()
119128
}
120-
async fn delete_user_scoped_dashboard_metadata_by_merchant_id(
129+
async fn delete_all_user_scoped_dashboard_metadata_by_merchant_id(
121130
&self,
122131
user_id: &str,
123132
merchant_id: &str,
124133
) -> CustomResult<bool, errors::StorageError> {
125134
let conn = connection::pg_connection_write(self).await?;
126-
storage::DashboardMetadata::delete_user_scoped_dashboard_metadata_by_merchant_id(
135+
storage::DashboardMetadata::delete_all_user_scoped_dashboard_metadata_by_merchant_id(
136+
&conn,
137+
user_id.to_owned(),
138+
merchant_id.to_owned(),
139+
)
140+
.await
141+
.map_err(Into::into)
142+
.into_report()
143+
}
144+
145+
async fn delete_user_scoped_dashboard_metadata_by_merchant_id_data_key(
146+
&self,
147+
user_id: &str,
148+
merchant_id: &str,
149+
data_key: enums::DashboardMetadata,
150+
) -> CustomResult<storage::DashboardMetadata, errors::StorageError> {
151+
let conn = connection::pg_connection_write(self).await?;
152+
storage::DashboardMetadata::delete_user_scoped_dashboard_metadata_by_merchant_id_data_key(
127153
&conn,
128154
user_id.to_owned(),
129155
merchant_id.to_owned(),
156+
data_key,
130157
)
131158
.await
132159
.map_err(Into::into)
@@ -267,7 +294,7 @@ impl DashboardMetadataInterface for MockDb {
267294
}
268295
Ok(query_result)
269296
}
270-
async fn delete_user_scoped_dashboard_metadata_by_merchant_id(
297+
async fn delete_all_user_scoped_dashboard_metadata_by_merchant_id(
271298
&self,
272299
user_id: &str,
273300
merchant_id: &str,
@@ -294,4 +321,31 @@ impl DashboardMetadataInterface for MockDb {
294321

295322
Ok(true)
296323
}
324+
325+
async fn delete_user_scoped_dashboard_metadata_by_merchant_id_data_key(
326+
&self,
327+
user_id: &str,
328+
merchant_id: &str,
329+
data_key: enums::DashboardMetadata,
330+
) -> CustomResult<storage::DashboardMetadata, errors::StorageError> {
331+
let mut dashboard_metadata = self.dashboard_metadata.lock().await;
332+
333+
let index_to_remove = dashboard_metadata
334+
.iter()
335+
.position(|metadata_inner| {
336+
metadata_inner
337+
.user_id
338+
.as_deref()
339+
.map_or(false, |user_id_inner| user_id_inner == user_id)
340+
&& metadata_inner.merchant_id == merchant_id
341+
&& metadata_inner.data_key == data_key
342+
})
343+
.ok_or(errors::StorageError::ValueNotFound(
344+
"No data found".to_string(),
345+
))?;
346+
347+
let deleted_value = dashboard_metadata.swap_remove(index_to_remove);
348+
349+
Ok(deleted_value)
350+
}
297351
}

crates/router/src/db/kafka_store.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1964,6 +1964,7 @@ impl UserRoleInterface for KafkaStore {
19641964
.update_user_role_by_user_id_merchant_id(user_id, merchant_id, update)
19651965
.await
19661966
}
1967+
19671968
async fn delete_user_role_by_user_id_merchant_id(
19681969
&self,
19691970
user_id: &str,
@@ -2021,6 +2022,7 @@ impl DashboardMetadataInterface for KafkaStore {
20212022
.find_user_scoped_dashboard_metadata(user_id, merchant_id, org_id, data_keys)
20222023
.await
20232024
}
2025+
20242026
async fn find_merchant_scoped_dashboard_metadata(
20252027
&self,
20262028
merchant_id: &str,
@@ -2032,13 +2034,28 @@ impl DashboardMetadataInterface for KafkaStore {
20322034
.await
20332035
}
20342036

2035-
async fn delete_user_scoped_dashboard_metadata_by_merchant_id(
2037+
async fn delete_all_user_scoped_dashboard_metadata_by_merchant_id(
20362038
&self,
20372039
user_id: &str,
20382040
merchant_id: &str,
20392041
) -> CustomResult<bool, errors::StorageError> {
20402042
self.diesel_store
2041-
.delete_user_scoped_dashboard_metadata_by_merchant_id(user_id, merchant_id)
2043+
.delete_all_user_scoped_dashboard_metadata_by_merchant_id(user_id, merchant_id)
2044+
.await
2045+
}
2046+
2047+
async fn delete_user_scoped_dashboard_metadata_by_merchant_id_data_key(
2048+
&self,
2049+
user_id: &str,
2050+
merchant_id: &str,
2051+
data_key: enums::DashboardMetadata,
2052+
) -> CustomResult<storage::DashboardMetadata, errors::StorageError> {
2053+
self.diesel_store
2054+
.delete_user_scoped_dashboard_metadata_by_merchant_id_data_key(
2055+
user_id,
2056+
merchant_id,
2057+
data_key,
2058+
)
20422059
.await
20432060
}
20442061
}

crates/router/src/types/domain/user/dashboard_metadata.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub enum MetaData {
2525
ConfigureWoocom(bool),
2626
SetupWoocomWebhook(bool),
2727
IsMultipleConfiguration(bool),
28+
IsChangePasswordRequired(bool),
2829
}
2930

3031
impl From<&MetaData> for DBEnum {
@@ -51,6 +52,7 @@ impl From<&MetaData> for DBEnum {
5152
MetaData::ConfigureWoocom(_) => Self::ConfigureWoocom,
5253
MetaData::SetupWoocomWebhook(_) => Self::SetupWoocomWebhook,
5354
MetaData::IsMultipleConfiguration(_) => Self::IsMultipleConfiguration,
55+
MetaData::IsChangePasswordRequired(_) => Self::IsChangePasswordRequired,
5456
}
5557
}
5658
}

crates/router/src/utils/user/dashboard_metadata.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,9 @@ pub fn separate_metadata_type_based_on_scope(
219219
| DBEnum::ConfigureWoocom
220220
| DBEnum::SetupWoocomWebhook
221221
| DBEnum::IsMultipleConfiguration => merchant_scoped.push(key),
222-
DBEnum::Feedback | DBEnum::ProdIntent => user_scoped.push(key),
222+
DBEnum::Feedback | DBEnum::ProdIntent | DBEnum::IsChangePasswordRequired => {
223+
user_scoped.push(key)
224+
}
223225
}
224226
}
225227
(merchant_scoped, user_scoped)

0 commit comments

Comments
 (0)