PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.2.0
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.2.0
2.5.0 2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 All 34 releases
fluent-booking / app / Http / Policies / MeetingPolicy.php

MeetingPolicy.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 2.2.0, at app/Http/Policies/MeetingPolicy.php

163 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBooking\App\Http\Policies;
4
5 use FluentBooking\App\Models\Booking;
6 use FluentBooking\App\Models\CalendarSlot;
7 use FluentBooking\App\Services\PermissionManager;
8 use FluentBooking\Framework\Http\Request\Request;
9 use FluentBooking\Framework\Foundation\Policy;
10
11 class MeetingPolicy extends Policy
12 {
13 /**
14 * Check user permission for any method
15 * @param \FluentBooking\Framework\Http\Request\Request $request
16 * @return Boolean
17 */
18 public function verifyRequest(Request $request)
19 {
20 if (PermissionManager::userCan(['manage_all_bookings', 'manage_all_data'])) {
21 return true;
22 }
23
24 // Authorize only against the URL route parameter so request-body
25 // values cannot override the resource being acted on.
26 $bookingId = $this->getRouteBookingId($request);
27
28 if ($request->method() == 'GET') {
29 if (PermissionManager::userCan(['manage_own_calendar','read_all_bookings'])) {
30 return true;
31 }
32
33 if ($bookingId) {
34 $booking = Booking::find($bookingId);
35 return $this->hasBookingAccess($booking);
36 }
37 }
38
39 if ($bookingId) {
40 $booking = Booking::find($bookingId);
41 return $this->hasBookingAccess($booking);
42 }
43
44 return false;
45 }
46
47 public function getGroupAttendees(Request $request)
48 {
49 if (current_user_can('manage_options')) {
50 return true;
51 }
52
53 if (PermissionManager::userCanSeeAllBookings()) {
54 return true;
55 }
56
57 $groupId = $this->getRouteParam($request, 'group_id');
58
59 if (!$groupId) {
60 return false;
61 }
62
63 $booking = Booking::where('group_id', $groupId)->first();
64
65 return $this->hasBookingAccess($booking);
66 }
67
68 public function getBookingActivities(Request $request)
69 {
70 return $this->authorizeBookingAccess($request);
71 }
72
73 public function getBookingMetaInfo(Request $request)
74 {
75 return $this->authorizeBookingAccess($request);
76 }
77
78 public function getCrmContact(Request $request)
79 {
80 return $this->authorizeBookingAccess($request);
81 }
82
83 public function getCrmOptions(Request $request)
84 {
85 return $this->authorizeBookingAccess($request);
86 }
87
88 // State-changing: use verifyRequest so read-only roles (read_all_bookings)
89 // cannot mutate CRM data; only host access or manage_all_* passes for POST.
90 public function updateCrmTags(Request $request)
91 {
92 return $this->verifyRequest($request);
93 }
94
95 public function updateCrmLists(Request $request)
96 {
97 return $this->verifyRequest($request);
98 }
99
100 private function authorizeBookingAccess(Request $request)
101 {
102 if (PermissionManager::userCan(['manage_all_bookings', 'manage_all_data', 'read_all_bookings'])) {
103 return true;
104 }
105
106 $bookingId = $this->getRouteBookingId($request);
107
108 if (!$bookingId) {
109 return false;
110 }
111
112 $booking = Booking::find($bookingId);
113
114 return $this->hasBookingAccess($booking);
115 }
116
117 /**
118 * Resolve the booking ID from the URL route parameter only.
119 *
120 * Why: merged request inputs let JSON body values shadow URL params,
121 * which previously allowed authorizing against an attacker-owned ID
122 * while the controller acted on the URL-targeted victim ID.
123 */
124 private function getRouteBookingId(Request $request)
125 {
126 return $this->getRouteParam($request, 'id');
127 }
128
129 /**
130 * Read a URL-only route parameter safely. Routes such as /schedules/
131 * and /schedules/export have no path placeholders, so a direct
132 * access would emit an undefined-array-key warning under PHP 8.
133 */
134 private function getRouteParam(Request $request, $key)
135 {
136 $params = (array) $request->get_url_params();
137 return isset($params[$key]) ? $params[$key] : null;
138 }
139
140 private function hasBookingAccess($booking)
141 {
142 if (!$booking) {
143 return false;
144 }
145
146 $userId = get_current_user_id();
147 if (in_array($userId, $booking->getHostIds())) {
148 return true;
149 }
150
151 if (!PermissionManager::userCan('manage_own_calendar')) {
152 return false;
153 }
154
155 $calendarEvent = CalendarSlot::find($booking->event_id);
156 if (!$calendarEvent) {
157 return false;
158 }
159
160 return in_array($userId, $calendarEvent->getHostIds());
161 }
162 }
163