@@ -51,6 +51,8 @@ const deleteUser = async (req, res) => {
51
51
52
52
// Patch user with ID - not password
53
53
const updateBasicUserInfo = async ( req , res ) => {
54
+ const t = await sequelize . transaction ( ) ; // Start a transaction
55
+
54
56
try {
55
57
const { id } = req . params ;
56
58
const {
@@ -61,20 +63,24 @@ const updateBasicUserInfo = async (req, res) => {
61
63
verifiedUser,
62
64
} = req . body ;
63
65
64
- // Find existing user details
65
- const existingUser = await User . findOne ( { where : { id } } ) ;
66
+ // Find existing user details within the transaction
67
+ const existingUser = await User . findOne ( { where : { id } , transaction : t } ) ;
66
68
67
69
// If user not found
68
70
if ( ! existingUser ) {
69
71
throw { status : 404 , message : "User not found" } ;
70
72
}
71
73
74
+ const changedInfo = [ ] ;
75
+
72
76
if ( firstName ) {
73
77
existingUser . firstName = firstName ;
78
+ changedInfo . push ( "firstName" ) ;
74
79
}
75
80
76
81
if ( lastName ) {
77
82
existingUser . lastName = lastName ;
83
+ changedInfo . push ( "lastName" ) ;
78
84
}
79
85
80
86
if ( registrationMethod ) {
@@ -85,7 +91,7 @@ const updateBasicUserInfo = async (req, res) => {
85
91
existingUser . registrationStatus = registrationStatus ;
86
92
}
87
93
88
- if ( verifiedUser !== undefined || verifiedUser !== null ) {
94
+ if ( verifiedUser !== undefined && verifiedUser !== null ) {
89
95
existingUser . verifiedUser = verifiedUser ;
90
96
}
91
97
@@ -94,15 +100,44 @@ const updateBasicUserInfo = async (req, res) => {
94
100
throw { status : 400 , message : "No update payload provided" } ;
95
101
}
96
102
97
- // Save user with updated details
98
- const updatedUser = await existingUser . save ( ) ;
103
+ // Save user with updated details within the transaction
104
+ const updatedUser = await existingUser . save ( { transaction : t } ) ;
105
+
106
+ // Queue notification within the same transaction
107
+ const readable_notification = `ACC_CNG_${ moment ( ) . format (
108
+ "YYYYMMDD_HHmmss_SSS"
109
+ ) } `;
110
+ await NotificationQueue . create (
111
+ {
112
+ type : "email" ,
113
+ templateName : "accountChange" ,
114
+ notificationOrigin : "User Management" ,
115
+ deliveryType : "immediate" ,
116
+ metaData : {
117
+ notificationId : readable_notification ,
118
+ recipientName : `${ updatedUser . firstName } ${ updatedUser . lastName } ` ,
119
+ notificationOrigin : "User Management" ,
120
+ subject : "Account Change" ,
121
+ mainRecipients : [ updatedUser . email ] ,
122
+ notificationDescription : "Account Change" ,
123
+ changedInfo,
124
+ } ,
125
+ createdBy : req . user . id ,
126
+ } ,
127
+ { transaction : t }
128
+ ) ;
129
+
130
+ // Commit the transaction
131
+ await t . commit ( ) ;
99
132
100
133
res . status ( 200 ) . json ( {
101
134
success : true ,
102
135
message : "User updated successfully" ,
103
136
data : updatedUser ,
104
137
} ) ;
105
138
} catch ( err ) {
139
+ // Rollback transaction if anything goes wrong
140
+ await t . rollback ( ) ;
106
141
logger . error ( `Update user: ${ err . message } ` ) ;
107
142
res
108
143
. status ( err . status || 500 )
@@ -159,14 +194,15 @@ const getAllUsers = async (req, res) => {
159
194
160
195
//Update password - Ensure current password provided is correct
161
196
const changePassword = async ( req , res ) => {
197
+ const t = await sequelize . transaction ( ) ; // Start transaction
198
+
162
199
try {
163
200
const { id } = req . params ;
164
201
const { currentPassword, newPassword } = req . body ;
165
202
166
203
// Find existing user details
167
- const existingUser = await User . findOne ( { where : { id } } ) ;
204
+ const existingUser = await User . findOne ( { where : { id } , transaction : t } ) ;
168
205
169
- // If user not found
170
206
if ( ! existingUser ) {
171
207
throw { status : 404 , message : "User not found" } ;
172
208
}
@@ -176,7 +212,7 @@ const changePassword = async (req, res) => {
176
212
throw { status : 400 , message : "Current password is incorrect" } ;
177
213
}
178
214
179
- //check for password security violations
215
+ // Check for password security violations
180
216
const errors = checkPasswordSecurityViolations ( {
181
217
password : newPassword ,
182
218
user : existingUser ,
@@ -190,31 +226,54 @@ const changePassword = async (req, res) => {
190
226
const salt = bcrypt . genSaltSync ( 10 ) ;
191
227
existingUser . hash = bcrypt . hashSync ( newPassword , salt ) ;
192
228
193
- //set password expiry
229
+ // Set password expiry and previous passwords
194
230
setPasswordExpiry ( existingUser ) ;
195
-
196
- //set previous passwords
197
231
setPreviousPasswords ( existingUser ) ;
198
232
199
233
// Save user with updated details
200
- const updatedUser = await User . update (
234
+ await User . update (
201
235
{
202
236
hash : existingUser . hash ,
203
237
metaData : existingUser . metaData ,
204
238
passwordExpiresAt : existingUser . passwordExpiresAt ,
205
239
forcePasswordReset : existingUser . forcePasswordReset ,
206
240
} ,
241
+ { where : { id } , transaction : t }
242
+ ) ;
243
+
244
+ // Queue notification
245
+ const readable_notification = `ACC_CNG_${ moment ( ) . format (
246
+ "YYYYMMDD_HHmmss_SSS"
247
+ ) } `;
248
+ await NotificationQueue . create (
207
249
{
208
- where : { id } ,
209
- }
250
+ type : "email" ,
251
+ templateName : "accountChange" ,
252
+ notificationOrigin : "User Management" ,
253
+ deliveryType : "immediate" ,
254
+ metaData : {
255
+ notificationId : readable_notification ,
256
+ recipientName : `${ existingUser . firstName } ${ existingUser . lastName } ` ,
257
+ notificationOrigin : "User Management" ,
258
+ subject : "Account Change" ,
259
+ mainRecipients : [ existingUser . email ] ,
260
+ notificationDescription : "Account Change" ,
261
+ changedInfo : [ "password" ] ,
262
+ } ,
263
+ createdBy : req . user . id ,
264
+ } ,
265
+ { transaction : t }
210
266
) ;
211
267
268
+ // Commit transaction
269
+ await t . commit ( ) ;
270
+
212
271
res . status ( 200 ) . json ( {
213
272
success : true ,
214
273
message : "Password updated successfully" ,
215
- data : updatedUser ,
216
274
} ) ;
217
275
} catch ( err ) {
276
+ await t . rollback ( ) ; // Rollback on failure
218
277
logger . error ( `Change password: ${ err . message } ` ) ;
219
278
res
220
279
. status ( err . status || 500 )
0 commit comments