@@ -95,29 +95,18 @@ impl RegistrationService {
9595 }
9696 }
9797
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+ } ;
113102
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+ ) ?;
116108
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 ) ?;
121110
122111 let user_id = self
123112 . user_repository
@@ -217,35 +206,24 @@ impl ProfileService {
217206
218207 let settings = self . configuration . settings . read ( ) . await ;
219208
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
223210
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+ } ;
239215
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+ ) ?;
242221
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 ) ?;
247223
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 ?;
249227
250228 Ok ( ( ) )
251229 }
@@ -429,3 +407,38 @@ impl DbBannedUserList {
429407 self . database . ban_user ( * user_id, & reason, date_expiry) . await
430408 }
431409}
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