PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.5
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.5
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
← All changes | app/Modules/StorageDrivers/S3/S3.php +504 -53 1.3.20 → 1.6.5 View file →
@@ -1,10 +1,12 @@
1 1 <?php
2 2
3 3 namespace FluentCart\App\Modules\StorageDrivers\S3;
4 4
5 +use FluentCart\App\Helpers\Helper;
5 6 use FluentCart\App\Services\FileSystem\Drivers\S3\S3ConnectionVerify;
6 7 use FluentCart\App\Services\FileSystem\Drivers\S3\S3Driver;
8 +use FluentCart\App\Services\FileSystem\Drivers\S3\S3InputValidator;
7 9 use FluentCart\App\Vite;
8 10 use FluentCart\App\Modules\StorageDrivers\BaseStorageDriver;
9 11 use FluentCart\Framework\Support\Arr;
10 12
@@ -25,14 +27,39 @@
25 27 public function registerHooks()
26 28 {
27 29 add_filter('fluent_cart/verify_driver_connect_info_' . $this->slug, [$this, 'verifyConnectInfo'], 10, 2);
28 30 add_filter('fluent_cart/get_dynamic_search_s3_bucket_list', [$this, 'getBucketList'], 10, 2);
29 -
30 31 }
31 32
32 - public function getBucketList(): array
33 + public function getBucketList($buckets = [], $args = []): array
33 34 {
34 - $bucketList = (new S3Driver())->buckets();
35 + $driverSettings = Arr::get($args, 'driver_settings', []);
36 + $query = strtolower(trim((string) Arr::get($args, 'query', '')));
37 + $resolvedCredentials = $this->resolveCredentials($driverSettings);
38 +
39 + if (empty($resolvedCredentials['access_key']) || empty($resolvedCredentials['secret_key'])) {
40 + return [];
41 + }
42 +
43 + $bucketList = \FluentCart\App\Services\FileSystem\Drivers\S3\S3BucketList::get(
44 + $resolvedCredentials['secret_key'],
45 + $resolvedCredentials['access_key'],
46 + 'us-east-1',
47 + $resolvedCredentials['session_token']
48 + );
49 +
50 + if (is_wp_error($bucketList)) {
51 + return [];
52 + }
53 +
54 + if ($query !== '') {
55 + $bucketList = array_values(array_filter($bucketList, function ($bucket) use ($query) {
56 + return strpos(strtolower((string) $bucket), $query) !== false;
57 + }));
58 + }
59 +
60 + $bucketList = array_slice($bucketList, 0, 50);
61 +
35 62 $buckets = [];
36 63 foreach ($bucketList as $bucket) {
37 64 $buckets[] = array(
38 65 "label" => $bucket,
@@ -46,14 +73,29 @@
46 73 {
47 74 return Vite::getAssetUrl("images/storage-drivers/s3.svg");
48 75 }
49 76
77 + public function getDarkLogo()
78 + {
79 + return Vite::getAssetUrl("images/storage-drivers/s3-dark.svg");
80 + }
81 +
50 82 public function hasBucket(): bool
51 83 {
52 84 return true;
53 85 }
54 86
87 + public function getEffectiveBucket(): string
88 + {
89 + return S3Settings::resolveEffectiveBucket($this->getSettings());
90 + }
55 91
92 + public function needsReconfigure(): bool
93 + {
94 + return S3Settings::resolveConfiguredBucket($this->getSettings()) === '';
95 + }
96 +
97 +
56 98 public function getDescription()
57 99 {
58 100 return esc_html__('S3 bucket allows to configure storage options and others for efficient and secure cloud-based file storage', 'fluent-cart');
59 101 }
@@ -61,10 +103,10 @@
61 103 public function isEnabled(): bool
62 104 {
63 105 $settings = $this->getSettings();
64 106 $isActive = Arr::get($settings, 'is_active') === 'yes';
65 - $hasSelectedBuckets = !empty(Arr::get($settings, 'buckets')) && is_array(Arr::get($settings, 'buckets')) && count(Arr::get($settings, 'buckets')) > 0;
66 - return $isActive && $hasSelectedBuckets;
107 + $hasSelectedBucket = S3Settings::resolveEffectiveBucket($settings) !== '';
108 + return $isActive && $hasSelectedBucket;
67 109 }
68 110
69 111 public function getSettings()
70 112 {
@@ -70,61 +112,329 @@
70 112 {
71 113 return (new S3Settings())->get();
72 114 }
73 115
116 + public function getSettingsTemplate(): ?string
117 + {
118 + $templatePath = dirname(__DIR__, 4) . '/app/Modules/StorageDrivers/S3/VueTemplates/SettingsPage.vue';
119 +
120 + if (!file_exists($templatePath)) {
121 + return null;
122 + }
123 +
124 + $template = file_get_contents($templatePath);
125 +
126 + return $template ?: null;
127 + }
128 +
129 + public function getSettingsTemplatePayload(array $response = []): array
130 + {
131 + return array_merge(parent::getSettingsTemplatePayload($response), [
132 + 'connection_verify_endpoint' => 'settings/storage-drivers/verify-info',
133 + 'create_bucket_endpoint' => 'settings/storage-drivers/create-bucket',
134 + 'bucket_list_endpoint' => 'settings/storage-drivers/bucket-list',
135 + 'save_endpoint' => 'settings/storage-drivers',
136 + 'reset_endpoint' => 'settings/storage-drivers/reset',
137 + 'supports_template_mode' => true,
138 + ]);
139 + }
140 +
141 + public function listBuckets(array $data, array $args = [])
142 + {
143 + $credentialError = $this->requireCredentials($data);
144 + if ($credentialError) {
145 + return $credentialError;
146 + }
147 +
148 + return $this->getBucketList([], [
149 + 'driver_settings' => $data,
150 + 'query' => Arr::get($args, 'query')
151 + ]);
152 + }
153 +
154 + public function createBucket(array $data)
155 + {
156 + $credentialError = $this->requireCredentials($data);
157 + if ($credentialError) {
158 + return $credentialError;
159 + }
160 +
161 + $resolvedCredentials = $this->resolveCredentials($data);
162 +
163 + if (empty($resolvedCredentials['access_key']) || empty($resolvedCredentials['secret_key'])) {
164 + return new \WP_Error('invalid_credentials', __('Invalid credentials for bucket creation', 'fluent-cart'));
165 + }
166 +
167 + $newBucket = sanitize_text_field(Arr::get($data, 'new_bucket_name'));
168 + $newBucket = strtolower($newBucket);
169 + $newBucket = preg_replace('/[^a-z0-9\.-]/', '-', $newBucket);
170 + $newBucket = preg_replace('/-+/', '-', $newBucket);
171 + $newBucket = trim($newBucket, '-.');
172 +
173 + $newRegion = sanitize_text_field(Arr::get($data, 'new_bucket_region', 'us-east-1')) ?: 'us-east-1';
174 +
175 + if (!$newBucket) {
176 + return new \WP_Error('invalid_bucket', __('Bucket name is required', 'fluent-cart'));
177 + }
178 +
179 + $validation = S3InputValidator::validateBucketAndRegion($newBucket, $newRegion);
180 + if (is_wp_error($validation)) {
181 + return $validation;
182 + }
183 +
184 + $creation = \FluentCart\App\Services\FileSystem\Drivers\S3\S3BucketCreator::create(
185 + $resolvedCredentials['secret_key'],
186 + $resolvedCredentials['access_key'],
187 + $newBucket,
188 + $newRegion,
189 + $resolvedCredentials['session_token']
190 + );
191 +
192 + if (is_wp_error($creation)) {
193 + return $creation;
194 + }
195 +
196 + $bucketCheck = S3ConnectionVerify::checkBucketExistence(
197 + $resolvedCredentials['secret_key'],
198 + $resolvedCredentials['access_key'],
199 + $resolvedCredentials['session_token'],
200 + $newBucket,
201 + $newRegion
202 + );
203 +
204 + if (is_wp_error($bucketCheck)) {
205 + return $bucketCheck;
206 + }
207 +
208 + $region = Arr::get($bucketCheck, 'region', $newRegion);
209 +
210 + $securitySettings = S3ConnectionVerify::checkSecuritySettings(
211 + $resolvedCredentials['secret_key'],
212 + $resolvedCredentials['access_key'],
213 + $resolvedCredentials['session_token'],
214 + $newBucket,
215 + $region
216 + );
217 +
218 + return [
219 + 'message' => __('Bucket created successfully', 'fluent-cart'),
220 + 'bucket' => $newBucket,
221 + 'region' => $region,
222 + 'connection_error' => '',
223 + 'block_public_access' => !empty($securitySettings['block_public_access']) ? 'yes' : 'no',
224 + 'object_ownership' => !empty($securitySettings['object_ownership']) ? 'yes' : 'no'
225 + ];
226 + }
227 +
74 228 public function updateSettings($data)
75 229 {
76 230 $settings = $this->getSettings();
77 - foreach ($this->hiddenSettingKeys() as $key) {
78 - if (empty($data[$key]) && isset($settings[$key])) {
231 +
232 + if (!array_key_exists('auth_method', $data) && isset($settings['auth_method'])) {
233 + $data['auth_method'] = $settings['auth_method'];
234 + }
235 +
236 + if (!array_key_exists('buckets', $data) && isset($settings['buckets'])) {
237 + $data['buckets'] = $settings['buckets'];
238 + }
239 +
240 + $mergeKeys = array_diff($this->hiddenSettingKeys(), ['create_new_bucket', 'new_bucket_name', 'new_bucket_region']);
241 + $credentialKeys = ['access_key', 'secret_key'];
242 + $storedAuthMethod = Arr::get($settings, 'auth_method');
243 +
244 + foreach ($mergeKeys as $key) {
245 + $isCredential = in_array($key, $credentialKeys, true);
246 +
247 + // In define mode getSettings() resolves credentials from the wp-config
248 + // constants, so merging one here would copy it into the database and
249 + // break revocation. Never fall back to a value we do not own.
250 + if ($isCredential && $storedAuthMethod === 'define') {
251 + continue;
252 + }
253 +
254 + // Credentials are stripped from the settings response, so an empty
255 + // submitted value means "unchanged" and must fall back to storage.
256 + $isMissing = $isCredential
257 + ? empty($data[$key])
258 + : !array_key_exists($key, $data);
259 +
260 + if ($isMissing && isset($settings[$key])) {
79 261 $data[$key] = $settings[$key];
80 262 }
81 263 }
82 264
83 - $isVarified = true;
84 - if (Arr::get($data, 'is_active') === 'yes') {
85 - $isVarified = $this->verifyConnectInfo($data);
265 + if (
266 + Arr::get($data, 'is_active') === 'no' &&
267 + !Arr::get($data, 'verify_only_credentials') &&
268 + !Arr::get($data, 'check_bucket_exists')
269 + ) {
270 + $data['is_active'] = 'no';
86 271
87 - if (!is_wp_error($isVarified)) {
88 - $data['is_active'] = 'yes';
272 + if (!Arr::get($data, 'preserve_settings')) {
273 + $resetSettings = $this->resetSettings();
274 +
275 + return [
276 + 'data' => Arr::except($resetSettings, $this->hiddenSettingKeys()),
277 + 'message' => __('S3 settings have been reset successfully', 'fluent-cart'),
278 + 'shouldReload' => false
279 + ];
89 280 }
90 - $data['show_buckets'] = 'yes';
91 - } else {
92 - $data['is_active'] = 'no';
93 - $data['access_key'] = '';
94 - $data['secret_key'] = '';
95 - $data['buckets'] = [];
96 - $data['show_buckets'] = 'no';
97 - $cacheKey = 'fct_s3_region';
98 - \FluentCart\App\Models\Meta::query()->where('meta_key', $cacheKey)->delete();
99 - $message = __('S3 is deactivated successfully', 'fluent-cart');
281 +
282 + if (!empty($data['bucket'])) {
283 + $data['show_buckets'] = 'yes';
284 + }
285 +
286 + parent::updateSettings($this->prepareSettingsForStorage($data));
287 +
288 + return [
289 + 'data' => Arr::except($data, $this->hiddenSettingKeys()),
290 + 'message' => __('S3 is deactivated successfully', 'fluent-cart'),
291 + 'shouldReload' => false
292 + ];
100 293 }
101 294
295 + $credentialError = $this->requireCredentials($data);
296 + if ($credentialError) {
297 + return $credentialError;
298 + }
102 299
103 -// if (empty($data['buckets'])) {
104 -// $data['is_active'] = 'no';
105 -// $data['buckets'] = [];
106 -// } else {
107 -// if ($isVarified) {
108 -// //$data['is_active'] = 'yes';
109 -// }
110 -// }
300 + $resolvedCredentials = $this->resolveCredentials($data);
301 + $userBlockPublicAccess = Arr::get($data, 'block_public_access');
302 + $userObjectOwnership = Arr::get($data, 'object_ownership');
303 + $verificationResult = true;
111 304
112 - if (is_wp_error($isVarified)) {
113 - return $isVarified;
305 + if (Arr::get($data, 'verify_only_credentials')) {
306 + $verificationResult = $this->verifyConnectInfo($data);
307 + if (is_wp_error($verificationResult)) {
308 + return $verificationResult;
309 + }
114 310 }
115 311
312 + // A credentials-only step must not run a bucket check: on failure the
313 + // branch below persists the stored settings and discards the credentials
314 + // the user just entered. Mirrors the guards further down.
315 + if (!empty($data['bucket']) && !Arr::get($data, 'verify_only_credentials')) {
316 + $bucketValidation = S3InputValidator::validateBucket($data['bucket']);
317 + if (is_wp_error($bucketValidation)) {
318 + return $bucketValidation;
319 + }
116 320
117 - parent::updateSettings($data);
321 + if (!empty($data['region'])) {
322 + $regionValidation = S3InputValidator::validateRegion($data['region']);
323 + if (is_wp_error($regionValidation)) {
324 + return $regionValidation;
325 + }
326 + }
118 327
119 - $shouldReload = true;
328 + $region = Arr::get($data, 'region') ?: self::getBucketRegion($data['bucket']) ?: 'us-east-1';
120 329
330 + $bucketCheck = S3ConnectionVerify::checkBucketExistence(
331 + $resolvedCredentials['secret_key'],
332 + $resolvedCredentials['access_key'],
333 + $resolvedCredentials['session_token'],
334 + $data['bucket'],
335 + $region
336 + );
337 +
338 + if (is_wp_error($bucketCheck)) {
339 + $errorSettings = $settings;
340 + $errorSettings['connection_error'] = $bucketCheck->get_error_message();
341 +
342 + parent::updateSettings($this->prepareSettingsForStorage($errorSettings));
343 +
344 + return $bucketCheck;
345 + }
346 +
347 + $data['connection_error'] = '';
348 +
349 + if (isset($bucketCheck['region']) && $bucketCheck['region'] !== Arr::get($data, 'region')) {
350 + $data['region'] = $bucketCheck['region'];
351 + }
352 +
353 + $securitySettings = S3ConnectionVerify::checkSecuritySettings(
354 + $resolvedCredentials['secret_key'],
355 + $resolvedCredentials['access_key'],
356 + $resolvedCredentials['session_token'],
357 + $data['bucket'],
358 + Arr::get($data, 'region') ?: $region
359 + );
360 +
361 + $bucketCheck['block_public_access'] = Arr::get($securitySettings, 'block_public_access');
362 + $bucketCheck['object_ownership'] = Arr::get($securitySettings, 'object_ownership');
363 + $verificationResult = $bucketCheck;
364 + }
365 +
366 + if (is_array($verificationResult) && array_key_exists('block_public_access', $verificationResult) && $userBlockPublicAccess === null) {
367 + $data['block_public_access'] = $verificationResult['block_public_access'] ? 'yes' : 'no';
368 + }
369 +
370 + if (is_array($verificationResult) && array_key_exists('object_ownership', $verificationResult) && $userObjectOwnership === null) {
371 + $data['object_ownership'] = $verificationResult['object_ownership'] ? 'yes' : 'no';
372 + }
373 +
374 + if (
375 + !empty($data['bucket']) &&
376 + Arr::get($data, 'is_active') === 'yes' &&
377 + !Arr::get($data, 'verify_only_credentials') &&
378 + !is_wp_error($verificationResult)
379 + ) {
380 + $bucketRegion = Arr::get($data, 'region') ?: self::getBucketRegion($data['bucket']) ?: 'us-east-1';
381 +
382 + if ($userBlockPublicAccess !== null) {
383 + $enableBlock = $this->isTrue($userBlockPublicAccess);
384 + $syncResult = S3ConnectionVerify::updatePublicAccessBlock(
385 + $resolvedCredentials['secret_key'],
386 + $resolvedCredentials['access_key'],
387 + $resolvedCredentials['session_token'],
388 + $data['bucket'],
389 + $enableBlock,
390 + $bucketRegion
391 + );
392 +
393 + if (is_wp_error($syncResult)) {
394 + return $syncResult;
395 + }
396 +
397 + $data['block_public_access'] = $enableBlock ? 'yes' : 'no';
398 + }
399 +
400 + if ($userObjectOwnership !== null) {
401 + $enableOwnership = $this->isTrue($userObjectOwnership);
402 + $syncResult = S3ConnectionVerify::updateObjectOwnership(
403 + $resolvedCredentials['secret_key'],
404 + $resolvedCredentials['access_key'],
405 + $resolvedCredentials['session_token'],
406 + $data['bucket'],
407 + $enableOwnership,
408 + $bucketRegion
409 + );
410 +
411 + if (is_wp_error($syncResult)) {
412 + return $syncResult;
413 + }
414 +
415 + $data['object_ownership'] = $enableOwnership ? 'yes' : 'no';
416 + }
417 + }
418 +
419 + if (Arr::get($data, 'verify_only_credentials') || !empty($data['bucket']) || Arr::get($data, 'is_active') === 'yes') {
420 + $data['show_buckets'] = 'yes';
421 + }
422 +
423 + if (Arr::get($data, 'is_active') === 'yes') {
424 + $data['is_active'] = 'yes';
425 + $data['connection_error'] = '';
426 + }
427 +
428 + parent::updateSettings($this->prepareSettingsForStorage($data));
429 +
430 + $shouldReload = Arr::get($data, 'is_active') === 'yes';
431 +
121 432 if (empty($message)) {
122 433 if (Arr::get($data, 'is_active') === 'yes') {
123 434 $message = __('Your s3 storage is activated successfully', 'fluent-cart');
124 435 } else {
125 - $message = __('S3 is configured successfully but not activated.', 'fluent-cart');
126 - $shouldReload = true;
436 + $message = __('Settings saved successfully.', 'fluent-cart');
127 437 }
128 438 }
129 439
130 440
@@ -134,36 +444,149 @@
134 444 'shouldReload' => $shouldReload
135 445 ];
136 446 }
137 447
138 - /**
139 - * Verify Connect configuration
140 - */
141 - public function verifyConnectInfo(array $data, $args = [])
448 + private function requireCredentials(array $data)
142 449 {
450 + $settings = $this->getSettings();
451 + $authMethod = Arr::get($data, 'auth_method', Arr::get($settings, 'auth_method', 'db'));
452 +
453 + if ($authMethod === 'define' && !S3Settings::hasDefinedCredentials()) {
454 + return new \WP_Error(
455 + 'missing_credentials',
456 + __('S3 credentials are not defined in wp-config.php. Please add them and try again.', 'fluent-cart')
457 + );
458 + }
459 +
460 + return null;
461 + }
462 +
463 + private function resolveCredentials(array $data): array
464 + {
143 465 $settings = $this->getSettings();
144 - $isUsingDefineMode = Arr::get($settings, 'is_using_define_mode');
466 + $authMethod = Arr::get($data, 'auth_method', Arr::get($settings, 'auth_method', 'db'));
145 467
146 - $accessKey = Arr::get($data, 'access_key', null);
147 - $secretKey = Arr::get($data, 'secret_key', null);
468 + if ($authMethod === 'define') {
469 + $definedCredentials = S3Settings::getDefinedCredentials();
148 470
471 + if (!empty($definedCredentials)) {
472 + return [
473 + 'access_key' => Arr::get($definedCredentials, 'access_key', ''),
474 + 'secret_key' => Arr::get($definedCredentials, 'secret_key', ''),
475 + 'session_token' => null
476 + ];
477 + }
478 + }
479 +
480 + $accessKey = Arr::get($data, 'access_key');
481 + if (empty($accessKey)) {
482 + $accessKey = Arr::get($settings, 'access_key');
483 + }
484 +
485 + $secretKey = Arr::get($data, 'secret_key');
149 486 if (empty($secretKey)) {
150 487 $secretKey = Arr::get($settings, 'secret_key');
151 488 }
152 489
490 + return [
491 + 'access_key' => $accessKey,
492 + 'secret_key' => $secretKey,
493 + 'session_token' => null
494 + ];
495 + }
153 496
154 - if ($isUsingDefineMode) {
155 - $secretKey = FCT_S3_SECRET_KEY;
156 - $accessKey = FCT_S3_ACCESS_KEY;
497 + public function resetSettings()
498 + {
499 + fluent_cart_update_option($this->driverHandler, []);
500 + S3Settings::$cachedSettings = null;
501 +
502 + return $this->getSettings();
503 + }
504 +
505 + private function prepareSettingsForStorage(array $settings): array
506 + {
507 + if (Arr::get($settings, 'auth_method') === 'define') {
508 + unset($settings['access_key'], $settings['secret_key'], $settings['session_token']);
509 + } else {
510 + if (!empty($settings['access_key'])) {
511 + $settings['access_key'] = Helper::encryptKey($settings['access_key']);
512 + }
513 +
514 + if (!empty($settings['secret_key'])) {
515 + $settings['secret_key'] = Helper::encryptKey($settings['secret_key']);
516 + }
157 517 }
158 518
519 + unset($settings['create_new_bucket'], $settings['new_bucket_name'], $settings['new_bucket_region']);
520 + unset($settings['verify_credentials'], $settings['verify_only_credentials'], $settings['preserve_settings'], $settings['check_bucket_exists']);
521 +
522 + return $settings;
523 + }
524 +
525 + /**
526 + * Verify Connect configuration
527 + */
528 + public function verifyConnectInfo(array $data, $args = [])
529 + {
530 + $credentialError = $this->requireCredentials($data);
531 + if ($credentialError) {
532 + return $credentialError;
533 + }
534 +
535 + $resolvedCredentials = $this->resolveCredentials($data);
536 + $accessKey = Arr::get($resolvedCredentials, 'access_key');
537 + $secretKey = Arr::get($resolvedCredentials, 'secret_key');
538 + $sessionToken = Arr::get($resolvedCredentials, 'session_token');
539 +
159 540 if (empty($secretKey) || empty($accessKey)) {
160 541 return new \WP_Error('invalid_credentials', __('Invalid credentials', 'fluent-cart'));
161 542 }
162 - return S3ConnectionVerify::verify(
543 +
544 + $verifyOnlyCredentials = (bool) Arr::get($data, 'verify_only_credentials');
545 + $bucket = '';
546 + $region = 'us-east-1';
547 +
548 + if (!$verifyOnlyCredentials) {
549 + $bucket = Arr::get($data, 'bucket');
550 +
551 + if ($bucket) {
552 + $bucketValidation = S3InputValidator::validateBucket($bucket);
553 + if (is_wp_error($bucketValidation)) {
554 + return $bucketValidation;
555 + }
556 +
557 + $region = Arr::get($data, 'region');
558 +
559 + if ($region) {
560 + $regionValidation = S3InputValidator::validateRegion($region);
561 + if (is_wp_error($regionValidation)) {
562 + return $regionValidation;
563 + }
564 + }
565 +
566 + if (!$region) {
567 + $region = self::getBucketRegion($bucket);
568 + }
569 + }
570 + }
571 +
572 + if (!$region && $bucket) {
573 + return new \WP_Error('missing_region', __('Region information is missing for the selected bucket.', 'fluent-cart'));
574 + }
575 +
576 + $result = S3ConnectionVerify::verify(
163 577 $secretKey,
164 - $accessKey
578 + $accessKey,
579 + $sessionToken,
580 + $bucket,
581 + $region ?: 'us-east-1'
165 582 );
583 +
584 + if (!is_wp_error($result)) {
585 + $result['is_active'] = 'yes';
586 + }
587 +
588 + return $result;
166 589 }
167 590
168 591 public function fields(): array
169 592 {
@@ -168,9 +591,9 @@
168 591 public function fields(): array
169 592 {
170 593 $settings = $this->getSettings();
171 594 $showBucket = Arr::get($settings, 'show_buckets') === 'yes';
172 - $usingDefineMode = Arr::get($settings, 'is_using_define_mode');
595 + $usingDefineMode = Arr::get($settings, 'auth_method') === 'define';
173 596
174 597 $schema = [
175 598 'is_active' => [
176 599 'value' => '',
@@ -244,9 +667,11 @@
244 667
245 668 if ($usingDefineMode) {
246 669 unset($schema['access_key'], $schema['secret_key']);
247 670 $schema['is_using_define_mode'] = [
248 - 'value' => __('Using Define Mode', 'fluent-cart'),
671 + 'value' => Arr::get($settings, 'define_credentials_missing')
672 + ? Arr::get($settings, 'define_credentials_missing_message')
673 + : __('Using Define Mode', 'fluent-cart'),
249 674 'type' => 'html'
250 675 ];
251 676 }
252 677
@@ -271,16 +696,28 @@
271 696
272 697 public function hiddenSettingKeys(): array
273 698 {
274 699 return [
275 - //'secret_key',
276 - 'region',
277 - 'show_buckets'
700 + 'show_buckets',
701 + 'access_key',
702 + 'secret_key',
703 + 'session_token',
704 + 'create_new_bucket',
705 + 'new_bucket_name',
706 + 'new_bucket_region',
707 + 'verify_credentials',
708 + 'verify_only_credentials',
709 + 'preserve_settings',
710 + 'check_bucket_exists',
278 711 ];
279 712 }
280 713
281 714 public static function getBucketRegion($bucket)
282 715 {
716 + if (!S3InputValidator::isValidBucket($bucket)) {
717 + return null;
718 + }
719 +
283 720 $cacheKey = 'fct_s3_region';
284 721 $existingMeta = \FluentCart\App\Models\Meta::query()->where('meta_key', $cacheKey)->first();
285 722
286 723
@@ -309,8 +746,11 @@
309 746
310 747 $headers = wp_remote_retrieve_headers($response);
311 748
312 749 $region = Arr::get($headers, 'x-amz-bucket-region') ?? 'us-east-1';
750 + if (!S3InputValidator::isValidRegion($region)) {
751 + $region = 'us-east-1';
752 + }
313 753
314 754 // 5. Save or update the Meta record
315 755 if ($existingMeta) {
316 756 $values = $existingMeta->meta_value;
@@ -326,6 +766,17 @@
326 766 ]);
327 767 }
328 768
329 769 return $region;
770 + }
771 +
772 + private function isTrue($value)
773 + {
774 + if (is_string($value)) {
775 + $value = strtolower($value);
776 +
777 + return in_array($value, ['yes', 'true', '1', 'on'], true);
778 + }
779 +
780 + return (bool) $value;
330 781 }
331 782 }