|
| 1 | +# AuthUser Component and Helper |
| 2 | + |
| 3 | +The AuthUser component and helper provide convenient methods for working with the currently authenticated user in your controllers and views. |
| 4 | + |
| 5 | +**Key Feature:** These work **standalone** and do not require the official Authentication or Authorization plugins. They work with any authentication solution that sets an identity in the request attributes. |
| 6 | + |
| 7 | +## AuthUser Component |
| 8 | + |
| 9 | +The component provides easy access to the current user's data and permission checks in your controllers. |
| 10 | + |
| 11 | +### Setup |
| 12 | + |
| 13 | +Load the component in your AppController: |
| 14 | + |
| 15 | +```php |
| 16 | +// src/Controller/AppController.php |
| 17 | + |
| 18 | +public function initialize(): void { |
| 19 | + parent::initialize(); |
| 20 | + |
| 21 | + $this->loadComponent('TinyAuth.AuthUser'); |
| 22 | +} |
| 23 | +``` |
| 24 | + |
| 25 | +### Available Methods |
| 26 | + |
| 27 | +#### `id()` |
| 28 | +Get the current user's ID: |
| 29 | + |
| 30 | +```php |
| 31 | +$userId = $this->AuthUser->id(); |
| 32 | +``` |
| 33 | + |
| 34 | +#### `isMe(int|string $id)` |
| 35 | +Check if a given ID belongs to the current user: |
| 36 | + |
| 37 | +```php |
| 38 | +if ($this->AuthUser->isMe($post->user_id)) { |
| 39 | + // User owns this post |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +#### `hasRole(string|int $role)` |
| 44 | +Check if the user has a specific role (by alias or ID): |
| 45 | + |
| 46 | +```php |
| 47 | +if ($this->AuthUser->hasRole('admin')) { |
| 48 | + // User is an admin |
| 49 | +} |
| 50 | + |
| 51 | +if ($this->AuthUser->hasRole(ROLE_MODERATOR)) { |
| 52 | + // User is a moderator (using constant) |
| 53 | +} |
| 54 | +``` |
| 55 | + |
| 56 | +#### `hasRoles(array $roles)` |
| 57 | +Check if the user has any of the specified roles: |
| 58 | + |
| 59 | +```php |
| 60 | +if ($this->AuthUser->hasRoles(['admin', 'moderator'])) { |
| 61 | + // User is either admin or moderator |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +#### `roles()` |
| 66 | +Get all roles for the current user: |
| 67 | + |
| 68 | +```php |
| 69 | +$userRoles = $this->AuthUser->roles(); |
| 70 | +``` |
| 71 | + |
| 72 | +#### `hasAccess(array $url)` |
| 73 | +Check if the user has access to a specific URL (checks ACL): |
| 74 | + |
| 75 | +```php |
| 76 | +if ($this->AuthUser->hasAccess(['action' => 'delete', $id])) { |
| 77 | + return $this->redirect(['action' => 'delete', $id]); |
| 78 | +} |
| 79 | +// Do something else instead |
| 80 | +``` |
| 81 | + |
| 82 | +**Note:** By default, `hasAccess()` only checks the `auth_acl.ini` file, not `auth_allow.ini`. Set `includeAuthentication` config to `true` if you need to check public actions as well. |
| 83 | + |
| 84 | +#### `identity()` |
| 85 | +Get the full identity object/array: |
| 86 | + |
| 87 | +```php |
| 88 | +$identity = $this->AuthUser->identity(); |
| 89 | +// Returns the original data from Authentication/Authorization identity |
| 90 | +``` |
| 91 | + |
| 92 | +### Example Usage |
| 93 | + |
| 94 | +```php |
| 95 | +// In a controller action |
| 96 | +public function edit($id) { |
| 97 | + $post = $this->Posts->get($id); |
| 98 | + |
| 99 | + // Only allow editing own posts unless admin |
| 100 | + if (!$this->AuthUser->isMe($post->user_id) && !$this->AuthUser->hasRole('admin')) { |
| 101 | + $this->Flash->error(__('You can only edit your own posts.')); |
| 102 | + return $this->redirect(['action' => 'index']); |
| 103 | + } |
| 104 | + |
| 105 | + // Continue with edit logic... |
| 106 | +} |
| 107 | +``` |
| 108 | + |
| 109 | +## AuthUser Helper |
| 110 | + |
| 111 | +The helper provides the same functionality in your templates, plus additional methods for conditionally displaying links. |
| 112 | + |
| 113 | +### Setup |
| 114 | + |
| 115 | +Load the helper in your AppView: |
| 116 | + |
| 117 | +```php |
| 118 | +// src/View/AppView.php |
| 119 | + |
| 120 | +public function initialize(): void { |
| 121 | + parent::initialize(); |
| 122 | + |
| 123 | + $this->loadHelper('TinyAuth.AuthUser'); |
| 124 | +} |
| 125 | +``` |
| 126 | + |
| 127 | +**Important:** The helper requires the component to be loaded, as it needs data passed from the controller. |
| 128 | + |
| 129 | +### Available Methods |
| 130 | + |
| 131 | +The helper has all the same methods as the component: |
| 132 | +- `id()` |
| 133 | +- `isMe($id)` |
| 134 | +- `hasRole($role)` |
| 135 | +- `hasRoles($roles)` |
| 136 | +- `roles()` |
| 137 | +- `hasAccess($url)` |
| 138 | +- `identity()` |
| 139 | + |
| 140 | +### Additional Helper-Only Methods |
| 141 | + |
| 142 | +#### `link(string $title, array $url, array $options = [])` |
| 143 | +Display a link only if the user has access to that URL: |
| 144 | + |
| 145 | +```php |
| 146 | +// Only displays if user has access to Admin prefix |
| 147 | +echo $this->AuthUser->link('Admin Backend', ['prefix' => 'Admin', 'action' => 'index']); |
| 148 | +``` |
| 149 | + |
| 150 | +If the user doesn't have access, nothing is displayed. |
| 151 | + |
| 152 | +#### `postLink(string $title, array $url, array $options = [])` |
| 153 | +Display a POST link only if the user has access: |
| 154 | + |
| 155 | +```php |
| 156 | +// Only displays delete link if user has delete permission |
| 157 | +echo $this->AuthUser->postLink('Delete', ['action' => 'delete', $id], [ |
| 158 | + 'confirm' => 'Are you sure?', |
| 159 | +]); |
| 160 | +``` |
| 161 | + |
| 162 | +### Named Routes Support |
| 163 | + |
| 164 | +Both `link()` and `postLink()` support named routes: |
| 165 | + |
| 166 | +```php |
| 167 | +<?= $this->AuthUser->link('Change Password', ['_name' => 'admin:account:password']); ?> |
| 168 | +``` |
| 169 | + |
| 170 | +### Template Examples |
| 171 | + |
| 172 | +#### Conditional Content Display |
| 173 | + |
| 174 | +```php |
| 175 | +<?php if ($this->AuthUser->hasRole('admin')): ?> |
| 176 | + <div class="admin-tools"> |
| 177 | + <?= $this->AuthUser->link('Manage Users', ['controller' => 'Users', 'action' => 'index']); ?> |
| 178 | + <?= $this->AuthUser->link('Settings', ['controller' => 'Settings', 'action' => 'index']); ?> |
| 179 | + </div> |
| 180 | +<?php endif; ?> |
| 181 | +``` |
| 182 | + |
| 183 | +#### Show/Hide Based on Ownership |
| 184 | + |
| 185 | +```php |
| 186 | +<?php if ($this->AuthUser->isMe($comment->user_id)): ?> |
| 187 | + <?= $this->AuthUser->postLink( |
| 188 | + 'Delete Comment', |
| 189 | + ['action' => 'delete', $comment->id], |
| 190 | + ['confirm' => 'Are you sure?'] |
| 191 | + ); ?> |
| 192 | +<?php endif; ?> |
| 193 | +``` |
| 194 | + |
| 195 | +#### Complex Access Checks |
| 196 | + |
| 197 | +```php |
| 198 | +<?php if ($this->AuthUser->hasAccess(['action' => 'secretArea'])): ?> |
| 199 | + <div class="secret-section"> |
| 200 | + <p>Only for you:</p> |
| 201 | + <?= $this->Html->link('Secret Area', ['action' => 'secretArea']); ?> |
| 202 | + <small>(do not tell anyone else!)</small> |
| 203 | + </div> |
| 204 | +<?php endif; ?> |
| 205 | +``` |
| 206 | + |
| 207 | +#### Role-Based Navigation |
| 208 | + |
| 209 | +```php |
| 210 | +<nav> |
| 211 | + <ul> |
| 212 | + <li><?= $this->Html->link('Home', ['action' => 'index']); ?></li> |
| 213 | + |
| 214 | + <?php if ($this->AuthUser->hasRole('user')): ?> |
| 215 | + <li><?= $this->AuthUser->link('My Posts', ['action' => 'myPosts']); ?></li> |
| 216 | + <?php endif; ?> |
| 217 | + |
| 218 | + <?php if ($this->AuthUser->hasRoles(['admin', 'moderator'])): ?> |
| 219 | + <li><?= $this->AuthUser->link('Moderation', ['action' => 'moderate']); ?></li> |
| 220 | + <?php endif; ?> |
| 221 | + |
| 222 | + <?php if ($this->AuthUser->hasRole('admin')): ?> |
| 223 | + <li><?= $this->AuthUser->link('Admin', ['prefix' => 'Admin', 'action' => 'dashboard']); ?></li> |
| 224 | + <?php endif; ?> |
| 225 | + </ul> |
| 226 | +</nav> |
| 227 | +``` |
| 228 | + |
| 229 | +## Configuration |
| 230 | + |
| 231 | +### Including Authentication in Access Checks |
| 232 | + |
| 233 | +By default, `hasAccess()` only checks authorization (ACL), not authentication (public actions). |
| 234 | + |
| 235 | +To include public actions in the access check: |
| 236 | + |
| 237 | +```php |
| 238 | +$this->loadComponent('TinyAuth.AuthUser', [ |
| 239 | + 'includeAuthentication' => true, |
| 240 | +]); |
| 241 | +``` |
| 242 | + |
| 243 | +**Note:** This only works with INI-based configuration. Controller-level `allow()` calls cannot be detected. |
| 244 | + |
| 245 | +## Best Practices |
| 246 | + |
| 247 | +### Use Constants for Roles |
| 248 | + |
| 249 | +Instead of magic strings, define role constants: |
| 250 | + |
| 251 | +```php |
| 252 | +// In your bootstrap |
| 253 | +define('ROLE_USER', 'user'); |
| 254 | +define('ROLE_MODERATOR', 'moderator'); |
| 255 | +define('ROLE_ADMIN', 'admin'); |
| 256 | + |
| 257 | +// In your code |
| 258 | +if ($this->AuthUser->hasRole(ROLE_ADMIN)) { |
| 259 | + // Much better than: hasRole('admin') |
| 260 | +} |
| 261 | +``` |
| 262 | + |
| 263 | +This provides: |
| 264 | +- IDE autocompletion |
| 265 | +- Easy refactoring |
| 266 | +- Prevents typos |
| 267 | +- Self-documenting code |
| 268 | + |
| 269 | +### Combine with Form Helper |
| 270 | + |
| 271 | +```php |
| 272 | +<?php |
| 273 | +echo $this->Form->create($post); |
| 274 | +echo $this->Form->control('title'); |
| 275 | +echo $this->Form->control('body'); |
| 276 | + |
| 277 | +// Only admins can change the status |
| 278 | +if ($this->AuthUser->hasRole('admin')) { |
| 279 | + echo $this->Form->control('status'); |
| 280 | +} |
| 281 | + |
| 282 | +echo $this->Form->button(__('Submit')); |
| 283 | +echo $this->Form->end(); |
| 284 | +?> |
| 285 | +``` |
| 286 | + |
| 287 | +## Standalone Usage |
| 288 | + |
| 289 | +AuthUser works with any authentication solution, not just TinyAuth: |
| 290 | + |
| 291 | +- **CakePHP Authentication plugin** - Works out of the box |
| 292 | +- **CakePHP Authorization plugin** - Works out of the box |
| 293 | +- **Custom auth** - As long as you set an identity in request attributes |
| 294 | + |
| 295 | +The component looks for the identity in `$request->getAttribute('identity')` and works with any object that implements `getOriginalData()` or is an array. |
0 commit comments