Initial commit: Pireon Admin — headless admin panel and public API

Laravel 13 + Filament 5 admin panel and REST API for a non-profit developer
collective, backed by the Pireon OAuth identity server. The public site is a
separate, server-rendered application consuming /api/public/v1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-19 17:55:27 +02:00
commit 3897113313
534 changed files with 64050 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace Database\Seeders;
use App\Support\Permissions;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Spatie\Permission\PermissionRegistrar;
/**
* Brings the database in line with App\Support\Permissions.
*
* Idempotent: safe to re-run after every deploy. Permissions removed from the
* catalogue are deleted, so a permission that no longer exists in code cannot
* keep granting access.
*/
class RolePermissionSeeder extends Seeder
{
public function run(): void
{
app(PermissionRegistrar::class)->forgetCachedPermissions();
$catalogue = Permissions::all();
foreach ($catalogue as $name) {
Permission::findOrCreate($name, 'web');
}
// Drop permissions that were retired from the catalogue, along with
// their role and user assignments.
Permission::query()->whereNotIn('name', $catalogue)->delete();
foreach (Permissions::roleDefinitions() as $roleName => $permissions) {
$role = Role::findOrCreate($roleName, 'web');
// syncPermissions is what makes this idempotent: the role ends up
// with exactly the definition in code, no more and no less.
// super_admin gets an empty set on purpose — its power comes from
// the Gate::before hook in AuthServiceProvider.
$role->syncPermissions($permissions);
}
app(PermissionRegistrar::class)->forgetCachedPermissions();
$this->command?->info(sprintf(
'Synced %d permissions across %d roles.',
count($catalogue),
count(Permissions::roleDefinitions()),
));
}
}