PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.8
Booking for Appointments and Events Calendar – Amelia v2.4.8
2.4.9 2.4.8 2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / src / Application / Commands / Command.php
ameliabooking / src / Application / Commands Last commit date
Bookable 1 month ago Booking 1 week ago Calendar 2 weeks ago Entities 2 weeks ago Google 5 months ago Import 1 week ago Mobile 2 months ago Notification 2 months ago Payment 1 week ago QrCode 2 weeks ago Settings 1 week ago Square 1 week ago Stash 2 weeks ago Stats 7 months ago Test 7 months ago User 1 week ago WhatsNew 5 months ago Command.php 1 week ago CommandHandler.php 1 week ago CommandResult.php 6 months ago SortParamsTrait.php 5 months ago
Command.php
394 lines
1 <?php
2
3 namespace AmeliaBooking\Application\Commands;
4
5 use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException;
6 use AmeliaBooking\Application\Commands\Booking\Appointment\AddBookingCommand;
7 use AmeliaBooking\Application\Commands\Booking\Appointment\DeleteBookingRemotelyCommand;
8 use AmeliaBooking\Application\Commands\Notification\SendUndeliveredNotificationsCommand;
9 use AmeliaBooking\Application\Commands\Notification\UpdateSMSNotificationHistoryCommand;
10 use AmeliaBooking\Application\Commands\Outlook\FetchAccessTokenWithAuthCodeOutlookCommand;
11 use AmeliaBooking\Application\Commands\Payment\CalculatePaymentAmountCommand;
12 use AmeliaBooking\Application\Commands\PaymentGateway\RazorpayPaymentNotifyCommand;
13 use AmeliaBooking\Application\Commands\Square\DisconnectFromSquareAccountCommand;
14 use AmeliaBooking\Application\Commands\Square\SquareRefundWebhookCommand;
15 use AmeliaBooking\Application\Services\User\UserApplicationService;
16 use AmeliaBooking\Domain\Entity\Entities;
17 use AmeliaBooking\Domain\Entity\User\AbstractUser;
18 use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException;
19 use AmeliaBooking\Domain\Services\Permissions\PermissionsService;
20 use AmeliaBooking\Domain\Services\Settings\SettingsService;
21 use AmeliaBooking\Infrastructure\WP\SettingsService\SettingsStorage;
22 use AmeliaVendor\Psr\Http\Message\ServerRequestInterface as Request;
23
24 /**
25 * Class Command
26 *
27 * @package AmeliaBooking\Application\Commands
28 */
29 abstract class Command
30 {
31 protected $args;
32
33 protected $container;
34
35 private $fields = [];
36
37 public $token;
38
39 private $page;
40
41 private $cabinetType;
42
43 private $permissionService;
44
45 private $userApplicationService;
46
47 /**
48 * Command constructor.
49 *
50 * @param $args
51 */
52 public function __construct($args)
53 {
54 $this->args = $args;
55 if (isset($args['type'])) {
56 $this->setField('type', $args['type']);
57 }
58 }
59
60 /**
61 * @return mixed
62 */
63 public function getArgs()
64 {
65 return $this->args;
66 }
67
68 /**
69 * @param mixed $arg Argument to be fetched
70 *
71 * @return null|mixed
72 */
73 public function getArg($arg)
74 {
75 return isset($this->args[$arg]) ? $this->args[$arg] : null;
76 }
77
78 /**
79 * @param $fieldName
80 * @param $fieldValue
81 */
82 public function setField($fieldName, $fieldValue)
83 {
84 $this->fields[$fieldName] = $fieldValue;
85 }
86
87 /**
88 * @param $fieldName
89 */
90 public function removeField($fieldName)
91 {
92 unset($this->fields[$fieldName]);
93 }
94
95 /**
96 * Return a single field
97 *
98 * @param $fieldName
99 *
100 * @return mixed|null
101 */
102 public function getField($fieldName)
103 {
104 return isset($this->fields[$fieldName]) ? $this->fields[$fieldName] : null;
105 }
106
107 /**
108 * Return all fields
109 *
110 * @return array
111 */
112 public function getFields()
113 {
114 return $this->fields;
115 }
116
117 /**
118 * Set Token
119 *
120 * @param Request $request
121 */
122 public function setToken($request): void
123 {
124 $token = null;
125
126 /** @var SettingsService $settingsService */
127 $settingsService = new SettingsService(new SettingsStorage());
128
129 $authorization = $request->getHeaderLine('Authorization');
130
131 if (
132 $authorization !== '' &&
133 ($values = explode(' ', $authorization)) &&
134 sizeof($values) === 2 &&
135 strcasecmp($values[0], 'Bearer') === 0 &&
136 $settingsService->getSetting('roles', 'enabledHttpAuthorization')
137 ) {
138 $token = $values[1];
139 } else {
140 $cookies = $request->getCookieParams();
141 if (!empty($cookies['ameliaToken'])) {
142 $token = $cookies['ameliaToken'];
143 }
144 }
145
146 $this->token = $token;
147 }
148
149 /**
150 * Return Token
151 *
152 * @return string|null
153 */
154 public function getToken()
155 {
156 return $this->token;
157 }
158
159 /**
160 * Set page
161 *
162 * @param string $page
163 */
164 public function setPage($page)
165 {
166 $this->page = explode('-', $page)[0];
167
168 $this->cabinetType = !empty(explode('-', $page)[1]) ? explode('-', $page)[1] : null;
169 }
170
171 /**
172 * Return page
173 *
174 * @return string|null
175 */
176 public function getPage()
177 {
178 return $this->page;
179 }
180
181 /**
182 * @param $request
183 * @return bool
184 */
185 public function validateNonce($request): bool
186 {
187 if (
188 $request->getMethod() === 'POST' &&
189 !self::getToken() &&
190 !($this instanceof CalculatePaymentAmountCommand) &&
191 !($this instanceof AddBookingCommand) &&
192 !($this instanceof DeleteBookingRemotelyCommand) &&
193 !($this instanceof RazorpayPaymentNotifyCommand) &&
194 !($this instanceof SquareRefundWebhookCommand) &&
195 !($this instanceof DisconnectFromSquareAccountCommand) &&
196 !($this instanceof FetchAccessTokenWithAuthCodeOutlookCommand) &&
197 !($this instanceof UpdateSMSNotificationHistoryCommand)
198 ) {
199 $queryParams = $request->getQueryParams();
200 $nonce = !empty($queryParams['wpAmeliaNonce'])
201 ? $queryParams['wpAmeliaNonce']
202 : ($queryParams['ameliaNonce'] ?? '');
203
204 return (bool) wp_verify_nonce(
205 $nonce,
206 'ajax-nonce'
207 );
208 }
209
210 return true;
211 }
212
213 /**
214 * Commands listed here are meant to be run from an external cron job, so they are reached with a GET request that
215 * carries neither a nonce nor a logged in user. They are protected with a secret key, generated per site and
216 * stored in the "activation" settings, that has to be passed as a "cronKey" query parameter.
217 *
218 * @param $request
219 * @return boolean
220 */
221 public function validateCron($request)
222 {
223 if (!($this instanceof SendUndeliveredNotificationsCommand)) {
224 return true;
225 }
226
227 $settingsService = new SettingsService(new SettingsStorage());
228
229 $cronKey = $settingsService->getSetting('activation', 'cronKey');
230
231 if (empty($cronKey)) {
232 return false;
233 }
234
235 $queryParams = $request->getQueryParams();
236
237 $givenKey = !empty($queryParams['cronKey']) ? $queryParams['cronKey'] : '';
238
239 return is_string($givenKey) && hash_equals((string)$cronKey, $givenKey);
240 }
241
242 /**
243 * Return cabinet type
244 *
245 * @return string|null
246 */
247 public function getCabinetType()
248 {
249 return $this->cabinetType;
250 }
251
252 /**
253 * @return PermissionsService
254 */
255 public function getPermissionService()
256 {
257 return $this->permissionService;
258 }
259
260 /**
261 * @param PermissionsService $permissionService
262 */
263 public function setPermissionService($permissionService)
264 {
265 $this->permissionService = $permissionService;
266 }
267
268 /**
269 * @return UserApplicationService
270 */
271 public function getUserApplicationService()
272 {
273 return $this->userApplicationService;
274 }
275
276 /**
277 * @param UserApplicationService $userApplicationService
278 */
279 public function setUserApplicationService($userApplicationService)
280 {
281 $this->userApplicationService = $userApplicationService;
282 }
283
284 /**
285 * Authorize user
286 *
287 * @return AbstractUser
288 * @throws AuthorizationException
289 * @throws AccessDeniedException
290 */
291 public function authorize($type = null): AbstractUser
292 {
293 if ($type === AbstractUser::USER_ROLE_PROVIDER || $type === AbstractUser::USER_ROLE_CUSTOMER) {
294 /** @var AbstractUser $user */
295 $user = $this->getUserApplicationService()->authorization(
296 $this->getToken(),
297 $type
298 );
299
300 // If user is admin or manager, return user
301 if (
302 $user && (
303 $user->getType() === AbstractUser::USER_ROLE_ADMIN ||
304 $user->getType() === AbstractUser::USER_ROLE_MANAGER
305 )
306 ) {
307 return $user;
308 }
309
310 // If user is not admin or manager, check if user is of the given type
311 if (!$user || $user->getType() !== $type) {
312 throw new AccessDeniedException('You are not allowed');
313 }
314
315 return $user;
316 }
317
318 return $this->getUserApplicationService()->authorization(
319 $this->getPage() === 'cabinet' ? $this->getToken() : null,
320 $this->getCabinetType()
321 );
322 }
323
324 /**
325 * Authorize provider read permission
326 *
327 * @param int $userId
328 * @param string $entity
329 *
330 * @return AbstractUser
331 *
332 * @throws AuthorizationException
333 * @throws AccessDeniedException
334 */
335 public function authorizeProviderReadPermission(int $userId, string $entity = Entities::EMPLOYEES): AbstractUser
336 {
337 // if logged in user is not WP admin, WP Amelia manager or WP Amelia provider, try to authorize as non WP Amelia provider
338 if (
339 !$this->getPermissionService()->currentUserCanRead($entity) ||
340 !$this->getPermissionService()->currentUserCanReadOthers($entity)
341 ) {
342 /** @var AbstractUser $user */
343 $user = $this->authorize(Entities::PROVIDER);
344
345 // if authorized as non WP Amelia provider, check if user ID is the same as the requested user ID
346 if (
347 $user->getType() === AbstractUser::USER_ROLE_PROVIDER &&
348 $user->getId()->getValue() !== $userId
349 ) {
350 throw new AccessDeniedException('You are not allowed');
351 }
352
353 return $user;
354 }
355
356 return $this->getUserApplicationService()->authorization(null, null);
357 }
358
359 /**
360 * Authorize provider write permission
361 *
362 * @param int $userId
363 * @param string $entity
364 *
365 * @return AbstractUser
366 *
367 * @throws AuthorizationException
368 * @throws AccessDeniedException
369 */
370 public function authorizeProviderWritePermission(int $userId, string $entity = Entities::EMPLOYEES): AbstractUser
371 {
372 // if logged in user is not WP admin, WP Amelia manager or WP Amelia provider, try to authorize as non WP Amelia provider
373 if (
374 !$this->getPermissionService()->currentUserCanWrite($entity) ||
375 !$this->getPermissionService()->currentUserCanWriteOthers($entity)
376 ) {
377 /** @var AbstractUser $user */
378 $user = $this->authorize(Entities::PROVIDER);
379
380 // if authorized as non WP Amelia provider, check if user ID is the same as the requested user ID
381 if (
382 $user->getType() === AbstractUser::USER_ROLE_PROVIDER &&
383 $user->getId()->getValue() !== $userId
384 ) {
385 throw new AccessDeniedException('You are not allowed');
386 }
387
388 return $user;
389 }
390
391 return $this->getUserApplicationService()->authorization(null, null);
392 }
393 }
394