1: <?php
2:
3: /**
4: * This file is part of the Nette Framework (http://nette.org)
5: *
6: * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
7: *
8: * For the full copyright and license information, please view
9: * the file license.txt that was distributed with this source code.
10: * @package Nette\Http
11: */
12:
13:
14:
15: /**
16: * Session storage for user object.
17: *
18: * @author David Grudl, Jan Tichý
19: * @package Nette\Http
20: */
21: class UserStorage extends Object implements IUserStorage
22: {
23: /** @var string */
24: private $namespace = '';
25:
26: /** @var Session */
27: private $sessionHandler;
28:
29: /** @var SessionSection */
30: private $sessionSection;
31:
32:
33:
34: public function __construct(Session $sessionHandler)
35: {
36: $this->sessionHandler = $sessionHandler;
37: }
38:
39:
40:
41: /**
42: * Sets the authenticated status of this user.
43: * @param bool
44: * @return UserStorage Provides a fluent interface
45: */
46: public function setAuthenticated($state)
47: {
48: $section = $this->getSessionSection(TRUE);
49: $section->authenticated = (bool) $state;
50:
51: // Session Fixation defence
52: $this->sessionHandler->regenerateId();
53:
54: if ($state) {
55: $section->reason = NULL;
56: $section->authTime = time(); // informative value
57:
58: } else {
59: $section->reason = self::MANUAL;
60: $section->authTime = NULL;
61: }
62: return $this;
63: }
64:
65:
66:
67: /**
68: * Is this user authenticated?
69: * @return bool
70: */
71: public function isAuthenticated()
72: {
73: $session = $this->getSessionSection(FALSE);
74: return $session && $session->authenticated;
75: }
76:
77:
78:
79: /**
80: * Sets the user identity.
81: * @return UserStorage Provides a fluent interface
82: */
83: public function setIdentity(IIdentity $identity = NULL)
84: {
85: $this->getSessionSection(TRUE)->identity = $identity;
86: return $this;
87: }
88:
89:
90:
91: /**
92: * Returns current user identity, if any.
93: * @return IIdentity|NULL
94: */
95: public function getIdentity()
96: {
97: $session = $this->getSessionSection(FALSE);
98: return $session ? $session->identity : NULL;
99: }
100:
101:
102:
103: /**
104: * Changes namespace; allows more users to share a session.
105: * @param string
106: * @return UserStorage Provides a fluent interface
107: */
108: public function setNamespace($namespace)
109: {
110: if ($this->namespace !== $namespace) {
111: $this->namespace = (string) $namespace;
112: $this->sessionSection = NULL;
113: }
114: return $this;
115: }
116:
117:
118:
119: /**
120: * Returns current namespace.
121: * @return string
122: */
123: public function getNamespace()
124: {
125: return $this->namespace;
126: }
127:
128:
129:
130: /**
131: * Enables log out after inactivity.
132: * @param string|int|DateTime Number of seconds or timestamp
133: * @param int Log out when the browser is closed | Clear the identity from persistent storage?
134: * @return UserStorage Provides a fluent interface
135: */
136: public function setExpiration($time, $flags = 0)
137: {
138: $section = $this->getSessionSection(TRUE);
139: if ($time) {
140: $time = DateTime53::from($time)->format('U');
141: $section->expireTime = $time;
142: $section->expireDelta = $time - time();
143:
144: } else {
145: unset($section->expireTime, $section->expireDelta);
146: }
147:
148: $section->expireIdentity = (bool) ($flags & self::CLEAR_IDENTITY);
149: $section->expireBrowser = (bool) ($flags & self::BROWSER_CLOSED);
150: $section->browserCheck = TRUE;
151: $section->setExpiration(0, 'browserCheck');
152: $section->setExpiration($time, 'foo'); // time check
153: return $this;
154: }
155:
156:
157:
158: /**
159: * Why was user logged out?
160: * @return int
161: */
162: public function getLogoutReason()
163: {
164: $session = $this->getSessionSection(FALSE);
165: return $session ? $session->reason : NULL;
166: }
167:
168:
169:
170: /**
171: * Returns and initializes $this->sessionSection.
172: * @return SessionSection
173: */
174: protected function getSessionSection($need)
175: {
176: if ($this->sessionSection !== NULL) {
177: return $this->sessionSection;
178: }
179:
180: if (!$need && !$this->sessionHandler->exists()) {
181: return NULL;
182: }
183:
184: $this->sessionSection = $section = $this->sessionHandler->getSection('Nette.Http.UserStorage/' . $this->namespace);
185:
186: if (!$section->identity instanceof IIdentity || !is_bool($section->authenticated)) {
187: $section->remove();
188: }
189:
190: if ($section->authenticated && $section->expireBrowser && !$section->browserCheck) { // check if browser was closed?
191: $section->reason = self::BROWSER_CLOSED;
192: $section->authenticated = FALSE;
193: if ($section->expireIdentity) {
194: unset($section->identity);
195: }
196: }
197:
198: if ($section->authenticated && $section->expireDelta > 0) { // check time expiration
199: if ($section->expireTime < time()) {
200: $section->reason = self::INACTIVITY;
201: $section->authenticated = FALSE;
202: if ($section->expireIdentity) {
203: unset($section->identity);
204: }
205: }
206: $section->expireTime = time() + $section->expireDelta; // sliding expiration
207: }
208:
209: if (!$section->authenticated) {
210: unset($section->expireTime, $section->expireDelta, $section->expireIdentity,
211: $section->expireBrowser, $section->browserCheck, $section->authTime);
212: }
213:
214: return $this->sessionSection;
215: }
216:
217: }
218: