PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 2.7.0
Tutor LMS – eLearning and online course solution v2.7.0
3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / restapi / RestAuth.php
tutor / restapi Last commit date
REST_Author.php 2 years ago REST_Course.php 2 years ago REST_Course_Announcement.php 2 years ago REST_Lesson.php 2 years ago REST_Quiz.php 2 years ago REST_Rating.php 2 years ago REST_Response.php 2 years ago REST_Topic.php 2 years ago RestAuth.php 2 years ago
RestAuth.php
359 lines
1 <?php
2 /**
3 * Manage Rest API Authentication
4 *
5 * API key, secret create, invoke etc
6 *
7 * @package Tutor
8 * @author Themeum <support@themeum.com>
9 * @link https://themeum.com
10 * @since 2.2.1
11 */
12
13 namespace TUTOR;
14
15 use Tutor\Helpers\QueryHelper;
16
17 if ( ! defined( 'ABSPATH' ) ) {
18 exit;
19 }
20
21 /**
22 * Rest API authentication
23 *
24 * @since 2.2.1
25 */
26 class RestAuth {
27
28 /**
29 * Read Permissions
30 *
31 * @var string
32 */
33 const READ = 'Read';
34
35 /**
36 * Write Permissions
37 *
38 * @var string
39 */
40 const WRITE = 'Write';
41
42 /**
43 * Delete Permissions
44 *
45 * @var string
46 */
47 const DELETE = 'Delete';
48
49 /**
50 * Read Write Permissions
51 *
52 * @var string
53 */
54 const READ_WRITE = 'Read/Write';
55
56 /**
57 * All Permissions
58 *
59 * @var string
60 */
61 const ALL = 'All';
62
63 /**
64 * User meta key to store key, secret, permission info
65 *
66 * @var string
67 */
68 const KEYS_USER_META_KEY = 'tutor-api-key-secret';
69
70 /**
71 * Register hooks.
72 *
73 * @since 2.2.1
74 *
75 * @return void
76 */
77 public function __construct() {
78 add_action( 'wp_ajax_tutor_generate_api_keys', __CLASS__ . '::generate_api_keys' );
79 add_action( 'wp_ajax_tutor_update_api_permission', __CLASS__ . '::update_api_permission' );
80 add_action( 'wp_ajax_tutor_revoke_api_keys', __CLASS__ . '::revoke_api_keys' );
81 }
82
83 /**
84 * Generate api keys
85 *
86 * @since 2.2.1
87 *
88 * @return void send wp_json response
89 */
90 public static function generate_api_keys() {
91 // Validate nonce.
92 tutor_utils()->checking_nonce();
93
94 // Check user permission.
95 if ( ! current_user_can( 'administrator' ) ) {
96 wp_send_json_error( tutor_utils()->error_message() );
97 }
98
99 $api_key = 'key_' . bin2hex( random_bytes( 16 ) );
100 $api_secret = 'secret_' . bin2hex( random_bytes( 32 ) );
101
102 $permission = Input::post( 'permission' );
103 $description = Input::post( 'description', '', Input::TYPE_TEXTAREA );
104
105 $info = wp_json_encode(
106 array(
107 'key' => $api_key,
108 'secret' => $api_secret,
109 'permission' => $permission,
110 'description' => $description,
111 )
112 );
113
114 // Update user meta.
115 $add = add_user_meta(
116 get_current_user_id(),
117 self::KEYS_USER_META_KEY,
118 $info
119 );
120
121 if ( $add ) {
122 $response = self::prepare_response( $add, $api_key, $api_secret, $permission, $description );
123 wp_send_json_success( $response );
124 } else {
125 wp_send_json_error( tutor_utils()->error_message( '0' ) );
126 }
127
128 }
129
130
131 /**
132 * Update api permission
133 *
134 * @since 2.5.0
135 *
136 * @return void send wp_json response
137 */
138 public static function update_api_permission() {
139 global $wpdb;
140
141 // Validate nonce.
142 tutor_utils()->checking_nonce();
143
144 // Check user permission.
145 if ( ! current_user_can( 'administrator' ) ) {
146 wp_send_json_error( tutor_utils()->error_message() );
147 }
148
149 $meta_id = Input::post( 'meta_id', 0, Input::TYPE_INT );
150 $permission = Input::post( 'permission' );
151 $description = Input::post( 'description', '', Input::TYPE_TEXTAREA );
152
153 $info = QueryHelper::get_row( $wpdb->usermeta, array( 'umeta_id' => $meta_id ), 'umeta_id' );
154 $meta_value = json_decode( $info->meta_value );
155
156 $meta_value->permission = $permission;
157 $meta_value->description = $description;
158
159 // Update user meta.
160 try {
161 QueryHelper::update(
162 $wpdb->usermeta,
163 array( 'meta_value' => json_encode( $meta_value ) ),
164 array( 'umeta_id' => $meta_id )
165 );
166
167 $response = self::prepare_response( $meta_id, $meta_value->key, $meta_value->secret, $permission, $description );
168 wp_send_json_success( $response );
169
170 } catch ( \Throwable $th ) {
171 wp_send_json_error( $th->getMessage() );
172 }
173 }
174
175 /**
176 * Revoke api keys
177 *
178 * @since 2.2.1
179 *
180 * @return void send wp_json response
181 */
182 public static function revoke_api_keys() {
183 // Validate nonce.
184 tutor_utils()->checking_nonce();
185
186 // Check user permission.
187 if ( ! current_user_can( 'administrator' ) ) {
188 wp_send_json_error( tutor_utils()->error_message() );
189 }
190
191 $meta_id = Input::post( 'meta_id', 0, Input::TYPE_INT );
192
193 if ( ! $meta_id ) {
194 wp_send_json_error( __( 'Invalid meta id', 'tutor' ) );
195 }
196
197 // Delete api keys.
198 global $wpdb;
199 $delete = QueryHelper::delete( $wpdb->usermeta, array( 'umeta_id' => $meta_id ) );
200
201 if ( $delete ) {
202 wp_send_json_success( __( 'API keys permanently revoked', 'tutor' ) );
203 } else {
204 wp_send_json_error( __( 'API keys revoke failed, please try again.', 'tutor' ) );
205 }
206 }
207
208 /**
209 * Check if api key & secret is valid
210 *
211 * @since 2.2.1
212 *
213 * @param string $api_key api key.
214 * @param string $api_secret api secret.
215 *
216 * @return boolean
217 */
218 public static function validate_api_key_secret( $api_key, $api_secret ) {
219 global $wpdb;
220 $table = $wpdb->usermeta;
221
222 $valid = false;
223
224 $results = QueryHelper::get_all(
225 $table,
226 array( 'meta_key' => self::KEYS_USER_META_KEY ), //phpcs:ignore
227 'umeta_id'
228 );
229
230 if ( is_array( $results ) && count( $results ) ) {
231 foreach ( $results as $result ) {
232 $result = json_decode( $result->meta_value );
233 if ( $result->key === $api_key && $result->secret === $api_secret ) {
234 $valid = true;
235 break;
236 }
237 }
238 }
239
240 return $valid;
241 }
242
243 /**
244 * Process api request
245 *
246 * @since 2.2.1
247 *
248 * @return boolean
249 */
250 public static function process_api_request() {
251 $headers = apache_request_headers();
252
253 if ( isset( $headers['Authorization'] ) ) {
254 $authorization_header = $headers['Authorization'];
255
256 if ( strpos( $authorization_header, 'Basic' ) !== false ) {
257 $base_64_credentials = str_replace( 'Basic ', '', $authorization_header );
258 $credentials = base64_decode( $base_64_credentials ); //phpcs:ignore
259
260 list($api_key, $api_secret) = explode( ':', $credentials );
261
262 if ( self::validate_api_key_secret( $api_key, $api_secret ) ) {
263 return true;
264 }
265 }
266 }
267
268 // Key and secret are invalid or not provided.
269 return false;
270 }
271
272 /**
273 * Prepare html response
274 *
275 * @since 2.2.1
276 *
277 * @param int $meta_id meta id.
278 * @param string $key api key.
279 * @param string $secret api secret.
280 * @param string $permission authorization permission.
281 * @param string $description description.
282 *
283 * @return string
284 */
285 public static function prepare_response( $meta_id, $key, $secret, $permission, $description = '' ) {
286 $user_id = get_current_user_id();
287 ob_start();
288 ?>
289 <tr id="<?php echo esc_attr( $meta_id ); ?>">
290 <td>
291 <?php echo esc_html( tutor_utils()->display_name( $user_id ) ); ?>
292 </td>
293 <td>
294 <a class="tutor-btn tutor-btn-outline-primary tutor-btn-sm">
295 <span class="tutor-icon-copy tutor-mr-8"></span>
296 <span class="tutor-copy-text" data-text="<?php echo esc_attr( $key ); ?>">
297 <?php echo esc_html( substr( $key, 0, 5 ) . '...' ); ?>
298 </span>
299 </a>
300 </td>
301 <td>
302 <a class="tutor-btn tutor-btn-outline-primary tutor-btn-sm">
303 <span class="tutor-icon-copy tutor-mr-8"></span>
304 <span class="tutor-copy-text" data-text="<?php echo esc_attr( $secret ); ?>">
305 <?php echo esc_html( substr( $secret, 0, 9 ) . '...' ); ?>
306 </span>
307 </a>
308 </td>
309 <td>
310 <?php echo esc_html( $permission ); ?>
311 <?php if ( ! empty( $description ) ) : ?>
312 <div class="tooltip-wrap tooltip-icon-custom" >
313 <i class="tutor-fs-7 tutor-icon-circle-info-o tutor-color-muted tutor-ml-4"></i>
314 <span class="tooltip-txt tooltip-bottom">
315 <?php echo esc_textarea( $description ); ?>
316 </span>
317 </div>
318 <?php endif; ?>
319 </td>
320 <td>
321 <div class="tutor-dropdown-parent">
322 <button type="button" class="tutor-iconic-btn" action-tutor-dropdown="toggle">
323 <span class="tutor-icon-kebab-menu" area-hidden="true"></span>
324 </button>
325 <div class="tutor-dropdown tutor-dropdown-dark tutor-text-left">
326 <a href="javascript:void(0)" class="tutor-dropdown-item" data-tutor-modal-target="tutor-update-permission-modal" data-update-id="<?php echo esc_attr( $meta_id ); ?>" data-permission="<?php echo esc_attr( $permission ); ?>" data-description="<?php echo esc_attr( $description ); ?>">
327 <i class="tutor-icon-edit tutor-mr-8" area-hidden="true" data-update-id="<?php echo esc_attr( $meta_id ); ?>" data-permission="<?php echo esc_attr( $permission ); ?>" data-description="<?php echo esc_attr( $description ); ?>"></i>
328 <span data-update-id="<?php echo esc_attr( $meta_id ); ?>" data-permission="<?php echo esc_attr( $permission ); ?>" data-description="<?php echo esc_attr( $description ); ?>"><?php esc_html_e( 'Edit', 'tutor' ); ?></span>
329 </a>
330 <a href="javascript:void(0)" class="tutor-dropdown-item" data-meta-id="<?php echo esc_attr( $meta_id ); ?>">
331 <i class="tutor-icon-trash-can-bold tutor-mr-8" area-hidden="true" data-meta-id="<?php echo esc_attr( $meta_id ); ?>"></i>
332 <span data-meta-id="<?php echo esc_attr( $meta_id ); ?>"><?php esc_html_e( 'Revoke', 'tutor' ); ?></span>
333 </a>
334 </div>
335 </div>
336 </td>
337 </tr>
338 <?php
339 return ob_get_clean();
340 }
341
342 /**
343 * Get available permission
344 *
345 * @since 2.2.1
346 *
347 * @return array
348 */
349 public static function available_permissions(): array {
350 $permissions = array(
351 array(
352 'value' => self::READ,
353 'label' => __( 'Read', 'tutor' ),
354 ),
355 );
356 return apply_filters( 'tutor_rest_api_permissions', $permissions );
357 }
358 }
359