UNPKG

@crowdin/app-project-module

Version:

Module that generates for you all common endpoints for serving standalone Crowdin App

104 lines (103 loc) 4.95 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getRequestCredentialsMasker = getRequestCredentialsMasker; exports.maskKey = maskKey; exports.postRequestCredentialsMasker = postRequestCredentialsMasker; const index_1 = require("../index"); const crowdin_client_1 = require("../middlewares/crowdin-client"); const token_1 = require("./app-functions/token"); const index_2 = require("./index"); function maskKey(key) { const maskWith = '*'; const unmaskedCharsAtEnd = 3; const repeatCount = key.length > unmaskedCharsAtEnd ? key.length - unmaskedCharsAtEnd : 0; return maskWith.repeat(repeatCount) + key.substring(key.length - 3); } function getMaskableFieldsKeys(moduleConfig) { if (!moduleConfig.formUiSchema) { return []; } return Object.keys(moduleConfig.formUiSchema).filter((fieldKey) => { var _a, _b; return ((_b = (_a = moduleConfig === null || moduleConfig === void 0 ? void 0 : moduleConfig.formUiSchema) === null || _a === void 0 ? void 0 : _a[fieldKey]) === null || _b === void 0 ? void 0 : _b['ui:widget']) === 'password'; }); } function getRequestCredentialsMasker({ moduleConfig, dataPath = 'formData', }) { return function (req, res, next) { if (req.__credentialsMaskerApplied) { return next(); } req.__credentialsMaskerApplied = true; // we can't find "password" fields without ui schema if (!moduleConfig || !moduleConfig.formSchema || !moduleConfig.formUiSchema) { return next(); } const maskableFieldsKeys = getMaskableFieldsKeys(moduleConfig); if (!maskableFieldsKeys.length) { return next(); } const originalSend = res.send; res.send = function (body) { const maskFields = (target) => { maskableFieldsKeys.forEach((fieldKey) => { if (target[fieldKey]) { target[fieldKey] = maskKey(target[fieldKey]); } }); }; if (body[dataPath]) { maskFields(body[dataPath]); } if (dataPath === '') { maskFields(body); } return originalSend.apply(res, [body]); }; return next(); }; } function postRequestCredentialsMasker({ secret, moduleConfig, credentialsExtractor, }) { return (0, index_2.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () { var _a; if (req.__credentialsMaskerApplied) { return next(); } req.__credentialsMaskerApplied = true; if (!moduleConfig || !moduleConfig.formSchema || !moduleConfig.formUiSchema) { return next(); } const fieldsKeysInRequest = Object.keys(((_a = req.body) === null || _a === void 0 ? void 0 : _a.data) || []); let unmaskedFields = {}; if (credentialsExtractor) { unmaskedFields = yield credentialsExtractor(req, res); } else { // most common way of storing data const jwtToken = (0, crowdin_client_1.getToken)(req) || ''; const jwtPayload = yield (0, token_1.validateJwtToken)(jwtToken, secret); const crowdinId = `${jwtPayload.context.organization_id}`; unmaskedFields = yield index_1.metadataStore.getMetadata(`form-data-${crowdinId}`); } unmaskedFields = unmaskedFields || {}; const maskableFieldsKeys = getMaskableFieldsKeys(moduleConfig); Object.keys(unmaskedFields).forEach((fieldKey) => { if (!maskableFieldsKeys.includes(fieldKey) || !fieldsKeysInRequest.includes(fieldKey)) { delete unmaskedFields[fieldKey]; } }); req.body.data = Object.assign(Object.assign({}, req.body.data), Object.keys(unmaskedFields).reduce((acc, key) => { if (maskKey(unmaskedFields[key]) === req.body.data[key]) { acc[key] = unmaskedFields[key]; } return acc; }, {})); // run getRequestCredentialsMasker to mask fields that can be in response return getRequestCredentialsMasker({ moduleConfig })(req, res, next); })); }