PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.2
6.2.3 6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 All 156 releases
mainwp / pages / page-mainwp-bulk-update-admin-passwords.php

page-mainwp-bulk-update-admin-passwords.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 6.2.2, at pages/page-mainwp-bulk-update-admin-passwords.php

494 lines 24.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Bulk Update Admin Passwords.
4 *
5 * Handles bulk updating of Administrator Passwords.
6 *
7 * @package MainWP/Dashboard
8 */
9
10 namespace MainWP\Dashboard;
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Class MainWP_Bulk_Update_Admin_Passwords
19 *
20 * @uses MainWP_Bulk_Add
21 */
22 class MainWP_Bulk_Update_Admin_Passwords { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
23
24 /**
25 * Get Class Name
26 *
27 * @return string __CLASS__
28 */
29 public static function get_class_name() {
30 return __CLASS__;
31 }
32
33 /**
34 * Method init_menu()
35 *
36 * Add Users sub menu "Admin Passwords".
37 */
38 public static function init_menu() {
39 add_submenu_page(
40 'mainwp_tab',
41 __( 'Admin Passwords', 'mainwp' ),
42 '<div class="mainwp-hidden">' . esc_html__( 'Admin Passwords', 'mainwp' ) . '</div>',
43 'read',
44 'UpdateAdminPasswords',
45 array(
46 static::get_class_name(),
47 'render',
48 )
49 );
50 }
51
52 /**
53 * Renders the Admin Passwords page footer.
54 */
55 public static function render_footer() {
56 echo '</div>';
57 }
58
59 /**
60 * Renders the Admin Passwords page.
61 *
62 * @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed()
63 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
64 * @uses \MainWP\Dashboard\MainWP_DB::query()
65 * @uses \MainWP\Dashboard\MainWP_DB::get_sql_websites_by_group_id()
66 * @uses \MainWP\Dashboard\MainWP_DB::get_sql_websites_for_current_user()
67 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
68 * @uses \MainWP\Dashboard\MainWP_DB::free_result()
69 * @uses \MainWP\Dashboard\MainWP_Bulk_Add::get_class_name()
70 * @uses \MainWP\Dashboard\MainWP_User::render_header()
71 * @uses \MainWP\Dashboard\MainWP_User::render_footer()
72 * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
73 * @uses \MainWP\Dashboard\MainWP_Utility::map_site()
74 */
75 public static function render() { // phpcs:ignore -- NOSONAR -Current complexity is the only way to achieve desired results, pull request solutions appreciated.
76 $show_form = true;
77 $dbwebsites = array();
78 $errors = array();
79 $form_submitted = false;
80
81 if ( isset( $_POST['bulk_updateadminpassword'] ) ) {
82 $form_submitted = true;
83 check_admin_referer( 'mainwp_updateadminpassword', 'security' );
84
85 if ( isset( $_POST['select_by'] ) ) {
86 $selected_sites = ( isset( $_POST['selected_sites'] ) && is_array( $_POST['selected_sites'] ) ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_sites'] ) ) : array();
87 $selected_groups = ( isset( $_POST['selected_groups'] ) && is_array( $_POST['selected_groups'] ) ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_groups'] ) ) : array();
88 $selected_clients = ( isset( $_POST['selected_clients'] ) && is_array( $_POST['selected_clients'] ) ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_clients'] ) ) : array();
89
90 if ( ( 'group' === $_POST['select_by'] && empty( $selected_groups ) ) || ( 'site' === $_POST['select_by'] && empty( $selected_sites ) ) || ( 'client' === $_POST['select_by'] && empty( $selected_clients ) ) ) {
91 $errors[] = esc_html__( 'Please select the sites or groups or clients where you want to change the administrator password.', 'mainwp' );
92 }
93 } else {
94 $errors[] = esc_html__( 'Please select whether you want to change the administrator password for specific sites, tags or clients.', 'mainwp' );
95 }
96
97 if ( ! isset( $_POST['password'] ) || '' === trim( wp_unslash( $_POST['password'] ) ) ) { //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- ok.
98 $errors[] = esc_html__( 'Please enter the password.', 'mainwp' );
99 }
100
101 $data_fields = MainWP_System_Utility::get_default_map_site_fields();
102
103 if ( empty( $errors ) ) {
104 $show_form = false;
105
106 $new_password = wp_unslash( $_POST['password'] ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- ok.
107
108 if ( 'site' === $_POST['select_by'] ) { // Get all selected websites.
109 foreach ( $selected_sites as $k ) {
110 if ( MainWP_Utility::ctype_digit( $k ) ) {
111 $website = MainWP_DB::instance()->get_website_by_id( $k );
112 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
113 continue;
114 }
115 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
116 $website,
117 $data_fields
118 );
119 }
120 }
121 } elseif ( 'client' === $_POST['select_by'] ) { // Get all selected websites.
122 $websites = MainWP_DB_Client::instance()->get_websites_by_client_ids(
123 $selected_clients,
124 array(
125 'select_data' => $data_fields,
126 )
127 );
128 if ( $websites ) {
129 foreach ( $websites as $website ) {
130 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
131 continue;
132 }
133 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
134 $website,
135 $data_fields
136 );
137 }
138 }
139 } else { // Get all websites from the selected groups.
140 foreach ( $selected_groups as $k ) {
141 if ( MainWP_Utility::ctype_digit( $k ) ) {
142 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_by_group_id( $k ) );
143 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
144 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
145 continue;
146 }
147 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
148 $website,
149 $data_fields
150 );
151 }
152 MainWP_DB::free_result( $websites );
153 }
154 }
155 }
156
157 if ( ! empty( $dbwebsites ) ) {
158 $post_data = array( 'new_password' => base64_encode( $new_password ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
159 $output = new \stdClass();
160 $output->ok = array();
161 $output->errors = array();
162
163 MainWP_Connect::fetch_urls_authed(
164 $dbwebsites,
165 'newadminpassword',
166 $post_data,
167 array(
168 MainWP_Bulk_Add::get_class_name(),
169 'posting_bulk_handler',
170 ),
171 $output
172 );
173 }
174 }
175 }
176
177 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_for_current_user( false, null, 'wp.url', false, false, null, false, array( 'admin_nicename', 'admin_useremail' ) ) );
178
179 MainWP_User::render_header( 'UpdateAdminPasswords' );
180 if ( ! $show_form ) {
181 static::render_modal( $dbwebsites, $output );
182 }
183 static::render_bulk_form( $websites, $errors, $form_submitted );
184 MainWP_User::render_footer( 'UpdateAdminPasswords' );
185 }
186
187 /**
188 * Renders update password results.
189 *
190 * @param object $dbwebsites The websites object.
191 * @param object $output Result of update password.
192 */
193 public static function render_modal( $dbwebsites, $output ) {
194 ?>
195 <div class="ui modal" id="mainwp-reset-admin-passwords-modal">
196 <i class="close icon"></i>
197 <div class="header"><?php esc_html_e( 'Update Admin Password', 'mainwp' ); ?></div>
198 <div class="scrolling content">
199 <?php
200 /**
201 * Action: mainwp_reset_admin_pass_modal_top
202 *
203 * Fires at the top of the Update Admin Passwords modal.
204 *
205 * @since 4.1
206 */
207 do_action( 'mainwp_reset_admin_pass_modal_top' );
208 ?>
209 <div class="ui relaxed divided list">
210 <?php foreach ( $dbwebsites as $website ) : ?>
211 <div class="item">
212 <a href="<?php echo esc_url( admin_url( 'admin.php?page=managesites&dashboard=' . $website->id ) ); ?>"><?php echo esc_html( stripslashes( $website->name ) ); ?></a>
213 <span class="right floated content">
214 <?php echo isset( $output->ok[ $website->id ] ) && 1 === (int) $output->ok[ $website->id ] ? '<i class="green check icon"></i>' : '<i class="red times icon"></i> ' . $output->errors[ $website->id ]; // phpcs:ignore WordPress.Security.EscapeOutput ?>
215 </span>
216 </div>
217 <?php endforeach; ?>
218 </div>
219 <?php
220 /**
221 * Action: mainwp_reset_admin_pass_modal_bottom
222 *
223 * Fires at the bottom of the Update Admin Passwords modal.
224 *
225 * @since 4.1
226 */
227 do_action( 'mainwp_reset_admin_pass_modal_bottom' );
228 ?>
229 </div>
230 <div class="actions">
231 </div>
232 </div>
233 <script type="text/javascript">
234 jQuery( '#mainwp-reset-admin-passwords-modal' ).modal( 'show' );
235 </script>
236 <?php
237 }
238
239 /**
240 * Renders bulk update administrator password form.
241 *
242 * @param object $websites Object containing child sites info.
243 * @param array $errors Array of error messages.
244 * @param bool $form_submitted Whether the form was submitted.
245 *
246 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
247 * @uses \MainWP\Dashboard\MainWP_DB::free_result()
248 * @uses \MainWP\Dashboard\MainWP_Utility::mainwp_display_site()
249 */
250 public static function render_bulk_form( $websites, $errors = array(), $form_submitted = false ) {
251 /**
252 * Filter: mainwp_update_admin_password_complexity
253 *
254 * Filters the Password lenght for the Update Admin Password, Password field.
255 *
256 * Since 4.1
257 */
258 $pass_complexity = apply_filters( 'mainwp_update_admin_password_complexity', '24' );
259 ?>
260 <div id="mainwp-bulk-update-admin-passwords">
261 <form action="" method="post" name="mainwp-update-admin-password-form" id="mainwp-update-admin-password-form">
262 <?php wp_nonce_field( 'mainwp-admin-nonce' ); ?>
263 <input type="hidden" name="security" value="<?php echo esc_attr( wp_create_nonce( 'mainwp_updateadminpassword' ) ); ?>"/>
264 <div class="mainwp-main-content ui padded segment" >
265 <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-admin-pass-info-message' ) ) : ?>
266 <div class="ui attention message">
267 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-admin-pass-info-message"></i>
268 <div><strong><?php esc_html_e( 'Caution: This updates the administrator passwords used for connecting to the selected Child Sites.', 'mainwp' ); ?></strong></div>
269 <div><?php /* translators: 1: opening anchor tag, 2: closing anchor tag */ printf( esc_html__( 'See the list of Admininstrator users used to establish secure connection between your MainWP Dashboard and child sites. If needed, use the provided form to set a new password for these accounts. For additional help, please check this %1$shelp documentation%2$s.', 'mainwp' ), '<a href="https://docs.mainwp.com/sites/users/manage-users#bulk-update-admin-passwords" target="_blank">', '</a> <i class="external alternate icon"></i>' ); // NOSONAR - noopener - open safe. ?></div>
270 </div>
271 <?php endif; ?>
272 <?php if ( $form_submitted ) : ?>
273 <?php if ( empty( $errors ) ) : ?>
274 <div class="ui green message">
275 <i class="close icon"></i>
276 <?php esc_html_e( 'Passwords updated successfully.', 'mainwp' ); ?>
277 </div>
278 <?php else : ?>
279 <div class="ui red message">
280 <i class="close icon"></i>
281 <?php foreach ( $errors as $error ) : ?>
282 <div><?php echo esc_html( $error ); ?></div>
283 <?php endforeach; ?>
284 </div>
285 <?php endif; ?>
286 <?php endif; ?>
287
288 <?php
289 /**
290 * Action: mainwp_admin_pass_before_users_table
291 *
292 * Fires before the Connected Admin Users mysql_list_tables
293 *
294 * @since 4.1
295 */
296 do_action( 'mainwp_admin_pass_before_users_table' );
297 ?>
298 <table id="mainwp-admin-users-table" class="ui single line unstackable table">
299 <thead>
300 <tr>
301 <th scope="col"><?php esc_html_e( 'Site', 'mainwp' ); ?></th>
302 <th scope="col" class="collapsing"><?php esc_html_e( 'Admin Username', 'mainwp' ); ?></th>
303 <th scope="col" class="collapsing"><?php esc_html_e( 'Admin Email', 'mainwp' ); ?></th>
304 </tr>
305 </thead>
306 <tbody>
307 <?php while ( $websites && $website = MainWP_DB::fetch_object( $websites ) ) : ?>
308 <tr>
309 <td><?php MainWP_Utility::mainwp_display_site( $website->id, true, true ); ?></td>
310 <td><?php echo esc_html( $website->adminname ); ?></td>
311 <td><?php echo esc_html( $website->admin_useremail ); ?></td>
312 </tr>
313 <?php endwhile; ?>
314 <?php MainWP_DB::free_result( $websites ); ?>
315 </tbody>
316 </table>
317 <?php
318 /**
319 * Action: mainwp_admin_pass_after_users_table
320 *
321 * Fires after the Connected Admin Users mysql_list_tables
322 *
323 * @since 4.1
324 */
325 do_action( 'mainwp_admin_pass_after_users_table' );
326
327 $table_features = array(
328 'searching' => 'true',
329 'paging' => 'true',
330 'info' => 'true',
331 'colReorder' => 'true',
332 'stateSave' => 'true',
333 'responsive' => 'true',
334 );
335 /**
336 * Filter: mainwp_admin_users_table_fatures
337 *
338 * Filters Admin Users table features.
339 *
340 * @since 4.1
341 */
342 $table_features = apply_filters( 'mainwp_admin_users_table_fatures', $table_features );
343 ?>
344 <script type="text/javascript">
345
346 jQuery( document ).ready( function () {
347 let responsive = <?php echo esc_html( $table_features['responsive'] ); ?>;
348 if( jQuery( window ).width() > 1140 ) {
349 responsive = false;
350 }
351 jQuery( '#mainwp-admin-users-table' ).DataTable( {
352 "searching" : <?php echo esc_html( $table_features['searching'] ); ?>,
353 "paging" : <?php echo esc_html( $table_features['paging'] ); ?>,
354 "info" : <?php echo esc_html( $table_features['info'] ); ?>,
355 "colReorder" : <?php echo $table_features['colReorder']; // phpcs:ignore -- specical chars. ?>,
356 "stateSave": <?php echo esc_html( $table_features['stateSave'] ); ?>,
357 "order": [],
358 "columnDefs": [ { "targets": 'no-sort', "orderable": false } ],
359 "responsive": responsive
360 } );
361 } );
362 </script>
363 </div>
364 <div class="mainwp-side-content mainwp-no-padding">
365 <?php
366 /**
367 * Action: mainwp_admin_pass_sidebar_top
368 *
369 * Fires at the top of the sidebar on Admin Passwords page.
370 *
371 * @since 4.1
372 */
373 do_action( 'mainwp_admin_pass_sidebar_top' );
374 ?>
375 <div class="mainwp-select-sites ui accordion mainwp-sidebar-accordion">
376 <?php
377 /**
378 * Action: mainwp_admin_pass_before_select_sites
379 *
380 * Fires before the Select Sites section on the Admin Passwords page.
381 *
382 * @since 4.1
383 */
384 do_action( 'mainwp_admin_pass_before_select_sites' );
385 ?>
386 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Select Sites', 'mainwp' ); ?></div>
387 <div class="content active">
388 <?php
389 $sel_params = array(
390 'show_client' => true,
391 );
392 MainWP_UI_Select_Sites::select_sites_box( $sel_params );
393 ?>
394 </div>
395 <?php
396 /**
397 * Action: mainwp_admin_pass_after_select_sites
398 *
399 * Fires after the Select Sites section on the Admin Passwords page.
400 *
401 * @since 4.1
402 */
403 do_action( 'mainwp_admin_pass_after_select_sites' );
404 ?>
405 </div>
406 <div class="ui fitted divider"></div>
407 <div class="mainwp-search-options ui accordion mainwp-sidebar-accordion">
408 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Change Admin Password', 'mainwp' ); ?></div>
409 <div class="content active">
410 <?php
411 /**
412 * Action: mainwp_admin_pass_before_pass_form
413 *
414 * Fires before the New password form on the Admin Passwords page.
415 *
416 * @since 4.1
417 */
418 do_action( 'mainwp_admin_pass_before_pass_form' );
419 ?>
420 <div class="ui mini form">
421 <div class="ui blue message"><?php esc_html_e( 'This password will be applied to all administrator accounts used for connecting to the selected Child Sites.', 'mainwp' ); ?></div>
422 <div class="field">
423 <label><?php esc_html_e( 'New Password', 'mainwp' ); ?></label>
424 <input class="hidden" value=" "/>
425 <div class="ui icon input">
426 <input type="text" id="password" name="password" autocomplete="off" value="<?php echo esc_attr( wp_generate_password( $pass_complexity ) ); ?>">
427 <i class="sync alternate link icon mainwp-generate-password-button"></i>
428 </div>
429 </div>
430 </div>
431 <?php
432 /**
433 * Action: mainwp_admin_pass_after_pass_form
434 *
435 * Fires after the New password form on the Admin Passwords page.
436 *
437 * @since 4.1
438 */
439 do_action( 'mainwp_admin_pass_after_pass_form' );
440 ?>
441 </div>
442 </div>
443 <div class="ui fitted divider"></div>
444 <div class="mainwp-search-submit">
445 <?php
446 /**
447 * Action: mainwp_admin_pass_before_submit_button
448 *
449 * Fires before the Submit button on the Admin Passwords page.
450 *
451 * @since 4.1
452 */
453 do_action( 'mainwp_admin_pass_before_submit_button' );
454
455 ?>
456 <input type="hidden" name="bulk_updateadminpassword" value="1" />
457 <a href="#" id="bulk_updateadminpassword" class="ui big green fluid button"><?php esc_html_e( 'Update Password', 'mainwp' ); ?></a>
458 <?php
459 /**
460 * Action: mainwp_admin_pass_after_submit_button
461 *
462 * Fires after the Submit button on the Admin Passwords page.
463 *
464 * @since 4.1
465 */
466 do_action( 'mainwp_admin_pass_after_submit_button' );
467 ?>
468 </div>
469 <?php
470 /**
471 * Action: mainwp_admin_pass_sidebar_bottom
472 *
473 * Fires at the bottom of the sidebar on Admin Passwords page.
474 *
475 * @since 4.1
476 */
477 do_action( 'mainwp_admin_pass_sidebar_bottom' );
478 ?>
479 </div>
480 <div style="clear:both"></div>
481 </form>
482 </div>
483 <script type="text/javascript">
484 jQuery( document ).ready( function () {
485 // Initialize button state based on site selection
486 mainwp_init_button_site_selection_dependency( 'bulk_updateadminpassword' );
487 } );
488 </script>
489 <?php
490 }
491 }
492
493 ?>
494