Uma permissão em nível de classe é uma regra no schema da classe que controla quais usuários ou papéis podem executar cada operação naquela classe. É o gate mais externo da segurança na camada de dados: antes de qualquer verificação por linha, a própria classe decide se este chamador pode consultar, criar, atualizar ou excluir ali — uma regra, a tabela inteira, verificada primeiro.
Principais pontos
| Pergunta | Resposta |
|---|---|
| O que é | Regras de acesso por operação na própria classe (tabela) |
| vs. ACLs | A CLP guarda a classe; ACLs guardam cada linha — a requisição passa pelos dois |
| As operações | Find, get, count, create, update, delete, add field — cada uma configurada à parte |
| Os defaults de ouro | Exigir autenticação, trancar o add field, jamais embarcar a master key |
| O primo em SQL | GRANT/REVOKE em tabelas e schemas — mesma ideia, outra sintaxe |
O gate da classe, declarado e sentido
Uma CLP é configuração de schema — aqui o payload REST que tranca uma classe Config em leitura pública e escrita só pelo servidor:
PUT /schemas/Config
{
"classLevelPermissions": {
"find": { "*": true }, // qualquer um pode consultar
"get": { "*": true },
"create": {}, // ninguém a partir do cliente
"update": { "role:admin": true }, // somente admins
"delete": {},
"addField": {} // schema congelado
}
}
O que os clientes experimentam é o gate fazendo seu trabalho — leituras fluem, escritas morrem na fronteira da classe antes de qualquer dado ser tocado:
// JavaScript / Node.js — Back4app JS SDK
// The class gate in action: Config is read-only for clients (CLP),
// so reads succeed and writes never reach the data
const config = await new Parse.Query('Config').first(); // ✓ public read
const c = new Parse.Object('Config');
c.set('flag', true);
try {
await c.save(); // ✗ CLP blocks client writes to this class entirely
} catch (e) {
console.log(e.code); // 119: operation forbidden by class-level permissions
} // Flutter / Dart — Back4app Flutter SDK
// The class gate in action: reads allowed, client writes blocked by CLP
final config = ParseObject('Config')..set('flag', true);
final response = await config.save();
if (!response.success) {
print(response.error?.code); // 119: forbidden by class-level permissions
} // iOS / Swift — Back4app Swift SDK
// The class gate in action: reads allowed, client writes blocked by CLP
var config = Config()
config.flag = true
config.save { result in
if case .failure(let error) = result {
print(error) // operation forbidden by class-level permissions
}
} // Android / Kotlin — Back4app Android SDK
// The class gate in action: reads allowed, client writes blocked by CLP
val config = ParseObject("Config").apply { put("flag", true) }
config.saveInBackground { e ->
if (e != null) {
Log.d("CLP", "blocked: ${e.code}") // forbidden by class-level permissions
}
} Como permissões de classe e ACLs funcionam juntas
A escada de granularidade: CLP vs. ACL vs. pointer permissions vs. campos protegidos
| Mecanismo | Escopo | Declarado onde | Verificado | Trabalho típico |
|---|---|---|---|---|
| Permissão em nível de classe | Classe inteira, por operação | Schema | Primeiro | ”Clientes nunca escrevem em Config” |
| Pointer permission | Por objeto, via regra de schema | Schema (amarrada a um campo) | Segundo | ”Só o owner toca nas próprias linhas” |
| ACL | Por objeto | Em cada linha, como dado | Segundo | ”Esta nota: só a autora” |
| Campos protegidos | Por coluna | Schema | Na leitura | ”Esconder email dos outros usuários” |
O idioma de design que cai disso: traço largo no schema, grão fino nas linhas. Classes cuja regra de acesso é uniforme (config, catálogos, logs) precisam só do gate da classe; classes com dados por usuário adicionam ACLs ou pointer permissions embaixo dele.
O mesmo gate em outros engines
-- PostgreSQL: privilégios em nível de tabela são CLPs com outro nome
GRANT SELECT ON films TO PUBLIC;
GRANT INSERT, UPDATE ON films TO role_editor;
REVOKE ALL ON launch_codes FROM PUBLIC;
Bancos de documentos espelham isso com papéis restritos a ações em nível de coleção — um papel com find e insert em exatamente uma coleção. O conceito é universal; o que muda é a ergonomia: grants em SQL e documentos de papéis são administrados em código, enquanto plataformas BaaS expõem a mesma matriz como checkboxes no dashboard.
Configurações recomendadas por tipo de conteúdo
| Tipo de conteúdo | Find/Get | Create | Update/Delete | Add field |
|---|---|---|---|---|
| Conteúdo público (catálogo, posts) | Público | Papéis/servidor | Papéis/servidor | Desligado |
| Dados do usuário (notas, pedidos) | Autenticado + ACLs | Autenticado | Restrito por ACL | Desligado |
| Config e flags | Público ou autenticado | Ninguém (só servidor) | Papel de admin | Desligado |
| Logs e analytics | Ninguém (só servidor) | Autenticado (só escrita) | Ninguém | Desligado |
| Dados só de admin | Papel de admin | Papel de admin | Papel de admin | Desligado |
Essa tabela é o checklist de que a maioria dos lançamentos realmente precisa — note a constante na última coluna e sua regra irmã: criação de classes pelo cliente desligada em produção, para que o schema só mude de propósito.
Casos de uso comuns
- Congelar schemas de produção. Add field desligado em tudo; classes param de surgir e mutar a partir do tráfego de clientes.
- Dados de referência somente leitura. Catálogos e configurações legíveis publicamente, graváveis só por código do servidor — o padrão
Configacima. - Caixas de entrada só de escrita. Classes de feedback e telemetria nas quais clientes podem criar, mas nunca ler — o gate inverso que o código na camada de app costuma esquecer.
- Superfícies de admin por papel. Update e delete reservados a um papel de admin enquanto o app lê livremente.
- Defesa contra o dump clássico. A famigerada one-liner — um curl com um app ID consultando uma classe
Useraberta — morre no gate de find quando a classe exige autenticação.
Quem deveria aplicar a regra: o gate da classe ou o código no servidor? Matriz de decisão
| Aplique com CLPs (+ ACLs) quando… | Passe pelo código no servidor quando… |
|---|---|
| A regra é “quem pode fazer o quê, onde” | A regra precisa de lógica de negócio (“só antes de o pedido ser enviado”) |
| Ela é uniforme por classe ou por dono | Ela atravessa múltiplos objetos ou classes |
| Você quer enforcement em todo caminho, incluindo clientes novos | Você quer um único chokepoint auditado para um fluxo sensível |
| Declarativo vence imperativo na revisão | Validação, enriquecimento ou efeitos colaterais pegam carona |
| O checkbox no dashboard é a especificação inteira | A especificação é um parágrafo de condições |
Eles se compõem: o padrão endurecido para classes genuinamente sensíveis tranca as CLPs por completo e expõe funções no servidor como a única porta — o gate da classe garante que ninguém contorna o chokepoint.
Limitações e trade-offs
- Granularidade de classe é grossa por definição. Qualquer coisa por linha pertence às ACLs e pointer permissions; qualquer coisa condicional pertence à validação no servidor — CLPs guardam, não raciocinam.
- Os defaults são permissivos para desenvolvimento. Classes novas nascem abertas para o protótipo voar; a passada pré-lançamento que vira a tabela acima é uma disciplina, não um automatismo.
- A master key ignora tudo. Todo gate deste artigo é nulo onde essa chave viaja — por isso ela vive só no servidor, usada por operação, jamais embarcada.
- A superfície de enforcement precisa ser completa. Assinaturas em tempo real e endpoints especiais historicamente tiveram lacunas — mantenha a plataforma atualizada e teste os gates de um cliente real, não só do dashboard.
- Checkboxes também precisam de revisão. Segurança declarativa só é segurança auditável se alguém audita — a matriz de configurações pertence ao seu checklist de lançamento, não à memória tribal.
CLPs no Back4app
O Back4app é uma plataforma open-source de Backend as a Service (BaaS) que combina banco de dados gerenciado, APIs REST e GraphQL geradas automaticamente, autenticação, armazenamento de arquivos e funções serverless com Cloud Code. As permissões em nível de classe são a sua superfície de segurança de schema em forma visual: cada classe no dashboard carrega a matriz de operações como checkboxes — público, exige autenticação, por papel — mais pointer permissions e campos protegidos, aplicados no servidor em toda requisição, igualmente pelos SDKs, REST e GraphQL. Embaixo ficam as ACLs por objeto; em cima, os triggers de Cloud Code para as regras que precisam de lógica. As diretrizes de segurança percorrem a passada pré-lançamento completa — a matriz de configurações deste artigo, aplicada clique a clique.
Perguntas frequentes
O que são permissões em nível de classe?
Regras anexadas ao schema de uma classe (tabela/coleção) que controlam quais usuários ou papéis podem executar cada operação — find, get, count, create, update, delete, add field — sobre qualquer objeto daquela classe. São o gate de acesso mais grosso e o primeiro verificado: se a regra da classe nega a operação, nenhuma permissão por objeto chega a ser consultada.
Qual a diferença entre CLPs e ACLs?
Escopo e ordem. A CLP responde "quem pode tocar nesta classe" — uma regra para a tabela inteira. A ACL responde "quem pode tocar nesta linha específica" — dado carregado por cada objeto. A requisição precisa passar pelos dois gates: primeiro o da classe, depois o do objeto, e qualquer um pode negar. Traço largo no nível da classe, grão fino no nível do objeto.
O que é requiresAuthentication?
O ajuste do meio entre público e papéis enumerados: restringe uma operação a qualquer usuário logado com session válida, sem nomear usuários ou papéis específicos. É o default certo para a maioria dos dados de app — requisições anônimas são rejeitadas, enquanto todo usuário autenticado passa o gate da classe e segue para as verificações de ACL por objeto.
O que são pointer permissions?
Regras em nível de classe amarradas a um campo de ponteiro de usuário no objeto — por exemplo, "só o usuário do campo owner pode ler ou escrever". Funcionam como uma ACL virtual: o enforcement é por objeto, mas a regra é declarada uma vez no schema, em vez de armazenada em cada linha. Elas se intersectam com ACLs reais; as duas precisam permitir a ação.
O que são campos protegidos (protected fields)?
Regras em nível de campo sobre o gate da classe: colunas específicas — um e-mail, um score interno — escondidas de alguns solicitantes enquanto o resto do objeto continua legível. Elas transformam a escada de permissões em três degraus num só schema: operações da classe inteira, acesso por objeto e visibilidade por campo.
Qual é o equivalente em SQL das permissões em nível de classe?
Privilégios de tabela e de schema: GRANT SELECT, INSERT, UPDATE, DELETE em uma tabela para um papel, REVOKE para remover, mais os direitos USAGE e CREATE no nível do schema. O conceito mapeia um para um — um GRANT de tabela é uma permissão em nível de classe com outra sintaxe — e bancos de documentos espelham isso com papéis restritos a ações por coleção.
Clientes deveriam poder adicionar campos ou criar classes em produção?
Não — este é o passo de hardening consensual. A flexibilidade de schema é uma conveniência de desenvolvimento; em produção, desabilite a permissão de add field em toda classe e desligue por completo a criação de classes pelo cliente, congelando o schema contra clientes. Mudanças de schema passam então pelo dashboard ou pelo código no servidor, onde pertencem.
Permissões em nível de classe bastam para proteger um app?
São a primeira camada, não a defesa inteira. O stack padrão: CLPs controlam operações por classe, ACLs ou pointer permissions delimitam linhas, campos protegidos escondem colunas sensíveis e triggers no servidor validam as escritas. E uma regra acima de todas: a master key — que ignora todos os gates — jamais embarca em código de cliente.