UserGroups.php 12 KB

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