Completed
Push — master ( 5d204a...db0ea1 )
by Peter
02:29
created

SessionTimeout::updateActivityCounter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 5
Ratio 62.5 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 5
loc 8
ccs 6
cts 6
cp 1
rs 9.4285
cc 2
eloc 5
nc 2
nop 1
crap 2
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\Http\Request;
9
use Illuminate\Session\Store as Session;
10
11
class SessionTimeout
12
{
13
    protected $session;
14
15
    protected $timeout;
16
17
    protected $login;
18
19
    protected $logout;
20
21
    protected $auth;
22
23 25
    public function __construct(Session $session, Config $config, Auth $auth)
24
    {
25 25
        $this->session = $session;
26
27 25
        $this->timeout = $config->get('session.lifetime') * 60;
28
29 25
        $this->login = $config->get('liveorletdie.login', 'login');
30 25
        $this->logout = $config->get('liveorletdie.logout', 'logout');
31
32 25
        $this->auth = $auth;
33 25
    }
34
35
    /**
36
     * Handle an incoming request.
37
     *
38
     * @param  \Illuminate\Http\Request  $request
39
     * @param  \Closure  $next
40
     * @return mixed
41
     */
42 25
    public function handle(Request $request, Closure $next)
43
    {
44
        // don't interfere with normal logout requests
45 25
        if ($request->is($this->logout)) {
46 3
            $this->session->forget('last_activity');
47 3
            return $next($request);
48
        }
49
50
        // check if we should the authenticated session to end
51
        // and if yes, terminate it
52 22
        if ($this->endSession($request)) {
53 15
            return $this->terminateAndRespond($request, $next);
54
        }
55
56
        // if we just want the time remaining claculate and return that
57
        // this will stop any further processing, including preventing unintended extension of the underlying session
58 7
        if ($request->is('session/remaining')) {
59 1
            return response($this->timeout - (time() - $this->session->get('last_activity')));
60
        }
61
62
        // for all other requests, including pings to extend the session, we update our timer and continue normally
63 6
        $this->session->put('last_activity', time());
64
65 6
        $response = $next($request);
66
67 6
        $this->afterRequest($request);
68
69 6
        return $response;
70
    }
71
72
    /**
73
     * Determine whether the session should be ended due to timeout or frontend request
74
     * We whitelist the login page from this assessment
75
     *
76
     * @param  \Illuminate\Http\Request $request
77
     * @return boolean 
78
     */
79 22
    protected function endSession(Request $request)
80
    {
81 22
        return !$request->is($this->login) && ($this->timedOut() || $request->is('session/end'));
82
    }
83
84
    /**
85
     * Determine whether timeout has occurred or been forced by other activity on the site
86
     * If there's no data to do the timeout check, then we assume the session has been otherwise ended
87
     *
88
     * @return boolean 
89
     */
90 18
    protected function timedOut()
91
    {
92 18
        return !$this->session->has('last_activity') || (time() - $this->session->get('last_activity')) > $this->timeout || $this->auth->guest();
93
    }
94
95
    /**
96
     * Logout and clear our the last_activity timer - one or both of which actions may be redundant, but not harmful
97
     * Then, for our package routes, compose a suitable response, and for other routes continue processing as normal
98
     *
99
     * @param  \Illuminate\Http\Request  $request
100
     * @param  Closure  $next
101
     * @return mixed
102
     */
103 15
    protected function terminateAndRespond(Request $request, Closure $next)
104
    {
105 15
        $this->auth->logout();
106 15
        $this->session->forget('last_activity');
107
108 15
        if ($request->is('session/end')) {
109 4
            return response('session ended', 200);
110
        }
111
112 11
        if ($request->is('session/remaining')) {
113 3
            return response(0, 200);
114
        }
115
116 8
        if ($request->is('session/ping')) {
117 3
            return response('trying to keep alive a session that has already expired', 400);
118
        }
119
120 5
        return $next($request);
121
    }
122
123
    /**
124
     * After the request has been processed, check if it was for actually
125
     * logging in and if not, i.e. redirect ot login page only, unset the
126
     * last_activity timer.
127
     *
128
     * @param  \Illuminate\Http\Request  $request
129
     * @return void
130
     */
131 6
    protected function afterRequest(Request $request)
132
    {
133 6
        if ($request->is($this->login) && $this->auth->guest()) {
134 3
            $this->session->forget('last_activity');
135 3
        }
136 6
    }
137
}
138