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