| @@ -18,97 +18,152 @@ | ||
| 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_users_log_table', array( $this, 'users_log_table' ) ); | |
| 24 | + add_action( 'wp_ajax_firewall_log_table', array( $this, 'firewall_log_table' ) ); | |
| 25 | + | |
| 22 | 26 | // License related actions. |
| 23 | - add_action( 'wp_ajax_patchstack_activate_license', [ $this, 'activate_license' ] ); | |
| 24 | - | |
| 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' ] ); | |
| 28 | - | |
| 29 | - // Manual connection re-check (Retry link on the settings card). | |
| 30 | - add_action( 'wp_ajax_patchstack_check_connection', [ $this, 'check_connection' ] ); | |
| 27 | + add_action( 'wp_ajax_activate_license', array( $this, 'activate_license' ) ); | |
| 31 | 28 | } |
| 32 | 29 | } |
| 33 | 30 | |
| 34 | 31 | /** |
| 35 | - * Test and activate a new license. | |
| 32 | + * Firewall logs pagination. | |
| 36 | 33 | * |
| 37 | - * @return void | |
| 34 | + * @return array | |
| 38 | 35 | */ |
| 39 | - public function activate_license() { | |
| 40 | - if ( ! isset( $_POST['key'] ) || strpos( $_POST['key'], '-' ) === false) { | |
| 41 | - wp_send_json( | |
| 42 | - [ | |
| 43 | - 'result' => 'error', | |
| 44 | - 'error_message' => esc_attr__('An invalid API key was provided.', 'patchstack') | |
| 45 | - ] | |
| 46 | - ); | |
| 36 | + public function firewall_log_table() { | |
| 37 | + if ( ! isset( $_POST['start'], $_POST['length'] ) || !ctype_digit( $_POST['start'] ) || !ctype_digit( $_POST['length'] ) ) { | |
| 38 | + exit; | |
| 47 | 39 | } |
| 48 | 40 | |
| 49 | - // Since we have the keys combined into one now, split them up here. | |
| 50 | - $split = explode('-', $_POST['key']); | |
| 51 | - $secretkey = trim($split[0]); | |
| 52 | - $clientid = trim($split[1]); | |
| 41 | + // Pull all entries, given parameters. | |
| 42 | + global $wpdb; | |
| 43 | + $entries = $wpdb->get_results( | |
| 44 | + $wpdb->prepare( | |
| 45 | + "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 | |
| 46 | + FROM " . $wpdb->prefix . 'patchstack_firewall_log AS a | |
| 47 | + LEFT JOIN ' . $wpdb->prefix . 'patchstack_logic AS b ON b.id = a.fid | |
| 48 | + ORDER BY a.id DESC | |
| 49 | + LIMIT %d, %d | |
| 50 | + ', | |
| 51 | + array( wp_filter_nohtml_kses( $_POST['start'] ), wp_filter_nohtml_kses( $_POST['length'] ) ) | |
| 52 | + ) | |
| 53 | + ); | |
| 53 | 54 | |
| 54 | - // Test the new keys. | |
| 55 | - update_option( 'patchstack_api_token', '' ); | |
| 56 | - $results = $this->plugin->activation->alter_license( wp_filter_nohtml_kses( $clientid ), wp_filter_nohtml_kses( $secretkey ), 'activate' ); | |
| 57 | - if ( $results ) { | |
| 58 | - $response = $this->plugin->api->update_license_status(); | |
| 59 | - $results['response'] = $response; | |
| 60 | - wp_send_json( $results ); | |
| 55 | + // Get total amount of rows. | |
| 56 | + $count = $wpdb->get_var( 'SELECT COUNT(id) FROM ' . $wpdb->prefix . 'patchstack_firewall_log' ); | |
| 57 | + $firewall_rules = json_decode( get_option( 'patchstack_firewall_rules', '' ), true ); | |
| 58 | + | |
| 59 | + // Modify data if necessary. | |
| 60 | + $list = array(); | |
| 61 | + foreach ( $entries as $entry ) { | |
| 62 | + foreach ( $entry as $key => $value ) { | |
| 63 | + if ( ! in_array( $key, array( 'referer' ) ) ) { | |
| 64 | + $entry->$key = sanitize_textarea_field( $value ); | |
| 65 | + } | |
| 66 | + } | |
| 67 | + | |
| 68 | + // Attempt to find the block reason. | |
| 69 | + $reason = $wpdb->get_var( $wpdb->prepare( 'SELECT cname FROM ' . $wpdb->prefix . 'patchstack_logic WHERE id = %d LIMIT 1', array( $entry->fid ) ) ); | |
| 70 | + if ( $reason ) { | |
| 71 | + $entry->fid = $reason; | |
| 72 | + } elseif ( $firewall_rules != '' ) { | |
| 73 | + foreach ( $firewall_rules as $rule ) { | |
| 74 | + if ( isset( $rule['title'], $rule['cat'] ) && '55' . $rule['id'] == $entry->fid ) { | |
| 75 | + $entry->fid = $rule['cat']; | |
| 76 | + $entry->description = $rule['title']; | |
| 77 | + } | |
| 78 | + } | |
| 79 | + } else { | |
| 80 | + $entry->fid = 'Unknown'; | |
| 81 | + } | |
| 82 | + | |
| 83 | + $list[] = $entry; | |
| 61 | 84 | } |
| 85 | + | |
| 86 | + // Return output. | |
| 87 | + wp_send_json( | |
| 88 | + array( | |
| 89 | + 'data' => $list, | |
| 90 | + 'recordsFiltered' => $count, | |
| 91 | + 'recordsTotal' => $count | |
| 92 | + ) | |
| 93 | + ); | |
| 62 | 94 | } |
| 63 | 95 | |
| 64 | 96 | /** |
| 65 | - * Attempt to auto activate the license after a plugin activation, if no current license exists. | |
| 66 | - * | |
| 97 | + * Activity logs pagination. | |
| 98 | + * | |
| 67 | 99 | * @return void |
| 68 | 100 | */ |
| 69 | - public function auto_activate() { | |
| 70 | - $secretToken = get_option( 'patchstack_activation_secret', '' ); | |
| 101 | + public function users_log_table() { | |
| 102 | + if ( ! isset( $_POST['start'], $_POST['length'] ) || !ctype_digit( $_POST['start'] ) || !ctype_digit( $_POST['length'] ) ) { | |
| 103 | + exit; | |
| 104 | + } | |
| 71 | 105 | |
| 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 ); | |
| 106 | + // Determine if searching? | |
| 107 | + global $wpdb; | |
| 108 | + $searching = false; | |
| 109 | + $likes = array(); | |
| 110 | + if ( isset( $_POST['search'], $_POST['search']['value'] ) && $_POST['search']['value'] != '' ) { | |
| 111 | + $val = wp_filter_nohtml_kses( $_POST['search']['value'] ); | |
| 112 | + $searching = true; | |
| 113 | + $columns = array( 'author', 'ip', 'object', 'object_name', 'action' ); | |
| 114 | + $search = 'WHERE 1=2 '; | |
| 115 | + foreach ( $columns as $column ) { | |
| 116 | + array_push( $likes, '%' . $wpdb->esc_like( $val ) . '%' ); | |
| 117 | + $search .= 'OR ' . $column . ' LIKE %s'; | |
| 118 | + } | |
| 76 | 119 | } |
| 77 | 120 | |
| 78 | - wp_send_json( [ | |
| 79 | - 'result' => $autoActivated || get_option( 'patchstack_clientid', false ) != false ? 'success' : 'error' | |
| 80 | - ] ); | |
| 81 | - } | |
| 121 | + $logs = $wpdb->get_results( | |
| 122 | + $wpdb->prepare( | |
| 123 | + 'SELECT * | |
| 124 | + FROM ' . $wpdb->prefix . 'patchstack_event_log ' . ( $searching ? $search : '' ) . ' | |
| 125 | + ORDER BY id DESC | |
| 126 | + LIMIT %d, %d | |
| 127 | + ', | |
| 128 | + array_merge( $likes, array( wp_filter_nohtml_kses( $_POST['start'] ), wp_filter_nohtml_kses( $_POST['length'] ) ) ) | |
| 129 | + ) | |
| 130 | + ); | |
| 82 | 131 | |
| 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 | - ] ); | |
| 132 | + $count = $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(id) FROM ' . $wpdb->prefix . 'patchstack_event_log ' . ( $searching ? $search : '' ), $likes ) ); | |
| 133 | + | |
| 134 | + // Modify data if necessary. | |
| 135 | + $list = array(); | |
| 136 | + foreach ( $logs as $log ) { | |
| 137 | + $list[] = $log; | |
| 138 | + } | |
| 139 | + | |
| 140 | + // Return output. | |
| 141 | + wp_send_json( | |
| 142 | + array( | |
| 143 | + 'data' => $list, | |
| 144 | + 'recordsFiltered' => $count, | |
| 145 | + 'recordsTotal' => $count | |
| 146 | + ) | |
| 147 | + ); | |
| 92 | 148 | } |
| 93 | 149 | |
| 94 | 150 | /** |
| 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. | |
| 151 | + * Test and activate a new license. | |
| 98 | 152 | * |
| 99 | 153 | * @return void |
| 100 | 154 | */ |
| 101 | - public function check_connection() { | |
| 102 | - $this->plugin->api->update_license_status(); | |
| 155 | + public function activate_license() { | |
| 156 | + if ( ! isset( $_POST['clientid'], $_POST['secretkey'] ) || !ctype_digit( $_POST['clientid'] ) ) { | |
| 157 | + return; | |
| 158 | + } | |
| 103 | 159 | |
| 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 | - ); | |
| 160 | + // Test the new keys. | |
| 161 | + update_option( 'patchstack_api_token', '' ); | |
| 162 | + $results = $this->plugin->activation->alter_license( wp_filter_nohtml_kses( $_POST['clientid'] ), wp_filter_nohtml_kses( $_POST['secretkey'] ), 'activate' ); | |
| 163 | + if ( $results ) { | |
| 164 | + $response = $this->plugin->api->update_license_status(); | |
| 165 | + $results['response'] = $response; | |
| 166 | + wp_send_json( $results ); | |
| 167 | + } | |
| 113 | 168 | } |
| 114 | 169 | } |