PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/web/system/PermissionsModule/Api/AdminApi.php

https://github.com/antoniom/core
PHP | 501 lines | 282 code | 83 blank | 136 comment | 61 complexity | 327bee646aa43354e3172324a7c10450 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0, MIT
  1. <?php
  2. /**
  3. * Copyright Zikula Foundation 2009 - Zikula Application Framework
  4. *
  5. * This work is contributed to the Zikula Foundation under one or more
  6. * Contributor Agreements and licensed to You under the following license:
  7. *
  8. * @license GNU/LGPLv3 (or at your option, any later version).
  9. * @package Zikula
  10. *
  11. * Please see the NOTICE file distributed with this source code for further
  12. * information regarding copyright and licensing.
  13. */
  14. namespace PermissionsModule\Api;
  15. use SecurityUtil, LogUtil, ModUtil, DataUtil;
  16. /**
  17. * Permissions_Api_Admin class.
  18. */
  19. class Permissions_Api_AdminApi extends \Zikula\Framework\Api\AbstractApi
  20. {
  21. /**
  22. * Increment sequence number of a permission.
  23. *
  24. * This function raises a permission higher up in the overall
  25. * permissions sequence, thus making it more likely to be acted
  26. * against.
  27. *
  28. * @param int $args ['pid'] the ID of the permission to increment.
  29. *
  30. * @return bool true on success, false on failure.
  31. */
  32. public function inc($args)
  33. {
  34. // Security check
  35. if (!SecurityUtil::checkPermission('Permissions::', "group::$args[pid]", ACCESS_ADMIN)) {
  36. throw new \Zikula\Framework\Exception\ForbiddenException();
  37. }
  38. // Argument check
  39. if (!isset($args['pid'])) {
  40. throw new \InvalidArgumentException('Missing or invalid arguments');
  41. }
  42. if (!is_null($args['permgrp']) && ($args['permgrp'] != SecurityUtil::PERMS_ALL)) {
  43. $where_gid = " AND (p.gid = " . SecurityUtil::PERMS_ALL . " OR p.gid = " . DataUtil::formatForStore($args['permgrp']) . ")";
  44. $showpartly = true;
  45. } else {
  46. $where_gid = '';
  47. $showpartly = false;
  48. }
  49. // get info on current perm
  50. $permission = $this->entityManager->find('PermissionsModule\Entity\Permission', $args['pid']);
  51. if (!$permission) {
  52. return LogUtil::registerError($this->__f('Error! Permission rule ID %s does not exist.', $args['pid']));
  53. }
  54. $sequence = $permission['sequence'];
  55. if ($sequence != 1) {
  56. $altsequence = $sequence - 1;
  57. // get info on displaced perm
  58. $where = "WHERE p.sequence = " . (int)DataUtil::formatForStore($altsequence) . " $where_gid";
  59. $dql = "SELECT p FROM PermissionsModule\Entity\Permission p $where";
  60. $query = $this->entityManager->createQuery($dql);
  61. $d_permission = $query->getOneOrNullResult();
  62. if (!$d_permission) {
  63. if ($showpartly) {
  64. // Changing the sequence by moving while in partial view may only be done if there
  65. // are no invisible permissions inbetween that might be affected by the move.
  66. LogUtil::registerError($this->__('Error! Permission rule-swapping in partial view can only be done if both affected permission rules are visible. Please switch to full view.'));
  67. } else {
  68. LogUtil::registerError($this->__('Error! No permission rule directly above that one.'));
  69. }
  70. return false;
  71. }
  72. $altpid = $d_permission['pid'];
  73. // swap sequence numbers
  74. $perm1 = $this->entityManager->find('PermissionsModule\Entity\Permission', $altpid);
  75. $perm1['sequence'] = $sequence;
  76. $perm2 = $this->entityManager->find('PermissionsModule\Entity\Permission', $args['pid']);
  77. $perm2['sequence'] = $altsequence;
  78. $this->entityManager->flush();
  79. }
  80. return true;
  81. }
  82. /**
  83. * Decrement sequence number of a permission.
  84. *
  85. * @param string $args ['type'] the type of the permission to decrement (user or group).
  86. * @param int $args ['pid'] the ID of the permission to decrement.
  87. *
  88. * @return boolean true on success, false on failure.
  89. */
  90. public function dec($args)
  91. {
  92. // Security check
  93. if (!SecurityUtil::checkPermission('Permissions::', "group::$args[pid]", ACCESS_ADMIN)) {
  94. throw new \Zikula\Framework\Exception\ForbiddenException();
  95. }
  96. // Argument check
  97. if (!isset($args['pid'])) {
  98. throw new \InvalidArgumentException('Missing or invalid arguments');
  99. }
  100. if (!is_null($args['permgrp']) && ($args['permgrp'] != SecurityUtil::PERMS_ALL)) {
  101. $where_gid = " AND (p.gid = " . SecurityUtil::PERMS_ALL . " OR p.gid = " . DataUtil::formatForStore($args['permgrp']) . ")";
  102. $showpartly = true;
  103. } else {
  104. $where_gid = '';
  105. $showpartly = false;
  106. }
  107. // get info on current perm
  108. $permission = $this->entityManager->find('PermissionsModule\Entity\Permission', $args['pid']);
  109. if (!$permission) {
  110. return LogUtil::registerError($this->__f('Error! Permission rule ID %s does not exist.', $args['pid']));
  111. }
  112. $sequence = $permission['sequence'];
  113. $maxsequence = $this->maxsequence();
  114. if ($sequence != $maxsequence) {
  115. $altsequence = $sequence + 1;
  116. // get info on displaced perm
  117. $where = "WHERE p.sequence = " . (int)DataUtil::formatForStore($altsequence) . " $where_gid";
  118. $dql = "SELECT p FROM PermissionsModule\Entity\Permission p $where";
  119. $query = $this->entityManager->createQuery($dql);
  120. $d_permission = $query->getOneOrNullResult();
  121. if (!$d_permission) {
  122. if ($showpartly) {
  123. // Changing the sequence by moving while in partial view may only be done if there
  124. // are no invisible permissions inbetween that might be affected by the move.
  125. LogUtil::registerError($this->__('Error! Permission rule-swapping in partial view can only be done if both affected permission rules are visible. Please switch to full view.'));
  126. } else {
  127. LogUtil::registerError($this->__('Error! No permission rule directly below that one.'));
  128. }
  129. return false;
  130. }
  131. $altpid = $d_permission['pid'];
  132. // swap sequence numbers
  133. $perm1 = $this->entityManager->find('PermissionsModule\Entity\Permission', $altpid);
  134. $perm1['sequence'] = $sequence;
  135. $perm2 = $this->entityManager->find('PermissionsModule\Entity\Permission', $args['pid']);
  136. $perm2['sequence'] = $altsequence;
  137. $this->entityManager->flush();
  138. }
  139. return true;
  140. }
  141. /**
  142. * Update attributes of a permission.
  143. *
  144. * @param int $args ['pid'] the ID of the permission to update.
  145. * @param string $args ['realm'] the new realm of the permission.
  146. * @param int $args ['id'] the new group/user id of the permission.
  147. * @param string $args ['component'] the new component of the permission.
  148. * @param string $args ['instance'] the new instance of the permission.
  149. * @param int $args ['level'] the new level of the permission.
  150. *
  151. * @return bool true on success, false on failure.
  152. */
  153. public function update($args)
  154. {
  155. // Security check
  156. if (!SecurityUtil::checkPermission('Permissions::', "group::$args[pid]", ACCESS_ADMIN)) {
  157. throw new \Zikula\Framework\Exception\ForbiddenException();
  158. }
  159. // Argument check
  160. if ((!isset($args['pid'])) ||
  161. (!isset($args['seq'])) ||
  162. (!isset($args['oldseq'])) ||
  163. (!isset($args['realm'])) ||
  164. (!isset($args['id'])) ||
  165. (!isset($args['component'])) ||
  166. (!isset($args['instance'])) ||
  167. (!isset($args['level']))) {
  168. throw new \InvalidArgumentException('Missing or invalid arguments');
  169. }
  170. // get and update permission
  171. $permission = $this->entityManager->find('PermissionsModule\Entity\Permission', $args['pid']);
  172. $permission['gid'] = $args['id'];
  173. $permission['realm'] = $args['realm'];
  174. $permission['component'] = $args['component'];
  175. $permission['instance'] = $args['instance'];
  176. $permission['level'] = $args['level'];
  177. $this->entityManager->flush();
  178. if ($args['seq'] != $args['oldseq']) {
  179. $this->resequence(array('type' => 'group', 'newseq' => $args['seq'], 'oldseq' => $args['oldseq']));
  180. }
  181. return true;
  182. }
  183. /**
  184. * Create a new perm.
  185. *
  186. * @param string $args ['realm'] the new realm of the permission.
  187. * @param int $args ['id'] the new group/user id of the permission.
  188. * @param string $args ['component'] the new component of the permission.
  189. * @param string $args ['instance'] the new instance of the permission.
  190. * @param int $args ['level'] the new level of the permission.
  191. *
  192. * @return boolean true on success, false on failure.
  193. */
  194. public function create($args)
  195. {
  196. // Security check
  197. if (!SecurityUtil::checkPermission('Permissions::', "group::$args[id]", ACCESS_ADMIN)) {
  198. throw new \Zikula\Framework\Exception\ForbiddenException();
  199. }
  200. // Argument check
  201. if ((!isset($args['realm'])) ||
  202. (!isset($args['id'])) ||
  203. (!isset($args['component'])) ||
  204. (!isset($args['instance'])) ||
  205. (!isset($args['level'])) ||
  206. (!isset($args['insseq']))) {
  207. throw new \InvalidArgumentException('Missing or invalid arguments');
  208. }
  209. // Insert Capability
  210. if ($args['insseq'] == -1) {
  211. $maxseq = $this->maxsequence();
  212. $newseq = $maxseq + 1;
  213. } else {
  214. // Increase sequence numbers
  215. $dql = "UPDATE PermissionsModule\Entity\Permission p SET p.sequence = p.sequence + 1 WHERE p.sequence >= " . (int)DataUtil::formatForStore($args['insseq']);
  216. $query = $this->entityManager->createQuery($dql);
  217. $result = $query->getResult();
  218. if (!$result) {
  219. return LogUtil::registerError($this->__('Error! Could not save permission rule sequences.'));
  220. }
  221. $newseq = $args['insseq'];
  222. }
  223. $obj = new \PermissionsModule\Entity\Permission;
  224. $obj['gid'] = (int)$args['id'];
  225. $obj['sequence'] = $newseq;
  226. $obj['realm'] = (int)$args['realm'];
  227. $obj['component'] = $args['component'];
  228. $obj['instance'] = $args['instance'];
  229. $obj['level'] = (int)$args['level'];
  230. $this->entityManager->persist($obj);
  231. $this->entityManager->flush();
  232. // Clean-up
  233. $this->resequence();
  234. return $obj->toArray();
  235. }
  236. /**
  237. * Delete a perm.
  238. *
  239. * @param string $args ['type'] the type of the permission to update (user or group).
  240. * @param int $args ['pid'] the ID of the permission to delete.
  241. *
  242. * @return boolean true on success, false on failure.
  243. */
  244. public function delete($args)
  245. {
  246. // Security check
  247. if (!SecurityUtil::checkPermission('Permissions::', "group::$args[pid]", ACCESS_ADMIN)) {
  248. throw new \Zikula\Framework\Exception\ForbiddenException();
  249. }
  250. // Argument check
  251. if (!isset($args['pid'])) {
  252. throw new \InvalidArgumentException('Missing or invalid arguments');
  253. }
  254. // get and delete permission
  255. $permission = $this->entityManager->find('PermissionsModule\Entity\Permission', $args['pid']);
  256. $this->entityManager->remove($permission);
  257. $this->entityManager->flush();
  258. $this->resequence();
  259. return true;
  260. }
  261. /**
  262. * Get the maximum sequence number in permissions table.
  263. *
  264. * @return int the maximum sequence number.
  265. */
  266. public function maxsequence()
  267. {
  268. // Security check
  269. if (!SecurityUtil::checkPermission('Permissions::', '::', ACCESS_ADMIN)) {
  270. throw new \Zikula\Framework\Exception\ForbiddenException();
  271. }
  272. $dql = "SELECT MAX(p.sequence) FROM PermissionsModule\Entity\Permission p";
  273. $query = $this->entityManager->createQuery($dql);
  274. return (int)$query->getSingleScalarResult();
  275. }
  276. /**
  277. * Resequence a permissions table.
  278. *
  279. * @return boolean
  280. */
  281. public function resequence()
  282. {
  283. // Security check
  284. if (!SecurityUtil::checkPermission('Permissions::', "group::", ACCESS_ADMIN)) {
  285. throw new \Zikula\Framework\Exception\ForbiddenException();
  286. }
  287. // get all permissions
  288. $permissions = $this->entityManager->getRepository('PermissionsModule\Entity\Permission')->findBy(array(), array('sequence' => 'ASC'));
  289. if (!$permissions) {
  290. return false;
  291. }
  292. // fix sequence numbers
  293. $sequence = 1;
  294. foreach ($permissions as $permission) {
  295. $curseq = $permission['sequence'];
  296. if ($curseq != $sequence) {
  297. $permission['sequence'] = $sequence;
  298. }
  299. $sequence++;
  300. }
  301. $this->entityManager->flush();
  302. return true;
  303. }
  304. /**
  305. * Resequence permissions.
  306. *
  307. * Called when a permission is assigned the same sequence number as an existing permission.
  308. *
  309. * @param string $args ['newseq'] the desired sequence.
  310. * @param string $args ['oldseq'] the original sequence number.
  311. *
  312. * @return boolean
  313. */
  314. public function full_resequence($args)
  315. {
  316. // Security check
  317. if (!SecurityUtil::checkPermission('Permissions::', "::", ACCESS_ADMIN)) {
  318. throw new \Zikula\Framework\Exception\ForbiddenException();
  319. }
  320. // Argument check
  321. if (!isset($args['newseq']) || !isset($args['oldseq'])) {
  322. throw new \InvalidArgumentException('Missing or invalid arguments');
  323. }
  324. $newseq = $args['newseq'];
  325. $oldseq = $args['oldseq'];
  326. unset($args);
  327. //find out the maximum sequence number
  328. $maxseq = $this->maxsequence();
  329. // The new sequence is higher in the list
  330. if ((int)$oldseq > (int)$newseq) {
  331. if ($newseq < 1) {
  332. $newseq = 1;
  333. }
  334. $dql = "SELECT p FROM PermissionsModule\Entity\Permission p WHERE p.sequence >= {$newseq} AND p.sequence <= {$oldseq} ORDER BY p.sequence DESC";
  335. $query = $this->entityManager->createQuery($dql);
  336. $permissions = $query->getResult();
  337. foreach ($permissions as $permission) {
  338. $curseq = $permission['sequence'];
  339. if ($curseq == $oldseq) {
  340. // we are dealing with the old value so make it the new value
  341. $curseq = $newseq;
  342. } else {
  343. $curseq++;
  344. }
  345. $permission['sequence'] = (int)$curseq;
  346. }
  347. } else {
  348. // The new sequence is lower in the list
  349. // if the new requested sequence is bigger than
  350. // the maximum sequence number then set it to
  351. // the maximum number. We don't want any spaces
  352. // in the sequence.
  353. if ($newseq > $maxseq) {
  354. $newseq = (int)$maxseq;
  355. }
  356. $dql = "SELECT p FROM PermissionsModule\Entity\Permission p WHERE p.sequence >= {$oldseq} AND p.sequence <= {$newseq} ORDER BY p.sequence ASC";
  357. $query = $this->entityManager->createQuery($dql);
  358. $permissions = $query->getResult();
  359. foreach ($permissions as $permission) {
  360. $curseq = $permission['sequence'];
  361. if ($curseq == $oldseq) {
  362. // we are dealing with the old value so make it the new value
  363. $curseq = $newseq;
  364. } else {
  365. $curseq--;
  366. }
  367. $permission['sequence'] = (int)$curseq;
  368. }
  369. }
  370. $this->entityManager->flush();
  371. return true;
  372. }
  373. /**
  374. * Get all security permissions schemas.
  375. *
  376. * @return array array if permission schema values.
  377. */
  378. public function getallschemas()
  379. {
  380. // Security check
  381. if (!SecurityUtil::checkPermission('Permissions::', '::', ACCESS_ADMIN)) {
  382. throw new \Zikula\Framework\Exception\ForbiddenException();
  383. }
  384. $schemas = SecurityUtil::getSchemas();
  385. BlockUtil::loadAll();
  386. $modinfos = ModUtil::getAllMods();
  387. foreach ($modinfos as $modinfo) {
  388. if (!empty($modinfo['securityschema'])) {
  389. $schemas = array_merge($schemas, $modinfo['securityschema']);
  390. }
  391. }
  392. uksort($schemas, 'strnatcasecmp');
  393. SecurityUtil::setSchemas($schemas);
  394. return $schemas;
  395. }
  396. /**
  397. * Get available admin panel links.
  398. *
  399. * @return array array of admin links.
  400. */
  401. public function getlinks()
  402. {
  403. $links = array();
  404. if (SecurityUtil::checkPermission('Permissions::', '::', ACCESS_READ)) {
  405. $links[] = array('url' => ModUtil::url('Permissions', 'admin', 'view', array()), 'text' => $this->__('Permission rules list'), 'id' => 'permissions_view', 'class' => 'z-icon-es-view');
  406. }
  407. if (SecurityUtil::checkPermission('Permissions::', '::', ACCESS_ADD)) {
  408. $links[] = array('url' => ModUtil::url('Permissions', 'admin', 'listedit', array('action' => 'add')), 'text' => $this->__('Create new permission rule'), 'id' => 'permissions_new', 'class' => 'z-icon-es-new');
  409. }
  410. if (SecurityUtil::checkPermission('Permissions::', '::', ACCESS_ADMIN)) {
  411. $links[] = array('url' => ModUtil::url('Permissions', 'admin', 'modifyconfig'), 'text' => $this->__('Settings'), 'id' => 'permissions_modifyconfig', 'class' => 'z-icon-es-config');
  412. }
  413. if (ModUtil::getName() == 'Permissions') {
  414. $links[] = array('url' => ModUtil::url('Permissions', 'admin', 'viewinstanceinfo'), 'text' => $this->__('Permission rules information'), 'title' => $this->__('Permission rules information'), 'class' => 'z-icon-es-info showinstanceinformation');
  415. }
  416. return $links;
  417. }
  418. }