PermissionsTrait   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 131
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 4
Bugs 1 Features 0
Metric Value
wmc 11
eloc 53
c 4
b 1
f 0
dl 0
loc 131
ccs 0
cts 66
cp 0
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A assignRole() 0 35 3
A hasRole() 0 12 1
A can() 0 25 5
A removeRole() 0 19 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Canvas\Traits;
6
7
use Canvas\Models\Roles;
8
use Canvas\Models\UserRoles;
9
use Canvas\Http\Exception\InternalServerErrorException;
10
use Canvas\Http\Exception\UnauthorizedException;
11
12
/**
13
 * Trait FractalTrait.
14
 *
15
 * @package Canvas\Traits
16
 */
17
trait PermissionsTrait
18
{
19
    /**
20
     * Assigne a user this role
21
     * Example: App.Role.
22
     *
23
     * @param string $role
24
     * @return boolean
25
     */
26
    public function assignRole(string $role): bool
27
    {
28
        /**
29
         * check if we have a dot, that mes it legacy and sending the app name
30
         * not needed any more so we remove it.
31
         */
32
        if (strpos($role, '.') !== false) {
33
            $appRole = explode('.', $role);
34
            $role = $appRole[1];
35
        }
36
37
        $role = Roles::getByName($role);
38
39
        $userRole = UserRoles::findFirst([
40
            'conditions' => 'users_id = ?0 and apps_id = ?1 and companies_id = ?2',
41
            'bind' => [
42
                $this->getId(),
0 ignored issues
show
Bug introduced by
It seems like getId() 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

42
                $this->/** @scrutinizer ignore-call */ 
43
                       getId(),
Loading history...
43
                $role->apps_id,
44
                $this->currentCompanyId()
0 ignored issues
show
Bug introduced by
It seems like currentCompanyId() 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

44
                $this->/** @scrutinizer ignore-call */ 
45
                       currentCompanyId()
Loading history...
45
            ]
46
        ]);
47
48
        if (!is_object($userRole)) {
49
            $userRole = new UserRoles();
50
            $userRole->users_id = $this->getId();
51
            $userRole->roles_id = $role->getId();
52
            $userRole->apps_id = $role->apps_id;
53
            $userRole->companies_id = $this->currentCompanyId();
54
        } else {
55
            $userRole->roles_id = $role->getId();
56
        }
57
58
        $userRole->saveOrFail();
59
60
        return true;
61
    }
62
63
    /**
64
     * Remove a role for the current user
65
     * Example: App.Role.
66
     *
67
     * @param string $role
68
     * @return boolean
69
     */
70
    public function removeRole(string $role): bool
71
    {
72
        $role = Roles::getByAppName($role, $this->getDefaultCompany());
0 ignored issues
show
Bug introduced by
It seems like getDefaultCompany() 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

72
        $role = Roles::getByAppName($role, $this->/** @scrutinizer ignore-call */ getDefaultCompany());
Loading history...
73
74
        $userRole = UserRoles::findFirst([
75
            'conditions' => 'users_id = ?0 and roles_id = ?1 and apps_id = ?2 and companies_id = ?3',
76
            'bind' => [
77
                $this->getId(),
78
                $role->getId(),
79
                $role->apps_id,
80
                $this->currentCompanyId()
81
            ]
82
        ]);
83
84
        if (is_object($userRole)) {
85
            return $userRole->delete();
86
        }
87
88
        return false;
89
    }
90
91
    /**
92
     * Check if the user has this role.
93
     *
94
     * @param string $role
95
     * @return boolean
96
     */
97
    public function hasRole(string $role): bool
98
    {
99
        $role = Roles::getByAppName($role, $this->getDefaultCompany());
100
101
        return (bool) UserRoles::count([
102
            'conditions' => 'users_id = ?0 and roles_id = ?1 and (apps_id = ?2 or apps_id = ?4) and companies_id = ?3',
103
            'bind' => [
104
                $this->getId(),
105
                $role->getId(),
106
                $role->apps_id,
107
                $this->currentCompanyId(),
108
                $this->di->getApp()->getId()
109
            ]
110
        ]);
111
    }
112
113
    /**
114
     * At this current system / app can you do this?
115
     *
116
     * Example: resource.action
117
     *  Leads.add || leads.updates || lead.delete
118
     *
119
     * @param string $action
120
     * @param bool $throwException
121
     * @return boolean
122
     */
123
    public function can(string $action, bool $throwException = false): bool
124
    {
125
        //if we find the . then les
126
        if (strpos($action, '.') === false) {
127
            throw new InternalServerErrorException('ACL - We are expecting the resource for this action');
128
        }
129
130
        $action = explode('.', $action);
131
        $resource = $action[0];
132
        $action = $action[1];
133
134
        //get your user account role for this app or the canvas ecosystem
135
        if (!$role = $this->getPermission()) {
0 ignored issues
show
Bug introduced by
It seems like getPermission() 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

135
        if (!$role = $this->/** @scrutinizer ignore-call */ getPermission()) {
Loading history...
136
            throw new InternalServerErrorException(
137
                'ACL - User doesnt have any set roles in this current app ' . $this->di->getApp()->name
138
            );
139
        }
140
141
        $canExecute = $this->di->getAcl()->isAllowed($role->roles->name, $resource, $action);
142
143
        if ($throwException && !$canExecute) {
144
            throw new UnauthorizedException("ACL - Users doesn't have permission to run this action `{$action}`");
145
        }
146
147
        return (bool) $canExecute;
148
    }
149
}
150