- All SKILL.md files now <500 lines (avg reduction 69%) - Detailed content extracted to references/ subdirectories - Frontmatter standardised: only name + description (Anthropic standard) - New skills: brand-guidelines, spec-coauthor, report-templates, skill-creator - Design skills: anti-slop guidelines, premium-proposals reference - Removed non-standard frontmatter fields (triggers, version, author, category) Plugins affected: infraestrutura, marketing, dev-tools, crm-ops, gestao, core-tools, negocio, perfex-dev, wordpress, design-media Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
11 KiB
11 KiB
name, description
| name | description |
|---|---|
| perfex-permissions | Sistema de permissões Perfex CRM — staff_can(), register_staff_capabilities(), controlo de acesso e roles. Baseado apenas na documentação oficial. |
/perfex-permissions - Permissões Perfex CRM
Sistema de permissões e controlo de acesso. Zero assumptions, zero hallucinations - apenas documentação oficial.
Documentação Base
Conceitos Fundamentais
| Conceito | Descrição |
|---|---|
| Feature | Área funcional (invoices, projects, meu_modulo) |
| Capability | Permissão específica (view, create, edit, delete) |
| Role | Conjunto de permissões pré-definido |
Registar Permissões do Módulo
No Init File
hooks()->add_action('admin_init', 'meu_modulo_register_permissions');
function meu_modulo_register_permissions()
{
$capabilities = [];
$capabilities['capabilities'] = [
'view' => _l('permission_view'), // Ver
'create' => _l('permission_create'), // Criar
'edit' => _l('permission_edit'), // Editar
'delete' => _l('permission_delete'), // Apagar
];
register_staff_capabilities(
'meu_modulo', // Feature ID (único)
$capabilities, // Array de capabilities
_l('meu_modulo_title') // Nome do módulo (mostrado em Settings)
);
}
Parâmetros register_staff_capabilities()
| Parâmetro | Tipo | Descrição |
|---|---|---|
$feature |
string | ID único da feature |
$capabilities |
array | Array com key 'capabilities' |
$name |
string | Nome mostrado na UI |
Verificar Permissões: staff_can()
Sintaxe
staff_can($capability, $feature = null, $staff_id = '');
Parâmetros
| Parâmetro | Tipo | Descrição |
|---|---|---|
$capability |
string | Nome da capability (view, create, etc.) |
$feature |
string | Feature ID (recomendado SEMPRE passar) |
$staff_id |
int | ID do staff (default: staff logado) |
Retorno
true- Staff tem permissãofalse- Staff não tem permissão
NOTA: Administradores SEMPRE retornam true (bypass total).
Exemplos de Uso
No Controller
class Meu_modulo extends AdminController
{
public function index()
{
// Verificar permissão de ver
if (!staff_can('view', 'meu_modulo')) {
access_denied('meu_modulo');
}
// ... código
}
public function create()
{
// Verificar permissão de criar
if (!staff_can('create', 'meu_modulo')) {
access_denied('meu_modulo');
}
// ... código
}
public function edit($id)
{
// Verificar permissão de editar
if (!staff_can('edit', 'meu_modulo')) {
access_denied('meu_modulo');
}
// ... código
}
public function delete($id)
{
// Verificar permissão de apagar
if (!staff_can('delete', 'meu_modulo')) {
access_denied('meu_modulo');
}
// ... código
}
}
Na View
<!-- Mostrar botão apenas se tem permissão -->
<?php if (staff_can('create', 'meu_modulo')): ?>
<a href="<?php echo admin_url('meu_modulo/create'); ?>" class="btn btn-primary">
<i class="fa fa-plus"></i> <?php echo _l('create'); ?>
</a>
<?php endif; ?>
<!-- Botões de acção condicionais -->
<td>
<?php if (staff_can('edit', 'meu_modulo')): ?>
<a href="<?php echo admin_url('meu_modulo/edit/' . $item->id); ?>"
class="btn btn-default btn-icon">
<i class="fa fa-pencil"></i>
</a>
<?php endif; ?>
<?php if (staff_can('delete', 'meu_modulo')): ?>
<a href="<?php echo admin_url('meu_modulo/delete/' . $item->id); ?>"
class="btn btn-danger btn-icon _delete">
<i class="fa fa-trash"></i>
</a>
<?php endif; ?>
</td>
No Menu
function meu_modulo_init_menu()
{
// Só mostrar menu se tem permissão
if (!staff_can('view', 'meu_modulo')) {
return;
}
$CI = &get_instance();
$CI->app_menu->add_sidebar_menu_item('meu-modulo', [
'name' => _l('meu_modulo'),
'href' => admin_url('meu_modulo'),
'position' => 25,
'icon' => 'fa fa-cube',
]);
}
Capabilities Padrão
Recomendadas para CRUD
| Capability | Descrição | Uso |
|---|---|---|
view |
Ver registos | Listar, ver detalhes |
create |
Criar novos | Formulário de criação |
edit |
Editar existentes | Formulário de edição |
delete |
Apagar registos | Botão de eliminar |
Adicionar Capabilities Custom
$capabilities['capabilities'] = [
// CRUD básico
'view' => _l('permission_view'),
'create' => _l('permission_create'),
'edit' => _l('permission_edit'),
'delete' => _l('permission_delete'),
// Custom
'export' => _l('permission_export'), // Exportar dados
'import' => _l('permission_import'), // Importar dados
'send_email' => _l('permission_send_email'), // Enviar emails
'view_all' => _l('permission_view_all'), // Ver todos (não só próprios)
'approve' => _l('permission_approve'), // Aprovar items
];
Adicionar Permissões a Features Existentes
Para adicionar capabilities a módulos do core (invoices, projects, etc.):
hooks()->add_action('admin_init', 'meu_modulo_extend_permissions');
function meu_modulo_extend_permissions()
{
$capabilities = [];
$capabilities['capabilities'] = [
'meu_modulo_custom_action' => _l('meu_modulo_custom_action_label'),
];
// Adicionar à feature "invoices"
register_staff_capabilities('invoices', $capabilities);
}
Uso:
if (staff_can('meu_modulo_custom_action', 'invoices')) {
// Acção custom em facturas
}
Verificar Administrador
// Verificar se é admin (tem todas as permissões)
if (is_admin()) {
// Utilizador é administrador
}
// Verificar se é admin específico (ID 1)
if (is_admin(1)) {
// Staff com ID 1 é admin
}
Funções Auxiliares
Acesso Negado
// Redireciona com mensagem de acesso negado
access_denied('meu_modulo');
Verificar Staff Logado
// ID do staff actual
$staff_id = get_staff_user_id();
// Verificar se está logado
if (is_staff_logged_in()) {
// Staff autenticado
}
Verificar Permissão de Outro Staff
// Verificar se staff ID 5 pode editar
$can_edit = staff_can('edit', 'meu_modulo', 5);
Exemplo Completo
Init File
<?php
defined('BASEPATH') or exit('No direct script access allowed');
/*
Module Name: Gestão de Inventário
Description: Sistema de inventário com controlo de acesso
Version: 1.0.0
Requires at least: 2.3.*
*/
// Registar permissões
hooks()->add_action('admin_init', 'inventario_register_permissions');
hooks()->add_action('admin_init', 'inventario_init_menu');
function inventario_register_permissions()
{
$capabilities = [
'capabilities' => [
'view' => _l('permission_view'),
'create' => _l('permission_create'),
'edit' => _l('permission_edit'),
'delete' => _l('permission_delete'),
'export' => _l('inventory_permission_export'),
'adjust' => _l('inventory_permission_adjust'), // Ajustar stock
'view_costs' => _l('inventory_permission_view_costs'), // Ver custos
],
];
register_staff_capabilities(
'inventario',
$capabilities,
_l('inventory_module')
);
}
function inventario_init_menu()
{
if (!staff_can('view', 'inventario')) {
return;
}
$CI = &get_instance();
$CI->app_menu->add_sidebar_menu_item('inventario', [
'name' => _l('inventory'),
'collapse' => true,
'position' => 22,
'icon' => 'fa fa-cubes',
]);
$CI->app_menu->add_sidebar_children_item('inventario', [
'slug' => 'inventario-lista',
'name' => _l('products'),
'href' => admin_url('inventario'),
'position' => 1,
'icon' => 'fa fa-list',
]);
if (staff_can('adjust', 'inventario')) {
$CI->app_menu->add_sidebar_children_item('inventario', [
'slug' => 'inventario-ajustes',
'name' => _l('adjustments'),
'href' => admin_url('inventario/adjustments'),
'position' => 2,
'icon' => 'fa fa-exchange',
]);
}
if (staff_can('export', 'inventario')) {
$CI->app_menu->add_sidebar_children_item('inventario', [
'slug' => 'inventario-export',
'name' => _l('export'),
'href' => admin_url('inventario/export'),
'position' => 3,
'icon' => 'fa fa-download',
]);
}
}
Controller
<?php
defined('BASEPATH') or exit('No direct script access allowed');
class Inventario extends AdminController
{
public function __construct()
{
parent::__construct();
$this->load->model('inventario/inventario_model');
}
public function index()
{
if (!staff_can('view', 'inventario')) {
access_denied('inventario');
}
$data['products'] = $this->inventario_model->get_all();
// Se pode ver custos, incluir
if (staff_can('view_costs', 'inventario')) {
$data['show_costs'] = true;
}
$this->load->view('inventario/index', $data);
}
public function adjustments()
{
if (!staff_can('adjust', 'inventario')) {
access_denied('inventario');
}
// ... lógica de ajustes
}
public function export()
{
if (!staff_can('export', 'inventario')) {
access_denied('inventario');
}
// ... lógica de exportação
}
}
Anti-Patterns (NUNCA FAZER)
| Anti-Pattern | Risco | Alternativa |
|---|---|---|
| Não verificar permissões no controller | Acesso não autorizado | staff_can() sempre |
| Confiar apenas na UI | Bypass via URL | Verificar em backend |
| Feature ID duplicado | Conflitos | Prefixar com nome módulo |
| Capability sem _l() | Não traduzível | Usar traduções |
| Assumir que view esconde acção | Vulnerável | Verificar em ambos |
Checklist Permissões
1. [ ] register_staff_capabilities no init file
2. [ ] Feature ID único
3. [ ] Capabilities com traduções (_l)
4. [ ] staff_can() em TODOS os métodos do controller
5. [ ] staff_can() nas views para UI condicional
6. [ ] staff_can() antes de mostrar menus
7. [ ] access_denied() para rejeitar acesso
8. [ ] Testado com utilizador não-admin
Versão: 1.0.0 | Autor: Descomplicar® Fonte: help.perfexcrm.com/staff-capabilities-and-access