• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

php-casbin / php-casbin / 11444189732

21 Oct 2024 04:08PM UTC coverage: 94.006% (+0.2%) from 93.837%
11444189732

push

github

web-flow
Merge pull request #167 from php-casbin/4.x

BREAKING CHANGE: Upgrade the minimum PHP version to 8.0.

716 of 758 new or added lines in 23 files covered. (94.46%)

10 existing lines in 4 files now uncovered.

1976 of 2102 relevant lines covered (94.01%)

134.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.01
/src/Rbac/DefaultRoleManager/ConditionalRoleManager.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Casbin\Rbac\DefaultRoleManager;
6

7
use Casbin\Exceptions\CasbinException;
8
use Casbin\Log\Logger\DefaultLogger;
9
use Casbin\Rbac\ConditionalRoleManager as ConditionalRoleManagerContract;
10
use Casbin\Rbac\DefaultRoleManager\Traits\RoleManager as RoleManagerTrait;
11
use Closure;
12
use Exception;
13

14
/**
15
 * Class ConditionalRoleManager.
16
 * Provides a default implementation for the ConditionalRoleManager interface.
17
 * 
18
 * @author 1692898084@qq.com
19
 */
20
class ConditionalRoleManager implements ConditionalRoleManagerContract
21
{
22
    use RoleManagerTrait;
23

24
    /**
25
     * ConditionalRoleManager constructor.
26
     *
27
     * @param int $maxHierarchyLevel
28
     * @param Closure|null $matchingFunc
29
     */
30
    public function __construct(int $maxHierarchyLevel, ?Closure $matchingFunc = null)
31
    {
32
        $this->clear();
36✔
33
        $this->maxHierarchyLevel = $maxHierarchyLevel;
36✔
34
        $this->setLogger(new DefaultLogger());
36✔
35
        $this->matchingFunc = $matchingFunc;
36✔
36
    }
37

38
    /**
39
     * Determines whether role: name1 inherits role: name2.
40
     * domain is a prefix to the roles.
41
     *
42
     * @param string $name1
43
     * @param string $name2
44
     * @param string ...$domain
45
     *
46
     * @return bool
47
     */
48
    public function hasLink(string $name1, string $name2, string ...$domain): bool
49
    {
50
        if ($name1 == $name2 || (!is_null($this->matchingFunc) && $this->match($name1, $name2))) {
36✔
51
            return true;
18✔
52
        }
53

54
        $userGet = &$this->getRole($name1);
36✔
55
        $roleGet = &$this->getRole($name2);
36✔
56
        $user = &$userGet[0];
36✔
57
        $role = &$roleGet[0];
36✔
58
        $userCreated = $userGet[1];
36✔
59
        $roleCreated = $roleGet[1];
36✔
60

61
        try {
62
            return $this->hasLinkHelper($role->name, [$user->name => $user], $this->maxHierarchyLevel, ...$domain);
36✔
63
        } finally {
64
            if ($userCreated) {
36✔
65
                $this->removeRole($user->name);
6✔
66
            }
67

68
            if ($roleCreated) {
36✔
69
                $this->removeRole($role->name);
36✔
70
            }
71
        }
72
    }
73

74
    /**
75
     * @param string $targetName
76
     * @param array $roles
77
     * @param int $level
78
     * @return bool
79
     */
80
    protected function hasLinkHelper(string $targetName, array $roles, int $level, string ...$domain): bool
81
    {
82
        if ($level < 0 || count($roles) == 0) {
36✔
83
            return false;
36✔
84
        }
85

86
        $nextRoles = [];
36✔
87
        foreach ($roles as $name => $role) {
36✔
88
            if ($targetName === $role->name || (!is_null($this->matchingFunc) && $this->match($role->name, $targetName))) {
36✔
89
                return true;
36✔
90
            }
91

92
            try {
93
                $role->rangeRoles(function ($name, $nextRole) use (&$role, $domain, &$nextRoles) {
36✔
94
                    if (!$this->getNextRoles($role, $nextRole, $domain, $nextRoles)) {
36✔
95
                        throw new CasbinException('failed to get next roles');
12✔
96
                    };
97
                });
36✔
98
            } catch (CasbinException) {
12✔
99
                continue;
12✔
100
            }
101
        }
102

103
        return $this->hasLinkHelper($targetName, $nextRoles, $level - 1);
36✔
104
    }
105

106
    /**
107
     * @param Role $currentRole
108
     * @param Role $nextRole
109
     * @param array $domain
110
     * @param array $nextRoles
111
     * 
112
     * @return bool
113
     */
114
    protected function getNextRoles(Role $currentRole, Role $nextRole, array $domain, array &$nextRoles): bool
115
    {
116
        $passLinkConditionFunc = true;
36✔
117
        try {
118
            if (count($domain) === 0) {
36✔
119
                $linkConditionFunc = $this->getLinkConditionFunc($currentRole->name, $nextRole->name);
24✔
120
                if (!is_null($linkConditionFunc)) {
24✔
121
                    $params = $this->getLinkConditionFuncParams($currentRole->name, $nextRole->name);
18✔
122
                    $passLinkConditionFunc = $linkConditionFunc(...$params);
22✔
123
                }
124
            } else {
125
                $linkConditionFunc = $this->getDomainLinkConditionFunc($currentRole->name, $nextRole->name, $domain[0]);
24✔
126
                if (!is_null($linkConditionFunc)) {
24✔
127
                    $params = $this->getDomainLinkConditionFuncParams($currentRole->name, $nextRole->name, $domain[0]);
24✔
128
                    $passLinkConditionFunc = $linkConditionFunc(...$params);
36✔
129
                }
130
            }
131
        } catch (Exception $e) {
12✔
132
            $this->logger->logError($e, 'hasLinkHelper LinkCondition Error');
12✔
133
            return false;
12✔
134
        }
135

136
        if ($passLinkConditionFunc) {
36✔
137
            $nextRoles[$nextRole->name] = $nextRole;
36✔
138
        }
139

140
        return true;
36✔
141
    }
142

143
    /**
144
     * @param string $userName
145
     * @param string $roleName
146
     *
147
     * @return Closure|null
148
     */
149
    private function getLinkConditionFunc(string $userName, string $roleName): ?Closure
150
    {
151
        return $this->getDomainLinkConditionFunc($userName, $roleName, RoleManager::DEFAULT_DOMAIN);
24✔
152
    }
153

154
    /**
155
     * @param string $userName
156
     * @param string $roleName
157
     * @param string $domain
158
     * 
159
     * @return Closure|null
160
     */
161
    private function getDomainLinkConditionFunc(string $userName, string $roleName, string $domain): ?Closure
162
    {
163
        $userGet = &$this->getRole($userName);
36✔
164
        $roleGet = &$this->getRole($roleName);
36✔
165
        $user = &$userGet[0];
36✔
166
        $role = &$roleGet[0];
36✔
167
        $userCreated = $userGet[1];
36✔
168
        $roleCreated = $roleGet[1];
36✔
169

170
        if ($userCreated) {
36✔
NEW
171
            $this->removeRole($user->name);
×
NEW
172
            return null;
×
173
        }
174

175
        if ($roleCreated) {
36✔
NEW
176
            $this->removeRole($role->name);
×
NEW
177
            return null;
×
178
        }
179

180
        return $user->getLinkConditionFunc($role, $domain);
36✔
181
    }
182

183
    /**
184
     * @param string $userName
185
     * @param string $roleName
186
     * 
187
     * @return array|null
188
     */
189
    private function getLinkConditionFuncParams(string $userName, string $roleName): ?array
190
    {
191
        return $this->getDomainLinkConditionFuncParams($userName, $roleName, RoleManager::DEFAULT_DOMAIN);
18✔
192
    }
193

194
    /**
195
     * @param string $userName
196
     * @param string $roleName
197
     * @param string $domain
198
     * 
199
     * @return array|null
200
     */
201
    private function getDomainLinkConditionFuncParams(string $userName, string $roleName, string $domain): ?array
202
    {
203
        $userGet = &$this->getRole($userName);
36✔
204
        $roleGet = &$this->getRole($roleName);
36✔
205
        $user = &$userGet[0];
36✔
206
        $role = &$roleGet[0];
36✔
207
        $userCreated = $userGet[1];
36✔
208
        $roleCreated = $roleGet[1];
36✔
209

210
        if ($userCreated) {
36✔
NEW
211
            $this->removeRole($user->name);
×
NEW
212
            return null;
×
213
        }
214

215
        if ($roleCreated) {
36✔
NEW
216
            $this->removeRole($role->name);
×
NEW
217
            return null;
×
218
        }
219

220
        return $user->getLinkConditionFuncParams($role, $domain);
36✔
221
    }
222

223
    /**
224
     * AddLinkConditionFunc Add condition function fn for Link userName->roleName,
225
     * when fn returns true, Link is valid, otherwise invalid
226
     *
227
     * @param string $userName
228
     * @param string $roleName
229
     * @param Closure $linkConditionFunc
230
     */
231
    public function addLinkConditionFunc(string $userName, string $roleName, Closure $linkConditionFunc): void
232
    {
233
        $this->addDomainLinkConditionFunc($userName, $roleName, RoleManager::DEFAULT_DOMAIN, $linkConditionFunc);
18✔
234
    }
235

236
    /**
237
     * AddDomainLinkConditionFunc Add condition function fn for Link userName-> {roleName, domain},
238
     * when fn returns true, Link is valid, otherwise invalid
239
     *
240
     * @param string $userName
241
     * @param string $roleName
242
     * @param string $domain
243
     * @param Closure $linkConditionFunc
244
     */
245
    public function addDomainLinkConditionFunc(string $userName, string $roleName, string $domain, Closure $linkConditionFunc): void
246
    {
247
        $userGet = &$this->getRole($userName);
36✔
248
        $roleGet = &$this->getRole($roleName);
36✔
249
        $user = &$userGet[0];
36✔
250
        $role = &$roleGet[0];
36✔
251

252
        $user->addLinkConditionFunc($role, $domain, $linkConditionFunc);
36✔
253
    }
254

255
    /**
256
     * SetLinkConditionFuncParams Sets the parameters of the condition function fn for Link userName->roleName
257
     *
258
     * @param string $userName
259
     * @param string $roleName
260
     * @param string ...$params
261
     */
262
    public function setLinkConditionFuncParams(string $userName, string $roleName, string ...$params): void
263
    {
264
        $this->setDomainLinkConditionFuncParams($userName, $roleName, RoleManager::DEFAULT_DOMAIN, ...$params);
18✔
265
    }
266

267
    /**
268
     * SetDomainLinkConditionFuncParams Sets the parameters of the condition function fn
269
     * for Link userName->{roleName, domain}
270
     *
271
     * @param string $userName
272
     * @param string $roleName
273
     * @param string $domain
274
     * @param string ...$params
275
     */
276
    public function setDomainLinkConditionFuncParams(string $userName, string $roleName, string $domain, string ...$params): void
277
    {
278
        $userGet = &$this->getRole($userName);
36✔
279
        $roleGet = &$this->getRole($roleName);
36✔
280
        $user = &$userGet[0];
36✔
281
        $role = &$roleGet[0];
36✔
282

283
        $user->setLinkConditionFuncParams($role, $domain, ...$params);
36✔
284
    }
285

286
    /**
287
     * @param ConditionalRoleManager $roleManager
288
     */
289
    public function copyFrom(ConditionalRoleManager &$roleManager): void
290
    {
291
        $this->rangeLinks($roleManager->allRoles, function ($name1, $name2, $domain) {
6✔
292
            $this->addLink($name1, $name2, $domain);
6✔
293
        });
6✔
294
    }
295
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc