PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/classes/Server/UserGroups.php

http://github.com/phpmyadmin/phpmyadmin
PHP | 357 lines | 263 code | 39 blank | 55 comment | 23 complexity | b1330385be4b382d33ddb95e0358f063 MD5 | raw file
Possible License(s): GPL-2.0, MIT, LGPL-3.0
  1. <?php
  2. /**
  3. * set of functions for user group handling
  4. */
  5. declare(strict_types=1);
  6. namespace PhpMyAdmin\Server;
  7. use PhpMyAdmin\Html\Generator;
  8. use PhpMyAdmin\Relation;
  9. use PhpMyAdmin\Template;
  10. use PhpMyAdmin\Url;
  11. use PhpMyAdmin\Util;
  12. use function __;
  13. use function htmlspecialchars;
  14. use function implode;
  15. use function in_array;
  16. use function mb_substr;
  17. use function substr;
  18. /**
  19. * PhpMyAdmin\Server\UserGroups class
  20. */
  21. class UserGroups
  22. {
  23. /**
  24. * Return HTML to list the users belonging to a given user group
  25. *
  26. * @param string $userGroup user group name
  27. *
  28. * @return string HTML to list the users belonging to a given user group
  29. */
  30. public static function getHtmlForListingUsersofAGroup(string $userGroup): string
  31. {
  32. global $dbi;
  33. $users = [];
  34. $numRows = 0;
  35. $relation = new Relation($dbi);
  36. $userGroupSpecialChars = htmlspecialchars($userGroup);
  37. $cfgRelation = $relation->getRelationsParam();
  38. $usersTable = Util::backquote($cfgRelation['db'])
  39. . '.' . Util::backquote($cfgRelation['users']);
  40. $sql_query = 'SELECT `username` FROM ' . $usersTable
  41. . " WHERE `usergroup`='" . $dbi->escapeString($userGroup)
  42. . "'";
  43. $result = $relation->queryAsControlUser($sql_query, false);
  44. if ($result) {
  45. $numRows = $dbi->numRows($result);
  46. if ($numRows != 0) {
  47. $i = 0;
  48. while ($row = $dbi->fetchRow($result)) {
  49. $i++;
  50. $user = [];
  51. $user['count'] = $i;
  52. $user['user'] = $row[0];
  53. $users[] = $user;
  54. }
  55. }
  56. }
  57. $dbi->freeResult($result);
  58. $template = new Template();
  59. return $template->render('server/user_groups/user_listings', [
  60. 'user_group_special_chars' => $userGroupSpecialChars,
  61. 'num_rows' => $numRows,
  62. 'users' => $users,
  63. ]);
  64. }
  65. /**
  66. * Returns HTML for the 'user groups' table
  67. *
  68. * @return string HTML for the 'user groups' table
  69. */
  70. public static function getHtmlForUserGroupsTable(): string
  71. {
  72. global $dbi;
  73. $relation = new Relation($dbi);
  74. $cfgRelation = $relation->getRelationsParam();
  75. $groupTable = Util::backquote($cfgRelation['db'])
  76. . '.' . Util::backquote($cfgRelation['usergroups']);
  77. $sql_query = 'SELECT * FROM ' . $groupTable . ' ORDER BY `usergroup` ASC';
  78. $result = $relation->queryAsControlUser($sql_query, false);
  79. $numRows = $dbi->numRows($result);
  80. $userGroups = [];
  81. $userGroupsValues = [];
  82. $action = Url::getFromRoute('/server/privileges');
  83. $hidden_inputs = null;
  84. if ($result && $numRows) {
  85. $hidden_inputs = Url::getHiddenInputs();
  86. while ($row = $dbi->fetchAssoc($result)) {
  87. $groupName = $row['usergroup'];
  88. if (! isset($userGroups[$groupName])) {
  89. $userGroups[$groupName] = [];
  90. }
  91. $userGroups[$groupName][$row['tab']] = $row['allowed'];
  92. }
  93. foreach ($userGroups as $groupName => $tabs) {
  94. $userGroupVal = [];
  95. $userGroupVal['name'] = htmlspecialchars((string) $groupName);
  96. $userGroupVal['serverTab'] = self::getAllowedTabNames($tabs, 'server');
  97. $userGroupVal['dbTab'] = self::getAllowedTabNames($tabs, 'db');
  98. $userGroupVal['tableTab'] = self::getAllowedTabNames($tabs, 'table');
  99. $userGroupVal['userGroupUrl'] = Url::getFromRoute('/server/user-groups');
  100. $userGroupVal['viewUsersUrl'] = Url::getCommon(
  101. [
  102. 'viewUsers' => 1,
  103. 'userGroup' => $groupName,
  104. ],
  105. ''
  106. );
  107. $userGroupVal['viewUsersIcon'] = Generator::getIcon('b_usrlist', __('View users'));
  108. $userGroupVal['editUsersUrl'] = Url::getCommon(
  109. [
  110. 'editUserGroup' => 1,
  111. 'userGroup' => $groupName,
  112. ],
  113. ''
  114. );
  115. $userGroupVal['editUsersIcon'] = Generator::getIcon('b_edit', __('Edit'));
  116. $userGroupsValues[] = $userGroupVal;
  117. }
  118. }
  119. $addUserUrl = Url::getFromRoute('/server/user-groups', ['addUserGroup' => 1]);
  120. $addUserIcon = Generator::getIcon('b_usradd');
  121. $dbi->freeResult($result);
  122. $template = new Template();
  123. return $template->render('server/user_groups/user_groups', [
  124. 'action' => $action,
  125. 'hidden_inputs' => $hidden_inputs ?? '',
  126. 'result' => $result,
  127. 'has_rows' => $numRows,
  128. 'user_groups_values' => $userGroupsValues,
  129. 'add_user_url' => $addUserUrl,
  130. 'add_user_icon' => $addUserIcon,
  131. ]);
  132. }
  133. /**
  134. * Returns the list of allowed menu tab names
  135. * based on a data row from usergroup table.
  136. *
  137. * @param array $row row of usergroup table
  138. * @param string $level 'server', 'db' or 'table'
  139. *
  140. * @return string comma separated list of allowed menu tab names
  141. */
  142. public static function getAllowedTabNames(array $row, string $level): string
  143. {
  144. $tabNames = [];
  145. $tabs = Util::getMenuTabList($level);
  146. foreach ($tabs as $tab => $tabName) {
  147. if (isset($row[$level . '_' . $tab]) && $row[$level . '_' . $tab] !== 'Y') {
  148. continue;
  149. }
  150. $tabNames[] = $tabName;
  151. }
  152. return implode(', ', $tabNames);
  153. }
  154. /**
  155. * Deletes a user group
  156. *
  157. * @param string $userGroup user group name
  158. */
  159. public static function delete(string $userGroup): void
  160. {
  161. global $dbi;
  162. $relation = new Relation($dbi);
  163. $cfgRelation = $relation->getRelationsParam();
  164. $userTable = Util::backquote($cfgRelation['db'])
  165. . '.' . Util::backquote($cfgRelation['users']);
  166. $groupTable = Util::backquote($cfgRelation['db'])
  167. . '.' . Util::backquote($cfgRelation['usergroups']);
  168. $sql_query = 'DELETE FROM ' . $userTable
  169. . " WHERE `usergroup`='" . $dbi->escapeString($userGroup)
  170. . "'";
  171. $relation->queryAsControlUser($sql_query, true);
  172. $sql_query = 'DELETE FROM ' . $groupTable
  173. . " WHERE `usergroup`='" . $dbi->escapeString($userGroup)
  174. . "'";
  175. $relation->queryAsControlUser($sql_query, true);
  176. }
  177. /**
  178. * Returns HTML for add/edit user group dialog
  179. *
  180. * @param string $userGroup name of the user group in case of editing
  181. *
  182. * @return string HTML for add/edit user group dialog
  183. */
  184. public static function getHtmlToEditUserGroup(?string $userGroup = null): string
  185. {
  186. global $dbi;
  187. $relation = new Relation($dbi);
  188. $urlParams = [];
  189. $editUserGroupSpecialChars = '';
  190. if ($userGroup !== null) {
  191. $editUserGroupSpecialChars = htmlspecialchars($userGroup);
  192. }
  193. if ($userGroup !== null) {
  194. $urlParams['userGroup'] = $userGroup;
  195. $urlParams['editUserGroupSubmit'] = '1';
  196. } else {
  197. $urlParams['addUserGroupSubmit'] = '1';
  198. }
  199. $allowedTabs = [
  200. 'server' => [],
  201. 'db' => [],
  202. 'table' => [],
  203. ];
  204. if ($userGroup !== null) {
  205. $cfgRelation = $relation->getRelationsParam();
  206. $groupTable = Util::backquote($cfgRelation['db'])
  207. . '.' . Util::backquote($cfgRelation['usergroups']);
  208. $sql_query = 'SELECT * FROM ' . $groupTable
  209. . " WHERE `usergroup`='" . $dbi->escapeString($userGroup)
  210. . "'";
  211. $result = $relation->queryAsControlUser($sql_query, false);
  212. if ($result) {
  213. while ($row = $dbi->fetchAssoc($result)) {
  214. $key = $row['tab'];
  215. $value = $row['allowed'];
  216. if (substr($key, 0, 7) === 'server_' && $value === 'Y') {
  217. $allowedTabs['server'][] = mb_substr($key, 7);
  218. } elseif (substr($key, 0, 3) === 'db_' && $value === 'Y') {
  219. $allowedTabs['db'][] = mb_substr($key, 3);
  220. } elseif (substr($key, 0, 6) === 'table_' && $value === 'Y') {
  221. $allowedTabs['table'][] = mb_substr($key, 6);
  222. }
  223. }
  224. }
  225. $dbi->freeResult($result);
  226. }
  227. $tabList = self::getTabList(
  228. __('Server-level tabs'),
  229. 'server',
  230. $allowedTabs['server']
  231. );
  232. $tabList .= self::getTabList(
  233. __('Database-level tabs'),
  234. 'db',
  235. $allowedTabs['db']
  236. );
  237. $tabList .= self::getTabList(
  238. __('Table-level tabs'),
  239. 'table',
  240. $allowedTabs['table']
  241. );
  242. $template = new Template();
  243. return $template->render('server/user_groups/edit_user_groups', [
  244. 'user_group' => $userGroup,
  245. 'edit_user_group_special_chars' => $editUserGroupSpecialChars,
  246. 'user_group_url' => Url::getFromRoute('/server/user-groups'),
  247. 'hidden_inputs' => Url::getHiddenInputs($urlParams),
  248. 'tab_list' => $tabList,
  249. ]);
  250. }
  251. /**
  252. * Returns HTML for checkbox groups to choose
  253. * tabs of 'server', 'db' or 'table' levels.
  254. *
  255. * @param string $title title of the checkbox group
  256. * @param string $level 'server', 'db' or 'table'
  257. * @param array $selected array of selected allowed tabs
  258. *
  259. * @return string HTML for checkbox groups
  260. */
  261. public static function getTabList(string $title, string $level, array $selected): string
  262. {
  263. $tabs = Util::getMenuTabList($level);
  264. $tabDetails = [];
  265. foreach ($tabs as $tab => $tabName) {
  266. $tabDetail = [];
  267. $tabDetail['in_array'] = (in_array($tab, $selected) ? ' checked="checked"' : '');
  268. $tabDetail['tab'] = $tab;
  269. $tabDetail['tab_name'] = $tabName;
  270. $tabDetails[] = $tabDetail;
  271. }
  272. $template = new Template();
  273. return $template->render('server/user_groups/tab_list', [
  274. 'title' => $title,
  275. 'level' => $level,
  276. 'tab_details' => $tabDetails,
  277. ]);
  278. }
  279. /**
  280. * Add/update a user group with allowed menu tabs.
  281. *
  282. * @param string $userGroup user group name
  283. * @param bool $new whether this is a new user group
  284. */
  285. public static function edit(string $userGroup, bool $new = false): void
  286. {
  287. global $dbi;
  288. $relation = new Relation($dbi);
  289. $tabs = Util::getMenuTabList();
  290. $cfgRelation = $relation->getRelationsParam();
  291. $groupTable = Util::backquote($cfgRelation['db'])
  292. . '.' . Util::backquote($cfgRelation['usergroups']);
  293. if (! $new) {
  294. $sql_query = 'DELETE FROM ' . $groupTable
  295. . " WHERE `usergroup`='" . $dbi->escapeString($userGroup)
  296. . "';";
  297. $relation->queryAsControlUser($sql_query, true);
  298. }
  299. $sql_query = 'INSERT INTO ' . $groupTable
  300. . '(`usergroup`, `tab`, `allowed`)'
  301. . ' VALUES ';
  302. $first = true;
  303. foreach ($tabs as $tabGroupName => $tabGroup) {
  304. foreach ($tabGroup as $tab => $tabName) {
  305. if (! $first) {
  306. $sql_query .= ', ';
  307. }
  308. $tabName = $tabGroupName . '_' . $tab;
  309. $allowed = isset($_POST[$tabName]) && $_POST[$tabName] === 'Y';
  310. $sql_query .= "('" . $dbi->escapeString($userGroup) . "', '" . $tabName . "', '"
  311. . ($allowed ? 'Y' : 'N') . "')";
  312. $first = false;
  313. }
  314. }
  315. $sql_query .= ';';
  316. $relation->queryAsControlUser($sql_query, true);
  317. }
  318. }