@scality/data-browser-library 1.0.8 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/__tests__/BucketCorsPage.test.js +67 -9
- package/dist/components/__tests__/BucketDetails.test.js +1 -0
- package/dist/components/__tests__/BucketLifecycleFormPage.test.js +16 -11
- package/dist/components/__tests__/BucketNotificationFormPage.test.js +45 -0
- package/dist/components/__tests__/BucketOverview.test.js +92 -2
- package/dist/components/__tests__/BucketPolicyPage.test.js +70 -51
- package/dist/components/__tests__/BucketReplicationFormPage.test.js +51 -24
- package/dist/components/__tests__/ObjectList.test.js +43 -2
- package/dist/components/buckets/BucketConfigEditButton.d.ts +2 -0
- package/dist/components/buckets/BucketConfigEditButton.js +9 -3
- package/dist/components/buckets/BucketCorsPage.js +57 -20
- package/dist/components/buckets/BucketDetails.js +27 -2
- package/dist/components/buckets/BucketLifecycleFormPage.js +310 -270
- package/dist/components/buckets/BucketOverview.js +21 -18
- package/dist/components/buckets/BucketPolicyPage.js +119 -83
- package/dist/components/buckets/BucketReplicationFormPage.d.ts +1 -0
- package/dist/components/buckets/BucketReplicationFormPage.js +165 -129
- package/dist/components/buckets/BucketVersioning.js +16 -10
- package/dist/components/buckets/__tests__/BucketVersioning.test.js +76 -23
- package/dist/components/buckets/notifications/BucketNotificationFormPage.js +13 -5
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +2 -2
- package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.js +3 -3
- package/dist/components/objects/ObjectList.js +22 -25
- package/dist/components/objects/ObjectLock/EditRetentionButton.js +2 -2
- package/dist/config/types.d.ts +11 -0
- package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +2 -0
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/objectOperations.d.ts +3 -3
- package/dist/hooks/objectOperations.js +3 -3
- package/dist/hooks/useBucketConfigEditor.d.ts +4 -4
- package/dist/hooks/useBucketConfigEditor.js +16 -31
- package/dist/test/mocks/esmOnlyModules.js +4 -0
- package/dist/types/index.d.ts +0 -1
- package/dist/utils/__tests__/proxyMiddleware.test.js +34 -0
- package/dist/utils/proxyMiddleware.js +2 -0
- package/package.json +4 -4
- package/dist/components/Editor.d.ts +0 -12
- package/dist/components/Editor.js +0 -28
- package/dist/types/monaco.d.ts +0 -13
- package/dist/types/monaco.js +0 -0
|
@@ -16,23 +16,22 @@ const mockUseGetBucketVersioning = jest.mocked(useGetBucketVersioning);
|
|
|
16
16
|
const mockUseGetBucketObjectLockConfiguration = jest.mocked(useGetBucketObjectLockConfiguration);
|
|
17
17
|
const mockUseISVBucketStatus = jest.mocked(useISVBucketStatus);
|
|
18
18
|
const mockUseSetBucketVersioning = jest.mocked(useSetBucketVersioning);
|
|
19
|
-
const renderBucketVersioning = (props = {})=>{
|
|
20
|
-
const mockMutate = jest.fn()
|
|
19
|
+
const renderBucketVersioning = (props = {}, { simulateSuccess = false } = {})=>{
|
|
20
|
+
const mockMutate = jest.fn().mockImplementation((_params, options)=>{
|
|
21
|
+
if (simulateSuccess && options?.onSuccess) options.onSuccess();
|
|
22
|
+
});
|
|
21
23
|
mockUseSetBucketVersioning.mockReturnValue(createMockMutationResult(mockMutate));
|
|
22
24
|
const Wrapper = createTestWrapper();
|
|
23
|
-
return {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
...props
|
|
31
|
-
})
|
|
25
|
+
return render(/*#__PURE__*/ jsx(Wrapper, {
|
|
26
|
+
children: /*#__PURE__*/ jsx(BucketOverviewContext.Provider, {
|
|
27
|
+
value: {
|
|
28
|
+
bucketName: 'test-bucket'
|
|
29
|
+
},
|
|
30
|
+
children: /*#__PURE__*/ jsx(BucketVersioning, {
|
|
31
|
+
...props
|
|
32
32
|
})
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
};
|
|
33
|
+
})
|
|
34
|
+
}));
|
|
36
35
|
};
|
|
37
36
|
const mockHookDefaults = ()=>{
|
|
38
37
|
mockUseGetBucketVersioning.mockReturnValue({
|
|
@@ -86,10 +85,10 @@ describe('BucketVersioning', ()=>{
|
|
|
86
85
|
expect(toggle).not.toBeChecked();
|
|
87
86
|
});
|
|
88
87
|
it('calls mutation with Suspended status when disabling versioning', ()=>{
|
|
89
|
-
|
|
88
|
+
renderBucketVersioning();
|
|
90
89
|
const toggle = findToggleByLabel('Active');
|
|
91
90
|
fireEvent.click(toggle);
|
|
92
|
-
expect(mutate).toHaveBeenCalledWith({
|
|
91
|
+
expect(mockUseSetBucketVersioning().mutate).toHaveBeenCalledWith({
|
|
93
92
|
Bucket: 'test-bucket',
|
|
94
93
|
VersioningConfiguration: {
|
|
95
94
|
Status: 'Suspended'
|
|
@@ -104,10 +103,10 @@ describe('BucketVersioning', ()=>{
|
|
|
104
103
|
status: 'success',
|
|
105
104
|
error: null
|
|
106
105
|
});
|
|
107
|
-
|
|
106
|
+
renderBucketVersioning();
|
|
108
107
|
const toggle = findToggleByLabel('Inactive');
|
|
109
108
|
fireEvent.click(toggle);
|
|
110
|
-
expect(mutate).toHaveBeenCalledWith({
|
|
109
|
+
expect(mockUseSetBucketVersioning().mutate).toHaveBeenCalledWith({
|
|
111
110
|
Bucket: 'test-bucket',
|
|
112
111
|
VersioningConfiguration: {
|
|
113
112
|
Status: 'Enabled'
|
|
@@ -135,16 +134,35 @@ describe('BucketVersioning', ()=>{
|
|
|
135
134
|
});
|
|
136
135
|
renderBucketVersioning();
|
|
137
136
|
expect(screen.getByText('Enabled')).toBeInTheDocument();
|
|
138
|
-
expect(screen.getByText(/Versioning cannot be
|
|
137
|
+
expect(screen.getByText(/Versioning cannot be disabled because Object-lock is enabled/i)).toBeInTheDocument();
|
|
139
138
|
expect(screen.queryByRole('checkbox')).not.toBeInTheDocument();
|
|
140
139
|
});
|
|
141
|
-
it(
|
|
142
|
-
|
|
140
|
+
it.each([
|
|
141
|
+
{
|
|
142
|
+
isvApplication: 'Veeam',
|
|
143
143
|
isVeeamBucket: true,
|
|
144
144
|
isCommvaultBucket: false,
|
|
145
|
-
isKastenBucket: false
|
|
145
|
+
isKastenBucket: false
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
isvApplication: 'Commvault',
|
|
149
|
+
isVeeamBucket: false,
|
|
150
|
+
isCommvaultBucket: true,
|
|
151
|
+
isKastenBucket: false
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
isvApplication: 'Kasten',
|
|
155
|
+
isVeeamBucket: false,
|
|
156
|
+
isCommvaultBucket: false,
|
|
157
|
+
isKastenBucket: true
|
|
158
|
+
}
|
|
159
|
+
])('disables toggle when bucket is managed by $isvApplication', ({ isvApplication, isVeeamBucket, isCommvaultBucket, isKastenBucket })=>{
|
|
160
|
+
mockUseISVBucketStatus.mockReturnValue({
|
|
161
|
+
isVeeamBucket,
|
|
162
|
+
isCommvaultBucket,
|
|
163
|
+
isKastenBucket,
|
|
146
164
|
isISVManaged: true,
|
|
147
|
-
isvApplication
|
|
165
|
+
isvApplication,
|
|
148
166
|
isLoading: false,
|
|
149
167
|
bucketTagsStatus: 'success'
|
|
150
168
|
});
|
|
@@ -152,6 +170,41 @@ describe('BucketVersioning', ()=>{
|
|
|
152
170
|
const toggle = screen.getByRole('checkbox');
|
|
153
171
|
expect(toggle).toHaveAttribute('aria-disabled', 'true');
|
|
154
172
|
});
|
|
173
|
+
it('shows toast with correct message when disabling versioning', ()=>{
|
|
174
|
+
jest.useFakeTimers();
|
|
175
|
+
renderBucketVersioning({}, {
|
|
176
|
+
simulateSuccess: true
|
|
177
|
+
});
|
|
178
|
+
const toggle = findToggleByLabel('Active');
|
|
179
|
+
fireEvent.click(toggle);
|
|
180
|
+
jest.advanceTimersByTime(500);
|
|
181
|
+
expect(mockShowToast).toHaveBeenCalledWith(expect.objectContaining({
|
|
182
|
+
message: 'Bucket versioning disabled',
|
|
183
|
+
status: 'success'
|
|
184
|
+
}));
|
|
185
|
+
jest.useRealTimers();
|
|
186
|
+
});
|
|
187
|
+
it('shows toast with correct message when enabling versioning', ()=>{
|
|
188
|
+
jest.useFakeTimers();
|
|
189
|
+
mockUseGetBucketVersioning.mockReturnValue({
|
|
190
|
+
data: {
|
|
191
|
+
Status: 'Suspended'
|
|
192
|
+
},
|
|
193
|
+
status: 'success',
|
|
194
|
+
error: null
|
|
195
|
+
});
|
|
196
|
+
renderBucketVersioning({}, {
|
|
197
|
+
simulateSuccess: true
|
|
198
|
+
});
|
|
199
|
+
const toggle = findToggleByLabel('Inactive');
|
|
200
|
+
fireEvent.click(toggle);
|
|
201
|
+
jest.advanceTimersByTime(500);
|
|
202
|
+
expect(mockShowToast).toHaveBeenCalledWith(expect.objectContaining({
|
|
203
|
+
message: 'Bucket versioning enabled',
|
|
204
|
+
status: 'success'
|
|
205
|
+
}));
|
|
206
|
+
jest.useRealTimers();
|
|
207
|
+
});
|
|
155
208
|
it('disables toggle when versioning query errors', ()=>{
|
|
156
209
|
mockUseGetBucketVersioning.mockReturnValue({
|
|
157
210
|
data: void 0,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { joiResolver } from "@hookform/resolvers/joi";
|
|
3
3
|
import { Form, FormGroup, FormSection, Icon, Loader, Stack, Text, spacing, useToast } from "@scality/core-ui";
|
|
4
4
|
import { convertRemToPixels } from "@scality/core-ui/dist/components/tablev2/TableUtils";
|
|
@@ -9,6 +9,7 @@ import { FormProvider, useForm } from "react-hook-form";
|
|
|
9
9
|
import { useParams } from "react-router";
|
|
10
10
|
import { useGetBucketNotification, useSetBucketNotification } from "../../../hooks/index.js";
|
|
11
11
|
import { useDataBrowserNavigate } from "../../../hooks/useDataBrowserNavigate.js";
|
|
12
|
+
import { useSupportedNotificationEvents } from "../../../hooks/useSupportedNotificationEvents.js";
|
|
12
13
|
import { EventsSection } from "./EventsSection.js";
|
|
13
14
|
const baseSchema = joi.object({
|
|
14
15
|
ruleName: joi.string().required().messages({
|
|
@@ -29,6 +30,7 @@ function BucketNotificationFormPage() {
|
|
|
29
30
|
const navigate = useDataBrowserNavigate();
|
|
30
31
|
const { showToast } = useToast();
|
|
31
32
|
const isEditMode = !!ruleId;
|
|
33
|
+
const supportedEvents = useSupportedNotificationEvents();
|
|
32
34
|
const { data: existingNotificationData, status: notificationStatus, error: notificationError } = useGetBucketNotification({
|
|
33
35
|
Bucket: bucketName
|
|
34
36
|
});
|
|
@@ -70,10 +72,15 @@ function BucketNotificationFormPage() {
|
|
|
70
72
|
if (isEditMode && existingRule) {
|
|
71
73
|
const prefixRule = existingRule.Filter?.Key?.FilterRules?.find((r)=>'prefix' === r.Name);
|
|
72
74
|
const suffixRule = existingRule.Filter?.Key?.FilterRules?.find((r)=>'suffix' === r.Name);
|
|
75
|
+
let events = existingRule.Events || [];
|
|
76
|
+
if (supportedEvents?.length) {
|
|
77
|
+
const supported = new Set(supportedEvents);
|
|
78
|
+
events = events.filter((event)=>supported.has(event));
|
|
79
|
+
}
|
|
73
80
|
reset({
|
|
74
81
|
ruleName: existingRule.Id || '',
|
|
75
82
|
queueArn: existingRule.QueueArn || '',
|
|
76
|
-
events
|
|
83
|
+
events,
|
|
77
84
|
prefix: prefixRule?.Value || '',
|
|
78
85
|
suffix: suffixRule?.Value || ''
|
|
79
86
|
});
|
|
@@ -81,7 +88,8 @@ function BucketNotificationFormPage() {
|
|
|
81
88
|
}, [
|
|
82
89
|
isEditMode,
|
|
83
90
|
existingRule,
|
|
84
|
-
reset
|
|
91
|
+
reset,
|
|
92
|
+
supportedEvents
|
|
85
93
|
]);
|
|
86
94
|
const handleCancel = useCallback(()=>{
|
|
87
95
|
navigate(`/buckets/${bucketName}?tab=notification`);
|
|
@@ -248,7 +256,7 @@ function BucketNotificationFormPage() {
|
|
|
248
256
|
direction: "horizontal",
|
|
249
257
|
error: errors?.ruleName?.message,
|
|
250
258
|
helpErrorPosition: "bottom",
|
|
251
|
-
labelHelpTooltip:
|
|
259
|
+
labelHelpTooltip: "Must be unique across all notification rules in this bucket. Cannot be changed after creation.",
|
|
252
260
|
required: true,
|
|
253
261
|
content: isEditMode ? /*#__PURE__*/ jsx(Text, {
|
|
254
262
|
children: existingRule?.Id
|
|
@@ -267,7 +275,7 @@ function BucketNotificationFormPage() {
|
|
|
267
275
|
direction: "horizontal",
|
|
268
276
|
error: errors?.queueArn?.message,
|
|
269
277
|
helpErrorPosition: "bottom",
|
|
270
|
-
labelHelpTooltip:
|
|
278
|
+
labelHelpTooltip: "Expected format: arn:aws:sqs:region:account-id:queue-name",
|
|
271
279
|
required: true,
|
|
272
280
|
content: /*#__PURE__*/ jsx(Input, {
|
|
273
281
|
id: "queueArn",
|
|
@@ -8,7 +8,7 @@ export { BucketList } from './buckets/BucketList';
|
|
|
8
8
|
export { BucketOverview, BucketOverviewField, BucketOverviewSection, useBucketOverviewContext, } from './buckets/BucketOverview';
|
|
9
9
|
export { BucketPage } from './buckets/BucketPage';
|
|
10
10
|
export { BucketPolicyPage } from './buckets/BucketPolicyPage';
|
|
11
|
-
export { BucketReplicationFormPage } from './buckets/BucketReplicationFormPage';
|
|
11
|
+
export { BucketReplicationFormPage, DefaultReplicationDestinationFields, } from './buckets/BucketReplicationFormPage';
|
|
12
12
|
export { BucketVersioning } from './buckets/BucketVersioning';
|
|
13
13
|
export { DeleteBucketButton } from './buckets/DeleteBucketButton';
|
|
14
14
|
export { EmptyBucketButton } from './buckets/EmptyBucketButton';
|
package/dist/components/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { BucketList } from "./buckets/BucketList.js";
|
|
|
8
8
|
import { BucketOverview, BucketOverviewField, BucketOverviewSection, useBucketOverviewContext } from "./buckets/BucketOverview.js";
|
|
9
9
|
import { BucketPage } from "./buckets/BucketPage.js";
|
|
10
10
|
import { BucketPolicyPage } from "./buckets/BucketPolicyPage.js";
|
|
11
|
-
import { BucketReplicationFormPage } from "./buckets/BucketReplicationFormPage.js";
|
|
11
|
+
import { BucketReplicationFormPage, DefaultReplicationDestinationFields } from "./buckets/BucketReplicationFormPage.js";
|
|
12
12
|
import { BucketVersioning } from "./buckets/BucketVersioning.js";
|
|
13
13
|
import { DeleteBucketButton } from "./buckets/DeleteBucketButton.js";
|
|
14
14
|
import { EmptyBucketButton } from "./buckets/EmptyBucketButton.js";
|
|
@@ -25,4 +25,4 @@ import { DataBrowserProvider, useDataBrowserConfig, useDataBrowserContext, useIn
|
|
|
25
25
|
import { QueryProvider } from "./providers/QueryProvider.js";
|
|
26
26
|
import { MetadataSearch } from "./search/MetadataSearch.js";
|
|
27
27
|
import { ArrayFieldActions } from "./ui/ArrayFieldActions.js";
|
|
28
|
-
export { ArrayFieldActions, Breadcrumb, BucketAccessor, BucketCorsPage, BucketCreate, BucketLifecycleFormPage, BucketList, BucketNotificationFormPage, BucketOverview, BucketOverviewField, BucketOverviewSection, BucketPage, BucketPolicyPage, BucketReplicationFormPage, BucketVersioning, CreateFolderButton, DataBrowserBreadcrumb, DataBrowserProvider, DataBrowserUI, DeleteBucketButton, EditRetentionButton, EmptyBucketButton, MetadataSearch, ObjectDetails, ObjectList, ObjectLockSettings, ObjectPage, QueryProvider, UploadButton, baseBucketCreateSchema, bucketErrorMessage, bucketNameValidationSchema, useBreadcrumbPaths, useBucketOverviewContext, useDataBrowserConfig, useDataBrowserContext, useDataBrowserNavigate, useInvalidateQueries };
|
|
28
|
+
export { ArrayFieldActions, Breadcrumb, BucketAccessor, BucketCorsPage, BucketCreate, BucketLifecycleFormPage, BucketList, BucketNotificationFormPage, BucketOverview, BucketOverviewField, BucketOverviewSection, BucketPage, BucketPolicyPage, BucketReplicationFormPage, BucketVersioning, CreateFolderButton, DataBrowserBreadcrumb, DataBrowserProvider, DataBrowserUI, DefaultReplicationDestinationFields, DeleteBucketButton, EditRetentionButton, EmptyBucketButton, MetadataSearch, ObjectDetails, ObjectList, ObjectLockSettings, ObjectPage, QueryProvider, UploadButton, baseBucketCreateSchema, bucketErrorMessage, bucketNameValidationSchema, useBreadcrumbPaths, useBucketOverviewContext, useDataBrowserConfig, useDataBrowserContext, useDataBrowserNavigate, useInvalidateQueries };
|
|
@@ -5,7 +5,7 @@ import { cleanup, render, screen } from "@testing-library/react";
|
|
|
5
5
|
import { MemoryRouter, Route, Routes } from "react-router";
|
|
6
6
|
import { DataBrowserUICustomizationProvider } from "../../../../contexts/DataBrowserUICustomizationContext.js";
|
|
7
7
|
var __webpack_modules__ = {
|
|
8
|
-
"
|
|
8
|
+
".." (module) {
|
|
9
9
|
module.exports = __rspack_external__index_js_95fdb65a;
|
|
10
10
|
}
|
|
11
11
|
};
|
|
@@ -19,7 +19,7 @@ function __webpack_require__(moduleId) {
|
|
|
19
19
|
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
|
20
20
|
return module.exports;
|
|
21
21
|
}
|
|
22
|
-
var external_index_js_ = __webpack_require__("
|
|
22
|
+
var external_index_js_ = __webpack_require__("..");
|
|
23
23
|
jest.mock('../ObjectSummary', ()=>({
|
|
24
24
|
ObjectSummary: ()=>/*#__PURE__*/ jsx("div", {
|
|
25
25
|
"data-testid": "object-summary",
|
|
@@ -398,7 +398,7 @@ describe('ObjectDetails', ()=>{
|
|
|
398
398
|
expect(screen.getByTestId('object-summary')).toBeInTheDocument();
|
|
399
399
|
});
|
|
400
400
|
it('should throw error when useObjectDetailsContext is used outside provider', ()=>{
|
|
401
|
-
const { useObjectDetailsContext } = __webpack_require__("
|
|
401
|
+
const { useObjectDetailsContext } = __webpack_require__("..");
|
|
402
402
|
const TestComponent = ()=>{
|
|
403
403
|
useObjectDetailsContext();
|
|
404
404
|
return null;
|
|
@@ -5,7 +5,7 @@ import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "rea
|
|
|
5
5
|
import { useLocation, useNavigate } from "react-router";
|
|
6
6
|
import styled_components from "styled-components";
|
|
7
7
|
import { useDataBrowserUICustomization } from "../../contexts/DataBrowserUICustomizationContext.js";
|
|
8
|
-
import { useSearchObjects, useSearchObjectsVersions } from "../../hooks/index.js";
|
|
8
|
+
import { useListObjectVersions, useListObjects, useSearchObjects, useSearchObjectsVersions } from "../../hooks/index.js";
|
|
9
9
|
import { useGetPresignedDownload } from "../../hooks/presignedOperations.js";
|
|
10
10
|
import { useBatchObjectLegalHold } from "../../hooks/useBatchObjectLegalHold.js";
|
|
11
11
|
import { useFeatures } from "../../hooks/useFeatures.js";
|
|
@@ -370,28 +370,8 @@ const ObjectList = ({ bucketName, prefix, onObjectSelect, onPrefixChange, onSele
|
|
|
370
370
|
getPresignedDownload,
|
|
371
371
|
showToast
|
|
372
372
|
]);
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
Bucket: bucketName,
|
|
376
|
-
Prefix: prefix,
|
|
377
|
-
MaxKeys: DEFAULT_PAGE_SIZE,
|
|
378
|
-
Delimiter: '/'
|
|
379
|
-
};
|
|
380
|
-
if (isMetadataSearchEnabled && metadataSearchQuery) return {
|
|
381
|
-
...baseParams,
|
|
382
|
-
Search: metadataSearchQuery
|
|
383
|
-
};
|
|
384
|
-
return baseParams;
|
|
385
|
-
}, [
|
|
386
|
-
bucketName,
|
|
387
|
-
prefix,
|
|
388
|
-
isMetadataSearchEnabled,
|
|
389
|
-
metadataSearchQuery
|
|
390
|
-
]);
|
|
391
|
-
const listObjectsQuery = useSearchObjects(searchParams, {
|
|
392
|
-
enabled: Boolean(bucketName)
|
|
393
|
-
});
|
|
394
|
-
const versionSearchParams = useMemo(()=>({
|
|
373
|
+
const isSearchActive = isMetadataSearchEnabled && Boolean(metadataSearchQuery);
|
|
374
|
+
const baseParams = useMemo(()=>({
|
|
395
375
|
Bucket: bucketName,
|
|
396
376
|
Prefix: prefix,
|
|
397
377
|
MaxKeys: DEFAULT_PAGE_SIZE,
|
|
@@ -400,9 +380,26 @@ const ObjectList = ({ bucketName, prefix, onObjectSelect, onPrefixChange, onSele
|
|
|
400
380
|
bucketName,
|
|
401
381
|
prefix
|
|
402
382
|
]);
|
|
403
|
-
const
|
|
404
|
-
enabled:
|
|
383
|
+
const regularListQuery = useListObjects(baseParams, {
|
|
384
|
+
enabled: Boolean(bucketName) && !isSearchActive
|
|
385
|
+
});
|
|
386
|
+
const searchListQuery = useSearchObjects({
|
|
387
|
+
...baseParams,
|
|
388
|
+
Query: metadataSearchQuery || ''
|
|
389
|
+
}, {
|
|
390
|
+
enabled: Boolean(bucketName) && isSearchActive
|
|
391
|
+
});
|
|
392
|
+
const listObjectsQuery = isSearchActive ? searchListQuery : regularListQuery;
|
|
393
|
+
const regularVersionsQuery = useListObjectVersions(baseParams, {
|
|
394
|
+
enabled: showVersions && Boolean(bucketName) && !isSearchActive
|
|
395
|
+
});
|
|
396
|
+
const searchVersionsQuery = useSearchObjectsVersions({
|
|
397
|
+
...baseParams,
|
|
398
|
+
Query: metadataSearchQuery || ''
|
|
399
|
+
}, {
|
|
400
|
+
enabled: showVersions && Boolean(bucketName) && isSearchActive
|
|
405
401
|
});
|
|
402
|
+
const listVersionsQuery = isSearchActive ? searchVersionsQuery : regularVersionsQuery;
|
|
406
403
|
useEffect(()=>{
|
|
407
404
|
setSelectedObjects([]);
|
|
408
405
|
onObjectSelectRef.current(null);
|
|
@@ -5,8 +5,8 @@ import { useISVBucketStatus } from "../../../hooks/index.js";
|
|
|
5
5
|
import { useDataBrowserNavigate } from "../../../hooks/useDataBrowserNavigate.js";
|
|
6
6
|
const EditRetentionButton = ({ bucketName })=>{
|
|
7
7
|
const navigate = useDataBrowserNavigate();
|
|
8
|
-
const {
|
|
9
|
-
const tooltipOverlay =
|
|
8
|
+
const { isISVManaged, isvApplication, isLoading } = useISVBucketStatus(bucketName);
|
|
9
|
+
const tooltipOverlay = isISVManaged ? `Edition is disabled as it is managed by ${isvApplication}.` : void 0;
|
|
10
10
|
return /*#__PURE__*/ jsx(Button, {
|
|
11
11
|
id: "edit-retention-btn",
|
|
12
12
|
variant: "outline",
|
package/dist/config/types.d.ts
CHANGED
|
@@ -262,6 +262,17 @@ export interface DataBrowserUIProps {
|
|
|
262
262
|
* - "legalHold" - Legal Hold field
|
|
263
263
|
*/
|
|
264
264
|
extraObjectSummaryDataProtection?: FieldConfig[];
|
|
265
|
+
/** Pre-fills the Role ARN input field with this value. */
|
|
266
|
+
replicationRoleDefault?: string;
|
|
267
|
+
/**
|
|
268
|
+
* When provided, replaces the default destination fields
|
|
269
|
+
* (sameAccount toggle, targetBucket, targetAccountId, switchObjectOwnership).
|
|
270
|
+
* The StorageClass/Location selector is rendered separately above.
|
|
271
|
+
*
|
|
272
|
+
* Use `DefaultReplicationDestinationFields` (exported from the library)
|
|
273
|
+
* to fall back to default behavior for non-custom cases.
|
|
274
|
+
*/
|
|
275
|
+
replicationDestinationFields?: React.ComponentType;
|
|
265
276
|
}
|
|
266
277
|
export type S3EventType = 's3:ObjectCreated:*' | 's3:ObjectCreated:Put' | 's3:ObjectCreated:Post' | 's3:ObjectCreated:Copy' | 's3:ObjectCreated:CompleteMultipartUpload' | 's3:ObjectRemoved:*' | 's3:ObjectRemoved:Delete' | 's3:ObjectRemoved:DeleteMarkerCreated' | 's3:ObjectRestore:*' | 's3:ObjectRestore:Post' | 's3:ObjectRestore:Completed' | 's3:ObjectRestore:Delete' | 's3:LifecycleExpiration:*' | 's3:LifecycleExpiration:Delete' | 's3:LifecycleExpiration:DeleteMarkerCreated' | 's3:LifecycleTransition' | 's3:Replication:*' | 's3:Replication:OperationFailedReplication' | 's3:Replication:OperationMissedThreshold' | 's3:Replication:OperationReplicatedAfterThreshold' | 's3:Replication:OperationNotTracked' | 's3:ObjectTagging:*' | 's3:ObjectTagging:Put' | 's3:ObjectTagging:Delete' | 's3:ReducedRedundancyLostObject' | 's3:IntelligentTiering' | 's3:ObjectAcl:Put' | 's3:TestEvent';
|
|
267
278
|
export type S3EventCategory = 'Object Creation' | 'Object Deletion' | 'Object Restoration' | 'Lifecycle' | 'Replication' | 'Object Tagging' | 'Storage & Access' | 'Testing';
|
|
@@ -46,6 +46,7 @@ function getPaginationParams(operationName, pageParam) {
|
|
|
46
46
|
ContinuationToken: pageParam
|
|
47
47
|
};
|
|
48
48
|
case 'ListObjectVersions':
|
|
49
|
+
case 'SearchObjectsVersions':
|
|
49
50
|
if (pageParam.includes('|')) {
|
|
50
51
|
const [keyMarker, versionIdMarker] = pageParam.split('|');
|
|
51
52
|
return {
|
|
@@ -71,6 +72,7 @@ function getNextPageToken(operationName, lastPage) {
|
|
|
71
72
|
case 'ListObjects':
|
|
72
73
|
return lastPage.IsTruncated ? lastPage.NextContinuationToken : void 0;
|
|
73
74
|
case 'ListObjectVersions':
|
|
75
|
+
case 'SearchObjectsVersions':
|
|
74
76
|
return lastPage.IsTruncated && (lastPage.NextKeyMarker || lastPage.NextVersionIdMarker) ? `${lastPage.NextKeyMarker || ''}|${lastPage.NextVersionIdMarker || ''}` : void 0;
|
|
75
77
|
default:
|
|
76
78
|
return lastPage.IsTruncated ? lastPage.NextContinuationToken : void 0;
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { useCopyObject, useCreateFolder, useDeleteObject, useDeleteObjects, useD
|
|
|
6
6
|
export { useGetPresignedDownload, useGetPresignedPost, useGetPresignedUpload, } from './presignedOperations';
|
|
7
7
|
export { getAccessibleBucketsStorageKey, getLimitedAccessFlagKey, setLimitedAccessFlag, useAccessibleBuckets, } from './useAccessibleBuckets';
|
|
8
8
|
export { useBatchObjectLegalHold } from './useBatchObjectLegalHold';
|
|
9
|
-
export { type BucketConfigEditorConfig, type BucketConfigEditorResult, useBucketConfigEditor
|
|
9
|
+
export { type BucketConfigEditorConfig, type BucketConfigEditorResult, useBucketConfigEditor } from './useBucketConfigEditor';
|
|
10
10
|
export { useBucketLocations } from './useBucketLocations';
|
|
11
11
|
export { useDeleteBucketConfigRule } from './useDeleteBucketConfigRule';
|
|
12
12
|
export { useEmptyBucket } from './useEmptyBucket';
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* configurations like retention and legal hold.
|
|
7
7
|
*/
|
|
8
8
|
import { type CopyObjectCommandInput, type CopyObjectCommandOutput, type DeleteObjectCommandInput, type DeleteObjectCommandOutput, type DeleteObjectsCommandInput, type DeleteObjectsCommandOutput, type DeleteObjectTaggingCommandInput, type DeleteObjectTaggingCommandOutput, type GetObjectAclCommandInput, type GetObjectAclCommandOutput, type GetObjectAttributesCommandInput, type GetObjectAttributesCommandOutput, type GetObjectCommandInput, type GetObjectCommandOutput, type GetObjectLegalHoldCommandInput, type GetObjectLegalHoldCommandOutput, type GetObjectRetentionCommandInput, type GetObjectRetentionCommandOutput, type GetObjectTaggingCommandInput, type GetObjectTaggingCommandOutput, type GetObjectTorrentCommandInput, type GetObjectTorrentCommandOutput, type HeadObjectCommandInput, type HeadObjectCommandOutput, type ListMultipartUploadsCommandInput, type ListMultipartUploadsCommandOutput, type ListObjectsV2CommandInput, type ListObjectVersionsCommandInput, type PutObjectAclCommandInput, type PutObjectAclCommandOutput, type PutObjectCommandInput, type PutObjectCommandOutput, type PutObjectLegalHoldCommandInput, type PutObjectLegalHoldCommandOutput, type PutObjectRetentionCommandInput, type PutObjectRetentionCommandOutput, type PutObjectTaggingCommandInput, type PutObjectTaggingCommandOutput, type RestoreObjectCommandInput, type RestoreObjectCommandOutput, type SelectObjectContentCommandInput, type SelectObjectContentCommandOutput } from '@aws-sdk/client-s3';
|
|
9
|
-
import { type
|
|
9
|
+
import { type ListObjectsV2ExtendedInput, type ListObjectVersionsExtendedInput } from '@scality/cloudserverclient';
|
|
10
10
|
/**
|
|
11
11
|
* Hook for listing S3 objects with infinite scroll support
|
|
12
12
|
*
|
|
@@ -27,14 +27,14 @@ export declare const useListObjectVersions: (params: ListObjectVersionsCommandIn
|
|
|
27
27
|
* Provides paginated search of objects in an S3 bucket using SQL-like query syntax.
|
|
28
28
|
* Supports advanced filtering and pattern matching on object keys and metadata.
|
|
29
29
|
*/
|
|
30
|
-
export declare const useSearchObjects: (params:
|
|
30
|
+
export declare const useSearchObjects: (params: ListObjectsV2ExtendedInput, options?: Partial<import("@tanstack/react-query").UseInfiniteQueryOptions<any, import("..").EnhancedS3Error, any, (string | ListObjectsV2ExtendedInput)[], string | undefined>> | undefined) => import("@tanstack/react-query").UseInfiniteQueryResult<any, import("..").EnhancedS3Error>;
|
|
31
31
|
/**
|
|
32
32
|
* Hook for searching S3 object versions with infinite scroll support
|
|
33
33
|
*
|
|
34
34
|
* Provides paginated search of object versions in an S3 bucket using SQL-like query syntax.
|
|
35
35
|
* Supports advanced filtering and pattern matching on object keys and metadata across all versions.
|
|
36
36
|
*/
|
|
37
|
-
export declare const useSearchObjectsVersions: (params:
|
|
37
|
+
export declare const useSearchObjectsVersions: (params: ListObjectVersionsExtendedInput, options?: Partial<import("@tanstack/react-query").UseInfiniteQueryOptions<any, import("..").EnhancedS3Error, any, (string | ListObjectVersionsExtendedInput)[], string | undefined>> | undefined) => import("@tanstack/react-query").UseInfiniteQueryResult<any, import("..").EnhancedS3Error>;
|
|
38
38
|
/**
|
|
39
39
|
* Hook for retrieving S3 object metadata
|
|
40
40
|
*
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { CopyObjectCommand, DeleteObjectCommand, DeleteObjectTaggingCommand, DeleteObjectsCommand, GetObjectAclCommand, GetObjectAttributesCommand, GetObjectCommand, GetObjectLegalHoldCommand, GetObjectRetentionCommand, GetObjectTaggingCommand, GetObjectTorrentCommand, HeadObjectCommand, ListMultipartUploadsCommand, ListObjectVersionsCommand, ListObjectsV2Command, PutObjectAclCommand, PutObjectCommand, PutObjectLegalHoldCommand, PutObjectRetentionCommand, PutObjectTaggingCommand, RestoreObjectCommand, SelectObjectContentCommand } from "@aws-sdk/client-s3";
|
|
2
|
-
import {
|
|
2
|
+
import { ListObjectVersionsExtendedCommand, ListObjectsV2ExtendedCommand } from "@scality/cloudserverclient";
|
|
3
3
|
import { useCreateS3InfiniteQueryHook } from "./factories/useCreateS3InfiniteQueryHook.js";
|
|
4
4
|
import { useCreateS3MutationHook } from "./factories/useCreateS3MutationHook.js";
|
|
5
5
|
import { useCreateS3QueryHook } from "./factories/useCreateS3QueryHook.js";
|
|
6
6
|
const useListObjects = useCreateS3InfiniteQueryHook(ListObjectsV2Command, 'ListObjects');
|
|
7
7
|
const useListObjectVersions = useCreateS3InfiniteQueryHook(ListObjectVersionsCommand, 'ListObjectVersions');
|
|
8
|
-
const useSearchObjects = useCreateS3InfiniteQueryHook(
|
|
9
|
-
const useSearchObjectsVersions = useCreateS3InfiniteQueryHook(
|
|
8
|
+
const useSearchObjects = useCreateS3InfiniteQueryHook(ListObjectsV2ExtendedCommand, 'SearchObjects');
|
|
9
|
+
const useSearchObjectsVersions = useCreateS3InfiniteQueryHook(ListObjectVersionsExtendedCommand, 'SearchObjectsVersions');
|
|
10
10
|
const useObjectMetadata = useCreateS3QueryHook(HeadObjectCommand, 'HeadObject');
|
|
11
11
|
const useGetObject = useCreateS3QueryHook(GetObjectCommand, 'GetObject');
|
|
12
12
|
const usePutObject = useCreateS3MutationHook(PutObjectCommand, 'PutObject', [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { JSONSchema7 } from 'json-schema';
|
|
2
2
|
import { useForm } from 'react-hook-form';
|
|
3
3
|
type FormValues = {
|
|
4
4
|
content: string;
|
|
@@ -13,10 +13,9 @@ export type BucketConfigEditorConfig = {
|
|
|
13
13
|
initialContent: string | undefined;
|
|
14
14
|
defaultTemplate: string;
|
|
15
15
|
isLoading: boolean;
|
|
16
|
-
notFoundErrorNames: string[];
|
|
17
16
|
errorInstance: Error | null;
|
|
18
17
|
validate: (content: string) => ValidationResult;
|
|
19
|
-
|
|
18
|
+
jsonSchema?: JSONSchema7;
|
|
20
19
|
};
|
|
21
20
|
export type BucketConfigEditorResult = {
|
|
22
21
|
bucketName: string;
|
|
@@ -24,8 +23,9 @@ export type BucketConfigEditorResult = {
|
|
|
24
23
|
content: string;
|
|
25
24
|
isCreateMode: boolean;
|
|
26
25
|
isValidFormat: boolean;
|
|
27
|
-
|
|
26
|
+
jsonSchema?: JSONSchema7;
|
|
28
27
|
navigateToBucket: () => void;
|
|
28
|
+
loadTemplate: () => void;
|
|
29
29
|
};
|
|
30
30
|
export declare const useBucketConfigEditor: (config: BucketConfigEditorConfig) => BucketConfigEditorResult;
|
|
31
31
|
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo } from "react";
|
|
2
2
|
import { useForm } from "react-hook-form";
|
|
3
|
+
import { isNotFoundError } from "../utils/errorHandling.js";
|
|
3
4
|
import { useDataBrowserNavigate } from "./useDataBrowserNavigate.js";
|
|
4
5
|
const useBucketConfigEditor = (config)=>{
|
|
5
6
|
const navigate = useDataBrowserNavigate();
|
|
@@ -12,12 +13,8 @@ const useBucketConfigEditor = (config)=>{
|
|
|
12
13
|
});
|
|
13
14
|
const { watch, reset } = form;
|
|
14
15
|
const content = watch('content');
|
|
15
|
-
const isCreateMode = useMemo(()=>
|
|
16
|
-
|
|
17
|
-
return config.notFoundErrorNames.some((name)=>config.errorInstance?.name === name);
|
|
18
|
-
}, [
|
|
19
|
-
config.errorInstance,
|
|
20
|
-
config.notFoundErrorNames
|
|
16
|
+
const isCreateMode = useMemo(()=>isNotFoundError(config.errorInstance), [
|
|
17
|
+
config.errorInstance
|
|
21
18
|
]);
|
|
22
19
|
const initialValue = useMemo(()=>{
|
|
23
20
|
if (config.initialContent) try {
|
|
@@ -26,10 +23,9 @@ const useBucketConfigEditor = (config)=>{
|
|
|
26
23
|
} catch {
|
|
27
24
|
return config.initialContent;
|
|
28
25
|
}
|
|
29
|
-
return
|
|
26
|
+
return '';
|
|
30
27
|
}, [
|
|
31
|
-
config.initialContent
|
|
32
|
-
config.defaultTemplate
|
|
28
|
+
config.initialContent
|
|
33
29
|
]);
|
|
34
30
|
useEffect(()=>{
|
|
35
31
|
reset({
|
|
@@ -43,40 +39,29 @@ const useBucketConfigEditor = (config)=>{
|
|
|
43
39
|
content,
|
|
44
40
|
config.validate
|
|
45
41
|
]);
|
|
46
|
-
const handleBeforeMount = useCallback((monaco)=>{
|
|
47
|
-
const jsonLanguage = monaco.languages.json;
|
|
48
|
-
if (jsonLanguage?.jsonDefaults) if (config.monacoSchema) jsonLanguage.jsonDefaults.setDiagnosticsOptions({
|
|
49
|
-
validate: true,
|
|
50
|
-
schemas: [
|
|
51
|
-
{
|
|
52
|
-
uri: 'http://myserver/schema.json',
|
|
53
|
-
fileMatch: [
|
|
54
|
-
'*'
|
|
55
|
-
],
|
|
56
|
-
schema: config.monacoSchema
|
|
57
|
-
}
|
|
58
|
-
]
|
|
59
|
-
});
|
|
60
|
-
else jsonLanguage.jsonDefaults.setDiagnosticsOptions({
|
|
61
|
-
validate: true
|
|
62
|
-
});
|
|
63
|
-
}, [
|
|
64
|
-
config.monacoSchema
|
|
65
|
-
]);
|
|
66
42
|
const navigateToBucket = useCallback(()=>{
|
|
67
43
|
navigate(`/buckets/${bucketName}`);
|
|
68
44
|
}, [
|
|
69
45
|
navigate,
|
|
70
46
|
bucketName
|
|
71
47
|
]);
|
|
48
|
+
const loadTemplate = useCallback(()=>{
|
|
49
|
+
form.setValue('content', config.defaultTemplate, {
|
|
50
|
+
shouldDirty: true
|
|
51
|
+
});
|
|
52
|
+
}, [
|
|
53
|
+
form,
|
|
54
|
+
config.defaultTemplate
|
|
55
|
+
]);
|
|
72
56
|
return {
|
|
73
57
|
bucketName,
|
|
74
58
|
form,
|
|
75
59
|
content,
|
|
76
60
|
isCreateMode,
|
|
77
61
|
isValidFormat,
|
|
78
|
-
|
|
79
|
-
navigateToBucket
|
|
62
|
+
jsonSchema: config.jsonSchema,
|
|
63
|
+
navigateToBucket,
|
|
64
|
+
loadTemplate
|
|
80
65
|
};
|
|
81
66
|
};
|
|
82
67
|
export { useBucketConfigEditor };
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import type { S3ClientConfig } from '@aws-sdk/client-s3';
|
|
|
2
2
|
import type { AwsCredentialIdentity } from '@aws-sdk/types';
|
|
3
3
|
import type { ProxyConfiguration, S3EventType } from '../config/types';
|
|
4
4
|
export type { _Object, Bucket, BucketCannedACL, BucketLocationConstraint, CopyObjectCommandInput, CopyObjectCommandOutput, CreateBucketCommandInput, CreateBucketCommandOutput, DeleteBucketCommandInput, DeleteBucketCommandOutput, DeleteBucketCorsCommandOutput, DeleteBucketLifecycleCommandOutput, DeleteBucketPolicyCommandOutput, DeleteBucketReplicationCommandOutput, DeleteBucketTaggingCommandOutput, DeleteMarkerEntry, DeleteObjectCommandInput, DeleteObjectCommandOutput, DeleteObjectsCommandInput, DeleteObjectsCommandOutput, DeleteObjectTaggingCommandOutput, GetBucketAclCommandOutput, GetBucketCorsCommandOutput, GetBucketEncryptionCommandOutput, GetBucketLifecycleConfigurationCommandOutput, GetBucketLocationCommandInput, GetBucketLocationCommandOutput, GetBucketNotificationConfigurationCommandOutput, GetBucketPolicyCommandOutput, GetBucketReplicationCommandOutput, GetBucketTaggingCommandOutput, GetBucketVersioningCommandOutput, GetObjectAclCommandOutput, GetObjectAttributesCommandInput, GetObjectAttributesCommandOutput, GetObjectCommandInput, GetObjectCommandOutput, GetObjectLegalHoldCommandOutput, GetObjectLockConfigurationCommandOutput, GetObjectRetentionCommandOutput, GetObjectTaggingCommandOutput, GetObjectTorrentCommandOutput, HeadObjectCommandInput, HeadObjectCommandOutput, ListBucketsCommandOutput, ListMultipartUploadsCommandInput, ListMultipartUploadsCommandOutput, ListObjectsV2CommandInput, ListObjectsV2CommandOutput, ListObjectVersionsCommandInput, ListObjectVersionsCommandOutput, ObjectCannedACL, ObjectVersion, Owner, PutBucketAclCommandInput, PutBucketCorsCommandInput, PutBucketEncryptionCommandInput, PutBucketLifecycleConfigurationCommandInput, PutBucketNotificationConfigurationCommandInput, PutBucketPolicyCommandInput, PutBucketReplicationCommandInput, PutBucketTaggingCommandInput, PutBucketTaggingCommandOutput, PutBucketVersioningCommandInput, PutObjectAclCommandInput, PutObjectCommandInput, PutObjectCommandOutput, PutObjectLegalHoldCommandInput, PutObjectLockConfigurationCommandInput, PutObjectRetentionCommandInput, PutObjectTaggingCommandInput, RestoreObjectCommandInput, RestoreObjectCommandOutput, SelectObjectContentCommandInput, SelectObjectContentCommandOutput, Tag, } from '@aws-sdk/client-s3';
|
|
5
|
-
export type { MonacoJsonDefaults, MonacoLanguagesJson } from './monaco';
|
|
6
5
|
/**
|
|
7
6
|
* S3 backend capabilities configuration.
|
|
8
7
|
*/
|
|
@@ -333,12 +333,45 @@ describe('createProxyMiddleware', ()=>{
|
|
|
333
333
|
expect(mockRequest.protocol).toBe('http:');
|
|
334
334
|
expect(mockRequest.path).toBe('/api/s3/bucket/key');
|
|
335
335
|
expect(mockRequest.headers.host).toBe('localhost:3000');
|
|
336
|
+
expect(mockRequest.headers['x-s3-target-endpoint']).toBe('https://s3.amazonaws.com');
|
|
336
337
|
expect(mockRequest.query).toEqual({
|
|
337
338
|
param: 'value'
|
|
338
339
|
});
|
|
339
340
|
expect(mockRequest.headers.authorization).toBe('AWS4-HMAC-SHA256 Credential=...');
|
|
340
341
|
expect(mockNext).toHaveBeenCalledTimes(1);
|
|
341
342
|
});
|
|
343
|
+
it('should set X-S3-Target-Endpoint header with custom port', async ()=>{
|
|
344
|
+
const mockNext = jest.fn().mockResolvedValue({
|
|
345
|
+
output: {}
|
|
346
|
+
});
|
|
347
|
+
const mockStack = {
|
|
348
|
+
add: jest.fn((middleware, config)=>{
|
|
349
|
+
if ('finalizeRequest' === config.step) mockStack.postSigningMiddleware = middleware;
|
|
350
|
+
}),
|
|
351
|
+
postSigningMiddleware: null
|
|
352
|
+
};
|
|
353
|
+
const middleware = createProxyMiddleware({
|
|
354
|
+
enabled: true,
|
|
355
|
+
endpoint: 'http://localhost:3000/api/s3',
|
|
356
|
+
target: 'http://s3.local:9000'
|
|
357
|
+
});
|
|
358
|
+
middleware.applyToStack(mockStack);
|
|
359
|
+
const postSigningMiddleware = mockStack.postSigningMiddleware(mockNext);
|
|
360
|
+
const mockRequest = new HttpRequest({
|
|
361
|
+
hostname: 's3.local',
|
|
362
|
+
port: 9000,
|
|
363
|
+
path: '/bucket/key',
|
|
364
|
+
protocol: 'http:',
|
|
365
|
+
headers: {
|
|
366
|
+
host: 's3.local:9000'
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
await postSigningMiddleware({
|
|
370
|
+
request: mockRequest,
|
|
371
|
+
input: {}
|
|
372
|
+
});
|
|
373
|
+
expect(mockRequest.headers['x-s3-target-endpoint']).toBe('http://s3.local:9000');
|
|
374
|
+
});
|
|
342
375
|
it('should preserve authorization header when routing through proxy', async ()=>{
|
|
343
376
|
const mockNext = jest.fn().mockResolvedValue({
|
|
344
377
|
output: {}
|
|
@@ -574,6 +607,7 @@ describe('createProxyMiddleware', ()=>{
|
|
|
574
607
|
expect(mockRequest.hostname).toBe(originalHostname);
|
|
575
608
|
expect(mockRequest.path).toBe(originalPath);
|
|
576
609
|
expect(mockRequest.port).toBe(originalPort);
|
|
610
|
+
expect(mockRequest.headers['x-s3-target-endpoint']).toBeUndefined();
|
|
577
611
|
});
|
|
578
612
|
});
|
|
579
613
|
});
|