PluginProbe
Sendy / trunk
Sendy vtrunk
3.4.6 3.4.7 trunk 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 All 32 releases
sendy / lib / Modules / OAuth.php

OAuth.php in Sendy trunk, at lib/Modules/OAuth.php

106 lines 3.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Sendy\WooCommerce\Modules;
4
5 use Sendy\Api\Exceptions\SendyException;
6 use Sendy\WooCommerce\ApiClientFactory;
7
8 class OAuth
9 {
10 public function __construct()
11 {
12 add_action('admin_init', [$this, 'initialize_credentials']);
13 add_action('admin_init', [$this, 'oauth_callback']);
14
15 add_action('update_option_sendy_access_token', [$this, 'reset_credentials_when_access_token_nullified'], 10, 3);
16 }
17
18 /**
19 * Initialize the OAuth credentials
20 */
21 public function initialize_credentials(): void
22 {
23 if (get_option('sendy_client_id') == '') {
24 update_option('sendy_client_id', wp_generate_uuid4());
25 update_option('sendy_client_secret', wp_generate_password(40, false), false);
26 update_option('sendy_hostname', get_site_url());
27
28 return;
29 }
30
31 // Regenerate secrets that contain characters requiring URL-encoding.
32 // Such characters (e.g. #, %) break the OAuth URL even when percent-encoded,
33 // because WordPress's esc_url() can revert %23 to # which browsers treat as a fragment separator.
34 $secret = get_option('sendy_client_secret');
35 if ($secret !== false && $secret !== '' && ! sendy_is_authenticated() && rawurlencode($secret) !== $secret) {
36 update_option('sendy_client_secret', wp_generate_password(40, false), false);
37 }
38 }
39
40 /**
41 * Reset the credentials when the access token is nullified
42 *
43 * When the domain of the site changed, the id/secret pair will be reset because the redirect URI for the OAuth
44 * connection will be changed as well. In that case the user will need to re-authenticate with the application.
45 *
46 * Otherwise, the user will be able to start the authentication flow with the existing id/secret pair.
47 *
48 * @param string $option The name of the updated option
49 * @param mixed $old_value The old option value
50 * @param mixed $value The new option value
51 */
52 public function reset_credentials_when_access_token_nullified($old_value, $value, string $option): void
53 {
54 if (! is_null($value)) {
55 return;
56 }
57
58 if (get_option('sendy_hostname') != get_site_url()) {
59 update_option('sendy_client_id', wp_generate_uuid4());
60 update_option('sendy_client_secret', wp_generate_password(40, false), false);
61 update_option('sendy_hostname', get_site_url());
62
63 update_option('sendy_refresh_token', null, false);
64 update_option('sendy_token_expires', null, false);
65
66 delete_option('sendy_webhook_secret');
67 }
68 }
69
70 /**
71 * Handle the OAuth callback
72 */
73 public function oauth_callback(): void
74 {
75 if (isset($_GET['sendy_oauth_callback'])) {
76 if (! current_user_can('manage_woocommerce')) {
77 wp_die('You do not have sufficient permissions to access this page.');
78 }
79
80 if (! isset($_GET['state']) || ! wp_verify_nonce(sanitize_key($_GET['state']), 'sendy_oauth_callback_nonce')) {
81 wp_die('Nonce verification failed.');
82 }
83
84 if (! isset($_GET['code'])) {
85 wp_die('Missing code parameter in the URL');
86 }
87
88 try {
89 ApiClientFactory::buildConnectionUsingCode(sanitize_key($_GET['code']))->checkOrAcquireAccessToken();
90
91 Webhooks::regenerateWebhookSecret();
92
93 sendy_flash_admin_notice('success', __('Authentication successful', 'sendy'));
94
95 wp_safe_redirect(admin_url('admin.php?page=sendy'));
96 } catch (SendyException $e) {
97 sendy_flash_admin_notice('warning', __('Authentication failed. Please try again', 'sendy'));
98
99 wp_safe_redirect(admin_url('admin.php?page=sendy'));
100 } finally {
101 exit;
102 }
103 }
104 }
105 }
106