Skip to content

Commit 54f15d3

Browse files
final commit
1 parent 72f18b8 commit 54f15d3

File tree

5 files changed

+83
-52
lines changed

5 files changed

+83
-52
lines changed

config/mirror.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,17 @@
4040

4141
'ttl' => null,
4242

43+
/*
44+
|--------------------------------------------------------------------------
45+
| Default Redirect URL
46+
|--------------------------------------------------------------------------
47+
|
48+
| The default URL to redirect to when the TTL middleware expires a session
49+
| and no leave redirect URL was specified. This allows you to customize
50+
| where users are sent after an automatic session expiration.
51+
|
52+
*/
53+
54+
'default_redirect_url' => '/',
55+
4356
];

src/Http/Middleware/CheckImpersonationTtl.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public function handle(Request $request, Closure $next): Response
3131
$ttl = $this->config->get('mirror.ttl');
3232

3333
if ($this->impersonationSession->isExpired($ttl)) {
34-
$redirectUrl = Mirror::getLeaveRedirectUrl() ?? '/';
34+
$redirectUrl = Mirror::getLeaveRedirectUrl() ?? $this->config->get('mirror.default_redirect_url', '/');
3535

3636
Mirror::forceStop();
3737

src/ImpersonationSession.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ public function clear(): void
144144
*/
145145
public function generateIntegrityHash(): self
146146
{
147-
$data = $this->getDataForHash();
148-
$hash = hash_hmac('sha256', $data, $this->appKey);
147+
$payload = $this->buildIntegrityPayload();
148+
$hash = hash_hmac('sha256', $payload, $this->appKey);
149149

150150
$this->session->put(self::INTEGRITY_KEY, $hash);
151151

@@ -171,7 +171,7 @@ public function verifyIntegrity(): void
171171
throw TamperedSessionException::detected();
172172
}
173173

174-
$expectedHash = hash_hmac('sha256', $this->getDataForHash(), $this->appKey);
174+
$expectedHash = hash_hmac('sha256', $this->buildIntegrityPayload(), $this->appKey);
175175

176176
if (! hash_equals($storedHash, $expectedHash)) {
177177
$this->clear();
@@ -181,16 +181,16 @@ public function verifyIntegrity(): void
181181
}
182182

183183
/**
184-
* Get the data string used for hash generation.
184+
* Build the payload for integrity hash verification.
185185
*/
186-
protected function getDataForHash(): string
186+
protected function buildIntegrityPayload(): string
187187
{
188-
return implode('|', [
189-
$this->getImpersonator() ?? '',
190-
$this->getGuardName() ?? '',
191-
$this->getStartedAt() ?? '',
192-
$this->getLeaveRedirectUrl() ?? '',
193-
]);
188+
return json_encode([
189+
'impersonator' => $this->getImpersonator(),
190+
'guard_name' => $this->getGuardName(),
191+
'started_at' => $this->getStartedAt(),
192+
'leave_redirect_url' => $this->getLeaveRedirectUrl(),
193+
], JSON_THROW_ON_ERROR);
194194
}
195195

196196
/**

src/Impersonator.php

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ protected function getCurrentGuardName(): string
3939
}
4040

4141
/**
42-
* Get the user model class.
42+
* Get the authenticatable class name.
4343
*/
44-
protected function getUserModel(): string
44+
protected function getAuthenticatableClass(): string
4545
{
4646
$defaultGuard = $this->config->get('auth.defaults.guard');
4747
$guardProvider = $this->config->get(sprintf('auth.guards.%s.provider', $defaultGuard));
@@ -155,9 +155,9 @@ public function getImpersonator(): ?Authenticatable
155155
return null;
156156
}
157157

158-
$model = $this->getUserModel();
158+
$class = $this->getAuthenticatableClass();
159159

160-
return $model::find($impersonatorId);
160+
return $class::find($impersonatorId);
161161
}
162162

163163
/**
@@ -168,8 +168,9 @@ public function getImpersonator(): ?Authenticatable
168168
*/
169169
public function startByKey(int|string $key, ?string $leaveRedirectUrl = null, ?string $startRedirectUrl = null): ?string
170170
{
171-
$model = $this->getUserModel();
172-
$user = $model::find($key);
171+
$class = $this->getAuthenticatableClass();
172+
173+
$user = $class::find($key);
173174

174175
if (! $user) {
175176
throw new \InvalidArgumentException(sprintf('User with key [%s] not found.', $key));
@@ -186,8 +187,9 @@ public function startByKey(int|string $key, ?string $leaveRedirectUrl = null, ?s
186187
*/
187188
public function startByEmail(string $email, ?string $leaveRedirectUrl = null, ?string $startRedirectUrl = null): ?string
188189
{
189-
$model = $this->getUserModel();
190-
$user = $model::where('email', $email)->first();
190+
$class = $this->getAuthenticatableClass();
191+
192+
$user = $class::query()->where('email', $email)->first();
191193

192194
if (! $user) {
193195
throw new \InvalidArgumentException(sprintf('User with email [%s] not found.', $email));
@@ -307,7 +309,7 @@ protected function ensureNotExpired(): void
307309
*/
308310
protected function ensureCanImpersonate(?Authenticatable $impersonator): void
309311
{
310-
if (! $impersonator instanceof \Illuminate\Contracts\Auth\Authenticatable) {
312+
if (! $impersonator instanceof Authenticatable) {
311313
throw ImpersonationException::cannotImpersonate();
312314
}
313315

src/MirrorServiceProvider.php

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -65,40 +65,56 @@ protected function registerMiddlewares(): void
6565
*/
6666
protected function registerBladeDirectives(): void
6767
{
68-
Blade::if('impersonating', function (?string $guard = null): bool {
69-
if ($guard !== null) {
70-
return session()->has('mirror.impersonating') && session('mirror.guard_name') === $guard;
71-
}
68+
Blade::if('impersonating', fn (?string $guard = null): bool => $this->checkImpersonating($guard));
69+
Blade::if('canImpersonate', fn (?string $guard = null): bool => $this->checkCanImpersonate($guard));
70+
Blade::if('canBeImpersonated', fn (?Authenticatable $user = null, ?string $guard = null): bool => $this->checkCanBeImpersonated($user, $guard));
71+
}
72+
73+
/**
74+
* Check if the authenticated model is impersonating.
75+
*/
76+
protected function checkImpersonating(?string $guard): bool
77+
{
78+
if ($guard !== null) {
79+
return session()->has('mirror.impersonating') && session('mirror.guard_name') === $guard;
80+
}
7281

73-
return Mirror::isImpersonating();
74-
});
82+
return Mirror::isImpersonating();
83+
}
84+
85+
/**
86+
* Check if the authenticated model can impersonate.
87+
*/
88+
protected function checkCanImpersonate(?string $guard): bool
89+
{
90+
$user = auth($guard)->user();
7591

76-
Blade::if('canImpersonate', function (?string $guard = null): bool {
92+
if (! $user) {
93+
return false;
94+
}
95+
96+
// @phpstan-ignore-next-line function.alreadyNarrowedType
97+
return method_exists($user, 'canImpersonate')
98+
? $user->canImpersonate()
99+
: true;
100+
}
101+
102+
/**
103+
* Check if the authenticated model can be impersonated.
104+
*/
105+
protected function checkCanBeImpersonated(?Authenticatable $user, ?string $guard): bool
106+
{
107+
if (! $user instanceof Authenticatable) {
77108
$user = auth($guard)->user();
109+
}
110+
111+
if (! $user) {
112+
return false;
113+
}
78114

79-
if (! $user) {
80-
return false;
81-
}
82-
83-
// @phpstan-ignore-next-line function.alreadyNarrowedType
84-
return method_exists($user, 'canImpersonate')
85-
? $user->canImpersonate()
86-
: true;
87-
});
88-
89-
Blade::if('canBeImpersonated', function ($user = null, ?string $guard = null): bool {
90-
if ($user === null) {
91-
$user = auth($guard)->user();
92-
}
93-
94-
if (! $user instanceof Authenticatable) {
95-
return false;
96-
}
97-
98-
// @phpstan-ignore-next-line function.alreadyNarrowedType
99-
return method_exists($user, 'canBeImpersonated')
100-
? $user->canBeImpersonated()
101-
: true;
102-
});
115+
// @phpstan-ignore-next-line function.alreadyNarrowedType
116+
return method_exists($user, 'canBeImpersonated')
117+
? $user->canBeImpersonated()
118+
: true;
103119
}
104120
}

0 commit comments

Comments
 (0)