Skip to content

Commit

Permalink
Merge pull request #57 from visto9259/update_v1_docs
Browse files Browse the repository at this point in the history
Update v1 docs
  • Loading branch information
visto9259 authored Jul 11, 2024
2 parents 542e893 + 8cedda4 commit 5858eb4
Show file tree
Hide file tree
Showing 19 changed files with 827 additions and 247 deletions.
6 changes: 3 additions & 3 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

## From ZfcRbac v3 to LmcRbac v1

The ZF-Commons orgnisation has been moved to Laminas-Commons and ZfcRbac has been split into two repositories.
The ZF-Commons organisation has been moved to LM-Commons and ZfcRbac has been split into two repositories.

- [LmcRbacMvc](https://github.com/Laminas-Commons/LmcRbacMvc) contains the old version 2 of ZfcRbac.
- [LmcRbacMvc](https://github.com/LM-Commons/LmcRbacMvc) contains the old version 2 of ZfcRbac.
- LmcRbac contains the version 3 of ZfcRbac, which was only released as v3.alpha.1.

To upgrade

- Uninstall `zf-commons/zfc-rbac:3.0.0-alpha.1`.
- Install `laminas-commons/lmc-rbac:^1.0`
- Install `lm-commons/lmc-rbac:^1.0`
- Change `zfc-rbac.global.php` to `lmc-rbac.global.php` and update the key `zfc_rbac` to `lmc_rbac`.
- Review your code for usages of the `ZfcRbac/*` namespace to `LmcRbac/*` namespace.

Expand Down
2 changes: 1 addition & 1 deletion config/config.global.php → config/lmcrbac.global.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
* It must be an array that contains configuration for the role provider.
* The default Role Provider is 'LmcRbac\Role\InMemoryRoleProvider'
*
* Supported options depend of the role provider, so please refer to the official documentation
* Supported options depend on the role provider, so please refer to the official documentation
*
* The provider config for InMemoryRoleProvider must follow the following format:
*
Expand Down
4 changes: 2 additions & 2 deletions docs/blog/2024-04-11-New-documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
slug: new-documentation
title: New documentation
authors: [ericr]
tags: [laminas, PHP, LmcUser, authentication, LM-Commons]
tags: [laminas, PHP, LmcRbac, authorization, LM-Commons]
---
This the new documentation site dedicated to the LmcUser module.
This the new documentation site dedicated to the LmcRbac module.

There are no changes to the code, just improvements in the documentation.
144 changes: 144 additions & 0 deletions docs/docs/assertions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
---
sidebar_label: Dynamic Assertions
sidebar_position: 6
title: Dynamic Assertions
---

Dynamic Assertions provide the capability to perform extra validations when
the authorization service's `isGranted()` method is called.

As described in [Authorization Service](authorization-service#reference), it is possible to pass a context to the
`isGranted()` method. This context is then passed to dynamic assertion functions. This context can be any object type.

You can define dynamic assertion functions and assigned them to permission via configuration.

## Defining a dynamic assertion function

A dynamic assertion must implement the `LmcRbac\Assertion\AssertionInterace` which defines only one method:

```php
public function assert(
string $permission,
IdentityInterface $identity = null,
$context = null
): bool
```
The assertion returns `true` when the access is granted, `false` otherwise.

A simple assertion could be to check that user represented by `$identity`, for the permission
represented by `$permission` owns the resource represented by `$context`.

```php
<?php

class MyAssertion implements \LmcRbac\Assertion\AssertionInterface
{
public function assert(string $permission, IdentityInterface $identity = null, $context = null): bool
{
// for 'edit' permission
if ('edit' === $permission) {
/** @var MyObjectClass $context */
return $context->getOwnerId() === $identity->getId();
}
// This should not happen since this assertion should only be
// called when the 'edit' permission is checked
return true;
}
}
```
## Configuring Assertions

Dynamic assertions are configured in LmcRbac via an assertion map defined in the LmcRbac configuration where assertions
are associated with permissions.

The `assertion_map` key in the configuration is used to define the assertion map. If an assertion needs to be created via
a factory, use the `assertion_manager` config key. The Assertion Manager is a standard
plugin manager and its configuration should be a service manager configuration array.

```php
<?php

return [
'lmc_rbac' => [
/* the rest of the file */
'assertion_map' => [
'edit' => \My\Namespace\MyAssertion::class,
],
'assertion_manager' => [
'factories' => [
\My\Namespace\MyAssertion::class => \Laminas\ServiceManager\Factory\InvokableFactory::class
],
],
],
];
```
It is also possible to configure an assertion using a callable instead of a class:

```php
<?php

return [
'lmc_rbac' => [
/* the rest of the file */
'assertion_map' => [
'edit' => function assert(string $permission, IdentityInterface $identity = null, $context = null): bool
{
// for 'edit' permission
if ('edit' === $permission) {
/** @var MyObjectClass $context */
return $context->getOwnerId() === $identity->getId();
}
// This should not happen since this assertion should only be
// called when the 'edit' permission is checked
return true;
},
],
],
];
```
## Dynamic Assertion sets

LmcRbac supports the creation of dynamic assertion sets where multiple assertions can be combined using 'and/or' logic.
Assertion sets are configured by associating an array of assertions to a permission in the assertion map:

```php
<?php

return [
'lmc_rbac' => [
/* the rest of the file */
'assertion_map' => [
'edit' => [
\My\Namespace\AssertionA::class,
\My\Namespace\AssertionB::class,
],
'read' => [
'condition' => \LmcRbac\Assertion\AssertionSet::CONDITION_OR,
\My\Namespace\AssertionC::class,
\My\Namespace\AssertionD::class,
],
'delete' => [
'condition' => \LmcRbac\Assertion\AssertionSet::CONDITION_OR,
\My\Namespace\AssertionE::class,
[
'condition' => \LmcRbac\Assertion\AssertionSet::CONDITION_AND,
\My\Namespace\AssertionF::class,
\My\Namespace\AssertionC::class,
],
],
/** the rest of the file */
],
];
```
By default, an assertion set combines assertions using a 'and' condition. This is demonstrated by the map associated with
the `'edit'` permission above.

It is possible to combine assertions using a 'or' condition by adding a `condition` equal to `AssertionSet::CONDITION_OR`
to the assertion set as demonstrated by the map associated with the `'read'` permission above.

Furthermore, it is possible to nest assertion sets in order to create more complex logic as demonstrated by the map
associated with the `'delete'` permission above.

The default logic is to combine assertions using 'and' logic but this can be explicitly set as shown above for `'delete'`
permission.

33 changes: 33 additions & 0 deletions docs/docs/authorization-service.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
sidebar_label: Authorization service
sidebar_position: 5
title: Authorization Service
---

### Usage

The Authorization service can be retrieved from the service manager using the name
`LmcRbac\Service\AuthorizationServiceInterface` and injected into your code:

```php
<?php
/** @var \Psr\Container\ContainerInterface $container */
$authorizationService = $container->get(LmcRbac\Service\AuthorizationServiceInterface::class);

```
### Reference

`LmcRbac\Service\AuthorizationServiceInterface` defines the following method:

`isGranted(?IdentityInterface $identity, string $permission, $context = null): bool`

| Parameter | Description |
|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `$identity` | The identity whose roles to checks. <br/>If `$identity` is null, then the `guest` is used. <br/>The `guest` role is definable via configuration and defaults to `'guest'`. |
| `$permission` | The permission to check against |
| `$context` | A context that will be passed to dynamic assertions that are defined for the permission |

More on dynamic assertions can be found in the [Assertions](assertions.md) section.

More on the `guest` role can be found in the [Configuration](configuration.md) section.

44 changes: 44 additions & 0 deletions docs/docs/concepts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
sidebar_label: Concepts
sidebar_position: 2
title: Concepts
---

[Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
is an approach to restricting system access to authorized users by putting emphasis
on roles and their permissions.

In the RBAC model:

- an **identity** has one of more roles.
- a **role** has one of more permissions.
- a **permission** is typically an action like "read", "write", "delete".
- a **role** can have **child roles** thus providing a hierarchy of roles where a role will inherit the permissions of all its child roles.

## Authorization

An identity will be authorized to perform an action, such as accessing a resource, if it is granted
the permission that controls the execution of the action.

For example, deleting an item could be restricted to identities that have at least one role that has the
`item.delete` permission. This could be implemented by defining a `member` role that has the `item.delete` and assigning
this role of an authenticated user.

## Dynamic Assertions

In some cases, just checking if the identity has the `item.delete` permission is not enough.
It would also be necessary to check, for example, that the `item` belongs to the identity. Dynamic assertion allow
to specify some extra checks before granting access to perform an action such as, in this case, being the owner of the
resource.

## Identities

An identity is typically provided by an authentication process within the application.

Authentication is not in the scope of `LmcRbac` and it is assumed that an identity entity providing assigned roles
is available when using the authorization service. If no identity is available, as it would be the case when no user is "logged in",
then a guest role is assumed.




18 changes: 18 additions & 0 deletions docs/docs/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
sidebar_label: Configuration
sidebar_position: 7
title: Configuring LmcRbac
---

LmcRbac is configured via the `lmc_rbac` key in the application config.

This is typically achieved by creating
a `config/autoload/lmcrbac.global.php` file. A sample configuration file is provided in the `config/` folder.

## Reference

| Key | Description |
|--|------------------------------------------------------------------------------------------------------------------------------------------------|
| `guest_role` | Defines the name of the `guest` role when no identity exists. <br/>Defaults to `'guest'`. |
| `assertion_map` | Defines the dynamic assertions that are associated to permissions.<br/>Defaults to `[]`.<br/>See the [Dynamic Assertions](assertions) section. |
| `role_provider` | Defines the role provider.<br/>Defaults to `[]`<br/>See the [Role Providers](role-providers) section. |
34 changes: 34 additions & 0 deletions docs/docs/gettingstarted.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
sidebar_label: Getting Started
sidebar_position: 1
title: Get started
---
## Requirements

- PHP 7.3 or higher

:::warning
The code is continuously tested against PHP 8.1 and higher only. There is no warranty that it will work for PHP 8.0 and lower.
:::

## Installation

LmcRbac only officially supports installation through Composer.

Install the module:

```sh
$ composer require lm-commons/lmc-rbac "~1.0"
```

You will be prompted by the `laminas-component-installer` plugin to inject LM-Commons\LmcRbac.

:::note
**Manual installation:**

Enable the module by adding `LmcRbac` key to your `application.config.php` or `modules.config.php` file for Laminas MVC
applications, or to the `config/config.php` file for Mezzio applications.
:::

Customize the module by copy-pasting
the `lmcrbac.global.php` file to your `config/autoload` folder.
26 changes: 0 additions & 26 deletions docs/docs/installation.md

This file was deleted.

15 changes: 0 additions & 15 deletions docs/docs/introduction.md

This file was deleted.

22 changes: 22 additions & 0 deletions docs/docs/migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
sidebar_label: Migration Guide
sidebar_position: 8
title: Migration Guide
---

## Migrating from ZF-Commons RBAC v3

The ZF-Commons Rbac was created for the Zend Framework. When the Zend Framework was migrated to
the Laminas project, the LM-Commons organization was created to provide components formerly provided by ZF-Commons.

When ZfcRbac was moved to LM-Commons, it was split into two repositories:

- [LmcRbacMvc](https://github.com/LM-Commons/LmcRbacMvc) contains the old version 2 of ZfcRbac.
- LmcRbac contains the version 3 of ZfcRbac, which was only released as v3.alpha.1.

To upgrade

- Uninstall `zf-commons/zfc-rbac:3.0.0-alpha.1`.
- Install `lm-commons/lmc-rbac:~1.0`
- Change `zfc-rbac.global.php` to `lmcrbac.global.php` and update the key `zfc_rbac` to `lmc_rbac`.
- Review your code for usages of the `ZfcRbac/*` namespace to `LmcRbac/*` namespace.
Loading

0 comments on commit 5858eb4

Please sign in to comment.