presseportale/app/Services/Auth/MagicLinkGenerator.php
Kevin Adametz 5b8bdf4182
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
12-05-2026 Frontend dev
2026-05-12 18:32:33 +02:00

75 lines
2.3 KiB
PHP

<?php
namespace App\Services\Auth;
use App\Models\MagicLink;
use App\Models\PressRelease;
use App\Models\User;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
class MagicLinkGenerator
{
/**
* @return array{magic_link: MagicLink, plain_token: string, expires_at: Carbon}
*/
public function createLoginLink(User $user, ?string $requestedIp = null, int $ttlMinutes = 15): array
{
$plainToken = Str::random(64);
$tokenHash = hash('sha256', $plainToken);
$expiresAt = now()->addMinutes($ttlMinutes);
MagicLink::query()
->where('user_id', $user->id)
->where('purpose', 'login')
->whereNull('consumed_at')
->update([
'consumed_at' => now(),
'ip_consumed' => $requestedIp,
]);
$magicLink = $user->magicLinks()->create([
'token_hash' => $tokenHash,
'purpose' => 'login',
'expires_at' => $expiresAt,
'ip_requested' => $requestedIp,
]);
return [
'magic_link' => $magicLink,
'plain_token' => $plainToken,
'expires_at' => $expiresAt,
];
}
/**
* Public read-only share link for a press release. Token holder can view
* the press release in any state (draft/review/rejected/published) until
* the link expires. Default TTL: 7 days.
*
* @return array{magic_link: MagicLink, plain_token: string, url: string, expires_at: Carbon}
*/
public function createPressReleaseShareLink(PressRelease $pressRelease, ?User $issuer = null, int $ttlDays = 7): array
{
$plainToken = Str::random(64);
$tokenHash = hash('sha256', $plainToken);
$expiresAt = now()->addDays($ttlDays);
$magicLink = MagicLink::query()->create([
'user_id' => $issuer?->id ?? $pressRelease->user_id,
'token_hash' => $tokenHash,
'purpose' => 'press_release_access',
'payload' => [
'press_release_id' => $pressRelease->id,
],
'expires_at' => $expiresAt,
]);
return [
'magic_link' => $magicLink,
'plain_token' => $plainToken,
'url' => route('press-releases.preview', ['token' => $plainToken]),
'expires_at' => $expiresAt,
];
}
}