user(); if (! $admin->can('impersonate.user', $target)) { return $this->error('Anda tidak mempunyai keizinan untuk menyamar pengguna.', 403); } if ($request->hasCookie(AuthCookie::originalUserCookieName())) { return $this->error('Anda sudah menyamar sebagai pengguna.', 400); } $issued = $this->issueToken($target, self::IMPERSONATION_TOKEN); return AuthCookie::attachAuthToken( response()->json([ 'success' => true, 'message' => "Anda sekarang menyamar sebagai {$target->name}", 'impersonated_user' => $this->userSummary($target), ...$this->sessionPayload($target, $issued['accessToken']), ]), $issued['plainTextToken'] )->withCookie(AuthCookie::makeOriginalUserId($admin->id)); } public function leave(Request $request): JsonResponse { $originalUserId = $request->cookie(AuthCookie::originalUserCookieName()); if (! $originalUserId) { return $this->error('Maklumat pengguna asal tidak ditemui.', 400); } $original = User::findOrFail($originalUserId); $request->user()?->tokens()->where('name', self::IMPERSONATION_TOKEN)->delete(); $original->tokens()->whereIn('name', [self::IMPERSONATION_TOKEN, ...self::AUTH_TOKEN_NAMES])->delete(); $issued = $this->issueToken($original, 'auth-token', expires: true); $response = response()->json([ 'success' => true, 'message' => 'Anda telah kembali ke akaun anda', 'original_user' => $this->userSummary($original), ...$this->sessionPayload($original, $issued['accessToken']), ]); if (AuthCookie::shouldExposeTokenInResponse()) { $response->setData(array_merge($response->getData(true), [ 'original_token' => $issued['plainTextToken'], ])); } return AuthCookie::attachAuthToken($response, $issued['plainTextToken']) ->withCookie(AuthCookie::forgetOriginalUserId()); } public function status(Request $request): JsonResponse { if (! $request->hasCookie(AuthCookie::originalUserCookieName())) { return response()->json(['is_impersonating' => false]); } $user = $request->user(); return response()->json([ 'is_impersonating' => true, 'impersonated_user' => $user ? $this->userSummary($user) : null, ]); } /** * @return array{plainTextToken: string, accessToken: PersonalAccessToken} */ private function issueToken(User $user, string $name, bool $expires = false): array { $user->loadMissing(['roles.permissions']); $result = $user->createToken( $name, ['*'], $expires ? now()->addMinutes((int) config('auth_cookie.lifetime_minutes', 720)) : null ); ActiveRoleService::assignDefaultToToken($user, $result->accessToken); return [ 'plainTextToken' => $result->plainTextToken, 'accessToken' => $result->accessToken, ]; } /** * @return array */ private function sessionPayload(User $user, PersonalAccessToken $accessToken): array { $user->loadMissing(['roles.permissions']); $activeRole = $user->roles->firstWhere('id', $accessToken->active_role_id) ?? ActiveRoleService::resolveDefaultRole($user); return [ 'data' => new UserResource($user), 'active_role' => ActiveRoleService::formatRole($activeRole), 'can_switch_role' => $user->roles->count() > 1, 'redirect_path' => $activeRole ? ActiveRoleService::redirectPathForRole($activeRole) : config('active_role.member_redirect', '/profile'), ]; } /** * @return array{id: mixed, name: string, email: string} */ private function userSummary(User $user): array { return [ 'id' => $user->id, 'name' => $user->name, 'email' => $user->email, ]; } private function error(string $message, int $status): JsonResponse { return response()->json([ 'success' => false, 'message' => $message, ], $status); } }