API Reference: Autenticacao

Base URL: /api/auth

O modulo de autenticacao gerencia signup, login, aprovacao/rejeicao de membros, recuperacao de senha e refresh de tokens. Suporta multi-membership: um usuario pode pertencer a varios nucleos simultaneamente.


POST /api/auth/signup

Cadastra um novo usuario. Se o email/CPF ja existir em outro nucleo, cria apenas uma nova membership PENDENTE como convidado (is_nucleo_origem=false). Se for usuario novo, cria auth + usuario + membership como nucleo de origem (is_nucleo_origem=true).

Permissao

Publica (sem autenticacao)

Body

{
  "nome": "Joao da Silva",
  "email": "joao@email.com",
  "senha": "Senha123",
  "cpf": "123.456.789-00",
  "telefone": "(27) 99999-9999",
  "dataNascimento": "1990-05-15",
  "nucleoId": "uuid-do-nucleo",
  "endereco": {
    "cep": "29000-000",
    "rua": "Rua das Flores",
    "numero": "42",
    "complemento": "Apto 101",
    "bairro": "Centro",
    "cidade": "Vitoria",
    "estado": "ES"
  },
  "competencias": [
    { "microId": "uuid-da-competencia", "nivel": "AVANCADO" }
  ],
  "consentimentoLgpd": true,
  "codigoReferral": "MBL-ES-A1B2"
}

Validacoes (Zod via signupSchema)

  • nome: min 3 caracteres
  • email: formato valido
  • senha: min 8 chars, 1 maiuscula, 1 numero
  • cpf: formato 000.000.000-00
  • nucleoId: obrigatorio (UUID do nucleo)
  • consentimentoLgpd: deve ser true
  • competencias, codigoReferral: opcionais

Response 201 (usuario novo)

{
  "message": "Cadastro realizado com sucesso. Aguarde aprovacao.",
  "usuario": {
    "id": "uuid",
    "nome": "Joao da Silva",
    "email": "joao@email.com",
    "status": "PENDENTE",
    "codigoReferral": "MBL-ES-X7K2"
  }
}

Response 201 (usuario existente pedindo acesso a outro nucleo)

{
  "message": "Pedido de acesso enviado. Aguarde aprovacao deste nucleo.",
  "usuario": {
    "id": "uuid",
    "nome": "Joao da Silva",
    "email": "joao@email.com",
    "status": "PENDENTE",
    "codigoReferral": ""
  }
}

Erros

  • 400: Nucleo nao encontrado / Email ou CPF ja cadastrado com dados diferentes / Ja possui cadastro neste nucleo

Notas Multi-Membership

  • Cria linha em membros_nucleos com is_nucleo_origem=true para usuario novo
  • Cria linha com is_nucleo_origem=false para usuario existente pedindo acesso a outro nucleo
  • Plano Free e atribuido automaticamente apenas no nucleo de origem

POST /api/auth/login

Valida credenciais e retorna a lista de nucleos ativos do usuario para que o frontend permita a escolha. NAO retorna tokens (accessToken, refreshToken e expiresIn sao retornados como valores vazios/zero) — a sessao e gerenciada pelo browser via cookies do Supabase Auth.

Permissao

Publica (sem autenticacao)

Body

{
  "email": "joao@email.com",
  "senha": "Senha123"
}

Response 200

{
  "accessToken": "",
  "refreshToken": "",
  "expiresIn": 0,
  "usuario": {
    "id": "uuid",
    "nome": "Joao da Silva",
    "email": "joao@email.com",
    "cargo": "MEMBRO"
  },
  "nucleos": [
    {
      "id": "uuid-nucleo-1",
      "nome": "MBL Vitoria",
      "slug": "mbl-vitoria",
      "logoUrl": "https://...",
      "corPrimaria": "#5CBCAE",
      "cargo": "MEMBRO",
      "isNucleoOrigem": true,
      "isConvidado": false
    },
    {
      "id": "uuid-nucleo-2",
      "nome": "MBL Vila Velha",
      "slug": "mbl-vila-velha",
      "logoUrl": null,
      "corPrimaria": null,
      "cargo": "MEMBRO",
      "isNucleoOrigem": false,
      "isConvidado": true
    }
  ]
}

Erros

  • 401: Email ou senha invalidos
  • 403: Cadastro pendente em todos os nucleos / Conta suspensa / Cadastro rejeitado / Sem acesso a nenhum nucleo

Notas

  • SUPER_ADMIN recebe nucleos: [] (escolhe nucleo via dropdown global)
  • Apenas memberships com status ATIVO aparecem na lista de nucleos
  • O frontend deve usar nucleos[] para permitir seletor de nucleo ao usuario

GET /api/auth/me

Retorna perfil completo do usuario logado, incluindo competencias e plano.

Permissao

Autenticado (AuthGuard)

Header

Authorization: Bearer token

Response 200

{
  "id": "uuid",
  "nome": "Joao da Silva",
  "email": "joao@email.com",
  "cpf": "123.456.789-00",
  "telefone": "(27) 99999-9999",
  "data_nascimento": "1990-05-15",
  "endereco": { "cidade": "Vitoria", ... },
  "cargo": "MEMBRO",
  "status": "ATIVO",
  "saldo_capixacoins": 1500,
  "codigo_referral": "MBL-ES-X7K2",
  "foto_url": null,
  "primeiro_login": false,
  "receber_whatsapp": true,
  "criado_em": "2026-03-01T10:00:00Z",
  "planos": { "id": "uuid", "nome": "Free" },
  "usuario_competencias": [
    {
      "nivel_proficiencia": "AVANCADO",
      "competencias_micro": {
        "id": "uuid",
        "nome": "Edicao de Video",
        "competencias_macro": { "id": "uuid", "nome": "Digital" }
      }
    }
  ]
}

Erros

  • 404: Usuario nao encontrado

POST /api/auth/approve

Aprova a membership de um usuario num nucleo especifico. Funciona tanto para cadastros novos (nucleo de origem) quanto para pedidos de acesso de convidados de outros nucleos.

Permissao

COORDENADOR ou ADMINISTRADOR (AuthGuard + RolesGuard)

Body

{ "usuarioId": "uuid-do-usuario" }

O nucleoId e extraido automaticamente do token do usuario logado via @CurrentUser('nucleoId').

Response 200

{ "message": "Membership aprovada com sucesso" }

Side Effects

  • Membership atualizada para status ATIVO com aprovado_por e aprovado_em
  • Se for nucleo de origem e usuario.status=PENDENTE, atualiza usuarios.status para ATIVO
  • 100 CC creditadas ao referral (apenas se is_nucleo_origem=true e referral_id existir)
  • Entrada no feed: "Bem-vindo ao [nucleo]!" (origem) ou "[nome] foi aceito como convidado"
  • Notificacao para o usuario aprovado
  • Email de boas-vindas enviado via MailService/Resend (template aprovacao)

Erros

  • 400: nucleoId nao identificado / Membership nao esta pendente
  • 404: Membership nao encontrada para este usuario neste nucleo

POST /api/auth/reject

Rejeita a membership de um usuario num nucleo especifico. Se for o nucleo de origem, tambem marca usuarios.status como REJEITADO.

Permissao

COORDENADOR ou ADMINISTRADOR (AuthGuard + RolesGuard). Body validado com approveRejectSchema (Zod).

Body

{ "usuarioId": "uuid-do-usuario" }

O nucleoId e extraido automaticamente do token via @CurrentUser('nucleoId').

Response 200

{ "message": "Membership rejeitada" }

Side Effects

  • Membership atualizada para status REJEITADO
  • Se for nucleo de origem (is_nucleo_origem=true), tambem atualiza usuarios.status para REJEITADO
  • Email de rejeicao enviado via MailService/Resend (template rejeicao)

Erros

  • 400: nucleoId nao identificado / Membership nao esta pendente
  • 404: Membership nao encontrada para este usuario neste nucleo

POST /api/auth/refresh

Renova o access token usando o refresh token via Supabase Auth (anon client).

Permissao

Publica (sem autenticacao)

Body

{ "refreshToken": "xxx" }

Response 200

{
  "accessToken": "eyJhbGci...",
  "refreshToken": "novo-refresh",
  "expiresIn": 3600
}

Erros

  • 401: Refresh token invalido

POST /api/auth/forgot-password

Envia email de recuperacao de senha. Usa admin.generateLink(type: 'recovery')para gerar o token_hash e envia via MailService/Resend com template brandado (recuperacao_senha). NAO dispara o email nativo do Supabase.

Permissao

Publica (sem autenticacao)

Body

{ "email": "joao@email.com" }

Response 200

{ "message": "Se o email estiver cadastrado, voce recebera um link de recuperacao." }

Notas de Seguranca

  • Retorna sempre a mesma mensagem, independentemente de o email existir ou nao
  • O link gerado aponta para {CORS_ORIGIN}/auth/reset-password?token_hash=...&type=recovery
  • O email usa o template recuperacao_senha com branding do nucleo do usuario
  • O link expira em 1 hora (definido pelo Supabase)

PATCH /api/auth/dismiss-first-login

Marca primeiro_login como false na tabela usuarios. Usado apos o onboarding tour.

Permissao

Autenticado (AuthGuard)

Body

Nenhum (o userId e extraido do token).

Response 200

{ "message": "Primeiro login marcado como concluido" }

Cargos do Sistema

O campo cargo pode assumir os seguintes valores:

CargoDescricao
MEMBROUsuario base
LIDER_PROJETOLider de projeto
PORTA_VOZPermissoes de comunicacao (comunicados, enquetes, emails, tarefas, IA)
COORDENADORGerente do nucleo
ADMINISTRADORAcesso total ao nucleo
SUPER_ADMINAcesso irrestrito a todos os nucleos