Implandação da customização das permissões dos usuarios e das notificaçoes

This commit is contained in:
2026-08-26 17:24:25 -03:00
parent 808c2c7545
commit 5bb5d74e22
71 changed files with 2487 additions and 269 deletions

View File

@@ -0,0 +1,60 @@
require 'rails_helper'
RSpec.describe PerfilAcesso do
it 'descarta chave que não existe mais no catálogo ao salvar' do
perfil = create(:perfil_acesso, permissoes: ['consolidacao.ver', 'permissao.aposentada'])
expect(perfil.permissoes).to eq(['consolidacao.ver'])
expect(perfil).to be_pode('consolidacao.ver')
expect(perfil).not_to be_pode('permissao.aposentada')
end
it 'não aceita dois perfis com o mesmo nome' do
create(:perfil_acesso, nome: 'Financeiro')
expect(build(:perfil_acesso, nome: 'financeiro')).not_to be_valid
end
describe '#apagavel?' do
it 'perfil de sistema não é apagável' do
expect(build(:perfil_acesso, sistema: true)).not_to be_apagavel
end
it 'perfil em uso não é apagável (o usuário cairia no fallback sem avisar)' do
perfil = create(:perfil_acesso)
create(:operador, perfil_acesso: perfil)
expect(perfil.reload).not_to be_apagavel
end
it 'perfil livre é apagável' do
expect(create(:perfil_acesso)).to be_apagavel
end
end
describe 'permissões do usuário' do
it 'o perfil vence o padrão do papel' do
# Gerente por papel veria Configurações; o perfil tira só isso.
perfil = create(:perfil_acesso, permissoes: Permissao.do_role('gerente') - ['admin.configuracoes'])
usuario = create(:gerente, perfil_acesso: perfil)
expect(usuario.pode?('consolidacao.registrar_pagamento')).to be(true)
expect(usuario.pode?('admin.configuracoes')).to be(false)
expect(usuario.pode_ver_config?).to be(false)
end
it 'sem perfil, vale o padrão do papel (e não consulta o banco)' do
usuario = build(:gerente) # não persistido, como nos specs de policy
expect(usuario.pode_consolidar?).to be(true)
expect(usuario.pode_ver_config?).to be(true)
expect(usuario.pode?('admin.perfis')).to be(false)
end
it 'perfil vazio tira tudo sem precisar desativar a conta' do
usuario = create(:operador, perfil_acesso: create(:perfil_acesso, permissoes: []))
expect(usuario.pode?('consolidacao.ver')).to be(false)
expect(usuario.pode_consolidar?).to be(false)
end
end
end

View File

@@ -0,0 +1,73 @@
require 'rails_helper'
# O catálogo é a fonte única de "o que dá para liberar". Estas travas existem
# porque um erro aqui não aparece na tela: uma chave escrita errado no
# PADRAO_POR_ROLE simplesmente não bate com nada e tira acesso de todo um papel
# em silêncio.
RSpec.describe Permissao do
describe 'catálogo' do
it 'toda chave segue o padrão area.acao e pertence a um grupo declarado' do
described_class::TODAS.each do |chave, cfg|
expect(chave.count('.')).to eq(1), "#{chave} fora do padrão area.acao"
expect(described_class::GRUPOS).to have_key(cfg[:grupo]), "#{chave}: grupo #{cfg[:grupo]} não existe"
expect(cfg[:label]).to be_present
expect(cfg[:descricao]).to be_present, "#{chave} sem descrição (é o texto que o ADM lê na tela)"
end
end
it 'por_grupo cobre todas as chaves' do
total = described_class.por_grupo.values.sum(&:size)
expect(total).to eq(described_class.chaves.size)
end
it 'filtrar descarta chave inexistente e repetida' do
expect(described_class.filtrar(['consolidacao.ver', 'nao.existe', 'consolidacao.ver']))
.to eq(['consolidacao.ver'])
end
end
describe 'PADRAO_POR_ROLE' do
it 'só usa chaves que existem no catálogo' do
described_class::PADRAO_POR_ROLE.each do |role, lista|
next if lista == :todas
lista.each do |chave|
expect(described_class).to be_existe(chave), "#{role} referencia chave inexistente: #{chave}"
end
end
end
it 'admin recebe o catálogo inteiro' do
expect(described_class.do_role('admin')).to match_array(described_class.chaves)
end
# O fallback é o que mantém o comportamento de hoje para quem ainda não tem
# perfil. Se estes pares mudarem, alguém perde acesso no dia do deploy.
it 'reproduz pode_consolidar? e pode_ver_config? de cada papel' do
{
'admin' => [true, true],
'gerente' => [true, true],
'operador' => [true, false],
'motorista' => [false, false],
'externo' => [false, false]
}.each do |role, (consolidar, config)|
chaves = described_class.do_role(role)
expect(chaves.include?('consolidacao.ver')).to eq(consolidar), "#{role}: consolidar"
expect(chaves.include?('admin.configuracoes')).to eq(config), "#{role}: config"
end
end
# As duas mudanças de comportamento deliberadas desta entrega.
it 'externo não enxerga o financeiro (era o furo do skip_authorization)' do
expect(described_class.do_role('externo')).not_to include('dashboard.financeiro')
end
it 'operador não enxerga a auditoria (o menu nunca ofereceu)' do
expect(described_class.do_role('operador')).not_to include('admin.auditoria')
end
it 'motorista não usa permissão — o acesso dele é por tipo de conta' do
expect(described_class.do_role('motorista')).to be_empty
end
end
end

View File

@@ -0,0 +1,27 @@
require 'rails_helper'
RSpec.describe VariavelPersonalizada do
it 'normaliza a chave (minúscula, sem espaço)' do
v = create(:variavel_personalizada, chave: ' Telefone Suporte ', valor: '4002-8922')
expect(v.chave).to eq('telefone_suporte')
expect(v.marcador).to eq('{{telefone_suporte}}')
end
it 'recusa chave com formato que o renderizador não substituiria' do
expect(build(:variavel_personalizada, chave: '2telefone')).not_to be_valid
expect(build(:variavel_personalizada, chave: 'telefone-suporte')).not_to be_valid
end
# Deixar o ADM criar {{valor}} faria a variável dele brigar com a do sistema —
# e o preview não mostraria o problema, só o envio real.
it 'recusa chave que já existe no sistema' do
v = build(:variavel_personalizada, chave: 'valor')
expect(v).not_to be_valid
expect(v.errors[:chave].join).to include('já existe no sistema')
end
it 'não aceita duas variáveis com a mesma chave' do
create(:variavel_personalizada, chave: 'site', valor: 'a')
expect(build(:variavel_personalizada, chave: 'SITE', valor: 'b')).not_to be_valid
end
end