Passed
Push — master ( 759454...136eb9 )
by Peter
02:28
created

SessionTimeout::afterRequest()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 3
Ratio 50 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 3
loc 6
rs 9.4285
cc 3
eloc 3
nc 2
nop 1
1
<?php
2
3
namespace PeterColes\LiveOrLetDie\Middleware;
4
5
use Closure;
6
use Illuminate\Config\Repository as Config;
7
use Illuminate\Auth\AuthManager as Auth;
8
use Illuminate\Session\Store as Session;
9
10
class SessionTimeout
11
{
12
    protected $session;
13
14
    protected $timeout;
15
16
    protected $login;
17
18
    protected $logout;
19
20
    protected $auth;
21
22
    public function __construct(Session $session, Config $config, Auth $auth)
23
    {
24
        $this->session = $session;
25
26
        $this->timeout = $config->get('session.lifetime') * 60;
27
28
        $this->login = $config->get('liveorletdie.login', 'login');
29
        $this->logout = $config->get('liveorletdie.logout', 'logout');
30
31
        $this->auth = $auth;
32
    }
33
34
    /**
35
     * Handle an incoming request.
36
     *
37
     * @param  \Illuminate\Http\Request  $request
38
     * @param  \Closure  $next
39
     * @return mixed
40
     */
41
    public function handle($request, Closure $next)
42
    {
43
        // don't interfere with normal logout requests
44
        if ($request->is($this->logout)) {
45
            $this->session->forget('last_activity');
46
            return $next($request);
47
        }
48
49
        // check if we should the authenticated session to end
50
        // and if yes, terminate it
51
        if ($this->endSession($request)) {
52
            return $this->terminateAndRespond($request, $next);
53
        }
54
55
        // if we just want the time remaining claculate and return that
56
        // this will stop any further processing, including preventing unintended extension of the underlying session
57
        if ($request->is('session/remaining')) {
58
            return response($this->timeout - (time() - $this->session->get('last_activity')));
59
        }
60
61
        // for all other requests, including pings to extend the session, we update our timer and continue normally
62
        $this->updateActivityCounter($request);
63
64
        $response = $next($request);
65
66
        $this->afterRequest($request);
67
68
        return $response;
69
    }
70
71
    /**
72
     * After the request has been processed, check if it was for login
73
     * and if so and successful initialise the last_activity timer
74
     *
75
     * @param  \Illuminate\Http\Request  $request
76
     * @return void
77
     */
78
    protected function afterRequest($request)
79
    {
80 View Code Duplication
        if ($request->is($this->login) && !$this->auth->guest()) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
81
            $this->session->put('last_activity', time());
82
        }
83
    }
84
85
    /**
86
     * Determine whether the session should be ended due to timeout or frontend request
87
     * We whitelist the login page from this assessment
88
     *
89
     * @param  \Illuminate\Http\Request $request
90
     * @return boolean 
91
     */
92
    protected function endSession($request)
93
    {
94
        return !$request->is($this->login) && ($this->timedOut() || $request->is('session/end'));
95
    }
96
97
    /**
98
     * Determine whether timeout has occurred or been forced by other activity on the site
99
     * If there's no data to do the timeout check, then we assume the session has been otherwise ended
100
     *
101
     * @return boolean 
102
     */
103
    protected function timedOut()
104
    {
105
        return !$this->session->has('last_activity') || (time() - $this->session->get('last_activity')) > $this->timeout || $this->auth->guest();
106
    }
107
108
    /**
109
     * Logout and clear our session var - one or both of which may be redundant, but not harmful
110
     * Then, for our package routes compose a suitable response, anf for other routes continue processing as normal
111
     *
112
     * @param  \Illuminate\Http\Request  $request
113
     * @param  Closure  $next
114
     * @return mixed
115
     */
116
    protected function terminateAndRespond($request, $next)
117
    {
118
        $this->auth->logout();
119
        $this->session->forget('last_activity');
120
121
        if ($request->is('session/end')) {
122
            return response('session ended', 200);
123
        }
124
125
        if ($request->is('session/remaining')) {
126
            return response(0, 200);
127
        }
128
129
        if ($request->is('session/ping')) {
130
            return response('trying to keep alive a session that has already expired', 400);
131
        }
132
133
        return $next($request);
134
    }
135
136
    /**
137
     * Update the counter 
138
     * Normally we wouldn't get here unless we are logged in
139
     * But we whitelisted the login page so need to handle that
140
     *
141
     * @param  \Illuminate\Http\Request  $request
142
     * @return void
143
     */
144
    protected function updateActivityCounter($request)
145
    {
146 View Code Duplication
        if ($request->is($this->login)) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
147
            $this->session->forget('last_activity');
148
        } else {
149
            $this->session->put('last_activity', time());
150
        }
151
    }
152
}
153