PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/acl_loader.php

https://github.com/jplante815/meican
PHP | 380 lines | 241 code | 69 blank | 70 comment | 63 complexity | bc34475c444f87e89dd5e7b9b43685c4 MD5 | raw file
  1. <?php
  2. include_once 'libs/Model/tree_model.php';
  3. include_once 'libs/auth.php';
  4. include_once 'apps/aaa/models/aros.php';
  5. include_once 'apps/aaa/models/acos.php';
  6. include_once 'apps/aaa/models/aros_acos.php';
  7. include_once 'libs/common.php';
  8. class AclLoader extends TreeModel {
  9. public $model;
  10. public $acl;
  11. private $perTyArray = array('read', 'create', 'update', 'delete');
  12. public function AclLoader() {
  13. $this->load();
  14. }
  15. public function load() {
  16. //fazer verificação da necessidade do reload
  17. $acl_ses = Common::getSessionVariable('acl');
  18. $last_update_server = Common::getLastUpdate();
  19. $last_update_client = Common::getSessionVariable('last_update');
  20. if ($last_update_server && $last_update_client) {
  21. //debug('last udpate server',$last_update_server);
  22. //debug('last udpate client',$last_update_client);
  23. if ($last_update_server >= $last_update_client)
  24. $reload = TRUE;
  25. else
  26. $reload = FALSE;
  27. } else
  28. $reload = TRUE;
  29. if (!$acl_ses || $reload) {
  30. $this->acl = $this->reloadACL();
  31. Common::setSessionVariable('acl', $this->acl);
  32. //debug("acl tree", $this->acl);
  33. }
  34. else
  35. $this->acl = $acl_ses;
  36. }
  37. public function reloadACL($options = array()) {
  38. Log::write('debug', 'Reloading ACL...');
  39. $debugLevel = Configure::read('debug');
  40. Configure::write('debug', 0);
  41. $time = time();
  42. //procura pelos aro_id do user (pode ser mais de um)
  43. $aro = new aros();
  44. $aro->obj_id = AuthSystem::getUserId();
  45. $aro->model = 'user_info';
  46. $result = $aro->fetch(FALSE);
  47. //array com os aros já analisados
  48. $old = array();
  49. $listaros = array();
  50. //preenche array listaros com os aros que devem ser analisados (todos possuem mesma prioridade)
  51. foreach ($result as $r) {
  52. $listaros[] = $r->aro_id;
  53. }
  54. //array listaros possui nodos de mesma prioridade
  55. while (!empty($listaros)) {
  56. $parentlist = array();
  57. //preenche array parentList possui os nodos pai da listaros
  58. foreach ($listaros as $la) {
  59. $aro = new aros();
  60. $aro->aro_id = $la;
  61. $result = $aro->fetch(FALSE);
  62. if ($result[0]->parent_id) {
  63. $parentlist[] = $result[0]->parent_id;
  64. }
  65. }
  66. //listaros é a lista de aro_id que serão checados na tabela aros_acos, todos possuem mesma prioridade
  67. $old = $this->analisaPrioridadeIgual($listaros, $old);
  68. //passa para listaros os pais e assim sucessivamente até chegar a raiz
  69. if (!empty($parentlist)) {
  70. $listaros = $parentlist;
  71. } else
  72. $listaros = array();
  73. }
  74. //passa do vetor old para um vetor intermediario para ser passado as variaveis de sessao
  75. $acl = new stdClass();
  76. foreach ($this->perTyArray as $perTy) {
  77. ${$perTy} = array_keys($old[$perTy], 'allow');
  78. $acl->{$perTy} = ${$perTy};
  79. }
  80. Common::setSessionVariable('last_update', $time);
  81. Configure::write('debug', $debugLevel);
  82. return $acl;
  83. }
  84. /**
  85. *
  86. * @param <array Aros> $listaros aros de mesma prioridade
  87. * @param <array[perTy][aco_id]> $old array multidimensional de string ('deny','allow')
  88. * @return <array> novo array old com as permissões de listaros atualizadas
  89. */
  90. function analisaPrioridadeIgual($listaros, $old) {
  91. Log::write('acl_debug', "analise prioridade igual aros: " . print_r($listaros, true));
  92. $new = array();
  93. //procura na tabela aros_acos os respectivos aros
  94. foreach ($listaros as $a) {
  95. $aros_acos = new aros_acos();
  96. $aros_acos->aro_id = $a;
  97. $lines_aros_acos = $aros_acos->fetch(FALSE);
  98. unset($restrModel);
  99. //analisa
  100. foreach ($this->perTyArray as $perTy) {
  101. unset($toSearch);
  102. $level = 0;
  103. Log::write('acl_debug', "***************** perty " . print_r($perTy, true));
  104. //avalia privilegios de mesmo nível, constroi um array new com as permissoes
  105. foreach ($lines_aros_acos as $perm) {
  106. Log::write('acl_debug', "analisando perm " . print_r($perm->perm_id, true));
  107. //ira restringir quais acos serao afetados, afetando apenas aqueles do model estipulado restrModel
  108. $aco_id = $perm->aco_id;
  109. if ($perm->model) {
  110. $aco_t = new Acos();
  111. $aco_t->aco_id = $aco_id;
  112. $aco_t->model = $perm->model;
  113. //se encontrar tal nodo, é do modelo estipulado, vai atribuir permissão
  114. if ($result_aco = $aco_t->fetch(FALSE)) {
  115. if (!array_key_exists($aco_id, $new[$perTy])) {
  116. if ($perm->{$perTy} == 'deny')
  117. $new[$perTy][$aco_id]->value = 'deny';
  118. elseif ($perm->{$perTy} == 'allow')
  119. $new[$perTy][$aco_id]->value = 'allow';
  120. $new[$perTy][$aco_id]->model = $perm->model;
  121. } else { //caso esse aco_id já tenha sido analisado nessa interação
  122. //se a permissao seja deny e aquela que estava era allow
  123. if ($perm->{$perTy} == 'deny' && $new[$perTy][$aco_id]->value == 'allow')
  124. //subscreve a permissao allow e deixa a deny (já que aqui possuem a mesma prioridade)
  125. $new[$perTy][$aco_id]->value = 'deny';
  126. }
  127. } else { //model nao conferiu, ira procurar descendo pela arvore, mas nao adiciona no vetor new
  128. //tosearch precisa ser em ordem a avaliacao
  129. if (isset($toSearch[$perTy][$level][$aco_id])) {
  130. $level++;
  131. Log::write('acl_debug', "vai incrementar a porquera" .print_r($level, true));
  132. }
  133. $toSearch[$perTy][$level][$aco_id]->value = $perm->{$perTy};
  134. $toSearch[$perTy][$level][$aco_id]->model = $perm->model;
  135. Log::write('acl_debug', "models diferentes ira analisar filhos" . print_r($toSearch, true));
  136. }
  137. } else { //nao tem model definido
  138. if (!array_key_exists($aco_id, $new[$perTy])) {
  139. if ($perm->{$perTy} == 'deny')
  140. $new[$perTy][$aco_id]->value = 'deny';
  141. elseif ($perm->{$perTy} == 'allow')
  142. $new[$perTy][$aco_id]->value = 'allow';
  143. } else { //caso esse aco_id já tenha sido analisado nessa interação
  144. //se a permissao seja deny e aquela que estava era allow
  145. if ($perm->{$perTy} == 'deny' && $new[$perTy][$aco_id]->value == 'allow')
  146. //subscreve a permissao allow e deixa a deny (já que aqui possuem a mesma prioridade)
  147. $new[$perTy][$aco_id]->value = 'deny';
  148. }
  149. }
  150. } //foreach lines_aros_acos
  151. //debug("array new ",$new);
  152. //colapsar array velho old com novo new, só vai atribuir se o novo nao estiver no velho
  153. if (array_key_exists($perTy, $new) && is_array($new[$perTy])) {
  154. foreach ($new[$perTy] as $aco_id => $perm) {
  155. //caso o aco_id não exista no array velho
  156. if (!array_key_exists($aco_id, $old[$perTy])) {
  157. Log::write('acl_debug', "vai atribuir ao aco " .print_r($aco_id, true));
  158. Log::write('acl_debug', "permissao " .print_r($perm->value, true));
  159. $old[$perTy][$aco_id] = $perm->value;
  160. if (isset($toSearch[$perTy][$level][$aco_id])) {
  161. $level++;
  162. Log::write('acl_debug', "vai incrementar a porquera" .print_r($level, true));
  163. }
  164. $toSearch[$perTy][$level][$aco_id]->value = $perm->value;
  165. //array com os nodos que forma atribuídos permissoes nessa interação
  166. //e a permissao que deve ser atribuída a tais nodos
  167. if (isset($perm->model))
  168. $toSearch[$perTy][$level][$aco_id]->model = $perm->model;
  169. }
  170. }
  171. }
  172. $level++;
  173. //vai atribuir aos proximos nodos filhos
  174. for ($ind = 0; $ind <= $level; $ind++) {
  175. unset($acos);
  176. $new = array();
  177. $children = array();
  178. if (isset($toSearch) && array_key_exists($perTy, $toSearch) && is_array($toSearch[$perTy][$ind])) {
  179. //retorna os aco_id dos nodos a serem analisados
  180. Log::write('acl_debug', "tosearch" . print_r($toSearch, true));
  181. $children = $this->getacosmesmonivel($toSearch[$perTy][$ind]);
  182. Log::write('acl_debug', "children" . print_r($children, true));
  183. }
  184. if (!$children)
  185. break;
  186. foreach ($children as $c) {
  187. Log::write('acl_debug', "analisando filhos do aco_id " . print_r($c->parent_id, true));
  188. if (!array_key_exists($c->aco_id, $new[$perTy])) {
  189. if ((!$toSearch[$perTy][$ind][$c->parent_id]->model) || ($toSearch[$perTy][$ind][$c->parent_id]->model == $c->model)) {
  190. if ($toSearch[$perTy][$ind][$c->parent_id]->value == 'deny')
  191. $new[$perTy][$c->aco_id]->value = 'deny';
  192. elseif ($toSearch[$perTy][$ind][$c->parent_id]->value == 'allow')
  193. $new[$perTy][$c->aco_id]->value = 'allow';
  194. }
  195. $toSearch[$perTy][$level][$c->aco_id]->value = $toSearch[$perTy][$ind][$c->parent_id]->value;
  196. if (isset($toSearch[$perTy][$ind][$c->parent_id]->model))
  197. $toSearch[$perTy][$level][$c->aco_id]->model = $toSearch[$perTy][$ind][$c->parent_id]->model;
  198. } else {
  199. if ($toSearch[$perTy][$ind][$c->parent_id]->value == 'deny' && $new[$perTy][$c->aco_id]->value == 'allow') {
  200. $new[$perTy][$c->aco_id]->value = 'deny';
  201. }
  202. }
  203. }
  204. foreach ($new[$perTy] as $aco_id => $perm) {
  205. if (!array_key_exists($aco_id, $old[$perTy])) {
  206. $old[$perTy][$aco_id] = $perm->value;
  207. Log::write('acl_debug', "vai atribuir ao aco " . print_r($aco_id, true));
  208. Log::write('acl_debug', "permissao " . print_r($perm->value, true));
  209. // $toSearch[$perTy][$level][$aco_id]->value= $perm->value;
  210. //
  211. // if ($toSearch[$perTy][$level][$c->parent_id]->model)
  212. // $toSearch[$perTy][$level][$aco_id]->model = $toSearch[$perTy][$level][$c->parent_id]->model;
  213. //limpa vetor do level já analisado
  214. }
  215. }
  216. unset($toSearch[$perTy][$ind]);
  217. $level++;
  218. } //for level
  219. } //foreach perty
  220. } //foreach listaros
  221. return $old;
  222. }
  223. /**
  224. * Retorna os aco_id imediatamente abaixo do aco em questão
  225. * @param <array int> $parentlist $toSearch[perTy][aco_id] dos nodos que devem ser procurados/cascateados
  226. * @return <array> StdObject aco_id e parent_id
  227. */
  228. function getacosmesmonivel($parentlist) {
  229. $new = array();
  230. $children = array();
  231. $ind = 0;
  232. foreach ($parentlist as $aco_id => $val) {
  233. $aco = new Acos();
  234. $aco->aco_id = $aco_id;
  235. $result = $aco->getImmediateNodes();
  236. foreach ($result as $val) {
  237. $children[$ind]->aco_id = $val->aco_id;
  238. $children[$ind]->model = $val->model;
  239. $children[$ind]->parent_id = $val->parent_id;
  240. $ind++;
  241. }
  242. }
  243. if ($ind > 0)
  244. return $children;
  245. else
  246. return FALSE;
  247. }
  248. function getAllowedPKey($right, $model) {
  249. //vetor de acos do modelo que o usuario tem acesso
  250. $acos = $this->acl->{$right};
  251. if ($acos) {
  252. $strAcos = implode(',', $acos);
  253. $acos = new acos();
  254. //retorna os objetos (obj_id) que o usuário possui acesso
  255. $result = $acos->getAcoGroupByModel($strAcos, $model);
  256. //array com os ids do modelo que o usuário possui acesso
  257. $objs = Common::arrayExtractAttr($result, "obj_id");
  258. //$strObj = implode(',', $obj);
  259. return $objs;
  260. } else
  261. return FALSE;
  262. }
  263. public function checkACL($right, $model, $id = NULL) {
  264. $acos = $this->acl->{$right};
  265. //debug('acos', $acos);
  266. if ($acos) {
  267. // primeiro pesquisa se possui acesso a um determinado modelo
  268. // por exemplo, testa se o modelo recebido como parâmetro está na lista de acos lida das rights
  269. // se possuir pelo menos uma linha no retorno, é porque possui permissão
  270. // se passou um ID como parâmetro, tem que testar se o ID está na lista dos 'objs' retornados de 'getAllowedPKey'
  271. $aco = new Acos();
  272. $strAcos = implode(',', $acos);
  273. if ($aco->hasAnyAcoOfModel($strAcos, $model)) {
  274. if ($id) {
  275. if ($restr = $this->getAllowedPKey($right, $model)) {
  276. //se tem o id especificado, deve estar especificado
  277. if (array_search($id, $restr) !== FALSE)
  278. return TRUE;
  279. }
  280. } else
  281. return TRUE;
  282. }
  283. //} else { //possui acesso a algum nodo!!! nao precisa necessariamente ser o VOID
  284. //pode ser qualquer UM. função getvoid parece inútil
  285. //
  286. //nao especificou id, procura pelo void
  287. //entes voids: obj_id = NULL, a presença de um ente void
  288. //em determinado modelo discrimina os direitos default do usuário
  289. //sobre aquele modelo (sem especificar o id)
  290. //$aco = new Acos();
  291. //$strAcos = implode(',', $acos);
  292. //$void = $aco->getVoid($strAcos, $model);
  293. //if ($void) //possui acesso ao ente void, logo possui right sobre aquele model
  294. //return TRUE;
  295. //}
  296. }
  297. return FALSE;
  298. }
  299. // Guarda uma instância da classe
  300. private static $instance;
  301. public static function getInstance() {
  302. if (!isset(self::$instance)) {
  303. $c = __CLASS__;
  304. self::$instance = new $c;
  305. }
  306. self::$instance->load();
  307. return self::$instance;
  308. }
  309. }
  310. // da classe
  311. ?>