workspace/projects/gamilit/apps/backend/src/shared/guards/account-status.guard.ts
rckrdmrd 49155822ae fix: Resolve TypeScript compilation errors across all projects
Platform Marketing Content:
- Add PaginationParams, PaginationMeta, PaginatedResponse interfaces
- Fix JwtAuthGuard import paths (common/guards instead of modules/auth)
- Add missing fields to CRM interfaces (address, keywords, features, benefits)
- Install @nestjs/throttler dependency

ERP Suite - Construccion:
- Create tsconfig.node.json for web frontend
- Add vite-env.d.ts for Vite types
- Fix implicit return errors in Express controllers
- Prefix unused parameters with underscore

ERP Suite - ERP Core:
- Export PoolClient type from database config
- Fix invoice type comparison (customer/supplier vs out_invoice)
- Refactor base.service.ts query handling for proper type inference
- Rename Role type to RoleType to avoid conflict with entity
- Fix ProtectedRoute to use role?.name instead of roles array

ERP Suite - POS Micro:
- Add vite-env.d.ts for Vite types
- Fix Sale property names (discountAmount, changeAmount)
- Export TodaySummary interface from sales service

All projects now pass npm install and npm run build successfully.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 22:35:55 -06:00

101 lines
2.7 KiB
TypeScript

import {
Injectable,
CanActivate,
ExecutionContext,
ForbiddenException,
UnauthorizedException,
} from '@nestjs/common';
/**
* Account Status Guard
*
* Verifica que la cuenta del usuario esté activa
* Bloquea acceso a cuentas:
* - Inactivas
* - Suspendidas
* - Eliminadas (soft delete)
*/
@Injectable()
export class AccountStatusGuard implements CanActivate {
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const user = request.user;
// Si no hay usuario, dejar que AuthGuard lo maneje
if (!user) {
return true;
}
// Verificar status de la cuenta
const status = user.status || user.accountStatus;
if (!status) {
// Si no hay información de status, asumir que está activo
return true;
}
// Estados bloqueados
switch (status.toLowerCase()) {
case 'inactive':
case 'deactivated':
throw new ForbiddenException(
'Your account has been deactivated. Please contact support.',
);
case 'suspended': {
const suspensionDetails = user.suspensionDetails || {};
const { isPermanent, suspendedUntil, reason } = suspensionDetails;
if (isPermanent) {
throw new ForbiddenException(
`Your account has been permanently suspended. Reason: ${reason || 'Policy violation'}`,
);
}
if (suspendedUntil) {
const now = new Date();
const suspensionEnd = new Date(suspendedUntil);
if (now < suspensionEnd) {
throw new ForbiddenException(
`Your account is suspended until ${suspensionEnd.toLocaleDateString()}. Reason: ${reason || 'Policy violation'}`,
);
}
// Si la suspensión ya expiró, permitir acceso
// (idealmente debería actualizarse el status automáticamente)
} else {
throw new ForbiddenException(
`Your account has been suspended. Reason: ${reason || 'Policy violation'}`,
);
}
break;
}
case 'deleted':
case 'banned':
throw new ForbiddenException(
'Your account has been permanently banned. Please contact support.',
);
case 'pending_verification':
case 'pending':
throw new UnauthorizedException(
'Please verify your email before accessing this resource.',
);
case 'active':
case 'verified':
// Estados válidos, permitir acceso
return true;
default:
// Estado desconocido, denegar por seguridad
throw new ForbiddenException(
`Account status '${status}' is not recognized. Please contact support.`,
);
}
return true;
}
}