Skip to content

Instantly share code, notes, and snippets.

@Fi1osof
Created August 30, 2015 13:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Fi1osof/0983698e48a892e65b8c to your computer and use it in GitHub Desktop.
Save Fi1osof/0983698e48a892e65b8c to your computer and use it in GitHub Desktop.
modZilla
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
* Description of modzilla
*
* @author Fi1osof
*/
class modzillaCacheManager{
public $modx = null;
protected $cachePath = "ModzillaCache/";
function __construct(MODx $modx) {
$this->modx = & $modx;
}
public function setPolicyCache($key, $var, $expire= 0, $options= array()){
$key = "PolicyCache/{$key}";
return $this->set($key, $var, $expire, $options);
}
public function getPolicyCache($key, $options= array()){
$key = "PolicyCache/{$key}";
return $this->get($key, $options);
}
public function set($key, $var, $expire= 0, $options= array()){
return true;
switch($key){
case "AccessesCache":
$key = "{$key}/{$this->modx->user->get('id')}";
break;
}
$key = "{$this->cachePath}{$key}";
return $this->modx->cacheManager->set($key, $var, $expire, $options);
}
public function get($key, $options= array()){
return null;
switch($key){
case "AccessesCache":
$key = "{$key}/{$this->modx->user->get('id')}";
break;
}
$key = "{$this->cachePath}{$key}";
return $this->modx->cacheManager->get($key, $options);
}
}
class modzilla {
public $modx = null;
public $cacheManager = null;
function __construct(MODx $modx) {
$this->modx = & $modx;
$this->cacheManager = new modzillaCacheManager($modx);
}
}
?>
<?php
class ModzillaAccess extends modAccess {
public static function addCheckListConditions(xPDO & $xpdo, xPDOCriteria $criteria){
if(empty($criteria->hasCheckListConditions)){
if($definitions = $xpdo->getFKDefinition($criteria->getClass(), 'Accesses')
AND $class = $definitions['class']
){
$user_id = $xpdo->user->get('id');
if(!$xpdo->user->get('sudo')){
$criteria->leftJoin($class, 'Accesses');
$criteria->leftJoin('modUserGroupMember', 'membergroup',
"Accesses.principal_class='modUserGroup'
AND Accesses.principal = membergroup.user_group");
$criteria->where(array(
'Accesses.id' => null,
));
$criteria->orCondition(array(
'owner' => $user_id,
));
$criteria->orCondition(array(
"Accesses.principal_class" => "modUser",
"AND:Accesses.principal:=" => $user_id,
));
$criteria->orCondition(array(
"Accesses.principal_class" => "modUserGroup",
"AND:membergroup.member:=" => $user_id,
));
}
$criteria->hasCheckListConditions = true;
}
}
return $criteria;
}
public static function loadAttributes(modX &$modx, $context = '', $userId = 0) {
$class = __CLASS__;
return self::__loadAttributes($modx, $context, $userId, $class);
}
protected static function __loadAttributes(modX &$modx, $context = '', $userId = 0, $class) {
$cacheKey = "AccessesCache/{$class}/{$userId}";
if(!$attributes = $modx->modzilla->cacheManager->get($cacheKey)){
$attributes = array();
$accessTable = $modx->getTableName($class);
$policyTable = $modx->getTableName('modAccessPolicy');
$memberTable = $modx->getTableName('modUserGroupMember');
$memberRoleTable = $modx->getTableName('modUserGroupRole');
// $legacyDocGroups = array();
$query = null;
if ($userId > 0) {
$sql = "SELECT acl.target, acl.principal_class, acl.principal, mr.authority, acl.policy, p.data
FROM {$accessTable} acl " .
"JOIN {$policyTable} p ON p.id = acl.policy " .
"LEFT JOIN {$memberTable} mug ON acl.principal_class = 'modUserGroup' AND acl.principal = mug.user_group " .
"LEFT JOIN {$memberRoleTable} mr ON mr.id = mug.role " .
"WHERE
( acl.principal_class = 'modUser'
AND acl.principal = :principal )
OR (acl.principal_class = 'modUserGroup'
AND mug.member = :principal)".
"AND mug.user_group = acl.principal " .
"AND mr.authority <= acl.authority " .
"ORDER BY acl.target, acl.principal, mr.authority, acl.policy";
$bindings = array(
':principal' => $userId,
);
$query = new xPDOCriteria($modx, $sql, $bindings);
} else {
$sql = "SELECT acl.target, acl.principal_class, acl.principal, 0 AS authority, acl.policy, p.data FROM {$accessTable} acl " .
"LEFT JOIN {$policyTable} p ON p.id = acl.policy " .
"WHERE acl.principal_class = 'modUserGroup' " .
"AND acl.principal = 0 " .
"ORDER BY acl.target, acl.principal, acl.authority, acl.policy";
$query = new xPDOCriteria($modx, $sql, $bindings);
}
if ($query && $query->stmt && $query->stmt->execute()) {
while ($row = $query->stmt->fetch(PDO::FETCH_ASSOC)) {
$attributes[$row['target']][] = array(
'principal' => $row['principal'],
'authority' => $row['authority'],
'principal_class' => $row['principal_class'],
'policy' => $row['data'] ? $modx->fromJSON($row['data'], true) : array(),
);
}
}
// print $query->toSQL();
//exit;
if($attributes){
$modx->modzilla->cacheManager->set($cacheKey, $attributes);
}
}
return $attributes;
}
public static function getAccessesTable(){
print __CLASS__;
}
}
<?php
$this->loadClass('ModzillaAccess');
class ModzillaAccessProjects extends ModzillaAccess {
public static function loadAttributes(modX &$modx, $context = '', $userId = 0) {
$class = __CLASS__;
return self::__loadAttributes($modx, $context, $userId, $class);
}
}
<?php
$this->loadClass('ModzillaAccess');
$this->loadClass('ModzillaAccessTasks');
class ModzillaProject extends modAccessibleSimpleObject {
protected $policyFinded = false;
public function checkPolicy($criteria, $targets = null) {
if ($criteria && $this->xpdo instanceof modX && $this->xpdo->getSessionState() == modX::SESSION_STATE_INITIALIZED) {
if ($this->xpdo->user->get('sudo') OR $this->xpdo->user->get('id') == $this->get('owner')){
return true;
}
if (!is_array($criteria) && is_scalar($criteria)) {
$criteria = array("{$criteria}" => true);
}
$policy = $this->findPolicy();
if (!empty($policy)) {
$class = $this->getAccessClass();
$principal = $class::loadAttributes($this->xpdo, '', $this->xpdo->user->get('id'));
/*print '<pre>';
print_r($principal);
print_r($policy);
print $this->get('owner');
print '</pre>';
exit;*/
if (!empty($principal) AND $userPerms = $principal[$this->get('id')]) {
foreach ($policy as $policyAccess => $access) {
foreach ($access as $targetId => $targetPolicy) {
foreach ($targetPolicy as $policyIndex => $applicablePolicy) {
if ($this->xpdo->getDebug() === true)
$this->xpdo->log(xPDO::LOG_LEVEL_DEBUG, 'target pk='. $this->getPrimaryKey() .'; evaluating policy: ' . print_r($applicablePolicy, 1) . ' against principal for user id=' . $this->xpdo->getLoginUserID() .': ' . print_r($principal[$policyAccess], 1));
$principalPolicyData = array();
$principalAuthority = 9999;
foreach ($userPerms as $acl) {
$principalAuthority = intval($acl['authority']);
$principalPolicyData = $acl['policy'];
$principalId = $acl['principal'];
$principalClass = $acl['principal_class'];
if ($applicablePolicy['principal'] == $principalId AND $applicablePolicy['principal_class'] == $principalClass){
if ($principalAuthority <= $applicablePolicy['authority']) {
if (!$applicablePolicy['policy']) {
return true;
}
if (empty($principalPolicyData)) $principalPolicyData = array();
$matches = array_intersect_assoc($principalPolicyData, $applicablePolicy['policy']);
if ($matches) {
if ($this->xpdo->getDebug() === true)
$this->xpdo->log(modX::LOG_LEVEL_DEBUG, 'Evaluating policy matches: ' . print_r($matches, 1));
$matched = array_diff_assoc($criteria, $matches);
if (empty($matched)) {
return true;
}
}
}
}
}
}
}
}
}
return false;
}
}
else{
return false;
}
return true;
}
protected function getPolicyCacheKey(){
return $this->_class."/".$this->get('id');
}
public function findPolicy($context = '') {
if (empty($this->_policies) && $this->policyFinded == false) {
$this->policyFinded = true;
$cacheKey = $this->getPolicyCacheKey();
$class = $this->getAccessClass();
if(!$policy = $this->xpdo->modzilla->cacheManager->getPolicyCache($cacheKey)){
$policy = array();
if($this->xpdo->user->get('sudo')){
return $policy;
}
$q = $this->xpdo->newQuery($class);
$q->leftJoin('modUserGroupMember', 'membergroup', "{$class}.principal_class='modUserGroup'
AND {$class}.principal = membergroup.user_group");
$q->leftJoin('modAccessPolicy', 'policy', "{$class}.policy=policy.id");
$q->select(array(
"{$class}.*",
"policy.data",
));
$q->where(array(
"target" => $this->get('id'),
// "policy.id:!=" => null,
));
$q->groupby('target');
$q->groupby('principal_class');
$q->groupby('principal');
$q->groupby('authority');
$q->groupby('policy');
if ($q->prepare() AND $q->stmt AND $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$policy[$class][$row['target']][] = array(
'principal' => $row['principal'],
'principal_class' => $row['principal_class'],
'authority' => $row['authority'],
'policy' => $row['data'] ? $this->xpdo->fromJSON($row['data'], true) : array(),
);
}
}
// print $q->toSQL();
$this->xpdo->modzilla->cacheManager->setPolicyCache($cacheKey, $policy);
$this->_policies = $policy;
}
} else {
$policy = $this->_policies;
}
return $policy;
}
protected function getAccessClass(){
$class = 'ModzillaAccess';
if($definitions = $this->getFKDefinition('Accesses')
AND !empty($definitions['class'])
){
$class = $definitions['class'];
}
return $class;
}
public function save($cacheFlag = null) {
if(!$this->get('owner')){
$this->set('owner', $this->xpdo->user->get('id'));
}
return parent::save($cacheFlag);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment