/Library/Kumbia/Acl/Adapters/Model.php

http://kumbia-enterprise.googlecode.com/ · PHP · 509 lines · 262 code · 24 blank · 223 comment · 63 complexity · 2c4819c1a303c95ba5283661c9faed7a MD5 · raw file

  1. <?php
  2. /**
  3. * Kumbia Enterprise Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the New BSD License that is bundled
  8. * with this package in the file docs/LICENSE.txt.
  9. * If you did not receive a copy of the license and are unable to
  10. * obtain it through the world-wide-web, please send an email
  11. * to license@loudertechnology.com so we can send you a copy immediately.
  12. *
  13. * @category Kumbia
  14. * @package Acl
  15. * @subpackage Adapters
  16. * @copyright Copyright (c) 2008-2009 Louder Technology COL. (http://www.loudertechnology.com)
  17. * @copyright Copyright (c) 2005-2009 Andres Felipe Gutierrez (gutierrezandresfelipe@gmail.com)
  18. * @license New BSD License
  19. * @version $Id: Model.php 82 2009-09-13 21:06:31Z gutierrezandresfelipe $
  20. */
  21. /**
  22. * AclModel
  23. *
  24. * Permite administrar listas ACL usando entidades de un gestor relacional
  25. *
  26. * @category Kumbia
  27. * @package Acl
  28. * @subpackage Adapters
  29. * @copyright Copyright (c) 2008-2009 Louder Technology COL. (http://www.loudertechnology.com)
  30. * @copyright Copyright (c) 2005-2009 Andres Felipe Gutierrez (gutierrezandresfelipe@gmail.com)
  31. * @license New BSD License
  32. */
  33. class AclModel implements AclAdapter {
  34. /**
  35. * Nombre de la clase que administra los accesos
  36. *
  37. * @var string
  38. */
  39. private $_modelName;
  40. /**
  41. * Nombre de la clase que administra los roles
  42. *
  43. * @var string
  44. */
  45. private $_modelRolesName;
  46. /**
  47. * Nombre de la clase que administra los recursos
  48. *
  49. * @var string
  50. */
  51. private $_modelResourcesName;
  52. /**
  53. * Nombre de la clase que relaciona los recursos con sus operaciones
  54. *
  55. * @var string
  56. */
  57. private $_modelAccessResourcesName;
  58. /**
  59. * Nombre de la clase que administra la herencia entre roles
  60. *
  61. * @var string
  62. */
  63. private $_modelInheritsName;
  64. /**
  65. * Objeto ActiveRecordTransaction
  66. *
  67. * @var ActiveRecordTransaction
  68. */
  69. private $_transaction;
  70. /**
  71. * Constructor de la Clase AclModel
  72. *
  73. * @param array $params
  74. */
  75. public function __construct($params){
  76. if(!isset($params['className'])){
  77. /**
  78. * Debe indicar el nombre del modelo que administra la lista de Acceso
  79. */
  80. $message = CoreLocale::getErrorMessage(-20);
  81. throw new AclException($message, -20);
  82. }
  83. if(!EntityManager::isModel($params['className'])){
  84. /**
  85. * La clase no es un modelo valido
  86. */
  87. $message = CoreLocale::getErrorMessage(-21, $params['className']);
  88. throw new AclException($message, -21);
  89. }
  90. $this->_modelName = $params['className'];
  91. if(isset($params['rolesClassName'])){
  92. if(!EntityManager::isModel($params['rolesClassName'])){
  93. $message = CoreLocale::getErrorMessage(-21, $params['rolesClassName']);
  94. throw new AclException($message, -21);
  95. }
  96. $this->_modelRolesName = $params['rolesClassName'];
  97. }
  98. if(isset($params['resourcesClassName'])){
  99. if(!EntityManager::isModel($params['resourcesClassName'])){
  100. $message = CoreLocale::getErrorMessage(-21, $params['resourcesClassName']);
  101. throw new AclException($message, -21);
  102. }
  103. $this->_modelResourcesName = $params['resourcesClassName'];
  104. }
  105. if(isset($params['accessResourcesClassName'])){
  106. if(!EntityManager::isModel($params['accessResourcesClassName'])){
  107. $message = CoreLocale::getErrorMessage(-21, $params['accessResourcesClassName']);
  108. throw new AclException($message, -21);
  109. }
  110. $this->_modelAccessResourcesName = $params['accessResourcesClassName'];
  111. }
  112. }
  113. /**
  114. * Agrega un Rol a la Lista ACL
  115. *
  116. * $roleObject = Objeto de la clase AclRole para agregar a la lista
  117. * $accessInherits = Nombre del Role del cual hereda permisos o array del grupo
  118. * de perfiles del cual hereda permisos
  119. *
  120. * Ej:
  121. * <code>$acl->addRole(new Acl_Role('administrador'), 'consultor');</code>
  122. *
  123. * @param AclRole $roleObject
  124. * @param array $accessInherits
  125. * @return boolean
  126. */
  127. public function addRole(AclRole $roleObject, $accessInherits=''){
  128. if(!$this->_modelRolesName){
  129. //No se ha definido el modelo que administra los roles
  130. $message = CoreLocale::getErrorMessage(-22);
  131. throw new AclException($message, -22);
  132. }
  133. $role = EntityManager::getEntityInstance($this->_modelRolesName);
  134. if(method_exists($role, "setName")){
  135. $role->setName($roleObject->getName());
  136. } else {
  137. $role->name = $roleObject->getName();
  138. }
  139. if($role->hasField('description')){
  140. $role->description = $roleObject->getDescription();
  141. }
  142. if(!$this->isRole($roleObject->getName())){
  143. if($role->save()==false){
  144. //No se pudo crear el rol
  145. foreach($role->getMessages() as $message){
  146. $message = CoreLocale::getErrorMessage(-23, $message->getMessage());
  147. throw new AclException($message, -23);
  148. }
  149. }
  150. } else {
  151. //El role ya se ha creado en la lista de acceso
  152. $message = CoreLocale::getErrorMessage(-24);
  153. throw new AclException($message, -24);
  154. }
  155. if($accessInherits!=''){
  156. }
  157. return true;
  158. }
  159. /**
  160. * Hace que un rol herede los accesos de otro rol
  161. *
  162. * @param string $role
  163. * @param string $roleToInherit
  164. */
  165. public function addInherit($role, $roleToInherit){
  166. }
  167. /**
  168. *
  169. * Verifica si un rol existe en la lista o no
  170. *
  171. * @param string $roleName
  172. * @return boolean
  173. */
  174. public function isRole($roleName){
  175. if(!$this->_modelRolesName){
  176. //No se ha definido el modelo que administra los Roles
  177. $message = CoreLocale::getErrorMessage(-22);
  178. throw new AclException($message, -22);
  179. }
  180. $roles = EntityManager::getEntityInstance($this->_modelRolesName);
  181. return $roles->count("name = '$roleName'") > 0 ? true : false;
  182. }
  183. /**
  184. *
  185. * Verifica si un resource existe en la lista o no
  186. *
  187. * @param string $resourceName
  188. * @return boolean
  189. */
  190. public function isResource($resourceName){
  191. if(!$this->_modelResourcesName){
  192. //No se ha definido el modelo que administra los Resources
  193. $message = CoreLocale::getErrorMessage(-25);
  194. throw new AclException($message, -25);
  195. }
  196. $resource = EntityManager::getEntityInstance($this->_modelResourcesName());
  197. return $resource->count("name = '$resourceName'") > 0 ? true : false;
  198. }
  199. /**
  200. * Agrega un recurso a la Lista ACL
  201. *
  202. * Resource_name puede ser el nombre de un objeto concreo, por ejemplo
  203. * consulta, buscar, insertar, valida etc ó una lista de ellos
  204. *
  205. * Ej:
  206. * <code>
  207. * //Agregar un resource a la lista:
  208. * $acl->addResource(new AclResource('clientes'), 'consulta');
  209. *
  210. * //Agregar Varios resources a la lista:
  211. * $acl->addResource(new AclResource('clientes'), array('consulta', 'buscar', 'insertar'));
  212. * </code>
  213. *
  214. * @param AclResource $resourceObject
  215. * @param array $operationsList
  216. * @return boolean
  217. */
  218. public function addResource(AclResource $resourceObject, $operationsList=''){
  219. if($operationsList==''){
  220. return $this->_createResource($resourceObject);
  221. } else {
  222. return $this->addResourceAccess($resourceObject, $operationsList);
  223. }
  224. }
  225. /**
  226. * Crea un recurso en el Modelo definido
  227. *
  228. * @param AclResource $resourceObject
  229. */
  230. private function _createResource(AclResource $resourceObject){
  231. if(!$this->_modelResourcesName){
  232. //No se ha definido el modelo que administra los Resources
  233. $message = CoreLocale::getErrorMessage(-25);
  234. throw new AclException($message, -25);
  235. }
  236. $resource = EntityManager::getEntityInstance($this->_modelResourcesName);
  237. if($this->_transaction){
  238. $resource->setTransaction($this->_transaction);
  239. }
  240. if(method_exists($resource, "setName")){
  241. $resource->setName($resourceObject->getName());
  242. } else {
  243. $resource->name = $resourceObject->getName();
  244. }
  245. if($resource->hasField('description')){
  246. if(method_exists($resource, "setDescription")){
  247. $resource->setDescription($resourceObject->getDescription());
  248. } else {
  249. $resource->description = $resourceObject->getDescription();
  250. }
  251. }
  252. if(!$this->isResource($resourceObject->getName())){
  253. if($resource->save()==false){
  254. //No se pudo crear el recurso
  255. foreach($resource->getMessages() as $message){
  256. $message = CoreLocale::getErrorMessage(-26, $message->getMessage());
  257. throw new AclException($message, -26);
  258. }
  259. }
  260. } else {
  261. //El resource ya se ha creado en la lista de acceso
  262. $message = CoreLocale::getErrorMessage(-27);
  263. throw new AclException($message, -27);
  264. }
  265. return true;
  266. }
  267. /**
  268. * Agrega accesos a un Resource
  269. *
  270. * @param AclResource $resourceObject
  271. * @param array $operationsList
  272. */
  273. public function addResourceAccess($resourceObject, $operationsList){
  274. if(!$this->_modelAccessResourcesName){
  275. //No se ha definido el modelo que relaciona los Resources con sus operaciones
  276. $message = CoreLocale::getErrorMessage(-28);
  277. throw new AclException($message, -28);
  278. }
  279. $createdResource = false;
  280. $this->_transaction = TransactionManager::getUserTransaction();
  281. if(!is_array($operationsList)){
  282. $operationsList = array($operationsList);
  283. }
  284. $numberList = count($operationsList);
  285. for($i=0;$i<$numberList;++$i){
  286. if(is_string($operationsList[$i])==false){
  287. $this->_transaction->rollback();
  288. $this->_transaction = null;
  289. //Nombre de operación invalido
  290. $message = CoreLocale::getErrorMessage(-29, $operationsList[$i]);
  291. throw new AclException($message, -29);
  292. }
  293. if($createdResource==false){
  294. if(!$this->isResource($resourceObject->getName())){
  295. $this->_createResource($resourceObject);
  296. } else {
  297. }
  298. $createdResource = true;
  299. }
  300. $accessResources = EntityManager::getEntityInstance($this->_modelAccessResourcesName);
  301. if(method_exists($accessResources, "setResource")){
  302. $accessResources->setResource($resourceObject->getName());
  303. } else {
  304. $accessResources->resource = $resourceObject->getName();
  305. }
  306. if(method_exists($accessResources, "setAction")){
  307. $accessResources->setAction($operationsList[$i]);
  308. } else {
  309. $accessResources->action = $operationsList[$i];
  310. }
  311. if($accessResources->save()==false){
  312. foreach($accessResources->getMessages() as $message){
  313. $this->_transaction->rollback();
  314. $this->_transaction = null;
  315. throw new AclException($accessResources->getMessage());
  316. }
  317. }
  318. }
  319. $this->_transaction->commit();
  320. $this->_transaction = null;
  321. return true;
  322. }
  323. /**
  324. * Elimina un acceso del resorce
  325. *
  326. * @param string $resource
  327. * @param mixed $accessList
  328. */
  329. public function dropResourceAccess($resource, $accessList){
  330. }
  331. /**
  332. * Agrega un acceso de la lista de resources a un rol
  333. *
  334. * Utilizar '*' como comodín
  335. *
  336. * Ej:
  337. * <code>
  338. * //Acceso para invitados a consultar en clientes
  339. * $acl->allow('invitados', 'clientes', 'consulta');
  340. *
  341. * //Acceso para invitados a consultar e insertar en clientes
  342. * $acl->allow('invitados', 'clientes', array('consulta', 'insertar'));
  343. *
  344. * //Acceso para cualquiera a visualizar en productos
  345. * $acl->allow('*', 'productos', 'visualiza');
  346. *
  347. * //Acceso para cualquiera a visualizar en cualquier resource
  348. * $acl->allow('*', '*', 'visualiza');
  349. * </code>
  350. *
  351. * @param string $role
  352. * @param string $resource
  353. * @param mixed $access
  354. * @return boolean
  355. */
  356. public function allow($role, $resource, $access){
  357. $model = EntityManager::getEntityInstance($this->modelName());
  358. $conditions = "role='$role' AND resource='$resource' AND action = '$access'";
  359. $access = $model->findFirst($conditions);
  360. if(!$access){
  361. if(method_exists($access, "setRole")){
  362. $access->setRole($role);
  363. } else {
  364. $access->role = $role;
  365. }
  366. if(method_exists($access, "setResource")){
  367. $access->setResource($resource);
  368. } else {
  369. $access->resource = $resource;
  370. }
  371. if(method_exists($access, "setAction")){
  372. $access->setAction($action);
  373. } else {
  374. $access->action = $action;
  375. }
  376. }
  377. $access->allow = 'Y';
  378. if($access->save()==false){
  379. //No se pudo guardar el acceso
  380. foreach($access->getMessages() as $message){
  381. $message = CoreLocale::getErrorMessage(-30, $message->getMessage());
  382. throw new AclException($message, -30);
  383. }
  384. }
  385. return true;
  386. }
  387. /**
  388. * Denegar un acceso de la lista de resources a un rol
  389. *
  390. * Utilizar '*' como comod?n
  391. *
  392. * Ej:
  393. * <code>
  394. * //Denega acceso para invitados a consultar en clientes
  395. * $acl->deny('invitados', 'clientes', 'consulta');
  396. *
  397. * //Denega acceso para invitados a consultar e insertar en clientes
  398. * $acl->deny('invitados', 'clientes', array('consulta', 'insertar'));
  399. *
  400. * //Denega acceso para cualquiera a visualizar en productos
  401. * $acl->deny('*', 'productos', 'visualiza');
  402. *
  403. * //Denega acceso para cualquiera a visualizar en cualquier resource
  404. * $acl->deny('*', '*', 'visualiza');
  405. * </code>
  406. *
  407. * @param string $role
  408. * @param string $resource
  409. * @param mixed $access
  410. * @return boolean
  411. */
  412. public function deny($role, $resource, $access){
  413. $model = EntityManager::getEntityInstance($this->modelName);
  414. $conditions = "role='$role' AND resource='$resource' AND action = '$access'";
  415. $access = $model->findFirst($conditions);
  416. if(!$access){
  417. if(method_exists($access, "setRole")){
  418. $access->setRole($role);
  419. } else {
  420. $access->role = $role;
  421. }
  422. if(method_exists($access, "setResource")){
  423. $access->setResource($resource);
  424. } else {
  425. $access->resource = $resource;
  426. }
  427. if(method_exists($access, "setAction")){
  428. $access->setAction($action);
  429. } else {
  430. $access->action = $action;
  431. }
  432. }
  433. $access->allow = 'N';
  434. if($access->save()==false){
  435. //No se pudo guardar el acceso
  436. foreach($access->getMessages() as $message){
  437. $message = CoreLocale::getErrorMessage(-30, $message->getMessage());
  438. throw new AclException($message, -30);
  439. }
  440. }
  441. return true;
  442. }
  443. /**
  444. * Devuelve true si un $role, tiene acceso en un resource
  445. *
  446. * <code>
  447. * //Andres tiene acceso a insertar en el resource productos
  448. * $acl->isAllowed('andres', 'productos', 'insertar');
  449. *
  450. * //Invitado tiene acceso a editar en cualquier resource?
  451. * $acl->isAllowed('invitado', '*', 'editar');
  452. *
  453. * //Invitado tiene acceso a editar en cualquier resource?
  454. * $acl->isAllowed('invitado', '*', 'editar');
  455. * </code>
  456. *
  457. * @param string $role
  458. * @param string $resource
  459. * @param mixed $accessList
  460. * @return boolean
  461. */
  462. public function isAllowed($role, $resource, $accessList){
  463. $model = EntityManager::getEntityInstance($this->_modelName);
  464. $conditions = "role='$role' AND resource='*' AND action = '*'";
  465. $access = $model->findFirst($conditions);
  466. if($access){
  467. if($access->getAllow()=='N'){
  468. return false;
  469. }
  470. }
  471. $conditions = "role='$role' AND resource='$resource' AND action = '*'";
  472. $access = $model->findFirst($conditions);
  473. if($access){
  474. if($access->getAllow()=='N'){
  475. return false;
  476. }
  477. }
  478. $conditions = "resource='$resource' AND role='$role' AND action = '$accessList' AND allow='N'";
  479. $deny = $model->count($conditions);
  480. if($deny){
  481. return false;
  482. }
  483. return true;
  484. }
  485. }