update controllers logic
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Auth;
|
||||
|
||||
use App\Models\Configuration;
|
||||
use App\Services\ApplicationUrlService;
|
||||
use App\Models\LoginActivity;
|
||||
use App\Models\Preferences;
|
||||
use App\Models\Role;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* CodeIgniter `AuthController` web (session) flow: session keys, dashboards, redirects, preferences.
|
||||
*/
|
||||
class AuthSessionService
|
||||
{
|
||||
private const FALLBACK_DASHBOARD = '/landing_page/guest_dashboard';
|
||||
|
||||
public function __construct(
|
||||
private ApplicationUrlService $urls,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Same-host relative redirect sanitization as CI `sanitizeRedirectTarget`.
|
||||
*/
|
||||
public function sanitizeRedirectTarget(string $redirectTo): ?string
|
||||
{
|
||||
$redirectTo = trim($redirectTo);
|
||||
if ($redirectTo === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (preg_match('#^https?://#i', $redirectTo)) {
|
||||
$appHost = (string) parse_url($this->urls->docsHomeUrl(), PHP_URL_HOST);
|
||||
$targetHost = (string) parse_url($redirectTo, PHP_URL_HOST);
|
||||
$targetPath = (string) parse_url($redirectTo, PHP_URL_PATH);
|
||||
$targetQuery = (string) parse_url($redirectTo, PHP_URL_QUERY);
|
||||
|
||||
if ($appHost === '' || $targetHost === '' || strcasecmp($appHost, $targetHost) !== 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$redirectTo = $targetPath !== '' ? $targetPath : '/';
|
||||
if ($targetQuery !== '') {
|
||||
$redirectTo .= '?'.$targetQuery;
|
||||
}
|
||||
}
|
||||
|
||||
if (! str_starts_with($redirectTo, '/')) {
|
||||
$redirectTo = '/'.ltrim($redirectTo, '/');
|
||||
}
|
||||
|
||||
if (str_starts_with($redirectTo, '//')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $redirectTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Highest-priority dashboard route matching any of the role names/slugs.
|
||||
*
|
||||
* @param list<string> $roleNames
|
||||
*/
|
||||
public function dashboardRouteForRoles(array $roleNames): string
|
||||
{
|
||||
if ($roleNames === []) {
|
||||
return self::FALLBACK_DASHBOARD;
|
||||
}
|
||||
|
||||
$rows = Role::findByNamesOrSlugs($roleNames);
|
||||
if ($rows !== []) {
|
||||
$route = $rows[0]->dashboard_route ?? null;
|
||||
if (is_string($route) && $route !== '') {
|
||||
return $route;
|
||||
}
|
||||
}
|
||||
|
||||
return self::FALLBACK_DASHBOARD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply CI-style preference keys into session (style/menu colors).
|
||||
*/
|
||||
public function applyStylePreferencesToSession(int $userId): void
|
||||
{
|
||||
if ($userId <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$prefs = Preferences::query()->where('user_id', $userId)->first();
|
||||
if (! $prefs) {
|
||||
return;
|
||||
}
|
||||
|
||||
$styleColor = (string) ($prefs->style_color ?? '');
|
||||
if ($styleColor !== '') {
|
||||
session()->put('style_color', $styleColor);
|
||||
}
|
||||
|
||||
$menuColor = (string) ($prefs->menu_color ?? '');
|
||||
if ($menuColor === 'custom') {
|
||||
session()->put('menu_color', 'custom');
|
||||
session()->put('menu_custom_bg', (string) ($prefs->menu_custom_bg ?? '#0f172a'));
|
||||
session()->put('menu_custom_text', (string) ($prefs->menu_custom_text ?? '#ffffff'));
|
||||
session()->put('menu_custom_mode', (string) ($prefs->menu_custom_mode ?? 'dark'));
|
||||
} elseif ($menuColor !== '') {
|
||||
session()->put('menu_color', $menuColor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate Laravel web auth + CI-compatible session keys.
|
||||
*
|
||||
* @param list<string> $roleNames
|
||||
*/
|
||||
public function writeCiAuthenticatedSession(User $user, array $roleNames): void
|
||||
{
|
||||
Auth::guard('web')->login($user);
|
||||
|
||||
$schoolYear = Configuration::getConfig('school_year');
|
||||
$semester = Configuration::getConfig('semester');
|
||||
|
||||
session([
|
||||
'user_id' => $user->id,
|
||||
'user_email' => $user->email,
|
||||
'user_name' => trim(($user->firstname ?? '').' '.($user->lastname ?? '')),
|
||||
'user_type' => $user->user_type ?? null,
|
||||
'is_logged_in' => true,
|
||||
'login_time' => time(),
|
||||
'last_activity' => time(),
|
||||
'roles' => $roleNames,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
]);
|
||||
|
||||
$this->applyStylePreferencesToSession((int) $user->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close open login_activity row(s) without logout_time for this user (CI parity).
|
||||
*/
|
||||
public function logLogout(?int $userId, ?string $email): void
|
||||
{
|
||||
if (! $userId || ! $email) {
|
||||
return;
|
||||
}
|
||||
|
||||
LoginActivity::query()
|
||||
->where('user_id', $userId)
|
||||
->whereNull('logout_time')
|
||||
->update([
|
||||
'logout_time' => utc_now(),
|
||||
'email' => $email,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine next navigation after credentials validated (single vs multi-role).
|
||||
*
|
||||
* @return array{kind: string, redirect_url?: string|null, roles?: array<int, string>, reason?: string}
|
||||
*/
|
||||
public function resolvePostLoginDestination(User $user, ?string $sanitizedRedirect): array
|
||||
{
|
||||
$roleNames = $user->roleNamesLikeCodeIgniter();
|
||||
|
||||
if ($roleNames === []) {
|
||||
Log::notice('session_login: user has no roles', ['user_id' => $user->id]);
|
||||
|
||||
return [
|
||||
'kind' => 'no_roles',
|
||||
'reason' => 'Role not assigned. Please contact support.',
|
||||
];
|
||||
}
|
||||
|
||||
$this->writeCiAuthenticatedSession($user, $roleNames);
|
||||
|
||||
if (count($roleNames) === 1) {
|
||||
session()->put('role', $roleNames[0]);
|
||||
if ($sanitizedRedirect !== null) {
|
||||
return ['kind' => 'redirect', 'redirect_url' => $sanitizedRedirect];
|
||||
}
|
||||
|
||||
return [
|
||||
'kind' => 'redirect',
|
||||
'redirect_url' => $this->dashboardRouteForRoles([$roleNames[0]]),
|
||||
];
|
||||
}
|
||||
|
||||
if ($sanitizedRedirect !== null) {
|
||||
session()->put('post_login_redirect', $sanitizedRedirect);
|
||||
} else {
|
||||
session()->forget('post_login_redirect');
|
||||
}
|
||||
|
||||
return [
|
||||
'kind' => 'select_role',
|
||||
'roles' => array_values($roleNames),
|
||||
'redirect_url' => $this->urls->webSelectRoleUrl(false),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user