Skip to content

Redefinir Senha de Usuário (Admin / root)

Status: mecanismo interino via CRUD genérico — não há endpoint dedicado. Funcional e com authz corrigida em 2026-05-18 (DEBT-057: customer_put deixou de dar 500 e ganhou guard de admin). Ver "Aviso de segurança".

Resumo

A troca de senha de outro usuário é feita pelo PUT genérico de atualização, enviando o campo password em texto plano. O backend gera o hash automaticamente (argon2 via passlib, validator password_hash nas entidades Admin/Customer) ao salvar. Não é necessário enviar a senha atual.

Alvo Endpoint Payload schema
Usuário admin (painel) PUT /api/v1/users AdminUpdate
Cliente (customer) PUT /api/v1/customers CustomerUpdate

Base URL: https://fdplay-api.infraifd.com

Pré-requisito de autorização

Pós DEBT-057, as rotas de cliente têm dupla trava: checagem users_type (em get_current_user) E guard de admin (_require_admin: exige user_type=='admin' no banco).

Acesso efetivo:

Sessão PUT /api/v1/customers (cliente) PUT /api/v1/users (admin)
root ✅ (recomendado)
Admin c/ perfil users-type incluindo customer_put / user_put e user_type=='admin'
Operador c/ perfil padrão Admin (ADR-061) HTTP 401 ❌ HTTP 401
Customer / não-admin ❌ 401/403 ❌ 401/403

Perfil Admin não basta

O perfil padrão Admin (ADR-061) não concede customer_put/user_put. Para esta tela, exija sessão root (caminho recomendado) ou um perfil customizado que conceda explicitamente a função e cujo portador seja user_type=='admin'.

Contrato da requisição

  • Método: PUT
  • Headers: Authorization: Bearer <token> + Content-Type: application/json
  • Identificação do alvo: query param ?_id=<OBJECT_ID> ou campo _id dentro do objeto.
  • Body: uma lista (array) de objetos. Enviar apenas password — a atualização é parcial (campos omitidos são preservados).
PUT /api/v1/users?_id=6a0a111650de0df77fde2a57
Authorization: Bearer <root_token>
Content-Type: application/json

[{ "password": "NovaSenhaSegura123" }]

Para cliente, troque a rota:

PUT /api/v1/customers?_id=<CUSTOMER_OID>

[{ "password": "NovaSenhaSegura123" }]

Regras que o front-end DEVE aplicar

  • Mínimo 8 caracteres. Validar no cliente antes de enviar (senha curta → HTTP 422).
  • Enviar somente password. Não reenviar username, email, name etc. no mesmo PUT.
    • Em customers, enviar email no PUT é bloqueado (HTTP 400 — ADR-033). Email muda por fluxo próprio.
  • Nunca exibir nem reutilizar o password da resposta. A resposta devolve o documento com password já como hash argon2. Reenviar esse hash num PUT futuro faz o backend tratá-lo como senha já criptografada (não re-hasheia). Tratar password como write-only.
  • Confirmação explícita na UI. O backend não exige senha atual e não registra auditoria. Compensar no front: diálogo de confirmação ("Redefinir senha de <nome>?") e log local de quem acionou.
  • Após sucesso, não manter a nova senha em memória/estado; limpar o campo.

Resposta de sucesso (200)

Retorna o(s) documento(s) atualizado(s) (formato GetDocsResponse200, lista em docs). O front-end só precisa confirmar status 200 e descartar o corpo (não renderizar password).

Tratamento de erros

HTTP Causa Ação no front-end
422 Senha < 8 chars Validar antes; erro de formulário
401 Sessão sem a permissão users_type (customer_put/user_put) "Sessão sem permissão. Use uma conta root."
403 _require_admin (não é admin/root) ou token inválido/expirado Forçar re-login / usar conta admin/root
400 (customers) email enviado junto no PUT Não enviar email; corrigir payload
500 _id inexistente / erro interno (controller encapsula exceções) Mensagem genérica; logar; revalidar o _id

Limitação conhecida

O 500 estrutural de customer_put (instanciava Admin para customer) foi corrigido em DEBT-057 (2026-05-18). Ainda assim, _id inexistente pode retornar 500 (não 404) — o controller genérico (ManageData) encapsula exceções. Garanta que o _id venha de um item realmente listado.

Exemplo (Dart / Dio)

Future<void> resetUserPassword({
  required String userId,
  required String newPassword,
  bool isCustomer = false,
}) async {
  assert(newPassword.length >= 8); // validar antes (evita 422)
  final path = isCustomer ? '/api/v1/customers' : '/api/v1/users';

  await dio.put(
    path,
    queryParameters: {'_id': userId},
    data: [
      {'password': newPassword}, // SOMENTE password; corpo é uma lista (array)
    ],
    options: Options(headers: {'Authorization': 'Bearer $rootToken'}),
  );
  // Sucesso: não armazenar/loggar newPassword; limpar o campo do form.
}

Aviso de segurança

Dívida de Governança

Este caminho não gera log de auditoria (diferente das ações ADMIN.CUSTOMER.*) e não exige a senha atual. É mecanismo interino via CRUD genérico, não endpoint projetado. Follow-up recomendado: endpoint dedicado auditado (POST /admin/customers/{id}/reset-password com reason, padrão ADR-048). Até lá, a rastreabilidade depende de o painel logar quem acionou e por quê.

Referências

  • ADR-061 — RBAC por nome-de-função + perfis padrão users-type
  • ADR-048 — Admin Customer Management (padrão de audit log)
  • ADR-033 — Re-verificação de email na alteração (bloqueio de email no PUT de customer)
  • ADR-057 — Serialização BSON-aware para insert/update