Issues (13)

Auth/Operator.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace HexMakina\kadro\Auth;
4
5
use HexMakina\BlackBox\Database\SelectInterface;
6
use HexMakina\BlackBox\Auth\OperatorInterface;
7
use HexMakina\Crudites\Queries\AutoJoin;
8
9
use HexMakina\TightORM\{TightModel,RelationManyToMany};
10
11
class Operator extends TightModel implements OperatorInterface
12
{
13
    public const TABLE_NAME = 'kadro_operator';
14
    public const TABLE_ALIAS = 'operator';
15
16
17
    protected $permissions = null;
18
19
    // use Permissionability;
20
    use \HexMakina\TightORM\RelationManyToMany;
21
22
    public function __toString()
23
    {
24
        return $this->get('username');
25
    }
26
27
    public function isActive(): bool
28
    {
29
        return !empty($this->get('active'));
30
    }
31
32
    public function operatorId()
33
    {
34
        return $this->getId();
35
    }
36
37
    public function username()
38
    {
39
        return $this->get('username');
40
    }
41
42
    // TODO remove this, pwd only useful when checkinin
43
    public function password()
44
    {
45
        return $this->get('password');
46
    }
47
48
    public function passwordChange($string)
49
    {
50
        $this->set('password', password_hash($this->validate_password($string), PASSWORD_DEFAULT));
51
    }
52
53
    public function passwordVerify($string): bool
54
    {
55
        return password_verify($this->validate_password($string), $this->password() ?? '');
56
    }
57
58
    public function name()
59
    {
60
        return $this->get('name');
61
    }
62
63
    public function email()
64
    {
65
        return $this->get('email');
66
    }
67
    public function phone()
68
    {
69
        return $this->get('phone');
70
    }
71
72
    public function languageCode()
73
    {
74
        return $this->get('language_code');
75
    }
76
77
    public static function safeLoading($op_id): OperatorInterface
78
    {
79
        $op = static::one($op_id);
80
        $op->set('password', null);
81
        return $op;
82
    }
83
84
    public static function query_retrieve($filters = [], $options = []): SelectInterface
85
    {
86
        $Query = static::table()->select();
87
        if (isset($options['eager']) && $options['eager'] === true) {
88
            $Query->groupBy('id');
89
90
            AutoJoin::join($Query, [ACL::table(), 'acl'], null, 'LEFT OUTER');
91
            AutoJoin::join($Query, [Permission::table(), 'kadro_permission'], null, 'LEFT OUTER');
92
            $Query->selectAlso(["GROUP_CONCAT(DISTINCT kadro_permission.id) as permission_ids", "GROUP_CONCAT(DISTINCT kadro_permission.name) as permission_names"]);
93
        }
94
95
        if (isset($filters['model']) && !empty($filters['model'])) {
96
            $Query->join([static::otm('t'), static::otm('a')], [[static::otm('a'),static::otm('k'), 't_from','id']], 'INNER');
97
            $Query->whereFieldsEQ(['model_id' => $filters['model']->getId(), 'model_type' => get_class($filters['model'])::model_type()], static::otm('a'));
98
        }
99
100
        $Query->orderBy([$Query->tableLabel(), 'name', 'ASC']);
101
102
103
        return $Query;
104
    }
105
106
    public function immortal(): bool
107
    {
108
        return true; // never delete a user, always deactivate
109
    }
110
111
    public function permission_names()
112
    {
113
        if (property_exists($this, 'permission_names') && !is_null($this->get('permission_names'))) {
114
            return explode(',', $this->get('permission_names') ?? '');
115
        } elseif (property_exists($this, 'permission_ids') && !is_null($this->get('permission_ids'))) {
116
            $ids = explode(',', $this->get('permission_ids') ?? '');
117
            $ret = [];
118
            $permissions = Permission::get_many_by_AIPK($ids);
119
            foreach ($permissions as $id => $p) {
120
                $ret[] = "$p";
121
            }
122
            return $ret;
123
        } else {
124
            return ACL::permissions_names_for($this);
125
        }
126
    }
127
128
    public function permissions()
129
    {
130
131
        if (!is_null($this->permissions)) {
132
            return $this->permissions;
133
        }
134
        $permission_unique_keys = null;
135
        if (property_exists($this, 'permission_names') && !is_null($this->get('permission_names'))) {
136
            $permission_unique_keys = explode(',', $this->get('permission_names') ?? '');
137
            $this->permissions = Permission::retrieve(Permission::table()->select()->whereStringIn('name', $permission_unique_keys));
138
        } elseif (property_exists($this, 'permission_ids') && !is_null($this->get('permission_ids'))) {
139
            $permission_unique_keys = explode(',', $this->get('permission_ids') ?? '');
140
            $this->permissions = Permission::retrieve(Permission::table()->select()->whereNumericIn('id', $permission_unique_keys));
141
        } else {
142
            $this->permissions = ACL::permissions_for($this);
143
        }
144
145
        return $this->permissions;
146
    }
147
148
    public function hasPermission($p): bool
149
    {
150
      // new instances or inactive operators, none shall pass
151
        if ($this->isNew() === true || $this->isActive()  === false) {
152
            return false;
153
        }
154
155
        $permission_name = $permission_id = null;
156
        if (is_subclass_of($p, '\HexMakina\kadro\Auth\Permission')) {
157
            $permission_name = $p->get('name');
158
            $permission_id = $p->getId();
159
        } elseif (preg_match('/[0-9]+/', $p)) {
160
            $permission_id = $p;
161
        } else {
162
            $permission_name = $p;
163
        }
164
165
        if (!is_null($this->get('permission_names')) && !is_null($permission_name)) {
166
            return strpos($this->get('permission_names'), $permission_name) !== false;
0 ignored issues
show
It seems like $this->get('permission_names') can also be of type null; however, parameter $haystack of strpos() does only seem to accept string, 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

166
            return strpos(/** @scrutinizer ignore-type */ $this->get('permission_names'), $permission_name) !== false;
Loading history...
167
        } elseif (!is_null($this->get('permission_ids')) && !is_null($permission_id)) {
168
            return strpos($this->get('permission_ids'), $permission_id) !== false;
169
        } elseif (!is_null($permission_name)) {
170
            if (method_exists($this, $permission_name) && $this->$permission_name() == true) {
171
                return true;
172
            } elseif (property_exists($this, $permission_name) && $this->get('$permission_name') == true) {
173
                return true;
174
            } elseif (ACL::match($this, $permission_name) === true) {
175
                return true;
176
            }
177
        }
178
179
        return false;
180
    }
181
182
    private function validate_password($string): string
183
    {
184
        if (empty($string)) {
185
            throw new \InvalidArgumentException('PASSWORD_CANT_BE_EMPTY');
186
        }
187
188
        return $string;
189
    }
190
}
191