Completed
Push — master ( 1df8b5...490900 )
by Marceau
03:18 queued 02:13
created

ImpersonateManager::getImpersonator()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
3
namespace Lab404\Impersonate\Services;
4
5
use Exception;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Foundation\Application;
8
use Lab404\Impersonate\Events\LeaveImpersonation;
9
use Lab404\Impersonate\Events\TakeImpersonation;
10
11
class ImpersonateManager
12
{
13
    const REMEMBER_PREFIX = 'remember_web';
14
15
    /** @var Application $app */
16
    private $app;
17
18
    /**
19
     * UserFinder constructor.
20
     *
21
     * @param Application $app
22
     */
23
    public function __construct(Application $app)
24
    {
25
        $this->app = $app;
26
    }
27
28
    /**
29
     * @param int $id
30
     * @return  Model
31
     * @throws Exception
32
     */
33
    public function findUserById($id, $guardName = null)
34
    {
35
        if (empty($guardName)) {
36
            $guardName = $this->app['config']->get('auth.default.guard', 'web');
37
        }
38
39
        $userProvider = $this->app['config']->get("auth.guards.$guardName.provider");
40
        $model = $this->app['config']->get("auth.providers.$userProvider.model");
41
42
        if (!$model) {
43
            throw new Exception("Auth guard \"$guardName\" does not exist.");
44
        }
45
46
        /** @var Model $modelInstance */
47
        $modelInstance = call_user_func([
48
            $model,
49
            'findOrFail'
50
        ], $id);
51
52
        return $modelInstance;
53
    }
54
55
    /**
56
     * @return bool
57
     */
58
    public function isImpersonating()
59
    {
60
        return session()->has($this->getSessionKey());
61
    }
62
63
    /**
64
     * @param void
65
     * @return  int|null
66
     */
67
    public function getImpersonatorId()
68
    {
69
        return session($this->getSessionKey(), null);
70
    }
71
72
    /**
73
     * Get impersonator model
74
     *
75
     * @return  Model
76
     */
77
    public function getImpersonator()
78
    {
79
        $id = session($this->getSessionKey(), null);
80
81
        return is_null($id) ? null : $this->findUserById($id);
82
    }
83
  
84
    /**
85
     * @return string|null
86
     */
87
    public function getImpersonatorGuardName()
88
    {
89
        return session($this->getSessionGuard(), null);
90
    }
91
92
    /**
93
     * @return string|null
94
     */
95
    public function getImpersonatorGuardUsingName()
96
    {
97
        return session($this->getSessionGuardUsing(), null);
98
    }
99
100
    /**
101
     * @param Model       $from
102
     * @param Model       $to
103
     * @param string|null $guardName
104
     * @return bool
105
     */
106
    public function take($from, $to, $guardName = null)
107
    {
108
        $this->saveAuthCookieInSession();
109
110
        try {
111
            $currentGuard = $this->getCurrentAuthGuardName();
112
            session()->put($this->getSessionKey(), $from->getKey());
113
            session()->put($this->getSessionGuard(), $currentGuard);
114
            session()->put($this->getSessionGuardUsing(), $guardName);
115
116
            $this->app['auth']->guard($currentGuard)->quietLogout();
117
            $this->app['auth']->guard($guardName)->quietLogin($to);
118
119
        } catch (\Exception $e) {
120
            unset($e);
121
            return false;
122
        }
123
124
        $this->app['events']->dispatch(new TakeImpersonation($from, $to));
125
126
        return true;
127
    }
128
129
    /**
130
     * @return  bool
131
     */
132
    public function leave()
133
    {
134
        try {
135
            $impersonated = $this->app['auth']->guard($this->getImpersonatorGuardUsingName())->user();
136
            $impersonator = $this->findUserById($this->getImpersonatorId(), $this->getImpersonatorGuardName());
137
138
            $this->app['auth']->guard($this->getCurrentAuthGuardName())->quietLogout();
139
            $this->app['auth']->guard($this->getImpersonatorGuardName())->quietLogin($impersonator);
140
141
            $this->extractAuthCookieFromSession();
142
143
            $this->clear();
144
145
        } catch (\Exception $e) {
146
            dump($e->getMessage());
147
            unset($e);
148
            return false;
149
        }
150
151
        $this->app['events']->dispatch(new LeaveImpersonation($impersonator, $impersonated));
152
153
        return true;
154
    }
155
156
    /**
157
     * @return void
158
     */
159
    public function clear()
160
    {
161
        session()->forget($this->getSessionKey());
162
        session()->forget($this->getSessionGuard());
163
        session()->forget($this->getSessionGuardUsing());
164
    }
165
166
    /**
167
     * @return string
168
     */
169
    public function getSessionKey()
170
    {
171
        return config('laravel-impersonate.session_key');
172
    }
173
174
    /**
175
     * @return string
176
     */
177
    public function getSessionGuard()
178
    {
179
        return config('laravel-impersonate.session_guard');
180
    }
181
182
    /**
183
     * @return string
184
     */
185
    public function getSessionGuardUsing()
186
    {
187
        return config('laravel-impersonate.session_guard_using');
188
    }
189
190
    /**
191
     * @return string
192
     */
193
    public function getDefaultSessionGuard()
194
    {
195
        return config('laravel-impersonate.default_impersonator_guard');
196
    }
197
198
    /**
199
     * @return  string
200
     */
201
    public function getTakeRedirectTo()
202
    {
203
        try {
204
            $uri = route(config('laravel-impersonate.take_redirect_to'));
205
        } catch (\InvalidArgumentException $e) {
206
            $uri = config('laravel-impersonate.take_redirect_to');
207
        }
208
209
        return $uri;
210
    }
211
212
    /**
213
     * @return  string
214
     */
215
    public function getLeaveRedirectTo()
216
    {
217
        try {
218
            $uri = route(config('laravel-impersonate.leave_redirect_to'));
219
        } catch (\InvalidArgumentException $e) {
220
            $uri = config('laravel-impersonate.leave_redirect_to');
221
        }
222
223
        return $uri;
224
    }
225
226
    /**
227
     * @return array
228
     */
229
    public function getCurrentAuthGuardName()
230
    {
231
        $guards = array_keys(config('auth.guards'));
232
        foreach ($guards as $guard) {
233
            if ($this->app['auth']->guard($guard)->check()) {
234
                return $guard;
235
            }
236
        }
237
        return null;
238
    }
239
240
    /**
241
     * @return void
242
     */
243
    protected function saveAuthCookieInSession()
244
    {
245
        $cookie = $this->findByKeyInArray($this->app['request']->cookies->all(), static::REMEMBER_PREFIX);
246
        $key = $cookie->keys()->first();
247
        $val = $cookie->values()->first();
248
249
        if (!$key || !$val) {
250
            return;
251
        }
252
253
        session()->put(static::REMEMBER_PREFIX, [
254
            $key,
255
            $val,
256
        ]);
257
    }
258
259
    /**
260
     * @return void
261
     */
262
    protected function extractAuthCookieFromSession()
263
    {
264
        if (!$session = $this->findByKeyInArray(session()->all(), static::REMEMBER_PREFIX)->first()) {
265
            return;
266
        }
267
268
        $this->app['cookie']->queue($session[0], $session[1]);
269
        session()->forget($session);
270
    }
271
272
    /**
273
     * @param array  $values
274
     * @param string $search
275
     * @return \Illuminate\Support\Collection
276
     */
277
    protected function findByKeyInArray(array $values, string $search)
278
    {
279
        return collect($values ?? session()->all())
280
            ->filter(function ($val, $key) use ($search) {
281
                return strpos($key, $search) !== false;
282
            });
283
    }
284
}
285