@controleonline/ui-common 1.2.104 → 1.2.105
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/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {env as APP_ENV} from '@env';
|
|
2
|
-
import {filterApiHeaders} from '../../utils/trustedApiUrl';
|
|
2
|
+
import {filterApiHeaders, isTrustedApiUrl} from '../../utils/trustedApiUrl';
|
|
3
3
|
import {buildAssetUrl} from '@controleonline/../../src/styles/branding';
|
|
4
4
|
import {
|
|
5
5
|
resolveAppDomain,
|
|
@@ -79,16 +79,11 @@ const ensureAbsoluteUrl = url => {
|
|
|
79
79
|
const resolveDownloadHost = ({company = null, appDomain = ''} = {}) => {
|
|
80
80
|
const fallbackDomain =
|
|
81
81
|
normalizeText(appDomain) || resolveAppDomain(APP_ENV?.DOMAIN);
|
|
82
|
-
|
|
82
|
+
const companyDomain = resolveCompanyDomain(company, fallbackDomain);
|
|
83
|
+
// FileService may return the API authority instead of an application domain.
|
|
84
|
+
return isApiEntrypointHost(companyDomain) ? fallbackDomain : companyDomain;
|
|
83
85
|
};
|
|
84
86
|
|
|
85
|
-
/**
|
|
86
|
-
* Environment / platform hosts (staging, dev, localhost) are not tenant domains.
|
|
87
|
-
* Injecting them into /{host}/files/{id}/download produces URLs like
|
|
88
|
-
* https://s.controleonline.com/staging.controleonline.com/files/... → 403.
|
|
89
|
-
* Keep app-domain header only; do not path-inject environment hosts.
|
|
90
|
-
* app-community#432
|
|
91
|
-
*/
|
|
92
87
|
const resolveApiEntrypointHost = () => {
|
|
93
88
|
const entry = normalizeText(APP_ENV?.API_ENTRYPOINT);
|
|
94
89
|
if (!entry) {
|
|
@@ -216,11 +211,10 @@ const buildTenantDownloadUrl = (url, host) => {
|
|
|
216
211
|
return absoluteUrl;
|
|
217
212
|
}
|
|
218
213
|
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
if (isEnvironmentLikeHost(normalizedHost) || isApiEntrypointHost(normalizedHost)) {
|
|
214
|
+
// Public file routes require the application domain, including registered
|
|
215
|
+
// staging/dev/platform domains. Never use the API authority as that domain.
|
|
216
|
+
if (isApiEntrypointHost(normalizedHost) ||
|
|
217
|
+
!isTrustedApiUrl(absoluteUrl, APP_ENV?.API_ENTRYPOINT)) {
|
|
224
218
|
return absoluteUrl;
|
|
225
219
|
}
|
|
226
220
|
|
|
@@ -377,8 +371,11 @@ const resolveFileSource = (
|
|
|
377
371
|
isDownloadLikeUrl(normalizedFile?.uri) ||
|
|
378
372
|
isDownloadLikeUrl(normalizedFile?.url) ||
|
|
379
373
|
isDownloadLikeUrl(normalizedFile?.path);
|
|
374
|
+
const rawUrl = normalizedFile.url || normalizedFile.path || normalizedFile.uri;
|
|
375
|
+
// Relative backend paths belong to API_ENTRYPOINT. File.domain selects the
|
|
376
|
+
// route's tenant segment, not a new server origin.
|
|
380
377
|
const uriBase =
|
|
381
|
-
directUrl ||
|
|
378
|
+
(isDownloadLikeUrl(rawUrl) ? rawUrl : directUrl) ||
|
|
382
379
|
(fileId ? buildBackendDownloadUrl(fileId, {company, appDomain}) : '');
|
|
383
380
|
|
|
384
381
|
if (!uriBase) {
|
|
@@ -14,6 +14,28 @@ const {
|
|
|
14
14
|
} = require('../../../react/utils/fileUrl');
|
|
15
15
|
|
|
16
16
|
describe('fileUrl helpers', () => {
|
|
17
|
+
it.each([
|
|
18
|
+
'staging.controleonline.com', 'dev.controleonline.com',
|
|
19
|
+
'admin.controleonline.com', 'manager.controleonline.com',
|
|
20
|
+
'pos.lave-go.com', 'shop.lave-go.com', 'delivery.controleonline.com',
|
|
21
|
+
'crm.controleonline.com', 'ppc.controleonline.com', 'service.controleonline.com',
|
|
22
|
+
'localhost:8081',
|
|
23
|
+
])('resolves shared file shapes on the application route for %s', appDomain => {
|
|
24
|
+
for (const file of [6042, '/files/6042', '/files/6042/download',
|
|
25
|
+
{id: 6042, domain: 'api.controleonline.com', url: '/api.controleonline.com/files/6042/download'},
|
|
26
|
+
{file: {id: 6042, url: '/files/6042/download'}}]) {
|
|
27
|
+
const source = resolveDefaultFileSource(file, {appDomain, headers: {'API-TOKEN': 'session'}});
|
|
28
|
+
expect(source.uri).toBe(`https://api.controleonline.com/${encodeURIComponent(appDomain)}/files/6042/download`);
|
|
29
|
+
expect(source.headers).toEqual({'API-TOKEN': 'session', 'app-domain': appDomain});
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('preserves URL parameters and fragments while replacing an infrastructure prefix', () => {
|
|
34
|
+
expect(resolveFileImageUrl('/api.controleonline.com/files/6042/download?size=48&app-domain=old#image', {
|
|
35
|
+
appDomain: 'staging.controleonline.com',
|
|
36
|
+
})).toBe('https://api.controleonline.com/staging.controleonline.com/files/6042/download?size=48#image');
|
|
37
|
+
});
|
|
38
|
+
|
|
17
39
|
it('uses path app-domain for backend download urls and keeps headers', () => {
|
|
18
40
|
const company = {
|
|
19
41
|
domain: 'maincompany.controleonline.com',
|
|
@@ -108,6 +130,7 @@ describe('file authentication origin boundary', () => {
|
|
|
108
130
|
expect(source.headers).not.toHaveProperty('Authorization');
|
|
109
131
|
expect(source.headers).not.toHaveProperty('App-Domain');
|
|
110
132
|
expect(source.headers.Accept).toBe('image/*');
|
|
133
|
+
expect(source.uri).toBe(uri);
|
|
111
134
|
}
|
|
112
135
|
});
|
|
113
136
|
it('preserves authentication on the configured API download', () => {
|