@openstax/ts-utils 1.31.2 → 1.32.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/cjs/services/apiGateway/index.d.ts +1 -1
- package/dist/cjs/services/authProvider/browser.d.ts +3 -3
- package/dist/cjs/services/authProvider/decryption.d.ts +5 -1
- package/dist/cjs/services/authProvider/decryption.js +28 -18
- package/dist/cjs/services/authProvider/index.d.ts +6 -6
- package/dist/cjs/services/authProvider/subrequest.d.ts +1 -1
- package/dist/cjs/services/authProvider/subrequest.js +2 -7
- package/dist/cjs/services/authProvider/utils/userSubrequest.d.ts +3 -0
- package/dist/cjs/services/authProvider/utils/userSubrequest.js +13 -0
- package/dist/cjs/services/fileServer/index.d.ts +0 -12
- package/dist/cjs/services/fileServer/localFileServer.js +1 -52
- package/dist/cjs/services/fileServer/s3FileServer.d.ts +0 -1
- package/dist/cjs/services/fileServer/s3FileServer.js +0 -78
- package/dist/cjs/services/searchProvider/openSearch.js +4 -6
- package/dist/cjs/tsconfig.without-specs.cjs.tsbuildinfo +1 -1
- package/dist/esm/services/apiGateway/index.d.ts +1 -1
- package/dist/esm/services/authProvider/browser.d.ts +3 -3
- package/dist/esm/services/authProvider/decryption.d.ts +5 -1
- package/dist/esm/services/authProvider/decryption.js +28 -18
- package/dist/esm/services/authProvider/index.d.ts +6 -6
- package/dist/esm/services/authProvider/subrequest.d.ts +1 -1
- package/dist/esm/services/authProvider/subrequest.js +2 -4
- package/dist/esm/services/authProvider/utils/userSubrequest.d.ts +3 -0
- package/dist/esm/services/authProvider/utils/userSubrequest.js +6 -0
- package/dist/esm/services/fileServer/index.d.ts +0 -12
- package/dist/esm/services/fileServer/localFileServer.js +2 -53
- package/dist/esm/services/fileServer/s3FileServer.d.ts +0 -1
- package/dist/esm/services/fileServer/s3FileServer.js +1 -76
- package/dist/esm/services/searchProvider/openSearch.js +4 -6
- package/dist/esm/tsconfig.without-specs.esm.tsbuildinfo +1 -1
- package/package.json +3 -4
- package/script/bin/.init-params-script.bash.swp +0 -0
|
@@ -38,7 +38,7 @@ export type ApiClientResponse<Ro> = Ro extends any ? {
|
|
|
38
38
|
} : never;
|
|
39
39
|
export type ExpandRoute<T> = T extends ((...args: infer A) => infer R) & {
|
|
40
40
|
renderUrl: (...args: infer Ar) => Promise<string>;
|
|
41
|
-
} ? (
|
|
41
|
+
} ? (...args: A) => R & {
|
|
42
42
|
renderUrl: (...args: Ar) => Promise<string>;
|
|
43
43
|
} : never;
|
|
44
44
|
export type MapRoutesToClient<Ru> = [Ru] extends [AnyRoute<Ru>] ? {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConfigProviderForConfig } from '../../config';
|
|
2
2
|
import { FetchConfig, GenericFetch } from '../../fetch';
|
|
3
|
-
import { User } from '.';
|
|
3
|
+
import { ApiUser, User } from '.';
|
|
4
4
|
type Config = {
|
|
5
5
|
accountsBase: string;
|
|
6
6
|
};
|
|
@@ -26,7 +26,7 @@ export interface Window {
|
|
|
26
26
|
addEventListener: (event: 'message', callback: EventHandler) => void;
|
|
27
27
|
removeEventListener: (event: 'message', callback: EventHandler) => void;
|
|
28
28
|
}
|
|
29
|
-
export type UpdatableUserFields = Partial<Pick<
|
|
29
|
+
export type UpdatableUserFields = Partial<Pick<ApiUser, 'consent_preferences' | 'first_name' | 'last_name'>>;
|
|
30
30
|
export declare const browserAuthProvider: <C extends string = "auth">({ window, configSpace }: Initializer<C>) => (configProvider: { [_key in C]: ConfigProviderForConfig<Config>; }) => {
|
|
31
31
|
/**
|
|
32
32
|
* gets the authentication token
|
|
@@ -65,7 +65,7 @@ export declare const browserAuthProvider: <C extends string = "auth">({ window,
|
|
|
65
65
|
* updates user settings, for example the cookie consent preferences
|
|
66
66
|
*/
|
|
67
67
|
updateUser: (updates: UpdatableUserFields) => Promise<{
|
|
68
|
-
user:
|
|
68
|
+
user: ApiUser;
|
|
69
69
|
token: string | null;
|
|
70
70
|
}>;
|
|
71
71
|
};
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import type { ConfigProviderForConfig } from '../../config';
|
|
2
|
-
import {
|
|
2
|
+
import { GenericFetch } from '../../fetch';
|
|
3
|
+
import { ApiUser, AuthProvider, CookieAuthProvider } from '.';
|
|
3
4
|
type Config = {
|
|
5
|
+
accountsBase: string;
|
|
4
6
|
cookieName: string;
|
|
5
7
|
encryptionPrivateKey: string;
|
|
6
8
|
signaturePublicKey: string;
|
|
7
9
|
};
|
|
8
10
|
interface Initializer<C> {
|
|
9
11
|
configSpace?: C;
|
|
12
|
+
fetch: GenericFetch;
|
|
10
13
|
}
|
|
11
14
|
export type DecryptionAuthProvider = AuthProvider & {
|
|
12
15
|
getTokenExpiration: (tokenString?: string) => Promise<number | null | undefined>;
|
|
16
|
+
loadUserData: () => Promise<ApiUser | undefined>;
|
|
13
17
|
};
|
|
14
18
|
export declare const decryptionAuthProvider: <C extends string = "decryption">(initializer: Initializer<C>) => (configProvider: { [_key in C]: ConfigProviderForConfig<Config>; }) => CookieAuthProvider<DecryptionAuthProvider>;
|
|
15
19
|
export {};
|
|
@@ -6,14 +6,17 @@ const errors_1 = require("../../errors");
|
|
|
6
6
|
const guards_1 = require("../../guards");
|
|
7
7
|
const helpers_1 = require("../../misc/helpers");
|
|
8
8
|
const decryptAndVerify_1 = require("./utils/decryptAndVerify");
|
|
9
|
+
const userSubrequest_1 = require("./utils/userSubrequest");
|
|
9
10
|
const _1 = require(".");
|
|
10
11
|
const decryptionAuthProvider = (initializer) => (configProvider) => {
|
|
11
12
|
const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'decryption')];
|
|
13
|
+
const accountsBase = (0, helpers_1.once)(() => (0, resolveConfigValue_1.resolveConfigValue)(config.accountsBase));
|
|
12
14
|
const cookieName = (0, helpers_1.once)(() => (0, resolveConfigValue_1.resolveConfigValue)(config.cookieName));
|
|
13
15
|
const encryptionPrivateKey = (0, helpers_1.once)(() => (0, resolveConfigValue_1.resolveConfigValue)(config.encryptionPrivateKey));
|
|
14
16
|
const signaturePublicKey = (0, helpers_1.once)(() => (0, resolveConfigValue_1.resolveConfigValue)(config.signaturePublicKey));
|
|
15
17
|
return ({ request, logger }) => {
|
|
16
18
|
let user;
|
|
19
|
+
let userData;
|
|
17
20
|
const getAuthToken = async () => (0, _1.getAuthTokenOrCookie)(request, await cookieName())[0];
|
|
18
21
|
const getAuthorizedFetchConfig = async () => {
|
|
19
22
|
const [token, headers] = (0, _1.getAuthTokenOrCookie)(request, await cookieName());
|
|
@@ -22,40 +25,47 @@ const decryptionAuthProvider = (initializer) => (configProvider) => {
|
|
|
22
25
|
}
|
|
23
26
|
return { headers };
|
|
24
27
|
};
|
|
25
|
-
const
|
|
28
|
+
const getDecryptedPayload = async (tokenString) => {
|
|
26
29
|
const token = tokenString !== null && tokenString !== void 0 ? tokenString : await getAuthToken();
|
|
27
30
|
if (!token) {
|
|
28
31
|
return undefined;
|
|
29
32
|
}
|
|
30
33
|
return (0, decryptAndVerify_1.decryptAndVerify)(token, await encryptionPrivateKey(), await signaturePublicKey());
|
|
31
34
|
};
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
const getUser = async () => {
|
|
36
|
+
if (!user) {
|
|
37
|
+
const result = await getDecryptedPayload();
|
|
38
|
+
if (!result) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
if ('error' in result && result.error == 'expired token') {
|
|
42
|
+
throw new errors_1.SessionExpiredError();
|
|
43
|
+
}
|
|
44
|
+
if ('user' in result) {
|
|
45
|
+
logger.setContext({ user: result.user.uuid });
|
|
46
|
+
user = result.user;
|
|
47
|
+
}
|
|
43
48
|
}
|
|
44
|
-
return
|
|
49
|
+
return user;
|
|
45
50
|
};
|
|
46
51
|
return {
|
|
47
52
|
getAuthToken,
|
|
48
53
|
getAuthorizedFetchConfig,
|
|
49
54
|
getTokenExpiration: async (tokenString) => {
|
|
50
55
|
var _a;
|
|
51
|
-
const payload = await
|
|
56
|
+
const payload = await getDecryptedPayload(tokenString);
|
|
52
57
|
return payload ? ((_a = payload.exp) !== null && _a !== void 0 ? _a : null) : undefined;
|
|
53
58
|
},
|
|
54
|
-
getUser
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
getUser,
|
|
60
|
+
loadUserData: async () => {
|
|
61
|
+
if (!userData) {
|
|
62
|
+
const token = await getAuthToken();
|
|
63
|
+
if (!token) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
userData = await (0, userSubrequest_1.loadUserData)(initializer.fetch, await accountsBase(), await cookieName(), token);
|
|
57
67
|
}
|
|
58
|
-
return
|
|
68
|
+
return userData;
|
|
59
69
|
},
|
|
60
70
|
};
|
|
61
71
|
};
|
|
@@ -10,14 +10,14 @@ export type ConsentPreferences = {
|
|
|
10
10
|
export type TokenUser = {
|
|
11
11
|
id: number;
|
|
12
12
|
name: string;
|
|
13
|
+
uuid: string;
|
|
14
|
+
faculty_status: string;
|
|
15
|
+
is_admin: boolean;
|
|
16
|
+
};
|
|
17
|
+
export type ApiUser = TokenUser & {
|
|
13
18
|
first_name: string;
|
|
14
19
|
last_name: string;
|
|
15
20
|
full_name: string;
|
|
16
|
-
uuid: string;
|
|
17
|
-
faculty_status: string;
|
|
18
|
-
is_administrator: boolean;
|
|
19
|
-
} & Partial<ConsentPreferences>;
|
|
20
|
-
export interface ApiUser extends TokenUser {
|
|
21
21
|
contact_infos: Array<{
|
|
22
22
|
type: string;
|
|
23
23
|
value: string;
|
|
@@ -34,7 +34,7 @@ export interface ApiUser extends TokenUser {
|
|
|
34
34
|
self_reported_role: string;
|
|
35
35
|
signed_contract_names: string[];
|
|
36
36
|
using_openstax: boolean;
|
|
37
|
-
}
|
|
37
|
+
} & Partial<ConsentPreferences>;
|
|
38
38
|
export type User = TokenUser | ApiUser;
|
|
39
39
|
export type AuthProvider = {
|
|
40
40
|
getAuthToken: () => Promise<string | null>;
|
|
@@ -2,8 +2,8 @@ import { ConfigProviderForConfig } from '../../config';
|
|
|
2
2
|
import { GenericFetch } from '../../fetch';
|
|
3
3
|
import { CookieAuthProvider } from '.';
|
|
4
4
|
type Config = {
|
|
5
|
-
cookieName: string;
|
|
6
5
|
accountsBase: string;
|
|
6
|
+
cookieName: string;
|
|
7
7
|
};
|
|
8
8
|
interface Initializer<C> {
|
|
9
9
|
configSpace?: C;
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.subrequestAuthProvider = void 0;
|
|
7
|
-
const cookie_1 = __importDefault(require("cookie"));
|
|
8
4
|
const __1 = require("../..");
|
|
9
5
|
const config_1 = require("../../config");
|
|
10
6
|
const guards_1 = require("../../guards");
|
|
7
|
+
const userSubrequest_1 = require("./utils/userSubrequest");
|
|
11
8
|
const _1 = require(".");
|
|
12
9
|
const subrequestAuthProvider = (initializer) => (configProvider) => {
|
|
13
10
|
const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'subrequest')];
|
|
@@ -29,9 +26,7 @@ const subrequestAuthProvider = (initializer) => (configProvider) => {
|
|
|
29
26
|
if (!token) {
|
|
30
27
|
return undefined;
|
|
31
28
|
}
|
|
32
|
-
const
|
|
33
|
-
const user = await initializer.fetch((await accountsBase()).replace(/\/+$/, '') + '/api/user', { headers })
|
|
34
|
-
.then(response => response.json());
|
|
29
|
+
const user = await (0, userSubrequest_1.loadUserData)(initializer.fetch, await accountsBase(), resolvedCookieName, token);
|
|
35
30
|
if (user) {
|
|
36
31
|
logger.setContext({ user: user.uuid });
|
|
37
32
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadUserData = void 0;
|
|
7
|
+
const cookie_1 = __importDefault(require("cookie"));
|
|
8
|
+
const loadUserData = (fetch, accountsBase, cookieName, token) => {
|
|
9
|
+
const headers = { cookie: cookie_1.default.serialize(cookieName, token) };
|
|
10
|
+
return fetch(accountsBase.replace(/\/+$/, '') + '/api/user', { headers })
|
|
11
|
+
.then(response => response.json());
|
|
12
|
+
};
|
|
13
|
+
exports.loadUserData = loadUserData;
|
|
@@ -13,18 +13,6 @@ export declare const isFolderValue: (thing: any) => thing is FolderValue;
|
|
|
13
13
|
export interface FileServerAdapter {
|
|
14
14
|
putFileContent: (source: FileValue, content: string) => Promise<FileValue>;
|
|
15
15
|
getSignedViewerUrl: (source: FileValue) => Promise<string>;
|
|
16
|
-
getPublicViewerUrl: (source: FileValue) => Promise<string>;
|
|
17
16
|
getFileContent: (source: FileValue) => Promise<Buffer>;
|
|
18
|
-
getSignedFileUploadConfig: () => Promise<{
|
|
19
|
-
url: string;
|
|
20
|
-
payload: {
|
|
21
|
-
[key: string]: string;
|
|
22
|
-
};
|
|
23
|
-
}>;
|
|
24
|
-
copyFileTo: (source: FileValue, destinationPath: string) => Promise<FileValue>;
|
|
25
|
-
copyFileToDirectory: (source: FileValue, destinationDirectory: string) => Promise<FileValue>;
|
|
26
|
-
isTemporaryUpload: (source: FileValue) => boolean;
|
|
27
|
-
getFileChecksum: (source: FileValue) => Promise<string>;
|
|
28
|
-
filesEqual: (sourceA: FileValue, sourceB: FileValue) => Promise<boolean>;
|
|
29
17
|
}
|
|
30
18
|
export declare const isFileOrFolder: (thing: any) => thing is FileValue | FolderValue;
|
|
@@ -5,20 +5,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.localFileServer = void 0;
|
|
7
7
|
/* cspell:ignore originalname */
|
|
8
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
9
8
|
const fs_1 = __importDefault(require("fs"));
|
|
10
9
|
const https_1 = __importDefault(require("https"));
|
|
11
10
|
const path_1 = __importDefault(require("path"));
|
|
12
11
|
const cors_1 = __importDefault(require("cors"));
|
|
13
12
|
const express_1 = __importDefault(require("express"));
|
|
14
13
|
const multer_1 = __importDefault(require("multer"));
|
|
15
|
-
const uuid_1 = require("uuid");
|
|
16
14
|
const assertions_1 = require("../../assertions");
|
|
17
15
|
const config_1 = require("../../config");
|
|
18
16
|
const guards_1 = require("../../guards");
|
|
19
17
|
const helpers_1 = require("../../misc/helpers");
|
|
20
18
|
/* istanbul ignore next */
|
|
21
|
-
const startServer = (0, helpers_1.
|
|
19
|
+
const startServer = (0, helpers_1.once)((port, uploadDir) => {
|
|
22
20
|
// TODO - re-evaluate the `preservePath` behavior to match whatever s3 does
|
|
23
21
|
const upload = (0, multer_1.default)({ dest: uploadDir, preservePath: true });
|
|
24
22
|
const fileServerApp = (0, express_1.default)();
|
|
@@ -63,9 +61,6 @@ const localFileServer = (initializer) => (configProvider) => {
|
|
|
63
61
|
const getSignedViewerUrl = async (source) => {
|
|
64
62
|
return `https://${await host}:${await port}/${source.path}`;
|
|
65
63
|
};
|
|
66
|
-
const getPublicViewerUrl = async (source) => {
|
|
67
|
-
return `https://${await host}:${await port}/${source.path}`;
|
|
68
|
-
};
|
|
69
64
|
const getFileContent = async (source) => {
|
|
70
65
|
const filePath = path_1.default.join(await fileDir, source.path);
|
|
71
66
|
return fs_1.default.promises.readFile(filePath);
|
|
@@ -77,56 +72,10 @@ const localFileServer = (initializer) => (configProvider) => {
|
|
|
77
72
|
await fs_1.default.promises.writeFile(filePath, content);
|
|
78
73
|
return source;
|
|
79
74
|
};
|
|
80
|
-
const getSignedFileUploadConfig = async () => {
|
|
81
|
-
const prefix = 'uploads/' + (0, uuid_1.v4)();
|
|
82
|
-
return {
|
|
83
|
-
url: `https://${await host}:${await port}/`,
|
|
84
|
-
payload: {
|
|
85
|
-
key: prefix + '/${filename}',
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
};
|
|
89
|
-
const copyFileTo = async (source, destinationPath) => {
|
|
90
|
-
const sourcePath = path_1.default.join(await fileDir, source.path);
|
|
91
|
-
const destPath = path_1.default.join(await fileDir, destinationPath);
|
|
92
|
-
const destDirectory = path_1.default.dirname(destPath);
|
|
93
|
-
await fs_1.default.promises.mkdir(destDirectory, { recursive: true });
|
|
94
|
-
await fs_1.default.promises.copyFile(sourcePath, destPath);
|
|
95
|
-
return {
|
|
96
|
-
...source,
|
|
97
|
-
path: destinationPath
|
|
98
|
-
};
|
|
99
|
-
};
|
|
100
|
-
const copyFileToDirectory = async (source, destination) => {
|
|
101
|
-
const destinationPath = path_1.default.join(destination, source.label);
|
|
102
|
-
return copyFileTo(source, destinationPath);
|
|
103
|
-
};
|
|
104
|
-
const isTemporaryUpload = (source) => {
|
|
105
|
-
return source.path.indexOf('uploads/') === 0;
|
|
106
|
-
};
|
|
107
|
-
const getFileChecksum = async (source) => {
|
|
108
|
-
const filePath = path_1.default.join(await fileDir, source.path);
|
|
109
|
-
const fileContent = await fs_1.default.promises.readFile(filePath);
|
|
110
|
-
return crypto_1.default.createHash('md5').update(fileContent).digest('hex');
|
|
111
|
-
};
|
|
112
|
-
const filesEqual = async (sourceA, sourceB) => {
|
|
113
|
-
const [aSum, bSum] = await Promise.all([
|
|
114
|
-
getFileChecksum(sourceA),
|
|
115
|
-
getFileChecksum(sourceB)
|
|
116
|
-
]);
|
|
117
|
-
return aSum === bSum;
|
|
118
|
-
};
|
|
119
75
|
return {
|
|
120
76
|
getSignedViewerUrl,
|
|
121
|
-
getPublicViewerUrl,
|
|
122
77
|
getFileContent,
|
|
123
78
|
putFileContent,
|
|
124
|
-
getSignedFileUploadConfig,
|
|
125
|
-
copyFileTo,
|
|
126
|
-
copyFileToDirectory,
|
|
127
|
-
isTemporaryUpload,
|
|
128
|
-
getFileChecksum,
|
|
129
|
-
filesEqual,
|
|
130
79
|
};
|
|
131
80
|
};
|
|
132
81
|
exports.localFileServer = localFileServer;
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.s3FileServer = void 0;
|
|
7
4
|
/* cspell:ignore presigner */
|
|
8
5
|
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
9
|
-
const s3_presigned_post_1 = require("@aws-sdk/s3-presigned-post");
|
|
10
6
|
const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
|
|
11
|
-
const path_1 = __importDefault(require("path"));
|
|
12
|
-
const uuid_1 = require("uuid");
|
|
13
7
|
const __1 = require("../..");
|
|
14
8
|
const assertions_1 = require("../../assertions");
|
|
15
9
|
const config_1 = require("../../config");
|
|
@@ -18,9 +12,6 @@ const s3FileServer = (initializer) => (configProvider) => {
|
|
|
18
12
|
const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'deployed')];
|
|
19
13
|
const bucketName = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.bucketName));
|
|
20
14
|
const bucketRegion = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.bucketRegion));
|
|
21
|
-
const publicViewerDomain = (0, __1.once)(() => 'publicViewerDomain' in config && config.publicViewerDomain
|
|
22
|
-
? (0, config_1.resolveConfigValue)(config.publicViewerDomain)
|
|
23
|
-
: undefined);
|
|
24
15
|
const s3Service = (0, __1.once)(async () => {
|
|
25
16
|
var _a, _b;
|
|
26
17
|
const args = { apiVersion: '2012-08-10', region: await bucketRegion() };
|
|
@@ -36,10 +27,6 @@ const s3FileServer = (initializer) => (configProvider) => {
|
|
|
36
27
|
expiresIn: 3600, // 1 hour
|
|
37
28
|
});
|
|
38
29
|
};
|
|
39
|
-
const getPublicViewerUrl = async (source) => {
|
|
40
|
-
const host = (0, assertions_1.assertDefined)(await publicViewerDomain(), new Error(`Tried to get public viewer URL for ${source.path} but no publicViewerDomain configured`));
|
|
41
|
-
return `https://${host}/${source.path}`;
|
|
42
|
-
};
|
|
43
30
|
const getFileContent = async (source) => {
|
|
44
31
|
const bucket = await bucketName();
|
|
45
32
|
const command = new client_s3_1.GetObjectCommand({ Bucket: bucket, Key: source.path });
|
|
@@ -57,75 +44,10 @@ const s3FileServer = (initializer) => (configProvider) => {
|
|
|
57
44
|
await (await s3Service()).send(command);
|
|
58
45
|
return source;
|
|
59
46
|
};
|
|
60
|
-
/*
|
|
61
|
-
* https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_s3_presigned_post.html
|
|
62
|
-
* https://docs.aws.amazon.com/AmazonS3/latest/userguide/HTTPPOSTExamples.html
|
|
63
|
-
* https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html
|
|
64
|
-
*/
|
|
65
|
-
const getSignedFileUploadConfig = async () => {
|
|
66
|
-
const prefix = 'uploads/' + (0, uuid_1.v4)();
|
|
67
|
-
const bucket = (await bucketName());
|
|
68
|
-
const Conditions = [
|
|
69
|
-
{ acl: 'private' },
|
|
70
|
-
{ bucket },
|
|
71
|
-
['starts-with', '$key', prefix]
|
|
72
|
-
];
|
|
73
|
-
const defaultFields = {
|
|
74
|
-
acl: 'private',
|
|
75
|
-
};
|
|
76
|
-
const { url, fields } = await (0, s3_presigned_post_1.createPresignedPost)(await s3Service(), {
|
|
77
|
-
Bucket: bucket,
|
|
78
|
-
Key: prefix + '/${filename}',
|
|
79
|
-
Conditions,
|
|
80
|
-
Fields: defaultFields,
|
|
81
|
-
Expires: 3600, // 1 hour
|
|
82
|
-
});
|
|
83
|
-
return {
|
|
84
|
-
url, payload: fields
|
|
85
|
-
};
|
|
86
|
-
};
|
|
87
|
-
const copyFileTo = async (source, destinationPath) => {
|
|
88
|
-
const bucket = (await bucketName());
|
|
89
|
-
const destinationPathWithoutLeadingSlash = destinationPath.replace(/^\//, '');
|
|
90
|
-
const command = new client_s3_1.CopyObjectCommand({
|
|
91
|
-
Bucket: bucket,
|
|
92
|
-
Key: destinationPathWithoutLeadingSlash,
|
|
93
|
-
CopySource: path_1.default.join(bucket, source.path),
|
|
94
|
-
});
|
|
95
|
-
await (await s3Service()).send(command);
|
|
96
|
-
return {
|
|
97
|
-
...source,
|
|
98
|
-
path: destinationPathWithoutLeadingSlash
|
|
99
|
-
};
|
|
100
|
-
};
|
|
101
|
-
const copyFileToDirectory = async (source, destination) => {
|
|
102
|
-
const destinationPath = path_1.default.join(destination, source.label);
|
|
103
|
-
return copyFileTo(source, destinationPath);
|
|
104
|
-
};
|
|
105
|
-
const isTemporaryUpload = (source) => {
|
|
106
|
-
return source.path.indexOf('uploads/') === 0;
|
|
107
|
-
};
|
|
108
|
-
const getFileChecksum = async (source) => {
|
|
109
|
-
const bucket = (await bucketName());
|
|
110
|
-
const command = new client_s3_1.HeadObjectCommand({ Bucket: bucket, Key: source.path });
|
|
111
|
-
const response = await (await s3Service()).send(command);
|
|
112
|
-
return (0, assertions_1.assertDefined)(response.ETag);
|
|
113
|
-
};
|
|
114
|
-
const filesEqual = async (sourceA, sourceB) => {
|
|
115
|
-
const [aSum, bSum] = await Promise.all([getFileChecksum(sourceA), getFileChecksum(sourceB)]);
|
|
116
|
-
return aSum === bSum;
|
|
117
|
-
};
|
|
118
47
|
return {
|
|
119
48
|
getFileContent,
|
|
120
49
|
putFileContent,
|
|
121
50
|
getSignedViewerUrl,
|
|
122
|
-
getPublicViewerUrl,
|
|
123
|
-
getSignedFileUploadConfig,
|
|
124
|
-
copyFileTo,
|
|
125
|
-
copyFileToDirectory,
|
|
126
|
-
isTemporaryUpload,
|
|
127
|
-
getFileChecksum,
|
|
128
|
-
filesEqual,
|
|
129
51
|
};
|
|
130
52
|
};
|
|
131
53
|
exports.s3FileServer = s3FileServer;
|
|
@@ -29,6 +29,10 @@ const openSearchService = (initializer = {}) => (configProvider) => {
|
|
|
29
29
|
maxRetries: 4, // default is 3
|
|
30
30
|
requestTimeout: 5000, // default is 30000
|
|
31
31
|
pingTimeout: 2000, // default is 30000
|
|
32
|
+
sniffOnConnectionFault: true,
|
|
33
|
+
sniffOnStart: true,
|
|
34
|
+
resurrectStrategy: 'ping',
|
|
35
|
+
agent: { keepAlive: false },
|
|
32
36
|
node: await (0, config_1.resolveConfigValue)(config.node),
|
|
33
37
|
}));
|
|
34
38
|
return (indexConfig) => {
|
|
@@ -64,9 +68,6 @@ const openSearchService = (initializer = {}) => (configProvider) => {
|
|
|
64
68
|
body: params.body,
|
|
65
69
|
id: params.id,
|
|
66
70
|
refresh: true
|
|
67
|
-
}, {
|
|
68
|
-
requestTimeout: 10000,
|
|
69
|
-
maxRetries: 1,
|
|
70
71
|
});
|
|
71
72
|
};
|
|
72
73
|
const bulkIndex = async (items) => {
|
|
@@ -78,9 +79,6 @@ const openSearchService = (initializer = {}) => (configProvider) => {
|
|
|
78
79
|
item.body
|
|
79
80
|
]),
|
|
80
81
|
refresh: true
|
|
81
|
-
}, {
|
|
82
|
-
requestTimeout: 10000,
|
|
83
|
-
maxRetries: 1,
|
|
84
82
|
});
|
|
85
83
|
};
|
|
86
84
|
const search = async (options) => {
|