Added opaque join-token support across backend and frontend: new migration/model/service/endpoints, guest controllers now resolve tokens, and the demo seeder seeds a token. Tenant event details list/manage tokens with copy/revoke actions, and the guest PWA uses tokens end-to-end (routing, storage, uploads, achievements, etc.). Docs TODO updated to reflect completed steps.

This commit is contained in:
Codex Agent
2025-10-12 10:32:37 +02:00
parent d04e234ca0
commit 9394c3171e
73 changed files with 3277 additions and 911 deletions

View File

@@ -0,0 +1,73 @@
<?php
namespace App\Http\Controllers\Api\Tenant;
use App\Http\Controllers\Controller;
use App\Http\Resources\Tenant\EventJoinTokenResource;
use App\Models\Event;
use App\Models\EventJoinToken;
use App\Services\EventJoinTokenService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class EventJoinTokenController extends Controller
{
public function __construct(private readonly EventJoinTokenService $joinTokenService)
{
}
public function index(Request $request, Event $event): JsonResponse
{
$this->authorizeEvent($request, $event);
$tokens = $event->joinTokens()
->orderByDesc('created_at')
->get();
return EventJoinTokenResource::collection($tokens);
}
public function store(Request $request, Event $event): JsonResponse
{
$this->authorizeEvent($request, $event);
$validated = $request->validate([
'label' => ['nullable', 'string', 'max:255'],
'expires_at' => ['nullable', 'date', 'after:now'],
'usage_limit' => ['nullable', 'integer', 'min:1'],
'metadata' => ['nullable', 'array'],
]);
$token = $this->joinTokenService->createToken($event, array_merge($validated, [
'created_by' => Auth::id(),
]));
return (new EventJoinTokenResource($token))
->response()
->setStatusCode(201);
}
public function destroy(Request $request, Event $event, EventJoinToken $joinToken): JsonResponse
{
$this->authorizeEvent($request, $event);
if ($joinToken->event_id !== $event->id) {
abort(404);
}
$reason = $request->input('reason');
$token = $this->joinTokenService->revoke($joinToken, $reason);
return new EventJoinTokenResource($token);
}
private function authorizeEvent(Request $request, Event $event): void
{
$tenantId = $request->attributes->get('tenant_id');
if ($event->tenant_id !== $tenantId) {
abort(404, 'Event not found');
}
}
}