Skip to content

Commit a37b358

Browse files
refactor: read whitlist from allowed-origins.json file in the main branch
1 parent 8a5c030 commit a37b358

3 files changed

Lines changed: 83 additions & 45 deletions

File tree

src/NMRiumWrapper.tsx

Lines changed: 50 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useEffect, useState, useCallback, CSSProperties, useRef } from 'react';
33
import events from './events';
44
import { usePreferences } from './hooks/usePreferences';
55
import { useLoadSpectra } from './hooks/useLoadSpectra';
6+
import { useWhiteList } from './hooks/useWhiteList';
67

78
const styles: Record<'container' | 'loadingContainer', CSSProperties> = {
89
container: {
@@ -30,6 +31,7 @@ const styles: Record<'container' | 'loadingContainer', CSSProperties> = {
3031
export type { NMRiumData };
3132

3233
export default function NMRiumWrapper() {
34+
const { allowedOrigins, isFetchAllowedOriginsPending } = useWhiteList();
3335
const nmriumRef = useRef<NMRiumRef>(null);
3436
const [data, setDate] = useState<NMRiumData>();
3537
const { workspace, preferences } = usePreferences();
@@ -46,44 +48,52 @@ export default function NMRiumWrapper() {
4648
}, [isLoading, loadedData]);
4749

4850
useEffect(() => {
49-
const clearActionListener = events.on('action-request', (request) => {
50-
switch (request.type) {
51-
case 'exportSpectraViewerAsBlob': {
52-
const blob = nmriumRef.current?.getSpectraViewerAsBlob();
53-
if (blob) {
54-
events.trigger('action-response', {
55-
type: request.type,
56-
data: blob,
57-
});
51+
const clearActionListener = events.on(
52+
'action-request',
53+
(request) => {
54+
switch (request.type) {
55+
case 'exportSpectraViewerAsBlob': {
56+
const blob = nmriumRef.current?.getSpectraViewerAsBlob();
57+
if (blob) {
58+
events.trigger('action-response', {
59+
type: request.type,
60+
data: blob,
61+
});
62+
}
63+
break;
64+
}
65+
default: {
66+
throw new Error(
67+
`ERROR! Property 'type' accept only 'exportViewerAsBlob'.`,
68+
);
5869
}
59-
break;
60-
}
61-
default: {
62-
throw new Error(
63-
`ERROR! Property 'type' accept only 'exportViewerAsBlob'.`,
64-
);
6570
}
66-
}
67-
});
68-
const clearLoadListener = events.on('load', (loadData) => {
69-
switch (loadData.type) {
70-
case 'nmrium':
71-
setDate(loadData.data);
72-
break;
73-
case 'file':
74-
loadSpectra({ files: loadData.data });
75-
break;
76-
case 'url':
77-
loadSpectra({ urls: loadData.data });
78-
break;
71+
},
72+
{ allowedOrigins },
73+
);
74+
const clearLoadListener = events.on(
75+
'load',
76+
(loadData) => {
77+
switch (loadData.type) {
78+
case 'nmrium':
79+
setDate(loadData.data);
80+
break;
81+
case 'file':
82+
loadSpectra({ files: loadData.data });
83+
break;
84+
case 'url':
85+
loadSpectra({ urls: loadData.data });
86+
break;
7987

80-
default: {
81-
throw new Error(
82-
`ERROR! Property 'type' accept only nmrium, url or file.`,
83-
);
88+
default: {
89+
throw new Error(
90+
`ERROR! Property 'type' accept only nmrium, url or file.`,
91+
);
92+
}
8493
}
85-
}
86-
});
94+
},
95+
{ allowedOrigins },
96+
);
8797

8898
return () => {
8999
clearLoadListener();
@@ -93,11 +103,12 @@ export default function NMRiumWrapper() {
93103

94104
return (
95105
<div style={styles.container}>
96-
{isLoading && (
97-
<div style={styles.loadingContainer}>
98-
<span>Loading .... </span>
99-
</div>
100-
)}
106+
{isLoading ||
107+
(isFetchAllowedOriginsPending && (
108+
<div style={styles.loadingContainer}>
109+
<span>Loading .... </span>
110+
</div>
111+
))}
101112
<NMRium
102113
ref={nmriumRef}
103114
data={data}

src/events/event.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { EventType, EventData } from './types';
2-
import ALLOWED_ORIGINS from '../allowed-origins.json';
32

43
const namespace = 'nmr-wrapper';
54

@@ -10,9 +9,14 @@ function trigger<T extends EventType>(type: T, data: EventData<T>) {
109
function on<T extends EventType>(
1110
type: T,
1211
dataListener: (data: EventData<T>) => void,
13-
options?: boolean | AddEventListenerOptions,
12+
options: {
13+
eventOptions?: boolean | AddEventListenerOptions;
14+
allowedOrigins?: string[];
15+
} = {},
1416
) {
15-
function listener(event: MessageEvent) {
17+
const { eventOptions, allowedOrigins = [] } = options;
18+
19+
async function listener(event: MessageEvent) {
1620
const {
1721
origin,
1822
data: { type: targetType, data },
@@ -21,17 +25,17 @@ function on<T extends EventType>(
2125
const url = new URL(origin);
2226

2327
const skipOriginCheck =
24-
ALLOWED_ORIGINS.length === 0 || ALLOWED_ORIGINS.includes('*');
28+
allowedOrigins.length === 0 || allowedOrigins.includes('*');
2529

26-
if (!skipOriginCheck && !ALLOWED_ORIGINS.includes(url.origin)) {
30+
if (!skipOriginCheck && !allowedOrigins.includes(url.origin)) {
2731
throw new Error(`Invalid Origin ${origin}`);
2832
}
2933

3034
if (`${namespace}:${type}` === targetType) {
3135
dataListener?.(data);
3236
}
3337
}
34-
window.addEventListener(`message`, listener, options);
38+
window.addEventListener(`message`, listener, eventOptions);
3539

3640
return () => window.removeEventListener(`message`, listener);
3741
}

src/hooks/useWhiteList.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { useEffect, useState, useTransition } from 'react';
2+
3+
async function readAllowedOrigins() {
4+
return fetch(
5+
'https://raw.githubusercontent.com/NFDI4Chem/nmrium-react-wrapper/main/src/allowed-origins.json',
6+
).then((response) => response.json());
7+
}
8+
9+
export function useWhiteList() {
10+
const [allowedOrigins, setAllowedOrigins] = useState([]);
11+
const [isFetchAllowedOriginsPending, startTransition] = useTransition();
12+
13+
useEffect(() => {
14+
startTransition(() => {
15+
readAllowedOrigins().then((whitelist) => setAllowedOrigins(whitelist));
16+
});
17+
}, []);
18+
19+
return {
20+
allowedOrigins,
21+
isFetchAllowedOriginsPending,
22+
};
23+
}

0 commit comments

Comments
 (0)