This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Spatie\Permission\Traits; |
||
4 | |||
5 | use Illuminate\Support\Collection; |
||
6 | use Spatie\Permission\Contracts\Role; |
||
7 | use Illuminate\Database\Eloquent\Builder; |
||
8 | use Spatie\Permission\PermissionRegistrar; |
||
9 | use Illuminate\Database\Eloquent\Relations\BelongsToMany; |
||
10 | |||
11 | trait HasRoles |
||
12 | { |
||
13 | use HasPermissions; |
||
14 | |||
15 | private $roleClass; |
||
16 | |||
17 | View Code Duplication | public static function bootHasRoles() |
|
0 ignored issues
–
show
|
|||
18 | { |
||
19 | static::deleting(function ($model) { |
||
20 | if (method_exists($model, 'isForceDeleting') && ! $model->isForceDeleting()) { |
||
21 | return; |
||
22 | } |
||
23 | |||
24 | $model->roles()->detach(); |
||
25 | }); |
||
26 | } |
||
27 | |||
28 | public function getRoleClass() |
||
29 | { |
||
30 | if (! isset($this->roleClass)) { |
||
31 | $this->roleClass = app(PermissionRegistrar::class)->getRoleClass(); |
||
32 | } |
||
33 | |||
34 | return $this->roleClass; |
||
35 | } |
||
36 | |||
37 | /** |
||
38 | * A model may have multiple roles. |
||
39 | */ |
||
40 | public function roles(): BelongsToMany |
||
41 | { |
||
42 | return $this->morphToMany( |
||
0 ignored issues
–
show
It seems like
morphToMany() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
43 | config('permission.models.role'), |
||
44 | 'model', |
||
45 | config('permission.table_names.model_has_roles'), |
||
46 | config('permission.column_names.model_morph_key'), |
||
47 | 'role_id' |
||
48 | ); |
||
49 | } |
||
50 | |||
51 | /** |
||
52 | * Scope the model query to certain roles only. |
||
53 | * |
||
54 | * @param \Illuminate\Database\Eloquent\Builder $query |
||
55 | * @param string|array|\Spatie\Permission\Contracts\Role|\Illuminate\Support\Collection $roles |
||
56 | * @param string $guard |
||
57 | * |
||
58 | * @return \Illuminate\Database\Eloquent\Builder |
||
59 | */ |
||
60 | public function scopeRole(Builder $query, $roles, $guard = null): Builder |
||
61 | { |
||
62 | if ($roles instanceof Collection) { |
||
63 | $roles = $roles->all(); |
||
64 | } |
||
65 | |||
66 | if (! is_array($roles)) { |
||
67 | $roles = [$roles]; |
||
68 | } |
||
69 | |||
70 | $roles = array_map(function ($role) use ($guard) { |
||
71 | if ($role instanceof Role) { |
||
72 | return $role; |
||
73 | } |
||
74 | |||
75 | $method = is_numeric($role) ? 'findById' : 'findByName'; |
||
76 | $guard = $guard ?: $this->getDefaultGuardName(); |
||
0 ignored issues
–
show
Consider using a different name than the imported variable
$guard , or did you forget to import by reference?
It seems like you are assigning to a variable which was imported through a For clarity, we suggest to use a different name or import by reference depending on whether you would like to have the change visibile in outer-scope. Change not visible in outer-scope$x = 1;
$callable = function() use ($x) {
$x = 2; // Not visible in outer scope. If you would like this, how
// about using a different variable name than $x?
};
$callable();
var_dump($x); // integer(1)
Change visible in outer-scope$x = 1;
$callable = function() use (&$x) {
$x = 2;
};
$callable();
var_dump($x); // integer(2)
![]() |
|||
77 | |||
78 | return $this->getRoleClass()->{$method}($role, $guard); |
||
79 | }, $roles); |
||
80 | |||
81 | return $query->whereHas('roles', function (Builder $subQuery) use ($roles) { |
||
82 | $subQuery->whereIn(config('permission.table_names.roles').'.id', \array_column($roles, 'id')); |
||
83 | }); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Assign the given role to the model. |
||
88 | * |
||
89 | * @param array|string|\Spatie\Permission\Contracts\Role ...$roles |
||
90 | * |
||
91 | * @return $this |
||
92 | */ |
||
93 | View Code Duplication | public function assignRole(...$roles) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
94 | { |
||
95 | $roles = collect($roles) |
||
96 | ->flatten() |
||
97 | ->map(function ($role) { |
||
98 | if (empty($role)) { |
||
99 | return false; |
||
100 | } |
||
101 | |||
102 | return $this->getStoredRole($role); |
||
103 | }) |
||
104 | ->filter(function ($role) { |
||
105 | return $role instanceof Role; |
||
106 | }) |
||
107 | ->each(function ($role) { |
||
108 | $this->ensureModelSharesGuard($role); |
||
109 | }) |
||
110 | ->map->id |
||
111 | ->all(); |
||
112 | |||
113 | $model = $this->getModel(); |
||
0 ignored issues
–
show
It seems like
getModel() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
114 | |||
115 | if ($model->exists) { |
||
116 | $this->roles()->sync($roles, false); |
||
117 | $model->load('roles'); |
||
118 | } else { |
||
119 | $class = \get_class($model); |
||
120 | |||
121 | $class::saved( |
||
122 | function ($object) use ($roles, $model) { |
||
123 | static $modelLastFiredOn; |
||
124 | if ($modelLastFiredOn !== null && $modelLastFiredOn === $model) { |
||
125 | return; |
||
126 | } |
||
127 | $object->roles()->sync($roles, false); |
||
128 | $object->load('roles'); |
||
129 | $modelLastFiredOn = $object; |
||
130 | }); |
||
131 | } |
||
132 | |||
133 | $this->forgetCachedPermissions(); |
||
134 | |||
135 | return $this; |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Revoke the given role from the model. |
||
140 | * |
||
141 | * @param string|\Spatie\Permission\Contracts\Role $role |
||
142 | */ |
||
143 | public function removeRole($role) |
||
144 | { |
||
145 | $this->roles()->detach($this->getStoredRole($role)); |
||
146 | |||
147 | $this->load('roles'); |
||
0 ignored issues
–
show
It seems like
load() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
148 | |||
149 | $this->forgetCachedPermissions(); |
||
150 | |||
151 | return $this; |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * Remove all current roles and set the given ones. |
||
156 | * |
||
157 | * @param array|\Spatie\Permission\Contracts\Role|string ...$roles |
||
158 | * |
||
159 | * @return $this |
||
160 | */ |
||
161 | public function syncRoles(...$roles) |
||
162 | { |
||
163 | $this->roles()->detach(); |
||
164 | |||
165 | return $this->assignRole($roles); |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Determine if the model has (one of) the given role(s). |
||
170 | * |
||
171 | * @param string|int|array|\Spatie\Permission\Contracts\Role|\Illuminate\Support\Collection $roles |
||
172 | * @param string|null $guard |
||
173 | * @return bool |
||
174 | */ |
||
175 | public function hasRole($roles, string $guard = null): bool |
||
176 | { |
||
177 | View Code Duplication | if (is_string($roles) && false !== strpos($roles, '|')) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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. ![]() |
|||
178 | $roles = $this->convertPipeToArray($roles); |
||
179 | } |
||
180 | |||
181 | View Code Duplication | if (is_string($roles)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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. ![]() |
|||
182 | return $guard |
||
183 | ? $this->roles->where('guard_name', $guard)->contains('name', $roles) |
||
0 ignored issues
–
show
The property
roles does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
184 | : $this->roles->contains('name', $roles); |
||
185 | } |
||
186 | |||
187 | View Code Duplication | if (is_int($roles)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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. ![]() |
|||
188 | return $guard |
||
189 | ? $this->roles->where('guard_name', $guard)->contains('id', $roles) |
||
190 | : $this->roles->contains('id', $roles); |
||
191 | } |
||
192 | |||
193 | if ($roles instanceof Role) { |
||
194 | return $this->roles->contains('id', $roles->id); |
||
0 ignored issues
–
show
Accessing
id on the interface Spatie\Permission\Contracts\Role suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
![]() |
|||
195 | } |
||
196 | |||
197 | if (is_array($roles)) { |
||
198 | foreach ($roles as $role) { |
||
199 | if ($this->hasRole($role, $guard)) { |
||
200 | return true; |
||
201 | } |
||
202 | } |
||
203 | |||
204 | return false; |
||
205 | } |
||
206 | |||
207 | return $roles->intersect($guard ? $this->roles->where('guard_name', $guard) : $this->roles)->isNotEmpty(); |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * Determine if the model has any of the given role(s). |
||
212 | * |
||
213 | * Alias to hasRole() but without Guard controls |
||
214 | * |
||
215 | * @param string|int|array|\Spatie\Permission\Contracts\Role|\Illuminate\Support\Collection $roles |
||
216 | * |
||
217 | * @return bool |
||
218 | */ |
||
219 | public function hasAnyRole(...$roles): bool |
||
220 | { |
||
221 | return $this->hasRole($roles); |
||
222 | } |
||
223 | |||
224 | /** |
||
225 | * Determine if the model has all of the given role(s). |
||
226 | * |
||
227 | * @param string|array|\Spatie\Permission\Contracts\Role|\Illuminate\Support\Collection $roles |
||
228 | * @param string|null $guard |
||
229 | * @return bool |
||
230 | */ |
||
231 | public function hasAllRoles($roles, string $guard = null): bool |
||
232 | { |
||
233 | View Code Duplication | if (is_string($roles) && false !== strpos($roles, '|')) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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. ![]() |
|||
234 | $roles = $this->convertPipeToArray($roles); |
||
235 | } |
||
236 | |||
237 | View Code Duplication | if (is_string($roles)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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. ![]() |
|||
238 | return $guard |
||
239 | ? $this->roles->where('guard_name', $guard)->contains('name', $roles) |
||
240 | : $this->roles->contains('name', $roles); |
||
241 | } |
||
242 | |||
243 | if ($roles instanceof Role) { |
||
244 | return $this->roles->contains('id', $roles->id); |
||
0 ignored issues
–
show
Accessing
id on the interface Spatie\Permission\Contracts\Role suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
![]() |
|||
245 | } |
||
246 | |||
247 | $roles = collect()->make($roles)->map(function ($role) { |
||
248 | return $role instanceof Role ? $role->name : $role; |
||
0 ignored issues
–
show
Accessing
name on the interface Spatie\Permission\Contracts\Role suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
![]() |
|||
249 | }); |
||
250 | |||
251 | return $roles->intersect( |
||
252 | $guard |
||
253 | ? $this->roles->where('guard_name', $guard)->pluck('name') |
||
254 | : $this->getRoleNames()) == $roles; |
||
255 | } |
||
256 | |||
257 | /** |
||
258 | * Return all permissions directly coupled to the model. |
||
259 | */ |
||
260 | public function getDirectPermissions(): Collection |
||
261 | { |
||
262 | return $this->permissions; |
||
0 ignored issues
–
show
The property
permissions does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
263 | } |
||
264 | |||
265 | public function getRoleNames(): Collection |
||
266 | { |
||
267 | return $this->roles->pluck('name'); |
||
268 | } |
||
269 | |||
270 | protected function getStoredRole($role): Role |
||
271 | { |
||
272 | $roleClass = $this->getRoleClass(); |
||
273 | |||
274 | if (is_numeric($role)) { |
||
275 | return $roleClass->findById($role, $this->getDefaultGuardName()); |
||
276 | } |
||
277 | |||
278 | if (is_string($role)) { |
||
279 | return $roleClass->findByName($role, $this->getDefaultGuardName()); |
||
280 | } |
||
281 | |||
282 | return $role; |
||
283 | } |
||
284 | |||
285 | protected function convertPipeToArray(string $pipeString) |
||
286 | { |
||
287 | $pipeString = trim($pipeString); |
||
288 | |||
289 | if (strlen($pipeString) <= 2) { |
||
290 | return $pipeString; |
||
291 | } |
||
292 | |||
293 | $quoteCharacter = substr($pipeString, 0, 1); |
||
294 | $endCharacter = substr($quoteCharacter, -1, 1); |
||
295 | |||
296 | if ($quoteCharacter !== $endCharacter) { |
||
297 | return explode('|', $pipeString); |
||
298 | } |
||
299 | |||
300 | if (! in_array($quoteCharacter, ["'", '"'])) { |
||
301 | return explode('|', $pipeString); |
||
302 | } |
||
303 | |||
304 | return explode('|', trim($pipeString, $quoteCharacter)); |
||
305 | } |
||
306 | } |
||
307 |
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.