Cadastro de Usuário
Resumo
Módulo de registro público de novos usuários na comunidade. Inclui sanitização, validação campo a campo, reCAPTCHA v3, rate-limiting por IP e integração com BuddyPress Signups para ativação via e-mail. Suporta cadastro normal e cadastro via convite (indicação).
Fontes de evidência
theme/functions/registration/class-registration-handler.php— orquestrador principal (228 linhas)theme/functions/registration/class-registration-validator.php— todas as validações (~620 linhas)theme/functions/registration/class-registration-sanitizer.php— sanitização de dadostheme/functions/registration/class-registration-user-service.php— criação de usuário WP/BPtheme/functions/registration/ajax.php— endpoints AJAX (~280 linhas)theme/templates/cadastrar.php— template da página
Campos do formulário
| Campo | Obrigatório | Validação |
|---|---|---|
display_name | Sim | 3-100 chars, só letras/espaços/hífens |
bio | Não | Máx 500 chars |
username | Sim | 4-30 chars, [a-z0-9_-], não começa com número, não pode ser username proibido |
email | Sim | Formato válido, único no WP e na tabela signups do BP |
password | Sim | 8-128 chars, ao menos 1 letra + 1 número |
password_confirm | Sim | Deve ser idêntico a password |
institution_state_id | Sim* | CPT estados válido |
institution_city_id | Sim* | CPT cidades válido |
institution_hospital_id | Sim | BP Group válido e existente |
position | Sim | Da lista ACF ou "Outro" + texto livre |
position_other | Condicional | 2-100 chars (se position = "Outro") |
terms_accepted | Sim | Deve ser true |
recaptcha_response | Sim** | Google reCAPTCHA v3, score ≥ 0.5 |
* Não obrigatório quando cadastro via convite (indicação).
** Obrigatório somente se recaptcha_secret_key estiver configurado no ACF Options.
Evidência: class-registration-validator.php:37-67 — método validate().
Usernames proibidos
admin, administrator, administrador, administrativo, corregedoria,
diretor, diretoria, manager, editor, sistema, sys, sysadmin, system,
root, suporte, support, moderador, moderator
Evidência: class-registration-validator.php:16-20.
Cargos permitidos
Carregados dinamicamente via campo ACF jobtitles (Options page). Fallback hardcoded:
Médico(a), Enfermeiro(a), Técnico(a) de Enfermagem, Auxiliar de Enfermagem,
Fisioterapeuta, Farmacêutico(a), Nutricionista, Psicólogo(a),
Assistente Social, Administrador(a), Outro
Evidência: class-registration-validator.php — método get_allowed_positions().
Rate Limiting
- Limite: 5 tentativas por IP a cada 5 minutos.
- Mecanismo: WordPress transients com chave
hsl_reg_limit_{md5(IP)}. - Resposta: HTTP 429 com mensagem "Muitas tentativas. Aguarde alguns minutos."
Evidência: registration/ajax.php — função hsl_registration_check_rate_limit().
Proteção CSRF
- Ação do nonce:
hsl_registration_submit - Campo:
hsl_registration_nonce - Verificação via
wp_verify_nonce()antes de processar.
Evidência: class-registration-handler.php:30-31 — constantes NONCE_ACTION e NONCE_FIELD.
Endpoints AJAX
| Action | Método | Auth | Descrição |
|---|---|---|---|
hsl_registration_submit | POST | nopriv | Submissão do formulário completo |
hsl_registration_validate_field | POST | nopriv | Validação inline de campo individual |
hsl_registration_get_cities | GET | nopriv | Cidades por estado (state_id) |
hsl_registration_get_hospitals | GET | nopriv | Hospitais por cidade (city_id) |
hsl_registration_check_hospital_status | GET | nopriv | Verifica se hospital está em intervenção |
Evidência: registration/ajax.php:9-20.
Fluxo — Cadastro normal
sequenceDiagram
participant U as Usuário
participant JS as Frontend (registration.js)
participant WP as WordPress AJAX
participant BP as BuddyPress
participant Mail as wp_mail
U->>JS: Preenche formulário
JS->>WP: validate_field (inline, a cada blur)
WP-->>JS: {valid: true/false, message}
U->>JS: Clica "Cadastrar"
JS->>WP: POST hsl_registration_submit + nonce + reCAPTCHA
WP->>WP: Verifica nonce
WP->>WP: Rate limit check (5/5min)
WP->>WP: Sanitizer.sanitize()
WP->>WP: Validator.validate()
alt Validação falhou
WP-->>JS: {success:false, errors:{campo: msg}}
end
WP->>BP: bp_core_signup_user()
BP->>Mail: E-mail de ativação
WP-->>JS: {success:true, requires_activation:true}
JS-->>U: "Cadastro realizado! Verifique seu e-mail."
Fluxo — Cadastro via indicação
sequenceDiagram
participant U as Usuário convidado
participant WP as WordPress
participant IH as Indication_Handler
participant BP as BuddyPress
U->>WP: Acessa /cadastre-se/?invite_token=XXX
WP->>IH: validate_token(XXX)
IH-->>WP: {email, group_id, group_name, ...}
WP-->>U: Formulário pré-preenchido (email + hospital fixos)
U->>WP: POST hsl_registration_submit + invite_token
WP->>IH: validate_token() novamente
WP->>WP: Força email/hospital do convite (ignora form)
WP->>WP: Sanitizar + Validar (sem estado/cidade)
WP->>BP: Cria usuário
WP->>IH: process_invited_registration()
IH->>BP: Ativa conta automaticamente
IH->>BP: groups_join_group() — adiciona ao hospital
IH->>IH: mark_token_used()
WP-->>U: "Conta ativada! Já pode fazer login."
Hospital em intervenção
Quando o hospital selecionado está "em intervenção" (hospital_in_intervention group meta), a mensagem de sucesso muda:
"Após a ativação, sua entrada no grupo deste hospital deverá ser aprovada pelos administradores."
Evidência: class-registration-handler.php — método success_response().
Frontend
- Script:
assets/dist/project/js/registration.js - Dados localizados via
wp_localize_script('hsl-registration', 'hslRegistration', {...}):ajaxUrl,nonce,nonceField,messages
- Template:
templates/cadastrar.php
Evidência: registration/ajax.php — função hsl_registration_enqueue_assets().