chore: migrate user identity from auth0_sub to UUID #219

Merged
egullickson merged 10 commits from issue-206-migrate-user-identity-uuid into main 2026-02-16 20:55:41 +00:00
16 changed files with 177 additions and 169 deletions
Showing only changes of commit dd3b58e061 - Show all commits

View File

@@ -110,17 +110,17 @@ export class AuthController {
*/ */
async getVerifyStatus(request: FastifyRequest, reply: FastifyReply) { async getVerifyStatus(request: FastifyRequest, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const auth0Sub = (request as any).user.sub;
const result = await this.authService.getVerifyStatus(userId); const result = await this.authService.getVerifyStatus(auth0Sub);
logger.info('Verification status checked', { userId, emailVerified: result.emailVerified }); logger.info('Verification status checked', { userId: request.userContext?.userId, emailVerified: result.emailVerified });
return reply.code(200).send(result); return reply.code(200).send(result);
} catch (error: any) { } catch (error: any) {
logger.error('Failed to get verification status', { logger.error('Failed to get verification status', {
error, error,
userId: (request as any).user?.sub, userId: request.userContext?.userId,
}); });
return reply.code(500).send({ return reply.code(500).send({
@@ -137,17 +137,17 @@ export class AuthController {
*/ */
async resendVerification(request: FastifyRequest, reply: FastifyReply) { async resendVerification(request: FastifyRequest, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const auth0Sub = (request as any).user.sub;
const result = await this.authService.resendVerification(userId); const result = await this.authService.resendVerification(auth0Sub);
logger.info('Verification email resent', { userId }); logger.info('Verification email resent', { userId: request.userContext?.userId });
return reply.code(200).send(result); return reply.code(200).send(result);
} catch (error: any) { } catch (error: any) {
logger.error('Failed to resend verification email', { logger.error('Failed to resend verification email', {
error, error,
userId: (request as any).user?.sub, userId: request.userContext?.userId,
}); });
return reply.code(500).send({ return reply.code(500).send({
@@ -199,23 +199,26 @@ export class AuthController {
*/ */
async getUserStatus(request: FastifyRequest, reply: FastifyReply) { async getUserStatus(request: FastifyRequest, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const auth0Sub = (request as any).user.sub;
const userId = request.userContext?.userId;
const result = await this.authService.getUserStatus(userId); const result = await this.authService.getUserStatus(auth0Sub);
// Log login event to audit trail (called once per Auth0 callback) // Log login event to audit trail (called once per Auth0 callback)
const ipAddress = this.getClientIp(request); const ipAddress = this.getClientIp(request);
await auditLogService.info( if (userId) {
'auth', await auditLogService.info(
userId, 'auth',
'User login', userId,
'user', 'User login',
userId, 'user',
{ ipAddress } userId,
).catch(err => logger.error('Failed to log login audit event', { error: err })); { ipAddress }
).catch(err => logger.error('Failed to log login audit event', { error: err }));
}
logger.info('User status retrieved', { logger.info('User status retrieved', {
userId: userId.substring(0, 8) + '...', userId: userId?.substring(0, 8) + '...',
emailVerified: result.emailVerified, emailVerified: result.emailVerified,
onboardingCompleted: result.onboardingCompleted, onboardingCompleted: result.onboardingCompleted,
}); });
@@ -224,7 +227,7 @@ export class AuthController {
} catch (error: any) { } catch (error: any) {
logger.error('Failed to get user status', { logger.error('Failed to get user status', {
error, error,
userId: (request as any).user?.sub, userId: request.userContext?.userId,
}); });
return reply.code(500).send({ return reply.code(500).send({
@@ -241,12 +244,12 @@ export class AuthController {
*/ */
async getSecurityStatus(request: FastifyRequest, reply: FastifyReply) { async getSecurityStatus(request: FastifyRequest, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const auth0Sub = (request as any).user.sub;
const result = await this.authService.getSecurityStatus(userId); const result = await this.authService.getSecurityStatus(auth0Sub);
logger.info('Security status retrieved', { logger.info('Security status retrieved', {
userId: userId.substring(0, 8) + '...', userId: request.userContext?.userId,
emailVerified: result.emailVerified, emailVerified: result.emailVerified,
}); });
@@ -254,7 +257,7 @@ export class AuthController {
} catch (error: any) { } catch (error: any) {
logger.error('Failed to get security status', { logger.error('Failed to get security status', {
error, error,
userId: (request as any).user?.sub, userId: request.userContext?.userId,
}); });
return reply.code(500).send({ return reply.code(500).send({
@@ -271,28 +274,31 @@ export class AuthController {
*/ */
async requestPasswordReset(request: FastifyRequest, reply: FastifyReply) { async requestPasswordReset(request: FastifyRequest, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const auth0Sub = (request as any).user.sub;
const userId = request.userContext?.userId;
const result = await this.authService.requestPasswordReset(userId); const result = await this.authService.requestPasswordReset(auth0Sub);
logger.info('Password reset email requested', { logger.info('Password reset email requested', {
userId: userId.substring(0, 8) + '...', userId: userId?.substring(0, 8) + '...',
}); });
// Log password reset request to unified audit log // Log password reset request to unified audit log
await auditLogService.info( if (userId) {
'auth', await auditLogService.info(
userId, 'auth',
'Password reset requested', userId,
'user', 'Password reset requested',
userId 'user',
).catch(err => logger.error('Failed to log password reset audit event', { error: err })); userId
).catch(err => logger.error('Failed to log password reset audit event', { error: err }));
}
return reply.code(200).send(result); return reply.code(200).send(result);
} catch (error: any) { } catch (error: any) {
logger.error('Failed to request password reset', { logger.error('Failed to request password reset', {
error, error,
userId: (request as any).user?.sub, userId: request.userContext?.userId,
}); });
return reply.code(500).send({ return reply.code(500).send({
@@ -312,21 +318,23 @@ export class AuthController {
*/ */
async trackLogout(request: FastifyRequest, reply: FastifyReply) { async trackLogout(request: FastifyRequest, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext?.userId;
const ipAddress = this.getClientIp(request); const ipAddress = this.getClientIp(request);
// Log logout event to audit trail // Log logout event to audit trail
await auditLogService.info( if (userId) {
'auth', await auditLogService.info(
userId, 'auth',
'User logout', userId,
'user', 'User logout',
userId, 'user',
{ ipAddress } userId,
).catch(err => logger.error('Failed to log logout audit event', { error: err })); { ipAddress }
).catch(err => logger.error('Failed to log logout audit event', { error: err }));
}
logger.info('User logout tracked', { logger.info('User logout tracked', {
userId: userId.substring(0, 8) + '...', userId: userId?.substring(0, 8) + '...',
}); });
return reply.code(200).send({ success: true }); return reply.code(200).send({ success: true });
@@ -334,7 +342,7 @@ export class AuthController {
// Don't block logout on audit failure - always return success // Don't block logout on audit failure - always return success
logger.error('Failed to track logout', { logger.error('Failed to track logout', {
error, error,
userId: (request as any).user?.sub, userId: request.userContext?.userId,
}); });
return reply.code(200).send({ success: true }); return reply.code(200).send({ success: true });

View File

@@ -15,7 +15,7 @@ export class DocumentsController {
private readonly service = new DocumentsService(); private readonly service = new DocumentsService();
async list(request: FastifyRequest<{ Querystring: ListQuery }>, reply: FastifyReply) { async list(request: FastifyRequest<{ Querystring: ListQuery }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
logger.info('Documents list requested', { logger.info('Documents list requested', {
operation: 'documents.list', operation: 'documents.list',
@@ -43,7 +43,7 @@ export class DocumentsController {
} }
async get(request: FastifyRequest<{ Params: IdParams }>, reply: FastifyReply) { async get(request: FastifyRequest<{ Params: IdParams }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const documentId = request.params.id; const documentId = request.params.id;
logger.info('Document get requested', { logger.info('Document get requested', {
@@ -74,7 +74,7 @@ export class DocumentsController {
} }
async create(request: FastifyRequest<{ Body: CreateBody }>, reply: FastifyReply) { async create(request: FastifyRequest<{ Body: CreateBody }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const userTier: SubscriptionTier = request.userContext?.subscriptionTier || 'free'; const userTier: SubscriptionTier = request.userContext?.subscriptionTier || 'free';
logger.info('Document create requested', { logger.info('Document create requested', {
@@ -120,7 +120,7 @@ export class DocumentsController {
} }
async update(request: FastifyRequest<{ Params: IdParams; Body: UpdateBody }>, reply: FastifyReply) { async update(request: FastifyRequest<{ Params: IdParams; Body: UpdateBody }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const userTier: SubscriptionTier = request.userContext?.subscriptionTier || 'free'; const userTier: SubscriptionTier = request.userContext?.subscriptionTier || 'free';
const documentId = request.params.id; const documentId = request.params.id;
@@ -174,7 +174,7 @@ export class DocumentsController {
} }
async remove(request: FastifyRequest<{ Params: IdParams }>, reply: FastifyReply) { async remove(request: FastifyRequest<{ Params: IdParams }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const documentId = request.params.id; const documentId = request.params.id;
logger.info('Document delete requested', { logger.info('Document delete requested', {
@@ -221,7 +221,7 @@ export class DocumentsController {
} }
async upload(request: FastifyRequest<{ Params: IdParams }>, reply: FastifyReply) { async upload(request: FastifyRequest<{ Params: IdParams }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const documentId = request.params.id; const documentId = request.params.id;
logger.info('Document upload requested', { logger.info('Document upload requested', {
@@ -373,7 +373,7 @@ export class DocumentsController {
} }
async download(request: FastifyRequest<{ Params: IdParams }>, reply: FastifyReply) { async download(request: FastifyRequest<{ Params: IdParams }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const documentId = request.params.id; const documentId = request.params.id;
logger.info('Document download requested', { logger.info('Document download requested', {
@@ -423,7 +423,7 @@ export class DocumentsController {
} }
async listByVehicle(request: FastifyRequest<{ Params: { vehicleId: string } }>, reply: FastifyReply) { async listByVehicle(request: FastifyRequest<{ Params: { vehicleId: string } }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const vehicleId = request.params.vehicleId; const vehicleId = request.params.vehicleId;
logger.info('Documents by vehicle requested', { logger.info('Documents by vehicle requested', {
@@ -457,7 +457,7 @@ export class DocumentsController {
} }
async addVehicle(request: FastifyRequest<{ Params: { id: string; vehicleId: string } }>, reply: FastifyReply) { async addVehicle(request: FastifyRequest<{ Params: { id: string; vehicleId: string } }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const { id: documentId, vehicleId } = request.params; const { id: documentId, vehicleId } = request.params;
logger.info('Add vehicle to document requested', { logger.info('Add vehicle to document requested', {
@@ -523,7 +523,7 @@ export class DocumentsController {
} }
async removeVehicle(request: FastifyRequest<{ Params: { id: string; vehicleId: string } }>, reply: FastifyReply) { async removeVehicle(request: FastifyRequest<{ Params: { id: string; vehicleId: string } }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const { id: documentId, vehicleId } = request.params; const { id: documentId, vehicleId } = request.params;
logger.info('Remove vehicle from document requested', { logger.info('Remove vehicle from document requested', {

View File

@@ -27,22 +27,22 @@ export class EmailIngestionController {
async getPendingAssociations(request: FastifyRequest, reply: FastifyReply): Promise<void> { async getPendingAssociations(request: FastifyRequest, reply: FastifyReply): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const associations = await this.repository.getPendingAssociations(userId); const associations = await this.repository.getPendingAssociations(userId);
return reply.code(200).send(associations); return reply.code(200).send(associations);
} catch (error: any) { } catch (error: any) {
logger.error('Error listing pending associations', { error: error.message, userId: (request as any).user?.sub }); logger.error('Error listing pending associations', { error: error.message, userId: request.userContext?.userId });
return reply.code(500).send({ error: 'Failed to list pending associations' }); return reply.code(500).send({ error: 'Failed to list pending associations' });
} }
} }
async getPendingAssociationCount(request: FastifyRequest, reply: FastifyReply): Promise<void> { async getPendingAssociationCount(request: FastifyRequest, reply: FastifyReply): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const count = await this.repository.getPendingAssociationCount(userId); const count = await this.repository.getPendingAssociationCount(userId);
return reply.code(200).send({ count }); return reply.code(200).send({ count });
} catch (error: any) { } catch (error: any) {
logger.error('Error counting pending associations', { error: error.message, userId: (request as any).user?.sub }); logger.error('Error counting pending associations', { error: error.message, userId: request.userContext?.userId });
return reply.code(500).send({ error: 'Failed to count pending associations' }); return reply.code(500).send({ error: 'Failed to count pending associations' });
} }
} }
@@ -52,7 +52,7 @@ export class EmailIngestionController {
reply: FastifyReply reply: FastifyReply
): Promise<void> { ): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { id } = request.params; const { id } = request.params;
const { vehicleId } = request.body; const { vehicleId } = request.body;
@@ -63,7 +63,7 @@ export class EmailIngestionController {
const result = await this.service.resolveAssociation(id, vehicleId, userId); const result = await this.service.resolveAssociation(id, vehicleId, userId);
return reply.code(200).send(result); return reply.code(200).send(result);
} catch (error: any) { } catch (error: any) {
const userId = (request as any).user?.sub; const userId = request.userContext?.userId;
logger.error('Error resolving pending association', { logger.error('Error resolving pending association', {
error: error.message, error: error.message,
associationId: request.params.id, associationId: request.params.id,
@@ -89,13 +89,13 @@ export class EmailIngestionController {
reply: FastifyReply reply: FastifyReply
): Promise<void> { ): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { id } = request.params; const { id } = request.params;
await this.service.dismissAssociation(id, userId); await this.service.dismissAssociation(id, userId);
return reply.code(204).send(); return reply.code(204).send();
} catch (error: any) { } catch (error: any) {
const userId = (request as any).user?.sub; const userId = request.userContext?.userId;
logger.error('Error dismissing pending association', { logger.error('Error dismissing pending association', {
error: error.message, error: error.message,
associationId: request.params.id, associationId: request.params.id,

View File

@@ -20,12 +20,12 @@ export class FuelLogsController {
async createFuelLog(request: FastifyRequest<{ Body: EnhancedCreateFuelLogRequest }>, reply: FastifyReply) { async createFuelLog(request: FastifyRequest<{ Body: EnhancedCreateFuelLogRequest }>, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const fuelLog = await this.fuelLogsService.createFuelLog(request.body, userId); const fuelLog = await this.fuelLogsService.createFuelLog(request.body, userId);
return reply.code(201).send(fuelLog); return reply.code(201).send(fuelLog);
} catch (error: any) { } catch (error: any) {
logger.error('Error creating fuel log', { error, userId: (request as any).user?.sub }); logger.error('Error creating fuel log', { error, userId: request.userContext?.userId });
if (error.message.includes('not found')) { if (error.message.includes('not found')) {
return reply.code(404).send({ return reply.code(404).send({
@@ -49,14 +49,14 @@ export class FuelLogsController {
async getFuelLogsByVehicle(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) { async getFuelLogsByVehicle(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { vehicleId } = request.params; const { vehicleId } = request.params;
const fuelLogs = await this.fuelLogsService.getFuelLogsByVehicle(vehicleId, userId); const fuelLogs = await this.fuelLogsService.getFuelLogsByVehicle(vehicleId, userId);
return reply.code(200).send(fuelLogs); return reply.code(200).send(fuelLogs);
} catch (error: any) { } catch (error: any) {
logger.error('Error listing fuel logs', { error, vehicleId: request.params.vehicleId, userId: (request as any).user?.sub }); logger.error('Error listing fuel logs', { error, vehicleId: request.params.vehicleId, userId: request.userContext?.userId });
if (error.message.includes('not found')) { if (error.message.includes('not found')) {
return reply.code(404).send({ return reply.code(404).send({
@@ -80,12 +80,12 @@ export class FuelLogsController {
async getUserFuelLogs(request: FastifyRequest, reply: FastifyReply) { async getUserFuelLogs(request: FastifyRequest, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const fuelLogs = await this.fuelLogsService.getUserFuelLogs(userId); const fuelLogs = await this.fuelLogsService.getUserFuelLogs(userId);
return reply.code(200).send(fuelLogs); return reply.code(200).send(fuelLogs);
} catch (error: any) { } catch (error: any) {
logger.error('Error listing all fuel logs', { error, userId: (request as any).user?.sub }); logger.error('Error listing all fuel logs', { error, userId: request.userContext?.userId });
return reply.code(500).send({ return reply.code(500).send({
error: 'Internal server error', error: 'Internal server error',
message: 'Failed to get fuel logs' message: 'Failed to get fuel logs'
@@ -95,14 +95,14 @@ export class FuelLogsController {
async getFuelLog(request: FastifyRequest<{ Params: FuelLogParams }>, reply: FastifyReply) { async getFuelLog(request: FastifyRequest<{ Params: FuelLogParams }>, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { id } = request.params; const { id } = request.params;
const fuelLog = await this.fuelLogsService.getFuelLog(id, userId); const fuelLog = await this.fuelLogsService.getFuelLog(id, userId);
return reply.code(200).send(fuelLog); return reply.code(200).send(fuelLog);
} catch (error: any) { } catch (error: any) {
logger.error('Error getting fuel log', { error, fuelLogId: request.params.id, userId: (request as any).user?.sub }); logger.error('Error getting fuel log', { error, fuelLogId: request.params.id, userId: request.userContext?.userId });
if (error.message === 'Fuel log not found') { if (error.message === 'Fuel log not found') {
return reply.code(404).send({ return reply.code(404).send({
@@ -126,14 +126,14 @@ export class FuelLogsController {
async updateFuelLog(request: FastifyRequest<{ Params: FuelLogParams; Body: EnhancedUpdateFuelLogRequest }>, reply: FastifyReply) { async updateFuelLog(request: FastifyRequest<{ Params: FuelLogParams; Body: EnhancedUpdateFuelLogRequest }>, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { id } = request.params; const { id } = request.params;
const updatedFuelLog = await this.fuelLogsService.updateFuelLog(id, request.body, userId); const updatedFuelLog = await this.fuelLogsService.updateFuelLog(id, request.body, userId);
return reply.code(200).send(updatedFuelLog); return reply.code(200).send(updatedFuelLog);
} catch (error: any) { } catch (error: any) {
logger.error('Error updating fuel log', { error, fuelLogId: request.params.id, userId: (request as any).user?.sub }); logger.error('Error updating fuel log', { error, fuelLogId: request.params.id, userId: request.userContext?.userId });
if (error.message.includes('not found')) { if (error.message.includes('not found')) {
return reply.code(404).send({ return reply.code(404).send({
@@ -163,14 +163,14 @@ export class FuelLogsController {
async deleteFuelLog(request: FastifyRequest<{ Params: FuelLogParams }>, reply: FastifyReply) { async deleteFuelLog(request: FastifyRequest<{ Params: FuelLogParams }>, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { id } = request.params; const { id } = request.params;
await this.fuelLogsService.deleteFuelLog(id, userId); await this.fuelLogsService.deleteFuelLog(id, userId);
return reply.code(204).send(); return reply.code(204).send();
} catch (error: any) { } catch (error: any) {
logger.error('Error deleting fuel log', { error, fuelLogId: request.params.id, userId: (request as any).user?.sub }); logger.error('Error deleting fuel log', { error, fuelLogId: request.params.id, userId: request.userContext?.userId });
if (error.message.includes('not found')) { if (error.message.includes('not found')) {
return reply.code(404).send({ return reply.code(404).send({
@@ -194,14 +194,14 @@ export class FuelLogsController {
async getFuelStats(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) { async getFuelStats(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { vehicleId } = request.params; const { vehicleId } = request.params;
const stats = await this.fuelLogsService.getVehicleStats(vehicleId, userId); const stats = await this.fuelLogsService.getVehicleStats(vehicleId, userId);
return reply.code(200).send(stats); return reply.code(200).send(stats);
} catch (error: any) { } catch (error: any) {
logger.error('Error getting fuel stats', { error, vehicleId: request.params.vehicleId, userId: (request as any).user?.sub }); logger.error('Error getting fuel stats', { error, vehicleId: request.params.vehicleId, userId: request.userContext?.userId });
if (error.message.includes('not found')) { if (error.message.includes('not found')) {
return reply.code(404).send({ return reply.code(404).send({

View File

@@ -18,7 +18,7 @@ export class MaintenanceController {
request: FastifyRequest<{ Querystring: { vehicleId?: string; category?: string } }>, request: FastifyRequest<{ Querystring: { vehicleId?: string; category?: string } }>,
reply: FastifyReply reply: FastifyReply
) { ) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
logger.info('Maintenance records list requested', { logger.info('Maintenance records list requested', {
operation: 'maintenance.records.list', operation: 'maintenance.records.list',
@@ -58,7 +58,7 @@ export class MaintenanceController {
} }
async getRecord(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) { async getRecord(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const recordId = request.params.id; const recordId = request.params.id;
logger.info('Maintenance record get requested', { logger.info('Maintenance record get requested', {
@@ -102,7 +102,7 @@ export class MaintenanceController {
request: FastifyRequest<{ Params: { vehicleId: string } }>, request: FastifyRequest<{ Params: { vehicleId: string } }>,
reply: FastifyReply reply: FastifyReply
) { ) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const vehicleId = request.params.vehicleId; const vehicleId = request.params.vehicleId;
logger.info('Maintenance records by vehicle requested', { logger.info('Maintenance records by vehicle requested', {
@@ -134,7 +134,7 @@ export class MaintenanceController {
} }
async createRecord(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply) { async createRecord(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
logger.info('Maintenance record create requested', { logger.info('Maintenance record create requested', {
operation: 'maintenance.records.create', operation: 'maintenance.records.create',
@@ -190,7 +190,7 @@ export class MaintenanceController {
request: FastifyRequest<{ Params: { id: string }; Body: unknown }>, request: FastifyRequest<{ Params: { id: string }; Body: unknown }>,
reply: FastifyReply reply: FastifyReply
) { ) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const recordId = request.params.id; const recordId = request.params.id;
logger.info('Maintenance record update requested', { logger.info('Maintenance record update requested', {
@@ -255,7 +255,7 @@ export class MaintenanceController {
} }
async deleteRecord(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) { async deleteRecord(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const recordId = request.params.id; const recordId = request.params.id;
logger.info('Maintenance record delete requested', { logger.info('Maintenance record delete requested', {
@@ -289,7 +289,7 @@ export class MaintenanceController {
request: FastifyRequest<{ Params: { vehicleId: string } }>, request: FastifyRequest<{ Params: { vehicleId: string } }>,
reply: FastifyReply reply: FastifyReply
) { ) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const vehicleId = request.params.vehicleId; const vehicleId = request.params.vehicleId;
logger.info('Maintenance schedules by vehicle requested', { logger.info('Maintenance schedules by vehicle requested', {
@@ -321,7 +321,7 @@ export class MaintenanceController {
} }
async createSchedule(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply) { async createSchedule(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
logger.info('Maintenance schedule create requested', { logger.info('Maintenance schedule create requested', {
operation: 'maintenance.schedules.create', operation: 'maintenance.schedules.create',
@@ -377,7 +377,7 @@ export class MaintenanceController {
request: FastifyRequest<{ Params: { id: string }; Body: unknown }>, request: FastifyRequest<{ Params: { id: string }; Body: unknown }>,
reply: FastifyReply reply: FastifyReply
) { ) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const scheduleId = request.params.id; const scheduleId = request.params.id;
logger.info('Maintenance schedule update requested', { logger.info('Maintenance schedule update requested', {
@@ -442,7 +442,7 @@ export class MaintenanceController {
} }
async deleteSchedule(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) { async deleteSchedule(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const scheduleId = request.params.id; const scheduleId = request.params.id;
logger.info('Maintenance schedule delete requested', { logger.info('Maintenance schedule delete requested', {
@@ -476,7 +476,7 @@ export class MaintenanceController {
request: FastifyRequest<{ Params: { vehicleId: string }; Querystring: { currentMileage?: string } }>, request: FastifyRequest<{ Params: { vehicleId: string }; Querystring: { currentMileage?: string } }>,
reply: FastifyReply reply: FastifyReply
) { ) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const vehicleId = request.params.vehicleId; const vehicleId = request.params.vehicleId;
const currentMileage = request.query.currentMileage ? parseInt(request.query.currentMileage, 10) : undefined; const currentMileage = request.query.currentMileage ? parseInt(request.query.currentMileage, 10) : undefined;
@@ -510,7 +510,7 @@ export class MaintenanceController {
} }
async getSubtypes(request: FastifyRequest<{ Params: { category: string } }>, reply: FastifyReply) { async getSubtypes(request: FastifyRequest<{ Params: { category: string } }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const category = request.params.category; const category = request.params.category;
logger.info('Maintenance subtypes requested', { logger.info('Maintenance subtypes requested', {

View File

@@ -24,7 +24,7 @@ export class NotificationsController {
// ======================== // ========================
async getSummary(request: FastifyRequest, reply: FastifyReply) { async getSummary(request: FastifyRequest, reply: FastifyReply) {
const userId = request.user.sub; const userId = request.userContext!.userId;
try { try {
const summary = await this.service.getNotificationSummary(userId); const summary = await this.service.getNotificationSummary(userId);
@@ -38,7 +38,7 @@ export class NotificationsController {
} }
async getDueMaintenanceItems(request: FastifyRequest, reply: FastifyReply) { async getDueMaintenanceItems(request: FastifyRequest, reply: FastifyReply) {
const userId = request.user.sub; const userId = request.userContext!.userId;
try { try {
const items = await this.service.getDueMaintenanceItems(userId); const items = await this.service.getDueMaintenanceItems(userId);
@@ -52,7 +52,7 @@ export class NotificationsController {
} }
async getExpiringDocuments(request: FastifyRequest, reply: FastifyReply) { async getExpiringDocuments(request: FastifyRequest, reply: FastifyReply) {
const userId = request.user.sub; const userId = request.userContext!.userId;
try { try {
const documents = await this.service.getExpiringDocuments(userId); const documents = await this.service.getExpiringDocuments(userId);
@@ -70,7 +70,7 @@ export class NotificationsController {
// ======================== // ========================
async getInAppNotifications(request: FastifyRequest, reply: FastifyReply) { async getInAppNotifications(request: FastifyRequest, reply: FastifyReply) {
const userId = request.user!.sub!; const userId = request.userContext!.userId;
const query = request.query as { limit?: string; includeRead?: string }; const query = request.query as { limit?: string; includeRead?: string };
const limit = query.limit ? parseInt(query.limit, 10) : 20; const limit = query.limit ? parseInt(query.limit, 10) : 20;
const includeRead = query.includeRead === 'true'; const includeRead = query.includeRead === 'true';
@@ -85,7 +85,7 @@ export class NotificationsController {
} }
async getUnreadCount(request: FastifyRequest, reply: FastifyReply) { async getUnreadCount(request: FastifyRequest, reply: FastifyReply) {
const userId = request.user!.sub!; const userId = request.userContext!.userId;
try { try {
const count = await this.service.getUnreadCount(userId); const count = await this.service.getUnreadCount(userId);
@@ -97,7 +97,7 @@ export class NotificationsController {
} }
async markAsRead(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) { async markAsRead(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) {
const userId = request.user!.sub!; const userId = request.userContext!.userId;
const notificationId = request.params.id; const notificationId = request.params.id;
try { try {
@@ -113,7 +113,7 @@ export class NotificationsController {
} }
async markAllAsRead(request: FastifyRequest, reply: FastifyReply) { async markAllAsRead(request: FastifyRequest, reply: FastifyReply) {
const userId = request.user!.sub!; const userId = request.userContext!.userId;
try { try {
const count = await this.service.markAllAsRead(userId); const count = await this.service.markAllAsRead(userId);
@@ -125,7 +125,7 @@ export class NotificationsController {
} }
async deleteNotification(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) { async deleteNotification(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) {
const userId = request.user!.sub!; const userId = request.userContext!.userId;
const notificationId = request.params.id; const notificationId = request.params.id;
try { try {

View File

@@ -51,7 +51,7 @@ export class OnboardingController {
const errorMessage = error instanceof Error ? error.message : 'Unknown error'; const errorMessage = error instanceof Error ? error.message : 'Unknown error';
logger.error('Error in savePreferences controller', { logger.error('Error in savePreferences controller', {
error, error,
userId: (request as AuthenticatedRequest).user?.sub, userId: request.userContext?.userId,
}); });
if (errorMessage === 'User profile not found') { if (errorMessage === 'User profile not found') {
@@ -86,7 +86,7 @@ export class OnboardingController {
const errorMessage = error instanceof Error ? error.message : 'Unknown error'; const errorMessage = error instanceof Error ? error.message : 'Unknown error';
logger.error('Error in completeOnboarding controller', { logger.error('Error in completeOnboarding controller', {
error, error,
userId: (request as AuthenticatedRequest).user?.sub, userId: request.userContext?.userId,
}); });
if (errorMessage === 'User profile not found') { if (errorMessage === 'User profile not found') {
@@ -124,7 +124,7 @@ export class OnboardingController {
const errorMessage = error instanceof Error ? error.message : 'Unknown error'; const errorMessage = error instanceof Error ? error.message : 'Unknown error';
logger.error('Error in getStatus controller', { logger.error('Error in getStatus controller', {
error, error,
userId: (request as AuthenticatedRequest).user?.sub, userId: request.userContext?.userId,
}); });
if (errorMessage === 'User profile not found') { if (errorMessage === 'User profile not found') {

View File

@@ -7,7 +7,7 @@ export class OwnershipCostsController {
private readonly service = new OwnershipCostsService(); private readonly service = new OwnershipCostsService();
async list(request: FastifyRequest<{ Querystring: ListQuery }>, reply: FastifyReply) { async list(request: FastifyRequest<{ Querystring: ListQuery }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
logger.info('Ownership costs list requested', { logger.info('Ownership costs list requested', {
operation: 'ownership-costs.list', operation: 'ownership-costs.list',
@@ -35,7 +35,7 @@ export class OwnershipCostsController {
} }
async get(request: FastifyRequest<{ Params: IdParams }>, reply: FastifyReply) { async get(request: FastifyRequest<{ Params: IdParams }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const costId = request.params.id; const costId = request.params.id;
logger.info('Ownership cost get requested', { logger.info('Ownership cost get requested', {
@@ -66,7 +66,7 @@ export class OwnershipCostsController {
} }
async create(request: FastifyRequest<{ Body: CreateBody }>, reply: FastifyReply) { async create(request: FastifyRequest<{ Body: CreateBody }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
logger.info('Ownership cost create requested', { logger.info('Ownership cost create requested', {
operation: 'ownership-costs.create', operation: 'ownership-costs.create',
@@ -91,7 +91,7 @@ export class OwnershipCostsController {
} }
async update(request: FastifyRequest<{ Params: IdParams; Body: UpdateBody }>, reply: FastifyReply) { async update(request: FastifyRequest<{ Params: IdParams; Body: UpdateBody }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const costId = request.params.id; const costId = request.params.id;
logger.info('Ownership cost update requested', { logger.info('Ownership cost update requested', {
@@ -123,7 +123,7 @@ export class OwnershipCostsController {
} }
async remove(request: FastifyRequest<{ Params: IdParams }>, reply: FastifyReply) { async remove(request: FastifyRequest<{ Params: IdParams }>, reply: FastifyReply) {
const userId = (request as any).user?.sub as string; const userId = request.userContext!.userId;
const costId = request.params.id; const costId = request.params.id;
logger.info('Ownership cost delete requested', { logger.info('Ownership cost delete requested', {

View File

@@ -47,7 +47,7 @@ export class CommunityStationsController {
reply: FastifyReply reply: FastifyReply
): Promise<void> { ): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
// Validate request body // Validate request body
const validation = submitCommunityStationSchema.safeParse(request.body); const validation = submitCommunityStationSchema.safeParse(request.body);
@@ -62,7 +62,7 @@ export class CommunityStationsController {
return reply.code(201).send(station); return reply.code(201).send(station);
} catch (error: any) { } catch (error: any) {
logger.error('Error submitting station', { error, userId: (request as any).user?.sub }); logger.error('Error submitting station', { error, userId: request.userContext?.userId });
return reply.code(500).send({ return reply.code(500).send({
error: 'Internal server error', error: 'Internal server error',
message: 'Failed to submit station' message: 'Failed to submit station'
@@ -79,7 +79,7 @@ export class CommunityStationsController {
reply: FastifyReply reply: FastifyReply
): Promise<void> { ): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
// Validate query params // Validate query params
const validation = paginationSchema.safeParse(request.query); const validation = paginationSchema.safeParse(request.query);
@@ -94,7 +94,7 @@ export class CommunityStationsController {
return reply.code(200).send(result); return reply.code(200).send(result);
} catch (error: any) { } catch (error: any) {
logger.error('Error getting user submissions', { error, userId: (request as any).user?.sub }); logger.error('Error getting user submissions', { error, userId: request.userContext?.userId });
return reply.code(500).send({ return reply.code(500).send({
error: 'Internal server error', error: 'Internal server error',
message: 'Failed to retrieve submissions' message: 'Failed to retrieve submissions'
@@ -111,7 +111,7 @@ export class CommunityStationsController {
reply: FastifyReply reply: FastifyReply
): Promise<void> { ): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
// Validate params // Validate params
const validation = stationIdSchema.safeParse(request.params); const validation = stationIdSchema.safeParse(request.params);
@@ -128,7 +128,7 @@ export class CommunityStationsController {
} catch (error: any) { } catch (error: any) {
logger.error('Error withdrawing submission', { logger.error('Error withdrawing submission', {
error, error,
userId: (request as any).user?.sub, userId: request.userContext?.userId,
stationId: request.params.id stationId: request.params.id
}); });
@@ -252,7 +252,7 @@ export class CommunityStationsController {
reply: FastifyReply reply: FastifyReply
): Promise<void> { ): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
// Validate params // Validate params
const paramsValidation = stationIdSchema.safeParse(request.params); const paramsValidation = stationIdSchema.safeParse(request.params);
@@ -280,7 +280,7 @@ export class CommunityStationsController {
return reply.code(200).send(result); return reply.code(200).send(result);
} catch (error: any) { } catch (error: any) {
logger.error('Error reporting removal', { error, userId: (request as any).user?.sub }); logger.error('Error reporting removal', { error, userId: request.userContext?.userId });
if (error.message.includes('not found')) { if (error.message.includes('not found')) {
return reply.code(404).send({ return reply.code(404).send({
@@ -379,7 +379,7 @@ export class CommunityStationsController {
reply: FastifyReply reply: FastifyReply
): Promise<void> { ): Promise<void> {
try { try {
const adminId = (request as any).user.sub; const adminId = request.userContext!.userId;
// Validate params // Validate params
const paramsValidation = stationIdSchema.safeParse(request.params); const paramsValidation = stationIdSchema.safeParse(request.params);
@@ -422,7 +422,7 @@ export class CommunityStationsController {
return reply.code(200).send(station); return reply.code(200).send(station);
} catch (error: any) { } catch (error: any) {
logger.error('Error reviewing station', { error, adminId: (request as any).user?.sub }); logger.error('Error reviewing station', { error, adminId: request.userContext?.userId });
if (error.message.includes('not found')) { if (error.message.includes('not found')) {
return reply.code(404).send({ return reply.code(404).send({

View File

@@ -27,7 +27,7 @@ export class StationsController {
async searchStations(request: FastifyRequest<{ Body: StationSearchBody }>, reply: FastifyReply) { async searchStations(request: FastifyRequest<{ Body: StationSearchBody }>, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { latitude, longitude, radius, fuelType } = request.body; const { latitude, longitude, radius, fuelType } = request.body;
if (!latitude || !longitude) { if (!latitude || !longitude) {
@@ -46,7 +46,7 @@ export class StationsController {
return reply.code(200).send(result); return reply.code(200).send(result);
} catch (error: any) { } catch (error: any) {
logger.error('Error searching stations', { error, userId: (request as any).user?.sub }); logger.error('Error searching stations', { error, userId: request.userContext?.userId });
return reply.code(500).send({ return reply.code(500).send({
error: 'Internal server error', error: 'Internal server error',
message: 'Failed to search stations' message: 'Failed to search stations'
@@ -79,7 +79,7 @@ export class StationsController {
async saveStation(request: FastifyRequest<{ Body: SaveStationBody }>, reply: FastifyReply) { async saveStation(request: FastifyRequest<{ Body: SaveStationBody }>, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { const {
placeId, placeId,
nickname, nickname,
@@ -106,7 +106,7 @@ export class StationsController {
return reply.code(201).send(result); return reply.code(201).send(result);
} catch (error: any) { } catch (error: any) {
logger.error('Error saving station', { error, userId: (request as any).user?.sub }); logger.error('Error saving station', { error, userId: request.userContext?.userId });
if (error.message.includes('not found')) { if (error.message.includes('not found')) {
return reply.code(404).send({ return reply.code(404).send({
@@ -127,7 +127,7 @@ export class StationsController {
reply: FastifyReply reply: FastifyReply
) { ) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { placeId } = request.params; const { placeId } = request.params;
const result = await this.stationsService.updateSavedStation(placeId, userId, request.body); const result = await this.stationsService.updateSavedStation(placeId, userId, request.body);
@@ -137,7 +137,7 @@ export class StationsController {
logger.error('Error updating saved station', { logger.error('Error updating saved station', {
error, error,
placeId: request.params.placeId, placeId: request.params.placeId,
userId: (request as any).user?.sub userId: request.userContext?.userId
}); });
if (error.message.includes('not found')) { if (error.message.includes('not found')) {
@@ -156,12 +156,12 @@ export class StationsController {
async getSavedStations(request: FastifyRequest, reply: FastifyReply) { async getSavedStations(request: FastifyRequest, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const result = await this.stationsService.getUserSavedStations(userId); const result = await this.stationsService.getUserSavedStations(userId);
return reply.code(200).send(result); return reply.code(200).send(result);
} catch (error: any) { } catch (error: any) {
logger.error('Error getting saved stations', { error, userId: (request as any).user?.sub }); logger.error('Error getting saved stations', { error, userId: request.userContext?.userId });
return reply.code(500).send({ return reply.code(500).send({
error: 'Internal server error', error: 'Internal server error',
message: 'Failed to get saved stations' message: 'Failed to get saved stations'
@@ -171,14 +171,14 @@ export class StationsController {
async removeSavedStation(request: FastifyRequest<{ Params: StationParams }>, reply: FastifyReply) { async removeSavedStation(request: FastifyRequest<{ Params: StationParams }>, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { placeId } = request.params; const { placeId } = request.params;
await this.stationsService.removeSavedStation(placeId, userId); await this.stationsService.removeSavedStation(placeId, userId);
return reply.code(204).send(); return reply.code(204).send();
} catch (error: any) { } catch (error: any) {
logger.error('Error removing saved station', { error, placeId: request.params.placeId, userId: (request as any).user?.sub }); logger.error('Error removing saved station', { error, placeId: request.params.placeId, userId: request.userContext?.userId });
if (error.message.includes('not found')) { if (error.message.includes('not found')) {
return reply.code(404).send({ return reply.code(404).send({

View File

@@ -28,7 +28,7 @@ export class DonationsController {
*/ */
async createDonation(request: FastifyRequest, reply: FastifyReply) { async createDonation(request: FastifyRequest, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { amount } = request.body as CreateDonationBody; const { amount } = request.body as CreateDonationBody;
logger.info('Creating donation', { userId, amount }); logger.info('Creating donation', { userId, amount });
@@ -63,7 +63,7 @@ export class DonationsController {
*/ */
async getDonations(request: FastifyRequest, reply: FastifyReply) { async getDonations(request: FastifyRequest, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
logger.info('Getting donations', { userId }); logger.info('Getting donations', { userId });

View File

@@ -24,7 +24,7 @@ export class SubscriptionsController {
*/ */
async getSubscription(request: FastifyRequest, reply: FastifyReply): Promise<void> { async getSubscription(request: FastifyRequest, reply: FastifyReply): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const subscription = await this.service.getSubscription(userId); const subscription = await this.service.getSubscription(userId);
@@ -39,7 +39,7 @@ export class SubscriptionsController {
reply.status(200).send(subscription); reply.status(200).send(subscription);
} catch (error: any) { } catch (error: any) {
logger.error('Failed to get subscription', { logger.error('Failed to get subscription', {
userId: (request as any).user?.sub, userId: request.userContext?.userId,
error: error.message, error: error.message,
}); });
reply.status(500).send({ reply.status(500).send({
@@ -54,14 +54,14 @@ export class SubscriptionsController {
*/ */
async checkNeedsVehicleSelection(request: FastifyRequest, reply: FastifyReply): Promise<void> { async checkNeedsVehicleSelection(request: FastifyRequest, reply: FastifyReply): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const result = await this.service.checkNeedsVehicleSelection(userId); const result = await this.service.checkNeedsVehicleSelection(userId);
reply.status(200).send(result); reply.status(200).send(result);
} catch (error: any) { } catch (error: any) {
logger.error('Failed to check needs vehicle selection', { logger.error('Failed to check needs vehicle selection', {
userId: (request as any).user?.sub, userId: request.userContext?.userId,
error: error.message, error: error.message,
}); });
reply.status(500).send({ reply.status(500).send({
@@ -85,8 +85,8 @@ export class SubscriptionsController {
reply: FastifyReply reply: FastifyReply
): Promise<void> { ): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const email = (request as any).user.email; const email = request.userContext!.email || '';
const { tier, billingCycle, paymentMethodId } = request.body; const { tier, billingCycle, paymentMethodId } = request.body;
// Validate inputs // Validate inputs
@@ -141,7 +141,7 @@ export class SubscriptionsController {
reply.status(200).send(updatedSubscription); reply.status(200).send(updatedSubscription);
} catch (error: any) { } catch (error: any) {
logger.error('Failed to create checkout', { logger.error('Failed to create checkout', {
userId: (request as any).user?.sub, userId: request.userContext?.userId,
error: error.message, error: error.message,
}); });
reply.status(500).send({ reply.status(500).send({
@@ -156,14 +156,14 @@ export class SubscriptionsController {
*/ */
async cancelSubscription(request: FastifyRequest, reply: FastifyReply): Promise<void> { async cancelSubscription(request: FastifyRequest, reply: FastifyReply): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const subscription = await this.service.cancelSubscription(userId); const subscription = await this.service.cancelSubscription(userId);
reply.status(200).send(subscription); reply.status(200).send(subscription);
} catch (error: any) { } catch (error: any) {
logger.error('Failed to cancel subscription', { logger.error('Failed to cancel subscription', {
userId: (request as any).user?.sub, userId: request.userContext?.userId,
error: error.message, error: error.message,
}); });
reply.status(500).send({ reply.status(500).send({
@@ -178,14 +178,14 @@ export class SubscriptionsController {
*/ */
async reactivateSubscription(request: FastifyRequest, reply: FastifyReply): Promise<void> { async reactivateSubscription(request: FastifyRequest, reply: FastifyReply): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const subscription = await this.service.reactivateSubscription(userId); const subscription = await this.service.reactivateSubscription(userId);
reply.status(200).send(subscription); reply.status(200).send(subscription);
} catch (error: any) { } catch (error: any) {
logger.error('Failed to reactivate subscription', { logger.error('Failed to reactivate subscription', {
userId: (request as any).user?.sub, userId: request.userContext?.userId,
error: error.message, error: error.message,
}); });
reply.status(500).send({ reply.status(500).send({
@@ -207,8 +207,8 @@ export class SubscriptionsController {
reply: FastifyReply reply: FastifyReply
): Promise<void> { ): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const email = (request as any).user.email; const email = request.userContext!.email || '';
const { paymentMethodId } = request.body; const { paymentMethodId } = request.body;
// Validate input // Validate input
@@ -228,7 +228,7 @@ export class SubscriptionsController {
}); });
} catch (error: any) { } catch (error: any) {
logger.error('Failed to update payment method', { logger.error('Failed to update payment method', {
userId: (request as any).user?.sub, userId: request.userContext?.userId,
error: error.message, error: error.message,
}); });
reply.status(500).send({ reply.status(500).send({
@@ -243,14 +243,14 @@ export class SubscriptionsController {
*/ */
async getInvoices(request: FastifyRequest, reply: FastifyReply): Promise<void> { async getInvoices(request: FastifyRequest, reply: FastifyReply): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const invoices = await this.service.getInvoices(userId); const invoices = await this.service.getInvoices(userId);
reply.status(200).send(invoices); reply.status(200).send(invoices);
} catch (error: any) { } catch (error: any) {
logger.error('Failed to get invoices', { logger.error('Failed to get invoices', {
userId: (request as any).user?.sub, userId: request.userContext?.userId,
error: error.message, error: error.message,
}); });
reply.status(500).send({ reply.status(500).send({
@@ -273,7 +273,7 @@ export class SubscriptionsController {
reply: FastifyReply reply: FastifyReply
): Promise<void> { ): Promise<void> {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { targetTier, vehicleIdsToKeep } = request.body; const { targetTier, vehicleIdsToKeep } = request.body;
// Validate inputs // Validate inputs
@@ -311,7 +311,7 @@ export class SubscriptionsController {
reply.status(200).send(updatedSubscription); reply.status(200).send(updatedSubscription);
} catch (error: any) { } catch (error: any) {
logger.error('Failed to downgrade subscription', { logger.error('Failed to downgrade subscription', {
userId: (request as any).user?.sub, userId: request.userContext?.userId,
error: error.message, error: error.message,
}); });
reply.status(500).send({ reply.status(500).send({

View File

@@ -15,7 +15,7 @@ export class UserExportController {
} }
async downloadExport(request: FastifyRequest, reply: FastifyReply): Promise<void> { async downloadExport(request: FastifyRequest, reply: FastifyReply): Promise<void> {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
logger.info('User export requested', { userId }); logger.info('User export requested', { userId });

View File

@@ -24,7 +24,7 @@ export class UserImportController {
* Uploads and imports user data archive * Uploads and imports user data archive
*/ */
async uploadAndImport(request: FastifyRequest, reply: FastifyReply): Promise<void> { async uploadAndImport(request: FastifyRequest, reply: FastifyReply): Promise<void> {
const userId = request.user?.sub; const userId = request.userContext?.userId;
if (!userId) { if (!userId) {
return reply.code(401).send({ error: 'Unauthorized' }); return reply.code(401).send({ error: 'Unauthorized' });
} }
@@ -139,7 +139,7 @@ export class UserImportController {
* Generates preview of import data without executing import * Generates preview of import data without executing import
*/ */
async generatePreview(request: FastifyRequest, reply: FastifyReply): Promise<void> { async generatePreview(request: FastifyRequest, reply: FastifyReply): Promise<void> {
const userId = request.user?.sub; const userId = request.userContext?.userId;
if (!userId) { if (!userId) {
return reply.code(401).send({ error: 'Unauthorized' }); return reply.code(401).send({ error: 'Unauthorized' });
} }

View File

@@ -18,7 +18,7 @@ export class UserPreferencesController {
async getPreferences(request: FastifyRequest, reply: FastifyReply) { async getPreferences(request: FastifyRequest, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
let preferences = await this.repository.findByUserId(userId); let preferences = await this.repository.findByUserId(userId);
// Create default preferences if none exist // Create default preferences if none exist
@@ -42,7 +42,7 @@ export class UserPreferencesController {
updatedAt: preferences.updatedAt, updatedAt: preferences.updatedAt,
}); });
} catch (error) { } catch (error) {
logger.error('Error getting user preferences', { error, userId: (request as any).user?.sub }); logger.error('Error getting user preferences', { error, userId: request.userContext?.userId });
return reply.code(500).send({ return reply.code(500).send({
error: 'Internal server error', error: 'Internal server error',
message: 'Failed to get preferences', message: 'Failed to get preferences',
@@ -55,7 +55,7 @@ export class UserPreferencesController {
reply: FastifyReply reply: FastifyReply
) { ) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { unitSystem, currencyCode, timeZone, darkMode } = request.body; const { unitSystem, currencyCode, timeZone, darkMode } = request.body;
// Validate unitSystem if provided // Validate unitSystem if provided
@@ -115,7 +115,7 @@ export class UserPreferencesController {
updatedAt: preferences.updatedAt, updatedAt: preferences.updatedAt,
}); });
} catch (error) { } catch (error) {
logger.error('Error updating user preferences', { error, userId: (request as any).user?.sub }); logger.error('Error updating user preferences', { error, userId: request.userContext?.userId });
return reply.code(500).send({ return reply.code(500).send({
error: 'Internal server error', error: 'Internal server error',
message: 'Failed to update preferences', message: 'Failed to update preferences',

View File

@@ -27,7 +27,7 @@ export class VehiclesController {
async getUserVehicles(request: FastifyRequest, reply: FastifyReply) { async getUserVehicles(request: FastifyRequest, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
// Use tier-aware method to filter out locked vehicles after downgrade // Use tier-aware method to filter out locked vehicles after downgrade
const vehiclesWithStatus = await this.vehiclesService.getUserVehiclesWithTierStatus(userId); const vehiclesWithStatus = await this.vehiclesService.getUserVehiclesWithTierStatus(userId);
// Only return active vehicles (filter out locked ones) // Only return active vehicles (filter out locked ones)
@@ -37,7 +37,7 @@ export class VehiclesController {
return reply.code(200).send(vehicles); return reply.code(200).send(vehicles);
} catch (error) { } catch (error) {
logger.error('Error getting user vehicles', { error, userId: (request as any).user?.sub }); logger.error('Error getting user vehicles', { error, userId: request.userContext?.userId });
return reply.code(500).send({ return reply.code(500).send({
error: 'Internal server error', error: 'Internal server error',
message: 'Failed to get vehicles' message: 'Failed to get vehicles'
@@ -65,12 +65,12 @@ export class VehiclesController {
} }
} }
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const vehicle = await this.vehiclesService.createVehicle(request.body, userId); const vehicle = await this.vehiclesService.createVehicle(request.body, userId);
return reply.code(201).send(vehicle); return reply.code(201).send(vehicle);
} catch (error: any) { } catch (error: any) {
logger.error('Error creating vehicle', { error, userId: (request as any).user?.sub }); logger.error('Error creating vehicle', { error, userId: request.userContext?.userId });
if (error instanceof VehicleLimitExceededError) { if (error instanceof VehicleLimitExceededError) {
return reply.code(403).send({ return reply.code(403).send({
@@ -110,7 +110,7 @@ export class VehiclesController {
async getVehicle(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) { async getVehicle(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { id } = request.params; const { id } = request.params;
// Check tier status - block access to locked vehicles // Check tier status - block access to locked vehicles
@@ -131,7 +131,7 @@ export class VehiclesController {
return reply.code(200).send(vehicle); return reply.code(200).send(vehicle);
} catch (error: any) { } catch (error: any) {
logger.error('Error getting vehicle', { error, vehicleId: request.params.id, userId: (request as any).user?.sub }); logger.error('Error getting vehicle', { error, vehicleId: request.params.id, userId: request.userContext?.userId });
if (error.message === 'Vehicle not found' || error.message === 'Unauthorized') { if (error.message === 'Vehicle not found' || error.message === 'Unauthorized') {
return reply.code(404).send({ return reply.code(404).send({
@@ -149,14 +149,14 @@ export class VehiclesController {
async updateVehicle(request: FastifyRequest<{ Params: VehicleParams; Body: UpdateVehicleBody }>, reply: FastifyReply) { async updateVehicle(request: FastifyRequest<{ Params: VehicleParams; Body: UpdateVehicleBody }>, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { id } = request.params; const { id } = request.params;
const vehicle = await this.vehiclesService.updateVehicle(id, request.body, userId); const vehicle = await this.vehiclesService.updateVehicle(id, request.body, userId);
return reply.code(200).send(vehicle); return reply.code(200).send(vehicle);
} catch (error: any) { } catch (error: any) {
logger.error('Error updating vehicle', { error, vehicleId: request.params.id, userId: (request as any).user?.sub }); logger.error('Error updating vehicle', { error, vehicleId: request.params.id, userId: request.userContext?.userId });
if (error.message === 'Vehicle not found' || error.message === 'Unauthorized') { if (error.message === 'Vehicle not found' || error.message === 'Unauthorized') {
return reply.code(404).send({ return reply.code(404).send({
@@ -183,14 +183,14 @@ export class VehiclesController {
async deleteVehicle(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) { async deleteVehicle(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { id } = request.params; const { id } = request.params;
await this.vehiclesService.deleteVehicle(id, userId); await this.vehiclesService.deleteVehicle(id, userId);
return reply.code(204).send(); return reply.code(204).send();
} catch (error: any) { } catch (error: any) {
logger.error('Error deleting vehicle', { error, vehicleId: request.params.id, userId: (request as any).user?.sub }); logger.error('Error deleting vehicle', { error, vehicleId: request.params.id, userId: request.userContext?.userId });
if (error.message === 'Vehicle not found' || error.message === 'Unauthorized') { if (error.message === 'Vehicle not found' || error.message === 'Unauthorized') {
return reply.code(404).send({ return reply.code(404).send({
@@ -208,13 +208,13 @@ export class VehiclesController {
async getTCO(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) { async getTCO(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) {
try { try {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const { id } = request.params; const { id } = request.params;
const tco = await this.vehiclesService.getTCO(id, userId); const tco = await this.vehiclesService.getTCO(id, userId);
return reply.code(200).send(tco); return reply.code(200).send(tco);
} catch (error: any) { } catch (error: any) {
logger.error('Error getting vehicle TCO', { error, vehicleId: request.params.id, userId: (request as any).user?.sub }); logger.error('Error getting vehicle TCO', { error, vehicleId: request.params.id, userId: request.userContext?.userId });
if (error.statusCode === 404 || error.message === 'Vehicle not found') { if (error.statusCode === 404 || error.message === 'Vehicle not found') {
return reply.code(404).send({ return reply.code(404).send({
@@ -383,7 +383,7 @@ export class VehiclesController {
* Requires Pro or Enterprise tier * Requires Pro or Enterprise tier
*/ */
async decodeVin(request: FastifyRequest<{ Body: DecodeVinRequest }>, reply: FastifyReply) { async decodeVin(request: FastifyRequest<{ Body: DecodeVinRequest }>, reply: FastifyReply) {
const userId = (request as any).user?.sub; const userId = request.userContext?.userId;
try { try {
const { vin } = request.body; const { vin } = request.body;
@@ -447,7 +447,7 @@ export class VehiclesController {
} }
async uploadImage(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) { async uploadImage(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const vehicleId = request.params.id; const vehicleId = request.params.id;
logger.info('Vehicle image upload requested', { logger.info('Vehicle image upload requested', {
@@ -604,7 +604,7 @@ export class VehiclesController {
} }
async downloadImage(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) { async downloadImage(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const vehicleId = request.params.id; const vehicleId = request.params.id;
logger.info('Vehicle image download requested', { logger.info('Vehicle image download requested', {
@@ -654,7 +654,7 @@ export class VehiclesController {
} }
async deleteImage(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) { async deleteImage(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) {
const userId = (request as any).user.sub; const userId = request.userContext!.userId;
const vehicleId = request.params.id; const vehicleId = request.params.id;
logger.info('Vehicle image delete requested', { logger.info('Vehicle image delete requested', {