Files
My-KOPKB/be/Modules/ExternalSystem/Services/ExternalSystemLaunchService.php
T
ismailmasseran b05e074456 Feature/phone register (#11)
Co-authored-by: ISMAIL MASSERAN <topaz@ISMAILs-Macbook.local>
Co-authored-by: ISMAIL MASSERAN <topaz@Mac.dlinkrouter.local>
Reviewed-on: #11
2026-07-14 12:03:22 +08:00

144 lines
4.4 KiB
PHP

<?php
namespace Modules\ExternalSystem\Services;
use Illuminate\Support\Str;
use Modules\Auth\Entities\User;
use Modules\ExternalSystem\Entities\ExternalSystem;
use Modules\ExternalSystem\Exceptions\ExternalSystemLaunchException;
use Modules\ExternalSystem\Support\JwtSigner;
class ExternalSystemLaunchService
{
/**
* @return array{launch_url: string, expires_at: string}
*/
public function launch(User $user, string $code): array
{
$system = $this->resolveSystem($code);
$this->assertSystemAvailable($system);
$this->assertUserEligible($user, $system);
if (! $system->sso_enabled) {
throw new ExternalSystemLaunchException(
'Sistem luaran tidak menyokong SSO.',
'external_system_sso_disabled',
422,
);
}
if (blank($system->sso_secret)) {
throw new ExternalSystemLaunchException(
'Sistem luaran belum dikonfigurasi untuk SSO.',
'external_system_sso_not_configured',
503,
);
}
$ttl = $system->sso_token_ttl ?: 120;
$issuedAt = now();
$expiresAt = $issuedAt->copy()->addSeconds($ttl);
$payload = [
'iss' => config('externalsystem.issuer', config('app.name', 'mykopkb')),
'aud' => $system->sso_audience ?: $system->code,
'sub' => $user->id,
'jti' => (string) Str::uuid(),
'iat' => $issuedAt->timestamp,
'nbf' => $issuedAt->timestamp,
'exp' => $expiresAt->timestamp,
'ic_number' => $user->ic_number,
'member_number' => $user->member_number,
];
$token = JwtSigner::sign($payload, $system->sso_secret);
$launchPath = $system->sso_launch_path ?: '/sso/login';
$launchUrl = rtrim($system->url, '/').'/'.ltrim($launchPath, '/');
$launchUrl .= '?token='.urlencode($token);
return [
'launch_url' => $launchUrl,
'expires_at' => $expiresAt->toIso8601String(),
];
}
protected function resolveSystem(string $code): ExternalSystem
{
$system = ExternalSystem::query()->where('code', $code)->first();
if (! $system) {
throw new ExternalSystemLaunchException(
'Sistem luaran tidak dijumpai.',
'external_system_not_found',
404,
);
}
return $system;
}
protected function assertSystemAvailable(ExternalSystem $system): void
{
if (! $system->is_active) {
throw new ExternalSystemLaunchException(
'Sistem luaran tidak aktif.',
'external_system_inactive',
403,
);
}
$now = now();
if ($system->starts_at?->isAfter($now)) {
throw new ExternalSystemLaunchException(
'Sistem luaran belum tersedia.',
'external_system_upcoming',
403,
);
}
if ($system->ends_at?->isBefore($now)) {
throw new ExternalSystemLaunchException(
'Tempoh akses sistem luaran telah tamat.',
'external_system_ended',
403,
);
}
}
protected function assertUserEligible(User $user, ExternalSystem $system): void
{
if ($user->status !== 'active') {
throw new ExternalSystemLaunchException(
'Hanya anggota aktif boleh membuka sistem luaran.',
'external_system_user_inactive',
403,
);
}
if (blank($user->ic_number)) {
throw new ExternalSystemLaunchException(
'Nombor kad pengenalan diperlukan sebelum membuka sistem luaran.',
'external_system_ic_required',
422,
);
}
if (blank($user->member_number)) {
throw new ExternalSystemLaunchException(
'Nombor anggota diperlukan sebelum membuka sistem luaran.',
'external_system_member_number_required',
422,
);
}
if ($system->require_onboarding && blank($user->onboarding_completed_at)) {
throw new ExternalSystemLaunchException(
'Sila lengkapkan profil anda sebelum membuka sistem luaran.',
'external_system_profile_incomplete',
422,
);
}
}
}