completePasswordReset static method
Returns the auth user ID for the successfully changed password
Throws an EmailAccountPasswordResetRequestNotFoundException in case no
reset request could be found for passwordResetRequestId
.
Throws an EmailAccountPasswordResetRequestExpiredException in case the
reset request has expired.
Throws an EmailAccountPasswordPolicyViolationException in case the
password does not confirm to the configured policy.
Throws an EmailAccountPasswordResetRequestUnauthorizedException in case
the verificationCode
is not valid.
In case of an invalid verificationCode
, the failed password reset
completion will be logged to the database outside of the transaction
and
can not be rolled back.
Implementation
static Future<UuidValue> completePasswordReset(
final Session session, {
required final UuidValue passwordResetRequestId,
required final String verificationCode,
required final String newPassword,
final Transaction? transaction,
}) async {
return DatabaseUtil.runInTransactionOrSavepoint(
session.db,
transaction,
(final transaction) async {
final resetRequest = await EmailAccountPasswordResetRequest.db.findById(
session,
passwordResetRequestId,
transaction: transaction,
);
if (resetRequest == null) {
throw EmailAccountPasswordResetRequestNotFoundException();
}
if (resetRequest.isExpired) {
await EmailAccountPasswordResetRequest.db.deleteRow(
session,
resetRequest,
// passing no transaction, so this will not be rolled back
);
throw EmailAccountPasswordResetRequestExpiredException();
}
if (!EmailAccounts.config.passwordValidationFunction(newPassword)) {
throw EmailAccountPasswordPolicyViolationException();
}
if (await _hasTooManyPasswordResetAttempts(
session,
passwordResetRequestId: resetRequest.id!,
)) {
await EmailAccountPasswordResetRequest.db.deleteRow(
session,
resetRequest,
// passing no transaction, so this will not be rolled back
);
throw EmailAccountPasswordResetTooManyAttemptsException();
}
if (!await EmailAccountSecretHash.validateHash(
value: verificationCode,
hash: resetRequest.verificationCodeHash.asUint8List,
salt: resetRequest.verificationCodeSalt.asUint8List,
)) {
throw EmailAccountPasswordResetRequestUnauthorizedException();
}
await EmailAccountPasswordResetRequest.db.deleteRow(
session,
resetRequest,
transaction: transaction,
);
final account = (await EmailAccount.db.findById(
session,
resetRequest.emailAccountId,
transaction: transaction,
))!;
final newPasswordHash = await EmailAccountSecretHash.createHash(
value: newPassword,
);
await EmailAccount.db.updateRow(
session,
account.copyWith(
passwordHash: ByteData.sublistView(newPasswordHash.hash),
passwordSalt: ByteData.sublistView(newPasswordHash.salt),
),
transaction: transaction,
);
return account.authUserId;
},
);
}