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:
85
app/Services/EventJoinTokenService.php
Normal file
85
app/Services/EventJoinTokenService.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Event;
|
||||
use App\Models\EventJoinToken;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class EventJoinTokenService
|
||||
{
|
||||
public function createToken(Event $event, array $attributes = []): EventJoinToken
|
||||
{
|
||||
return DB::transaction(function () use ($event, $attributes) {
|
||||
$tokenValue = $this->generateUniqueToken();
|
||||
|
||||
$payload = [
|
||||
'event_id' => $event->id,
|
||||
'token' => $tokenValue,
|
||||
'label' => Arr::get($attributes, 'label'),
|
||||
'usage_limit' => Arr::get($attributes, 'usage_limit'),
|
||||
'metadata' => Arr::get($attributes, 'metadata', []),
|
||||
];
|
||||
|
||||
if ($expiresAt = Arr::get($attributes, 'expires_at')) {
|
||||
$payload['expires_at'] = $expiresAt instanceof Carbon
|
||||
? $expiresAt
|
||||
: Carbon::parse($expiresAt);
|
||||
}
|
||||
|
||||
if ($createdBy = Arr::get($attributes, 'created_by')) {
|
||||
$payload['created_by'] = $createdBy;
|
||||
}
|
||||
|
||||
return EventJoinToken::create($payload);
|
||||
});
|
||||
}
|
||||
|
||||
public function revoke(EventJoinToken $joinToken, ?string $reason = null): EventJoinToken
|
||||
{
|
||||
$joinToken->revoked_at = now();
|
||||
|
||||
if ($reason) {
|
||||
$metadata = $joinToken->metadata ?? [];
|
||||
$metadata['revoked_reason'] = $reason;
|
||||
$joinToken->metadata = $metadata;
|
||||
}
|
||||
|
||||
$joinToken->save();
|
||||
|
||||
return $joinToken;
|
||||
}
|
||||
|
||||
public function incrementUsage(EventJoinToken $joinToken): void
|
||||
{
|
||||
$joinToken->increment('usage_count');
|
||||
}
|
||||
|
||||
public function findActiveToken(string $token): ?EventJoinToken
|
||||
{
|
||||
return EventJoinToken::query()
|
||||
->where('token', $token)
|
||||
->whereNull('revoked_at')
|
||||
->where(function ($query) {
|
||||
$query->whereNull('expires_at')
|
||||
->orWhere('expires_at', '>', now());
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('usage_limit')
|
||||
->orWhereColumn('usage_limit', '>', 'usage_count');
|
||||
})
|
||||
->first();
|
||||
}
|
||||
|
||||
protected function generateUniqueToken(int $length = 48): string
|
||||
{
|
||||
do {
|
||||
$token = Str::random($length);
|
||||
} while (EventJoinToken::where('token', $token)->exists());
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user