← All changes
|
core/appointment/controllers/appointment-controller.php
+40
-0
1.0.26
→
1.0.28
View file →
| @@ -392,9 +392,14 @@ | ||
| 392 | 392 | // Remove user_email from team data to protect privacy |
| 393 | 393 | $team_member_data->user_email = ''; |
| 394 | 394 | } |
| 395 | 395 | } |
| 396 | + | |
| 397 | + // Never hand the cancel/reschedule credential to a customer | |
| 398 | + // through the list feed; it is delivered only via e-mail links. | |
| 399 | + $appointment->security_token = ''; | |
| 396 | 400 | } |
| 401 | + unset( $appointment ); | |
| 397 | 402 | } |
| 398 | 403 | |
| 399 | 404 | if ( ! $data ) { |
| 400 | 405 | return $this->error( __( 'No appointment found', 'booktics' ), 404 ); |
| @@ -542,8 +547,35 @@ | ||
| 542 | 547 | } |
| 543 | 548 | |
| 544 | 549 | $args = apply_filters( 'booktics_appointment_args', $args ); |
| 545 | 550 | |
| 551 | + // Scope to the caller's own appointments when they are not an | |
| 552 | + // admin/team-member. The calendar route is open to any logged-in user, | |
| 553 | + // so without this a plain customer would read every booking on the | |
| 554 | + // site. Mirrors the scoping already enforced in get_items(). | |
| 555 | + $scope_to_customer = ! booktics_is_admin_or_team_member() && is_user_logged_in(); | |
| 556 | + if ( $scope_to_customer ) { | |
| 557 | + $db = new Booktics_Database(); | |
| 558 | + $guest = ( new Guest_Model( $db ) )->find( array( 'wp_user_id' => get_current_user_id() ) ); | |
| 559 | + if ( ! $guest ) { | |
| 560 | + return $this->response( | |
| 561 | + array( | |
| 562 | + 'month' => gmdate( 'Y-m', strtotime( $month ) ), | |
| 563 | + 'date_range' => array( | |
| 564 | + 'start' => $adjusted_start_date, | |
| 565 | + 'end' => $adjusted_end_date, | |
| 566 | + ), | |
| 567 | + 'appointments' => array(), | |
| 568 | + ), __( 'Calendar appointments retrieved successfully', 'booktics' ) | |
| 569 | + ); | |
| 570 | + } | |
| 571 | + $args['meta_query'][] = array( | |
| 572 | + 'key' => 'customer_id', | |
| 573 | + 'value' => $guest->id, | |
| 574 | + 'compare' => '=', | |
| 575 | + ); | |
| 576 | + } | |
| 577 | + | |
| 546 | 578 | $appointments = Appointment_Model::paginate( $per_page, $paged, $args ); |
| 547 | 579 | |
| 548 | 580 | // Format the response |
| 549 | 581 | $formatted_appointments = array(); |
| @@ -551,8 +583,16 @@ | ||
| 551 | 583 | if ( ! empty( $appointments ) ) { |
| 552 | 584 | foreach ( $appointments['items'] as $appointment ) { |
| 553 | 585 | if ( ! empty( $appointment ) ) { |
| 554 | 586 | $appointment->source = 'booktics'; |
| 587 | + | |
| 588 | + // The per-appointment security token is the credential that | |
| 589 | + // authorises cancel/reschedule. Customers receive it only | |
| 590 | + // through their e-mailed links, never through this feed, so | |
| 591 | + // strip it from any non-admin response. | |
| 592 | + if ( $scope_to_customer ) { | |
| 593 | + $appointment->security_token = ''; | |
| 594 | + } | |
| 555 | 595 | } |
| 556 | 596 | |
| 557 | 597 | $formatted_appointments[] = $appointment; |
| 558 | 598 | } |