@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 +28 -0
- package/out/modules/integration/handlers/oauth-login.js +3 -1
- package/out/modules/integration/handlers/oauth-url.js +1 -1
- package/out/modules/manifest.js +1 -1
- package/out/modules/status.d.ts +4 -0
- package/out/modules/status.js +74 -0
- package/out/static/js/form.js +11 -11
- package/out/storage/index.d.ts +1 -2
- package/out/storage/index.js +3 -3
- package/out/types.d.ts +12 -0
- package/package.json +2 -1
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
|
}));
|
package/out/modules/manifest.js
CHANGED
|
@@ -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;
|