Helper.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. <?php
  2. /**
  3. * Helper class file.
  4. *
  5. * @author Spyros Soldatos <spyros@valor.gr>
  6. * @link http://code.google.com/p/srbac/
  7. */
  8. /**
  9. * Helper is a class providing static methods that are used across srbac.
  10. *
  11. * @author Spyros Soldatos <spyros@valor.gr>
  12. * @package srbac.components
  13. * @since 1.0.0
  14. */
  15. class Helper {
  16. const SUCCESS = 0;
  17. const OVERWRITE = 1;
  18. const ERROR = 2;
  19. /**
  20. * Return the roles assigned to a user or all the roles if no userid is provided
  21. * @param string $userid The id of the user
  22. * @return array An array of roles(AuthItems) assigned to the user
  23. */
  24. public static function getUserAssignedRoles($userid) {
  25. $assigned = new CDbCriteria();
  26. $assigned->join = 'LEFT JOIN ' . Assignments::model()->tableName() . ' a ON name = a.itemname';
  27. if ($userid) {
  28. $assigned->condition = "type = ". CAuthItem::TYPE_ROLE ." AND userid= '" . $userid . "'";
  29. } else {
  30. $assigned->condition = "type = ". CAuthItem::TYPE_ROLE;
  31. }
  32. $assigned->order = "name ASC";
  33. $assigned = AuthItem::model()->findAll($assigned);
  34. return ($assigned === null) ? array(): $assigned;
  35. }
  36. /**
  37. * Gets the roles that are not assigned to the user by getting all the roles and
  38. * removes those assigned to the user, or all the roles if no user id is provided
  39. * @param String $userid The user's id
  40. * @return array An array of roles(AuthItems) not assigned to the user
  41. */
  42. public static function getUserNotAssignedRoles($userid) {
  43. $roles = new CDbCriteria();
  44. $roles->condition = "type=". CAuthItem::TYPE_ROLE;
  45. $roles->order = "name ASC";
  46. $final = array();
  47. if ($userid) {
  48. $na = AuthItem::model()->findAll($roles);
  49. } else {
  50. return AuthItem::model()->findAll($roles);
  51. }
  52. $as = self::getUserAssignedRoles($userid);
  53. foreach ($na as $n) {
  54. $exists = false;
  55. foreach ($as as $a) {
  56. if ($a['name'] == $n['name']) {
  57. $exists = true;
  58. }
  59. }
  60. if (!$exists) {
  61. $final[] = $n;
  62. }
  63. }
  64. return ($final === null) ? array(): $final;
  65. }
  66. /**
  67. * Return the tasks assigned to a role or all the tasks if no role is provided
  68. * @param string $name The name of the role
  69. * @return array An array of tasks(AuthItems) assigned to the role
  70. */
  71. public static function getRoleAssignedTasks($name) {
  72. $tasks = new CDbCriteria();
  73. if ($name) {
  74. $tasks->condition = "type=". CAuthItem::TYPE_TASK." AND parent ='" . $name . "'";
  75. $tasks->join = 'left join ' . Yii::app()->authManager->itemChildTable . ' on name = child';
  76. } else {
  77. $tasks->condition = "type=". CAuthItem::TYPE_TASK;
  78. }
  79. $tasks->order = "name ASC";
  80. $assigned = AuthItem::model()->findAll($tasks);
  81. return ($assigned === null) ? array(): $assigned;
  82. }
  83. /**
  84. * Return the tasks not assigned to a role by getting all the tasks and
  85. * removing those assigned to the role, or all the tasks if no role is provided
  86. * @param string $name The name of the role
  87. * @return array An array of tasks(AuthItems) not assigned to the role
  88. */
  89. public static function getRoleNotAssignedTasks($name) {
  90. $tasks = new CDbCriteria();
  91. $tasks->condition = "type=". CAuthItem::TYPE_TASK;
  92. $tasks->order = "name ASC";
  93. $final = array();
  94. if ($name) {
  95. $na = AuthItem::model()->findAll($tasks);
  96. } else {
  97. return AuthItem::model()->findAll($tasks);
  98. }
  99. $as = self::getRoleAssignedTasks($name);
  100. foreach ($na as $n) {
  101. $exists = false;
  102. foreach ($as as $a) {
  103. if ($a['name'] == $n['name']) {
  104. $exists = true;
  105. }
  106. }
  107. if (!$exists) {
  108. $final[] = $n;
  109. }
  110. }
  111. return ($final === null) ? array(): $final;
  112. }
  113. /**
  114. * Return the operations assigned to a task or all the operations if no task
  115. * is provided
  116. * @param string $name The name of the task
  117. * @param boolean $clever Use clever Assigning
  118. * @return array An array of operations(AuthItems) assigned to the task
  119. */
  120. public static function getTaskAssignedOpers($name, $clever = false) {
  121. $tasks = new CDbCriteria();
  122. if ($name) {
  123. $tasks->condition = "type=". CAuthItem::TYPE_OPERATION." AND parent ='" . $name . "'";
  124. $tasks->join = 'left join ' . Yii::app()->authManager->itemChildTable . ' on name = child';
  125. if ($clever) {
  126. // $p[0] = "/Viewing/";
  127. // $p[1] = "/Administrating/";
  128. // $r[0] = "";
  129. // $r[1] = "";
  130. // $cleverName = preg_replace($p, $r, $name);
  131. // $len = strlen($cleverName);
  132. //$tasks->addCondition("SUBSTR(child,0," . $len . ") = '" . $cleverName . "'");
  133. $tasks->addCondition("SUBSTR(child,0,3) = SUBSTR('" . $name . "',0,3)");
  134. }
  135. } else {
  136. $tasks->condition = "type=". CAuthItem::TYPE_OPERATION;
  137. }
  138. $tasks->order = "name ASC";
  139. $assigned = AuthItem::model()->findAll($tasks);
  140. return ($assigned === null) ? array(): $assigned;
  141. }
  142. /**
  143. * Return the operations not assigned to a task by getting all the operations
  144. * and removing those assigned to the task, or all the operations if no task
  145. * is provided
  146. * @param string $name The name of the task
  147. * @param boolean $clever Use clever Assigning
  148. * @return array An array of operations(AuthItems) not assigned to the task
  149. */
  150. public static function getTaskNotAssignedOpers($name, $clever = false) {
  151. $tasks = new CDbCriteria();
  152. $tasks->condition = "type=". CAuthItem::TYPE_OPERATION;
  153. if ($clever) {
  154. // $p[0] = "/Viewing/";
  155. // $p[1] = "/Administrating/";
  156. // $r[0] = "";
  157. // $r[1] = "";
  158. // $cleverName = preg_replace($p, $r, $name);
  159. // $len = strlen($cleverName);
  160. //$tasks->addCondition("SUBSTR(name,0," . $len . ") = '" . $cleverName . "'");
  161. $tasks->addCondition("SUBSTR(name,0,3) = SUBSTR('" . $name . "',0,3)");
  162. }
  163. $final = array();
  164. if ($name) {
  165. $na = AuthItem::model()->findAll($tasks);
  166. } else {
  167. return AuthItem::model()->findAll($tasks);
  168. }
  169. $as = self::getTaskAssignedOpers($name, $clever);
  170. foreach ($na as $n) {
  171. $exists = false;
  172. foreach ($as as $a) {
  173. if ($a['name'] == $n['name']) {
  174. $exists = true;
  175. }
  176. }
  177. if (!$exists) {
  178. $final[] = $n;
  179. }
  180. }
  181. return ($final === null) ? array(): $final;
  182. }
  183. /**
  184. * Marking words / phrases that are missing translation by adding a red * after
  185. * the word / phrase
  186. * @param CMissingTranslationEvent $event
  187. */
  188. public static function markWords($event) {
  189. if (self::findModule('srbac')->debug) {
  190. $event->message .= "*";
  191. }
  192. }
  193. /**
  194. * Check if authorizer is assigned to a user.
  195. * Until Authorizer is assigned to a user all users have access to srbac
  196. * administration. Also all users have access to srbac admin if srbac debug
  197. * attribute is true
  198. * @return true if authorizer is assigned to a user
  199. */
  200. public static function isAuthorizer() {
  201. if (self::findModule('srbac')->debug) {
  202. return false;
  203. }
  204. $criteria = new CDbCriteria();
  205. $criteria->condition = "itemname = '" . self::findModule('srbac')->superUser . "'";
  206. $authorizer = Assignments::model()->find($criteria);
  207. if ($authorizer !== null) {
  208. return true;
  209. }
  210. return false;
  211. }
  212. /**
  213. * If action is "install" checks for previous installations and if there's
  214. * one asks for ovewrite. If action is "ovewrite" or there's not a previous
  215. * installation performs the installation and returns the status of the
  216. * installation
  217. * @param String action
  218. * @param int demo
  219. * @return int status (0:Success, 1:Ovewrite, 2: Error)
  220. */
  221. public static function install($action, $demo) {
  222. $db = Yii::app()->authManager->db;
  223. /* @var $db CDbConnection */
  224. $auth = Yii::app()->authManager;
  225. /* @var $auth CDbAuthManager */
  226. $itemTable = $auth->itemTable;
  227. if ($action == "Install") {
  228. if (self::findModule("srbac")->isInstalled()) {
  229. return self::OVERWRITE; // Already installed
  230. } else {
  231. return self::_install($demo);
  232. }
  233. } else {
  234. return self::_install($demo);
  235. }
  236. }
  237. /**
  238. * Performs the installation and returns the status
  239. * @param int demo
  240. * @return int status (0:Success, 1:Ovewrite, 2: Error)
  241. */
  242. private static function _install($demo) {
  243. $db = Yii::app()->authManager->db;
  244. /* @var $db CDbConnection */
  245. $auth = Yii::app()->authManager;
  246. /* @var $auth CDbAuthManager */
  247. $transaction = $db->beginTransaction();
  248. $itemTable = $auth->itemTable;
  249. $assignmentTable = $auth->assignmentTable;
  250. $itemChildTable = $auth->itemChildTable;
  251. try {
  252. // Drop tables
  253. $db->createCommand("drop table if exists " . $assignmentTable . ";")->execute();
  254. $db->createCommand("drop table if exists " . $itemChildTable . ";")->execute();
  255. $db->createCommand("drop table if exists " . $itemTable . ";")->execute();
  256. //create tables
  257. $sql = "create table " . $itemTable . " (name varchar(64) not null,
  258. type integer not null,
  259. description text,
  260. bizrule text,
  261. data text,
  262. primary key (name));";
  263. $db->createCommand($sql)->execute();
  264. $sql = "create table " . $itemChildTable . " (parent varchar(64) not null,
  265. child varchar(64) not null,
  266. primary key (parent,child),
  267. foreign key (parent) references " . $itemTable . " (name) on delete cascade on update cascade,
  268. foreign key (child) references " . $itemTable . " (name) on delete cascade on update cascade
  269. );";
  270. $db->createCommand($sql)->execute();
  271. $sql = "create table " . $assignmentTable . "(itemname varchar(64) not null,
  272. userid varchar(64) not null,
  273. bizrule text,
  274. data text,
  275. primary key (itemname,userid),
  276. foreign key (itemname) references " . $itemTable . " (name) on delete cascade on update cascade
  277. );";
  278. $db->createCommand($sql)->execute();
  279. //Insert Authorizer
  280. $sql = "INSERT INTO " . $itemTable . " (name, type) VALUES ('" . self::findModule('srbac')->superUser . "',2)";
  281. $db->createCommand($sql)->execute();
  282. if ($demo == 1) {
  283. //Insert Demo Data
  284. $sql = "INSERT INTO " . $itemTable . " (name, type) VALUES ('Administrator',". CAuthItem::TYPE_ROLE.")";
  285. $db->createCommand($sql)->execute();
  286. $sql = "INSERT INTO " . $itemTable . " (name, type) VALUES ('User',". CAuthItem::TYPE_ROLE.")";
  287. $db->createCommand($sql)->execute();
  288. $sql = "INSERT INTO " . $itemTable . " (name, type) VALUES ('Post Manager',". CAuthItem::TYPE_TASK.")";
  289. $db->createCommand($sql)->execute();
  290. $sql = "INSERT INTO " . $itemTable . " (name, type) VALUES ('User Manager',". CAuthItem::TYPE_TASK.")";
  291. $db->createCommand($sql)->execute();
  292. $sql = "INSERT INTO " . $itemTable . " (name, type) VALUES ('Delete Post',". CAuthItem::TYPE_OPERATION.")";
  293. $db->createCommand($sql)->execute();
  294. $sql = "INSERT INTO " . $itemTable . " (name, type) VALUES ('Create Post',". CAuthItem::TYPE_OPERATION.")";
  295. $db->createCommand($sql)->execute();
  296. $sql = "INSERT INTO " . $itemTable . " (name, type) VALUES ('Edit Post',". CAuthItem::TYPE_OPERATION.")";
  297. $db->createCommand($sql)->execute();
  298. $sql = "INSERT INTO " . $itemTable . " (name, type) VALUES ('View Post',". CAuthItem::TYPE_OPERATION.")";
  299. $db->createCommand($sql)->execute();
  300. $sql = "INSERT INTO " . $itemTable . " (name, type) VALUES ('Delete User',". CAuthItem::TYPE_OPERATION.")";
  301. $db->createCommand($sql)->execute();
  302. $sql = "INSERT INTO " . $itemTable . " (name, type) VALUES ('Create User',". CAuthItem::TYPE_OPERATION.")";
  303. $db->createCommand($sql)->execute();
  304. $sql = "INSERT INTO " . $itemTable . " (name, type) VALUES ('Edit User',". CAuthItem::TYPE_OPERATION.")";
  305. $db->createCommand($sql)->execute();
  306. $sql = "INSERT INTO " . $itemTable . " (name, type) VALUES ('View User',". CAuthItem::TYPE_OPERATION.")";
  307. $db->createCommand($sql)->execute();
  308. }
  309. $transaction->commit();
  310. } catch (CDbException $ex) {
  311. $transaction->rollback();
  312. return self::ERROR; //Error
  313. }
  314. return self::SUCCESS;
  315. //Success
  316. }
  317. /**
  318. * Find a module searching in application modules and if it's not found there
  319. * looks in modules' modules
  320. * @param String $moduleID The model to find
  321. * @return The module, if it's found else null
  322. */
  323. public static function findModule($moduleID) {
  324. if (Yii::app()->getModule($moduleID)) {
  325. return Yii::app()->getModule($moduleID);
  326. }
  327. $modules = Yii::app()->getModules();
  328. foreach ($modules as $mod=>$conf) {
  329. if (Yii::app()->getModule($mod)) {
  330. return self::findInModule(Yii::app()->getModule($mod), $moduleID);
  331. }
  332. }
  333. return null;
  334. }
  335. /**
  336. * Search for a child module
  337. * @param String $parent The parent module
  338. * @param String $moduleID The module to find
  339. * @return The module, if it's not found returns null
  340. */
  341. private static function findInModule($parent, $moduleID) {
  342. if ($parent->getModule($moduleID)) {
  343. return $parent->getModule($moduleID);
  344. } else {
  345. $modules = $parent->getModules();
  346. foreach ($modules as $mod => $conf) {
  347. return $this->findInModule($parent->getModule($mod), $moduleID);
  348. }
  349. }
  350. return null;
  351. }
  352. /**
  353. * Translates texts based on Yii version
  354. * @param String $source The messages source
  355. * @param String $text The text to transalte
  356. * @return String The translated text
  357. */
  358. public static function translate($source, $text, $lang = null) {
  359. return self::findModule("srbac")->tr->translate($source, $text, $lang);
  360. }
  361. /**
  362. * Checks if a given version is supported by the current running Yii version
  363. * @param String $checkVersion
  364. * @return boolean True if the given version is supportedby the running Yii
  365. * version
  366. */
  367. public static function checkYiiVersion($checkVersion) {
  368. //remove dev builds
  369. $version = preg_replace("/[a-z]/", "", Yii::getVersion());
  370. $yiiVersionNoBuilds = explode("-", $version);
  371. $checkVersion = explode(".", $checkVersion);
  372. $yiiVersion = explode(".", $yiiVersionNoBuilds[0]);
  373. $yiiVersion[2] = isset($yiiVersion[2]) ? $yiiVersion[2] : "0";
  374. if ($yiiVersion[0] > $checkVersion[0]) {
  375. return true;
  376. } else if ($yiiVersion[0] < $checkVersion[0]) {
  377. return false;
  378. } else {
  379. if ($yiiVersion[1] > $checkVersion[1]) {
  380. return true;
  381. } else if ($yiiVersion[1] < $checkVersion[1]) {
  382. return false;
  383. } else {
  384. if ($yiiVersion[2] > $checkVersion[2]) {
  385. return true;
  386. } else if ($yiiVersion[2] == $checkVersion[2]) {
  387. return true;
  388. } else {
  389. return false;
  390. }
  391. }
  392. }
  393. return false;
  394. }
  395. public static function checkInstall($key, $value) {
  396. if (in_array($key, explode(",", SrbacModule::PRIVATE_ATTRIBUTES))) {
  397. return;
  398. }
  399. $class = "";
  400. $out = array("", "");
  401. switch ($key) {
  402. case ($key == "userid" || $key == "username"):
  403. $class = "installNoError";
  404. $u = self::findModule("srbac")->getUserModel();
  405. $user = new $u;
  406. if (!$user->hasAttribute($value)) {
  407. $class = "installError";
  408. $out[1] = self::ERROR;
  409. }
  410. break;
  411. case "css":
  412. $class = "installNoError";
  413. $cssPublished = self::findModule("srbac")->isCssPublished();
  414. if (!$cssPublished) {
  415. $class = "installError";
  416. $out[1] = self::ERROR;
  417. }
  418. break;
  419. case (($key == "layout" && $value != "main" ) || $key == "notAuthorizedView" || $key == "imagesPath"
  420. || $key == "header" || $key == "footer"):
  421. $class = "installNoError";
  422. $file = Yii::getPathOfAlias($value) . ".php";
  423. $path = Yii::getPathOfAlias($value);
  424. if (!file_exists($file) && !is_dir($path)) {
  425. $class = "installError";
  426. $out[1] = self::ERROR;
  427. }
  428. break;
  429. case ($key == "imagesPack"):
  430. $class = "installNoError";
  431. if (!in_array($value, explode(",", SrbacModule::ICON_PACKS))) {
  432. $class = "installError";
  433. $out[1] = self::ERROR;
  434. }
  435. break;
  436. case "debug":
  437. break;
  438. }
  439. $out[0] = "<tr><td valign='top'>" . (substr($key, 0, 1) == "_" ? substr($key, 1) : $key) . "</td>";
  440. $out[0] .= "<td><div class='$class'>";
  441. $out[0] .= (!is_array($value)) ? $value : implode(", ", $value);
  442. $out[0] .= "</div><div class='$class'></div></td>";
  443. return $out;
  444. }
  445. /**
  446. * Publishes srbac cssfile
  447. * @return boolean If css published or not
  448. */
  449. public static function publishCss($css, $forcePublish = false) {
  450. if (Yii::app()->request->isAjaxRequest && !$forcePublish) {
  451. return true;
  452. }
  453. //Search in default Yii css directory
  454. $cssFile = Yii::getPathOfAlias("webroot.css") . DIRECTORY_SEPARATOR . $css;
  455. if (is_file($cssFile) && !Yii::app()->clientScript->isCssFileRegistered(Yii::app()->request->baseUrl . "/css/" . $css)) {
  456. $cssUrl = Yii::app()->request->baseUrl . "/css/" . $css;
  457. Yii::app()->clientScript->registerCssFile($cssUrl);
  458. self::findModule("srbac")->setCssUrl($cssUrl);
  459. return true;
  460. } else {
  461. // Search in srbac css dir
  462. $cssFile = Yii::getPathOfAlias("srbac.css") . DIRECTORY_SEPARATOR . $css;
  463. $cssDir = Yii::getPathOfAlias("srbac.css");
  464. if (is_file($cssFile)) {
  465. $published = Yii::app()->assetManager->publish($cssDir);
  466. $cssFile = $published . "/" . $css;
  467. if (!Yii::app()->clientScript->isCssFileRegistered($cssFile)) {
  468. Yii::app()->clientScript->registerCssFile($cssFile);
  469. }
  470. return true;
  471. } else {
  472. return false;
  473. }
  474. }
  475. }
  476. /**
  477. * Publish srbac images
  478. * @param String $imagesPath The path to the images
  479. * @param String $imagesPack The icons pack to use
  480. */
  481. public static function publishImages($imagesPath, $imagesPack) {
  482. $path = Yii::getPathOfAlias($imagesPath) . DIRECTORY_SEPARATOR . $imagesPack;
  483. if (is_dir($path)) {
  484. return Yii::app()->assetManager->publish($path);
  485. } else {
  486. return "";
  487. }
  488. }
  489. /**
  490. * Checks if the always allowed file is writeable
  491. * @return boolean true if always allowed file is writeable or false otherwise
  492. */
  493. public static function isAlwaysAllowedFileWritable() {
  494. if (!($f = @fopen(self::findModule("srbac")->getAlwaysAllowedFile(), 'r+'))) {
  495. return false;
  496. }
  497. fclose($f);
  498. return true;
  499. }
  500. }