PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 3.36
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v3.36
3.36 3.35 3.34 3.33 2.19 2.20 2.21 2.22 2.23 2.24 2.25 2.26 2.27 2.28 2.29 2.30 2.31 2.32 2.33 2.34 2.40 2.41 2.42 2.43 2.44 All 141 releases
photonic / Admin / Authentication.php

Authentication.php in Photonic Gallery & Lightbox for Flickr, SmugMug & Others 3.36, at Admin/Authentication.php

365 lines 16.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Photonic_Plugin\Admin;
4
5 if (!current_user_can('edit_theme_options')) {
6 wp_die(esc_html__('You are not authorized to use this capability.', 'photonic'));
7 }
8
9 use Photonic_Plugin\Core\Photonic;
10 use Photonic_Plugin\Platforms\Authenticator;
11 use Photonic_Plugin\Platforms\Base;
12 use Photonic_Plugin\Platforms\Flickr;
13 use Photonic_Plugin\Platforms\Google_Photos;
14 use Photonic_Plugin\Platforms\Instagram;
15 use Photonic_Plugin\Platforms\SmugMug;
16 use Photonic_Plugin\Platforms\Zenfolio;
17 use Photonic_Plugin\Platforms\DeviantArt;
18
19 require_once 'Admin_Page.php';
20
21 class Authentication extends Admin_Page {
22 private static ?Authentication $instance = null;
23
24 private function __construct() {
25 require_once PHOTONIC_PATH . '/Platforms/Zenfolio.php';
26 }
27
28 public static function get_instance() {
29 if (null === self::$instance) {
30 self::$instance = new Authentication();
31 }
32 return self::$instance;
33 }
34
35 public function render_content() {
36 ?>
37 <form method="post" id="photonic-auth-form">
38 <h2 id="#photonic-flickr-auth-section" class="photonic-section">Flickr</h2>
39 <?php $this->display_flickr(); ?>
40
41 <h2 id="#photonic-smugmug-auth-section" class="photonic-section">SmugMug</h2>
42 <?php $this->display_smugmug(); ?>
43
44 <h2 id="#photonic-zenfolio-auth-section" class="photonic-section">Zenfolio</h2>
45 <?php $this->display_zenfolio(); ?>
46
47 <!-- <h2 id="#photonic-deviantart-auth-section" class="photonic-section">DeviantArt</h2>
48 --><?php /*$this->display_deviantart(); */?>
49
50 </form>
51 <?php
52 }
53
54 private function display_flickr() {
55 global $photonic_flickr_api_key, $photonic_flickr_api_secret, $photonic_flickr_access_token;
56 $auth = [
57 'api_key' => trim($photonic_flickr_api_key),
58 'api_secret' => trim($photonic_flickr_api_secret),
59 'token' => trim($photonic_flickr_access_token),
60 ];
61 $this->show_token_section($auth, 'flickr', 'Flickr');
62 }
63
64 private function display_smugmug() {
65 global $photonic_smug_api_key, $photonic_smug_api_secret, $photonic_smug_access_token;
66 $auth = [
67 'api_key' => !empty($photonic_smug_api_key) ? trim($photonic_smug_api_key) : '86MZ8N8TqJf5x2fQ4FRWXRtJ3C6Jm7XV',
68 'api_secret' => trim($photonic_smug_api_secret),
69 'token' => trim($photonic_smug_access_token),
70 ];
71 $this->show_token_section($auth, 'smug', 'SmugMug');
72 }
73
74 private function display_zenfolio() {
75 global $photonic_zenfolio_default_user;
76 $gallery = Zenfolio::get_instance();
77
78 echo "<div class=\"photonic-token-header\">\n";
79 if (empty($photonic_zenfolio_default_user)) {
80 /* Translators: 1: Menu location, untranslated */
81 echo sprintf(esc_html__('Please set up the default user for Zenfolio under %s', 'photonic'), '<em>Photonic &rarr; Settings &rarr; Zenfolio &rarr; Zenfolio Photo Settings &rarr; Default User</em>') . "\n";
82 }
83 elseif (!empty($gallery->token)) {
84 $this->print_auth_done_all_good();
85 }
86 echo "</div>\n";
87
88 $response = Base::parse_parameters($_SERVER['QUERY_STRING'] ?? '');
89 if (!empty($photonic_zenfolio_default_user) && (empty($response['provider']) || 'zenfolio' !== $response['provider'])) {
90 echo '<label>' . esc_html__('Password:', 'photonic') . "<input type='password' name='zenfolio-password' id='zenfolio-password'></label>";
91 }
92
93 echo "<div style='display: block; width: 100%;'>\n";
94 if (!empty($photonic_zenfolio_default_user) && (empty($response['provider']) || 'zenfolio' !== $response['provider'])) {
95 $nonce = wp_create_nonce('zenfolio-save-token');
96 echo "<a href='#' class='button button-primary' data-photonic-provider='zenfolio' style='margin-right: 1em;' data-photonic-nonce='" . esc_attr($nonce) . "'>" . esc_html__('Login and Authenticate', 'photonic') . '</a>';
97 }
98
99 if (!empty($gallery->token)) {
100 $nonce = wp_create_nonce('zenfolio-delete-token');
101 echo "<a href='#' class='button button-primary photonic-zenfolio-delete' data-photonic-nonce='" . esc_attr($nonce) . "'>" . esc_html__('Delete current Zenfolio authentication data', 'photonic') . '</a>';
102 }
103 echo "</div>\n";
104
105 echo '<div class="result" id="zenfolio-result">&nbsp;</div>';
106 }
107
108 private function display_deviantart() {
109 global $photonic_deviantart_client_id, $photonic_deviantart_client_secret, $photonic_deviantart_refresh_token;
110
111 echo "<div class=\"photonic-token-header\">\n";
112
113 if (empty($photonic_deviantart_client_id) || empty($photonic_deviantart_client_secret)) {
114 echo sprintf(
115 /* Translators: 1: Location in menu, untranslated */
116 esc_html__('Please set up your DeviantArt Client ID and Client Secret under %s', 'photonic'),
117 '<em>Photonic &rarr; Settings &rarr; DeviantArt &rarr; DeviantArt Settings</em>'
118 );
119 }
120 else {
121 require_once PHOTONIC_PATH . '/Platforms/DeviantArt.php';
122
123 $parameters = Base::parse_parameters($_SERVER['QUERY_STRING'] ?? '');
124
125 if (!empty($photonic_deviantart_refresh_token)) {
126 $this->print_auth_done_all_good();
127 }
128
129 echo "</div>\n";
130 echo "<div class=\"photonic-token-header\">\n";
131 echo "<p>\n";
132 esc_html_e('You first have to authorize Photonic to connect to your DeviantArt account.', 'photonic');
133 echo "</p>\n";
134
135 if (!isset($parameters['code']) || !isset($parameters['source']) || 'deviantart' !== $parameters['source']) {
136 $url = add_query_arg('test', 'test');
137 $url = remove_query_arg('test', $url);
138 $parameters = [
139 'response_type' => 'code',
140 'client_id' => $photonic_deviantart_client_id,
141 'redirect_uri' => admin_url('admin.php?page=photonic-auth&source=deviantart'),
142 'scope' => 'basic browse',
143 'access_type' => 'offline',
144 'state' => md5($photonic_deviantart_client_secret . 'deviantart') . '::' . rawurlencode($url),
145 'prompt' => 'consent',
146 ];
147 $url = 'https://www.deviantart.com/oauth2/authorize?' . DeviantArt::build_query($parameters);
148
149 echo "<a href='" . esc_url($url) . "' class='button button-primary'>" . esc_html__('Step 1: Authenticate', 'photonic') . '</a>';
150 echo "</div>\n";
151 echo "<div class=\"photonic-token-header\">\n";
152 echo "<p>\n";
153 echo esc_html__('Next, you have to obtain the token.', 'photonic') . '<br/>';
154 echo "</p>\n";
155 echo "<span class='button photonic-helper-button-disabled'>" .
156 esc_html__('Step 2: Obtain Token', 'photonic') . '</span>';
157 }
158 else {
159 echo "<span class='button photonic-helper-button-disabled'>" .
160 esc_html__('Step 1: Authenticate', 'photonic') . '</span>';
161 echo "</div>\n";
162 echo "<div class=\"photonic-token-header\">\n";
163 echo esc_html__('Next, you have to obtain the token.', 'photonic') . '<br/>';
164 $nonce = wp_create_nonce('deviantart-obtain-token-' . $photonic_deviantart_client_secret);
165 echo "<a href='#' class='button button-primary photonic-deviantart-refresh' data-photonic-nonce='" . esc_attr($nonce) . "' data-photonic-provider='deviantart'>" .
166 esc_html__('Step 2: Obtain Token', 'photonic') . '</a>';
167 echo '<input type="hidden" value="' . esc_attr($parameters['code']) . '" id="photonic-deviantart-oauth-code"/>';
168 echo '<input type="hidden" value="' . esc_attr($parameters['state']) . '" id="photonic-deviantart-oauth-state"/>';
169 }
170 }
171 echo "</div>\n";
172 echo '<div class="result" id="deviantart-result">&nbsp;</div>';
173 }
174
175 private function show_token_section($auth, $provider_slug, $provider_text) {
176 $this->show_token_section_header($auth, $provider_text);
177 if (!empty($auth['api_key']) && !empty($auth['api_secret'])) {
178 $this->show_token_section_body($auth, $provider_slug, $provider_text);
179 }
180 else {
181 echo '<div class="result" id="' . esc_attr($provider_slug) . '-result">&nbsp;</div>';
182 }
183 }
184
185 /**
186 * @param $auth array
187 * @param $provider string
188 */
189 private function show_token_section_header(array $auth, string $provider): void {
190 echo "<div class=\"photonic-token-header\">\n";
191
192 if ('Instagram' === $provider) {
193 echo '<p class="notice notice-error">' . esc_html__("Unfortunately Instagram is no longer supported in Photonic. This is due to a change in Meta's Terms and Conditions, that only allow businesses to access their API. As Photonic is developed by an individual, the API is no longer accessible to the developer.", 'photonic') . '</p><br/>';
194 }
195 elseif (empty($auth['api_key']) || empty($auth['api_secret'])) {
196 /* Translators: 1: Platform 2: Menu location */
197 echo sprintf(esc_html__('Please set up your %1$s API key under %2$s.', 'photonic'), esc_html($provider), sprintf('<em>Photonic &rarr; Settings &rarr; %1$s &rarr; %1$s Settings</em>', esc_html($provider)));
198 }
199 elseif ('Instagram' === $provider && !empty($auth['token'])) {
200 require_once PHOTONIC_PATH . '/Platforms/Instagram.php';
201 $module = Instagram::get_instance();
202 $expiring_soon = $module->is_token_expiring_soon(30);
203 if (is_null($expiring_soon)) {
204 // Not yet authenticated with the new API.
205 echo '<p class="notice notice-error">' . esc_html__('Your authentication credentials are for the old Instagram API. Please reauthenticate to keep Photonic working.', 'photonic') . '</p><br/>';
206 }
207 elseif (1 === $expiring_soon) {
208 echo '<p class="notice notice-warning">' . esc_html__('Your authentication credentials are expiring soon. Please reauthenticate to keep Photonic working.', 'photonic') . '</p><br/>';
209 }
210 elseif (-1 === $expiring_soon) {
211 echo '<p class="notice notice-error">' . esc_html__('Your authentication credentials have expired! Please reauthenticate to keep Photonic working.', 'photonic') . '</p><br/>';
212 }
213 else {
214 $cached_token = $module->get_cached_token();
215
216 if (!empty($cached_token) && !empty($cached_token['user'])) {
217 /* Translators: 1: User in <code> tags */
218 $this->print_auth_done_all_good(sprintf(esc_html__('You are logged in as %1$s.', 'photonic'), '<code>' . $cached_token['user'] . '</code>'));
219 }
220 else {
221 $this->print_auth_done_all_good();
222 }
223 }
224 }
225 elseif (!empty($auth['token'])) {
226 $this->print_auth_done_all_good();
227 }
228 echo "</div>\n";
229 }
230
231 /**
232 * @param $auth
233 * @param $provider
234 * @param $provider_text
235 */
236 public function show_token_section_body($auth, $provider, $provider_text) {
237 $photonic_authentication = get_option('photonic_authentication');
238 $response = Base::parse_parameters($_SERVER['QUERY_STRING'] ?? '');
239
240 if (empty($response['provider']) || (!empty($response['provider']) && $provider !== $response['provider'])) {
241 $nonce = wp_create_nonce($provider . '-request-token-' . $auth['api_secret']);
242 echo "<a href='#' class='button button-primary photonic-token-request' data-photonic-provider='" . esc_attr($provider) . "' data-photonic-nonce='" . esc_attr($nonce) . "'>" . wp_kses_post($this->get_login_button($provider_text)) . '</a>';
243 }
244 elseif (!empty($response['oauth_token']) && !empty($response['oauth_verifier'])) {
245 if (in_array($provider, ['flickr', 'smug', 'smugmug'], true)) {
246 if ('flickr' === $provider) {
247 require_once PHOTONIC_PATH . '/Platforms/Flickr.php';
248 $module = Flickr::get_instance();
249 }
250 else {
251 require_once PHOTONIC_PATH . '/Platforms/SmugMug.php';
252 $module = SmugMug::get_instance();
253 }
254 echo "<span class='button photonic-helper-button-disabled'>" . wp_kses_post($this->get_login_button($provider_text)) . '</span>';
255 $authorization = ['oauth_token' => $response['oauth_token'], 'oauth_verifier' => $response['oauth_verifier']];
256 if (isset($photonic_authentication) && isset($photonic_authentication[$provider]) && isset($photonic_authentication[$provider]['oauth_token_secret'])) {
257 $authorization['oauth_token_secret'] = $photonic_authentication[$provider]['oauth_token_secret'];
258 }
259 $access_token = $module->get_access_token($authorization);
260 if (isset($access_token['oauth_token'])) {
261 echo '<div class="result">Access Token: <code id="' . esc_attr($provider) . '-token">' . esc_html($access_token['oauth_token']) . '</code><br/>Access Token Secret: <code id="' . esc_attr($provider) . '-token-secret">' . esc_html($access_token['oauth_token_secret']) . '</code></div>' . "\n";
262 $nonce = wp_create_nonce($provider . '-save-token-' . $access_token['oauth_token']);
263 echo "<a href='#' class='button button-primary photonic-save-token' data-photonic-provider='" . esc_attr($provider) . "' data-photonic-nonce='" . esc_attr($nonce) . "'>" . esc_html__('Save Token', 'photonic') . '</a>';
264 }
265 }
266 }
267 }
268
269 private function print_auth_done_all_good($additional_msg = null) {
270 echo '<p class="notice notice-success">';
271 esc_html_e('You have already set up your authentication. Unless you wish to regenerate the token this step is not required. ', 'photonic');
272 if (!empty($additional_msg)) {
273 echo esc_html($additional_msg);
274 }
275 echo '</p>';
276 }
277
278 private function get_login_button($provider) {
279 /* Translators: 1: Platform, untranslated */
280 return sprintf(esc_html__('Login and get Access Token from %s', 'photonic'), $provider);
281 }
282
283 private function show_token_deletion_button($provider) {
284 // echo "<a href='#' class='button button-primary photonic-" . strtolower($provider) . "-delete'>" . esc_html__(sprintf('Delete current %s authentication data', $provider), 'photonic') . '</a>';
285 }
286
287 public function obtain_token() {
288 $provider = sanitize_text_field($_POST['provider'] ?? '');
289 global $photonic_flickr_api_secret, $photonic_smug_api_secret, $photonic_deviantart_client_secret;
290 if ('flickr' === $provider && check_ajax_referer('flickr-request-token-' . $photonic_flickr_api_secret, '_ajax_nonce')) {
291 require_once PHOTONIC_PATH . '/Platforms/Flickr.php';
292 $module = Flickr::get_instance();
293 if (empty($_POST['oauth_token']) && empty($_POST['oauth_verifier'])) {
294 $request_token = $module->get_request_token(admin_url('admin.php?page=photonic-auth&provider=flickr'));
295 $authorize_url = $module->get_authorize_URL($request_token);
296 $authorize_url .= '&perms=read';
297 $module->save_token($request_token);
298 echo esc_url_raw($authorize_url);
299 }
300 }
301 elseif ('smug' === $provider && check_ajax_referer('smug-request-token-' . $photonic_smug_api_secret, '_ajax_nonce')) {
302 require_once PHOTONIC_PATH . '/Platforms/SmugMug.php';
303 $module = SmugMug::get_instance();
304 if (empty($_POST['oauth_token']) && empty($_POST['oauth_verifier'])) {
305 $request_token = $module->get_request_token(admin_url('admin.php?page=photonic-auth&provider=smug'));
306 $authorize_url = $module->get_authorize_URL($request_token);
307 $authorize_url .= '&Access=Full&Permissions=Read';
308 $module->save_token($request_token);
309 echo esc_url_raw($authorize_url);
310 }
311 }
312 elseif ('zenfolio' === $provider) {
313 $module = Zenfolio::get_instance();
314 if (!empty($_POST['password'])) {
315 $response = $module->authenticate($_POST['password']);
316 if (!empty($response['error'])) {
317 echo wp_kses_post($response['error']);
318 }
319 elseif (!empty($response['success'])) {
320 esc_html_e('Authentication successful! All your galleries will be displayed with Authentication in place.', 'photonic');
321 }
322 }
323 }
324 elseif ('deviantart' === $provider && check_ajax_referer('deviantart-obtain-token-' . $photonic_deviantart_client_secret, '_ajax_nonce')) {
325 $code = sanitize_text_field($_POST['code'] ?? '');
326 require_once PHOTONIC_PATH . '/Platforms/DeviantArt.php';
327 $module = DeviantArt::get_instance();
328 $response = Photonic::http(
329 $module->access_token_URL(),
330 'POST',
331 [
332 'code' => $code,
333 'grant_type' => 'authorization_code',
334 'client_id' => $module->client_id,
335 'client_secret' => $module->client_secret,
336 'redirect_uri' => admin_url('admin.php?page=photonic-auth&source=deviantart'),
337 ]
338 );
339
340 if (!is_wp_error($response) && is_array($response)) {
341 $body = json_decode($response['body']);
342 // Add nonce to the response. This will be used to save the information in the options.
343 $body->nonce = wp_create_nonce('deviantart-save-token-' . $body->refresh_token);
344 echo(wp_json_encode($body));
345 }
346 }
347 }
348
349 public function delete_token_from_options() {
350 if (isset($_POST['provider']) && check_ajax_referer($_POST['provider'] . '-delete-token')) {
351 $provider = strtolower(sanitize_text_field($_POST['provider']));
352 if (in_array($provider, ['flickr', 'smug', 'zenfolio', 'google', 'instagram'], true) && current_user_can('edit_theme_options')) {
353 $photonic_authentication = get_option('photonic_authentication');
354 if ('zenfolio' === $provider) {
355 if (isset($photonic_authentication[$provider])) {
356 unset($photonic_authentication[$provider]);
357 }
358 }
359 update_option('photonic_authentication', $photonic_authentication);
360 }
361 }
362 die();
363 }
364 }
365