@@ -95,29 +95,18 @@ impl RegistrationService {
95
95
}
96
96
}
97
97
98
- if registration_form. password != registration_form. confirm_password {
99
- return Err ( ServiceError :: PasswordsDontMatch ) ;
100
- }
101
-
102
- let password_length = registration_form. password . len ( ) ;
103
-
104
- if password_length <= settings. auth . min_password_length {
105
- return Err ( ServiceError :: PasswordTooShort ) ;
106
- }
107
-
108
- if password_length >= settings. auth . max_password_length {
109
- return Err ( ServiceError :: PasswordTooLong ) ;
110
- }
111
-
112
- let salt = SaltString :: generate ( & mut OsRng ) ;
98
+ let password_constraints = PasswordConstraints {
99
+ min_password_length : settings. auth . min_password_length ,
100
+ max_password_length : settings. auth . max_password_length ,
101
+ } ;
113
102
114
- // Argon2 with default params (Argon2id v19)
115
- let argon2 = Argon2 :: default ( ) ;
103
+ validate_password (
104
+ & registration_form. password ,
105
+ & registration_form. confirm_password ,
106
+ & password_constraints,
107
+ ) ?;
116
108
117
- // Hash password to PHC string ($argon2id$v=19$...)
118
- let password_hash = argon2
119
- . hash_password ( registration_form. password . as_bytes ( ) , & salt) ?
120
- . to_string ( ) ;
109
+ let password_hash = hash_password ( & registration_form. password ) ?;
121
110
122
111
let user_id = self
123
112
. user_repository
@@ -217,35 +206,24 @@ impl ProfileService {
217
206
218
207
let settings = self . configuration . settings . read ( ) . await ;
219
208
220
- // todo:
221
- // - Validate current password
222
- // - Remove duplicate code for password validation and hashing
209
+ // todo: guard that current password matches the one provided in change password form
223
210
224
- if change_password_form. password != change_password_form. confirm_password {
225
- return Err ( ServiceError :: PasswordsDontMatch ) ;
226
- }
227
-
228
- let password_length = change_password_form. password . len ( ) ;
229
-
230
- if password_length <= settings. auth . min_password_length {
231
- return Err ( ServiceError :: PasswordTooShort ) ;
232
- }
233
-
234
- if password_length >= settings. auth . max_password_length {
235
- return Err ( ServiceError :: PasswordTooLong ) ;
236
- }
237
-
238
- let salt = SaltString :: generate ( & mut OsRng ) ;
211
+ let password_constraints = PasswordConstraints {
212
+ min_password_length : settings. auth . min_password_length ,
213
+ max_password_length : settings. auth . max_password_length ,
214
+ } ;
239
215
240
- // Argon2 with default params (Argon2id v19)
241
- let argon2 = Argon2 :: default ( ) ;
216
+ validate_password (
217
+ & change_password_form. password ,
218
+ & change_password_form. confirm_password ,
219
+ & password_constraints,
220
+ ) ?;
242
221
243
- // Hash password to PHC string ($argon2id$v=19$...)
244
- let new_password_hash = argon2
245
- . hash_password ( change_password_form. password . as_bytes ( ) , & salt) ?
246
- . to_string ( ) ;
222
+ let password_hash = hash_password ( & change_password_form. password ) ?;
247
223
248
- self . user_authentication_repository . change_password ( user_id, & new_password_hash) . await ?;
224
+ self . user_authentication_repository
225
+ . change_password ( user_id, & password_hash)
226
+ . await ?;
249
227
250
228
Ok ( ( ) )
251
229
}
@@ -429,3 +407,38 @@ impl DbBannedUserList {
429
407
self . database . ban_user ( * user_id, & reason, date_expiry) . await
430
408
}
431
409
}
410
+
411
+ struct PasswordConstraints {
412
+ pub min_password_length : usize ,
413
+ pub max_password_length : usize ,
414
+ }
415
+
416
+ fn validate_password ( password : & str , confirm_password : & str , password_rules : & PasswordConstraints ) -> Result < ( ) , ServiceError > {
417
+ if password != confirm_password {
418
+ return Err ( ServiceError :: PasswordsDontMatch ) ;
419
+ }
420
+
421
+ let password_length = password. len ( ) ;
422
+
423
+ if password_length <= password_rules. min_password_length {
424
+ return Err ( ServiceError :: PasswordTooShort ) ;
425
+ }
426
+
427
+ if password_length >= password_rules. max_password_length {
428
+ return Err ( ServiceError :: PasswordTooLong ) ;
429
+ }
430
+
431
+ Ok ( ( ) )
432
+ }
433
+
434
+ fn hash_password ( password : & str ) -> Result < String , ServiceError > {
435
+ let salt = SaltString :: generate ( & mut OsRng ) ;
436
+
437
+ // Argon2 with default params (Argon2id v19)
438
+ let argon2 = Argon2 :: default ( ) ;
439
+
440
+ // Hash password to PHC string ($argon2id$v=19$...)
441
+ let password_hash = argon2. hash_password ( password. as_bytes ( ) , & salt) ?. to_string ( ) ;
442
+
443
+ Ok ( password_hash)
444
+ }
0 commit comments