Painel
Dashboard
Próximos eventos
Atividades recentes
Agenda
Eventos
| Evento | Tipo | Data | Local | Inscritos | Status |
|---|
Base
Participantes
| Nome | CPF | Contato | Cidade/UF | Status |
|---|
Relação participante + evento
Inscrições
| Número | Participante | Evento | Data | Tipo | Status |
|---|
Controle
Presença
| Participante | Inscrição | Check-in | Entrada | Check-out | Saída | Permanência | Status | Certificado |
|---|
Lei de incentivo à cultura
Frequência
Emissão e validação
Certificados
| Chave | Número | Participante | Evento | Carga | Consultas | Status |
|---|
Prestação de contas
Comprovação cultural
Formulário do site
Contatos
| Data | Contato | Mensagem | Status |
|---|
Auditoria
Logs
| Quando | Ação | Detalhe | Usuário |
|---|
Projeto
Configurações
Banco de dados
Só o administrador faz login. O site público lê eventos e certificados sem autenticação e grava apenas contatos e consultas.
Regras do Realtime Database
{
"rules": {
"odp": {
"events": { ".read": true, ".write": "auth != null" },
"certificates": { ".read": true, ".write": "auth != null" },
"settings": { ".read": true, ".write": "auth != null" },
"adminMeta": {
".read": true,
"created": { ".write": "auth != null && !data.exists()" }
},
"participants": {
".read": "auth != null", ".write": "auth != null",
"$pid": {
"cpf": { ".write": "auth != null || newData.val() == data.val()" },
"email": { ".write": "auth != null || newData.parent().child('cpf').val() == data.parent().child('cpf').val()" },
"whats": { ".write": "auth != null || newData.parent().child('cpf').val() == data.parent().child('cpf').val()" }
}
},
"registrations": { ".read": "auth != null", ".write": "auth != null" },
"attendance": { ".read": "auth != null", ".write": "auth != null" },
"evidence": { ".read": "auth != null", ".write": "auth != null" },
"auditLogs": { ".read": "auth != null", ".write": "auth != null" },
"contacts": { ".read": "auth != null",
"$id": { ".write": "!data.exists()" } },
"consultas": { ".read": "auth != null",
"$id": { ".write": "!data.exists()" } },
"regRequests": { ".read": "auth != null", ".write": "auth != null",
"$id": { ".write": "!data.exists()" } },
"certsByCpf": {
"$cpf": { ".read": true, ".write": "auth != null",
"status": { ".write": true }
}
}
}
}
}
O nó adminMeta/created controla o primeiro acesso: enquanto estiver vazio, a tela de login mostra "criar conta administradora"; a regra !data.exists() permite gravá-lo uma única vez, e só por quem acabou de se autenticar — depois disso o cadastro fecha sozinho. Dados pessoais de participantes, inscrições e presença ficam fechados: só quem está autenticado lê. Em contacts e consultas, a mesma regra !data.exists() permite criar um registro novo, mas nunca ler, alterar ou apagar os que já existem. Em regRequests (pedidos de inscrição feitos pelo formulário público de eventos) a mesma regra !data.exists() libera a criação sem login, mas quem está autenticado (o admin) também pode ler, atualizar e apagar — é assim que a tela de Inscrições consegue aprovar ou recusar um pedido. Em certsByCpf a leitura só é liberada por CPF específico ($cpf) — dá para ler quem já sabe o CPF, mas não listar o nó inteiro; a escrita continua exigindo login, feita automaticamente ao emitir um certificado (exceto status, o sinalizador de cadastro completo, que qualquer um pode gravar sabendo o CPF). Em participants/$pid, e-mail e WhatsApp também podem ser gravados sem login — mas só numa escrita que reenvie, junto, o CPF exatamente igual ao que já está salvo naquele registro: isso é o que garante que só quem já sabe o CPF certo da pessoa consegue completar e-mail/WhatsApp dela pela consulta pública, e nunca alterar nome, status ou qualquer outro campo. Nome, CPF (para criar/alterar) e todo o resto continuam fechados para quem não está logado.