feat: inicializar repositorio oficial do clube67.com
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import { db } from '../config/database';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { auditLog } from '../utils/audit';
|
||||
|
||||
export class UserLifecycleService {
|
||||
|
||||
/**
|
||||
* Soft Deletes a user (Anonymization)
|
||||
* This process is irreversible and designed to comply with LGPD/GDPR
|
||||
*/
|
||||
static async anonymizeUser(userId: number, adminId: number): Promise<boolean> {
|
||||
return await db.transaction(async (trx) => {
|
||||
// 1. Get User
|
||||
const user = await trx('users').where({ id: userId }).first();
|
||||
if (!user) throw new Error('Usuário não encontrado');
|
||||
|
||||
if (user.role === 'partner' || user.role === 'partner_admin') {
|
||||
const partner = await trx('partners').where({ owner_user_id: user.id }).first();
|
||||
if (partner && partner.status === 'active') {
|
||||
throw new Error('Não é possível excluir um parceiro ativo. Desative o parceiro primeiro.');
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Anonymize User Data
|
||||
const anonEmail = `deleted_${uuidv4()}@clube67.com`;
|
||||
const randomHash = await import('bcryptjs').then(b => b.hash(uuidv4(), 10));
|
||||
|
||||
// Backup Leads info before scrubbing user (optional, if we want to keep name in leads table static)
|
||||
// But actually we want to anonymize leads too to remove PII
|
||||
|
||||
// 3. Update Leads (Keep stats, remove PII)
|
||||
await trx('leads')
|
||||
.where({ user_id: userId })
|
||||
.update({
|
||||
name: `Usuário Excluído ${userId}`,
|
||||
email: anonEmail,
|
||||
phone: null,
|
||||
updated_at: new Date()
|
||||
});
|
||||
|
||||
// 4. Delete Favorites
|
||||
await trx('favorites').where({ user_id: userId }).delete();
|
||||
|
||||
// 5. Update User Record
|
||||
await trx('users')
|
||||
.where({ id: userId })
|
||||
.update({
|
||||
name: `Usuário Excluído ${userId}`,
|
||||
email: anonEmail,
|
||||
password_hash: randomHash,
|
||||
whatsapp: null,
|
||||
// cpf: null, // if exists
|
||||
status: 'banned', // Prevent login logic
|
||||
deleted_at: new Date(),
|
||||
is_anonymized: true,
|
||||
updated_at: new Date()
|
||||
});
|
||||
|
||||
// 6. Log
|
||||
// Audit log needs to happen AFTER transaction or be part of it,
|
||||
// but our auditLog util might use a different connection or be simple.
|
||||
// We'll log it separately.
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Ban/Block User
|
||||
*/
|
||||
static async banUser(userId: number, reason: string, adminId: number): Promise<void> {
|
||||
await db('users').where({ id: userId }).update({
|
||||
status: 'banned',
|
||||
updated_at: new Date()
|
||||
});
|
||||
await auditLog(adminId, 'BAN_USER', 'user', userId, `Usuário banido: ${reason}`, '0.0.0.0');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Express } from 'express';
|
||||
import { logger } from '../utils/logger';
|
||||
|
||||
export const pluginService = {
|
||||
async loadPlugins(app: Express) {
|
||||
logger.info('Loading plugins...');
|
||||
// Implementation details...
|
||||
},
|
||||
async installPlugin(zipPath: string) { },
|
||||
async activatePlugin(slug: string) { },
|
||||
async deactivatePlugin(slug: string) { },
|
||||
async removePlugin(slug: string) { },
|
||||
};
|
||||
Reference in New Issue
Block a user