88 lines
2.3 KiB
TypeScript
88 lines
2.3 KiB
TypeScript
/**
|
|
* @ai-summary Account purge job for GDPR-compliant deletion
|
|
* @ai-context Processes user accounts past their 30-day grace period
|
|
*/
|
|
|
|
import { UserProfileRepository } from '../data/user-profile.repository';
|
|
import { pool } from '../../../core/config/database';
|
|
import { logger } from '../../../core/logging/logger';
|
|
import { auth0ManagementClient } from '../../../core/auth/auth0-management.client';
|
|
|
|
interface PurgeResult {
|
|
processed: number;
|
|
deleted: number;
|
|
errors: Array<{ auth0Sub: string; error: string }>;
|
|
}
|
|
|
|
/**
|
|
* Process account purges for users past the 30-day grace period
|
|
* This job runs daily at 2 AM
|
|
*/
|
|
export async function processAccountPurges(): Promise<PurgeResult> {
|
|
const repository = new UserProfileRepository(pool);
|
|
const result: PurgeResult = {
|
|
processed: 0,
|
|
deleted: 0,
|
|
errors: [],
|
|
};
|
|
|
|
try {
|
|
logger.info('Starting account purge job');
|
|
|
|
// Get users past grace period
|
|
const usersToPurge = await repository.getUsersPastGracePeriod();
|
|
|
|
logger.info('Found users to purge', { count: usersToPurge.length });
|
|
|
|
result.processed = usersToPurge.length;
|
|
|
|
// Process each user
|
|
for (const user of usersToPurge) {
|
|
try {
|
|
logger.info('Purging user account', {
|
|
auth0Sub: user.auth0Sub,
|
|
email: user.email,
|
|
deletionScheduledFor: user.deletionScheduledFor,
|
|
});
|
|
|
|
// Hard delete from database
|
|
await repository.hardDeleteUser(user.auth0Sub);
|
|
|
|
// Delete from Auth0
|
|
await auth0ManagementClient.deleteUser(user.auth0Sub);
|
|
|
|
result.deleted++;
|
|
|
|
logger.info('User account purged successfully', {
|
|
auth0Sub: user.auth0Sub,
|
|
email: user.email,
|
|
});
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
|
|
logger.error('Failed to purge user account', {
|
|
auth0Sub: user.auth0Sub,
|
|
email: user.email,
|
|
error: errorMessage,
|
|
});
|
|
|
|
result.errors.push({
|
|
auth0Sub: user.auth0Sub,
|
|
error: errorMessage,
|
|
});
|
|
}
|
|
}
|
|
|
|
logger.info('Account purge job completed', {
|
|
processed: result.processed,
|
|
deleted: result.deleted,
|
|
errors: result.errors.length,
|
|
});
|
|
|
|
return result;
|
|
} catch (error) {
|
|
logger.error('Account purge job failed', { error });
|
|
throw error;
|
|
}
|
|
}
|