1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Web;
13:
14: use Nette,
15: Nette\Environment,
16: Nette\Security\IAuthenticator,
17: Nette\Security\IAuthorizator,
18: Nette\Security\IIdentity;
19:
20:
21:
22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
34: class User extends Nette\Object implements IUser
35: {
36:
37: const MANUAL = 1;
38: const INACTIVITY = 2;
39: const BROWSER_CLOSED = 3;
40:
41:
42:
43: public $guestRole = 'guest';
44:
45:
46: public $authenticatedRole = 'authenticated';
47:
48:
49: public $onLoggedIn;
50:
51:
52: public $onLoggedOut;
53:
54:
55: public $onAuthenticated;
56:
57:
58: public $onSignedOut;
59:
60:
61: private $authenticationHandler;
62:
63:
64: private $authorizationHandler;
65:
66:
67: private $namespace = '';
68:
69:
70: private $session;
71:
72:
73:
74: public function __construct()
75: {
76:
77: $this->onLoggedIn = & $this->onAuthenticated;
78: $this->onLoggedOut = & $this->onSignedOut;
79: }
80:
81:
82:
83:
84:
85:
86:
87: 88: 89: 90: 91: 92: 93: 94:
95: public function login($username, $password, $extra = NULL)
96: {
97: $handler = $this->getAuthenticationHandler();
98: if ($handler === NULL) {
99: throw new \InvalidStateException('Authentication handler has not been set.');
100: }
101:
102: $this->logout(TRUE);
103:
104: $credentials = array(
105: IAuthenticator::USERNAME => $username,
106: IAuthenticator::PASSWORD => $password,
107: 'extra' => $extra,
108: );
109:
110: $this->setIdentity($handler->authenticate($credentials));
111: $this->setAuthenticated(TRUE);
112: $this->onLoggedIn($this);
113: }
114:
115:
116:
117: 118: 119: 120: 121:
122: final public function logout($clearIdentity = FALSE)
123: {
124: if ($this->isLoggedIn()) {
125: $this->setAuthenticated(FALSE);
126: $this->onLoggedOut($this);
127: }
128:
129: if ($clearIdentity) {
130: $this->setIdentity(NULL);
131: }
132: }
133:
134:
135:
136: 137: 138: 139:
140: final public function isLoggedIn()
141: {
142: $session = $this->getSessionNamespace(FALSE);
143: return $session && $session->authenticated;
144: }
145:
146:
147:
148: 149: 150: 151:
152: final public function getIdentity()
153: {
154: $session = $this->getSessionNamespace(FALSE);
155: return $session ? $session->identity : NULL;
156: }
157:
158:
159:
160: 161: 162: 163: 164:
165: public function setAuthenticationHandler(IAuthenticator $handler)
166: {
167: $this->authenticationHandler = $handler;
168: return $this;
169: }
170:
171:
172:
173: 174: 175: 176:
177: final public function getAuthenticationHandler()
178: {
179: if ($this->authenticationHandler === NULL) {
180: $this->authenticationHandler = Environment::getService('Nette\\Security\\IAuthenticator');
181: }
182: return $this->authenticationHandler;
183: }
184:
185:
186:
187: 188: 189: 190: 191:
192: public function setNamespace($namespace)
193: {
194: if ($this->namespace !== $namespace) {
195: $this->namespace = (string) $namespace;
196: $this->session = NULL;
197: }
198: return $this;
199: }
200:
201:
202:
203: 204: 205: 206:
207: final public function getNamespace()
208: {
209: return $this->namespace;
210: }
211:
212:
213:
214: 215: 216: 217: 218: 219: 220:
221: public function setExpiration($time, $whenBrowserIsClosed = TRUE, $clearIdentity = FALSE)
222: {
223: $session = $this->getSessionNamespace(TRUE);
224: if ($time) {
225: $time = Nette\DateTime::from($time)->format('U');
226: $session->expireTime = $time;
227: $session->expireDelta = $time - time();
228:
229: } else {
230: unset($session->expireTime, $session->expireDelta);
231: }
232:
233: $session->expireIdentity = (bool) $clearIdentity;
234: $session->expireBrowser = (bool) $whenBrowserIsClosed;
235: $session->browserCheck = TRUE;
236: $session->setExpiration(0, 'browserCheck');
237: return $this;
238: }
239:
240:
241:
242: 243: 244: 245:
246: final public function getLogoutReason()
247: {
248: $session = $this->getSessionNamespace(FALSE);
249: return $session ? $session->reason : NULL;
250: }
251:
252:
253:
254: 255: 256: 257:
258: protected function getSessionNamespace($need)
259: {
260: if ($this->session !== NULL) {
261: return $this->session;
262: }
263:
264: $sessionHandler = $this->getSession();
265: if (!$need && !$sessionHandler->exists()) {
266: return NULL;
267: }
268:
269: $this->session = $session = $sessionHandler->getNamespace('Nette.Web.User/' . $this->namespace);
270:
271: if (!($session->identity instanceof IIdentity) || !is_bool($session->authenticated)) {
272: $session->remove();
273: }
274:
275: if ($session->authenticated && $session->expireBrowser && !$session->browserCheck) {
276: $session->reason = self::BROWSER_CLOSED;
277: $session->authenticated = FALSE;
278: $this->onLoggedOut($this);
279: if ($session->expireIdentity) {
280: unset($session->identity);
281: }
282: }
283:
284: if ($session->authenticated && $session->expireDelta > 0) {
285: if ($session->expireTime < time()) {
286: $session->reason = self::INACTIVITY;
287: $session->authenticated = FALSE;
288: $this->onLoggedOut($this);
289: if ($session->expireIdentity) {
290: unset($session->identity);
291: }
292: }
293: $session->expireTime = time() + $session->expireDelta;
294: }
295:
296: if (!$session->authenticated) {
297: unset($session->expireTime, $session->expireDelta, $session->expireIdentity,
298: $session->expireBrowser, $session->browserCheck, $session->authTime);
299: }
300:
301: return $this->session;
302: }
303:
304:
305:
306: 307: 308: 309: 310:
311: protected function setAuthenticated($state)
312: {
313: $session = $this->getSessionNamespace(TRUE);
314: $session->authenticated = (bool) $state;
315:
316:
317: $this->getSession()->regenerateId();
318:
319: if ($state) {
320: $session->reason = NULL;
321: $session->authTime = time();
322:
323: } else {
324: $session->reason = self::MANUAL;
325: $session->authTime = NULL;
326: }
327: return $this;
328: }
329:
330:
331:
332: 333: 334: 335: 336:
337: protected function setIdentity(IIdentity $identity = NULL)
338: {
339: $this->getSessionNamespace(TRUE)->identity = $identity;
340: return $this;
341: }
342:
343:
344:
345:
346:
347:
348:
349: 350: 351: 352:
353: public function getRoles()
354: {
355: if (!$this->isLoggedIn()) {
356: return array($this->guestRole);
357: }
358:
359: $identity = $this->getIdentity();
360: return $identity ? $identity->getRoles() : array($this->authenticatedRole);
361: }
362:
363:
364:
365: 366: 367: 368: 369:
370: final public function isInRole($role)
371: {
372: return in_array($role, $this->getRoles(), TRUE);
373: }
374:
375:
376:
377: 378: 379: 380: 381: 382: 383:
384: public function isAllowed($resource = IAuthorizator::ALL, $privilege = IAuthorizator::ALL)
385: {
386: $handler = $this->getAuthorizationHandler();
387: if (!$handler) {
388: throw new \InvalidStateException("Authorization handler has not been set.");
389: }
390:
391: foreach ($this->getRoles() as $role) {
392: if ($handler->isAllowed($role, $resource, $privilege)) return TRUE;
393: }
394:
395: return FALSE;
396: }
397:
398:
399:
400: 401: 402: 403: 404:
405: public function setAuthorizationHandler(IAuthorizator $handler)
406: {
407: $this->authorizationHandler = $handler;
408: return $this;
409: }
410:
411:
412:
413: 414: 415: 416:
417: final public function getAuthorizationHandler()
418: {
419: if ($this->authorizationHandler === NULL) {
420: $this->authorizationHandler = Environment::getService('Nette\\Security\\IAuthorizator');
421: }
422: return $this->authorizationHandler;
423: }
424:
425:
426:
427:
428:
429:
430:
431: 432: 433: 434:
435: protected function getSession()
436: {
437: return Environment::getSession();
438: }
439:
440:
441:
442:
443: function authenticate($username, $password, $extra = NULL)
444: {
445: trigger_error(__METHOD__ . '() is deprecated; use login() instead.', E_USER_WARNING);
446: return $this->login($username, $password, $extra);
447: }
448:
449: function signOut($clearIdentity = FALSE)
450: {
451: trigger_error(__METHOD__ . '() is deprecated; use logout() instead.', E_USER_WARNING);
452: return $this->logout($clearIdentity);
453: }
454:
455: function isAuthenticated()
456: {
457: trigger_error(__METHOD__ . '() is deprecated; use isLoggedIn() instead.', E_USER_WARNING);
458: return $this->isLoggedIn();
459: }
460:
461: function getSignOutReason()
462: {
463: trigger_error(__METHOD__ . '() is deprecated; use getLogoutReason() instead.', E_USER_WARNING);
464: return $this->getLogoutReason();
465: }
466:
467:
468: }
469: