Skip to content

Commit 0d0a63f

Browse files
author
Lasim
committed
refactor(backend): enhance password reset logging and error handling
1 parent 0786ad2 commit 0d0a63f

File tree

3 files changed

+58
-12
lines changed

3 files changed

+58
-12
lines changed

services/backend/src/routes/auth/resetPassword.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export default async function resetPasswordRoute(server: FastifyInstance) {
131131
server.log.info('Password reset attempt with token');
132132

133133
// Validate token and reset password
134-
const result = await PasswordResetService.validateAndResetPassword(token, new_password);
134+
const result = await PasswordResetService.validateAndResetPassword(token, new_password, server.log);
135135

136136
if (!result.success) {
137137
if (result.error === 'Invalid or expired reset token') {

services/backend/src/services/passwordResetService.ts

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,35 +75,82 @@ export class PasswordResetService {
7575
/**
7676
* Validate reset token and reset password
7777
*/
78-
static async validateAndResetPassword(token: string, newPassword: string, logger?: FastifyBaseLogger): Promise<{ success: boolean; error?: string; userId?: string }> {
78+
static async validateAndResetPassword(token: string, newPassword: string, logger: FastifyBaseLogger): Promise<{ success: boolean; error?: string; userId?: string }> {
7979
const db = getDb();
8080
const schema = getSchema();
8181
const passwordResetTokensTable = schema.passwordResetTokens;
8282
const authUserTable = schema.authUser;
8383

8484
if (!passwordResetTokensTable || !authUserTable) {
85-
return { success: false, error: 'Database tables not found' };
85+
const error = 'Database tables not found';
86+
logger.error({ error }, 'Database configuration error during password reset');
87+
return { success: false, error };
8688
}
8789

8890
try {
89-
// Get all non-expired tokens
91+
logger.debug({
92+
tokenLength: token.length,
93+
tokenStart: token.substring(0, 8) + '...',
94+
operation: 'validate_reset_password'
95+
}, 'Starting password reset token validation');
96+
97+
// Get all non-expired tokens with more detailed logging
98+
const currentTime = new Date();
9099
// eslint-disable-next-line @typescript-eslint/no-explicit-any
91100
const tokens = await (db as any)
92101
.select()
93102
.from(passwordResetTokensTable)
94-
.where(gt(passwordResetTokensTable.expires_at, new Date()));
103+
.where(gt(passwordResetTokensTable.expires_at, currentTime));
95104

96-
// Find matching token
105+
logger.debug({
106+
totalTokensFound: tokens.length,
107+
currentTime: currentTime.toISOString(),
108+
operation: 'validate_reset_password'
109+
}, 'Retrieved non-expired tokens from database');
110+
111+
if (tokens.length === 0) {
112+
logger.warn('No non-expired tokens found in database');
113+
return { success: false, error: 'Invalid or expired reset token' };
114+
}
115+
116+
// Find matching token with detailed logging
97117
let matchingToken = null;
118+
let verificationAttempts = 0;
119+
98120
for (const dbToken of tokens) {
121+
verificationAttempts++;
122+
logger.debug({
123+
attempt: verificationAttempts,
124+
tokenId: dbToken.id,
125+
expiresAt: dbToken.expires_at,
126+
userId: dbToken.user_id
127+
}, 'Attempting token verification');
128+
99129
const isValid = await this.verifyToken(token, dbToken.token_hash);
130+
131+
logger.debug({
132+
attempt: verificationAttempts,
133+
tokenId: dbToken.id,
134+
isValid
135+
}, 'Token verification result');
136+
100137
if (isValid) {
101138
matchingToken = dbToken;
139+
logger.debug({
140+
tokenId: dbToken.id,
141+
userId: dbToken.user_id,
142+
attempts: verificationAttempts
143+
}, 'Found matching token');
102144
break;
103145
}
104146
}
105147

106148
if (!matchingToken) {
149+
logger.warn({
150+
totalAttempts: verificationAttempts,
151+
providedTokenLength: token.length,
152+
operation: 'validate_reset_password'
153+
}, 'No matching token found after verification attempts');
107154
return { success: false, error: 'Invalid or expired reset token' };
108155
}
109156

@@ -153,12 +200,10 @@ export class PasswordResetService {
153200

154201
return { success: true, userId: matchingToken.user_id };
155202
} catch (error) {
156-
if (logger) {
157-
logger.error({
158-
error,
159-
operation: 'validate_reset_password'
160-
}, 'Error validating reset token and resetting password');
161-
}
203+
logger.error({
204+
error,
205+
operation: 'validate_reset_password'
206+
}, 'Error validating reset token and resetting password');
162207
return { success: false, error: 'An error occurred during password reset' };
163208
}
164209
}

services/frontend/src/views/ResetPassword.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ const navigateToLogin = () => {
161161
// Extract token from URL on component mount
162162
onMounted(() => {
163163
const urlToken = route.query.token as string
164+
164165
if (!urlToken) {
165166
errorMessage.value = t('resetPassword.errors.invalidToken')
166167
return

0 commit comments

Comments
 (0)