Coder Social home page Coder Social logo

owasp / rbac Goto Github PK

View Code? Open in Web Editor NEW
427.0 54.0 139.0 5.77 MB

PHP-RBAC is an authorization library for PHP. It provides developers with NIST Level 2 Standard Role Based Access Control and more, in the fastest implementation yet.

Home Page: http://phprbac.net/

License: Apache License 2.0

PHP 99.75% Shell 0.25%

rbac's Introduction

#PHP-RBAC v2.x

PHP-RBAC is an authorization library for PHP. It provides developers with NIST Level 2 Hierarchical Role Based Access Control and more, in the fastest implementation yet.

Current Stable Release: PHP-RBAC v2.0

##Connect With Us

##What is an Rbac System?

Take a look at the "Before You Begin" section of our Documentation to learn what an RBAC system is and what PHP-RBAC has to offer you and your project.

##NIST Level 2 Compliance

For information regarding NIST RBAC Levels, please see This Paper.

For more great resources see the NIST RBAC Group Page.

##Installation

You can now use Composer to install the PHP-RBAC code base.

For Installation Instructions please refer to the "Getting Started" section of our Documentation.

##Usage##

Instantiating a PHP-RBAC Object

With a 'use' statement:

    use PhpRbac;
    
    $rbac = new Rbac();

Without a 'use' statement, outside of a namespace:

    $rbac = new PhpRbac\Rbac();

Without a 'use' statement, inside of another namespace (notice the leading backslash):

    $rbac = new \PhpRbac\Rbac();

##PHP-RBAC and PSR

PHP-RBAC's Public API is now fully PSR-0, PSR-1 and PSR-2 compliant.

You can now:

  • Use Composer to install/update PHP-RBAC
  • Use any PSR-0 compliant autoloader with PHP-RBAC
  • Use the included autoloader to load PHP-RBAC

If you notice any conflicts with PSR compliance please Submit an Issue.

##The future of PHP-RBAC

We are in the process of refactoring the PHP-RBAC internals. We have two goals in mind while doing this:

With a PSR compliant Public API already in place we can continue to work towards our goals one piece at a time without altering the Public API that developers are working with and rely on, making the transition as seamless and invisible as possible.

##Contributing##

We welcome all contributions that will help make PHP-RBAC even better tomorrow than it is today!

Please visit the PHP-RBAC Wiki to learn about our development process and workflow.

###How You Can Help

rbac's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rbac's Issues

Error Handling: Need improvements to database error handling

The error handling could be improved when a database exists but does not contain tables.

For MySQL:

If there is already a database but no tables then $rbac->reset(true) returns true, even though no tables are created and no data is inserted.

I think there should either be a check to make sure that reset() actually inserted data into the database or a check to make sure that the tables have been created prior to executing reset(). This does sound like it could be resource intensive if we're checking for an existing database and existing tables inside 'setup.php'.

For MySQLi:

Same issue, but php sends warnings and errors on its own.

For SQLite:

Still need to test with an empty database.

PDOStatement->fetchAll(); after an INSERT query results in an error (jf.php)

Using PDOStatement->fetchAll() after an INSERT query results in an error : "SQLSTATE[HY000]: General error" (ex: using Mysql/PDO with PropelORM on Symfony2 framework)

I fix'd it this way into jf.php :

static function SQL_pdo($Query)
{
    $args = func_get_args ();
    if (count ( $args ) == 1)
    {
        $result = self::$Db->query ( $Query );

        /* --- OLD ---
        if ($result===false)
            return null;
        $res=$result->fetchAll ( PDO::FETCH_ASSOC );
        if ($res===array())
            return null;
        return $res;
        //--- OLD --- */

        // --- FIX ---
        $type = substr ( trim ( strtoupper ( $Query ) ), 0, 6 );
        if ($type == "INSERT")
        {
            if ($result===false)
                return null;
            $res = self::$Db->lastInsertId ();
            if ($res == 0)
                return $result->rowCount ();
            return $res;
        }
        elseif ($type == "DELETE" or $type == "UPDATE" or $type == "REPLAC")
            return $result->rowCount ();
        elseif ($type == "SELECT")
        {
            $res=$result->fetchAll ( PDO::FETCH_ASSOC );
            if ($res===array())
                return null;
            else
                return $res;
        }
        // --- FIX ---

    }
    else
    {
        if (! $stmt = self::$Db->prepare ( $Query ))
        {
            return false;
        }
        array_shift ( $args ); // remove $Query from args
        $i = 0;
        foreach ( $args as &$v )
            $stmt->bindValue ( ++ $i, $v );

        $success=$stmt->execute ();

        $type = substr ( trim ( strtoupper ( $Query ) ), 0, 6 );
        if ($type == "INSERT")
        {
            if (!$success)
                return null;
            $res = self::$Db->lastInsertId ();
            if ($res == 0)
                return $stmt->rowCount ();
            return $res;
        }
        elseif ($type == "DELETE" or $type == "UPDATE" or $type == "REPLAC")
            return $stmt->rowCount ();
        elseif ($type == "SELECT")
        {
            $res=$stmt->fetchAll ( PDO::FETCH_ASSOC );
            if ($res===array())
                return null;
            else
                return $res;
        }
    }
}

can some one tell me about the leftId and rightId meanings?

can some one tell me about the leftId and rightId meanings?
CREATE TABLE IF NOT EXISTS rbac_permissions (
ID int(11) NOT NULL AUTO_INCREMENT,
Lft int(11) NOT NULL,
Rght int(11) NOT NULL,
Title char(64) COLLATE utf8_bin NOT NULL,
Description text COLLATE utf8_bin NOT NULL,
PRIMARY KEY (ID),
KEY Title (Title),
KEY Lft (Lft),
KEY Rght (Rght)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=5 ;

License?

I'm used to seeing a license included in the readme or a txt file in the root (license.txt, legalnotes, etc.). Is this information found somewhere else in the repo? Can someone add an appropriate reference in a "usual" place?

BaseRBAC: Create a 'getList()' method

Right now there are no methods to get/return all Roles/Permissions.

I think a good addition to the BaseRBAC class would be a 'getList()' method that does just that.

Alternative proposed names:

  • getList
  • getAll
  • listAll

PathID length calculation error

The following code on line 120 of rbac.php:

    // $row_count = jf::SQL ( "SELECT count(*) FROM " . $this->tablePrefix() . $this->type());
    // $separator_count = --$row_count[0]['count(*)'];
    // $total_char_count = $query_char_count + $separator_count;

    // if ((int) $total_char_count >= 1024)
    //     throw new Exception ( "Path exceeds character count limit" );

Is invalid, because it counts for all the nodes that exist, and not just the ones that are being used! And always throws exceptions on big enough data sets. Should be fixed.

setup.php: Mysqli setup - throws 'Unknown database' warning

While testing the GUI installer I discovered that I get an 'Unknown database' warning. This does NOT cause execution to stop. The specified database IS created and populated with the required initial data.

Steps to reproduce:

  1. Create a database user with proper permissions to create databases
    Do not create a database

  2. Create a valid 'database.config' file

  3. Instantiate a 'PhpRbac\Rbac' object:

    require_once 'rbac/PhpRbac/autoload.php';
    $rbac = new PhpRbac\Rbac();
    
  4. Execute the following:

    $rbac->reset(true);
    

5a. If you finish script execution on this page you will see the following warning:

    Warning: mysqli::mysqli() [mysqli.mysqli]: (42000/1049): Unknown database 'test_database' in path\to\PhpRbac\src\PhpRbac\core\setup.php on line 27

5b. You will not see this warning if you forward the client to another page or part of the script that causes the script to (re)load:

    header("Location: index.php");

This is a minor issue, but I still feel it should be looked at.

Unit Tests: Need new/updated Unit Tests for recent API changes

This Issue will be used to keep track of new/altered unit tests needed for v2.0 Stable release.

Tests:

  • [COMPLETE] BaseRbac::pathId() - Extended group_concat max char limit
  • [COMPLETE] BaseRbac::addPath() - Should return number of nodes created
  • [COMPLETE] BaseRbac::assign() - Should be able to assign using Id, Title and Path
  • [COMPLETE] BaseRbac::unassign() - Should be able to unassign using Id, Title and Path
  • [COMPLETE] RbacUserManager::unassign() - Should be able to unassign using Id, Title and Path

The following methods need to be changed because addPath returns number of nodes created, not the id of the last node created:

  • [COMPLETE] RbacManagerTest::testManagerCheckPath() - RbacManagerTest.php, line 143
  • [COMPLETE] RbacManagerTest::testManagerEnforcePath() - RbacManagerTest.php, line 221
  • [COMPLETE] RbacUsersTest::testUsersAssignWithPath() - RbacUsersTest.php, line 53
  • [COMPLETE] RbacUsersTest::testUsersHasRolePath() - RbacUsersTest.php, line 122

Results:

Windows 8.1

  • MySQL
    • All tests pass
  • SQLite
    • All tests pass

Linux: CENTOS 6.5 x86_64

  • MySQL
    • All tests pass
  • SQLite
    • All tests pass

Notes:

  • Had to change all instances of 'is_int' to 'is_numeric'
  • Removed all 'core' Unit Tests
  • Should we also create Unit Tests for MySQLi adapter as well? If so I'll create a new Issue to address this.
    • We might want to wait and see if we switch to a lightweight Database Abstraction Layer.

      I have created MySQLi specific PHPUnit connection scripts locally and there were fails and errors, but that is mainly due to the PHP MySQLi library returning strings instead of integers, and returning '-1' instead of 0 on failed queries.

      These return values do not seem to have a negative effect when working with the 'mysqli' adapter. The reason the tests fail is because the PHPUnit assertions test for value AND type, while PHP itself is a dynamic language and has no problems working with numeric strings vs integers.

      If we wanted to use a lightweight DAL while refactoring the core into PSR compliant code then the results will be consistent between databases. This is not a small decision and will take a lot of conversation and benchmarks to come to a decision.

Is it possible to create database.config outside the /vendor (composer)?

I think it would be more convenient to work with composer when I can store config file as part of my repository (outside /vendor dir, which is not included). As example: phinx library.

And another one about installation: if i already have database (without rbac tables) install script just telling me "ok, congrats...", but actually it wasn't, because mysql file was not executed.

Entire Code Base: Methods are not checking for valid/existing Roles and Permissions

It seems that most methods (mainly assignment methods) are not checking to see if we are trying to assign valid/existing Roles and Permissions.

Example:

  • The only Role/Permission in the database is the 'root' Role and 'root' Permission when we execute this,

    $rbac->Assign(5, 5);
    

    After execution the rolepermission table contains this

    RoleID = 5, PermissionID = 5
    

Result:

  • We now have a role->permission relation to non-existent roles and permissions.

Should we be checking for the existence of roles/permissions before trying to manipulate them?

Please improve your exception handling

At the moment, your code appears to make no attempt whatsoever to catch errors... after entering database details on the first install.php screen and clicking submit, I was greeted by a white screen.

No on-screen error messages, only found out more once I'd dug through the PHP logs.

PHP message: PHP Warning: chmod(): Operation not permitted in /usr/XXXX/www/lib/PhpRbac/install
.php on line 286
PHP message: PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] [14] unable to
open database file' in /usr/XXXX/www/lib/PhpRbac/src/PhpRbac/core/setup.php:51

Typo in jf.php

File jf.php
Line 89

elseif ($type == "DELETE" or $type == "UPDATE" or $type == "REPLAC") 

should be REPLACE

Pass PDO instance as adapter.

It would be beneficial if the database connection can be passed as a PDO object that's already been initialised.

This makes sense for applications where the pdo object has already been created and connection details don't have to be looked up again. It's also useful for PDO objects that are created using more complex connection mechanisms than the usual host, username, password.

As a practical example, I would like to make use of PDO MySQL's SSL features (documented in the php manual), but I'm not currently able to do so due to the limitations of the way database connections are handled by PhpRbac.

$rbac->reset() does not set up correct links with root due to auto increment settings

(I could have some issues with my database so I need someone else to confirm this)

After running $rbac->reset() I get the following in my mysqli database as default values:

rolepermissions.RoleID = 1,
rolepermissions.PermissionID = 1
permissions.ID = y
roles.ID = x
userroles.RoleID = x

The auto increment number for Permissions.ID and Roles.ID are not reset to 1, the link between the Permissions and Roles in the rolepermissions table is therefore broken. X and Y should be equal to 1.

Seems not to cause any issue in the userroles table as this link is kept.

I suppose an easy fix would be to also reset the auto increment value, or to drop the table and recreate it completely. The former could have unforseen impacts on custom implementations of your library.

Edit: I am using v2.0.0 release

$rbac->EntityType->PathID(): Tests Fail On Linux Server

PathID passes tests on my local windows box, yet the tests fail on my linux server.

I've getting a few errors on my linux box that I'm not getting on my local Windows box, and at first I was chalking it up to case sensitivity, but that doesn't seem to be the case here.

I've narrowed it down to the SQL Query, namely the 'ORDER BY parent.Lft' clause:
https://github.com/OWASP/rbac/blob/dev/PSR/Unit_Tests/PhpRbac/src/PhpRbac/core/lib/rbac.php#L116

With the ORDER BY clause the query works properly and returns the expected result on my Windows box. On my Linux box the query executes with no errors yet returns zero results.

If I remove the ORDER BY clause then PathID works properly in both test environments.

I'm not used to queries with so much going on, but I have a couple observations.

  • Since the 'GROUP_CONCAT' is ordering results by 'parent.Lft' (at least with mysql), does the entire query need to be order by that?
  • Can we ORDER BY a field that is not returned in the result set?
  • Since with we're searching by path would there ever be multiple results that need to be ordered?

Those are really questions more than observations.

I've done lot of research and testing in both environments and this is what I've been able to put together.

Abiusx, would you be able to take a look at this and let me know what you come up with?

Thanks!

Open source website

Hi

I've come across a few problems on the phprbac.net website. I'd love to be able to send pull requests for those, especially for documentation fixes. Any chance of making that website open source? Perhaps on a new orphan branch of this repository even, I'd happily do the legwork if anyone wants to send me the relevant files in a zip file.

Cheers
Sheldon

AddPath node creation

AddPath should return the number of nodes created, not the ID of the final node. That can be get by PathID later. AddPath omits nodes that exist, so the number of nodes that are actually created are important. The following code helps (rbac.php line 240):
if (! $t)
{
$IID = $this->Add ( $p, $Description, $Parent );
$Parent = $IID;
$NodesCreated++;
}
else
{
$Parent = $t;
}

        $index += 1;

No joy with install.php

I get my credentials in, hit submit and all I get is a blank screen. Any suggestions as to what could be going wrong?

I'm:

  • Using mysql (mariadb)
  • Getting the code from the sourceforge download (2.0)

Very slow and buggy?

Hi,

First, I want to say that I find the utter lack of online source code demos for PHPRBAC to be troubling. But now this github issue will be one of the primary example code snippets on the Internet, so I'm hoping you can get this to work by showing me the error of my ways!

The following code mostly works, except for two failures which you'll see below. However, it takes an incredibly long time (30-40 seconds on an Intel i7). I want to know 1) how to fix the failures, 2) how to increase the performance dramatically and 3) any other tips you can give me.

Thank you so much! Time is of the essence.

Output:

Success: User 1 has the 'intent to leave' permission.
Success: User 1 has the 'profile-blocks-1' permission.
Failure! User 1 has the 'profile-blocks-2' permission.
Success! 'survey items-3' is an unknown/invalid permission.
Success: User 2 has the 'intent to leave' permission.
Failure! User 2 has the 'profile-blocks-1' permission.
Success: User 2 has the 'profile-blocks-n' permission.
Success! 'survey items-3' is an unknown/invalid permission.
<?php
// PHP-RBAC Proof of Concept

require_once 'PhpRbac/autoload.php';
header('Content-Type: text/plain');

$rbac = new PhpRbac\Rbac();

$commonPerms = [
    'intent-to-leave',
    'referrals-public-view',
    'referrals-teams-view',
];

$role1Perms = [
    'access level-individual_aggregate'.
    'risk-indicator',
    'profile-blocks-1',
    'profile-blocks-4',
    'profile-blocks-n',
    'profile-items-2',
    'profile-items-n',
    'survey-blocks-2',
    'survey-blocks-4',
    'survey-blocks-n',
    'survey-items-2',
    'survey-items-n',
    'notes-public-view',
    'notes-teams-view',
    'contacts-public-view',
    'contacts-teams-view',
    'booking-public-view',
    'booking-teams-view',
];

$role2Perms = [
     'access-level_aggregate',
     'profile-blocks-2',
     'profile-blocks-4',
     'profile-blocks-n',
     'profile-items-2',
     'profile-items-n',
     'survey-blocks-2',
     'survey-blocks-4',
     'survey-blocks-n',
     'survey-items-2',
     'survey-items-n',
     'notes-public-create',
     'notes-teams-create',
     'contacts-public-view',
     'contacts-private-create',
     'contacts-teams-view',
     'booking-public-create',
     'booking-teams-create',
     'referrals-private-create',
];

$role3Perms = [
    'access-level_individual_aggregate',
    'risk-indicator',
    'referrals-public-create',
    'referrals-private-create',
    'referrals-teams-create',
    'receive-referrals',
];


$commonRoleId = $rbac->Roles->add('common_role', 'Common permissions for all users');

foreach ($commonPerms as $info) {
    $permId = $rbac->Permissions->add($info, 'Default description', $commonRoleId);
    $rbac->Roles->assign('common_role', $permId);
}

$role1Id = $rbac->Roles->add('role1', 'Role 1', $commonRoleId);

foreach ($role1Perms as $permName) {
    $rbac->Permissions->add($permName, 'Default description', $role1Id);
    $rbac->Roles->assign('role1', $permName);
}

$role2Id = $rbac->Roles->add('role2', 'Role 2', $commonRoleId);

foreach ($role2Perms as $permName) {
    $rbac->Permissions->add($permName, 'Default description', $role2Id);
    $rbac->Roles->assign('role2', $permName);
}


// Create User
$users = [
    [
        'id' => 1,
        'username' => 'admin',
        'roles' => [
            'role1'
        ]
    ],
    [
        'id' => 2,
        'username' => 'editor',
        'roles' => [
            'common_role',
            'role2'
        ]
    ],
];

// Assign the proper roles.
foreach ($users as $user) {
    if (!empty($user['roles']) && is_array($user['roles'])) {
        foreach ($user['roles'] as $role) {
            $rbac->Users->assign($role, $user['id']);
        }
    }
}


$tests = [
    $users[0]['id'] => [
        'intent to leave' => true,
        'profile-blocks-1' => true,
        'profile-blocks-2' => false,
        'survey items-3' => false,
    ],
    $users[1]['id'] => [
        'intent to leave' => true,
        'profile-blocks-1' => false,
        'profile-blocks-n' => true,
        'survey items-3' => false,
    ],
];


// Validate if a user has a particular permission.
foreach ($tests as $userId => $test) {
    foreach ($test as $permission => $hasPermission) {
        $permissionVerb = $hasPermission ? 'has' : 'doesn\'t have';
        $noPermissionVerb = $hasPermission ? 'doesn\'t have' : 'has';
        try {
            if ($rbac->check($permission, $userId) === $hasPermission) {
                echo "Success: User {$userId} $permissionVerb the '{$permission}' permission.\n";
            } else {
                echo "Failure! User {$userId} $noPermissionVerb the '{$permission}' permission.\n";
            }
        }
        catch(Exception $e) {
            $status = $hasPermission ? 'Failure' : 'Success';
            echo "$status! '{$permission}' is an unknown/invalid permission.\n";
        }
    }
}

Enhancement: New method to move a node and it's descendants

We've recognized the need for a new method that will move a node and it's descendants from one part of the hierarchy to another part of the hierarchy.

The reason for this is that assets and their roles/permissions change over time.

Deleting an existing node and its descendants and then recreating the same node and its descendants on a different part of the hierarchy is time consuming, inefficient and error prone.

Creating a "BaseRbac::moveNode()" method (or similar naming scheme) which will actually move a node and its descendants to a different part of the hierarchy will save time and minimize the risk for errors.

How does Hierarchy work?

TL:DR; I'm not sure how the hierarchy works :)

I've been running some tests on rbac.
I have 3 roles (member, collaborator, admin).
member has basic permissions
collaborator should have member permissions plus some others (created with parent: member).
admin should have collaborator permissions plus some others (created with parent: collaborator).
The 'root' role has the 'root' permission, has no parents and no children.

Here's what I came up to (my debugging output only, plus resulting table):

truncate table permissions
truncate table rolepermissions
truncate table roles
INSERT INTO `phprbac_permissions` (`ID`, `Lft`, `Rght`, `Title`, `Description`) VALUES (1, 0, 1, "root", "root");
INSERT INTO `phprbac_rolepermissions` (`RoleID`, `PermissionID`, `AssignmentDate`) VALUES (1, 1, UNIX_TIMESTAMP());
INSERT INTO `phprbac_roles` (`ID`, `Lft`, `Rght`, `Title`, `Description`) VALUES (1, 0, 1, "root", "root");

created role 'member' with description 'Registered User' and parent ''. New id: '2'

created permission 'write_site_review' with description 'Write review for a site' and parent ''. New id: '2'
assigned permission '2' to role '2'

created role 'collaborator' with description 'Collaborator user' and parent '2'. New id: '3'

created permission 'access_admin' with description 'Access the admin panel' and parent ''. New id: '3'
assigned permission '3' to role '3'

created role 'admin' with description 'Admin user' and parent '3'. New id: '4'

created permission 'view_stats' with description 'View stats' and parent ''. New id: '4'
assigned permission '4' to role '4'

created permission 'manage_users' with description 'Manage Users' and parent ''. New id: '5'
assigned permission '5' to role '4'

created permission 'edit_users' with description 'Edit Users' and parent '5'. New id: '6'
assigned permission '6' to role '4'

created permission 'export_users' with description 'Export Users as CSV' and parent '5'. New id: '7'
assigned permission '7' to role '4'

tests:

INSERT INTO `phprbac_userroles` (`UserID`, `RoleID`, `AssignmentDate`) VALUES (123, 2, UNIX_TIMESTAMP()); /*member*/
INSERT INTO `phprbac_userroles` (`UserID`, `RoleID`, `AssignmentDate`) VALUES (456, 3, UNIX_TIMESTAMP()); /*collaborator*/
INSERT INTO `phprbac_userroles` (`UserID`, `RoleID`, `AssignmentDate`) VALUES (789, 4, UNIX_TIMESTAMP()); /*admin*/

member can access admin? true //should be false
collaborator can access admin? true //ok
admin can access admin? false //should be true
member can write site reviews? true //ok
collaborator can write site reviews? false //should be true
admin can write site reviews? false //should be true

Resulting tables:
permissions

ID Lft Rght Title Description
1   0   13  root    root
2   1   2   write_site_review   Write review for a site
3   3   4   access_admin    Access the admin panel
4   5   6   view_stats  View stats
5   7   12  manage_users    Manage Users
6   8   9   edit_users  Edit Users
7   10  11  export_users    Export Users as CSV

roles

ID Lft Rght Title Description
1   0   7   root    root
2   1   6   member  Registered User
3   2   5   collaborator    Collaborator user
4   3   4   admin   Admin user

rolepermissions

RoleID PermissionID AssignmentDate
1   1   1413214573
2   2   1413214573
3   3   1413214573
4   4   1413214573
4   5   1413214573
4   6   1413214573
4   7   1413214573

I also tried reversing the parents:
admin with no parent.
collaborator with admin parent.
member with collaborator parent.

result:

member can access admin? false //ok
collaborator can access admin? true //ok
admin can access admin? false //should be true
member can write site reviews? true //ok
collaborator can write site reviews? false //should be true
admin can write site reviews? false //should be true

What am I doing wrong?

RoleManager->Permissions error

If onlyIds is false, the query should be:
return jf::SQL ( "SELECT TP.* FROM {$this->tablePrefix()}rolepermissions AS TR
RIGHT JOIN {$this->tablePrefix()}permissions AS TP ON (TR.PermissionID=TP.ID)
WHERE RoleID=? ORDER BY TP.ID", $Role );
instead of
return jf::SQL ( "SELECT TP.* FROM {$this->tablePrefix()}rolepermissions AS TR
RIGHT JOIN {$this->tablePrefix()}permissions AS TP ON (TR.PermissionID=TP.ID)
WHERE RoleID=? ORDER BY TP.PermissionID", $Role );

Installation: Updating the GUI Installation Routine

[UPDATED: 01-06-15]

I've opened this issue to track the update to the GUI Installation Routine.

Tasks:

  • Develop tests/error handling to check if 'chmod' is available and/or was successful
  • Include error handling throughout every stage of the Installation

This Issue will address Issue #31, Issue #32, Issue #33, Issue #43 and possibly Issue #35.

Notes:

  • We are currently removing "GUI Installation Routine" from the official PHP-RBAC code base
  • The "GUI Installation Routine":
    • has been labeled as a "3rd Party" contribution to PHP-RBAC (see below)
    • is currently being removed from the official PHP-RBAC code base
    • will be redesigned from the ground up as a stand-alone/optional tool
    • will be hosted in it's own individual repo under the Github Organization "[https://github.com/FriendsOf-PhpRbac](Friends of PHP-RBAC)"

3rd Party Contributions

We will be adding more information regarding "3rd Party Contributions" to a more public area of the project (official website/README/Wiki/etc...), but here's a quick explanation:

  • All functionality that is not part of the core PHP-RBAC library will be considered a "3rd Party Contribution". At this time this includes contributed tools, utilities, add-ons, integrations, etc... (including the "Installation GUI Routine" and the planned "Administrative GUI Panel")
  • All "3rd Party Contributions" will be hosted under the Github Organization "[https://github.com/FriendsOf-PhpRbac](Friends of PHP-RBAC)"
  • This includes utilities contributed by both Core Developers as well as Community Members

BaseRbac::Assign(): Allow id, path and title for both arguments

Right now the Roles/Permissions 'Assign' method is different than the Users 'Assign' method:

  • Roles->Assign() and Permissions->Assign() only take integers as their arguments
  • The Users->Assign method will take an id, path or title as it's first argument

We would like to allow the Roles->Assign() and Permissions->Assign() (it's actually one method, BaseRbac::Assign) to accept an id, path or title argument in both parameters.

Proposal

Use RBACUserManager::Assign() as a starting point. It already dynamically retrieves the RoleID. Just need to copy and alter that to get both the RoleID and PermissionID inside BaseRbac::Assign().

This issue was generated due to some discussion located in Issue #19.

Granularity of Roles/Permissions

I am looking to implement an RBAC-based authorization/entitlements management system at work (1000 employees) for various in-house applications, and thus found your PHP:RBAC library.

If you don't mind, I have a conceptual question about "permissions". Basically, permissions is the entitlement to perform action x on resource y, simple enough.

In PHP:RBAC, these distinct things (actions, resources) are merged into the single entity "permission". So the question then is, how to deal with a relatively simple use case:

  1. A user may have a role called "Translator"
  2. "Translators" may translate (action) files (resource)
  3. However, a given translator may only translate certain files, not all, depending on say
    a) language
    b) subject matter
    c) criticality

This is a little contrived of an example (not much terrible can happen if a Chinese translator had the permission to translate a Russian file where he has no clue about the subject matter - he is simply not going to do it), but I could think of more sensitive scenarios (say "Sales Person" may read (action) revenue data (resource) - but for example, he may clearly not be permissioned to read all Revenue data for all markets an all products above a given revenue threshold ).

So, how would you suggest people model this level of granularity, or does this effectively exceed the scope of what's possible with PHP:RBAC?

I worry that we'd end up with an unmanagable inflation of Roles and/or Resources, e.g. we would have to have one "Translator" role for each language (or one "Sales Person" role for each market), which right there could be quite a few roles and/or one permission for each subject matter and criticality combination (or for each product and revenue threshold combination), and we haven't even covered all actions (only read, but not say update).

Of course, we'd like to keep it as simple as possible - any suggestions?

Thanks!

Enhancement: Move *.sql files

I feel the 'mysql.sql' and 'sqlite.sql' files should be more readily accessible in the case of a manual installation.

Proposed directory: PhpRbac/database/

Updating Project Wiki To Address The Status Of PHP-RBAC

PHP-RBAC's Status & Updates - 01-24-15

There have been questions asked, Issues logged, great suggestions/feedback and interest in the status and future of PHP-RBAC, along with interest in shown in helping the project move forward.

First of all, we'd like to thank everyone for their interest.

Second of all, I am in the process of updating the Project Wiki in order to share:

  • The history of PHP-RBAC
  • The current status of PHP-RBAC
  • And our plans regarding the future of PHP-RBAC

Please stay tuned, as I will update this Issue once the Wiki has been updated!

Thanks!

$rbac->Permissions->Roles calls undefined method '$this->Permission_ID'

If you look at the first if statement of $rbac->Permissions->Roles (rbac.php) you'll notice a call to the undefined method $this->Permission_ID:

if (! is_numeric ( $Permission ))
    $Permission = $this->Permission_ID ( $Permission );

I was wondering if we should implement $this->Permission_ID.

Method to return users

Similar to Rbac->Permissions->roles() there should be a Rbac->Roles->users() function, maybe even a Rbac->Permissions->users() function.

Something you would consider adding?

Installation... Cannot Modify Headers

(headers already sent by...)
Basically, the install.php - im obviously missing something here, please correct me - is full of output HTML... so when it says "header" (relocate to other page) it's a very unhappy bunny.
What am i missing here?
/PhpRbac/install.php returns :

"Warning: Cannot modify header information - headers already sent by (output started at /var/www/[...pathto...]/PhpRbac/install.php:20) in /var/www/[...pathto...]/PhpRbac/install.php on line 235"

Now, when i put my site online (also was full of such holes) i had to redesign a little to get all the "location:xxxxx" and "header:xxxxxx" stuff to actually work - and not break the page load...

I went about fixing all that 1 at a time, and am fine with the outcome...
But now here again, the same issue...
Im such a noob.
AM I MISSING SOMETHING HERE?

Enhancement: Create GUI Installation

This will allow users to navigate to a web page, enter database credentials, click 'Install', then the script will create the proper tables and insert the proper initial data.

$rbac->Enforce seems to have multiple issues

I may not understand the proper use of $rbac->Enforce, but here are my observations:

  • If the check for jf::CurrentUser() passes, $rbac->Enforce does not send enough parameters to $this->Check()
  • If the check for jf::CurrentUser() pass does not pass errors are thrown because jf::run does not exist
  • If $this->Check() returns false errors are thrown because jf::run does not exist

$rbac->Edit: Sqlite query fails when missing parameters.

As the title says, sqlite gives an error when the last 2 parameters are missing/null.

This is due to sqlite not binding missing/null values. MySQL does not throw an error, it just returns 'false'.

The Edit method builds a $Data array and passes that on to EditData, which is in full.php. EditData then passes that on to the SQL/SQL_pdo.

We should check to make sure that $Data is not empty before executing EditData.

Old Code:

function Edit($ID, $NewTitle = null, $NewDescription = null)
{
    $Data = array ();
    if ($NewTitle !== null)
        $Data ['Title'] = $NewTitle;
    if ($NewDescription !== null)
        $Data ['Description'] = $NewDescription;
    return $this->{$this->Type ()}->EditData ( $Data, "ID=?", $ID ) == 1;
}

Proposed Change:

function Edit($ID, $NewTitle = null, $NewDescription = null)
{
    $Data = array ();
    if ($NewTitle !== null)
        $Data ['Title'] = $NewTitle;
    if ($NewDescription !== null)
        $Data ['Description'] = $NewDescription;

    if (!empty($Data))
        return $this->{$this->Type ()}->EditData ( $Data, "ID=?", $ID ) == 1;

    return false;
}

I've got the sqlite tests up and running, and this is the only test that fails on both Windows and Linux.

I have tested the proposed change on both platforms and all tests are green.

SQLSTATE[HY000]: General error when using jf::$RBAC->Permissions->Add('Test', 'Test Rights')

I am getting the following:

PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error' in SNAP/PhpRbac/src/PhpRbac/core/lib/jf.php:61
Stack trace:
#0 SNAP/PhpRbac/src/PhpRbac/core/lib/jf.php(61): PDOStatement->fetchAll(2)
#1 [internal function]: jf::SQL_pdo('LOCK TABLE phpr...')
#2 SNAP/PhpRbac/src/PhpRbac/core/lib/jf.php(45): call_user_func_array('self::SQL_pdo', Array)
#3 SNAP/PhpRbac/src/PhpRbac/core/lib/nestedset/full.php(53): jf::SQL('LOCK TABLE phpr...')
#4 SNAP/PhpRbac/src/PhpRbac/core/lib/nestedset/full.php(419): FullNestedSet->Lock()
#5 SNAP/PhpRbac/src/PhpRbac/core/lib/rbac.php(74): FullNestedSet->insertChildData(Array, 'ID=?', 1)
#6 SNAP/test.php(32): BaseRbac->Add('Test', 'Test Rights')
#7 {main}

thrown in SNAP/PhpRbac/src/PhpRbac/core/lib/jf.php on line 61

In https://github.com/OWASP/rbac/blob/master/PhpRbac/src/PhpRbac/core/lib/jf.php#L61:

$res=$result->fetchAll ( PDO::FETCH_ASSOC );

I think we shouldn't use the above when there is an insert or update query?

The 'jf::CurrentUser()' method does not exist

The 'jf::CurrentUser()' method does not exist, causing errors:

  • $rbac->Users->HasRole() // Complete
  • $rbac->Users->Assign() // Complete
  • $rbac->Users->Unassign() // Complete
  • $rbac->Users->AllRoles() // Complete
  • $rbac->Users->RoleCount() // Complete
  • $rbac->Users->Enforce() // Complete

All of the above throw PHP errors if no '$User/$UserID' parameter is provided ($User/$UserID = null). The proper behavior is to check 'jf::CurrentUser()' for current user id, but if 'jf::CurrentUser()' does not exist we get an error stating that fact.

I'm assuming that 'CurrentUser' is an interface that users of PhpRbac needs to implement, but wanted to verify that.

I was wondering if it might be a good idea to implement CurrentUser() with a default of 0 (zero, for guest), and either allow the user of PhpRbac to override it, or have a setter so users can dynamically update the current UserID.

I've added the following code to the jf class (jf.php) as a temporary fix so I can continue working on Unit Tests:

static function CurrentUser() {
    return 0; // Guest
}

rbac_rolepermissions doesn't exist (/PhpRbac/core/lib/Jf.php)

mysql Ver 14.14 Distrib 5.5.35, for debian-linux-gnu (x86_64)
PHP 5.5.9-1+sury.org~precise+1 (cli) (built: Feb 13 2014 15:53:53)

2014/03/15 10:10:46 [error] 32603#0: *3968 FastCGI sent in stderr: "PHP message: PHP Notice: Unable to prepare statement: INSERT INTO rbac
_rolepermissions
(RoleID,PermissionID,AssignmentDate)
VALUES (?,?,?), reason: Table 'mydb.rbac_rolepermissions' doesn't exist in /usr/XXXX/www/lib/PhpRbac/src
/PhpRbac/core/lib/Jf.php on line 149

PHP message: PHP Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name
or object in /usr/XXXX/www/lib/PhpRbac/src/PhpRbac/core/lib/Jf.php on line 159

PHP message: PHP Fatal error: Call to a member function execute() on a non-object in /usr/XXXX/www/lib/PhpRbac/src/PhpRbac/core/lib/Jf.ph
p on line 160" while reading response header from upstream

Users->Unassign only works with role ID

should be updated to this
if ($UserID === null)
throw new \RbacUserNotProvidedException ("$UserID is a required argument.");
if (is_int ( $Role ))
{
$RoleID = $Role;
}
else
{
if (substr ( $Role, 0, 1 ) == "/")
$RoleID = jf::$RBAC->Roles->PathID ( $Role );
else
$RoleID = jf::$RBAC->Roles->TitleID ( $Role );
}
return jf::SQL ( "DELETE FROM {$this->tablePrefix()}userroles
WHERE UserID=? AND RoleID=?", $UserID, $RoleID ) >= 1;

Enhancement: Update *.sql files, insert initial default data

Currently there are two steps to manually creating and populating the initial database schema:

  1. Use the proper 'mysql.sql' or 'sqlite.sql' file to create the database structure
  2. Creating a script to call $rbac->reset(true)

I feel that the 'mysql.sql' and 'sqlite.sql' files should not only contain the database structure, but also the initial default data.

With this enhancement a manual database installation and setup will only be a one step process.

The *.sql files should be updated to include the insertion of initial default data.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.