@crowdin/app-project-module 0.82.1 → 0.83.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 CHANGED
@@ -37,6 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
38
  exports.addCrowdinEndpoints = exports.createApp = exports.metadataStore = exports.express = exports.UserPermissions = exports.Scope = exports.ProjectPermissions = exports.maskKey = exports.postRequestCredentialsMasker = exports.getRequestCredentialsMasker = void 0;
39
39
  const logsFormatter = __importStar(require("@crowdin/logs-formatter"));
40
+ const express_rate_limit_1 = require("express-rate-limit");
40
41
  const path_1 = require("path");
41
42
  const crowdin_client_1 = __importStar(require("./middlewares/crowdin-client"));
42
43
  const json_response_1 = __importDefault(require("./middlewares/json-response"));
@@ -46,6 +47,7 @@ const install_1 = __importDefault(require("./modules/install"));
46
47
  const manifest_1 = __importDefault(require("./modules/manifest"));
47
48
  const subscription_paid_1 = __importDefault(require("./modules/subscription-paid"));
48
49
  const uninstall_1 = __importDefault(require("./modules/uninstall"));
50
+ const status_1 = __importDefault(require("./modules/status"));
49
51
  const storage = __importStar(require("./storage"));
50
52
  const types_1 = require("./types");
51
53
  const util_1 = require("./util");
@@ -94,6 +96,15 @@ exports.metadataStore = {
94
96
  return storage.getStorage().getMetadata(id);
95
97
  },
96
98
  saveMetadata: (id, metadata, crowdinId) => __awaiter(void 0, void 0, void 0, function* () {
99
+ if (!crowdinId) {
100
+ console.warn('Warning: The crowdinId parameter in saveMetadata will be required. Please update your code to provide this parameter.');
101
+ }
102
+ else {
103
+ const crowdinCredentials = yield storage.getStorage().getCrowdinCredentials(crowdinId);
104
+ if (!crowdinCredentials) {
105
+ console.error('Invalid crowdinId parameter: You can get your crowdinId from the JWT payload');
106
+ }
107
+ }
97
108
  const existing = yield storage.getStorage().getMetadata(id);
98
109
  if (existing) {
99
110
  yield storage.getStorage().updateMetadata(id, metadata, crowdinId);
@@ -121,6 +132,7 @@ function createApp(clientConfig) {
121
132
  }
122
133
  exports.createApp = createApp;
123
134
  function addCrowdinEndpoints(app, clientConfig) {
135
+ var _a, _b, _c;
124
136
  const config = convertClientConfig(clientConfig);
125
137
  if (!config.disableGlobalErrorHandling) {
126
138
  handleUncaughtErrors();
@@ -146,6 +158,21 @@ function addCrowdinEndpoints(app, clientConfig) {
146
158
  app.set('view engine', 'handlebars');
147
159
  app.get((0, util_1.getLogoUrl)(), (req, res) => res.sendFile(config.imagePath));
148
160
  app.get('/manifest.json', json_response_1.default, (0, manifest_1.default)(config));
161
+ if (((_a = config === null || config === void 0 ? void 0 : config.enableStatusPage) === null || _a === void 0 ? void 0 : _a.database) || ((_b = config === null || config === void 0 ? void 0 : config.enableStatusPage) === null || _b === void 0 ? void 0 : _b.filesystem)) {
162
+ app.set('trust proxy', 1);
163
+ const limiter = (0, express_rate_limit_1.rateLimit)({
164
+ windowMs: 60 * 1000,
165
+ limit: ((_c = config.enableStatusPage) === null || _c === void 0 ? void 0 : _c.rateLimit) || 10,
166
+ standardHeaders: true,
167
+ legacyHeaders: false,
168
+ message: {
169
+ status: 429,
170
+ error: 'Too Many Requests',
171
+ message: 'Rate limit exceeded. Please try again later.',
172
+ },
173
+ });
174
+ app.get('/status', limiter, (0, status_1.default)(config));
175
+ }
149
176
  if (!(0, subscription_1.isAppFree)(config)) {
150
177
  app.post('/subscription-paid', (0, subscription_paid_1.default)());
151
178
  }
@@ -258,6 +285,7 @@ function convertClientConfig(clientConfig) {
258
285
  if (clientConfig.projectIntegration) {
259
286
  clientConfig.api = Object.assign({ default: true }, clientConfig.api);
260
287
  }
288
+ clientConfig.enableStatusPage = Object.assign({ database: true, filesystem: true }, (clientConfig.enableStatusPage || {}));
261
289
  return Object.assign(Object.assign({}, clientConfig), { baseUrl: baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl, clientId,
262
290
  clientSecret, awsConfig: {
263
291
  tmpBucketName,
@@ -17,6 +17,7 @@ const util_1 = require("../../../util");
17
17
  const defaults_1 = require("../util/defaults");
18
18
  const logger_1 = require("../../../util/logger");
19
19
  const storage_1 = require("../../../storage");
20
+ const crowdin_apps_functions_1 = require("@crowdin/crowdin-apps-functions");
20
21
  function handle(config, integration) {
21
22
  return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
22
23
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
@@ -28,6 +29,7 @@ function handle(config, integration) {
28
29
  (0, logger_1.log)(`Received request from OAuth login callback. Code ${code}`);
29
30
  (0, logger_1.log)(`Received request from OAuth login callback. State ${state}`);
30
31
  const clientId = Buffer.from(state, 'base64').toString();
32
+ const { organization } = (0, crowdin_apps_functions_1.parseCrowdinId)(clientId);
31
33
  const redirectUri = `${config.baseUrl}${(0, defaults_1.getOauthRoute)(integration)}`;
32
34
  try {
33
35
  const oauthLogin = integration.oauthLogin;
@@ -61,7 +63,7 @@ function handle(config, integration) {
61
63
  message.data = oauthCredentials;
62
64
  if (((_o = integration.oauthLogin) === null || _o === void 0 ? void 0 : _o.mode) === 'polling') {
63
65
  yield (0, storage_1.getStorage)().deleteMetadata((0, defaults_1.getOAuthPollingId)(clientId));
64
- yield (0, storage_1.getStorage)().saveMetadata((0, defaults_1.getOAuthPollingId)(clientId), oauthCredentials);
66
+ yield (0, storage_1.getStorage)().saveMetadata((0, defaults_1.getOAuthPollingId)(clientId), oauthCredentials, organization);
65
67
  }
66
68
  return res.render('oauth', { message: JSON.stringify(message), oauthMode: (_p = integration.oauthLogin) === null || _p === void 0 ? void 0 : _p.mode });
67
69
  }
@@ -23,7 +23,7 @@ function handle(config, integration) {
23
23
  }
24
24
  const { loginForm } = req.body;
25
25
  yield (0, storage_1.getStorage)().deleteMetadata((0, defaults_1.getOAuthLoginFormId)(req.crowdinContext.clientId));
26
- yield (0, storage_1.getStorage)().saveMetadata((0, defaults_1.getOAuthLoginFormId)(req.crowdinContext.clientId), loginForm);
26
+ yield (0, storage_1.getStorage)().saveMetadata((0, defaults_1.getOAuthLoginFormId)(req.crowdinContext.clientId), loginForm, req.crowdinContext.crowdinId);
27
27
  const url = (0, defaults_1.constructOauthUrl)({ config, integration, clientId: req.crowdinContext.clientId, loginForm });
28
28
  res.send({ url });
29
29
  }));
@@ -359,7 +359,7 @@ function handle(config) {
359
359
  const manifest = Object.assign(Object.assign(Object.assign(Object.assign({ identifier: config.identifier, name: config.name, logo: (0, util_1.getLogoUrl)(), baseUrl: config.baseUrl, authentication: {
360
360
  type: config.authenticationType || types_1.AuthenticationType.APP,
361
361
  clientId: config.clientId,
362
- } }, (config.agent && { agent: config.agent })), { events, scopes: config.scopes ? config.scopes : defaultScopes }), (config.defaultPermissions && { default_permissions: config.defaultPermissions })), { modules });
362
+ }, restrictAiToSameApp: config.restrictAiToSameApp }, (config.agent && { agent: config.agent })), { events, scopes: config.scopes ? config.scopes : defaultScopes }), (config.defaultPermissions && { default_permissions: config.defaultPermissions })), { modules });
363
363
  res.send(manifest);
364
364
  };
365
365
  }
@@ -0,0 +1,4 @@
1
+ /// <reference types="qs" />
2
+ import { Request, Response } from 'express';
3
+ import { Config, UnauthorizedConfig } from '../types';
4
+ export default function handle(config: Config | UnauthorizedConfig): (req: import("../types").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;
@@ -0,0 +1,74 @@
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
+ const util_1 = require("../util");
16
+ const logger_1 = require("../util/logger");
17
+ const storage_1 = require("../storage");
18
+ const promises_1 = __importDefault(require("fs/promises"));
19
+ const path_1 = __importDefault(require("path"));
20
+ const os_1 = __importDefault(require("os"));
21
+ function handle(config) {
22
+ return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
23
+ var _a, _b;
24
+ const response = {
25
+ status: 'ok',
26
+ timestamp: new Date().toISOString(),
27
+ };
28
+ let hasError = false;
29
+ if (((_a = config === null || config === void 0 ? void 0 : config.enableStatusPage) === null || _a === void 0 ? void 0 : _a.database) === true) {
30
+ let status = 'ok';
31
+ let message = 'Database connection successful';
32
+ try {
33
+ yield (0, storage_1.getStorage)().getAllMetadata();
34
+ }
35
+ catch (e) {
36
+ status = 'error';
37
+ message = (e === null || e === void 0 ? void 0 : e.message) || 'Database connection error';
38
+ hasError = true;
39
+ (0, logger_1.logError)(e);
40
+ }
41
+ response.database = {
42
+ status,
43
+ message,
44
+ };
45
+ }
46
+ if (((_b = config === null || config === void 0 ? void 0 : config.enableStatusPage) === null || _b === void 0 ? void 0 : _b.filesystem) === true) {
47
+ let status = 'ok';
48
+ let message = 'Filesystem access successful';
49
+ try {
50
+ const testFile = path_1.default.join(os_1.default.tmpdir(), 'status-check.txt');
51
+ yield promises_1.default.writeFile(testFile, 'test');
52
+ yield promises_1.default.unlink(testFile);
53
+ }
54
+ catch (e) {
55
+ status = 'error';
56
+ message = (e === null || e === void 0 ? void 0 : e.message) || 'Filesystem error';
57
+ hasError = true;
58
+ (0, logger_1.logError)(e);
59
+ }
60
+ response.filesystem = {
61
+ status,
62
+ message,
63
+ };
64
+ }
65
+ if (hasError) {
66
+ response.status = 'error';
67
+ res.status(503).json(response);
68
+ }
69
+ else {
70
+ res.json(response);
71
+ }
72
+ }));
73
+ }
74
+ exports.default = handle;