b05e074456
Co-authored-by: ISMAIL MASSERAN <topaz@ISMAILs-Macbook.local> Co-authored-by: ISMAIL MASSERAN <topaz@Mac.dlinkrouter.local> Reviewed-on: #11
144 lines
4.4 KiB
PHP
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,
|
|
);
|
|
}
|
|
}
|
|
}
|