dce-reactkit 3.12.1-beta-cross-server.8 → 4.0.0-beta-date-and-time.1
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/.vscode/settings.json +3 -1
- package/README.md +0 -20
- package/dist/cjs/index.js +7838 -15905
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/ItemPicker/index.d.ts +1 -0
- package/dist/cjs/types/components/LoadingSpinner.d.ts +2 -2
- package/dist/cjs/types/components/Modal/ModalProps.d.ts +2 -0
- package/dist/cjs/types/components/SimpleDateChooser.d.ts +3 -1
- package/dist/cjs/types/components/SimpleTimeChooser.d.ts +20 -0
- package/dist/cjs/types/components/TabBox.d.ts +1 -0
- package/dist/cjs/types/components/Tooltip.d.ts +1 -1
- package/dist/cjs/types/helpers/getWordCount.d.ts +10 -0
- package/dist/cjs/types/index.d.ts +13 -13
- package/dist/cjs/types/types/ParamType.d.ts +10 -10
- package/dist/cjs/types/types/ReactKitErrorCode.d.ts +2 -28
- package/dist/esm/index.js +6661 -14723
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/ItemPicker/index.d.ts +1 -0
- package/dist/esm/types/components/LoadingSpinner.d.ts +2 -2
- package/dist/esm/types/components/Modal/ModalProps.d.ts +2 -0
- package/dist/esm/types/components/SimpleDateChooser.d.ts +3 -1
- package/dist/esm/types/components/SimpleTimeChooser.d.ts +20 -0
- package/dist/esm/types/components/TabBox.d.ts +1 -0
- package/dist/esm/types/components/Tooltip.d.ts +1 -1
- package/dist/esm/types/helpers/getWordCount.d.ts +10 -0
- package/dist/esm/types/index.d.ts +13 -13
- package/dist/esm/types/types/ParamType.d.ts +10 -10
- package/dist/esm/types/types/ReactKitErrorCode.d.ts +2 -28
- package/dist/index.d.ts +189 -379
- package/package.json +5 -11
- package/src/components/AppWrapper.tsx +3 -1
- package/src/components/CheckboxButton.tsx +1 -1
- package/src/components/Dropdown.tsx +1 -1
- package/src/components/IntelliTable.tsx +1 -1
- package/src/components/ItemPicker/NestableItemList.tsx +1 -0
- package/src/components/ItemPicker/index.tsx +96 -0
- package/src/components/LogReviewer.tsx +2 -2
- package/src/components/Modal/ModalProps.ts +4 -0
- package/src/components/Modal/index.tsx +60 -21
- package/src/components/RadioButton.tsx +3 -1
- package/src/components/SimpleDateChooser.tsx +62 -26
- package/src/components/SimpleTimeChooser.tsx +195 -0
- package/src/components/TabBox.tsx +27 -9
- package/src/components/Tooltip.tsx +1 -1
- package/src/helpers/getWordCount.ts +26 -0
- package/src/{client → helpers}/initClient.tsx +5 -1
- package/src/helpers/logClientEvent.tsx +3 -1
- package/src/helpers/visitServerEndpoint.tsx +1 -1
- package/src/index.ts +22 -24
- package/src/types/ParamType.ts +10 -10
- package/src/types/ReactKitErrorCode.tsx +3 -31
- package/dist/cjs/types/components/ItemPicker/index.test.d.ts +0 -1
- package/dist/cjs/types/helpers/addDBEditorEndpoints.d.ts +0 -41
- package/dist/cjs/types/helpers/dataSigner.d.ts +0 -40
- package/dist/cjs/types/helpers/genRouteHandler.d.ts +0 -76
- package/dist/cjs/types/helpers/handleError.d.ts +0 -18
- package/dist/cjs/types/helpers/handleSuccess.d.ts +0 -8
- package/dist/cjs/types/helpers/parseUserAgent.d.ts +0 -17
- package/dist/cjs/types/helpers/visitEndpointOnAnotherServer/index.d.ts +0 -20
- package/dist/cjs/types/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.d.ts +0 -27
- package/dist/cjs/types/server/initCrossServerCredentialCollection.d.ts +0 -8
- package/dist/cjs/types/server/initLogCollection.d.ts +0 -8
- package/dist/cjs/types/server/initServer.d.ts +0 -53
- package/dist/cjs/types/types/CrossServerCredential.d.ts +0 -11
- package/dist/esm/types/components/ItemPicker/index.test.d.ts +0 -1
- package/dist/esm/types/helpers/addDBEditorEndpoints.d.ts +0 -41
- package/dist/esm/types/helpers/dataSigner.d.ts +0 -40
- package/dist/esm/types/helpers/genRouteHandler.d.ts +0 -76
- package/dist/esm/types/helpers/handleError.d.ts +0 -18
- package/dist/esm/types/helpers/handleSuccess.d.ts +0 -8
- package/dist/esm/types/helpers/parseUserAgent.d.ts +0 -17
- package/dist/esm/types/helpers/visitEndpointOnAnotherServer/index.d.ts +0 -20
- package/dist/esm/types/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.d.ts +0 -27
- package/dist/esm/types/server/initCrossServerCredentialCollection.d.ts +0 -8
- package/dist/esm/types/server/initLogCollection.d.ts +0 -8
- package/dist/esm/types/server/initServer.d.ts +0 -53
- package/dist/esm/types/types/CrossServerCredential.d.ts +0 -11
- package/src/components/ItemPicker/index.test.tsx +0 -783
- package/src/helpers/addDBEditorEndpoints.ts +0 -128
- package/src/helpers/dataSigner.ts +0 -342
- package/src/helpers/genRouteHandler.ts +0 -911
- package/src/helpers/handleError.ts +0 -65
- package/src/helpers/handleSuccess.ts +0 -18
- package/src/helpers/parseUserAgent.ts +0 -108
- package/src/helpers/visitEndpointOnAnotherServer/index.ts +0 -152
- package/src/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.ts +0 -162
- package/src/server/initCrossServerCredentialCollection.ts +0 -16
- package/src/server/initLogCollection.ts +0 -27
- package/src/server/initServer.ts +0 -305
- package/src/types/CrossServerCredential.ts +0 -16
- /package/dist/cjs/types/{client → helpers}/initClient.d.ts +0 -0
- /package/dist/esm/types/{client → helpers}/initClient.d.ts +0 -0
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
// Import express
|
|
2
|
-
import express from 'express';
|
|
3
|
-
|
|
4
|
-
// Import shared helpers
|
|
5
|
-
import genRouteHandler from './genRouteHandler';
|
|
6
|
-
import generateEndpointPath from '../components/DBEntryManagerPanel/helpers/generateEndpointPath';
|
|
7
|
-
|
|
8
|
-
// Import shared types
|
|
9
|
-
import ParamType from '../types/ParamType';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Interface for a collection in the database
|
|
13
|
-
* @author Yuen Ler Chow
|
|
14
|
-
*/
|
|
15
|
-
type DCEMangoCollection = {
|
|
16
|
-
/**
|
|
17
|
-
* Find all items in the collection that match the filter query
|
|
18
|
-
* @param filterQuery query for the filter
|
|
19
|
-
* @returns list of items that match the filter query
|
|
20
|
-
*/
|
|
21
|
-
find: (filterQuery: any) => Promise<any[]>,
|
|
22
|
-
/**
|
|
23
|
-
* Insert an item into the collection
|
|
24
|
-
* @param item the item to insert
|
|
25
|
-
*/
|
|
26
|
-
insert: (item: any) => Promise<void>,
|
|
27
|
-
/**
|
|
28
|
-
* Delete an item in the collection
|
|
29
|
-
* @param id the id of the item to delete
|
|
30
|
-
*/
|
|
31
|
-
delete: (filterQuery: { id: string }) => Promise<void>,
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Add all routes for the DBEditor
|
|
36
|
-
* @author Yuen Ler Chow
|
|
37
|
-
* @param opts object containing all arguments
|
|
38
|
-
* @param opts.app express app to add routes too
|
|
39
|
-
* @param opts.collectionName the name of the collection
|
|
40
|
-
* @param opts.adminsOnly true if the endpoint is for admins only
|
|
41
|
-
* @param opts.collection dce-mango db collection
|
|
42
|
-
*/
|
|
43
|
-
const addDBEditorEndpoints = (
|
|
44
|
-
opts: {
|
|
45
|
-
app: express.Application,
|
|
46
|
-
collectionName: string,
|
|
47
|
-
adminsOnly: boolean,
|
|
48
|
-
collection: DCEMangoCollection,
|
|
49
|
-
},
|
|
50
|
-
) => {
|
|
51
|
-
const {
|
|
52
|
-
app,
|
|
53
|
-
collectionName,
|
|
54
|
-
adminsOnly,
|
|
55
|
-
collection,
|
|
56
|
-
} = opts;
|
|
57
|
-
|
|
58
|
-
// Generate the endpoint path
|
|
59
|
-
const endpointPath = generateEndpointPath(collectionName, adminsOnly);
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* List all items in the collection
|
|
63
|
-
* @author Yuen Ler Chow
|
|
64
|
-
* @returns {any[]} the list of items in the collection
|
|
65
|
-
*/
|
|
66
|
-
app.get(
|
|
67
|
-
endpointPath,
|
|
68
|
-
genRouteHandler({
|
|
69
|
-
paramTypes: {
|
|
70
|
-
filterQuery: ParamType.JSONOptional,
|
|
71
|
-
},
|
|
72
|
-
handler: async ({ params }) => {
|
|
73
|
-
const filterQuery = params.filterQuery ?? {};
|
|
74
|
-
const categories = await collection.find(filterQuery);
|
|
75
|
-
return categories;
|
|
76
|
-
},
|
|
77
|
-
}),
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Create a new item in the collection
|
|
82
|
-
* @author Yuen Ler Chow
|
|
83
|
-
* @param {any} item the item to create
|
|
84
|
-
*/
|
|
85
|
-
app.post(
|
|
86
|
-
endpointPath,
|
|
87
|
-
genRouteHandler({
|
|
88
|
-
paramTypes: {
|
|
89
|
-
item: ParamType.JSON,
|
|
90
|
-
},
|
|
91
|
-
handler: async ({
|
|
92
|
-
params,
|
|
93
|
-
}) => {
|
|
94
|
-
// Destructure params
|
|
95
|
-
const {
|
|
96
|
-
item,
|
|
97
|
-
} = params;
|
|
98
|
-
|
|
99
|
-
await collection.insert(item);
|
|
100
|
-
},
|
|
101
|
-
}),
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Remove an item from the collection by id
|
|
106
|
-
* @author Yuen Ler Chow
|
|
107
|
-
*/
|
|
108
|
-
app.delete(
|
|
109
|
-
`${endpointPath}/:id`,
|
|
110
|
-
genRouteHandler({
|
|
111
|
-
paramTypes: {
|
|
112
|
-
id: ParamType.String,
|
|
113
|
-
},
|
|
114
|
-
handler: async ({
|
|
115
|
-
params,
|
|
116
|
-
}) => {
|
|
117
|
-
// Destructure params
|
|
118
|
-
const {
|
|
119
|
-
id,
|
|
120
|
-
} = params;
|
|
121
|
-
|
|
122
|
-
await collection.delete({ id });
|
|
123
|
-
},
|
|
124
|
-
}),
|
|
125
|
-
);
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
export default addDBEditorEndpoints;
|
|
@@ -1,342 +0,0 @@
|
|
|
1
|
-
// Import shared helpers
|
|
2
|
-
// eslint-disable-next-line import/no-cycle
|
|
3
|
-
import { internalGetCrossServerCredentialCollection } from '../server/initServer';
|
|
4
|
-
|
|
5
|
-
// Import shared types
|
|
6
|
-
import ErrorWithCode from '../errors/ErrorWithCode';
|
|
7
|
-
import ReactKitErrorCode from '../types/ReactKitErrorCode';
|
|
8
|
-
import CrossServerCredential from '../types/CrossServerCredential';
|
|
9
|
-
|
|
10
|
-
// Import shared constants
|
|
11
|
-
import MINUTE_IN_MS from '../constants/MINUTE_IN_MS';
|
|
12
|
-
|
|
13
|
-
/*------------------------------------------------------------------------*/
|
|
14
|
-
/* --------------------------- Dynamic Imports -------------------------- */
|
|
15
|
-
/*------------------------------------------------------------------------*/
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Get a copy of the oauth lib
|
|
19
|
-
* @author Gabe Abrams
|
|
20
|
-
* @return the oauth lib
|
|
21
|
-
*/
|
|
22
|
-
const getOauthLib = async () => {
|
|
23
|
-
// Get the oauth signing library (included with caccl)
|
|
24
|
-
// Ignore because this is assumed to be included with caccl
|
|
25
|
-
try {
|
|
26
|
-
// @ts-ignore
|
|
27
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
28
|
-
const oauth = await import('oauth-signature');
|
|
29
|
-
return oauth;
|
|
30
|
-
} catch (err) {
|
|
31
|
-
throw new ErrorWithCode(
|
|
32
|
-
'Could not sign a cross-server request because we could not load the oauth library. Please make sure this app has caccl as one of its dependencies.',
|
|
33
|
-
ReactKitErrorCode.NoOauthLib,
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Get a copy of the crypto lib
|
|
40
|
-
* @author Gabe Abrams
|
|
41
|
-
* @return the crypto lib
|
|
42
|
-
*/
|
|
43
|
-
const getCryptoLib = async () => {
|
|
44
|
-
// Get the crypto library (included on the server)
|
|
45
|
-
// Ignore because this is assumed to be included with typescript
|
|
46
|
-
// @ts-ignore
|
|
47
|
-
try {
|
|
48
|
-
// @ts-ignore
|
|
49
|
-
// eslint-disable-next-line global-require
|
|
50
|
-
const crypto = await require('crypto');
|
|
51
|
-
return crypto;
|
|
52
|
-
} catch (err) {
|
|
53
|
-
throw new ErrorWithCode(
|
|
54
|
-
'Could not sign a cross-server request because we could not load the crypto library. Please make sure this operation is running on the server.',
|
|
55
|
-
ReactKitErrorCode.NoCryptoLib,
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/*------------------------------------------------------------------------*/
|
|
61
|
-
/* ------------------------------- Helpers ------------------------------ */
|
|
62
|
-
/*------------------------------------------------------------------------*/
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Generate an oauth signature
|
|
66
|
-
* @author Gabe Abrams
|
|
67
|
-
* @param opts object containing all arguments
|
|
68
|
-
* @param opts.method the http method
|
|
69
|
-
* @param opts.path the http request path
|
|
70
|
-
* @param opts.params the data in the body to sign
|
|
71
|
-
* @param opts.secret the secret to sign with
|
|
72
|
-
* @return the signature
|
|
73
|
-
*/
|
|
74
|
-
const genSignature = async (
|
|
75
|
-
opts: {
|
|
76
|
-
method?: string,
|
|
77
|
-
path?: string,
|
|
78
|
-
params?: { [key: string]: any },
|
|
79
|
-
secret: string,
|
|
80
|
-
},
|
|
81
|
-
): Promise<string> => {
|
|
82
|
-
// Destructure opts
|
|
83
|
-
const {
|
|
84
|
-
method,
|
|
85
|
-
path,
|
|
86
|
-
params,
|
|
87
|
-
secret,
|
|
88
|
-
} = opts;
|
|
89
|
-
|
|
90
|
-
// Get the oauth library
|
|
91
|
-
const oauth = await getOauthLib();
|
|
92
|
-
|
|
93
|
-
// Order the params alphabetically by key
|
|
94
|
-
const keys = Object.keys(params ?? {});
|
|
95
|
-
keys.sort();
|
|
96
|
-
const orderedParams: {
|
|
97
|
-
[key: string]: any,
|
|
98
|
-
} = {};
|
|
99
|
-
keys.forEach((key) => {
|
|
100
|
-
// Skip oauth_signature
|
|
101
|
-
if (key === 'oauth_signature') {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Add the param
|
|
106
|
-
orderedParams[key] = (params ?? {})[key];
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
// Generate the signature
|
|
110
|
-
return decodeURIComponent(oauth.generate(
|
|
111
|
-
method ?? 'GET',
|
|
112
|
-
path ?? 'no-path',
|
|
113
|
-
orderedParams,
|
|
114
|
-
secret,
|
|
115
|
-
));
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Decrypt an encrypted string using a secret
|
|
120
|
-
* @author Gabe Abrams
|
|
121
|
-
* @param str the encrypted string
|
|
122
|
-
* @return the decrypted string
|
|
123
|
-
*/
|
|
124
|
-
const decrypt = async (
|
|
125
|
-
encryptedPack: string,
|
|
126
|
-
): Promise<string> => {
|
|
127
|
-
// Decryption process based on:
|
|
128
|
-
// https://medium.com/@tony.infisical/guide-to-nodes-crypto-module-for-encryption-decryption-65c077176980
|
|
129
|
-
|
|
130
|
-
// Get the encryption secret
|
|
131
|
-
const { REACTKIT_CRED_ENCODING_SALT } = process.env;
|
|
132
|
-
if (!REACTKIT_CRED_ENCODING_SALT) {
|
|
133
|
-
throw new ErrorWithCode(
|
|
134
|
-
'Could not decrypt a string because the encryption salt was not set.',
|
|
135
|
-
ReactKitErrorCode.CrossServerNoCredentialEncodingSalt,
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Get the crypto library
|
|
140
|
-
const crypto = await getCryptoLib();
|
|
141
|
-
|
|
142
|
-
// Separate encrypted pack
|
|
143
|
-
const {
|
|
144
|
-
ciphertext,
|
|
145
|
-
iv,
|
|
146
|
-
tag,
|
|
147
|
-
} = JSON.parse(decodeURIComponent(encryptedPack));
|
|
148
|
-
|
|
149
|
-
// Parse the encrypted data
|
|
150
|
-
const decipher = crypto.createDecipheriv(
|
|
151
|
-
'aes-256-gcm',
|
|
152
|
-
Buffer.from(REACTKIT_CRED_ENCODING_SALT, 'base64'),
|
|
153
|
-
Buffer.from(iv, 'base64'),
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
// Set the authentication tag
|
|
157
|
-
decipher.setAuthTag(Buffer.from(tag, 'base64'));
|
|
158
|
-
|
|
159
|
-
// Decrypt the string
|
|
160
|
-
let str = decipher.update(ciphertext, 'base64', 'utf8');
|
|
161
|
-
str += decipher.final('utf8');
|
|
162
|
-
|
|
163
|
-
// Return the decrypted string
|
|
164
|
-
return str;
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
/*------------------------------------------------------------------------*/
|
|
168
|
-
/* ------------------------------- Signing ------------------------------ */
|
|
169
|
-
/*------------------------------------------------------------------------*/
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Sign a request and get the new request params
|
|
173
|
-
* @author Gabe Abrams
|
|
174
|
-
* @param opts object containing all arguments
|
|
175
|
-
* @param opts.method the method to sign
|
|
176
|
-
* @param opts.path the http request path
|
|
177
|
-
* @param opts.params the data in the body to sign
|
|
178
|
-
* @param opts.key the reactkit key to sign with
|
|
179
|
-
* @param opts.secret the reactkit secret to sign with
|
|
180
|
-
* @return augmented params for the request, including a signature, timestamp, and key
|
|
181
|
-
*/
|
|
182
|
-
export const signRequest = async (
|
|
183
|
-
opts: {
|
|
184
|
-
method: string,
|
|
185
|
-
path: string,
|
|
186
|
-
params: { [key: string]: any },
|
|
187
|
-
key: string,
|
|
188
|
-
secret: string,
|
|
189
|
-
},
|
|
190
|
-
): Promise<{ [key: string]: any }> => {
|
|
191
|
-
// Destructure opts
|
|
192
|
-
const method = opts.method.toUpperCase();
|
|
193
|
-
const {
|
|
194
|
-
path,
|
|
195
|
-
params,
|
|
196
|
-
key,
|
|
197
|
-
secret,
|
|
198
|
-
} = opts;
|
|
199
|
-
|
|
200
|
-
// Augment the params
|
|
201
|
-
const augmentedParams: {
|
|
202
|
-
[key: string]: any,
|
|
203
|
-
} = {
|
|
204
|
-
...params,
|
|
205
|
-
oauth_consumer_key: key,
|
|
206
|
-
oauth_nonce: Math.random().toString(36),
|
|
207
|
-
oauth_timestamp: Date.now(),
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
// Generate a signature
|
|
211
|
-
const signature = await genSignature({
|
|
212
|
-
method,
|
|
213
|
-
path,
|
|
214
|
-
params,
|
|
215
|
-
secret,
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
// Add signature to the augmented params
|
|
219
|
-
augmentedParams.oauth_signature = signature;
|
|
220
|
-
|
|
221
|
-
// Return the augmented params
|
|
222
|
-
return augmentedParams;
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Validate a signed request. Throws an error if invalid
|
|
227
|
-
* @author Gabe Abrams
|
|
228
|
-
* @param opts object containing all arguments
|
|
229
|
-
* @param opts.method the method of the data validate
|
|
230
|
-
* @param opts.path the http request path to validate
|
|
231
|
-
* @param opts.scope the name of the scope to validate
|
|
232
|
-
* @param opts.params the request data to validate
|
|
233
|
-
* @returns parsed and validated params
|
|
234
|
-
*/
|
|
235
|
-
export const validateSignedRequest = async (
|
|
236
|
-
opts: {
|
|
237
|
-
method: string,
|
|
238
|
-
path: string,
|
|
239
|
-
scope: string,
|
|
240
|
-
params: { [key: string]: any },
|
|
241
|
-
},
|
|
242
|
-
) => {
|
|
243
|
-
/* ---------- Collect Info ---------- */
|
|
244
|
-
|
|
245
|
-
// Get the signature
|
|
246
|
-
if (!opts.params.oauth_signature) {
|
|
247
|
-
throw new ErrorWithCode(
|
|
248
|
-
'Could not validate a cross-server request there was no oauth signature.',
|
|
249
|
-
ReactKitErrorCode.CrossServerMissingSignedRequestInfo,
|
|
250
|
-
);
|
|
251
|
-
}
|
|
252
|
-
const signature = opts.params.oauth_signature;
|
|
253
|
-
|
|
254
|
-
// Get the timestamp
|
|
255
|
-
if (
|
|
256
|
-
// No timestamp
|
|
257
|
-
!opts.params.oauth_timestamp
|
|
258
|
-
// Invalid timestamp
|
|
259
|
-
|| Number.isNaN(Number.parseInt(opts.params.oauth_timestamp, 10))
|
|
260
|
-
) {
|
|
261
|
-
throw new ErrorWithCode(
|
|
262
|
-
'Could not validate a cross-server request there was no valid oauth timestamp.',
|
|
263
|
-
ReactKitErrorCode.CrossServerMissingSignedRequestInfo,
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
const timestamp = Number.parseInt(opts.params.oauth_timestamp, 10);
|
|
267
|
-
|
|
268
|
-
// Get the key
|
|
269
|
-
if (!opts.params.oauth_consumer_key) {
|
|
270
|
-
throw new ErrorWithCode(
|
|
271
|
-
'Could not validate a cross-server request there was no oauth consumer key.',
|
|
272
|
-
ReactKitErrorCode.CrossServerMissingSignedRequestInfo,
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
const key = opts.params.oauth_consumer_key;
|
|
276
|
-
|
|
277
|
-
// Get the rest of the info
|
|
278
|
-
const {
|
|
279
|
-
method,
|
|
280
|
-
path,
|
|
281
|
-
params,
|
|
282
|
-
} = opts;
|
|
283
|
-
|
|
284
|
-
/* ------- Look Up Credential ------- */
|
|
285
|
-
|
|
286
|
-
// Get the cross-server credential collection
|
|
287
|
-
const crossServerCredentialCollection = internalGetCrossServerCredentialCollection();
|
|
288
|
-
if (!crossServerCredentialCollection) {
|
|
289
|
-
throw new ErrorWithCode(
|
|
290
|
-
'Could not validate a cross-server request because the cross-server credential collection was not ready in time.',
|
|
291
|
-
ReactKitErrorCode.SignedRequestInvalidCollection,
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// Get the cross-server credential
|
|
296
|
-
const crossServerCredential: CrossServerCredential = await crossServerCredentialCollection.find({ key });
|
|
297
|
-
if (!crossServerCredential) {
|
|
298
|
-
throw new ErrorWithCode(
|
|
299
|
-
'Could not validate a cross-server request because the credential was not found.',
|
|
300
|
-
ReactKitErrorCode.SignedRequestInvalidCredential,
|
|
301
|
-
);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Make sure the scope is included
|
|
305
|
-
const allowedScopes = crossServerCredential.scopes;
|
|
306
|
-
if (!allowedScopes.includes(opts.scope)) {
|
|
307
|
-
throw new ErrorWithCode(
|
|
308
|
-
'Could not validate a cross-server request because the scope was not included.',
|
|
309
|
-
ReactKitErrorCode.SignedRequestInvalidScope,
|
|
310
|
-
);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// Decode the secret
|
|
314
|
-
const secret = await decrypt(crossServerCredential.encodedeSecret);
|
|
315
|
-
|
|
316
|
-
/* -------- Verify Signature -------- */
|
|
317
|
-
|
|
318
|
-
// Generate a new signature to compare
|
|
319
|
-
const expectedSignature = await genSignature({
|
|
320
|
-
method,
|
|
321
|
-
path,
|
|
322
|
-
params,
|
|
323
|
-
secret,
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
// Make sure the signatures match
|
|
327
|
-
if (signature !== expectedSignature) {
|
|
328
|
-
throw new ErrorWithCode(
|
|
329
|
-
'Could not validate a cross-server request because the signature did not match.',
|
|
330
|
-
ReactKitErrorCode.SignedRequestInvalidSignature,
|
|
331
|
-
);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// Make sure the timestamp was recent enough
|
|
335
|
-
const elapsedMs = Math.abs(Date.now() - timestamp);
|
|
336
|
-
if (elapsedMs < MINUTE_IN_MS) {
|
|
337
|
-
throw new ErrorWithCode(
|
|
338
|
-
'Could not validate a cross-server request because the request was too old.',
|
|
339
|
-
ReactKitErrorCode.SignedRequestInvalidTimestamp,
|
|
340
|
-
);
|
|
341
|
-
}
|
|
342
|
-
};
|