server_privileges.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. /* vim: set expandtab sw=4 ts=4 sts=4: */
  2. /**
  3. * @fileoverview functions used in server privilege pages
  4. * @name Server Privileges
  5. *
  6. * @requires jQuery
  7. * @requires jQueryUI
  8. * @requires js/functions.js
  9. *
  10. */
  11. /**
  12. * Validates the "add a user" form
  13. *
  14. * @return boolean whether the form is validated or not
  15. */
  16. function checkAddUser(the_form)
  17. {
  18. if (the_form.elements['pred_hostname'].value == 'userdefined' && the_form.elements['hostname'].value == '') {
  19. alert(PMA_messages['strHostEmpty']);
  20. the_form.elements['hostname'].focus();
  21. return false;
  22. }
  23. if (the_form.elements['pred_username'].value == 'userdefined' && the_form.elements['username'].value == '') {
  24. alert(PMA_messages['strUserEmpty']);
  25. the_form.elements['username'].focus();
  26. return false;
  27. }
  28. return PMA_checkPassword($(the_form));
  29. } // end of the 'checkAddUser()' function
  30. /**
  31. * When a new user is created and retrieved over Ajax, append the user's row to
  32. * the user's table
  33. *
  34. * @param new_user_string the html for the new user's row
  35. * @param new_user_initial the first alphabet of the user's name
  36. * @param new_user_initial_string html to replace the initial for pagination
  37. */
  38. function appendNewUser(new_user_string, new_user_initial, new_user_initial_string)
  39. {
  40. //Append the newly retrieved user to the table now
  41. //Calculate the index for the new row
  42. var $curr_last_row = $("#usersForm").find('tbody').find('tr:last');
  43. var $curr_first_row = $("#usersForm").find('tbody').find('tr:first');
  44. var first_row_initial = $curr_first_row.find('label').html().substr(0, 1).toUpperCase();
  45. var curr_shown_initial = $curr_last_row.find('label').html().substr(0, 1).toUpperCase();
  46. var curr_last_row_index_string = $curr_last_row.find('input:checkbox').attr('id').match(/\d+/)[0];
  47. var curr_last_row_index = parseFloat(curr_last_row_index_string);
  48. var new_last_row_index = curr_last_row_index + 1;
  49. var new_last_row_id = 'checkbox_sel_users_' + new_last_row_index;
  50. var is_show_all = (first_row_initial != curr_shown_initial) ? true : false;
  51. //Append to the table and set the id/names correctly
  52. if ((curr_shown_initial == new_user_initial) || is_show_all) {
  53. $(new_user_string)
  54. .insertAfter($curr_last_row)
  55. .find('input:checkbox')
  56. .attr('id', new_last_row_id)
  57. .val(function() {
  58. //the insert messes up the &27; part. let's fix it
  59. return $(this).val().replace(/&/,'&');
  60. })
  61. .end()
  62. .find('label')
  63. .attr('for', new_last_row_id)
  64. .end();
  65. }
  66. //Let us sort the table alphabetically
  67. $("#usersForm").find('tbody').PMA_sort_table('label');
  68. $("#initials_table").find('td:contains('+new_user_initial+')')
  69. .html(new_user_initial_string);
  70. //update the checkall checkbox
  71. $(checkboxes_sel).trigger("change");
  72. }
  73. function addUser($form)
  74. {
  75. if (! checkAddUser($form.get(0))) {
  76. return false;
  77. }
  78. //We also need to post the value of the submit button in order to get this to work correctly
  79. $.post($form.attr('action'), $form.serialize() + "&adduser_submit=" + $("input[name=adduser_submit]").val(), function(data) {
  80. if (data.success == true) {
  81. // Refresh navigation, if we created a database with the name
  82. // that is the same as the username of the new user
  83. if ($('#add_user_dialog #createdb-1:checked').length) {
  84. PMA_reloadNavigation();
  85. }
  86. $('#page_content').show();
  87. $("#add_user_dialog").remove();
  88. PMA_ajaxShowMessage(data.message);
  89. $("#result_query").remove();
  90. $('#page_content').prepend(data.sql_query);
  91. $("#result_query").css({
  92. 'margin-top' : '0.5em'
  93. });
  94. //Remove the empty notice div generated due to a NULL query passed to PMA_getMessage()
  95. var $notice_class = $("#result_query").find('.notice');
  96. if ($notice_class.text() == '') {
  97. $notice_class.remove();
  98. }
  99. if ($('#fieldset_add_user a.ajax').attr('name') == 'db_specific') {
  100. /*process the fieldset_add_user attribute and get the val of privileges*/
  101. var url = $('#fieldset_add_user a.ajax').attr('rel');
  102. if (url.substring(url.length - 23, url.length) == "&goto=db_operations.php") {
  103. url = url.substring(0, url.length - 23);
  104. }
  105. url = url + "&ajax_request=true&db_specific=true";
  106. /* post request for get the updated userForm table */
  107. $.post($form.attr('action'), url, function(priv_data) {
  108. /*Remove the old userForm table*/
  109. if ($('#userFormDiv').length != 0) {
  110. $('#userFormDiv').remove();
  111. } else {
  112. $("#usersForm").remove();
  113. }
  114. if (priv_data.success == true) {
  115. $('<div id="userFormDiv"></div>')
  116. .html(priv_data.user_form)
  117. .insertAfter('#result_query');
  118. } else {
  119. PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + priv_data.error, false);
  120. }
  121. });
  122. } else {
  123. appendNewUser(data.new_user_string, data.new_user_initial, data.new_user_initial_string);
  124. }
  125. } else {
  126. PMA_ajaxShowMessage(data.error, false);
  127. }
  128. });
  129. }
  130. /**
  131. * AJAX scripts for server_privileges page.
  132. *
  133. * Actions ajaxified here:
  134. * Add user
  135. * Revoke a user
  136. * Edit privileges
  137. * Export privileges
  138. * Paginate table of users
  139. * Flush privileges
  140. *
  141. * @memberOf jQuery
  142. * @name document.ready
  143. */
  144. /**
  145. * Unbind all event handlers before tearing down a page
  146. */
  147. AJAX.registerTeardown('server_privileges.js', function() {
  148. $("#fieldset_add_user a.ajax").die("click");
  149. $('form[name=usersForm]').unbind('submit');
  150. $("#fieldset_delete_user_footer #buttonGo.ajax").die('click');
  151. $("a.edit_user_anchor.ajax").die('click');
  152. $("#edit_user_dialog").find("form.ajax").die('submit');
  153. $("button.mult_submit[value=export]").die('click');
  154. $("a.export_user_anchor.ajax").die('click');
  155. $("#initials_table").find("a.ajax").die('click');
  156. $('#checkbox_drop_users_db').unbind('click');
  157. });
  158. AJAX.registerOnload('server_privileges.js', function() {
  159. /**
  160. * AJAX event handler for 'Add a New User'
  161. *
  162. * @see PMA_ajaxShowMessage()
  163. * @see appendNewUser()
  164. * @memberOf jQuery
  165. * @name add_user_click
  166. *
  167. */
  168. $("#fieldset_add_user a.ajax").live("click", function(event) {
  169. /** @lends jQuery */
  170. event.preventDefault();
  171. var $msgbox = PMA_ajaxShowMessage();
  172. $.get($(this).attr("href"), {'ajax_request':true}, function(data) {
  173. if (data.success == true) {
  174. $('#page_content').hide();
  175. var $div = $('#add_user_dialog');
  176. if ($div.length == 0) {
  177. $div = $('<div id="add_user_dialog" style="margin: 0.5em;"></div>')
  178. .insertBefore('#page_content');
  179. } else {
  180. $div.empty();
  181. }
  182. $div.html(data.message)
  183. .find("form[name=usersForm]")
  184. .append('<input type="hidden" name="ajax_request" value="true" />')
  185. .end();
  186. displayPasswordGenerateButton();
  187. PMA_showHints($div);
  188. PMA_ajaxRemoveMessage($msgbox);
  189. $div.find("input.autofocus").focus();
  190. $div.find('form[name=usersForm]').bind('submit', function (event) {
  191. event.preventDefault();
  192. addUser($(this));
  193. });
  194. } else {
  195. PMA_ajaxShowMessage(data.error, false);
  196. }
  197. }); // end $.get()
  198. });//end of Add New User AJAX event handler
  199. /**
  200. * AJAX handler for 'Revoke User'
  201. *
  202. * @see PMA_ajaxShowMessage()
  203. * @memberOf jQuery
  204. * @name revoke_user_click
  205. */
  206. $("#fieldset_delete_user_footer #buttonGo.ajax").live('click', function(event) {
  207. event.preventDefault();
  208. PMA_ajaxShowMessage(PMA_messages['strRemovingSelectedUsers']);
  209. var $form = $("#usersForm");
  210. $.post($form.attr('action'), $form.serialize() + "&delete=" + $(this).val() + "&ajax_request=true", function(data) {
  211. if (data.success == true) {
  212. PMA_ajaxShowMessage(data.message);
  213. // Refresh navigation, if we droppped some databases with the name
  214. // that is the same as the username of the deleted user
  215. if ($('#checkbox_drop_users_db:checked').length) {
  216. PMA_reloadNavigation();
  217. }
  218. //Remove the revoked user from the users list
  219. $form.find("input:checkbox:checked").parents("tr").slideUp("medium", function() {
  220. var this_user_initial = $(this).find('input:checkbox').val().charAt(0).toUpperCase();
  221. $(this).remove();
  222. //If this is the last user with this_user_initial, remove the link from #initials_table
  223. if ($("#tableuserrights").find('input:checkbox[value^=' + this_user_initial + ']').length == 0) {
  224. $("#initials_table").find('td > a:contains(' + this_user_initial + ')').parent('td').html(this_user_initial);
  225. }
  226. //Re-check the classes of each row
  227. $form
  228. .find('tbody').find('tr:odd')
  229. .removeClass('even').addClass('odd')
  230. .end()
  231. .find('tr:even')
  232. .removeClass('odd').addClass('even');
  233. //update the checkall checkbox
  234. $(checkboxes_sel).trigger("change");
  235. });
  236. } else {
  237. PMA_ajaxShowMessage(data.error, false);
  238. }
  239. }); // end $.post()
  240. }); // end Revoke User
  241. /**
  242. * AJAX handler for 'Edit User'
  243. *
  244. * @see PMA_ajaxShowMessage()
  245. *
  246. */
  247. /**
  248. * Step 1: Load Edit User Dialog
  249. * @memberOf jQuery
  250. * @name edit_user_click
  251. */
  252. $("a.edit_user_anchor.ajax").live('click', function(event) {
  253. /** @lends jQuery */
  254. event.preventDefault();
  255. var $msgbox = PMA_ajaxShowMessage();
  256. $(this).parents('tr').addClass('current_row');
  257. var token = $(this).parents('form').find('input[name="token"]').val();
  258. $.get(
  259. $(this).attr('href'),
  260. {
  261. 'ajax_request':true,
  262. 'edit_user_dialog': true,
  263. 'token': token
  264. },
  265. function(data) {
  266. if (data.success == true) {
  267. $('#page_content').hide();
  268. var $div = $('#edit_user_dialog');
  269. if ($div.length == 0) {
  270. $div = $('<div id="edit_user_dialog" style="margin: 0.5em;"></div>')
  271. .insertBefore('#page_content');
  272. } else {
  273. $div.empty();
  274. }
  275. $div.html(data.message);
  276. displayPasswordGenerateButton();
  277. PMA_ajaxRemoveMessage($msgbox);
  278. PMA_showHints($div);
  279. } else {
  280. PMA_ajaxShowMessage(data.error, false);
  281. }
  282. }
  283. ); // end $.get()
  284. });
  285. /**
  286. * Step 2: Submit the Edit User Dialog
  287. *
  288. * @see PMA_ajaxShowMessage()
  289. * @memberOf jQuery
  290. * @name edit_user_submit
  291. */
  292. $("#edit_user_dialog").find("form.ajax").live('submit', function(event) {
  293. /** @lends jQuery */
  294. event.preventDefault();
  295. var $t = $(this);
  296. if ($t.is('.copyUserForm') && ! PMA_checkPassword($t)) {
  297. return false;
  298. }
  299. PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']);
  300. $t.append('<input type="hidden" name="ajax_request" value="true" />');
  301. /**
  302. * @var curr_submit_name name of the current button being submitted
  303. */
  304. var curr_submit_name = $t.find('.tblFooters').find('input:submit').attr('name');
  305. /**
  306. * @var curr_submit_value value of the current button being submitted
  307. */
  308. var curr_submit_value = $t.find('.tblFooters').find('input:submit').val();
  309. // If any option other than 'keep the old one'(option 4) is chosen, we need to remove
  310. // the old one from the table.
  311. var $row_to_remove;
  312. if (curr_submit_name == 'change_copy'
  313. && $('input[name=mode]:checked', '#fieldset_mode').val() != '4') {
  314. var old_username = $t.find('input[name="old_username"]').val();
  315. var old_hostname = $t.find('input[name="old_hostname"]').val();
  316. $('#usersForm tbody tr').each(function() {
  317. var $tr = $(this);
  318. if ($tr.find('td:nth-child(2) label').text() == old_username
  319. && $tr.find('td:nth-child(3)').text() == old_hostname) {
  320. $row_to_remove = $tr;
  321. return false;
  322. }
  323. });
  324. }
  325. $.post($t.attr('action'), $t.serialize() + '&' + curr_submit_name + '=' + curr_submit_value, function(data) {
  326. if (data.success == true) {
  327. $('#page_content').show();
  328. $("#edit_user_dialog").remove();
  329. PMA_ajaxShowMessage(data.message);
  330. if (data.sql_query) {
  331. $("#result_query").remove();
  332. $('#page_content').prepend(data.sql_query);
  333. $("#result_query").css({
  334. 'margin-top' : '0.5em'
  335. });
  336. var $notice_class = $("#result_query").find('.notice');
  337. if ($notice_class.text() == '') {
  338. $notice_class.remove();
  339. }
  340. } //Show SQL Query that was executed
  341. // Remove the old row if the old user is deleted
  342. if ($row_to_remove != null) {
  343. $row_to_remove.remove();
  344. }
  345. //Append new user if necessary
  346. if (data.new_user_string) {
  347. appendNewUser(data.new_user_string, data.new_user_initial, data.new_user_initial_string);
  348. }
  349. //Check if we are on the page of the db-specific privileges
  350. var db_priv_page = !!($('#dbspecificuserrights').length); // the "!!" part is merely there to ensure a value of type boolean
  351. // we always need to reload on the db-specific privilege page
  352. // and on the global page when adjusting global privileges,
  353. // but not on the global page when adjusting db-specific privileges.
  354. var reload_privs = false;
  355. if (data.db_specific_privs == false || (db_priv_page == data.db_specific_privs)) {
  356. reload_privs = true;
  357. }
  358. if (data.db_wildcard_privs) {
  359. reload_privs = false;
  360. }
  361. //Change privileges, if they were edited and need to be reloaded
  362. if (data.new_privileges && reload_privs) {
  363. $("#usersForm")
  364. .find('.current_row')
  365. .find('code')
  366. .html(data.new_privileges);
  367. }
  368. $("#usersForm")
  369. .find('.current_row')
  370. .removeClass('current_row');
  371. } else {
  372. PMA_ajaxShowMessage(data.error, false);
  373. }
  374. });
  375. });
  376. //end Edit user
  377. /**
  378. * AJAX handler for 'Export Privileges'
  379. *
  380. * @see PMA_ajaxShowMessage()
  381. * @memberOf jQuery
  382. * @name export_user_click
  383. */
  384. $("button.mult_submit[value=export]").live('click', function(event) {
  385. event.preventDefault();
  386. // can't export if no users checked
  387. if ($(this.form).find("input:checked").length == 0) {
  388. return;
  389. }
  390. var $msgbox = PMA_ajaxShowMessage();
  391. var button_options = {};
  392. button_options[PMA_messages['strClose']] = function() {
  393. $(this).dialog("close");
  394. };
  395. $.post(
  396. $(this.form).prop('action'),
  397. $(this.form).serialize() + '&submit_mult=export&ajax_request=true',
  398. function(data) {
  399. if (data.success == true) {
  400. var $ajaxDialog = $('<div />')
  401. .append(data.message)
  402. .dialog({
  403. title: data.title,
  404. width: 500,
  405. buttons: button_options,
  406. close: function () {
  407. $(this).remove();
  408. }
  409. });
  410. PMA_ajaxRemoveMessage($msgbox);
  411. // Attach syntax highlited editor to export dialog
  412. if (typeof CodeMirror != 'undefined') {
  413. CodeMirror.fromTextArea(
  414. $ajaxDialog.find('textarea')[0],
  415. {
  416. lineNumbers: true,
  417. matchBrackets: true,
  418. indentUnit: 4,
  419. mode: "text/x-mysql"
  420. }
  421. );
  422. }
  423. } else {
  424. PMA_ajaxShowMessage(data.error, false);
  425. }
  426. }
  427. ); //end $.post
  428. });
  429. // if exporting non-ajax, highlight anyways
  430. if ($("textarea.export").length > 0
  431. && typeof CodeMirror != 'undefined')
  432. {
  433. CodeMirror.fromTextArea(
  434. $('textarea.export')[0],
  435. {
  436. lineNumbers: true,
  437. matchBrackets: true,
  438. indentUnit: 4,
  439. mode: "text/x-mysql"
  440. }
  441. );
  442. }
  443. $("a.export_user_anchor.ajax").live('click', function(event) {
  444. event.preventDefault();
  445. var $msgbox = PMA_ajaxShowMessage();
  446. /**
  447. * @var button_options Object containing options for jQueryUI dialog buttons
  448. */
  449. var button_options = {};
  450. button_options[PMA_messages['strClose']] = function() {
  451. $(this).dialog("close");
  452. };
  453. $.get($(this).attr('href'), {'ajax_request': true}, function(data) {
  454. if (data.success == true) {
  455. var $ajaxDialog = $('<div />')
  456. .append(data.message)
  457. .dialog({
  458. title: data.title,
  459. width: 500,
  460. buttons: button_options,
  461. close: function () {
  462. $(this).remove();
  463. }
  464. });
  465. PMA_ajaxRemoveMessage($msgbox);
  466. // Attach syntax highlited editor to export dialog
  467. if (typeof CodeMirror != 'undefined') {
  468. CodeMirror.fromTextArea(
  469. $ajaxDialog.find('textarea')[0],
  470. {
  471. lineNumbers: true,
  472. matchBrackets: true,
  473. indentUnit: 4,
  474. mode: "text/x-mysql"
  475. }
  476. );
  477. }
  478. } else {
  479. PMA_ajaxShowMessage(data.error, false);
  480. }
  481. }); //end $.get
  482. }); //end export privileges
  483. /**
  484. * AJAX handler to Paginate the Users Table
  485. *
  486. * @see PMA_ajaxShowMessage()
  487. * @name paginate_users_table_click
  488. * @memberOf jQuery
  489. */
  490. $("#initials_table").find("a.ajax").live('click', function(event) {
  491. event.preventDefault();
  492. var $msgbox = PMA_ajaxShowMessage();
  493. $.get($(this).attr('href'), {'ajax_request' : true}, function(data) {
  494. if (data.success == true) {
  495. PMA_ajaxRemoveMessage($msgbox);
  496. // This form is not on screen when first entering Privileges
  497. // if there are more than 50 users
  498. $("div.notice").remove();
  499. $("#usersForm").hide("medium").remove();
  500. $("#fieldset_add_user").hide("medium").remove();
  501. $("#initials_table")
  502. .after(data.message).show("medium")
  503. .siblings("h2").not(":first").remove();
  504. } else {
  505. PMA_ajaxShowMessage(data.error, false);
  506. }
  507. }); // end $.get
  508. }); // end of the paginate users table
  509. /*
  510. * Additional confirmation dialog after clicking
  511. * 'Drop the databases...'
  512. */
  513. $('#checkbox_drop_users_db').click(function() {
  514. var $this_checkbox = $(this);
  515. if ($this_checkbox.is(':checked')) {
  516. var is_confirmed = confirm(PMA_messages['strDropDatabaseStrongWarning'] + '\n' + $.sprintf(PMA_messages['strDoYouReally'], 'DROP DATABASE'));
  517. if (! is_confirmed) {
  518. $this_checkbox.prop('checked', false);
  519. }
  520. }
  521. });
  522. displayPasswordGenerateButton();
  523. });