/** * * Mode table: * * 0 all * 1 list * 2 view * 3 add * 4 update * 5 delete * * @static * * @param $objectKey * @param int $mode * * @param integer|null $targetType * @param integer|null $targetId * * @return mixed */ public function getRules($objectKey, $mode = 1, $targetType = ACL::TARGET_TYPE_USER, $targetId = null) { $objectKey = Objects::normalizeObjectKey($objectKey); //normalize input. default is user $targetType = ACL::TARGET_TYPE_GROUP === $targetType ? ACL::TARGET_TYPE_GROUP : ACL::TARGET_TYPE_USER; $user = null; if ($targetType === ACL::TARGET_TYPE_USER) { if (!$targetId) { $user = $this->pageStack->getUser(); } else { $user = UserQuery::create()->findPk($targetId); } } if (ACL::TARGET_TYPE_USER === $targetType) { if ($user) { $targetId = $user->getId(); $inGroups = $user->getGroupIdsArray(); } else { //no user found, so we check against guest $targetId = 0; $inGroups = [0]; } } else { $inGroups = [(string) $targetId]; } $cacheKey = ''; if ($this->getCaching()) { $cacheKey = md5($targetType . '.' . $targetId . '.' . implode(',', $inGroups) . '.' . $objectKey . '.' . $mode); $cached = $this->cacher->getDistributedCache('core/acl/rules/' . $cacheKey); if (null !== $cached) { return $cached; } } $mode += 0; $data = array($objectKey, $mode); $targets = array(); //group is always checked. If no user found, $inGroups is 0, which means it checks against Guest group. $targets[] = "( target_type = 1 AND target_id IN (?))"; $data[] = implode(', ', $inGroups); if (ACL::TARGET_TYPE_USER === $targetType) { //if user type, we include additionally all user rules $targets[] = "( target_type = 0 AND target_id = ?)"; if ($user) { $data[] = $user->getId(); } else { //no user found, so we check against guest $data[] = 0; } } //now it gets dirty. A bit more complicated query, so we do it directly with PDO. $con = Propel::getReadConnection('default'); $targets = implode(' OR ', $targets); $query = "\n SELECT constraint_type, constraint_code, mode, access, sub, fields\n FROM system_acl\n WHERE\n object = ? AND\n (mode = ? OR mode = 0) AND\n (\n {$targets}\n )\n ORDER BY prio DESC\n "; $stmt = $con->prepare($query); $stmt->execute($data); $rules = array(); while ($rule = $stmt->fetch(\PDO::FETCH_ASSOC)) { $rule['mode'] = (int) $rule['mode']; $rule['access'] = (int) $rule['access']; $rule['sub'] = (bool) $rule['sub']; $rule['constraint_type'] = (int) $rule['constraint_type']; if ($rule['fields'] && substr($rule['fields'], 0, 1) === '{') { $rule['fields'] = json_decode($rule['fields'], true); } if ($rule['constraint_type'] === ACL::CONSTRAINT_CONDITION && substr($rule['constraint_code'], 0, 1) === '[') { $rule['constraint_code'] = json_decode($rule['constraint_code'], true); } $rules[] = $rule; } if ($this->getCaching()) { $this->cacher->setDistributedCache('core/acl/rules/' . $cacheKey, $rules); return $rules; } else { return $rules; } }
public function testNestedSubPermission() { $this->getACL()->setCaching(false); $this->getACL()->removeObjectRules('jarves/node'); $tokenStorage = $this->getTokenStorage(); $token = new UsernamePasswordToken(UserQuery::create()->findOneByUsername('test'), null, "main"); $tokenStorage->setToken($token); $user = $this->getPageStack()->getUser(); $this->assertEquals('test', $user->getUsername()); $domain = DomainQuery::create()->findOne(); $root = NodeQuery::create()->findRoot($domain->getId()); $subNode = new Node(); $subNode->setTitle('TestNode tree'); $subNode->insertAsFirstChildOf($root); $subNode->save(); $subNode2 = new Node(); $subNode2->setTitle('TestNode sub'); $subNode2->insertAsFirstChildOf($subNode); $subNode2->save(); //make access for all $rule = new Acl(); $rule->setAccess(true); $rule->setObject('jarves/node'); $rule->setTargetType(\Jarves\ACL::TARGET_TYPE_USER); $rule->setTargetId($user->getId()); $rule->setMode(\Jarves\ACL::MODE_ALL); $rule->setConstraintType(\Jarves\ACL::CONSTRAINT_ALL); $rule->setPrio(2); $rule->save(); //revoke access for all children of `TestNode tree` $rule2 = new Acl(); $rule2->setAccess(false); $rule2->setObject('jarves/node'); $rule2->setTargetType(\Jarves\ACL::TARGET_TYPE_USER); $rule2->setTargetId($user->getId()); $rule2->setMode(\Jarves\ACL::MODE_ALL); $rule2->setConstraintType(\Jarves\ACL::CONSTRAINT_CONDITION); $rule2->setConstraintCode(json_encode(['title', '=', 'TestNode tree'])); $rule2->setPrio(3); $rule2->setSub(true); $rule2->save(); $this->getCacher()->invalidateCache('core'); $node1RequestListing = ACLRequest::create('jarves/node', $subNode->getId())->onlyListingMode(); $node2RequestListing = ACLRequest::create('jarves/node', $subNode2->getId())->onlyListingMode(); $this->assertFalse($this->getACL()->check($node1RequestListing)); $this->assertFalse($this->getACL()->check($node2RequestListing)); $items = $this->getObjects()->getBranch('jarves/node', $subNode->getId(), null, 1, null, ['permissionCheck' => true]); $this->assertNull($items, 'rule2 revokes the access to all elements'); $item = $this->getObjects()->get('jarves/node', $subNode2->getId(), ['permissionCheck' => true]); $this->assertNull($item); // Deactivate sub $rule2->setSub(false); $rule2->save(); $this->assertFalse($this->getACL()->check($node1RequestListing)); $this->assertTrue($this->getACL()->check($node2RequestListing)); $items = $this->getObjects()->getBranch('jarves/node', $subNode->getId(), null, 1, null, ['permissionCheck' => true]); $this->assertEquals('TestNode sub', $items[0]['title'], 'We got TestNode sub'); $item = $this->getObjects()->get('jarves/node', $subNode2->getId(), ['permissionCheck' => true]); $this->assertEquals('TestNode sub', $item['title'], 'We got TestNode sub'); // Activate access $rule2->setAccess(true); $rule2->save(); $this->assertTrue($this->getACL()->check($node1RequestListing)); $this->assertTrue($this->getACL()->check($node2RequestListing)); $items = $this->getObjects()->getBranch('jarves/node', $subNode->getId(), null, 1, null, ['permissionCheck' => true]); $this->assertEquals('TestNode sub', $items[0]['title'], 'We got TestNode sub'); $subNode->delete(); $subNode2->delete(); $rule->delete(); $rule2->delete(); $this->getACL()->setCaching(true); }