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/Http/Controllers/ProductDownloadablesController.php +51 -5 1.6.3 → 1.6.5 View file →
@@ -8,8 +8,9 @@
8 8 use FluentCart\App\Http\Requests\ProductDownloadable\ProductDownloadableFileRequest;
9 9 use FluentCart\App\Models\Product;
10 10 use FluentCart\App\Models\ProductDetail;
11 11 use FluentCart\App\Models\ProductDownload;
12 +use FluentCart\App\Services\FileSystem\StorageBucketResolver;
12 13 use FluentCart\App\Services\FileSystem\StoragePath;
13 14 use FluentCart\App\Services\URL;
14 15 use FluentCart\Framework\Http\Request\Request;
15 16 use FluentCart\Framework\Http\URL as BaseUrl;
@@ -21,9 +22,13 @@
21 22 {
22 23 public function syncDownloadableFiles(Request $request): \WP_REST_Response
23 24 {
24 25 $productDownloadableBulkFileRequest = new ProductDownloadableBulkFileRequest();
25 - $validator = Validator::make($request->all(), $productDownloadableBulkFileRequest->rules());
26 + $validator = Validator::make(
27 + $request->all(),
28 + $productDownloadableBulkFileRequest->rules(),
29 + $productDownloadableBulkFileRequest->messages()
30 + );
26 31 $validationErrors = [];
27 32
28 33
29 34 if ($validator->fails()) {
@@ -96,12 +101,21 @@
96 101 $fileName = explode('_____fluent-cart_____', $fileName)[0];
97 102 $fileName = explode('__fluent-cart__', $fileName)[0];
98 103 $file['file_name'] = $fileName;
99 104
100 - $file['settings'] = json_encode(
101 - Arr::get($file, 'settings', [])
102 - );
105 + // settings.bucket decides which cloud bucket the download is later signed
106 + // against, so it is resolved from the driver's own settings rather than
107 + // taken from the request — otherwise any editable product could point at
108 + // a sibling bucket the store credentials happen to read.
109 + $settings = $this->withResolvedBucket(Arr::get($file, 'settings', []), $file['driver']);
110 + if (is_wp_error($settings)) {
111 + return $this->sendError([
112 + 'message' => $settings->get_error_message()
113 + ], 422);
114 + }
103 115
116 + $file['settings'] = json_encode($settings);
117 +
104 118 unset($file['id']);
105 119 unset($file['bucket']);
106 120 }
107 121
@@ -122,8 +136,31 @@
122 136 ]);
123 137 }
124 138 }
125 139
140 + /**
141 + * Replace the caller-supplied settings.bucket with the bucket the selected
142 + * driver is actually configured to use.
143 + *
144 + * @param mixed $settings the submitted settings blob
145 + * @param string $driver the submitted driver slug
146 + * @return array|\WP_Error WP_Error when the driver is unknown, disabled, or
147 + * bucket-backed with no configured bucket
148 + */
149 + private function withResolvedBucket($settings, $driver)
150 + {
151 + $settings = is_array($settings) ? $settings : [];
152 +
153 + $bucket = StorageBucketResolver::resolve($driver);
154 + if (is_wp_error($bucket)) {
155 + return $bucket;
156 + }
157 +
158 + $settings['bucket'] = $bucket;
159 +
160 + return $settings;
161 + }
162 +
126 163 public function getDownloadableUrl($downloadableId)
127 164 {
128 165 $productDownload = ProductDownload::query()->findOrFail($downloadableId);
129 166
@@ -172,8 +209,17 @@
172 209 } else {
173 210 $productVariationId = [];
174 211 }
175 212
213 + // Same server-side bucket resolution as the sync path — editing a file must
214 + // not be a second way to substitute an unconfigured bucket.
215 + $settings = $this->withResolvedBucket(Arr::get($data, 'settings', []), Arr::get($data, 'driver'));
216 + if (is_wp_error($settings)) {
217 + return $this->sendError([
218 + 'message' => $settings->get_error_message()
219 + ], 422);
220 + }
221 +
176 222 $productDownload->product_variation_id = $productVariationId;
177 223 $productDownload->title = Arr::get($data, 'title');
178 224 $productDownload->type = Arr::get($data, 'type');
179 225 $productDownload->driver = Arr::get($data, 'driver');
@@ -179,9 +225,9 @@
179 225 $productDownload->driver = Arr::get($data, 'driver');
180 226 $productDownload->file_name = $fileName;
181 227 $productDownload->file_path = $filePath;
182 228 $productDownload->file_url = $fileUrl;
183 - $productDownload->settings = Arr::get($data, 'settings');
229 + $productDownload->settings = $settings;
184 230 $productDownload->serial = Arr::get($data, 'serial');
185 231
186 232 if ($productDownload->save()) {
187 233 return $this->sendSuccess([