PageRenderTime 58ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/common/helpers/AuthHelper.php

https://gitlab.com/joepa37/ierschool.dev
PHP | 315 lines | 207 code | 40 blank | 68 comment | 27 complexity | 37002b9f49c8057afe0c4a0c0c5e593d MD5 | raw file
  1. <?php
  2. namespace common\helpers;
  3. use common\models\AbstractItem;
  4. use common\models\Permission;
  5. use common\models\Role;
  6. use common\models\Route;
  7. use Yii;
  8. use yii\base\InvalidParamException;
  9. use yii\helpers\Inflector;
  10. use yii\helpers\Url;
  11. use yii\rbac\DbManager;
  12. class AuthHelper
  13. {
  14. const SESSION_PREFIX_LAST_UPDATE = '__auth_last_update';
  15. const SESSION_PREFIX_ROLES = '__userRoles';
  16. const SESSION_PREFIX_PERMISSIONS = '__userPermissions';
  17. const SESSION_PREFIX_ROUTES = '__userRoutes';
  18. /**
  19. * Gather all user permissions and roles and store them in the session
  20. *
  21. * @param UserIdentity $identity
  22. */
  23. public static function updatePermissions($identity)
  24. {
  25. $session = Yii::$app->session;
  26. // Clear data first in case we want to refresh permissions
  27. $session->remove(self::SESSION_PREFIX_ROLES);
  28. $session->remove(self::SESSION_PREFIX_PERMISSIONS);
  29. $session->remove(self::SESSION_PREFIX_ROUTES);
  30. // Set permissions last mod time
  31. $session->set(self::SESSION_PREFIX_LAST_UPDATE,
  32. filemtime(self::getPermissionsLastModFile()));
  33. // Save roles, permissions and routes in session
  34. $session->set(self::SESSION_PREFIX_ROLES,
  35. array_keys(Role::getUserRoles($identity->id)));
  36. $session->set(self::SESSION_PREFIX_PERMISSIONS,
  37. array_keys(Permission::getUserPermissions($identity->id)));
  38. $session->set(self::SESSION_PREFIX_ROUTES,
  39. Route::getUserRoutes($identity->id));
  40. }
  41. /**
  42. * Checks if permissions has been changed somehow, and refresh data in session if necessary
  43. */
  44. public static function ensurePermissionsUpToDate()
  45. {
  46. if (!Yii::$app->user->isGuest) {
  47. if (Yii::$app->session->get(self::SESSION_PREFIX_LAST_UPDATE) != filemtime(self::getPermissionsLastModFile())) {
  48. static::updatePermissions(Yii::$app->user->identity);
  49. }
  50. }
  51. }
  52. /**
  53. * Get path to file that store time of the last auth changes
  54. *
  55. * @return string
  56. */
  57. public static function getPermissionsLastModFile()
  58. {
  59. $file = Yii::$app->runtimePath . '/__permissions_last_mod.txt';
  60. if (!is_file($file)) {
  61. file_put_contents($file, '');
  62. chmod($file, 0777);
  63. }
  64. return $file;
  65. }
  66. /**
  67. * Change modification time of permissions last mod file
  68. */
  69. public static function invalidatePermissions()
  70. {
  71. touch(static::getPermissionsLastModFile());
  72. }
  73. /**
  74. * Return route without baseUrl and start it with slash
  75. *
  76. * @param string|array $route
  77. *
  78. * @return string
  79. */
  80. public static function unifyRoute($route)
  81. {
  82. // If its like Html::a('Create', ['create'])
  83. if (is_array($route) AND strpos($route[0], '/') === false) {
  84. $route = Url::toRoute($route);
  85. }
  86. // URL starts with http
  87. if (!is_array($route) && (substr($route, 0, 4) === "http")) {
  88. return $route;
  89. }
  90. if (Yii::$app->getUrlManager()->showScriptName === true) {
  91. $baseUrl = Yii::$app->getRequest()->scriptUrl;
  92. } else {
  93. $baseUrl = Yii::$app->getRequest()->baseUrl;
  94. }
  95. // Check if $route has been passed as array or as string with params (or without)
  96. if (!is_array($route)) {
  97. $route = explode('?', $route);
  98. }
  99. $routeAsString = $route[0];
  100. // If it's not clean url like localhost/folder/index.php/bla-bla then remove
  101. // baseUrl and leave only relative path 'bla-bla'
  102. if ($baseUrl) {
  103. if (strpos($routeAsString, $baseUrl) === 0) {
  104. $routeAsString = substr_replace($routeAsString, '', 0,
  105. strlen($baseUrl));
  106. }
  107. }
  108. $languagePrefix = '/' . Yii::$app->language . '/';
  109. // Remove language prefix
  110. if (strpos($routeAsString, $languagePrefix) === 0) {
  111. $routeAsString = substr_replace($routeAsString, '', 0,
  112. strlen($languagePrefix));
  113. }
  114. return '/' . ltrim($routeAsString, '/');
  115. }
  116. /**
  117. * Get child routes, permissions or roles
  118. *
  119. * @param string $itemName
  120. * @param integer $childType
  121. *
  122. * @return array
  123. */
  124. public static function getChildrenByType($itemName, $childType)
  125. {
  126. $children = (new DbManager())->getChildren($itemName);
  127. $result = [];
  128. foreach ($children as $id => $item) {
  129. if ($item->type == $childType) {
  130. $result[$id] = $item;
  131. }
  132. }
  133. return $result;
  134. }
  135. /**
  136. * Select items that has "/" in permissions
  137. *
  138. * @param array $allPermissions
  139. *
  140. * @return object
  141. */
  142. public static function separateRoutesAndPermissions($allPermissions)
  143. {
  144. $arrayOfPermissions = $allPermissions;
  145. $routes = [];
  146. $permissions = [];
  147. foreach ($arrayOfPermissions as $id => $item) {
  148. if ($item->type == AbstractItem::TYPE_ROUTE) {
  149. $routes[$id] = $item;
  150. } else {
  151. $permissions[$id] = $item;
  152. }
  153. }
  154. return (object)compact('routes', 'permissions');
  155. }
  156. /**
  157. * @return array
  158. */
  159. public static function getAllModules()
  160. {
  161. $result = [];
  162. $currentEnvModules = \Yii::$app->getModules();
  163. foreach ($currentEnvModules as $moduleId => $uselessStuff) {
  164. $result[$moduleId] = \Yii::$app->getModule($moduleId);
  165. }
  166. return $result;
  167. }
  168. /**
  169. * @return array
  170. */
  171. public static function getRoutes()
  172. {
  173. $result = [];
  174. self::getRouteRecursive(Yii::$app, $result);
  175. return array_reverse(array_combine($result, $result));
  176. }
  177. /**
  178. * @param \yii\base\Module $module
  179. * @param array $result
  180. */
  181. private static function getRouteRecursive($module, &$result)
  182. {
  183. foreach ($module->getModules() as $id => $child)
  184. {
  185. if ( ($child = $module->getModule($id)) !== null )
  186. {
  187. self::getRouteRecursive($child, $result);
  188. }
  189. }
  190. /* @var $controller \yii\base\Controller */
  191. foreach ($module->controllerMap as $id => $value)
  192. {
  193. $controller = Yii::createObject($value, [
  194. $id,
  195. $module
  196. ]);
  197. self::getActionRoutes($controller, $result);
  198. $result[] = '/' . $controller->uniqueId . '/*';
  199. }
  200. $namespace = trim($module->controllerNamespace, '\\') . '\\';
  201. self::getControllerRoutes($module, $namespace, '', $result);
  202. if ( $module->uniqueId )
  203. {
  204. $result[] = '/'. $module->uniqueId . '/*';
  205. }
  206. else
  207. {
  208. $result[] = $module->uniqueId . '/*';
  209. }
  210. }
  211. /**
  212. * @param \yii\base\Controller $controller
  213. * @param Array $result all controller action.
  214. */
  215. private static function getActionRoutes($controller, &$result)
  216. {
  217. $prefix = '/' . $controller->uniqueId . '/';
  218. foreach ($controller->actions() as $id => $value) {
  219. $result[] = $prefix . $id;
  220. }
  221. $class = new \ReflectionClass($controller);
  222. foreach ($class->getMethods() as $method) {
  223. $name = $method->getName();
  224. if ($method->isPublic() && !$method->isStatic() && strpos($name,
  225. 'action') === 0 && $name !== 'actions'
  226. ) {
  227. $result[] = $prefix . Inflector::camel2id(substr($name, 6));
  228. }
  229. }
  230. }
  231. /**
  232. * @param \yii\base\Module $module
  233. * @param $namespace
  234. * @param $prefix
  235. * @param $result
  236. */
  237. private static function getControllerRoutes($module, $namespace, $prefix, &$result)
  238. {
  239. try
  240. {
  241. $path = Yii::getAlias('@' . str_replace('\\', '/', $namespace));
  242. }
  243. catch (InvalidParamException $e)
  244. {
  245. $path = $module->getBasePath() . '/controllers';
  246. }
  247. if ( is_dir($path) )
  248. {
  249. foreach (scandir($path) as $file)
  250. {
  251. if ( strpos($file, '.') === 0 )
  252. {
  253. continue;
  254. }
  255. if ( is_dir($path . '/' . $file) )
  256. {
  257. self::getControllerRoutes($module, $namespace . $file . '\\', $prefix . $file . '/', $result);
  258. }
  259. elseif ( strcmp(substr($file, -14), 'Controller.php') === 0 )
  260. {
  261. $id = Inflector::camel2id(substr(basename($file), 0, -14), '-', true);
  262. $className = $namespace . Inflector::id2camel($id) . 'Controller';
  263. if ( strpos($className, '-') === false && class_exists($className) && is_subclass_of($className, 'yii\base\Controller') )
  264. {
  265. $controller = new $className($prefix . $id, $module);
  266. self::getActionRoutes($controller, $result);
  267. $result[] = '/' . $controller->uniqueId . '/*';
  268. }
  269. }
  270. }
  271. }
  272. }
  273. }