Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ env:

matrix:
include:
- php: 5.6
- php: 7.0
env: PHPCS=1 DEFAULT=0

- php: 5.6
- php: 7.0
env: COVERALLS=1 DEFAULT=0

fast_finish: true
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ It is also possible to manage the config files without the need of coding skills
Ask yourself: Do you need the overhead and complexity involved with the core CakePHP ACL? See also my post [acl-access-control-lists-revised/](http://www.dereuromark.de/2015/01/06/acl-access-control-lists-revised/).
If not, then this plugin could very well be your answer and a super quick solution to your auth problem :)

But even if you don't leverage the authentication or authorization, the available AuthUserComponent and AuthUserHelper
can be very useful when dealing with role based decisions in your controller or view level. They also work standa-alone.

## Demo
See http://sandbox3.dereuromark.de/auth-sandbox

Expand All @@ -41,6 +44,23 @@ add,edit = user,mod
* = admin
```

### AuthUser component and helper
```php
$currentId = $this->AuthUser->id();

$isMe = $this->AuthUser->isMe($userEntity->id);

if ($this->AuthUser->hasRole('mod') {
}

if ($this->AuthUser->hasAccess(['action' => 'secretArea'])) {
}

// Helper only
echo $this->AuthUser->link('Admin Backend', ['prefix' => 'admin', 'action' => 'index']);
echo $this->AuthUser->postLink('Delete', ['action' => 'delete', $id], ['confirm' => 'Sure?']);
```

## How to include
Installing the plugin is pretty much as with every other CakePHP plugin:

Expand Down
10 changes: 6 additions & 4 deletions docs/Authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ Authentication is set up in your controller's `initialize` method:
public function initialize() {
parent::initialize();

$this->loadComponent('TinyAuth.Auth', [
'autoClearCache' => ...
]);
$this->loadComponent('TinyAuth.Auth');
}
```

Expand Down Expand Up @@ -64,6 +62,10 @@ Accounts.Accounts = view, edit
Accounts.admin/Accounts = index
```

### Multiple files and merging
You can specify multiple paths in your config, e.g. when you have plugins and separated the definitions across them.
Make sure you are using each key only once, though. The first definition will be kept and all others for the same key are ignored.

### Mixing with code
It is possible to have mixed INI and code rules. Those will get merged prior to authentication.
So in case any of your controllers (or plugin controllers) contain such a statement, it will merge itself with your INI whitelist:
Expand Down Expand Up @@ -101,7 +103,7 @@ TinyAuth AuthComponent supports the following configuration options.
Option | Type | Description
:----- | :--- | :----------
autoClearCache|bool|True will generate a new ACL cache file every time.
filePath|string|Full path to the INI file. Defaults to `ROOT . DS . 'config' . DS`.
filePath|string|Full path to the INI file. Can also be an array of paths. Defaults to `ROOT . DS . 'config' . DS`.
file|string|Name of the INI file. Defaults to `auth_allow.ini`.
cache|string|Cache type. Defaults to `_cake_core_`.
cacheKey|string|Cache key. Defaults to `tiny_auth_allow`.
152 changes: 143 additions & 9 deletions docs/Authorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function initialize() {
$this->loadComponent('TinyAuth.Auth', [
'authorize' => [
'TinyAuth.Tiny' => [
'autoClearCache' => ...
...
],
...
]
Expand All @@ -45,7 +45,7 @@ You can also use the default one, if you only want to use ACL (authorization):
$this->loadComponent('Auth', [
'authorize' => [
'TinyAuth.Tiny' => [
'autoClearCache' => ...
...
]
]
]);
Expand All @@ -63,11 +63,11 @@ Define your roles in a Configure array if you want to prevent database role
lookups, for example:

```php
// config/app_custom.php
// config/app.php

/**
* Optionally define constants for easy referencing throughout your code
*/
/*
* Optionally define constants for easy referencing throughout your code
*/
define('ROLE_USER', 1);
define('ROLE_ADMIN', 2);
define('ROLE_SUPERADMIN', 9);
Expand Down Expand Up @@ -193,6 +193,11 @@ view, edit = user
* = admin
```

### Multiple files and merging
You can specify multiple paths in your config, e.g. when you have plugins and separated the definitions across them.
Make sure you are using each section key only once, though. The first definition will be kept and all others for the same section key are ignored.


## Caching

TinyAuth makes heavy use of caching to achieve optimal performance.
Expand Down Expand Up @@ -229,11 +234,140 @@ prefixes|array|A list of authorizeByPrefix handled prefixes.
allowUser|bool|True will give authenticated users access to all resources except those using the `adminPrefix`
adminPrefix|string|Name of the prefix used for admin pages. Defaults to admin.
autoClearCache|bool|True will generate a new ACL cache file every time.
filePath|string|Full path to the acl.ini. Defaults to `ROOT . DS . 'config' . DS`.
filePath|string|Full path to the acl.ini. Can also be an array of multiple paths. Defaults to `ROOT . DS . 'config' . DS`.
file|string|Name of the INI file. Defaults to `acl.ini`.
cache|string|Cache type. Defaults to `_cake_core_`.
cacheKey|string|Cache key. Defaults to `tiny_auth_acl`.


## Auth user data
For reading auth user data take a look at [Tools plugin AuthUser component/helper](https://github.com/dereuromark/cakephp-tools/blob/master/docs/Auth/Auth.md).
## AuthUserComponent
Add the AuthUserComponent and you can easily check permissions inside your controller scope:
```php
$this->loadComponent('TinyAuth.AuthUser');
```

Maybe you only want to redirect to a certain action if that is accessible for this user (role):
```php
if ($this->AuthUser->hasAccess(['action' => 'forModeratorOnly'])) {
return $this->redirect(['action' => 'forModeratorOnly']);
}
// Do something else
```

Or if that person is of a certain role in general:
```php
if ($this->AuthUser->hasRole('mod') { // Either by alias or id
// OK, do something now
}
```

For any action that get's the user id passed, you can also ask:
```php
$isMe = $this->AuthUser->isMe($userEntity->id);
// This would be equal to
$isMe = $this->AuthUser->id() == $userEntity->id;
```

## AuthHelper
The helper assists with the same in the templates.

Include the helper in your `AppView.php`:
```php
$this->loadHelper('TinyAuth.AuthUser');
```

Note that this helper only works if you also enabled the above component, as it needs some data to be passed down.

All the above gotchas also are available in the views and helpers now (id, isMe, roles, hasRole, hasRoles, hasAccess).
But on top, if you want to display certain content or a link for specific roles, you can do that, too.

Let's say we only want to print an admin backend link if the role can access it:
```php
echo $this->AuthUser->link('Admin Backend', ['prefix' => 'admin', 'action' => 'index']);
```
It will not show anything for all others.

Let's say we only want to print the delete link if the role is actually allowed to do that:
```php
echo $this->AuthUser->postLink('Delete this', ['action' => 'delete', $id], ['confirm' => 'Sure?']);
```

You can also do more complex things:
```php
if ($this->AuthUser->hasAccess(['action' => 'secretArea'])) {
echo 'Only for you: ';
echo $this->Html->link('admin/index', ['action' => 'secretArea']);
echo ' (do not tell anyone else!);
}
```

## Tips

### Use constants instead of magic strings
If you are using the `hasRole()` or `hasRoles()` checks with a DB roles table, it is always better to use the aliases than the IDs (as the IDs can change).
But even so, it is better not to use magic strings like `'moderator'`, but define constants in your bootstrap for each:
````php
// In your bootstrap
define('ROLE_MOD', 'moderator');

// In your template
if ($this->AuthUser->hasRole(ROLE_MOD)) {
...
}
```
This way, if you ever refactor them, it will be easier to adjust all occurrences, it will also be possible to use auto-completion type-hinting.

### Leverage session
Especially when working with multi-role setup, it can be useful to not every time read the current user's roles from the database.
When logging in a user you can write the roles to the session right away.
If available here, TinyAuth will use those and will not try to query the roles table (or the `roles_users` pivot table).

For basic single-role setup, the session is expected to be filled like
```php
'Auth' => [
'User' => [
'id' => '1',
'role_id' => '1',
...
]
];
```
The expected `'role_id'` session key is configurable via `roleColumn` config key.

For a multi-role setup it can be either the normalized array form
```php
'Auth' => [
'User' => [
'id' => '1',
...
'Roles' => [
'id' => '1',
...
],
]
];
```
or the simplified numeric list form
```php
'Auth' => [
'User' => [
'id' => '1',
...
'Roles' => [
'1',
'2',
...
]
]
];
```
The expected `'Roles'` session key is configurable via `rolesTable` config key.

When logging the user in you can have a custom handler modifying your input accordingly, prior to calling
```php
// Modify or add roles in $user
$this->Auth->setUser($user);
```

The easiest way here to contain the roles, however, is to have your custom `findAuth()` finder which also fetches those.
See [customizing-find-query](http://book.cakephp.org/3.0/en/controllers/components/authentication.html#customizing-find-query).
26 changes: 20 additions & 6 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,41 @@ In that case the role of this logged in user decides if that action is allowed t
## Authentication
NEW since version 1.4.0

This is done via TinyAuth Auth Component.
This is done via TinyAuth AuthComponent.

The component plays well together with the adapter (see below).
If you do not have any roles and either all are logged in or not logged in you can also use this stand-alone to make certain pages public.

See [Authentication](Authentication.md) docs.

## Authorization
For this we have a TinyAuth Authorize adapter.
For this we have a TinyAuthorize adapter.

The adapter plays well together with the component above.
But if you prefer to control the action whitelisting for authentication via code and `$this->Auth->allow()` calls, you can
also just use this adapter stand-alone for the ACL part of your application.

There is also an AuthUserComponent and AuthUserHelper to assist you in making role based decisions or displaying role based links in your templates.

See [Authorization](Authorization.md) docs.


## Contributing
There are a few guidelines that I need contributors to follow:
## Configuration
Those classes most likely share quite a few configs, in that case you definitely should use Configure to define those centrally:
````php
// in your app.php
'TinyAuth' => [
'multiRole' => true,
...
],
```
This way you keep it DRY.

- Coding standards passing: `vendor/bin/sniff` and `vendor/bin/sniff -f`
- Tests passing for Windows and Unix: `php phpunit.phar`

## Contributing
Feel free to fork and pull request.

There are a few guidelines:

- Coding standards passing: `./sniff` to check and `./sniff -f` to fix.
- Tests passing: `php phpunit.phar` to run them.
10 changes: 3 additions & 7 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,9 @@
</listeners>

<filter>
<blacklist>
<directory suffix=".php">./vendor/</directory>
<directory suffix=".ctp">./vendor/</directory>

<directory suffix=".php">./tests/</directory>
<directory suffix=".ctp">./tests/</directory>
</blacklist>
<whitelist>
<directory suffix=".php">./src</directory>
</whitelist>
</filter>

</phpunit>
18 changes: 18 additions & 0 deletions sniff
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

# Make sure this file is executable
# chmod +x sniff

if [ `echo "$@" | grep '\-\-fix'` ] || [ `echo "$@" | grep '\-f'` ]; then
FIX=1
else
FIX=0
fi

if [ "$FIX" = 1 ]; then
# Sniff and fix
vendor/bin/phpcbf --standard=vendor/fig-r/psr2r-sniffer/PSR2R/ruleset.xml --ignore=cakephp-tinyauth/vendor/,tmp/,logs/,tests/test_files/,config/Migrations/ --extensions=php -v -f ./
else
# Sniff only
vendor/bin/phpcs --standard=vendor/fig-r/psr2r-sniffer/PSR2R/ruleset.xml --ignore=cakephp-tinyauth/vendor/,tmp/,logs/,tests/test_files/,config/Migrations/ --extensions=php -v ./
fi
Loading