| @@ -18,21 +18,142 @@ | ||
| 18 | 18 | */ |
| 19 | 19 | public function __construct( $core ) { |
| 20 | 20 | parent::__construct( $core ); |
| 21 | 21 | if ( isset( $_POST['PatchstackNonce'] ) && current_user_can( 'manage_options' ) && wp_verify_nonce( $_POST['PatchstackNonce'], 'patchstack-nonce' ) ) { |
| 22 | + // Log tables actions. | |
| 23 | + add_action( 'wp_ajax_patchstack_users_log_table', [ $this, 'users_log_table' ] ); | |
| 24 | + add_action( 'wp_ajax_patchstack_firewall_log_table', [ $this, 'firewall_log_table' ] ); | |
| 25 | + | |
| 22 | 26 | // License related actions. |
| 23 | 27 | add_action( 'wp_ajax_patchstack_activate_license', [ $this, 'activate_license' ] ); |
| 24 | 28 | |
| 25 | - // Auto license activator. | |
| 26 | - add_action( 'wp_ajax_patchstack_activate_auto', [ $this, 'auto_activate' ] ); | |
| 27 | - add_action( 'wp_ajax_patchstack_activation_status', [ $this, 'activation_status' ] ); | |
| 29 | + // Hide login related actions. | |
| 30 | + add_action( 'wp_ajax_patchstack_send_new_url_email', [ $this, 'send_new_url_email' ] ); | |
| 31 | + } | |
| 32 | + } | |
| 28 | 33 | |
| 29 | - // Manual connection re-check (Retry link on the settings card). | |
| 30 | - add_action( 'wp_ajax_patchstack_check_connection', [ $this, 'check_connection' ] ); | |
| 34 | + /** | |
| 35 | + * Firewall logs pagination. | |
| 36 | + * | |
| 37 | + * @return array | |
| 38 | + */ | |
| 39 | + public function firewall_log_table() { | |
| 40 | + if ( ! isset( $_POST['start'], $_POST['length'] ) || !ctype_digit( $_POST['start'] ) || !ctype_digit( $_POST['length'] ) ) { | |
| 41 | + exit; | |
| 31 | 42 | } |
| 43 | + | |
| 44 | + // Pull all entries, given parameters. | |
| 45 | + global $wpdb; | |
| 46 | + $entries = $wpdb->get_results( | |
| 47 | + $wpdb->prepare( | |
| 48 | + "SELECT a.id, a.ip, a.flag, a.method, a.log_date, case when a.referer IS NULL or a.referer = '' then a.request_uri else a.referer end as referer, a.fid, b.description | |
| 49 | + FROM " . $wpdb->prefix . 'patchstack_firewall_log AS a | |
| 50 | + LEFT JOIN ' . $wpdb->prefix . 'patchstack_logic AS b ON b.id = a.fid | |
| 51 | + ORDER BY a.id DESC | |
| 52 | + LIMIT %d, %d | |
| 53 | + ', | |
| 54 | + [ wp_filter_nohtml_kses( $_POST['start'] ), wp_filter_nohtml_kses( $_POST['length'] ) ] | |
| 55 | + ) | |
| 56 | + ); | |
| 57 | + | |
| 58 | + // Get total amount of rows. | |
| 59 | + $count = $wpdb->get_var( 'SELECT COUNT(id) FROM ' . $wpdb->prefix . 'patchstack_firewall_log' ); | |
| 60 | + $firewall_rules = json_decode( get_option( 'patchstack_firewall_rules', '' ), true ); | |
| 61 | + $firewall_rules_v3 = json_decode( get_option( 'patchstack_firewall_rules_v3', [] ), true ); | |
| 62 | + $firewall_rules = array_merge($firewall_rules, $firewall_rules_v3); | |
| 63 | + | |
| 64 | + // Modify data if necessary. | |
| 65 | + $list = []; | |
| 66 | + foreach ( $entries as $entry ) { | |
| 67 | + foreach ( $entry as $key => $value ) { | |
| 68 | + if ( ! in_array( $key, [ 'referer' ] ) ) { | |
| 69 | + $entry->$key = sanitize_textarea_field( $value ); | |
| 70 | + } | |
| 71 | + } | |
| 72 | + | |
| 73 | + // Attempt to find the block reason. | |
| 74 | + $reason = $wpdb->get_var( $wpdb->prepare( 'SELECT cname FROM ' . $wpdb->prefix . 'patchstack_logic WHERE id = %d LIMIT 1', [ $entry->fid ] ) ); | |
| 75 | + if ( $reason ) { | |
| 76 | + $entry->fid = $reason; | |
| 77 | + } elseif ( $firewall_rules != '' ) { | |
| 78 | + foreach ( $firewall_rules as $rule ) { | |
| 79 | + if ( isset( $rule['title'], $rule['cat'] ) && '55' . $rule['id'] == $entry->fid ) { | |
| 80 | + $entry->fid = $rule['cat']; | |
| 81 | + $entry->description = $rule['title']; | |
| 82 | + } | |
| 83 | + } | |
| 84 | + } else { | |
| 85 | + $entry->fid = 'Unknown'; | |
| 86 | + } | |
| 87 | + | |
| 88 | + $list[] = $entry; | |
| 89 | + } | |
| 90 | + | |
| 91 | + // Return output. | |
| 92 | + wp_send_json( | |
| 93 | + [ | |
| 94 | + 'data' => $list, | |
| 95 | + 'recordsFiltered' => $count, | |
| 96 | + 'recordsTotal' => $count | |
| 97 | + ] | |
| 98 | + ); | |
| 32 | 99 | } |
| 33 | 100 | |
| 34 | 101 | /** |
| 102 | + * Activity logs pagination. | |
| 103 | + * | |
| 104 | + * @return void | |
| 105 | + */ | |
| 106 | + public function users_log_table() { | |
| 107 | + if ( ! isset( $_POST['start'], $_POST['length'] ) || !ctype_digit( $_POST['start'] ) || !ctype_digit( $_POST['length'] ) ) { | |
| 108 | + exit; | |
| 109 | + } | |
| 110 | + | |
| 111 | + // Determine if searching? | |
| 112 | + global $wpdb; | |
| 113 | + $searching = false; | |
| 114 | + $likes = []; | |
| 115 | + if ( isset( $_POST['search'], $_POST['search']['value'] ) && $_POST['search']['value'] != '' ) { | |
| 116 | + $val = wp_filter_nohtml_kses( $_POST['search']['value'] ); | |
| 117 | + $searching = true; | |
| 118 | + $columns = [ 'author', 'ip', 'object', 'object_name', 'action' ]; | |
| 119 | + $search = 'WHERE 1=2 '; | |
| 120 | + foreach ( $columns as $column ) { | |
| 121 | + array_push( $likes, '%' . $wpdb->esc_like( $val ) . '%' ); | |
| 122 | + $search .= 'OR ' . $column . ' LIKE %s'; | |
| 123 | + } | |
| 124 | + } | |
| 125 | + | |
| 126 | + $logs = $wpdb->get_results( | |
| 127 | + $wpdb->prepare( | |
| 128 | + 'SELECT * | |
| 129 | + FROM ' . $wpdb->prefix . 'patchstack_event_log ' . ( $searching ? $search : '' ) . ' | |
| 130 | + ORDER BY id DESC | |
| 131 | + LIMIT %d, %d | |
| 132 | + ', | |
| 133 | + array_merge( $likes, [ wp_filter_nohtml_kses( $_POST['start'] ), wp_filter_nohtml_kses( $_POST['length'] ) ] ) | |
| 134 | + ) | |
| 135 | + ); | |
| 136 | + | |
| 137 | + $count = $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(id) FROM ' . $wpdb->prefix . 'patchstack_event_log ' . ( $searching ? $search : '' ), $likes ) ); | |
| 138 | + | |
| 139 | + // Modify data if necessary. | |
| 140 | + $list = []; | |
| 141 | + foreach ( $logs as $log ) { | |
| 142 | + $list[] = $log; | |
| 143 | + } | |
| 144 | + | |
| 145 | + // Return output. | |
| 146 | + wp_send_json( | |
| 147 | + [ | |
| 148 | + 'data' => $list, | |
| 149 | + 'recordsFiltered' => $count, | |
| 150 | + 'recordsTotal' => $count | |
| 151 | + ] | |
| 152 | + ); | |
| 153 | + } | |
| 154 | + | |
| 155 | + /** | |
| 35 | 156 | * Test and activate a new license. |
| 36 | 157 | * |
| 37 | 158 | * @return void |
| 38 | 159 | */ |
| @@ -40,9 +161,9 @@ | ||
| 40 | 161 | if ( ! isset( $_POST['key'] ) || strpos( $_POST['key'], '-' ) === false) { |
| 41 | 162 | wp_send_json( |
| 42 | 163 | [ |
| 43 | 164 | 'result' => 'error', |
| 44 | - 'error_message' => esc_attr__('An invalid API key was provided.', 'patchstack') | |
| 165 | + 'error_message' => 'An invalid API key was provided.' | |
| 45 | 166 | ] |
| 46 | 167 | ); |
| 47 | 168 | } |
| 48 | 169 | |
| @@ -47,10 +168,10 @@ | ||
| 47 | 168 | } |
| 48 | 169 | |
| 49 | 170 | // Since we have the keys combined into one now, split them up here. |
| 50 | 171 | $split = explode('-', $_POST['key']); |
| 51 | - $secretkey = trim($split[0]); | |
| 52 | - $clientid = trim($split[1]); | |
| 172 | + $secretkey = $split[0]; | |
| 173 | + $clientid = $split[1]; | |
| 53 | 174 | |
| 54 | 175 | // Test the new keys. |
| 55 | 176 | update_option( 'patchstack_api_token', '' ); |
| 56 | 177 | $results = $this->plugin->activation->alter_license( wp_filter_nohtml_kses( $clientid ), wp_filter_nohtml_kses( $secretkey ), 'activate' ); |
| @@ -61,54 +182,16 @@ | ||
| 61 | 182 | } |
| 62 | 183 | } |
| 63 | 184 | |
| 64 | 185 | /** |
| 65 | - * Attempt to auto activate the license after a plugin activation, if no current license exists. | |
| 66 | - * | |
| 67 | - * @return void | |
| 68 | - */ | |
| 69 | - public function auto_activate() { | |
| 70 | - $secretToken = get_option( 'patchstack_activation_secret', '' ); | |
| 71 | - | |
| 72 | - // Only continue if we have a secret token. | |
| 73 | - $autoActivated = false; | |
| 74 | - if ( ! empty( $secretToken ) ) { | |
| 75 | - $autoActivated = $this->plugin->api->send_secret_token( $secretToken ); | |
| 76 | - } | |
| 77 | - | |
| 78 | - wp_send_json( [ | |
| 79 | - 'result' => $autoActivated || get_option( 'patchstack_clientid', false ) != false ? 'success' : 'error' | |
| 80 | - ] ); | |
| 81 | - } | |
| 82 | - | |
| 83 | - /** | |
| 84 | - * Get the current license activation status. | |
| 85 | - * | |
| 86 | - * @return void | |
| 87 | - */ | |
| 88 | - public function activation_status() { | |
| 89 | - wp_send_json( [ | |
| 90 | - 'activated' => get_option( 'patchstack_clientid', false ) != false | |
| 91 | - ] ); | |
| 92 | - } | |
| 93 | - | |
| 94 | - /** | |
| 95 | - * Run a connection check on demand and return the new state for the settings card row. | |
| 96 | - * Wraps P_Api::update_license_status() so the existing 422-handling happens for free; a | |
| 97 | - * successful request stamps patchstack_last_sync, which get_last_sync_time() reads back. | |
| 186 | + * Send an email to the current logged in user that contains the new admin page URL. | |
| 98 | 187 | * |
| 99 | 188 | * @return void |
| 100 | 189 | */ |
| 101 | - public function check_connection() { | |
| 102 | - $this->plugin->api->update_license_status(); | |
| 103 | - | |
| 104 | - $timestamp = $this->get_last_sync_time(); | |
| 105 | - | |
| 106 | - wp_send_json( | |
| 107 | - [ | |
| 108 | - 'connected' => $this->is_connected(), | |
| 109 | - 'timestamp' => $timestamp, | |
| 110 | - 'label' => $this->format_relative_time( $timestamp ), | |
| 111 | - ] | |
| 112 | - ); | |
| 190 | + public function send_new_url_email() { | |
| 191 | + global $current_user; | |
| 192 | + $subject = __( 'New Login URL', 'patchstack' ); | |
| 193 | + $message = '<br /><br />Your login page is now here: <strong> <a href="' . get_site_url() . '/' . get_site_option( 'patchstack_rename_wp_login' ) . '">' . get_site_url() . '/' . get_site_option( 'patchstack_rename_wp_login' ) . '</strong></a>'; | |
| 194 | + $email_sent = wp_mail( $current_user->user_email, $subject, $message ); | |
| 195 | + die( $email_sent ? 'success' : 'fail' ); | |
| 113 | 196 | } |
| 114 | 197 | } |