88 lines
1.4 KiB
PHP
88 lines
1.4 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace alveolata\accesscontrol;
|
||
|
|
||
|
require_once(DIR_ALVEOLATA . '/list/functions.php');
|
||
|
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
class struct_subject
|
||
|
{
|
||
|
|
||
|
/**
|
||
|
* @var array {map<string,function<tuple<any,any>,bool>>}
|
||
|
*/
|
||
|
public $getters;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @var array {record<default:list<list<record<type:string,?parameters:any>>>,concrete:map<string,list<list<record<type:string,?parameters:any>>>>>}
|
||
|
*/
|
||
|
public $acl;
|
||
|
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
public function __construct(
|
||
|
array $getters,
|
||
|
array $acl
|
||
|
)
|
||
|
{
|
||
|
$this->getters = $getters;
|
||
|
$this->acl = $acl;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
function make(
|
||
|
array $getters,
|
||
|
array $acl
|
||
|
)
|
||
|
{
|
||
|
return (
|
||
|
new struct_subject(
|
||
|
$getters,
|
||
|
$acl
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
function check(
|
||
|
struct_subject $subject,
|
||
|
string $action,
|
||
|
$state = null
|
||
|
) : bool
|
||
|
{
|
||
|
$acl_section = (
|
||
|
$subject->acl['concrete'][$action]
|
||
|
?? $subject->acl['default']
|
||
|
?? []
|
||
|
);
|
||
|
return \alveolata\list_\some(
|
||
|
$acl_section,
|
||
|
function (array $acl_section_sub) use ($subject, $state) : bool {
|
||
|
return \alveolata\list_\every(
|
||
|
$acl_section_sub,
|
||
|
function (array $entry) use ($subject, $state) : bool {
|
||
|
if (! array_key_exists($entry['type'], $subject->getters)) {
|
||
|
throw (new \Exception('unhandled ACL check type: ' . $entry['type']));
|
||
|
}
|
||
|
else {
|
||
|
$getter = $subject->getters[$entry['type']];
|
||
|
return $getter($entry['parameters'] ?? null, $state);
|
||
|
}
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
|
||
|
?>
|