Download the PHP package twstec/kit-admin without Composer
On this page you can find all versions of the php package twstec/kit-admin. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download twstec/kit-admin
More information about twstec/kit-admin
Files in twstec/kit-admin
Package kit-admin
Short Description Painel de super admin do TWS Laravel Starter Kit como plugin do Filament 5: usuários, chaves de API, projetos, uploads, logs de requisição, trilha de auditoria e configurações, login com verificação em duas etapas por e-mail, variantes de dashboard, trilha de auditoria de toda ação do painel (falha fechada) e as proteções de acesso (allowlist de IP, só admin com conta ativa) ligadas pelo pacote.
License MIT
Homepage https://github.com/kelvindk9w/tws-laravel-starter-kit
Informations about the package kit-admin
twstec/kit-admin
Parte do TWS Laravel Starter Kit. O código, as issues e os pull requests ficam no monorepo kelvindk9w/tws-laravel-starter-kit (pasta
packages/admin); este repositório é o espelho só-leitura publicado a cada versão. Documentação: docs/ · Segurança: LICENSE).
O super admin do TWS Laravel Starter Kit (/admin) como plugin do
Filament 5: usuários, chaves de API, projetos, uploads, logs de requisição,
trilha de auditoria e configurações, login com verificação em duas etapas por
e-mail, variantes de dashboard, a trilha de auditoria de toda ação do painel
(que falha fechada) e as proteções de acesso — ligadas pelo pacote, não pelo
aplicativo.
É a camada de cima do kit e o único pacote com telas: depende do
twstec/kit-auth, do twstec/kit-foundation, do
Laravel e do Filament (com o Livewire, que o Filament usa). O
twstec/kit-accounts e o twstec/kit-uploads são
sugeridos (suggest), não exigidos: o painel se adapta ao que está
instalado (abaixo). Não conhece o
aplicativo — o model de usuário é o configurado em
auth.providers.users.model — e um teste de arquitetura na suíte do pacote
garante isso.
- Requisitos: PHP 8.4+, Laravel 13, Filament 5, Livewire 4,
twstec/kit-foundationetwstec/kit-auth2.x (e, se quiser as telas deles,twstec/kit-accountsetwstec/kit-uploads2.x). - Licença: MIT.
O que o pacote traz
| Peça | O que faz |
|---|---|
AdminPlugin |
O plugin que o aplicativo registra no painel: resources, páginas, login, segundo fator, dashboards, navegação, menu do usuário, avatar de iniciais e as proteções |
Resources\… |
Usuários (CRUD com guardas), Contas (só leitura: membros e papéis, projetos e chaves da conta), Chaves de API, Projetos, Uploads, Logs de requisição e Auditoria |
Pages\… |
Perfil do admin (foto, nome, segundo fator), Configurações editáveis e o Login (Pages\Auth\Login) |
Auth\EmailCodeAuthentication |
Provedor de MFA do Filament com o motor do twstec/kit-auth (código por e-mail, mesmos limites do painel do cliente); obrigatório quando AUTH_TWO_FACTOR_REQUIRED alcança os administradores |
Dashboards\…, Widgets\… |
As variantes "Visão geral" e "Crescimento & API", o DashboardRegistry (lê config/dashboards.php) e a base de widgets (Metric, Period, BaseStatsWidget…) |
Support\AdminAudit |
A trilha de auditoria das ações: toda chamada Livewire de tela do painel roda com um escopo aberto; o AuditTrail do foundation grava cada escrita de model |
Support\AdminPanelHardening |
As garantias de segurança do painel, aplicadas pelo pacote qualquer que seja a ordem do PanelProvider |
Access\AdminAccess, Concerns\AccessesAdminPanel, Http\Middleware\EnsureAdminPanelAccess |
Quem entra: is_admin + conta ativa — o critério, a trait do canAccessPanel e a conferência do pacote |
Resources\Users\Support\UserAdminGuard, MarkEmailVerifiedAction |
Guardas de servidor (conta protegida, a própria conta, o último admin ativo) e a ação de suporte |
Support\AvatarUpload |
O campo de foto: grava pela função global de upload (foto pessoal) e só vincula upload da própria pessoa |
Authorization\AdminPermissions, AdminAuthorization, AdminRoles |
Papéis e permissões do painel: o critério (admin.authorization.roles), a checagem de servidor em toda chamada Livewire (403 + denied na trilha) e a atribuição de papel (ação sensível, sem escalada) |
Approvals\…, Resources\ApprovalRequests\… |
Aprovação em dois passos: ApprovableAction, Approvals::register()/gate(), o ApprovalService (quatro olhos ou um operador, uma execução só, sob trava) e a tela "Aprovações" |
Console\MakeAdminUser |
php artisan user:make-admin email [--role=papel] [--remove] — o resgate de acesso (papel de dono por padrão), auditado no contexto console |
Módulos opcionais: o painel se adapta
O plugin pergunta ao ponto único de detecção do kit
(Twstec\Kit\Foundation\Kit::has()) o que está instalado e só registra o que
existe (AdminPlugin::RESOURCES diz qual tela é de qual módulo):
| Sem… | O painel |
|---|---|
twstec/kit-accounts |
Sem as telas de contas, chaves de API e projetos (nem menu, nem rota); sem o filtro por conta na trilha de auditoria; os dashboards sem os cards de chaves/projetos e sem a tabela de projetos recentes; sem o modo sistema das contas (não há contas); a guarda de exclusão de usuário não consulta contas |
twstec/kit-uploads |
Sem a tela de uploads e o widget dos últimos uploads; sem o campo de foto no cadastro de usuário e no perfil do admin (o avatar são as iniciais) |
Uma trava de arquitetura da suíte (DependenciesTest) confere que todo
arquivo do pacote que nomeia uma classe de accounts ou uploads é uma tela
registrada só com o módulo ou pergunta Kit::has() antes. A suíte finge a
ausência (Kit::pretendAbsent) e sobe o painel de novo (OptionalModulesTest);
a prova com os pacotes ausentes de verdade é a suíte do starter em cada
combinação, no CI.
Instalação
Pelo Packagist:
Durante o beta, cada pacote do kit que você requerer leva o @beta (ou o
projeto declara "minimum-stability": "beta" com "prefer-stable": true) —
ver docs/instalacao.md.
No monorepo (desenvolvimento do próprio kit), o starter instala o pacote por
path repository — como os
outros ("url": "../../packages/admin", "twstec/kit-admin": "2.x-dev").
O AdminServiceProvider é descoberto automaticamente. O aplicativo precisa de:
-
Um painel com o plugin — o registro mínimo:
-
O model de usuário implementando
Filament\Models\Contracts\FilamentUsercom a traitTwstec\Kit\Admin\Concerns\AccessesAdminPanel(além das dotwstec/kit-authe doHasAvatardotwstec/kit-uploads), e as colunasusers.is_admin(boolean, padrãofalse) eusers.avatar_upload_idnuma migration do aplicativo. O pacote não traz migration. - O tema (opcional, para o visual do kit): um tema Vite do Filament que importe as fontes do pacote — ver Tema e CSS.
Depois: php artisan user:make-admin [email protected] para o primeiro admin.
Personalizar
O painel é do aplicativo: marca, cores, fonte, caminho, id e o que mais for
do Filament vão no PanelProvider, antes ou depois do plugin (o que vier
depois sobrescreve o que o plugin declarou):
Configuração (config/admin.php e config/dashboards.php, publicáveis com
--tag=admin-config; a do aplicativo vence chave a chave):
| Chave | Padrão | O que faz |
|---|---|---|
admin.protections |
true (ADMIN_PROTECTIONS) |
Opt-out das proteções do painel (ver abaixo), com aviso no log a cada boot |
dashboards.enabled |
overview,growth (DASHBOARD_ENABLED) |
Variantes ligadas, na ordem do menu |
dashboards.default |
overview |
A variante que responde na raiz do painel |
dashboards.variants |
as duas do pacote | Catálogo slug → página + ícone + ordem; uma variante nova entra aqui |
dashboards.widgets |
[] |
Widgets que extensões acrescentam a uma variante (com posição) |
Traduções: o grupo admin.* (e as poucas chaves de auth.* e panel.* que
as telas usam e que nenhum pacote de baixo traz) vem do pacote; o lang/ do
aplicativo vence na mesma chave, em todo idioma e no de reserva. Um bloco
novo (admin.faturas, por exemplo) vai no lang/admin.php do aplicativo.
Acrescentar um resource auditado
- Escreva o resource no aplicativo (
app/Filament/Resources/…), estendendoTwstec\Kit\Admin\Support\BaseResourcee a listagem deTwstec\Kit\Admin\Support\BaseListRecords— rota por uuid, rótulos traduzidos, paginação e o alternador tabela/cards vêm da base. - Registre-o no painel (
discoverResourcesou->resources([...])). - A auditoria já vale: as telas de
<namespace do app>\Filament\(no starter,App\Filament\) e as do Filament abrem o escopo de auditoria como as do pacote. Toda escrita pelo model (save,update,delete, as Actions de criar/editar/excluir) vira uma linha emaudit_events. Tela vinda de outro pacote ou extensão entra declarando o namespace emaudit.admin_extension_namespaces(noregisterda extensão). - Duas regras: escreva pelo model (
DB::, query em massa,*Quietly()ewithoutEvents()não geram linha) e recuse comAdminAudit::denied($motivo, $record)(registra a tentativa comodeniede mostra a notificação numa chamada só). O teste de arquitetura do pacote cobra as duas no código dele; o starter cobra no dele, e a suíte da demonstração (twstec/kit-demo) no dela.
Papéis, permissões e aprovação em dois passos
Entrar no painel é is_admin + conta ativa; o que se faz lá dentro vem do
papel (admin_role, migration do pacote — quem já era admin vira
owner). Os papéis ficam em config/admin.php (owner, operations,
support, auditor de fábrica), com permissões <recurso>.<ação> e
curinga. A checagem é no servidor, em toda chamada Livewire de tela do
painel: faltou a permissão, 403 e linha denied na trilha. Atribuir papel é
ação sensível (senha de transação + código), auditada e sem escalada.
Ação de alto impacto pode exigir aprovação em dois passos: declare uma
ApprovableAction, registre com Approvals::register(), passe a Action do
Filament por Approvals::gate() e ligue em ADMIN_APPROVALS_ACTIONS. Modo
quatro olhos (padrão) ou um operador (ação sensível + espera mínima). O kit
traz "excluir usuário" como exemplo (ADMIN_APPROVALS_ACTIONS=users.delete).
Guia completo, com o passo a passo de declarar uma ação num resource novo: docs/admin-e-dashboards.md.
Opt-outs só explícitos, com aviso no log a cada boot:
ADMIN_AUTHORIZATION=false (volta o tudo-ou-nada),
ADMIN_APPROVALS_MODE=single_operator, ADMIN_APPROVALS_SENSITIVE=false.
O que ele liga sozinho
Em todo painel que registra o plugin, sem nenhuma linha no aplicativo e
qualquer que seja a ordem do PanelProvider (Support\AdminPanelHardening,
aplicado no registro do plugin e de novo depois que o Filament montou os
painéis):
- Barreira de origem — a allowlist de IP do
twstec/kit-foundation(security.admin.allowed_ips,ADMIN_ALLOWED_IPS; em produção sem lista o painel recusa) é o primeiro middleware do painel e é persistente no endpoint de atualização do Livewire: vale para abrir a página e para executar a ação dela. Também entra no grupofilament.actions(o download de exports/imports do Filament, fora do painel). - Só administrador com conta ativa — o
Authenticatedo Filament e oEnsureAdminPanelAccessdo pacote, os dois persistentes. O pacote confere mesmo que o model não implemente o contrato do Filament (em ambiente local o Filament deixaria qualquer conta entrar). - Pilha sem repetição — um
PanelProvidercopiado do modelo do Filament, com a pilha de sessão/CSRF inteira, continua funcionando: nenhum middleware entra duas vezes. - Transação — Actions e Criar/Salvar em transação: a linha da trilha é gravada na mesma transação da mudança, e sem ela a mudança é desfeita (falha fechada). Recusa das guardas confirma a transação — a tentativa recusada fica registrada.
- Trilha de auditoria das ações do painel (
AdminAudit, ligada no boot do provider) e o segundo fator por e-mail no login. - Segundo fator obrigatório — com
AUTH_TWO_FACTOR_REQUIRED=adminsouall(regra dotwstec/kit-auth), o MFA do Filament fica obrigatório e oEnsureAdminTwoFactorIsConfigured(na pilha persistente, entre o acesso de admin e o modo sistema) leva o administrador sem segundo fator à tela de configuração do front (two-factor.setup) em toda tela e ação Livewire. "Administrador" é quem entra no painel ou tem qualquer papel dele (Access\PanelAdministrators). - Papéis — a permissão de cada tela e de cada Action conferida no
servidor, pelo mesmo gancho da trilha (
AdminAuthorization). - Modo sistema das contas (
twstec/kit-accounts) — o painel vê projetos e chaves de todas as contas: oOperateAdminPanelAsSystementra na autenticação do painel, depois do acesso de admin, e é persistente. Ele declara o modo sistema da requisição (Accounts::systemModeForRequest) em vez de envolver o$next: nas ações, o Livewire reaplica os middlewares persistentes num pipeline à parte, antes do componente — um modo sistema só em volta do$nextterminaria antes da ação. O fim da requisição o desfaz. As telas de projetos e chaves mostram a conta de cada linha (códigoACC-…, com filtro), o dono da conta e quem criou; a exclusão de pessoa dona de conta com outros membros é recusada (ação escondida e, forjada, recusada com o motivo na trilha).
Opt-out só explícito: ADMIN_PROTECTIONS=false desliga a barreira de origem
do painel, a conferência de acesso do pacote e a transação obrigatória — o
aplicativo assume as três — e o pacote grava um aviso no log a cada boot.
A trilha, o segundo fator e o modo sistema das contas continuam ligados (sem
ele as telas de projetos e chaves não teriam conta atual).
Telas próprias do aplicativo no painel que leem dado de conta rodam no
mesmo modo sistema (a requisição é do painel). Um teste com Livewire::test
de uma tela do painel não passa pela pilha HTTP: declare o modo sistema no
teste (o starter faz isso para tests/Feature/Admin no tests/Pest.php).
O dashboard de filas (/horizon) é do aplicativo (o Horizon não é
dependência do pacote), mas o gate viewHorizon do starter lê o mesmo
critério: AdminAccess::allows($user).
Tema e CSS
O pacote não entrega CSS compilado: o tema do painel é do aplicativo (os
tokens de marca dele + o preset do Filament), compilado pelo Vite dele. O
pacote entrega resources/css/sources.css, que só diz ao Tailwind 4 onde
estão as classes das telas do pacote. O tema do aplicativo o importa:
Por ser um @import, o build falha se o pacote não estiver ao alcance —
em vez de gerar em silêncio um tema sem as classes do painel. Com o pacote
instalado por link (path repository), o build em container precisa montar a
pasta dos pacotes (no starter: -v $(pwd)/../../packages:/packages).
Foto de perfil: só upload da própria pessoa
O campo de foto (cadastro de usuário e perfil do admin) grava pela função
global de upload do twstec/kit-uploads — como foto pessoal
(SecureUploadService::handlePersonal, sem conta, com o operador em
created_by: a foto é da pessoa e aparece em todas as contas dela) — e só
vincula como foto:
- um upload enviado agora, naquele formulário (o servidor o gravou nesta
requisição —
Support\FreshAvatarUploads); - um upload da própria pessoa: foto pessoal que ela mesma enviou, upload da conta pessoal dela (pela web ou pela chave de API dela), ou a foto atual.
O valor do campo vem do navegador; apontá-lo para o upload de outra pessoa é
recusado antes de gravar qualquer coisa (nem os outros campos mudam), com a
recusa na trilha como denied (user.updated; na criação, user.created).
A regra está em AvatarUpload::denialFor().
Uploads e Auditoria por conta
O painel opera em modo sistema (todas as contas). A tela de Uploads mostra
a conta de cada linha (código, com filtro por conta), quem enviou e o tipo de
dono (da conta, foto pessoal, órfão — com filtro); a de Auditoria filtra
pela conta em que a ação aconteceu (audit_events.tenant_uuid, valor que não
é uuid não derruba a consulta). Excluir uma pessoa pelo painel apaga os
arquivos dela (regra do twstec/kit-uploads), com a linha upload.erased na
trilha em nome do operador — menos o que está sob guarda legal, que fica
desvinculado (tipo "Retido") com a recusa na trilha.
Cada upload mostra a classificação (com filtro) e o "guardar até".
Abrir um confidencial é a ação "Abrir documento confidencial", com
permissão própria uploads.view_confidential (fora de *.view): a URL nasce
no clique e a geração e a visualização ficam na trilha com o contexto admin.
As ações de guarda legal pedem uploads.legal_hold.
Excluir usuário respeita os impedimentos de exclusão declarados pelo
aplicativo (twstec/kit-accounts): a ação some com o motivo; e um registro do
aplicativo que aponta para a pessoa com chave estrangeira RESTRICT sem ter
sido declarado vira recusa limpa na hora (notificação + denied na trilha,
nada apagado), não o erro do banco. Com a aprovação em dois passos
(users.delete), o mesmo vale em cada passo: impedimento recusa o pedido; a
recusa que só aparece na execução deixa o pedido failed com a mensagem
traduzida (Approvals\ExecutionRefused), nada apagado. Nos dois caminhos, a
exclusão é a do caminho único do twstec/kit-accounts
(Deletion\AccountDeletion::deleteUser), que grava a recusa na trilha uma vez
só; o painel só avisa o operador. (UserAdminGuard::deleteRefusal(Closure)
deu lugar a UserAdminGuard::delete($pessoa), que lança a recusa já gravada —
Support\Exceptions\RecordedDenial.)
Nomes antigos → nomes novos
Até a 1.x o painel morava no aplicativo, em App\Filament\…. Os nomes antigos
continuam resolvendo até a 3.0 (apelido preguiçoso, lista fechada em
Compat\LegacyNames — as peças novas do pacote e uma tela que o aplicativo
escreve em App\Filament\ não ganham nome antigo):
| Antigo | Novo |
|---|---|
App\Filament\<resto> (as 59 classes do painel da 1.x) |
Twstec\Kit\Admin\<resto> |
App\Console\Commands\MakeAdminUser, App\Core\Auth\Console\MakeAdminUser |
Twstec\Kit\Admin\Console\MakeAdminUser |
Onde o nome antigo pode estar gravado, e o que acontece:
- snapshot de componente Livewire aberto no navegador durante o deploy (o nome do componente de uma página do Filament é a classe): o Livewire acha a classe pelo nome antigo e a ação funciona;
- config de dashboards publicada: o
DashboardRegistryaceita o nome antigo e registra sempre o novo; - estado de tabela (itens por página, ordenação, filtros, busca, colunas —
o Filament grava na sessão pelo nome da classe) e o modo tabela/cards:
migram para o nome novo na primeira abertura da tela
(
Support\LegacySessionState, idempotente — uma escolha feita depois da atualização vence); - exports/imports do Filament e jobs: o painel não tem exportação,
importação nem job com o nome da classe; a trilha de auditoria grava o nome
curto do model (
user), nunca a classe.
Lacunas conhecidas
- A coluna de código público das listagens pede
admin.common.code, chave que nunca existiu (a 1.x já mostrava a chave crua). A extração manteve a tela idêntica; a correção é uma mudança de texto própria.
Testes
A suíte do pacote (Pest + Orchestra Testbench) sobe uma aplicação Laravel
limpa com o Filament, o model de usuário mínimo e um PanelProvider que
só registra o plugin — nada do starter — e prova que as proteções e a trilha
vêm do pacote: não-admin e admin inativo sem acesso (inclusive com model sem o
contrato do Filament em ambiente local), allowlist de IP nas páginas, nas ações
Livewire e no download de exports, a barreira em primeiro lugar em qualquer
ordem do PanelProvider, criar/editar/excluir/bloquear usuário gravando a
linha com quem, registro, antes/depois redigido, IP, User-Agent e
correlation_id, recusa como denied, falha fechada, contas protegidas,
user:make-admin, foto só de upload da própria conta, a matriz de
permissões por papel no servidor (inclusive a chamada forjada: 403 + denied),
atribuição de papel sem escalada, o último dono protegido, a aprovação em dois
passos (quatro olhos, um operador, vencido, estado mudado, falha), nomes antigos,
traduções (o aplicativo vence) e a arquitetura (só os pacotes do kit, o
Laravel, o Filament e o Livewire).
All versions of kit-admin with dependencies
filament/filament Version ^5.7
laravel/framework Version ^13.17
livewire/livewire Version ^4.4
twstec/kit-auth Version ^2.0
twstec/kit-foundation Version ^2.0