Skip to content

Commit

Permalink
Merge pull request #1 from visto9259/1.x
Browse files Browse the repository at this point in the history
First version
  • Loading branch information
visto9259 authored Aug 8, 2024
2 parents 7d29bf3 + 1dbb77c commit 79e39db
Show file tree
Hide file tree
Showing 23 changed files with 1,049 additions and 1 deletion.
66 changes: 66 additions & 0 deletions .github/workflows/build_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Continuous Integration

on:
push:
# Avoid running tests on changes to documentation
paths-ignore:
- 'docs/**'
pull_request:
paths-ignore:
- 'docs/**'

env:
COMPOSER_ARGS: '--no-progress'

jobs:
build:
strategy:
matrix:
php_version: ['8.1', '8.2', '8.3']
deps: ['--prefer-lowest --prefer-dist', '']
include:
- code-coverage: 'yes'
php_version: '8.3'
deps: ''
runs-on: ubuntu-latest

steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{matrix.php_version}}

- name: Show PHP version
run: php -v

- uses: actions/checkout@v4
name: Checkout branch

- name: Validate composer.json and composer.lock
run: composer validate --strict

- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v4
with:
path: vendor
key: ${{ runner.os }}-php-${{ matrix.php_version }}-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php--${{matrix.php_version}}-
- name: Install/update dependencies
run: composer update ${{matrix.deps}} $COMPOSER_ARGS

- name: Run PHPUnit test suite
if: ${{ matrix.code-coverage != 'yes' }}
run: composer run-script test

- name: Run PHPUnit test suite with coverage
if: ${{ matrix.code-coverage == 'yes' }}
run: composer run-script test-coverage

- name: Upload coverage results to Coverall
if: ${{ matrix.code-coverage == 'yes' }}
uses: coverallsapp/github-action@v2


9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
._*
.~lock.*
data/
vendor/
build/
composer.lock
composer.phar
.idea
.phpunit.result.cache
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# CHANGELOG

## 1.2.0

* `isGranted` no longer cast permissions to string. Instead, the permission is now given to your role entity as it. This
may be a potential BC if you only expected string in your `hasPermission` method.
* `PermissionInterface` is deprecated and will be removed in final implementation (likely for ZF3). RBAC should not
enforce any interface for a permission as its representation is dependant of your application. However, modules
like ZfcRbac may enforce an interface for permissions.
* Various PHPDoc fixes

## 1.1.0

* [BC] Remove factory. It was not intend to be here but rather on ZfcRbac. This way this component is completely
framework agnostic

## 1.0.0

* Initial release
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,24 @@
# LmcZfrRbac
Rbac
====

[![Build Status](https://travis-ci.org/zf-fr/rbac.png)](https://travis-ci.org/zf-fr/rbac)
[![Latest Stable Version](https://poser.pugx.org/zfr/rbac/v/stable.png)](https://packagist.org/packages/zfr/rbac)
[![Total Downloads](https://poser.pugx.org/zfr/rbac/downloads.png)](https://packagist.org/packages/zfr/rbac)

Rbac (not to be confused with ZfcRbac) is a pure PHP implementation of the RBAC (*Role based access control*)
concept. Actually, it is a Zend Framework 3 prototype of the ZF2 Zend\Permissions\Rbac component.

It aims to fix some design mistakes that were made to make it more usable and more efficient.

It differs on those points:

* A `PermissionInterface` has been introduced.
* `RoleInterface` no longer have `setParent` and `getParent` methods, and cannot have children anymore (this is
used to implement a simpler "flat RBAC").
* A new `HierarchicalRoleInterface` has been introduced to allow roles to have children.
* Method `hasPermission` on a role no longer recursively iterate the children role, but only check its own permissions.
To properly check if a role is granted, you should use the `isGranted` method of the `Rbac` class.
* `Rbac` class is no longer a container. Instead, it just has a `isGranted` method. The container was complex to
properly handle because of role duplication, which could lead to security problems if not used correctly.

This library is used in ZfcRbac 2.0
49 changes: 49 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"name": "lm-commons/lmc-zfr-rbac",
"description": "Clone of zfr/rbac v1.2",
"type": "library",
"license": "MIT",
"keywords": [
"zf2",
"zf3",
"rbac",
"security"
],
"homepage": "https://github.com/lm-commons/LmcZfrRbac",
"authors": [
{
"name": "Michaël Gallego",
"email": "[email protected]"
},
{
"name": "Eric Richer",
"email": "[email protected]"
}
],
"require": {
"php": "^8.0"
},
"require-dev": {
"zendframework/zend-servicemanager": "~2.2",
"phpunit/phpunit": "^10.0 || ^11.0",
"squizlabs/php_codesniffer": "^3.5.5",
"php-coveralls/php-coveralls": "^2.2",
"phpspec/prophecy-phpunit": "^2.0"
},
"autoload": {
"psr-4": {
"Rbac\\": "src/Rbac"
}
},
"scripts": {
"check": [
"@cs",
"@test"
],
"cs": "phpcs -n --standard=PSR2 ./src/",
"cs-fix": "phpcbf ./src/",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml",
"test-coverage-html": "phpunit --colors=always --coverage-html ./build/html"
}
}
18 changes: 18 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
bootstrap="./tests/Bootstrap.php"
colors="true"
displayDetailsOnTestsThatTriggerDeprecations="true"
>
<testsuite name="ZfrRbac tests">
<directory>./tests</directory>
</testsuite>
<logging/>
<source>
<include>
<directory>./src</directory>
</include>
</source>
</phpunit>
28 changes: 28 additions & 0 deletions src/Rbac/Permission/PermissionInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Rbac\Permission;

/**
* Interface for permission
*
* @deprecated It will be removed from final implementation (likely for Zend Framework 3)
*/
interface PermissionInterface
{
/**
* Get the permission name
*
* You really must return the name of the permission as internally, the casting to string is used
* as an optimization to avoid type checkings
*
* @return string
*/
public function __toString();
}
68 changes: 68 additions & 0 deletions src/Rbac/Rbac.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Rbac;

use Rbac\Role\RoleInterface;
use Rbac\Traversal\Strategy\TraversalStrategyInterface;
use Traversable;

/**
* Rbac object. It is used to check a permission against roles
*/
class Rbac
{
/**
* @var TraversalStrategyInterface
*/
protected $traversalStrategy;

/**
* @param TraversalStrategyInterface $strategy
*/
public function __construct(TraversalStrategyInterface $strategy)
{
$this->traversalStrategy = $strategy;
}

/**
* Determines if access is granted by checking the roles for permission.
*
* @param RoleInterface|RoleInterface[]|Traversable $roles
* @param mixed $permission
* @return bool
*/
public function isGranted($roles, $permission)
{
if ($roles instanceof RoleInterface) {
$roles = [$roles];
}

$iterator = $this->traversalStrategy->getRolesIterator($roles);

foreach ($iterator as $role) {
/* @var RoleInterface $role */
if ($role->hasPermission($permission)) {
return true;
}
}

return false;
}

/**
* Get the strategy.
*
* @return TraversalStrategyInterface
*/
public function getTraversalStrategy()
{
return $this->traversalStrategy;
}
}
49 changes: 49 additions & 0 deletions src/Rbac/Role/HierarchicalRole.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Rbac\Role;

use Traversable;

/**
* Simple implementation for a hierarchical role
*/
class HierarchicalRole extends Role implements HierarchicalRoleInterface
{
/**
* @var array|RoleInterface[]
*/
protected array $children = [];

/**
* {@inheritDoc}
*/
public function hasChildren(): bool
{
return !empty($this->children);
}

/**
* {@inheritDoc}
*/
public function getChildren(): Traversable|array
{
return $this->children;
}

/**
* Add a child role
*
* @param RoleInterface $child
*/
public function addChild(RoleInterface $child): void
{
$this->children[$child->getName()] = $child;
}
}
34 changes: 34 additions & 0 deletions src/Rbac/Role/HierarchicalRoleInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Rbac\Role;

use Traversable;

/**
* Interface for a hierarchical role
*
* A hierarchical role is a role that can have children.
*/
interface HierarchicalRoleInterface extends RoleInterface
{
/**
* Check if the role has children
*
* @return bool
*/
public function hasChildren(): bool;

/**
* Get child roles
*
* @return array|RoleInterface[]|Traversable
*/
public function getChildren(): array|Traversable;
}
Loading

0 comments on commit 79e39db

Please sign in to comment.