@crowdin/app-project-module 0.61.0 → 0.63.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/out/index.js +10 -3
- package/out/modules/integration/util/cron.js +224 -216
- package/out/static/js/form.js +1 -1
- package/out/types.d.ts +4 -0
- package/out/util/credentials-masker.d.ts +6 -0
- package/out/util/credentials-masker.js +102 -0
- package/out/util/form-schema.d.ts +3 -0
- package/out/util/form-schema.js +21 -0
- package/out/util/index.d.ts +0 -1
- package/out/util/index.js +1 -9
- package/package.json +1 -1
package/out/types.d.ts
CHANGED
|
@@ -364,6 +364,10 @@ export interface UiModule {
|
|
|
364
364
|
* Module name
|
|
365
365
|
*/
|
|
366
366
|
name?: string;
|
|
367
|
+
/**
|
|
368
|
+
* Temporary property. Indicates if passwords should be masked. Will be dropped when all existing apps will migrate.
|
|
369
|
+
*/
|
|
370
|
+
maskPasswords?: boolean;
|
|
367
371
|
}
|
|
368
372
|
export interface ImagePath {
|
|
369
373
|
/**
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/// <reference types="qs" />
|
|
2
|
+
import { CrowdinClientRequest, UiModule } from '../types';
|
|
3
|
+
import { Request, Response } from 'express';
|
|
4
|
+
declare function postRequestCredentialsMasker(moduleConfig?: UiModule, credentialsExtractor?: Function): (req: CrowdinClientRequest | Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: Function) => void;
|
|
5
|
+
declare function getRequestCredentialsMasker(moduleConfig?: UiModule): (req: Request | CrowdinClientRequest, res: Response, next: Function) => any;
|
|
6
|
+
export { getRequestCredentialsMasker, postRequestCredentialsMasker };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.postRequestCredentialsMasker = exports.getRequestCredentialsMasker = void 0;
|
|
16
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
17
|
+
const index_1 = require("./index");
|
|
18
|
+
const index_2 = require("../index");
|
|
19
|
+
const crowdin_client_1 = require("../middlewares/crowdin-client");
|
|
20
|
+
const crowdin_apps_functions_1 = require("@crowdin/crowdin-apps-functions");
|
|
21
|
+
function maskKey(key) {
|
|
22
|
+
const maskWith = '*';
|
|
23
|
+
const unmaskedCharsAtEnd = 3;
|
|
24
|
+
const repeatCount = key.length > unmaskedCharsAtEnd ? key.length - unmaskedCharsAtEnd : 0;
|
|
25
|
+
return maskWith.repeat(repeatCount) + key.substring(key.length - 3);
|
|
26
|
+
}
|
|
27
|
+
function getMaskableFieldsKeys(moduleConfig) {
|
|
28
|
+
if (!moduleConfig.formUiSchema) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
return Object.keys(moduleConfig.formUiSchema).filter((fieldKey) => {
|
|
32
|
+
return lodash_1.default.get(moduleConfig, `formUiSchema[${fieldKey}]['ui:widget']`) === 'password';
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function postRequestCredentialsMasker(moduleConfig, credentialsExtractor) {
|
|
36
|
+
return (0, index_1.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
if (!moduleConfig || !moduleConfig.formSchema || !moduleConfig.formUiSchema) {
|
|
38
|
+
return next();
|
|
39
|
+
}
|
|
40
|
+
// temporary
|
|
41
|
+
if (!moduleConfig.maskPasswords) {
|
|
42
|
+
return next();
|
|
43
|
+
}
|
|
44
|
+
const fieldsKeysInRequest = Object.keys(req.body.data);
|
|
45
|
+
let unmaskedFields = {};
|
|
46
|
+
if (credentialsExtractor) {
|
|
47
|
+
unmaskedFields = yield credentialsExtractor(req, res);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
// most common way of storing data
|
|
51
|
+
const jwtToken = (0, crowdin_client_1.getToken)(req) || '';
|
|
52
|
+
const jwtPayload = yield (0, crowdin_apps_functions_1.validateJwtToken)(jwtToken, process.env.CROWDIN_CLIENT_SECRET || '');
|
|
53
|
+
const crowdinId = `${jwtPayload.context.organization_id}`;
|
|
54
|
+
unmaskedFields = yield index_2.metadataStore.getMetadata(`form-data-${crowdinId}`);
|
|
55
|
+
}
|
|
56
|
+
unmaskedFields = unmaskedFields || {};
|
|
57
|
+
const maskableFieldsKeys = getMaskableFieldsKeys(moduleConfig);
|
|
58
|
+
Object.keys(unmaskedFields).forEach((fieldKey) => {
|
|
59
|
+
if (!maskableFieldsKeys.includes(fieldKey) || !fieldsKeysInRequest.includes(fieldKey)) {
|
|
60
|
+
delete unmaskedFields[fieldKey];
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
req.body.data = Object.assign(Object.assign({}, req.body.data), Object.keys(unmaskedFields).reduce((acc, key) => {
|
|
64
|
+
if (maskKey(unmaskedFields[key]) === req.body.data[key]) {
|
|
65
|
+
acc[key] = unmaskedFields[key];
|
|
66
|
+
}
|
|
67
|
+
return acc;
|
|
68
|
+
}, {}));
|
|
69
|
+
next();
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
exports.postRequestCredentialsMasker = postRequestCredentialsMasker;
|
|
73
|
+
function getRequestCredentialsMasker(moduleConfig) {
|
|
74
|
+
return function (req, res, next) {
|
|
75
|
+
// we can't find "password" fields without ui schema
|
|
76
|
+
if (!moduleConfig || !moduleConfig.formSchema || !moduleConfig.formUiSchema) {
|
|
77
|
+
return next();
|
|
78
|
+
}
|
|
79
|
+
// temporary
|
|
80
|
+
if (!moduleConfig.maskPasswords) {
|
|
81
|
+
return next();
|
|
82
|
+
}
|
|
83
|
+
const maskableFieldsKeys = getMaskableFieldsKeys(moduleConfig);
|
|
84
|
+
if (!maskableFieldsKeys.length) {
|
|
85
|
+
return next();
|
|
86
|
+
}
|
|
87
|
+
const originalSend = res.send;
|
|
88
|
+
res.send = function (body) {
|
|
89
|
+
if (body.formData) {
|
|
90
|
+
maskableFieldsKeys.forEach((fieldKey) => {
|
|
91
|
+
if (!body.formData[fieldKey]) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
body.formData[fieldKey] = maskKey(body.formData[fieldKey]);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return originalSend.apply(res, [body]);
|
|
98
|
+
};
|
|
99
|
+
return next();
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
exports.getRequestCredentialsMasker = getRequestCredentialsMasker;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasFormSchema = exports.getLowCodeUiConfigFromModuleConfig = void 0;
|
|
4
|
+
function getLowCodeUiConfigFromModuleConfig(moduleConfig) {
|
|
5
|
+
var _a;
|
|
6
|
+
if (typeof moduleConfig !== 'object' || moduleConfig === null) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
if ((_a = moduleConfig.settingsUiModule) === null || _a === void 0 ? void 0 : _a.formSchema) {
|
|
10
|
+
return moduleConfig.settingsUiModule;
|
|
11
|
+
}
|
|
12
|
+
if (moduleConfig.formSchema) {
|
|
13
|
+
return moduleConfig;
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
exports.getLowCodeUiConfigFromModuleConfig = getLowCodeUiConfigFromModuleConfig;
|
|
18
|
+
function hasFormSchema(moduleConfig) {
|
|
19
|
+
return !!getLowCodeUiConfigFromModuleConfig(moduleConfig);
|
|
20
|
+
}
|
|
21
|
+
exports.hasFormSchema = hasFormSchema;
|
package/out/util/index.d.ts
CHANGED
|
@@ -10,4 +10,3 @@ export declare function decryptData(config: Config, data: string): string;
|
|
|
10
10
|
export declare function executeWithRetry<T>(func: () => Promise<T>, numOfRetries?: number): Promise<T>;
|
|
11
11
|
export declare function getLogoUrl(moduleConfig?: ImagePath, modulePath?: string): string;
|
|
12
12
|
export declare function isAuthorizedConfig(config: Config | UnauthorizedConfig): config is Config;
|
|
13
|
-
export declare function hasFormSchema(moduleConfig: any): boolean;
|
package/out/util/index.js
CHANGED
|
@@ -32,7 +32,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
32
32
|
});
|
|
33
33
|
};
|
|
34
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
-
exports.
|
|
35
|
+
exports.isAuthorizedConfig = exports.getLogoUrl = exports.executeWithRetry = exports.decryptData = exports.encryptData = exports.runAsyncWrapper = exports.CodeError = void 0;
|
|
36
36
|
const crypto = __importStar(require("crypto-js"));
|
|
37
37
|
const storage_1 = require("../storage");
|
|
38
38
|
const types_1 = require("../types");
|
|
@@ -118,11 +118,3 @@ function isAuthorizedConfig(config) {
|
|
|
118
118
|
return !!config.clientId && !!config.clientSecret && config.authenticationType !== types_1.AuthenticationType.NONE;
|
|
119
119
|
}
|
|
120
120
|
exports.isAuthorizedConfig = isAuthorizedConfig;
|
|
121
|
-
function hasFormSchema(moduleConfig) {
|
|
122
|
-
var _a;
|
|
123
|
-
if (typeof moduleConfig === 'object' && moduleConfig !== null) {
|
|
124
|
-
return moduleConfig.formSchema || ((_a = moduleConfig.settingsUiModule) === null || _a === void 0 ? void 0 : _a.formSchema);
|
|
125
|
-
}
|
|
126
|
-
return false;
|
|
127
|
-
}
|
|
128
|
-
exports.hasFormSchema = hasFormSchema;
|
package/package.json
CHANGED