forked from OWASP/rbac
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRbac.php
More file actions
184 lines (165 loc) · 5.72 KB
/
Rbac.php
File metadata and controls
184 lines (165 loc) · 5.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
<?php
namespace PhpRbac;
/**
* Provide NIST Level 2 Standard Role Based Access Control functionality.
*
* Allows maintainable function-level access control for enterprises, small
* applications, or frameworks.
*
* Has three members, Roles, Users and Permissions for specific operations.
*
* @author jamesvl
* @author abiusx
*
* @see http://phprbac.net/index.php
* @see https://www.owasp.org/index.php/OWASP_PHPRBAC_Project
*/
class Rbac
{
/** @var \models\PermissionManager */
public $Permissions;
/** @var \models\RoleManager */
public $Roles;
/** @var \models\UserManager */
public $Users;
public $config;
/**
* Create this class and configure Manager classes with proper backend.
*
* You _must_ pass in a map of options with the following parameters:
*
* $config is a map with the following keys:
* - dbType - DSN prefix for PDO; e.g. 'mysql', 'pgsql', or 'sqlite'
* - dmap - data mapper type, defaults to same as dbType, but for
* testing it may also be 'pgsql-nst'
*
* - host - DB host to connect to
* - port - optional, port to connect to if not the default port
* OR
* - socket - unix socket used to connect to database
* OR
* - filePath - absolute path to sqlite DB file
*
* - dbName - name of database to connect to, optional for sqlite
* - user - username to connect with, optional for sqlite
* - pass - the password to connect with, optional for sqlite
*
* - appName - optional, Postgres only
* - persist - whether to use persistent DB connection; default is false
*
* - pfx - prefix for all table names, default is 'rbac_'
*
**/
function __construct($config)
{
$defaultCfg = array(
'pfx' => 'rbac_'
);
$this->config = array_merge($defaultCfg, $config);
if (!array_key_exists('dmap', $this->config) || empty($this->config['dmap']))
$this->config['dmap'] = $this->config['dbType'];
$this->Permissions = new models\PermissionManager($this->config);
$this->Roles = new models\RoleManager($this->config);
$this->Users = new models\UserManager($this->config);
}
/**
* Assign a role to a permission.
*
* @param string|integer Id, Title or Path of the Role
* @param string|integer Id, Title or Path of the Permission
* @return boolean Indicates result was successful or not
*/
function assign($Role, $Permission)
{
return $this->Roles->assign($Role, $Permission);
}
/**
* Unassign a Role from a Permission.
*
* @param string|integer Id, Title or Path of the Role
* @param string|integer Id, Title or Path of the Permission
* @return boolean Indicates result was successful or not
**/
function unassign($Role, $Permission)
{
return $this->Roles->unassign($Role, $Permission);
}
/**
* Checks whether a user has a permission or not.
*
* @param string|integer $Permission
* You can provide a path like /some/permission, a title, or the
* permission ID.
* In case of ID, don't forget to provide integer (not a string
* containing a number).
* @param string|integer User ID of a user
*
* @throws exceptions\PermissionNotFoundException
* @throws exceptions\UserNotProvidedException
* @return boolean
*/
function check($Permission, $UserID = null)
{
if ($UserID === null)
throw new exceptions\UserNotProvidedException("\$UserID is a required argument.");
$PermissionID = $this->Permissions->returnId($Permission);
// if invalid, throw exception
if ($PermissionID === null)
throw new exceptions\PermissionNotFoundException("The permission '{$Permission}' not found.");
return $this->Users->check($UserID, $PermissionID);
}
/**
* Enforce a permission on a user.
*
* Side effects: sends a 403 Forbidden header and instantly dies().
*
* This will abort any code called by your framework, to use with caution!
*
* @param string|integer path or title or ID of permission
* @param integer User id.
*
* @throws exceptions\UserNotProvidedException
*/
function enforce($Permission, $UserID = null)
{
if ($UserID === null)
throw new exceptions\UserNotProvidedException("\$UserID is a required argument.");
if (!$this->check($Permission, $UserID)) {
header('HTTP/1.1 403 Forbidden');
die("<strong>Forbidden</strong>: You do not have permission to access this resource.");
}
return true;
}
/**
* Remove all roles, permissions and assignments in your database.
*
* Used for testing.
*
* @param boolean Must set to true or throws error.
* @return boolean
*/
function reset($Ensure = false)
{
if ($Ensure !== true) {
throw new \Exception("You must pass true to this function, otherwise it won't work.");
return;
}
$res = true;
$res = $res and $this->Roles->resetAssignments(true);
$res = $res and $this->Roles->reset(true);
$res = $res and $this->Permissions->reset(true);
$res = $res and $this->Users->resetAssignments(true);
return $res;
}
/**
* Present only because test cases expect this method.
*
* No need for Rbac class to actually have knowledge about table internals.
*
* @deprecated
**/
public function tablePrefix()
{
return $this->Roles->tablePrefix();
}
}