@crowdin/app-project-module 1.3.1 → 1.4.1
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/middlewares/integration-credentials.d.ts +6 -1
- package/out/middlewares/integration-credentials.js +39 -2
- package/out/middlewares/render-ui-module.js +9 -2
- package/out/modules/api/api.js +13 -13
- package/out/modules/integration/handlers/integration-logout.js +2 -1
- package/out/modules/integration/index.js +13 -13
- package/out/modules/integration/types.d.ts +1 -0
- package/out/modules/integration/util/cron.js +12 -4
- package/out/modules/integration/util/webhooks.js +6 -3
- package/out/modules/manifest.js +3 -1
- package/out/modules/workflow-step-type/index.js +1 -1
- package/out/static/ui/error.bundle.js +2 -2
- package/out/static/ui/error.bundle.js.map +1 -1
- package/out/types.d.ts +4 -0
- package/out/util/connection.js +55 -20
- package/out/util/index.d.ts +1 -1
- package/out/util/index.js +56 -3
- package/out/views/AboutPage.js +14 -2
- package/package.json +1 -1
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { Response } from 'express';
|
|
2
2
|
import { IntegrationLogic } from '../modules/integration/types';
|
|
3
3
|
import { Config } from '../types';
|
|
4
|
-
export default function handle(config
|
|
4
|
+
export default function handle({ config, integration, optional, isLogout, }: {
|
|
5
|
+
config: Config;
|
|
6
|
+
integration: IntegrationLogic;
|
|
7
|
+
optional?: boolean;
|
|
8
|
+
isLogout?: boolean;
|
|
9
|
+
}): (req: import("express").Request | import("../types").CrowdinClientRequest, res: Response, next: Function) => void;
|
|
@@ -44,22 +44,24 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
45
|
exports.default = handle;
|
|
46
46
|
const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
|
|
47
|
+
const users_1 = require("../modules/integration/handlers/users");
|
|
47
48
|
const storage_1 = require("../storage");
|
|
48
49
|
const util_1 = require("../util");
|
|
49
50
|
const connection_1 = require("../util/connection");
|
|
50
51
|
const jsx_renderer_1 = require("../util/jsx-renderer");
|
|
51
52
|
const logger_1 = require("../util/logger");
|
|
52
|
-
function handle(config, integration, optional = false) {
|
|
53
|
+
function handle({ config, integration, optional = false, isLogout = false, }) {
|
|
53
54
|
return (0, util_1.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
54
55
|
let clientId = req.crowdinContext.clientId;
|
|
55
56
|
const isApiCall = req === null || req === void 0 ? void 0 : req.isApiCall;
|
|
56
57
|
const { organization, projectId, userId } = crowdinAppFunctions.parseCrowdinId(clientId);
|
|
57
58
|
req.logInfo(`Loading integration credentials for client ${clientId}`);
|
|
58
59
|
let integrationCredentials = yield (0, storage_1.getStorage)().getIntegrationCredentials(clientId);
|
|
60
|
+
let projectIntegrationCredentials = [];
|
|
59
61
|
const ownerIds = [];
|
|
60
62
|
// check if user has access to integration in settings(managers)
|
|
61
63
|
if (!integrationCredentials) {
|
|
62
|
-
|
|
64
|
+
projectIntegrationCredentials = (yield (0, storage_1.getStorage)().getAllIntegrationCredentials(organization)).filter((item) => {
|
|
63
65
|
const { organization: itemOrganization, projectId: itemProjectId } = crowdinAppFunctions.parseCrowdinId(item.id);
|
|
64
66
|
return itemOrganization === organization && itemProjectId === projectId;
|
|
65
67
|
});
|
|
@@ -74,6 +76,19 @@ function handle(config, integration, optional = false) {
|
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
}
|
|
79
|
+
if (!integrationCredentials && isLogout && projectIntegrationCredentials.length) {
|
|
80
|
+
const canForceLogout = yield isCrowdinProjectManager({
|
|
81
|
+
req,
|
|
82
|
+
projectId,
|
|
83
|
+
memberId: req.crowdinContext.jwtPayload.context.user_id,
|
|
84
|
+
});
|
|
85
|
+
if (canForceLogout) {
|
|
86
|
+
integrationCredentials = projectIntegrationCredentials[0];
|
|
87
|
+
clientId = integrationCredentials.id;
|
|
88
|
+
req.crowdinContext.clientId = clientId;
|
|
89
|
+
req.canForceIntegrationLogout = true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
77
92
|
}
|
|
78
93
|
if (!integrationCredentials) {
|
|
79
94
|
const owners = yield getIntegrationManagedBy(ownerIds, req);
|
|
@@ -85,6 +100,7 @@ function handle(config, integration, optional = false) {
|
|
|
85
100
|
message: 'Access denied',
|
|
86
101
|
owners: null,
|
|
87
102
|
hideActions: false,
|
|
103
|
+
allowLogout: false,
|
|
88
104
|
};
|
|
89
105
|
if (isApiCall) {
|
|
90
106
|
return res.status(errorOptions.code).json({
|
|
@@ -97,6 +113,11 @@ function handle(config, integration, optional = false) {
|
|
|
97
113
|
errorOptions.message = 'Looks like you don’t have access';
|
|
98
114
|
errorOptions.hideActions = true;
|
|
99
115
|
errorOptions.owners = owners;
|
|
116
|
+
errorOptions.allowLogout = yield isCrowdinProjectManager({
|
|
117
|
+
req,
|
|
118
|
+
projectId,
|
|
119
|
+
memberId: req.crowdinContext.jwtPayload.context.user_id,
|
|
120
|
+
});
|
|
100
121
|
}
|
|
101
122
|
else {
|
|
102
123
|
(0, logger_1.temporaryErrorDebug)('Access denied: integration-credentials', req);
|
|
@@ -174,3 +195,19 @@ function getIntegrationManagedBy(ownerIds, req) {
|
|
|
174
195
|
});
|
|
175
196
|
});
|
|
176
197
|
}
|
|
198
|
+
function isCrowdinProjectManager(_a) {
|
|
199
|
+
return __awaiter(this, arguments, void 0, function* ({ req, projectId, memberId, }) {
|
|
200
|
+
try {
|
|
201
|
+
const canManageProject = yield (0, users_1.isManager)({
|
|
202
|
+
client: req.crowdinApiClient,
|
|
203
|
+
projectId,
|
|
204
|
+
memberId,
|
|
205
|
+
});
|
|
206
|
+
return !!canManageProject;
|
|
207
|
+
}
|
|
208
|
+
catch (e) {
|
|
209
|
+
console.warn('Failed to determine project manager role', e);
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
}
|
|
@@ -17,11 +17,18 @@ const jsx_renderer_1 = require("../util/jsx-renderer");
|
|
|
17
17
|
function handle(moduleConfig, config) {
|
|
18
18
|
return (0, util_1.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
19
19
|
if (moduleConfig.formSchema) {
|
|
20
|
+
// Skip non-HTML requests so custom form data endpoints (formGetDataUrl/formPostDataUrl)
|
|
21
|
+
// are not intercepted when they share the same base path as the module UI route
|
|
22
|
+
if (!/\.html?$/i.test(req.path)) {
|
|
23
|
+
return next();
|
|
24
|
+
}
|
|
20
25
|
const html = (0, jsx_renderer_1.renderJSXOnServer)(views_1.FormPage, {
|
|
21
26
|
formGetDataUrl: moduleConfig.formGetDataUrl || `/api/${moduleConfig.key}/form-data`,
|
|
22
27
|
formPostDataUrl: moduleConfig.formPostDataUrl || `/api/${moduleConfig.key}/form-data`,
|
|
23
|
-
formSchema: JSON.stringify(moduleConfig.formSchema),
|
|
24
|
-
formUiSchema: moduleConfig.formUiSchema
|
|
28
|
+
formSchema: JSON.stringify(moduleConfig.formSchema).replace(/</g, '\\u003c'),
|
|
29
|
+
formUiSchema: moduleConfig.formUiSchema
|
|
30
|
+
? JSON.stringify(moduleConfig.formUiSchema).replace(/</g, '\\u003c')
|
|
31
|
+
: '{}',
|
|
25
32
|
formPatchDataUrl: moduleConfig.formPatchDataUrl,
|
|
26
33
|
});
|
|
27
34
|
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
package/out/modules/api/api.js
CHANGED
|
@@ -206,7 +206,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
206
206
|
optional: false,
|
|
207
207
|
checkSubscriptionExpiration: true,
|
|
208
208
|
moduleKey: 'crowdin-files-api',
|
|
209
|
-
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, crowdin_files_1.default)(config, config.projectIntegration));
|
|
209
|
+
}), (0, integration_credentials_1.default)({ config, integration: config.projectIntegration }), (0, crowdin_files_1.default)(config, config.projectIntegration));
|
|
210
210
|
/**
|
|
211
211
|
* @openapi
|
|
212
212
|
* /file-progress:
|
|
@@ -240,7 +240,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
240
240
|
optional: false,
|
|
241
241
|
checkSubscriptionExpiration: true,
|
|
242
242
|
moduleKey: 'file-translation-progress-api',
|
|
243
|
-
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, crowdin_file_progress_1.default)(config.projectIntegration));
|
|
243
|
+
}), (0, integration_credentials_1.default)({ config, integration: config.projectIntegration }), (0, crowdin_file_progress_1.default)(config.projectIntegration));
|
|
244
244
|
/**
|
|
245
245
|
* @openapi
|
|
246
246
|
* /integration-files:
|
|
@@ -272,7 +272,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
272
272
|
optional: false,
|
|
273
273
|
checkSubscriptionExpiration: true,
|
|
274
274
|
moduleKey: 'integration-files-api',
|
|
275
|
-
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, integration_data_1.default)(config.projectIntegration));
|
|
275
|
+
}), (0, integration_credentials_1.default)({ config, integration: config.projectIntegration }), (0, integration_data_1.default)(config.projectIntegration));
|
|
276
276
|
/**
|
|
277
277
|
* @openapi
|
|
278
278
|
* /crowdin-update:
|
|
@@ -300,7 +300,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
300
300
|
optional: false,
|
|
301
301
|
checkSubscriptionExpiration: true,
|
|
302
302
|
moduleKey: 'crowdin-update-api',
|
|
303
|
-
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, crowdin_update_1.default)(config, config.projectIntegration));
|
|
303
|
+
}), (0, integration_credentials_1.default)({ config, integration: config.projectIntegration }), (0, crowdin_update_1.default)(config, config.projectIntegration));
|
|
304
304
|
/**
|
|
305
305
|
* @openapi
|
|
306
306
|
* /integration-update:
|
|
@@ -328,7 +328,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
328
328
|
optional: false,
|
|
329
329
|
checkSubscriptionExpiration: true,
|
|
330
330
|
moduleKey: 'integration-update-api',
|
|
331
|
-
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, integration_update_1.default)(config, config.projectIntegration));
|
|
331
|
+
}), (0, integration_credentials_1.default)({ config, integration: config.projectIntegration }), (0, integration_update_1.default)(config, config.projectIntegration));
|
|
332
332
|
/**
|
|
333
333
|
* @openapi
|
|
334
334
|
* /all-jobs:
|
|
@@ -372,7 +372,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
372
372
|
optional: false,
|
|
373
373
|
checkSubscriptionExpiration: true,
|
|
374
374
|
moduleKey: 'job-list-api',
|
|
375
|
-
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, job_list_1.default)());
|
|
375
|
+
}), (0, integration_credentials_1.default)({ config, integration: config.projectIntegration }), (0, job_list_1.default)());
|
|
376
376
|
/**
|
|
377
377
|
* @openapi
|
|
378
378
|
* /job-info:
|
|
@@ -416,7 +416,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
416
416
|
optional: false,
|
|
417
417
|
checkSubscriptionExpiration: true,
|
|
418
418
|
moduleKey: 'job-info-api',
|
|
419
|
-
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, job_info_1.default)());
|
|
419
|
+
}), (0, integration_credentials_1.default)({ config, integration: config.projectIntegration }), (0, job_info_1.default)());
|
|
420
420
|
/**
|
|
421
421
|
* @openapi
|
|
422
422
|
* /jobs:
|
|
@@ -447,7 +447,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
447
447
|
optional: false,
|
|
448
448
|
checkSubscriptionExpiration: true,
|
|
449
449
|
moduleKey: 'job-get-api',
|
|
450
|
-
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, job_info_deprecated_1.default)(config));
|
|
450
|
+
}), (0, integration_credentials_1.default)({ config, integration: config.projectIntegration }), (0, job_info_deprecated_1.default)(config));
|
|
451
451
|
/**
|
|
452
452
|
* @openapi
|
|
453
453
|
* /jobs:
|
|
@@ -487,7 +487,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
487
487
|
optional: false,
|
|
488
488
|
checkSubscriptionExpiration: true,
|
|
489
489
|
moduleKey: 'job-cancel-api',
|
|
490
|
-
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, job_cancel_1.default)());
|
|
490
|
+
}), (0, integration_credentials_1.default)({ config, integration: config.projectIntegration }), (0, job_cancel_1.default)());
|
|
491
491
|
/**
|
|
492
492
|
* @openapi
|
|
493
493
|
* /settings:
|
|
@@ -513,7 +513,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
513
513
|
optional: false,
|
|
514
514
|
checkSubscriptionExpiration: true,
|
|
515
515
|
moduleKey: 'settings-api',
|
|
516
|
-
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, settings_1.default)());
|
|
516
|
+
}), (0, integration_credentials_1.default)({ config, integration: config.projectIntegration }), (0, settings_1.default)());
|
|
517
517
|
/**
|
|
518
518
|
* @openapi
|
|
519
519
|
* /settings:
|
|
@@ -536,7 +536,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
536
536
|
optional: false,
|
|
537
537
|
checkSubscriptionExpiration: true,
|
|
538
538
|
moduleKey: 'settings-update-api',
|
|
539
|
-
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, settings_save_1.default)(config, config.projectIntegration));
|
|
539
|
+
}), (0, integration_credentials_1.default)({ config, integration: config.projectIntegration }), (0, settings_save_1.default)(config, config.projectIntegration));
|
|
540
540
|
/**
|
|
541
541
|
* @openapi
|
|
542
542
|
* /sync-settings:
|
|
@@ -573,7 +573,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
573
573
|
optional: false,
|
|
574
574
|
checkSubscriptionExpiration: true,
|
|
575
575
|
moduleKey: 'sync-settings-api',
|
|
576
|
-
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, sync_settings_1.default)());
|
|
576
|
+
}), (0, integration_credentials_1.default)({ config, integration: config.projectIntegration }), (0, sync_settings_1.default)());
|
|
577
577
|
/**
|
|
578
578
|
* @openapi
|
|
579
579
|
* /sync-settings:
|
|
@@ -596,7 +596,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
596
596
|
optional: false,
|
|
597
597
|
checkSubscriptionExpiration: true,
|
|
598
598
|
moduleKey: 'sync-settings-update-api',
|
|
599
|
-
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, sync_settings_save_1.default)(config, config.projectIntegration));
|
|
599
|
+
}), (0, integration_credentials_1.default)({ config, integration: config.projectIntegration }), (0, sync_settings_save_1.default)(config, config.projectIntegration));
|
|
600
600
|
if (config.projectIntegration.loginForm) {
|
|
601
601
|
/**
|
|
602
602
|
* @openapi
|
|
@@ -52,7 +52,8 @@ const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-function
|
|
|
52
52
|
function handle(config, integration) {
|
|
53
53
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
54
54
|
const { userId } = crowdinAppFunctions.parseCrowdinId(req.crowdinContext.clientId);
|
|
55
|
-
|
|
55
|
+
const isCredentialOwner = +userId === +req.crowdinContext.jwtPayload.sub;
|
|
56
|
+
if (!isCredentialOwner && !req.canForceIntegrationLogout) {
|
|
56
57
|
return res.status(403).send({ error: 'Access denied' });
|
|
57
58
|
}
|
|
58
59
|
req.logInfo('Received integration logout request');
|
|
@@ -62,7 +62,7 @@ function register({ config, app }) {
|
|
|
62
62
|
optional: true,
|
|
63
63
|
checkSubscriptionExpiration: false,
|
|
64
64
|
moduleKey: integrationLogic.key,
|
|
65
|
-
}), (0, integration_credentials_1.default)(config, integrationLogic, true), (0, main_1.default)(config, integrationLogic));
|
|
65
|
+
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic, optional: true }), (0, main_1.default)(config, integrationLogic));
|
|
66
66
|
app.get('/api/subscription-info', json_response_1.default, (0, crowdin_client_1.default)({
|
|
67
67
|
config,
|
|
68
68
|
optional: false,
|
|
@@ -98,7 +98,7 @@ function register({ config, app }) {
|
|
|
98
98
|
optional: false,
|
|
99
99
|
checkSubscriptionExpiration: true,
|
|
100
100
|
moduleKey: integrationLogic.key,
|
|
101
|
-
}), (0, integration_credentials_1.default)(config, integrationLogic), (0, settings_save_1.default)(config, integrationLogic));
|
|
101
|
+
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, settings_save_1.default)(config, integrationLogic));
|
|
102
102
|
app.post('/api/login', (0, crowdin_client_1.default)({
|
|
103
103
|
config,
|
|
104
104
|
optional: false,
|
|
@@ -110,13 +110,13 @@ function register({ config, app }) {
|
|
|
110
110
|
optional: false,
|
|
111
111
|
checkSubscriptionExpiration: false,
|
|
112
112
|
moduleKey: integrationLogic.key,
|
|
113
|
-
}), (0, integration_credentials_1.default)(config, integrationLogic), (0, integration_logout_1.default)(config, integrationLogic));
|
|
113
|
+
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic, isLogout: true }), (0, integration_logout_1.default)(config, integrationLogic));
|
|
114
114
|
app.get('/api/crowdin/files', json_response_1.default, (0, crowdin_client_1.default)({
|
|
115
115
|
config,
|
|
116
116
|
optional: false,
|
|
117
117
|
checkSubscriptionExpiration: true,
|
|
118
118
|
moduleKey: integrationLogic.key,
|
|
119
|
-
}), (0, integration_credentials_1.default)(config, integrationLogic), (0, crowdin_files_1.default)(config, integrationLogic));
|
|
119
|
+
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, crowdin_files_1.default)(config, integrationLogic));
|
|
120
120
|
app.get('/api/crowdin/project', json_response_1.default, (0, crowdin_client_1.default)({
|
|
121
121
|
config,
|
|
122
122
|
optional: false,
|
|
@@ -134,37 +134,37 @@ function register({ config, app }) {
|
|
|
134
134
|
optional: false,
|
|
135
135
|
checkSubscriptionExpiration: true,
|
|
136
136
|
moduleKey: integrationLogic.key,
|
|
137
|
-
}), (0, integration_credentials_1.default)(config, integrationLogic), (0, integration_data_1.default)(integrationLogic));
|
|
137
|
+
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, integration_data_1.default)(integrationLogic));
|
|
138
138
|
app.post('/api/crowdin/update', json_response_1.default, (0, crowdin_client_1.default)({
|
|
139
139
|
config,
|
|
140
140
|
optional: false,
|
|
141
141
|
checkSubscriptionExpiration: true,
|
|
142
142
|
moduleKey: integrationLogic.key,
|
|
143
|
-
}), (0, integration_credentials_1.default)(config, integrationLogic), (0, crowdin_update_1.default)(config, integrationLogic));
|
|
143
|
+
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, crowdin_update_1.default)(config, integrationLogic));
|
|
144
144
|
app.post('/api/crowdin/files-target-languages', json_response_1.default, (0, crowdin_client_1.default)({
|
|
145
145
|
config,
|
|
146
146
|
optional: false,
|
|
147
147
|
checkSubscriptionExpiration: true,
|
|
148
148
|
moduleKey: integrationLogic.key,
|
|
149
|
-
}), (0, integration_credentials_1.default)(config, integrationLogic), (0, crowdin_files_target_languages_1.default)(config, integrationLogic));
|
|
149
|
+
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, crowdin_files_target_languages_1.default)(config, integrationLogic));
|
|
150
150
|
app.post('/api/integration/update', json_response_1.default, (0, crowdin_client_1.default)({
|
|
151
151
|
config,
|
|
152
152
|
optional: false,
|
|
153
153
|
checkSubscriptionExpiration: true,
|
|
154
154
|
moduleKey: integrationLogic.key,
|
|
155
|
-
}), (0, integration_credentials_1.default)(config, integrationLogic), (0, integration_update_1.default)(config, integrationLogic));
|
|
155
|
+
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, integration_update_1.default)(config, integrationLogic));
|
|
156
156
|
app.get('/api/sync-settings/:provider', json_response_1.default, (0, crowdin_client_1.default)({
|
|
157
157
|
config,
|
|
158
158
|
optional: false,
|
|
159
159
|
checkSubscriptionExpiration: true,
|
|
160
160
|
moduleKey: integrationLogic.key,
|
|
161
|
-
}), (0, integration_credentials_1.default)(config, integrationLogic), (0, sync_settings_1.default)());
|
|
161
|
+
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, sync_settings_1.default)());
|
|
162
162
|
app.post('/api/sync-settings', json_response_1.default, (0, crowdin_client_1.default)({
|
|
163
163
|
config,
|
|
164
164
|
optional: false,
|
|
165
165
|
checkSubscriptionExpiration: true,
|
|
166
166
|
moduleKey: integrationLogic.key,
|
|
167
|
-
}), (0, integration_credentials_1.default)(config, integrationLogic), (0, sync_settings_save_1.default)(config, integrationLogic));
|
|
167
|
+
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, sync_settings_save_1.default)(config, integrationLogic));
|
|
168
168
|
if (integrationLogic.oauthLogin) {
|
|
169
169
|
app.get((0, defaults_1.getOauthRoute)(integrationLogic), (0, oauth_login_1.default)(config, integrationLogic));
|
|
170
170
|
app.post('/api/oauth-url', json_response_1.default, (0, crowdin_client_1.default)({
|
|
@@ -226,17 +226,17 @@ function register({ config, app }) {
|
|
|
226
226
|
optional: false,
|
|
227
227
|
checkSubscriptionExpiration: true,
|
|
228
228
|
moduleKey: integrationLogic.key,
|
|
229
|
-
}), (0, integration_credentials_1.default)(config, integrationLogic), (0, user_errors_1.default)());
|
|
229
|
+
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, user_errors_1.default)());
|
|
230
230
|
app.get('/api/users', json_response_1.default, (0, crowdin_client_1.default)({
|
|
231
231
|
config,
|
|
232
232
|
optional: false,
|
|
233
233
|
checkSubscriptionExpiration: true,
|
|
234
234
|
moduleKey: integrationLogic.key,
|
|
235
|
-
}), (0, integration_credentials_1.default)(config, integrationLogic), (0, users_1.default)());
|
|
235
|
+
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, users_1.default)());
|
|
236
236
|
app.post('/api/invite-users', json_response_1.default, (0, crowdin_client_1.default)({
|
|
237
237
|
config,
|
|
238
238
|
optional: false,
|
|
239
239
|
checkSubscriptionExpiration: true,
|
|
240
240
|
moduleKey: integrationLogic.key,
|
|
241
|
-
}), (0, integration_credentials_1.default)(config, integrationLogic), (0, invite_users_1.default)());
|
|
241
|
+
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, invite_users_1.default)());
|
|
242
242
|
}
|
|
@@ -533,6 +533,7 @@ export interface UpdateTargetLanguagesRequest {
|
|
|
533
533
|
export interface IntegrationRequest extends CrowdinClientRequest {
|
|
534
534
|
integrationCredentials: any;
|
|
535
535
|
integrationSettings?: any;
|
|
536
|
+
canForceIntegrationLogout?: boolean;
|
|
536
537
|
}
|
|
537
538
|
export interface CronJob {
|
|
538
539
|
task: (options: {
|
|
@@ -166,10 +166,18 @@ function filesCron(_a) {
|
|
|
166
166
|
const syncSettingsList = yield (0, storage_1.getStorage)().getSyncSettingsBySchedule('schedule', period);
|
|
167
167
|
const crowdinSyncSettings = syncSettingsList.filter((syncSettings) => syncSettings.provider === types_1.Provider.CROWDIN);
|
|
168
168
|
const integrationSyncSettings = syncSettingsList.filter((syncSettings) => syncSettings.provider === types_1.Provider.INTEGRATION);
|
|
169
|
-
yield Promise.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
169
|
+
const crowdinResults = yield Promise.allSettled(crowdinSyncSettings.map((syncSettings) => processSyncSettings({ config, integration, period, syncSettings })));
|
|
170
|
+
crowdinResults.forEach((result) => {
|
|
171
|
+
if (result.status === 'rejected') {
|
|
172
|
+
(0, logger_1.logError)(result.reason);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
const integrationResults = yield Promise.allSettled(integrationSyncSettings.map((syncSettings) => processSyncSettings({ config, integration, period, syncSettings })));
|
|
176
|
+
integrationResults.forEach((result) => {
|
|
177
|
+
if (result.status === 'rejected') {
|
|
178
|
+
(0, logger_1.logError)(result.reason);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
173
181
|
(0, logger_1.log)(`Files cron job with period [${period}] completed`);
|
|
174
182
|
});
|
|
175
183
|
}
|
|
@@ -108,7 +108,8 @@ function registerWebhooks(_a) {
|
|
|
108
108
|
yield integration.webhooks.crowdinWebhooks({ client, projectId, available: isWebhookSync, settings });
|
|
109
109
|
}
|
|
110
110
|
else {
|
|
111
|
-
const
|
|
111
|
+
const { userId } = crowdinAppFunctions.parseCrowdinId(crowdinContext.clientId);
|
|
112
|
+
const webhookName = `${config.name} application hook ${userId}`;
|
|
112
113
|
const webhookUrl = makeCrowdinWebhookUrl({
|
|
113
114
|
config,
|
|
114
115
|
integration,
|
|
@@ -166,7 +167,8 @@ function unregisterWebhooks(_a) {
|
|
|
166
167
|
});
|
|
167
168
|
}
|
|
168
169
|
else {
|
|
169
|
-
const
|
|
170
|
+
const { userId } = crowdinAppFunctions.parseCrowdinId(crowdinContext.clientId);
|
|
171
|
+
const webhookName = `${config.name} application hook ${userId}`;
|
|
170
172
|
const webhook = yield getCrowdinProjectWebhook({
|
|
171
173
|
client,
|
|
172
174
|
projectId: crowdinContext.jwtPayload.context.project_id,
|
|
@@ -212,7 +214,8 @@ function createPayload(events) {
|
|
|
212
214
|
}
|
|
213
215
|
function registerCrowdinWebhook(_a) {
|
|
214
216
|
return __awaiter(this, arguments, void 0, function* ({ client, config, crowdinContext, events, url, }) {
|
|
215
|
-
const
|
|
217
|
+
const { userId } = crowdinAppFunctions.parseCrowdinId(crowdinContext.clientId);
|
|
218
|
+
const name = `${config.name} application hook ${userId}`;
|
|
216
219
|
const payload = createPayload(events);
|
|
217
220
|
yield client.webhooksApi.addWebhook(crowdinContext.jwtPayload.context.project_id, {
|
|
218
221
|
name,
|
package/out/modules/manifest.js
CHANGED
|
@@ -387,7 +387,9 @@ function handle(config) {
|
|
|
387
387
|
workflowStep.key = config.identifier + '-' + (0, util_3.getWorkflowStepKey)(workflowStep);
|
|
388
388
|
}
|
|
389
389
|
const uiModule = ((_b = workflowStep === null || workflowStep === void 0 ? void 0 : workflowStep.settingsUiModule) === null || _b === void 0 ? void 0 : _b.formSchema) || ((_c = workflowStep === null || workflowStep === void 0 ? void 0 : workflowStep.settingsUiModule) === null || _c === void 0 ? void 0 : _c.fileName);
|
|
390
|
-
modules['workflow-step-type'].push(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ key: workflowStep.key, name: workflowStep.name || config.name }, (
|
|
390
|
+
modules['workflow-step-type'].push(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ key: workflowStep.key, name: workflowStep.name || config.name }, (workflowStep.imageUrl || workflowStep.imagePath
|
|
391
|
+
? { logo: (0, util_1.getLogoUrl)(config, workflowStep, `-${workflowStep.key}`) }
|
|
392
|
+
: {})), { description: workflowStep.description || config.description, boundaries: workflowStep.boundaries }), (workflowStep.editorMode ? { editorMode: workflowStep.editorMode } : {})), { updateSettingsUrl: (0, util_3.getWorkflowStepUrl)('/workflow-step/settings', workflowStep), deleteSettingsUrl: (0, util_3.getWorkflowStepUrl)('/workflow-step/delete', workflowStep) }), (uiModule ? { url: (0, util_3.getWorkflowStepUrl)('/workflow-step', workflowStep) } : {})));
|
|
391
393
|
}
|
|
392
394
|
}
|
|
393
395
|
if (config.automationAction) {
|
|
@@ -41,7 +41,7 @@ function register({ config, app }) {
|
|
|
41
41
|
checkSubscriptionExpiration: false,
|
|
42
42
|
}), (0, delete_step_1.default)(workflowStep));
|
|
43
43
|
// END TEMPORARY CODE
|
|
44
|
-
if (workflowStep.imagePath) {
|
|
44
|
+
if (workflowStep.imagePath || workflowStep.imageUrl) {
|
|
45
45
|
app.use(`/logo-${workflowStep.key}`, (0, util_2.serveLogo)(config, workflowStep));
|
|
46
46
|
}
|
|
47
47
|
if (workflowStep.settingsUiModule) {
|
|
@@ -518,7 +518,7 @@
|
|
|
518
518
|
|
|
519
519
|
var clientExports = requireClient();
|
|
520
520
|
|
|
521
|
-
const ErrorPage = ({ message, name, owners, hideActions }) => {
|
|
521
|
+
const ErrorPage = ({ message, name, owners, hideActions, allowLogout }) => {
|
|
522
522
|
function integrationLogout() {
|
|
523
523
|
checkOrigin()
|
|
524
524
|
.then((queryParams) => fetch(`api/logout${queryParams}`, { method: 'POST' }))
|
|
@@ -532,7 +532,7 @@
|
|
|
532
532
|
AP.redirect(`${context.organization_id ? '/u' : ''}/messages/create/${userId}`);
|
|
533
533
|
});
|
|
534
534
|
}
|
|
535
|
-
return (jsxRuntimeExports.jsx("div", { className: "i_w", children: jsxRuntimeExports.jsx("div", { className: "error-page", children: jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsxs("div", { className: "error-page-message", children: [jsxRuntimeExports.jsx("crowdin-h3", { children: message }), owners && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("crowdin-p", { children: "This integration allows only one connection per project to ensure consistent configuration and prevent file import or synchronization issues." }), owners.length > 1 ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("crowdin-p", { class: "mt-2", children: "Managed by:" }), jsxRuntimeExports.jsx("ul", { children: owners.map((owner) => (jsxRuntimeExports.jsx("li", { children: jsxRuntimeExports.jsx("crowdin-a", { href: "#", onClick: () => contactUser(owner.id), children: owner.name }) }))) }), jsxRuntimeExports.jsx("crowdin-p", { class: "mt-2", children: "To request access, please contact one of the project members listed above." })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("crowdin-p", { class: "mt-2", children: ["Managed by:", ' ', jsxRuntimeExports.jsx("crowdin-a", { href: "#", onClick: () => contactUser(owners[0].id), children: owners[0].name })] }), jsxRuntimeExports.jsx("crowdin-p", { class: "mt-2", children: "To request access, please contact the project member listed above." })] }))] }))] }), !hideActions && (jsxRuntimeExports.jsxs("div", { className: "error-page-action", children: [jsxRuntimeExports.jsx("crowdin-button", { outlined: true, onClick: () => integrationLogout(), children: "Log out" }), jsxRuntimeExports.jsxs("span", { children: [' ', "or", ' ', jsxRuntimeExports.jsx("crowdin-a", { href: "https://crowdin.com/contacts", target: "_blank", children: "contact us" }), ' ', "for help"] })] }))] }) }) }));
|
|
535
|
+
return (jsxRuntimeExports.jsx("div", { className: "i_w", children: jsxRuntimeExports.jsx("div", { className: "error-page", children: jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsxs("div", { className: "error-page-message", children: [jsxRuntimeExports.jsx("crowdin-h3", { children: message }), owners && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("crowdin-p", { children: "This integration allows only one connection per project to ensure consistent configuration and prevent file import or synchronization issues." }), owners.length > 1 ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("crowdin-p", { class: "mt-2", children: "Managed by:" }), jsxRuntimeExports.jsx("ul", { children: owners.map((owner) => (jsxRuntimeExports.jsx("li", { children: jsxRuntimeExports.jsx("crowdin-a", { href: "#", onClick: () => contactUser(owner.id), children: owner.name }) }))) }), jsxRuntimeExports.jsx("crowdin-p", { class: "mt-2", children: "To request access, please contact one of the project members listed above." })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("crowdin-p", { class: "mt-2", children: ["Managed by:", ' ', jsxRuntimeExports.jsx("crowdin-a", { href: "#", onClick: () => contactUser(owners[0].id), children: owners[0].name })] }), jsxRuntimeExports.jsx("crowdin-p", { class: "mt-2", children: "To request access, please contact the project member listed above." })] }))] }))] }), allowLogout && hideActions ? (jsxRuntimeExports.jsxs("crowdin-card", { "light-filled": true, children: [jsxRuntimeExports.jsx("crowdin-alert", { type: "warning", margin: true, message: "Deleting the integration will disconnect it and reset its settings for this project." }), jsxRuntimeExports.jsx("crowdin-button", { outlined: true, onClick: () => integrationLogout(), children: "Delete Integration" })] })) : (!hideActions && (jsxRuntimeExports.jsxs("div", { className: "error-page-action", children: [jsxRuntimeExports.jsx("crowdin-button", { outlined: true, onClick: () => integrationLogout(), children: "Log out" }), jsxRuntimeExports.jsxs("span", { children: [' ', "or", ' ', jsxRuntimeExports.jsx("crowdin-a", { href: "https://crowdin.com/contacts", target: "_blank", children: "contact us" }), ' ', "for help"] })] })))] }) }) }));
|
|
536
536
|
};
|
|
537
537
|
|
|
538
538
|
clientExports.createRoot(document.getElementById('root')).render(jsxRuntimeExports.jsx(ErrorPage, { ...window.__PAGE_PROPS__ }));
|