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

91
app/Models/Revision.php Normal file
View File

@@ -0,0 +1,91 @@
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
/**
* One recorded change to one record.
*
* Keeps the author's name as well as the link to their account: people leave,
* accounts get deleted, and "somebody published this in March" is worth less
* than a name.
*/
#[Fillable(['user_id', 'user_name', 'event', 'changeset'])]
class Revision extends Model
{
public const UPDATED_AT = null;
protected function casts(): array
{
return ['changeset' => 'array'];
}
/**
* @return MorphTo<Model, $this>
*/
public function revisionable(): MorphTo
{
return $this->morphTo();
}
/**
* @return BelongsTo<User, $this>
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function author(): string
{
// The live name when the account is at hand — people rename
// themselves — and the recorded one otherwise, including once the
// account is gone. Never a lazy load: this is read inside table rows.
if ($this->relationLoaded('user') && $this->user !== null) {
return $this->user->name;
}
return $this->user_name ?? __('panel.revisions.system');
}
/**
* The attributes this revision touched.
*
* @return array<int, string>
*/
public function fields(): array
{
return array_keys($this->changeset ?? []);
}
/**
* What a given attribute looked like before and after.
*
* @return array{old: mixed, new: mixed}
*/
public function diff(string $field): array
{
return [
'old' => $this->changeset[$field]['old'] ?? null,
'new' => $this->changeset[$field]['new'] ?? null,
];
}
/**
* The values needed to put a record back the way it was.
*
* @return array<string, mixed>
*/
public function previousValues(): array
{
return collect($this->changeset ?? [])
->map(fn (array $change) => $change['old'] ?? null)
->all();
}
}