• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nette / security / 22835249014

09 Mar 2026 01:53AM UTC coverage: 91.812%. Remained the same
22835249014

push

github

dg
User: deprecated magic properties (BC break)

527 of 574 relevant lines covered (91.81%)

0.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.83
/src/Security/User.php
1
<?php declare(strict_types=1);
1✔
2

3
/**
4
 * This file is part of the Nette Framework (https://nette.org)
5
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6
 */
7

8
namespace Nette\Security;
9

10
use Nette;
11
use Nette\Utils\Arrays;
12
use function func_get_args;
13

14

15
/**
16
 * User authentication and authorization.
17
 *
18
 * @property-read bool $loggedIn
19
 * @property-read ?IIdentity $identity
20
 * @property-deprecated string|int|null $id
21
 * @property-deprecated string[] $roles
22
 * @property-deprecated ?int $logoutReason
23
 * @property-deprecated Authenticator $authenticator
24
 * @property-deprecated Authorizator $authorizator
25
 */
26
class User
27
{
28
        use Nette\SmartObject;
29

30
        /** Log-out reason */
31
        public const
32
                LogoutManual = 1,
33
                LogoutInactivity = 2;
34

35
        /** @deprecated use User::LogoutManual */
36
        public const LOGOUT_MANUAL = self::LogoutManual;
37

38
        /** @deprecated use User::LogoutManual */
39
        public const MANUAL = self::LogoutManual;
40

41
        /** @deprecated use User::LogoutInactivity */
42
        public const LOGOUT_INACTIVITY = self::LogoutInactivity;
43

44
        /** @deprecated use User::LogoutInactivity */
45
        public const INACTIVITY = self::LogoutInactivity;
46

47
        /** default role for unauthenticated user */
48
        public string $guestRole = 'guest';
49

50
        /** default role for authenticated user without own identity */
51
        public string $authenticatedRole = 'authenticated';
52

53
        /** @var array<callable(self): void>  Occurs when the user is successfully logged in */
54
        public array $onLoggedIn = [];
55

56
        /** @var array<callable(self): void>  Occurs when the user is logged out */
57
        public array $onLoggedOut = [];
58

59
        private ?IIdentity $identity = null;
60
        private ?bool $authenticated = null;
61
        private ?int $logoutReason = null;
62

63

64
        public function __construct(
1✔
65
                private UserStorage $storage,
66
                private ?Authenticator $authenticator = null,
67
                private ?Authorizator $authorizator = null,
68
        ) {
69
        }
1✔
70

71

72
        final public function getStorage(): UserStorage
73
        {
74
                return $this->storage;
×
75
        }
76

77

78
        /********************* Authentication ****************d*g**/
79

80

81
        /**
82
         * Authenticates the user. Accepts username and password, or an IIdentity directly.
83
         * @param  string|IIdentity  $username  username or identity
84
         * @throws AuthenticationException if authentication was not successful
85
         */
86
        public function login(
1✔
87
                string|IIdentity $username,
88
                #[\SensitiveParameter]
89
                ?string $password = null,
90
        ): void
91
        {
92
                $this->logout(clearIdentity: true);
1✔
93
                if ($username instanceof IIdentity) {
1✔
94
                        $this->identity = $username;
1✔
95
                } else {
96
                        $authenticator = $this->getAuthenticator();
1✔
97
                        $this->identity = $authenticator->authenticate(...func_get_args());
1✔
98
                }
99

100
                $id = $this->authenticator instanceof IdentityHandler
1✔
101
                        ? $this->authenticator->sleepIdentity($this->identity)
1✔
102
                        : $this->identity;
1✔
103

104
                $this->storage->saveAuthentication($id);
1✔
105
                $this->authenticated = true;
1✔
106
                $this->logoutReason = null;
1✔
107
                Arrays::invoke($this->onLoggedIn, $this);
1✔
108
        }
1✔
109

110

111
        /**
112
         * Logs out the user from the current session.
113
         */
114
        final public function logout(bool $clearIdentity = false): void
1✔
115
        {
116
                $logged = $this->isLoggedIn();
1✔
117
                $this->storage->clearAuthentication($clearIdentity);
1✔
118
                $this->authenticated = false;
1✔
119
                $this->logoutReason = self::LogoutManual;
1✔
120
                if ($logged) {
1✔
121
                        Arrays::invoke($this->onLoggedOut, $this);
1✔
122
                }
123

124
                $this->identity = $clearIdentity ? null : $this->identity;
1✔
125
        }
1✔
126

127

128
        /**
129
         * Checks whether the user is authenticated.
130
         */
131
        final public function isLoggedIn(): bool
132
        {
133
                if ($this->authenticated === null) {
1✔
134
                        $this->getStoredData();
1✔
135
                }
136

137
                return (bool) $this->authenticated;
1✔
138
        }
139

140

141
        /**
142
         * Returns the current user identity, or null if not authenticated.
143
         */
144
        final public function getIdentity(): ?IIdentity
145
        {
146
                if ($this->authenticated === null) {
1✔
147
                        $this->getStoredData();
1✔
148
                }
149

150
                return $this->identity;
1✔
151
        }
152

153

154
        private function getStoredData(): void
155
        {
156
                (function (bool $state, ?IIdentity $id, ?int $reason) use (&$identity) {
1✔
157
                        $identity = $id;
1✔
158
                        $this->authenticated = $state;
1✔
159
                        $this->logoutReason = $reason;
1✔
160
                })(...$this->storage->getState());
1✔
161

162
                $this->identity = $identity && $this->authenticator instanceof IdentityHandler
1✔
163
                        ? $this->authenticator->wakeupIdentity($identity)
1✔
164
                        : $identity;
1✔
165
                $this->authenticated = $this->authenticated && $this->identity !== null;
1✔
166
        }
1✔
167

168

169
        /**
170
         * Returns current user ID, if any.
171
         */
172
        public function getId(): string|int|null
173
        {
174
                $identity = $this->getIdentity();
1✔
175
                return $identity ? $identity->getId() : null;
1✔
176
        }
177

178

179
        /**
180
         * Discards cached authentication state, forcing a reload from storage on next access.
181
         */
182
        final public function refreshStorage(): void
183
        {
184
                $this->identity = $this->authenticated = $this->logoutReason = null;
1✔
185
        }
1✔
186

187

188
        /**
189
         * Sets authentication handler.
190
         */
191
        public function setAuthenticator(Authenticator $handler): static
1✔
192
        {
193
                $this->authenticator = $handler;
1✔
194
                return $this;
1✔
195
        }
196

197

198
        /**
199
         * Returns authentication handler.
200
         */
201
        final public function getAuthenticator(): Authenticator
202
        {
203
                if (!$this->authenticator) {
1✔
204
                        throw new Nette\InvalidStateException('Authenticator has not been set.');
1✔
205
                }
206

207
                return $this->authenticator;
1✔
208
        }
209

210

211
        /**
212
         * Returns authentication handler, or null if none is set.
213
         */
214
        final public function getAuthenticatorIfExists(): ?Authenticator
215
        {
216
                return $this->authenticator;
×
217
        }
218

219

220
        /** @deprecated */
221
        final public function hasAuthenticator(): bool
222
        {
223
                return (bool) $this->authenticator;
×
224
        }
225

226

227
        /**
228
         * Enables log out after inactivity (like '20 minutes').
229
         */
230
        public function setExpiration(?string $expire, bool $clearIdentity = false): static
1✔
231
        {
232
                $this->storage->setExpiration($expire, $clearIdentity);
1✔
233
                return $this;
1✔
234
        }
235

236

237
        /**
238
         * Returns the logout reason: LogoutManual or LogoutInactivity, or null if not applicable.
239
         */
240
        final public function getLogoutReason(): ?int
241
        {
242
                return $this->logoutReason;
1✔
243
        }
244

245

246
        /********************* Authorization ****************d*g**/
247

248

249
        /**
250
         * Returns effective roles of the user. Unauthenticated users get the guest role.
251
         * @return string[]
252
         */
253
        public function getRoles(): array
254
        {
255
                if (!$this->isLoggedIn()) {
1✔
256
                        return [$this->guestRole];
1✔
257
                }
258

259
                $identity = $this->getIdentity();
1✔
260
                return $identity?->getRoles() ?? [$this->authenticatedRole];
1✔
261
        }
262

263

264
        /**
265
         * Checks whether the user has the specified effective role.
266
         */
267
        final public function isInRole(string $role): bool
1✔
268
        {
269
                foreach ($this->getRoles() as $r) {
1✔
270
                        if ($role === ($r instanceof Role ? $r->getRoleId() : $r)) {
1✔
271
                                return true;
1✔
272
                        }
273
                }
274

275
                return false;
1✔
276
        }
277

278

279
        /**
280
         * Checks whether the user has access to the given resource and privilege.
281
         * Null means all resources or all privileges.
282
         */
283
        public function isAllowed(mixed $resource = Authorizator::All, mixed $privilege = Authorizator::All): bool
1✔
284
        {
285
                foreach ($this->getRoles() as $role) {
1✔
286
                        if ($this->getAuthorizator()->isAllowed($role, $resource, $privilege)) {
1✔
287
                                return true;
1✔
288
                        }
289
                }
290

291
                return false;
1✔
292
        }
293

294

295
        /**
296
         * Sets authorization handler.
297
         */
298
        public function setAuthorizator(Authorizator $handler): static
1✔
299
        {
300
                $this->authorizator = $handler;
1✔
301
                return $this;
1✔
302
        }
303

304

305
        /**
306
         * Returns current authorization handler.
307
         */
308
        final public function getAuthorizator(): Authorizator
309
        {
310
                if (!$this->authorizator) {
1✔
311
                        throw new Nette\InvalidStateException('Authorizator has not been set.');
1✔
312
                }
313

314
                return $this->authorizator;
1✔
315
        }
316

317

318
        /**
319
         * Returns authorization handler, or null if none is set.
320
         */
321
        final public function getAuthorizatorIfExists(): ?Authorizator
322
        {
323
                return $this->authorizator;
×
324
        }
325

326

327
        /** @deprecated */
328
        final public function hasAuthorizator(): bool
329
        {
330
                return (bool) $this->authorizator;
×
331
        }
332
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc