# app/controllers/usuarios_controller.rb class Admin::UsuariosController < ApplicationController before_action :set_usuario, only: [:show, :edit, :update, :destroy, :toggle_ativo] def index authorize User @usuarios = policy_scope(User).includes(:perfil_acesso).order(:nome).limit(200) @roles = User.roles.keys end def show authorize @usuario end def new @usuario = User.new authorize @usuario end def create @usuario = User.new(usuario_params) authorize @usuario if @usuario.save AuditoriaLog.registrar(user: current_user, acao: 'criar_usuario', entidade: 'User', dados_novos: { detalhes: "Criou usuário #{@usuario.email} (#{@usuario.role})" }, request: request) redirect_to admin_usuarios_path, notice: 'Usuário criado com sucesso.' else render :new, status: :unprocessable_entity end end def edit authorize @usuario end def update authorize @usuario # Trava do último administrador: mudar perfil ou desativar a única pessoa que # ainda administra acesso deixaria o sistema sem quem conserte. if desligaria_o_ultimo_administrador? @usuario.errors.add(:base, MENSAGEM_ULTIMO_ADMIN) return render(:edit, status: :unprocessable_entity) end if @usuario.update(usuario_params_update) AuditoriaLog.registrar(user: current_user, acao: 'editar_usuario', entidade: 'User', dados_novos: { detalhes: "Editou usuário #{@usuario.email}" }, request: request) redirect_to admin_usuarios_path, notice: 'Usuário atualizado.' else render :edit, status: :unprocessable_entity end end def destroy authorize @usuario if User.ultimo_administrador?(@usuario) return redirect_to(admin_usuarios_path, alert: MENSAGEM_ULTIMO_ADMIN) end if @usuario == current_user redirect_to admin_usuarios_path, alert: 'Você não pode excluir sua própria conta.' return end @usuario.destroy AuditoriaLog.registrar(user: current_user, acao: 'excluir_usuario', entidade: 'User', dados_novos: { detalhes: "Excluiu usuário #{@usuario.email}" }, request: request) redirect_to admin_usuarios_path, notice: 'Usuário removido.' end def toggle_ativo authorize @usuario, :toggle_ativo? if @usuario.ativo? && User.ultimo_administrador?(@usuario) return redirect_to(admin_usuarios_path, alert: MENSAGEM_ULTIMO_ADMIN) end @usuario.update!(ativo: !@usuario.ativo) status = @usuario.ativo? ? 'ativado' : 'desativado' AuditoriaLog.registrar(user: current_user, acao: "usuario_#{status}", entidade: 'User', dados_novos: { detalhes: "#{@usuario.email} foi #{status}" }, request: request) redirect_to admin_usuarios_path, notice: "Usuário #{status} com sucesso." end private MENSAGEM_ULTIMO_ADMIN = 'Esta alteração deixaria o sistema sem nenhum usuário ativo capaz de ' \ 'gerenciar perfis e usuários. Dê esse acesso a outra pessoa antes.'.freeze def set_usuario @usuario = User.find(params[:id]) end # Aplica as mudanças em memória e pergunta: sobra alguém administrando? def desligaria_o_ultimo_administrador? simulado = @usuario.dup simulado.id = @usuario.id simulado.assign_attributes(usuario_params_update) simulado.recarregar_permissoes! return false if simulado.ativo? && simulado.pode?('admin.perfis') && simulado.pode?('admin.usuarios_gerenciar') User.ultimo_administrador?(@usuario) end # ⚠️ CAMPOS DE ACESSO SÓ PARA QUEM PODE MEXER NELES. # `UserPolicy#update?` libera editar a PRÓPRIA ficha (nome, senha) — é o que # permite alguém trocar a própria senha. Sem o filtro abaixo, essa mesma # permissão deixava qualquer usuário logado enviar `user[role]=admin` na edição # do próprio cadastro e se promover. Quem decide papel e perfil é # `UserPolicy#alterar_acesso?` (nunca sobre si mesmo). CAMPOS_DE_ACESSO = %i[role perfil_acesso_id ativo].freeze def usuario_params permitidos = [:nome, :email, :password, :password_confirmation, :pin_code] permitidos += CAMPOS_DE_ACESSO if pode_alterar_acesso? params.require(:user).permit(permitidos) end def usuario_params_update permitidos = [:nome, :email, :pin_code] permitidos += CAMPOS_DE_ACESSO if pode_alterar_acesso? permitidos += [:password, :password_confirmation] if params[:user][:password].present? params.require(:user).permit(permitidos) end def pode_alterar_acesso? if @usuario&.persisted? policy(@usuario).alterar_acesso? else # Criação: não há "si mesmo" para se promover, basta poder gerenciar. current_user.pode?('admin.usuarios_gerenciar') end end helper_method :pode_alterar_acesso? end