Pular para o conteúdo principal

Change user status (Admin only)

POST 

/company/users/status/:id

Altera o estado de um usuário (ativar/desativar) através do campo status. Apenas administradores podem alterar o estado dos usuários.

Objetivo

Permitir que administradores controlem o acesso de usuários à plataforma por meio da ativação/desativação de contas.

Casos de Uso

  • Desativar um usuário temporariamente
  • Ativar um usuário que estava desativado
  • Suspender acesso por motivos de segurança
  • Bloquear usuário por falta de pagamento ou descumprimento

Autenticação & Autorização

  • Requer JWT válido (middleware m.isLoged)
  • Requer função admin ou dev (middleware m.isAdmin)

Comportamento

  • reason = NONE: Ativa usuário (status = true), limpa reason, reasonDate, reasonMessage
  • reason ≠ NONE: Desativa usuário (status = false), define reason e reasonMessage
  • Valida razão com model.isValidReason()
  • Atualiza reasonDate se for válida (formato ISO8601)

Razões Válidas

  • NONE: Usuário normal ativo sem incidentes (ativa usuário)
  • BAD_USER: Bloqueado por mau comportamento (relatos, fraude)
  • PENDING: Registro concluído, aguardando ativação
  • ACTIVE: Usuário verificado e operacional
  • BLOCKED: Bloqueado administrativamente (inadimplência, segurança)

Fluxo de Validação

flowchart TD
A[Receber POST /status/:id] --> B\{Usuário Admin?\}
B -->|Não| C[403 Forbidden]
B -->|Sim| D\{Usuário Existe?\}
D -->|Não| E[404 Not Found]
D -->|Sim| F\{Reason === 'NONE'?\}
F -->|Sim| G[Ativar Usuário]
G --> H[status = true]
H --> I[reason = NONE]
I --> J[Limpar reasonDate e reasonMessage]

<Heading
id={"request"}
as={"h2"}
className={"openapi-tabs__heading"}
children={"Request"}
>
</Heading>

<ParamsDetails
parameters={[{"name":"id","in":"path","required":true,"description":"ID do usuário para o qual o estado será alterado","schema":{"type":"string","pattern":"^[a-f0-9]{24}$","example":"63d7907cbe76403b35da63df"}}]}
>

</ParamsDetails>

<RequestSchema
title={"Body"}
body={{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","enum":["NONE","BAD_USER","PENDING","ACTIVE","BLOCKED"],"description":"Motivo da alteração de status. Se for NONE, o usuário é ativado.\nQualquer outro valor desativa o usuário.","example":"NONE"},"reasonDate":{"type":"string","format":"date-time","description":"Data/hora da alteração de estado (opcional). Se não for fornecida,\nutiliza-se a data atual. Formato ISO8601.","example":"2025-02-12T14:30:00.000Z","nullable":true},"reasonMessage":{"type":"string","maxLength":500,"description":"Mensagem explicativa da alteração de status (opcional).\nVisível para o usuário e administradores.","example":"Usuario bloqueado temporalmente por verificación de documentación","nullable":true}}},"example":{"reason":"NONE","reasonDate":"2025-02-12T14:30:00.000Z","reasonMessage":"Usuario reactivado tras completar verificación"}}}}}
>

</RequestSchema>

<StatusCodes
id={undefined}
label={undefined}
responses={{"200":{"description":"Estado do usuário alterado com sucesso.","content":{"application/json":{"schema":{"type":"object","description":"Representa um usuário de empresa (company_user) com acesso à plataforma Cargoffer.\n**Funcionalidade**: - Usuário empregado de uma empresa transportadora que gerencia leilões, entregas e documentação - Autenticação via JWT (tokens com expiração configurável conforme refresh_time) - Sistema de funções hierárquico: dev > admin > gestor (permissões descendentes) - Associado a uma empresa (company.users array contém referências a _id de usuários)\n**Modelo**: `src/features/models/company_user.model.js`\n**Controladores**: - `src/features/company/users/company_user.account.controller.js` (CRUD, senhas) - `src/features/company/users/company_user.profile.controller.js` (perfil, preferências) - `src/features/company/auth/auth.account.controller.js` (login, tokens)\n**Middleware**: `src/features/common/middleware/company.middleware.js` - `m.isLoged` - Verifica JWT válido - `m.isGestor` - Requer função 'gestor' ou superior - `m.isAdmin` - Requer função 'admin' ou 'dev'","properties":{"_id":{"type":"string","description":"Identificador único MongoDB do usuário (24 caracteres hexadecimais). Gerado automaticamente no registro. Referenciado em: company.users[], auction.user, delivery.user, notifications.user. Incluído no payload do JWT como claim '_id'.","pattern":"^[a-f0-9]{24}$","example":"63d7907cbe76403b35da63df"},"email":{"type":"string","format":"email","description":"E-mail único do usuário (usado para login). **Obrigatório** - Único na base de dados (índice unique em produção). Normalizado para letras minúsculas automaticamente (hook pre-save). Usado em: autenticação, recuperação de senha, notificações. Validado com formato de e-mail padrão.","example":"usuario@cargoffer.com"},"name":{"type":"string","description":"Nome do usuário (firstName em contexto internacional). Usado em: interface, assinatura de documentos CMR, identificação em notificações. Mínimo de 2 caracteres (validação no frontend).","minLength":2,"maxLength":50,"example":"Juan"},"lastname":{"type":"string","description":"Sobrenomes do usuário (lastName na API, lastname no modelo). Usado em conjunto com 'name' para identificação completa em documentos oficiais. Concatenado em: contratos, CMR, faturas.","minLength":2,"maxLength":100,"example":"García López"},"role":{"type":"string","enum":["dev","admin","gestor"],"description":"Papel do usuário que define permissões na plataforma. **dev**: Acesso total + depuração + gestão de todas as empresas (superadmin) **admin**: Gestão completa da sua empresa (criar usuários, ver faturamento, modificar dados) **gestor**: Operações diárias (criar leilões/entregas, ver painel, editar seu perfil)\n**Verificações de middleware**: - m.isGestor aceita: ['gestor', 'admin', 'dev'] - m.isAdmin aceita: ['admin', 'dev']\nArmazenado no payload JWT (usado na validação de permissões).","default":"gestor","example":"admin"},"status":{"type":"boolean","description":"Estado ativo/inativo do usuário. **true**: Usuário pode fazer login e operar normalmente. **false**: Usuário bloqueado (não pode fazer login, JWTs inválidos). \nUsado em: o middleware m.isLoged verifica status=true antes de permitir acesso. Alterado via: POST /company/users/status/:id (somente admin). Diferente de 'deleted' (exclusão lógica) – este é um bloqueio reversível.","default":true,"example":true},"reason":{"type":"string","enum":["NONE","BAD_USER","PENDING","ACTIVE","BLOCKED"],"description":"Código de razão do estado do usuário. **NONE**: Usuário normal ativo sem incidentes **PENDING**: Registro concluído, aguardando ativação por e-mail **ACTIVE**: Usuário verificado e operacional **BAD_USER**: Bloqueado por mau comportamento (denúncias, fraude) **BLOCKED**: Bloqueado administrativamente (inadimplência, segurança)\nUsado em conjunto com 'status' e 'reasonMessage' para auditoria. Armazenado com 'reasonDate' (timestamp da alteração).","default":"NONE","example":"ACTIVE"},"reasonMessage":{"type":"string","description":"Mensagem descritiva do motivo do bloqueio/estado atual. Opcional - Preenchido pelo administrador ao alterar o status para falso. Visível para: administradores no painel de usuários, usuário bloqueado na mensagem de erro de login. Exemplo: Conta suspensa por falta de pagamento, Usuário reportado por práticas inadequadas","example":"Usuario bloqueado temporalmente por verificación de documentación"},"reasonDate":{"type":"string","format":"date-time","description":"Timestamp de quando o campo 'reason' foi alterado pela última vez. Automático - Definido no hook pre-save ao detectar alteração em 'reason'. Usado em: auditoria, cálculo de tempo de bloqueio, históricos de alterações.","example":"2025-01-15T14:30:00.000Z"},"i18n":{"type":"string","enum":["es","en","fr","de"],"description":"Código de idioma preferido do usuário (internacionalização). **es**: Espanhol (padrão para Espanha) **en**: Inglês (padrão internacional)\nUsado em: emails automáticos, interface do usuário, mensagens de erro, documentos CMR. Armazenado no payload JWT para personalização a partir do backend. Alterado via: POST /company/users/lang","default":"es","example":"en"},"birthDate":{"type":"string","format":"date-time","description":"Data de nascimento do usuário (opcional). Usado em: validações de idade mínima (18 anos para motoristas), estatísticas demográficas. Formato ISO 8601. Anulável.","nullable":true,"example":"1990-05-15T00:00:00.000Z"},"emailVerified":{"type":"boolean","description":"Indica se o usuário verificou seu e-mail. **false**: Usuário registrado, mas não clicou no link de ativação **true**: E-mail confirmado através do token de ativação\nFluxo: registro → e-mail com token → GET /company/auth/activate/:token → emailVerified=true Usuários com emailVerified=false podem ter funcionalidades limitadas (depende da configuração).","default":false,"example":true},"emailVerifiedDate":{"type":"string","format":"date-time","description":"Timestamp de quando o email foi verificado (null se emailVerified=false). Definido automaticamente ao confirmar o token de ativação. Usado em: auditoria, calcular tempo desde a verificação, requisitos de re-verificação.","nullable":true,"example":"2025-01-10T09:20:30.000Z"},"phone":{"type":"string","description":"Número de telefone do usuário (opcional, mas recomendado). Formato: preferencialmente internacional (+código do país), mínimo 9 dígitos, máximo 15. Usado em: coordenação logística, alertas por SMS, contato de emergência. Validação: `minlength: 9, maxlength: 15` no modelo.","pattern":"^\\+?[0-9]{9,15}$","example":"+34612345678"},"lastSignInAt":{"type":"string","format":"date-time","description":"Carimbo de data/hora do último login bem-sucedido do usuário. Atualizado automaticamente no controlador de login (POST /company/auth/login). Usado em: painel de atividade, detecção de contas inativas, auditoria de segurança.","example":"2025-10-23T08:15:45.000Z"},"lastSignInIp":{"type":"string","description":"Endereço IP de onde o último login foi realizado. Extraído de req.ip ou req.headers['x-forwarded-for']. Usado em: detecção de acessos suspeitos, logs de segurança, geolocalização de acessos.","format":"ipv4","example":"192.168.1.100"},"country":{"type":"string","description":"Código de país ISO 3166-1 alpha-3 do usuário (3 letras minúsculas). Usado em: filtros de fuso horário, formatos de data, configuração regional, validações de TaxID. Padrão: esp (Espanha). Deve existir na collection 'countries'.","pattern":"^[a-z]{3}$","default":"esp","example":"esp"},"timezone":{"type":"string","description":"Fuso horário do usuário no formato IANA Time Zone Database. Usado em: conversão de timestamps UTC para local, exibição de datas, cálculo de horários de carga/descarga. Deve corresponder a zonas válidas da biblioteca moment-timezone. Padrão: Europe/Madrid.","default":"Europe/Madrid","example":"Europe/Madrid"},"taxid":{"type":"string","description":"Número de identificação fiscal pessoal (NIF, DNI, NIE, etc.). **Único em produção** (índice único). Mínimo de 6 caracteres, máximo de 9. Normalizado para maiúsculas automaticamente (uppercase: true no modelo). Usado em: faturação, contratos, documentação legal. Valor padrão temporário: '---------' (9 hífens) para permitir criação sem dado.","minLength":6,"maxLength":9,"example":"12345678A"},"img":{"type":"string","format":"uri","description":"URL da imagem de perfil do usuário (armazenada no AWS S3). Opcional - Enviada via endpoint de documentos com multerS3. Usado em: avatar na interface, assinatura visual em documentos. Formato: URL completa do bucket S3.","nullable":true,"example":"https://cargoffer-storage.s3.amazonaws.com/users/63d7907cbe76403b35da63df.jpg"},"recovery_token":{"type":"string","description":"Token temporário para recuperação de senha (hash). Gerado em: POST /company/auth/recovery (solicitação de reset) Usado em: GET /company/auth/recovery/:token (validar token) Limpo após: alteração bem-sucedida de senha ou expiração (48h) Padrão: '' (string vazia quando não há processo de recuperação ativo)","example":"a7f5e8d3c2b9..."},"refresh_time":{"type":"integer","enum":[1,3,5,10],"description":"Tempo de expiração do JWT em dias. Usado em: geração de token (exp claim = iat + refresh_time * 24h). **1**: Máxima segurança (re-login diário) - Para funções sensíveis **3**: Padrão equilíbrio segurança/conforto **5**: Uso frequente **10**: Aplicativos móveis com offline\nArmazenado no payload do JWT, validado no middleware m.isLoged.","default":3,"example":3},"is_bot":{"type":"boolean","description":"Indica se o usuário é um bot automatizado (para integrações de API). **true**: Usuário criado para integração automática (webhooks, scripts) **false**: Usuário humano real\nUsado em: estatísticas, auditoria, excluir bots de métricas de atividade humana. Bots podem ter permissões especiais e limites de taxa diferentes.","default":false,"example":false},"deleted":{"type":"boolean","description":"Flag de soft delete (plugin mongoose-delete). **false**: Usuário ativo **true**: Usuário excluído (não aparece em consultas normais)\nConsultas incluem deleted:false automaticamente (plugin overrideMethods:true). Recuperável via: POST /company/users/disabled/reactivate/:id Relacionado ao timestamp 'deletedAt'.","default":false,"example":false},"deletedAt":{"type":"string","format":"date-time","description":"Timestamp de quando o usuário foi excluído (soft delete). Nulo se deleted=false. Definido automaticamente pelo plugin mongoose-delete. Usado em: auditoria de exclusões, recuperação de usuários, conformidade GDPR.","nullable":true,"example":"2025-10-01T12:00:00.000Z"},"createdAt":{"type":"string","format":"date-time","description":"Timestamp de criação do usuário (automático por mongoose timestamps). Imutável - Não pode ser modificado após a criação. Usado em: ordenação, estatísticas de crescimento, auditoria.","example":"2024-12-01T10:30:00.000Z"},"updatedAt":{"type":"string","format":"date-time","description":"Timestamp da última modificação do usuário (automático por timestamps do mongoose). Atualizado em cada save() - Reflete a última edição de qualquer campo. Usado em: sincronização, invalidação de cache, detecção de alterações.","example":"2025-10-20T15:45:30.000Z"},"lastAccess":{"type":"string","format":"date-time","description":"Timestamp do último acesso registrado a qualquer endpoint autenticado. Atualizado por: middleware m.getAction em cada request autenticado. Diferente de lastSignInAt (este é atualizado em cada request, não apenas no login). Usado em: detecção de inatividade, métricas de engajamento.","example":"2025-10-23T10:22:15.000Z"}},"title":"User"},"example":{"_id":"63d7907cbe76403b35da63df","email":"usuario@empresa.com","name":"Juan","lastname":"Pérez García","status":true,"reason":"NONE","reasonDate":null,"reasonMessage":null,"updatedAt":"2025-02-12T14:30:00.000Z"}}}},"400":{"description":"Solicitação inválida. Possíveis causas:\n- Motivo inválido\n- Erro ao salvar","content":{"application/json":{"schema":{"type":"object","required":["status","message"],"properties":{"status":{"type":"integer","description":"Código de status HTTP","minimum":400,"maximum":599,"example":400},"message":{"type":"string","description":"Código de erro do sistema.\n\nCódigos de erro comuns (consulte listado_errores_http.txt para a lista completa):\n- NO_TOKEN (401): Token JWT não fornecido\n- TOKEN_NOT_VALID (401): Token JWT é inválido ou expirado\n- NO_ADMIN_ROLE (401): Usuário não possui privilégios de administrador\n- INVALID_PARAMETERS (400): Parâmetros da requisição são inválidos\n- NOT_FOUND (404): Recurso solicitado não encontrado\n- ALREADY_EXIST (401): Recurso com o mesmo identificador já existe\n- UTC_VALIDATION_FAILED (400): Falha na validação do timestamp UTC\n- INTERNAL_ERROR (500): Ocorreu um erro inesperado no servidor\n\nA mensagem é resolvida por `handlerError.getErrorMessage(error)`.","example":"INVALID_PARAMETERS"}},"description":"Formato padrão de resposta de erro utilizado em todos os endpoints da API.\n\nTodos os erros seguem o padrão `{status: number, message: string}`.\nO código de status é repetido tanto na resposta HTTP quanto no corpo da resposta.\n\nAs mensagens de erro são constantes definidas na base de código e devem ser\ntratadas no lado do cliente com mensagens apropriadas para o usuário final.","example":{"status":400,"message":"INVALID_PARAMETERS"},"title":"ErrorResponse"},"example":{"message":"FORM_DATA_NOT_VALID"}}}},"401":{"description":"Não autorizado (função de administrador ou desenvolvedor necessária)","content":{"application/json":{"schema":{"type":"object","required":["status","message"],"properties":{"status":{"type":"integer","description":"Código de status HTTP","minimum":400,"maximum":599,"example":400},"message":{"type":"string","description":"Código de erro do sistema.\n\nCódigos de erro comuns (consulte listado_errores_http.txt para a lista completa):\n- NO_TOKEN (401): Token JWT não fornecido\n- TOKEN_NOT_VALID (401): Token JWT é inválido ou expirado\n- NO_ADMIN_ROLE (401): Usuário não possui privilégios de administrador\n- INVALID_PARAMETERS (400): Parâmetros da requisição são inválidos\n- NOT_FOUND (404): Recurso solicitado não encontrado\n- ALREADY_EXIST (401): Recurso com o mesmo identificador já existe\n- UTC_VALIDATION_FAILED (400): Falha na validação do timestamp UTC\n- INTERNAL_ERROR (500): Ocorreu um erro inesperado no servidor\n\nA mensagem é resolvida por `handlerError.getErrorMessage(error)`.","example":"INVALID_PARAMETERS"}},"description":"Formato padrão de resposta de erro utilizado em todos os endpoints da API.\n\nTodos os erros seguem o padrão `{status: number, message: string}`.\nO código de status é repetido tanto na resposta HTTP quanto no corpo da resposta.\n\nAs mensagens de erro são constantes definidas na base de código e devem ser\ntratadas no lado do cliente com mensagens apropriadas para o usuário final.","example":{"status":400,"message":"INVALID_PARAMETERS"},"title":"ErrorResponse"},"example":{"message":"NO_TOKEN"}}}},"403":{"description":"Proibido (usuário não é administrador)","content":{"application/json":{"schema":{"type":"object","required":["status","message"],"properties":{"status":{"type":"integer","description":"Código de status HTTP","minimum":400,"maximum":599,"example":400},"message":{"type":"string","description":"Código de erro do sistema.\n\nCódigos de erro comuns (consulte listado_errores_http.txt para a lista completa):\n- NO_TOKEN (401): Token JWT não fornecido\n- TOKEN_NOT_VALID (401): Token JWT é inválido ou expirado\n- NO_ADMIN_ROLE (401): Usuário não possui privilégios de administrador\n- INVALID_PARAMETERS (400): Parâmetros da requisição são inválidos\n- NOT_FOUND (404): Recurso solicitado não encontrado\n- ALREADY_EXIST (401): Recurso com o mesmo identificador já existe\n- UTC_VALIDATION_FAILED (400): Falha na validação do timestamp UTC\n- INTERNAL_ERROR (500): Ocorreu um erro inesperado no servidor\n\nA mensagem é resolvida por `handlerError.getErrorMessage(error)`.","example":"INVALID_PARAMETERS"}},"description":"Formato padrão de resposta de erro utilizado em todos os endpoints da API.\n\nTodos os erros seguem o padrão `{status: number, message: string}`.\nO código de status é repetido tanto na resposta HTTP quanto no corpo da resposta.\n\nAs mensagens de erro são constantes definidas na base de código e devem ser\ntratadas no lado do cliente com mensagens apropriadas para o usuário final.","example":{"status":400,"message":"INVALID_PARAMETERS"},"title":"ErrorResponse"},"example":{"message":"USER_NOT_ALLOWED"}}}},"404":{"description":"Usuário não encontrado","content":{"application/json":{"schema":{"type":"object","required":["status","message"],"properties":{"status":{"type":"integer","description":"Código de status HTTP","minimum":400,"maximum":599,"example":400},"message":{"type":"string","description":"Código de erro do sistema.\n\nCódigos de erro comuns (consulte listado_errores_http.txt para a lista completa):\n- NO_TOKEN (401): Token JWT não fornecido\n- TOKEN_NOT_VALID (401): Token JWT é inválido ou expirado\n- NO_ADMIN_ROLE (401): Usuário não possui privilégios de administrador\n- INVALID_PARAMETERS (400): Parâmetros da requisição são inválidos\n- NOT_FOUND (404): Recurso solicitado não encontrado\n- ALREADY_EXIST (401): Recurso com o mesmo identificador já existe\n- UTC_VALIDATION_FAILED (400): Falha na validação do timestamp UTC\n- INTERNAL_ERROR (500): Ocorreu um erro inesperado no servidor\n\nA mensagem é resolvida por `handlerError.getErrorMessage(error)`.","example":"INVALID_PARAMETERS"}},"description":"Formato padrão de resposta de erro utilizado em todos os endpoints da API.\n\nTodos os erros seguem o padrão `{status: number, message: string}`.\nO código de status é repetido tanto na resposta HTTP quanto no corpo da resposta.\n\nAs mensagens de erro são constantes definidas na base de código e devem ser\ntratadas no lado do cliente com mensagens apropriadas para o usuário final.","example":{"status":400,"message":"INVALID_PARAMETERS"},"title":"ErrorResponse"},"example":{"message":"USER_NOT_FOUND"}}}}}}
>

</StatusCodes>