87 lines
1.4 KiB
PHP
87 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);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
);
|
|
}
|
|
|
|
?>
|