AgentSkillsCN

Create Permission

创建权限

SKILL.md

🔐 Skill: Criar Permissão

Quando Usar

Quando precisar adicionar nova permissão ao sistema RBAC.

Formato de Permissão

code
{recurso}:{ação}:{escopo}

Passos

1. Definir a Permissão

typescript
// Exemplo: permitir exportar relatórios
const permission = 'relatorio:export:all';

2. Usar no Backend (Controller)

typescript
// src/modules/relatorio/relatorio.controller.ts
import { RequirePermission } from '@/common/decorators/permissions.decorator';

@Controller('relatorios')
export class RelatorioController {
  @Get('export')
  @RequirePermission('relatorio', 'export', 'all')
  async export(@CurrentUser() user: User) {
    return this.relatorioService.export(user.tenantId);
  }
}

3. Usar no Backend (Service com escopo)

typescript
// src/modules/relatorio/relatorio.service.ts
@Injectable()
export class RelatorioService {
  constructor(
    private readonly prisma: PrismaService,
    private readonly permissionService: PermissionService,
  ) {}

  async export(user: User) {
    // Verificar escopo da permissão
    const scope = await this.permissionService.getEffectiveScope(
      user,
      'relatorio',
      'export'
    );

    const where: any = { tenantId: user.tenantId };

    // Aplicar filtro baseado no escopo
    switch (scope) {
      case 'own':
        where.createdById = user.id;
        break;
      case 'team':
        where.createdBy = { organizationId: user.organizationId };
        break;
      // 'all' não precisa de filtro adicional
    }

    return this.prisma.relatorio.findMany({ where });
  }
}

4. Usar no Frontend (Hook)

typescript
// hooks/use-permission.ts
import { usePermission } from '@/hooks/use-permission';

function RelatorioPage() {
  const { can } = usePermission();

  return (
    <div>
      {can('relatorio', 'export') && (
        <Button onClick={handleExport}>Exportar</Button>
      )}
    </div>
  );
}

5. Usar no Frontend (Component Gate)

typescript
// components/shared/permission-gate.tsx
import { PermissionGate } from '@/components/shared/permission-gate';

function RelatorioPage() {
  return (
    <div>
      <PermissionGate resource="relatorio" action="export">
        <Button onClick={handleExport}>Exportar</Button>
      </PermissionGate>
    </div>
  );
}

6. Adicionar às Roles Padrão

typescript
// prisma/seed.ts

// Roles com a nova permissão
const roles = {
  admin: [
    // ... outras permissões
    'relatorio:manage:all',  // Admin pode tudo
  ],
  manager: [
    // ... outras permissões
    'relatorio:read:all',
    'relatorio:export:team', // Gerente exporta da equipe
  ],
  user: [
    // ... outras permissões
    'relatorio:read:team',
    'relatorio:export:own', // Usuário exporta os próprios
  ],
  viewer: [
    'relatorio:read:team', // Viewer só visualiza
  ],
};

7. Documentar

markdown
<!-- .claude/docs/PERMISSIONS.md -->

## Relatórios

| Permissão | Descrição |
|-----------|-----------|
| `relatorio:read:all` | Ver todos os relatórios |
| `relatorio:read:team` | Ver relatórios da equipe |
| `relatorio:read:own` | Ver próprios relatórios |
| `relatorio:create:all` | Criar relatórios |
| `relatorio:export:all` | Exportar todos |
| `relatorio:export:team` | Exportar da equipe |
| `relatorio:export:own` | Exportar próprios |

Permissões Comuns

typescript
// CRUD básico
'recurso:create:all'
'recurso:read:all'
'recurso:read:team'
'recurso:read:own'
'recurso:update:all'
'recurso:update:team'
'recurso:update:own'
'recurso:delete:all'
'recurso:delete:team'
'recurso:delete:own'

// Extras
'recurso:export:all'
'recurso:import:all'
'recurso:manage:all'  // Todas as ações

Checklist

  • Permissão definida no formato correto
  • @RequirePermission no controller
  • Escopo aplicado no service (se necessário)
  • Hook usePermission no frontend
  • PermissionGate nos componentes
  • Adicionada nas roles padrão (seed)
  • Documentada em PERMISSIONS.md