Merge pull request #14825 from williamdes/issue-14478-export-stream
[phpmyadmin.git] / js / server_privileges.js
blob1625333657506e86ea5e4299a160902ab75c7532
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  */
12 /**
13  * Validates the "add a user" form
14  *
15  * @return boolean  whether the form is validated or not
16  */
17 function checkAddUser (the_form) {
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     }
24     if (the_form.elements.pred_username.value === 'userdefined' && the_form.elements.username.value === '') {
25         alert(PMA_messages.strUserEmpty);
26         the_form.elements.username.focus();
27         return false;
28     }
30     return PMA_checkPassword($(the_form));
31 } // end of the 'checkAddUser()' function
33 function checkPasswordStrength (value, meter_obj, meter_object_label, username) {
34     // List of words we don't want to appear in the password
35     customDict = [
36         'phpmyadmin',
37         'mariadb',
38         'mysql',
39         'php',
40         'my',
41         'admin',
42     ];
43     if (username !== null) {
44         customDict.push(username);
45     }
46     var zxcvbn_obj = zxcvbn(value, customDict);
47     var strength = zxcvbn_obj.score;
48     strength = parseInt(strength);
49     meter_obj.val(strength);
50     switch (strength) {
51     case 0: meter_obj_label.html(PMA_messages.strExtrWeak);
52         break;
53     case 1: meter_obj_label.html(PMA_messages.strVeryWeak);
54         break;
55     case 2: meter_obj_label.html(PMA_messages.strWeak);
56         break;
57     case 3: meter_obj_label.html(PMA_messages.strGood);
58         break;
59     case 4: meter_obj_label.html(PMA_messages.strStrong);
60     }
63 /**
64  * AJAX scripts for server_privileges page.
65  *
66  * Actions ajaxified here:
67  * Add user
68  * Revoke a user
69  * Edit privileges
70  * Export privileges
71  * Paginate table of users
72  * Flush privileges
73  *
74  * @memberOf    jQuery
75  * @name        document.ready
76  */
79 /**
80  * Unbind all event handlers before tearing down a page
81  */
82 AJAX.registerTeardown('server_privileges.js', function () {
83     $('#fieldset_add_user_login').off('change', 'input[name=\'username\']');
84     $(document).off('click', '#fieldset_delete_user_footer #buttonGo.ajax');
85     $(document).off('click', 'a.edit_user_group_anchor.ajax');
86     $(document).off('click', 'button.mult_submit[value=export]');
87     $(document).off('click', 'a.export_user_anchor.ajax');
88     $(document).off('click',  '#initials_table a.ajax');
89     $('#checkbox_drop_users_db').off('click');
90     $(document).off('click', '.checkall_box');
91     $(document).off('change', '#checkbox_SSL_priv');
92     $(document).off('change', 'input[name="ssl_type"]');
93     $(document).off('change', '#select_authentication_plugin');
94 });
96 AJAX.registerOnload('server_privileges.js', function () {
97     /**
98      * Display a warning if there is already a user by the name entered as the username.
99      */
100     $('#fieldset_add_user_login').on('change', 'input[name=\'username\']', function () {
101         var username = $(this).val();
102         var $warning = $('#user_exists_warning');
103         if ($('#select_pred_username').val() === 'userdefined' && username !== '') {
104             var href = $('form[name=\'usersForm\']').attr('action');
105             var params = {
106                 'ajax_request' : true,
107                 'server' : PMA_commonParams.get('server'),
108                 'validate_username' : true,
109                 'username' : username
110             };
111             $.get(href, params, function (data) {
112                 if (data.user_exists) {
113                     $warning.show();
114                 } else {
115                     $warning.hide();
116                 }
117             });
118         } else {
119             $warning.hide();
120         }
121     });
123     /**
124      * Indicating password strength
125      */
126     $('#text_pma_pw').on('keyup', function () {
127         meter_obj = $('#password_strength_meter');
128         meter_obj_label = $('#password_strength');
129         username = $('input[name="username"]');
130         username = username.val();
131         checkPasswordStrength($(this).val(), meter_obj, meter_obj_label, username);
132     });
134     $('#text_pma_change_pw').on('keyup', function () {
135         meter_obj = $('#change_password_strength_meter');
136         meter_obj_label = $('#change_password_strength');
137         checkPasswordStrength($(this).val(), meter_obj, meter_obj_label, PMA_commonParams.get('user'));
138     });
140     /**
141      * Display a notice if sha256_password is selected
142      */
143     $(document).on('change', '#select_authentication_plugin', function () {
144         var selected_plugin = $(this).val();
145         if (selected_plugin === 'sha256_password') {
146             $('#ssl_reqd_warning').show();
147         } else {
148             $('#ssl_reqd_warning').hide();
149         }
150     });
152     /**
153      * AJAX handler for 'Revoke User'
154      *
155      * @see         PMA_ajaxShowMessage()
156      * @memberOf    jQuery
157      * @name        revoke_user_click
158      */
159     $(document).on('click', '#fieldset_delete_user_footer #buttonGo.ajax', function (event) {
160         event.preventDefault();
162         var $thisButton = $(this);
163         var $form = $('#usersForm');
165         $thisButton.PMA_confirm(PMA_messages.strDropUserWarning, $form.attr('action'), function (url) {
166             var $drop_users_db_checkbox = $('#checkbox_drop_users_db');
167             if ($drop_users_db_checkbox.is(':checked')) {
168                 var is_confirmed = confirm(PMA_messages.strDropDatabaseStrongWarning + '\n' + PMA_sprintf(PMA_messages.strDoYouReally, 'DROP DATABASE'));
169                 if (! is_confirmed) {
170                     // Uncheck the drop users database checkbox
171                     $drop_users_db_checkbox.prop('checked', false);
172                 }
173             }
175             PMA_ajaxShowMessage(PMA_messages.strRemovingSelectedUsers);
177             var argsep = PMA_commonParams.get('arg_separator');
178             $.post(url, $form.serialize() + argsep + 'delete=' + $thisButton.val() + argsep + 'ajax_request=true', function (data) {
179                 if (typeof data !== 'undefined' && data.success === true) {
180                     PMA_ajaxShowMessage(data.message);
181                     // Refresh navigation, if we droppped some databases with the name
182                     // that is the same as the username of the deleted user
183                     if ($('#checkbox_drop_users_db:checked').length) {
184                         PMA_reloadNavigation();
185                     }
186                     // Remove the revoked user from the users list
187                     $form.find('input:checkbox:checked').parents('tr').slideUp('medium', function () {
188                         var this_user_initial = $(this).find('input:checkbox').val().charAt(0).toUpperCase();
189                         $(this).remove();
191                         // If this is the last user with this_user_initial, remove the link from #initials_table
192                         if ($('#tableuserrights').find('input:checkbox[value^="' + this_user_initial + '"], input:checkbox[value^="' + this_user_initial.toLowerCase() + '"]').length === 0) {
193                             $('#initials_table').find('td > a:contains(' + this_user_initial + ')').parent('td').html(this_user_initial);
194                         }
196                         // Re-check the classes of each row
197                         $form
198                             .find('tbody').find('tr:odd')
199                             .removeClass('even').addClass('odd')
200                             .end()
201                             .find('tr:even')
202                             .removeClass('odd').addClass('even');
204                         // update the checkall checkbox
205                         $(checkboxes_sel).trigger('change');
206                     });
207                 } else {
208                     PMA_ajaxShowMessage(data.error, false);
209                 }
210             }); // end $.post()
211         });
212     }); // end Revoke User
214     $(document).on('click', 'a.edit_user_group_anchor.ajax', function (event) {
215         event.preventDefault();
216         $(this).parents('tr').addClass('current_row');
217         var $msg = PMA_ajaxShowMessage();
218         $.get(
219             $(this).attr('href'),
220             {
221                 'ajax_request': true,
222                 'edit_user_group_dialog': true
223             },
224             function (data) {
225                 if (typeof data !== 'undefined' && data.success === true) {
226                     PMA_ajaxRemoveMessage($msg);
227                     var buttonOptions = {};
228                     buttonOptions[PMA_messages.strGo] = function () {
229                         var usrGroup = $('#changeUserGroupDialog')
230                             .find('select[name="userGroup"]')
231                             .val();
232                         var $message = PMA_ajaxShowMessage();
233                         var argsep = PMA_commonParams.get('arg_separator');
234                         $.post(
235                             'server_privileges.php',
236                             $('#changeUserGroupDialog').find('form').serialize() + argsep + 'ajax_request=1',
237                             function (data) {
238                                 PMA_ajaxRemoveMessage($message);
239                                 if (typeof data !== 'undefined' && data.success === true) {
240                                     $('#usersForm')
241                                         .find('.current_row')
242                                         .removeClass('current_row')
243                                         .find('.usrGroup')
244                                         .text(usrGroup);
245                                 } else {
246                                     PMA_ajaxShowMessage(data.error, false);
247                                     $('#usersForm')
248                                         .find('.current_row')
249                                         .removeClass('current_row');
250                                 }
251                             }
252                         );
253                         $(this).dialog('close');
254                     };
255                     buttonOptions[PMA_messages.strClose] = function () {
256                         $(this).dialog('close');
257                     };
258                     var $dialog = $('<div/>')
259                         .attr('id', 'changeUserGroupDialog')
260                         .append(data.message)
261                         .dialog({
262                             width: 500,
263                             minWidth: 300,
264                             modal: true,
265                             buttons: buttonOptions,
266                             title: $('legend', $(data.message)).text(),
267                             close: function () {
268                                 $(this).remove();
269                             }
270                         });
271                     $dialog.find('legend').remove();
272                 } else {
273                     PMA_ajaxShowMessage(data.error, false);
274                     $('#usersForm')
275                         .find('.current_row')
276                         .removeClass('current_row');
277                 }
278             }
279         );
280     });
282     /**
283      * AJAX handler for 'Export Privileges'
284      *
285      * @see         PMA_ajaxShowMessage()
286      * @memberOf    jQuery
287      * @name        export_user_click
288      */
289     $(document).on('click', 'button.mult_submit[value=export]', function (event) {
290         event.preventDefault();
291         // can't export if no users checked
292         if ($(this.form).find('input:checked').length === 0) {
293             PMA_ajaxShowMessage(PMA_messages.strNoAccountSelected, 2000, 'success');
294             return;
295         }
296         var $msgbox = PMA_ajaxShowMessage();
297         var button_options = {};
298         button_options[PMA_messages.strClose] = function () {
299             $(this).dialog('close');
300         };
301         var argsep = PMA_commonParams.get('arg_separator');
302         $.post(
303             $(this.form).prop('action'),
304             $(this.form).serialize() + argsep + 'submit_mult=export' + argsep + 'ajax_request=true',
305             function (data) {
306                 if (typeof data !== 'undefined' && data.success === true) {
307                     var $ajaxDialog = $('<div />')
308                         .append(data.message)
309                         .dialog({
310                             title: data.title,
311                             width: 500,
312                             buttons: button_options,
313                             close: function () {
314                                 $(this).remove();
315                             }
316                         });
317                     PMA_ajaxRemoveMessage($msgbox);
318                     // Attach syntax highlighted editor to export dialog
319                     PMA_getSQLEditor($ajaxDialog.find('textarea'));
320                 } else {
321                     PMA_ajaxShowMessage(data.error, false);
322                 }
323             }
324         ); // end $.post
325     });
326     // if exporting non-ajax, highlight anyways
327     PMA_getSQLEditor($('textarea.export'));
329     $(document).on('click', 'a.export_user_anchor.ajax', function (event) {
330         event.preventDefault();
331         var $msgbox = PMA_ajaxShowMessage();
332         /**
333          * @var button_options  Object containing options for jQueryUI dialog buttons
334          */
335         var button_options = {};
336         button_options[PMA_messages.strClose] = function () {
337             $(this).dialog('close');
338         };
339         $.get($(this).attr('href'), { 'ajax_request': true }, function (data) {
340             if (typeof data !== 'undefined' && data.success === true) {
341                 var $ajaxDialog = $('<div />')
342                     .append(data.message)
343                     .dialog({
344                         title: data.title,
345                         width: 500,
346                         buttons: button_options,
347                         close: function () {
348                             $(this).remove();
349                         }
350                     });
351                 PMA_ajaxRemoveMessage($msgbox);
352                 // Attach syntax highlighted editor to export dialog
353                 PMA_getSQLEditor($ajaxDialog.find('textarea'));
354             } else {
355                 PMA_ajaxShowMessage(data.error, false);
356             }
357         }); // end $.get
358     }); // end export privileges
360     /**
361      * AJAX handler to Paginate the Users Table
362      *
363      * @see         PMA_ajaxShowMessage()
364      * @name        paginate_users_table_click
365      * @memberOf    jQuery
366      */
367     $(document).on('click', '#initials_table a.ajax', function (event) {
368         event.preventDefault();
369         var $msgbox = PMA_ajaxShowMessage();
370         $.get($(this).attr('href'), { 'ajax_request' : true }, function (data) {
371             if (typeof data !== 'undefined' && data.success === true) {
372                 PMA_ajaxRemoveMessage($msgbox);
373                 // This form is not on screen when first entering Privileges
374                 // if there are more than 50 users
375                 $('div.notice').remove();
376                 $('#usersForm').hide('medium').remove();
377                 $('#fieldset_add_user').hide('medium').remove();
378                 $('#initials_table')
379                     .prop('id', 'initials_table_old')
380                     .after(data.message).show('medium')
381                     .siblings('h2').not(':first').remove();
382                 // prevent double initials table
383                 $('#initials_table_old').remove();
384             } else {
385                 PMA_ajaxShowMessage(data.error, false);
386             }
387         }); // end $.get
388     }); // end of the paginate users table
390     $(document).on('change', 'input[name="ssl_type"]', function (e) {
391         var $div = $('#specified_div');
392         if ($('#ssl_type_SPECIFIED').is(':checked')) {
393             $div.find('input').prop('disabled', false);
394         } else {
395             $div.find('input').prop('disabled', true);
396         }
397     });
399     $(document).on('change', '#checkbox_SSL_priv', function (e) {
400         var $div = $('#require_ssl_div');
401         if ($(this).is(':checked')) {
402             $div.find('input').prop('disabled', false);
403             $('#ssl_type_SPECIFIED').trigger('change');
404         } else {
405             $div.find('input').prop('disabled', true);
406         }
407     });
409     $('#checkbox_SSL_priv').trigger('change');
411     /*
412      * Create submenu for simpler interface
413      */
414     var addOrUpdateSubmenu = function () {
415         var $topmenu2 = $('#topmenu2');
416         var $edit_user_dialog = $('#edit_user_dialog');
417         var submenu_label;
418         var submenu_link;
419         var link_number;
421         // if submenu exists yet, remove it first
422         if ($topmenu2.length > 0) {
423             $topmenu2.remove();
424         }
426         // construct a submenu from the existing fieldsets
427         $topmenu2 = $('<ul/>').prop('id', 'topmenu2');
429         $('#edit_user_dialog .submenu-item').each(function () {
430             submenu_label = $(this).find('legend[data-submenu-label]').data('submenu-label');
432             submenu_link = $('<a/>')
433                 .prop('href', '#')
434                 .html(submenu_label);
436             $('<li/>')
437                 .append(submenu_link)
438                 .appendTo($topmenu2);
439         });
441         // click handlers for submenu
442         $topmenu2.find('a').click(function (e) {
443             e.preventDefault();
444             // if already active, ignore click
445             if ($(this).hasClass('tabactive')) {
446                 return;
447             }
448             $topmenu2.find('a').removeClass('tabactive');
449             $(this).addClass('tabactive');
451             // which section to show now?
452             link_number = $topmenu2.find('a').index($(this));
453             // hide all sections but the one to show
454             $('#edit_user_dialog .submenu-item').hide().eq(link_number).show();
455         });
457         // make first menu item active
458         // TODO: support URL hash history
459         $topmenu2.find('> :first-child a').addClass('tabactive');
460         $edit_user_dialog.prepend($topmenu2);
462         // hide all sections but the first
463         $('#edit_user_dialog .submenu-item').hide().eq(0).show();
465         // scroll to the top
466         $('html, body').animate({ scrollTop: 0 }, 'fast');
467     };
469     $('input.autofocus').focus();
470     $(checkboxes_sel).trigger('change');
471     displayPasswordGenerateButton();
472     if ($('#edit_user_dialog').length > 0) {
473         addOrUpdateSubmenu();
474     }
476     var windowwidth = $(window).width();
477     $('.jsresponsive').css('max-width', (windowwidth - 35) + 'px');