Skip to content

Painel Administrativo

O painel administrativo do CSGOFlip oferece controle completo sobre a plataforma, com dashboards, gestão de conteúdo, moderação e relatórios.

Visão Geral

Stack do Admin Dashboard

TecnologiaUso
Next.js 16Framework
shadcn/uiComponentes
React QueryData fetching
ZustandState management
RechartsGráficos
TanStack TableTabelas

Seções

Autenticação Admin

Níveis de Acesso

typescript
enum AdminRole {
  SUPER_ADMIN = 'SUPER_ADMIN',   // Acesso total
  ADMIN = 'ADMIN',               // Gestão geral
  MODERATOR = 'MODERATOR',       // Moderação de usuários
  SUPPORT = 'SUPPORT',           // Apenas visualização
  FINANCIAL = 'FINANCIAL',       // Transações e saques
}

Permissões por Módulo

MóduloSuper AdminAdminModeratorSupportFinancial
Dashboard
Usuários (view)
Usuários (edit)
Usuários (ban)
Caixas (CRUD)
Itens (CRUD)
Transações
Saques (aprovar)
Configurações
Logs de Auditoria

Guard de Autorização

typescript
// admin-auth.guard.ts
@Injectable()
export class AdminAuthGuard implements CanActivate {
  constructor(
    private reflector: Reflector,
    private sessionService: SessionService,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    
    // 1. Validar sessão
    const sessionId = this.extractSessionId(request);
    if (!sessionId) {
      throw new UnauthorizedException('Session required');
    }
    
    const session = await this.sessionService.validate(sessionId);
    if (!session) {
      throw new UnauthorizedException('Invalid session');
    }
    
    // 2. Verificar se é admin
    const user = await this.userService.findById(session.userId);
    if (!user.isAdmin) {
      throw new ForbiddenException('Admin access required');
    }
    
    // 3. Verificar permissão específica
    const requiredRoles = this.reflector.get<AdminRole[]>(
      'adminRoles',
      context.getHandler(),
    );
    
    if (requiredRoles && !requiredRoles.includes(user.adminRole)) {
      throw new ForbiddenException('Insufficient permissions');
    }
    
    // 4. Anexar user ao request
    request.admin = user;
    
    return true;
  }
}

Decorator de Roles

typescript
// admin-roles.decorator.ts
export const AdminRoles = (...roles: AdminRole[]) =>
  SetMetadata('adminRoles', roles);

// Uso no controller
@Post('users/:id/ban')
@AdminRoles(AdminRole.SUPER_ADMIN, AdminRole.ADMIN, AdminRole.MODERATOR)
async banUser(@Param('id') id: string): Promise<void> {
  // ...
}

Estrutura do Frontend Admin

next-shadcn-admin-dashboard/
├── app/
│   ├── (auth)/
│   │   └── login/
│   │       └── page.tsx
│   ├── (dashboard)/
│   │   ├── layout.tsx
│   │   ├── page.tsx               # Dashboard
│   │   ├── users/
│   │   │   ├── page.tsx           # Lista de usuários
│   │   │   └── [id]/
│   │   │       └── page.tsx       # Detalhes do usuário
│   │   ├── cases/
│   │   │   ├── page.tsx           # Lista de caixas
│   │   │   ├── new/
│   │   │   │   └── page.tsx       # Criar caixa
│   │   │   └── [id]/
│   │   │       └── page.tsx       # Editar caixa
│   │   ├── items/
│   │   │   └── page.tsx           # Lista de itens
│   │   ├── transactions/
│   │   │   └── page.tsx           # Transações
│   │   ├── withdrawals/
│   │   │   └── page.tsx           # Fila de saques
│   │   ├── deposits/
│   │   │   └── page.tsx           # Depósitos
│   │   ├── battles/
│   │   │   └── page.tsx           # Batalhas
│   │   └── settings/
│   │       └── page.tsx           # Configurações
│   └── api/
│       └── [...proxy]/            # Proxy para backend
├── components/
│   ├── ui/                        # shadcn components
│   ├── layout/
│   │   ├── sidebar.tsx
│   │   ├── header.tsx
│   │   └── breadcrumb.tsx
│   ├── dashboard/
│   │   ├── stats-cards.tsx
│   │   ├── revenue-chart.tsx
│   │   └── recent-activity.tsx
│   └── data-tables/
│       ├── users-table.tsx
│       ├── cases-table.tsx
│       └── withdrawals-table.tsx
├── lib/
│   ├── api.ts                     # API client
│   └── utils.ts
├── hooks/
│   ├── use-admin-auth.ts
│   └── use-data-table.ts
└── stores/
    └── admin-store.ts             # Zustand store

API Admin

Base URL

/api/admin/*

Endpoints Principais

MétodoEndpointDescrição
GET/dashboardEstatísticas gerais
GET/dashboard/revenue-chartDados do gráfico de receita
GET/dashboard/recent-activityAtividades recentes
GET/usersListar usuários
GET/users/:idDetalhes do usuário
POST/users/:id/banBanir usuário
POST/users/:id/unbanDesbanir usuário
GET/casesListar caixas
POST/casesCriar caixa
PUT/cases/:idAtualizar caixa
DELETE/cases/:idDeletar caixa
GET/itemsListar itens
POST/itemsCriar item
GET/transactionsListar transações
GET/withdrawalsListar saques
POST/withdrawals/:id/approveAprovar saque
POST/withdrawals/:id/rejectRejeitar saque
GET/depositsListar depósitos
POST/deposits/:id/confirmConfirmar depósito
GET/battlesListar batalhas
POST/battles/:id/cancelCancelar batalha

Auditoria

Todas as ações administrativas são registradas:

typescript
interface AdminAuditLog {
  id: bigint;
  adminId: bigint;
  action: AdminAction;
  resourceType: string;
  resourceId: bigint;
  previousValue?: Record<string, any>;
  newValue?: Record<string, any>;
  ipAddress: string;
  userAgent: string;
  createdAt: Date;
}

enum AdminAction {
  USER_BANNED = 'USER_BANNED',
  USER_UNBANNED = 'USER_UNBANNED',
  USER_BALANCE_ADJUSTED = 'USER_BALANCE_ADJUSTED',
  CASE_CREATED = 'CASE_CREATED',
  CASE_UPDATED = 'CASE_UPDATED',
  CASE_DELETED = 'CASE_DELETED',
  ITEM_CREATED = 'ITEM_CREATED',
  ITEM_UPDATED = 'ITEM_UPDATED',
  ITEM_DELETED = 'ITEM_DELETED',
  WITHDRAWAL_APPROVED = 'WITHDRAWAL_APPROVED',
  WITHDRAWAL_REJECTED = 'WITHDRAWAL_REJECTED',
  DEPOSIT_CONFIRMED = 'DEPOSIT_CONFIRMED',
  DEPOSIT_REJECTED = 'DEPOSIT_REJECTED',
  BATTLE_CANCELLED = 'BATTLE_CANCELLED',
  SETTINGS_UPDATED = 'SETTINGS_UPDATED',
}

Segurança

Rate Limiting Admin

typescript
// admin-throttler.config.ts
export const ADMIN_THROTTLE_CONFIG = {
  // Limites mais generosos para admin
  ttl: 60,              // 1 minuto
  limit: 100,           // 100 requests/min
  
  // Limites específicos por ação
  actions: {
    ban: { ttl: 60, limit: 10 },
    approve_withdrawal: { ttl: 60, limit: 20 },
    delete: { ttl: 60, limit: 5 },
  },
};

2FA Obrigatório

Admins devem ter 2FA ativado:

typescript
// admin-2fa.guard.ts
@Injectable()
export class Admin2FAGuard implements CanActivate {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    const admin = request.admin;
    
    if (!admin.twoFactorEnabled) {
      throw new ForbiddenException(
        'Two-factor authentication is required for admin access',
      );
    }
    
    return true;
  }
}

IP Whitelist (Opcional)

typescript
// admin-ip.guard.ts
@Injectable()
export class AdminIPGuard implements CanActivate {
  private readonly allowedIPs = process.env.ADMIN_ALLOWED_IPS?.split(',') || [];
  
  canActivate(context: ExecutionContext): boolean {
    if (this.allowedIPs.length === 0) {
      return true; // Whitelist desabilitado
    }
    
    const request = context.switchToHttp().getRequest();
    const clientIP = getClientIP(request);
    
    if (!this.allowedIPs.includes(clientIP)) {
      throw new ForbiddenException('IP not allowed');
    }
    
    return true;
  }
}

Documentação Técnica CSGOFlip