Completed
Push — master ( 9771ef...d8f002 )
by Peter
02:21
created

SessionTimeout::authenticating()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 2
eloc 2
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 27
    public function __construct(Session $session, Config $config, Auth $auth)
24
    {
25 27
        $this->session = $session;
26
27 27
        $this->timeout = $config->get('session.lifetime') * 60;
28
29 27
        $this->login = $config->get('liveorletdie.login', 'login');
30 27
        $this->logout = $config->get('liveorletdie.logout', 'logout');
31
32 27
        $this->auth = $auth;
33 27
    }
34
35
    /**
36
     * Handle an incoming request.
37
     *
38
     * @param  \Illuminate\Http\Request  $request
39
     * @param  \Closure  $next
40
     * @return mixed
41
     */
42 27
    public function handle(Request $request, Closure $next)
43
    {
44
        // don't interfere with normal logout requests
45 27
        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 24
        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 9
        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 8
        $this->session->put('last_activity', time());
64
65 8
        $response = $next($request);
66
67 8
        $this->afterRequest($request);
68
69 8
        return $response;
70
    }
71
72
    /**
73
     * Determine whether the user is authenticating, i.e. logging in or signing up
74
     *
75
     * @param  \Illuminate\Http\Request $request
76
     * @return boolean 
77
     */
78 24
    protected function authenticating(Request $request)
79
    {
80 24
        return $request->is($this->login) || $request->is('register');
81
    }
82
83
    /**
84
     * Determine whether the session should be ended due to timeout or frontend request
85
     * We whitelist the login page from this assessment
86
     *
87
     * @param  \Illuminate\Http\Request $request
88
     * @return boolean 
89
     */
90 24
    protected function endSession(Request $request)
91
    {
92 24
        return !$this->authenticating($request) && ($this->timedOut() || $request->is('session/end'));
93
    }
94
95
    /**
96
     * Determine whether timeout has occurred or been forced by other activity on the site
97
     * If there's no data to do the timeout check, then we assume the session has been otherwise ended
98
     *
99
     * @return boolean 
100
     */
101 18
    protected function timedOut()
102
    {
103 18
        return !$this->session->has('last_activity') || (time() - $this->session->get('last_activity')) > $this->timeout || $this->auth->guest();
104
    }
105
106
    /**
107
     * Logout and clear our the last_activity timer - one or both of which actions may be redundant, but not harmful
108
     * Then, for our package routes, compose a suitable response, and for other routes continue processing as normal
109
     *
110
     * @param  \Illuminate\Http\Request  $request
111
     * @param  Closure  $next
112
     * @return mixed
113
     */
114 15
    protected function terminateAndRespond(Request $request, Closure $next)
115
    {
116 15
        $this->auth->logout();
117 15
        $this->session->forget('last_activity');
118
119 15
        if ($request->is('session/end')) {
120 4
            return response('session ended', 200);
121
        }
122
123 11
        if ($request->is('session/remaining')) {
124 3
            return response(0, 200);
125
        }
126
127 8
        if ($request->is('session/ping')) {
128 3
            return response('trying to keep alive a session that has already expired', 400);
129
        }
130
131 5
        return $next($request);
132
    }
133
134
    /**
135
     * After the request has been processed, check if it was for actually
136
     * authenticating and if not, i.e. redirect to login page and unset the
137
     * last_activity timer.
138
     *
139
     * @param  \Illuminate\Http\Request  $request
140
     * @return void
141
     */
142 8
    protected function afterRequest(Request $request)
143
    {
144 8
        if ($this->authenticating($request) && $this->auth->guest()) {
145 4
            $this->session->forget('last_activity');
146 4
        }
147 8
    }
148
}
149