1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Sco\Admin\Traits; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* This file is part of Entrust, |
7
|
|
|
* a role & permission management solution for Laravel. |
8
|
|
|
* |
9
|
|
|
* @license MIT |
10
|
|
|
* @package Zizaco\Entrust |
11
|
|
|
*/ |
12
|
|
|
|
13
|
|
|
use Illuminate\Cache\TaggableStore; |
14
|
|
|
use Illuminate\Support\Facades\Cache; |
15
|
|
|
use Illuminate\Support\Facades\Config; |
16
|
|
|
use InvalidArgumentException; |
17
|
|
|
|
18
|
|
|
trait EntrustUserTrait |
19
|
|
|
{ |
20
|
|
|
//Big block of caching functionality. |
21
|
|
View Code Duplication |
public function cachedRoles() |
|
|
|
|
22
|
|
|
{ |
23
|
|
|
$userPrimaryKey = $this->primaryKey; |
|
|
|
|
24
|
|
|
$cacheKey = 'entrust_roles_for_user_' . $this->$userPrimaryKey; |
25
|
|
|
if (Cache::getStore() instanceof TaggableStore) { |
26
|
|
|
return Cache::tags(Config::get('admin.role_user_table'))->remember($cacheKey, |
27
|
|
|
Config::get('cache.ttl'), function () { |
28
|
|
|
return $this->roles()->get(); |
29
|
|
|
}); |
30
|
|
|
} else { |
31
|
|
|
return $this->roles()->get(); |
32
|
|
|
} |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
public function save(array $options = []) |
36
|
|
|
{ //both inserts and updates |
37
|
|
|
if (Cache::getStore() instanceof TaggableStore) { |
38
|
|
|
Cache::tags(Config::get('admin.role_user_table'))->flush(); |
39
|
|
|
} |
40
|
|
|
return parent::save($options); |
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
public function delete(array $options = []) |
44
|
|
|
{ //soft or hard |
45
|
|
|
parent::delete($options); |
46
|
|
|
if (Cache::getStore() instanceof TaggableStore) { |
47
|
|
|
Cache::tags(Config::get('admin.role_user_table'))->flush(); |
48
|
|
|
} |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
public function restore() |
52
|
|
|
{ //soft delete undo's |
53
|
|
|
parent::restore(); |
54
|
|
|
if (Cache::getStore() instanceof TaggableStore) { |
55
|
|
|
Cache::tags(Config::get('admin.role_user_table'))->flush(); |
56
|
|
|
} |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Many-to-Many relations with Role. |
61
|
|
|
* |
62
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany |
63
|
|
|
*/ |
64
|
|
|
public function roles() |
65
|
|
|
{ |
66
|
|
|
return $this->belongsToMany(Config::get('admin.role'), |
|
|
|
|
67
|
|
|
Config::get('admin.role_user_table'), |
68
|
|
|
Config::get('admin.user_foreign_key'), |
69
|
|
|
Config::get('admin.role_foreign_key')); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Boot the user model |
74
|
|
|
* Attach event listener to remove the many-to-many records when trying to |
75
|
|
|
* delete Will NOT delete any records if the user model uses soft deletes. |
76
|
|
|
* |
77
|
|
|
* @return void|bool |
78
|
|
|
*/ |
79
|
|
View Code Duplication |
public static function boot() |
|
|
|
|
80
|
|
|
{ |
81
|
|
|
parent::boot(); |
82
|
|
|
|
83
|
|
|
static::deleting(function ($user) { |
84
|
|
|
if (!method_exists(Config::get('admin.user'), |
85
|
|
|
'bootSoftDeletes') |
86
|
|
|
) { |
87
|
|
|
$user->roles()->sync([]); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
return true; |
91
|
|
|
}); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Checks if the user has a role by its name. |
96
|
|
|
* |
97
|
|
|
* @param string|array $name Role name or array of role names. |
98
|
|
|
* @param bool $requireAll All roles in the array are required. |
99
|
|
|
* |
100
|
|
|
* @return bool |
101
|
|
|
*/ |
102
|
|
View Code Duplication |
public function hasRole($name, $requireAll = false) |
|
|
|
|
103
|
|
|
{ |
104
|
|
|
if (is_array($name)) { |
105
|
|
|
foreach ($name as $roleName) { |
106
|
|
|
$hasRole = $this->hasRole($roleName); |
107
|
|
|
|
108
|
|
|
if ($hasRole && !$requireAll) { |
109
|
|
|
return true; |
110
|
|
|
} elseif (!$hasRole && $requireAll) { |
111
|
|
|
return false; |
112
|
|
|
} |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
// If we've made it this far and $requireAll is FALSE, then NONE of the roles were found |
116
|
|
|
// If we've made it this far and $requireAll is TRUE, then ALL of the roles were found. |
117
|
|
|
// Return the value of $requireAll; |
118
|
|
|
return $requireAll; |
119
|
|
|
} else { |
120
|
|
|
foreach ($this->cachedRoles() as $role) { |
121
|
|
|
if ($role->name == $name) { |
122
|
|
|
return true; |
123
|
|
|
} |
124
|
|
|
} |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
return false; |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* Check if user has a permission by its name. |
132
|
|
|
* |
133
|
|
|
* @param string|array $permission Permission string or array of |
134
|
|
|
* permissions. |
135
|
|
|
* @param bool $requireAll All permissions in the array are |
136
|
|
|
* required. |
137
|
|
|
* |
138
|
|
|
* @return bool |
139
|
|
|
*/ |
140
|
|
View Code Duplication |
public function can($permission, $requireAll = false) |
|
|
|
|
141
|
|
|
{ |
142
|
|
|
if (is_array($permission)) { |
143
|
|
|
foreach ($permission as $permName) { |
144
|
|
|
$hasPerm = $this->can($permName); |
145
|
|
|
|
146
|
|
|
if ($hasPerm && !$requireAll) { |
147
|
|
|
return true; |
148
|
|
|
} elseif (!$hasPerm && $requireAll) { |
149
|
|
|
return false; |
150
|
|
|
} |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
// If we've made it this far and $requireAll is FALSE, then NONE of the perms were found |
154
|
|
|
// If we've made it this far and $requireAll is TRUE, then ALL of the perms were found. |
155
|
|
|
// Return the value of $requireAll; |
156
|
|
|
return $requireAll; |
157
|
|
|
} else { |
158
|
|
|
foreach ($this->cachedRoles() as $role) { |
159
|
|
|
// Validate against the Permission table |
160
|
|
|
foreach ($role->cachedPermissions() as $perm) { |
161
|
|
|
if (str_is($permission, $perm->name)) { |
162
|
|
|
return true; |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
} |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
return false; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* Checks role(s) and permission(s). |
173
|
|
|
* |
174
|
|
|
* @param string|array $roles Array of roles or comma separated |
175
|
|
|
* string |
176
|
|
|
* @param string|array $permissions Array of permissions or comma separated |
177
|
|
|
* string. |
178
|
|
|
* @param array $options validate_all (true|false) or |
179
|
|
|
* return_type (boolean|array|both) |
180
|
|
|
* |
181
|
|
|
* @throws \InvalidArgumentException |
182
|
|
|
* @return array|bool |
183
|
|
|
*/ |
184
|
|
|
public function ability($roles, $permissions, $options = []) |
185
|
|
|
{ |
186
|
|
|
// Convert string to array if that's what is passed in. |
187
|
|
|
if (!is_array($roles)) { |
188
|
|
|
$roles = explode(',', $roles); |
189
|
|
|
} |
190
|
|
|
if (!is_array($permissions)) { |
191
|
|
|
$permissions = explode(',', $permissions); |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
// Set up default values and validate options. |
195
|
|
|
if (!isset($options['validate_all'])) { |
196
|
|
|
$options['validate_all'] = false; |
197
|
|
|
} else { |
198
|
|
|
if ($options['validate_all'] !== true && $options['validate_all'] !== false) { |
199
|
|
|
throw new InvalidArgumentException(); |
200
|
|
|
} |
201
|
|
|
} |
202
|
|
|
if (!isset($options['return_type'])) { |
203
|
|
|
$options['return_type'] = 'boolean'; |
204
|
|
|
} else { |
205
|
|
|
if ($options['return_type'] != 'boolean' && |
206
|
|
|
$options['return_type'] != 'array' && |
207
|
|
|
$options['return_type'] != 'both' |
208
|
|
|
) { |
209
|
|
|
throw new InvalidArgumentException(); |
210
|
|
|
} |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
// Loop through roles and permissions and check each. |
214
|
|
|
$checkedRoles = []; |
215
|
|
|
$checkedPermissions = []; |
216
|
|
|
foreach ($roles as $role) { |
217
|
|
|
$checkedRoles[$role] = $this->hasRole($role); |
218
|
|
|
} |
219
|
|
|
foreach ($permissions as $permission) { |
220
|
|
|
$checkedPermissions[$permission] = $this->can($permission); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
// If validate all and there is a false in either |
224
|
|
|
// Check that if validate all, then there should not be any false. |
225
|
|
|
// Check that if not validate all, there must be at least one true. |
226
|
|
|
if (($options['validate_all'] && !(in_array(false, |
227
|
|
|
$checkedRoles) || in_array(false, |
228
|
|
|
$checkedPermissions))) || |
229
|
|
|
(!$options['validate_all'] && (in_array(true, |
230
|
|
|
$checkedRoles) || in_array(true, $checkedPermissions))) |
231
|
|
|
) { |
232
|
|
|
$validateAll = true; |
233
|
|
|
} else { |
234
|
|
|
$validateAll = false; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
// Return based on option |
238
|
|
|
if ($options['return_type'] == 'boolean') { |
239
|
|
|
return $validateAll; |
240
|
|
|
} elseif ($options['return_type'] == 'array') { |
241
|
|
|
return [ |
242
|
|
|
'roles' => $checkedRoles, 'permissions' => $checkedPermissions, |
243
|
|
|
]; |
244
|
|
|
} else { |
245
|
|
|
return [ |
246
|
|
|
$validateAll, |
247
|
|
|
['roles' => $checkedRoles, 'permissions' => $checkedPermissions], |
248
|
|
|
]; |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* Alias to eloquent many-to-many relation's attach() method. |
255
|
|
|
* |
256
|
|
|
* @param mixed $role |
257
|
|
|
*/ |
258
|
|
View Code Duplication |
public function attachRole($role) |
|
|
|
|
259
|
|
|
{ |
260
|
|
|
if (is_object($role)) { |
261
|
|
|
$role = $role->getKey(); |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
if (is_array($role)) { |
265
|
|
|
$role = $role['id']; |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
$this->roles()->attach($role); |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
/** |
272
|
|
|
* Alias to eloquent many-to-many relation's detach() method. |
273
|
|
|
* |
274
|
|
|
* @param mixed $role |
275
|
|
|
*/ |
276
|
|
View Code Duplication |
public function detachRole($role) |
|
|
|
|
277
|
|
|
{ |
278
|
|
|
if (is_object($role)) { |
279
|
|
|
$role = $role->getKey(); |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
if (is_array($role)) { |
283
|
|
|
$role = $role['id']; |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
$this->roles()->detach($role); |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
/** |
290
|
|
|
* Attach multiple roles to a user |
291
|
|
|
* |
292
|
|
|
* @param mixed $roles |
293
|
|
|
*/ |
294
|
|
|
public function attachRoles($roles) |
295
|
|
|
{ |
296
|
|
|
foreach ($roles as $role) { |
297
|
|
|
$this->attachRole($role); |
298
|
|
|
} |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
/** |
302
|
|
|
* Detach multiple roles from a user |
303
|
|
|
* |
304
|
|
|
* @param mixed $roles |
305
|
|
|
*/ |
306
|
|
|
public function detachRoles($roles = null) |
307
|
|
|
{ |
308
|
|
|
if (!$roles) { |
309
|
|
|
$roles = $this->roles()->get(); |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
foreach ($roles as $role) { |
313
|
|
|
$this->detachRole($role); |
314
|
|
|
} |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
} |
318
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.