Passed
Push — feature/permissions-management ( 41e93d )
by
unknown
11:22 queued 04:04
created

HasPermissions   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 200
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 41
c 1
b 0
f 0
dl 0
loc 200
rs 10
wmc 22

12 Methods

Rating   Name   Duplication   Size   Complexity  
A revokeAllPermissions() 0 3 1
A revokeModuleItemPermission() 0 7 2
A permissions() 0 12 3
A revokeModuleItemAllPermissions() 0 3 1
A revokeModulePermission() 0 6 2
A grantModulePermission() 0 10 1
A removePermissions() 0 4 2
A revokeGlobalPermission() 0 5 1
A grantModuleItemPermission() 0 15 3
A revokeAllModulePermission() 0 4 2
A grantGlobalPermission() 0 9 2
A checkPermissionAvailable() 0 4 2
1
<?php
2
3
namespace A17\Twill\Models\Behaviors;
4
5
use A17\Twill\Models\Permission;
6
use Illuminate\Support\Collection;
7
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
8
9
trait HasPermissions
10
{
11
    /**
12
     * Permissions relationship
13
     *
14
     * @return BelongsToMany|Collection|Permission[]
15
     */
16
    public function permissions()
17
    {
18
        if (config('twill.enabled.permissions-management')) {
19
            // Deal with the situation that twill user's table has been renamed.
20
            if (get_class($this) === twillModel('user')) {
21
                return $this->belongsToMany('A17\Twill\Models\Permission', 'permission_twill_user', 'twill_user_id', 'permission_id');
0 ignored issues
show
Bug introduced by
It seems like belongsToMany() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

21
                return $this->/** @scrutinizer ignore-call */ belongsToMany('A17\Twill\Models\Permission', 'permission_twill_user', 'twill_user_id', 'permission_id');
Loading history...
22
            } else {
23
                return $this->belongsToMany('A17\Twill\Models\Permission');
24
            }
25
        }
26
27
        return null;
28
    }
29
30
    /**
31
     * Add global permission to item, after making sure the permission is
32
     * valid
33
     *
34
     * @param string $name
35
     * @return void
36
     */
37
    public function grantGlobalPermission($name)
38
    {
39
        $this->checkPermissionAvailable($name, Permission::SCOPE_GLOBAL);
40
41
        $permission = Permission::firstOrCreate(['name' => $name,]);
42
43
        // check the existence to avoid duplicate records on pivot table
44
        if (!$this->permissions()->global()->where('name', $name)->exists()) {
45
            $this->permissions()->save($permission);
46
        }
47
    }
48
49
    /**
50
     * Revoke global permission from the item, after making sure the permission is
51
     * valid
52
     *
53
     * @param string $name
54
     * @return void
55
     */
56
    public function revokeGlobalPermission($name)
57
    {
58
        $this->checkPermissionAvailable($name, Permission::SCOPE_GLOBAL);
59
60
        $this->permissions()->global()->detach(Permission::where('name', $name)->first()->id);
61
    }
62
63
64
    /**
65
     * Add module permission to item, after making sure the permission is
66
     * valid
67
     *
68
     * @param string $name
69
     * @param string|object $permissionableType
70
     * @return void
71
     */
72
    public function grantModulePermission($name, $permissionableType)
73
    {
74
        $this->checkPermissionAvailable($name, Permission::SCOPE_MODULE);
75
76
        $permission = Permission::firstOrCreate([
77
            'name' => $name,
78
            'permissionable_type' => $permissionableType,
79
        ]);
80
81
        $this->permissions()->save($permission);
82
83
    }
84
85
    /**
86
     * Revoke module permission from the item, after making sure the permission is
87
     * valid
88
     *
89
     * @param string $name
90
     * @param string|object $permissionableType
91
     * @return void
92
     */
93
    public function revokeModulePermission($name, $permissionableType)
94
    {
95
        $this->checkPermissionAvailable($name, Permission::SCOPE_MODULE);
96
        $permission = Permission::ofModel($permissionableType)->where('name', $name)->first();
0 ignored issues
show
Bug introduced by
It seems like $permissionableType can also be of type string; however, parameter $model of A17\Twill\Models\Permission::ofModel() does only seem to accept Illuminate\Database\Eloquent\Model, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

96
        $permission = Permission::ofModel(/** @scrutinizer ignore-type */ $permissionableType)->where('name', $name)->first();
Loading history...
97
        if ($permission) {
98
            $this->permissions()->module()->detach($permission->id);
99
        }
100
    }
101
102
103
    /**
104
     * Revoke all module permissions from the item
105
     *
106
     * @param string|object $permissionableType
107
     * @return void
108
     */
109
    public function revokeAllModulePermission($permissionableType)
110
    {
111
        foreach(Permission::ofModel($permissionableType)->get() as $permission) {
0 ignored issues
show
Bug introduced by
It seems like $permissionableType can also be of type string; however, parameter $model of A17\Twill\Models\Permission::ofModel() does only seem to accept Illuminate\Database\Eloquent\Model, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

111
        foreach(Permission::ofModel(/** @scrutinizer ignore-type */ $permissionableType)->get() as $permission) {
Loading history...
112
            $this->permissions()->module()->detach($permission->id);
113
        }
114
    }
115
116
    /**
117
     * Add module item permission, after making sure the permission is
118
     * valid
119
     *
120
     * @param string $name
121
     * @param object $permissionableItem
122
     * @return void
123
     */
124
    public function grantModuleItemPermission($name, $permissionableItem)
125
    {
126
        // First find or create the corresponding permission
127
        // If the object haven't been given this permission, give it
128
        // If the object already had this permission, skip it
129
        $this->checkPermissionAvailable($name, Permission::SCOPE_ITEM);
130
131
        $permission = Permission::firstOrCreate([
132
            'name' => $name,
133
            'permissionable_type' => $permissionableItem ? get_class($permissionableItem) : null,
0 ignored issues
show
introduced by
$permissionableItem is of type object, thus it always evaluated to true.
Loading history...
134
            'permissionable_id' => $permissionableItem ? $permissionableItem->id : null,
0 ignored issues
show
introduced by
$permissionableItem is of type object, thus it always evaluated to true.
Loading history...
135
        ]);
136
137
        $this->revokeModuleItemAllPermissions($permissionableItem);
138
        $this->permissions()->attach($permission->id);
139
    }
140
141
    /**
142
     * Revoke module item permissions, after making sure the permission is
143
     * valid
144
     *
145
     * @param string $name
146
     * @param object $permissionableItem
147
     * @return void
148
     */
149
    public function revokeModuleItemPermission($name, $permissionableItem)
150
    {
151
        $this->checkPermissionAvailable($name, Permission::SCOPE_ITEM);
152
153
        $permission = Permission::ofItem($permissionableItem)->where('name', $name)->first();
154
        if ($permission) {
155
            $this->permissions()->ofItem($permissionableItem)->detach($permission->id);
156
        }
157
    }
158
159
    /**
160
     * Revoke all module item permissions
161
     *
162
     * @param object $permissionableItem
163
     * @return void
164
     */
165
    public function revokeModuleItemAllPermissions($permissionableItem)
166
    {
167
        $this->removePermissions(Permission::ofItem($permissionableItem)->pluck('id')->toArray());
168
    }
169
170
    /**
171
     * Revoke all permissions
172
     *
173
     * @param object $permissionableItem
174
     * @return void
175
     */
176
    public function revokeAllPermissions()
177
    {
178
        $this->removePermissions($this->permissions->pluck('id')->toArray());
179
    }
180
181
    /**
182
     * Revoke all permissions from a list of permission ids
183
     *
184
     * @param int[] $permissionableIds
185
     * @return void
186
     */
187
    public function removePermissions($permissionableIds)
188
    {
189
        if (!empty($permissionableIds)) {
190
            $this->permissions()->detach($permissionableIds);
191
        }
192
    }
193
194
    /**
195
     * Check if a permission is available for a particular scope
196
     *
197
     * @see Permission::SCOPE_GLOBAL
198
     * @see Permission::SCOPE_MODULE
199
     * @see Permission::SCOPE_ITEM
200
     *
201
     * @param string $name
202
     * @param string $scope
203
     * @return void
204
     */
205
    protected function checkPermissionAvailable($name, $scope)
206
    {
207
        if (!in_array($name, Permission::available($scope))) {
208
            abort(400, 'Operation failed, permission ' . $name . ' not available on ' . $scope);
209
        }
210
    }
211
}
212