@crowdin/app-project-module 1.5.4 → 1.6.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/middlewares/crowdin-client.d.ts +2 -1
- package/out/middlewares/crowdin-client.js +25 -1
- package/out/middlewares/integration-access-denied.d.ts +22 -0
- package/out/middlewares/integration-access-denied.js +107 -0
- package/out/middlewares/integration-credentials.js +34 -135
- package/out/modules/integration/handlers/job-info-deprecated.js +10 -2
- package/out/modules/integration/handlers/sync-settings-save.js +1 -1
- package/out/modules/integration/index.js +22 -0
- package/out/modules/integration/util/files.js +4 -1
- package/out/modules/integration/util/snapshot.d.ts +4 -2
- package/out/modules/integration/util/snapshot.js +17 -7
- package/out/util/connection.d.ts +8 -0
- package/out/util/connection.js +33 -0
- package/package.json +1 -1
|
@@ -15,10 +15,11 @@ export declare function prepareCrowdinRequest({ jwtToken, config, optional, chec
|
|
|
15
15
|
client?: Crowdin;
|
|
16
16
|
subscriptionInfo?: SubscriptionInfo;
|
|
17
17
|
}>;
|
|
18
|
-
export default function handle({ config, optional, checkSubscriptionExpiration, moduleKey, }: {
|
|
18
|
+
export default function handle({ config, optional, checkSubscriptionExpiration, moduleKey, isIntegration, }: {
|
|
19
19
|
config: Config;
|
|
20
20
|
optional: boolean;
|
|
21
21
|
checkSubscriptionExpiration: boolean;
|
|
22
22
|
moduleKey?: string[] | string | undefined;
|
|
23
|
+
isIntegration?: boolean;
|
|
23
24
|
}): (req: import("express").Request | CrowdinClientRequest, res: Response, next: Function) => void;
|
|
24
25
|
export declare function getToken(req: CrowdinClientRequest): string | undefined;
|
|
@@ -17,6 +17,7 @@ const storage_1 = require("../storage");
|
|
|
17
17
|
const util_1 = require("../util");
|
|
18
18
|
const api_1 = require("../modules/api/api");
|
|
19
19
|
const connection_1 = require("../util/connection");
|
|
20
|
+
const integration_access_denied_1 = require("./integration-access-denied");
|
|
20
21
|
const logger_1 = require("../util/logger");
|
|
21
22
|
const subscription_1 = require("../util/subscription");
|
|
22
23
|
function prepareCrowdinRequest(_a) {
|
|
@@ -64,7 +65,7 @@ function prepareCrowdinRequest(_a) {
|
|
|
64
65
|
return { context, client, subscriptionInfo, logInfo, logError };
|
|
65
66
|
});
|
|
66
67
|
}
|
|
67
|
-
function handle({ config, optional = false, checkSubscriptionExpiration = true, moduleKey, }) {
|
|
68
|
+
function handle({ config, optional = false, checkSubscriptionExpiration = true, moduleKey, isIntegration = false, }) {
|
|
68
69
|
return (0, util_1.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
69
70
|
var _a, _b;
|
|
70
71
|
const jwtToken = getToken(req);
|
|
@@ -90,6 +91,29 @@ function handle({ config, optional = false, checkSubscriptionExpiration = true,
|
|
|
90
91
|
}
|
|
91
92
|
data.context = (0, api_1.updateCrowdinContext)(req, data.context);
|
|
92
93
|
}
|
|
94
|
+
if (isIntegration && data.client) {
|
|
95
|
+
const result = yield (0, connection_1.resolveIntegrationAccess)(data.context.clientId);
|
|
96
|
+
if (!result.integrationCredentials) {
|
|
97
|
+
const owners = yield (0, integration_access_denied_1.getIntegrationManagedBy)({
|
|
98
|
+
ownerIds: result.ownerIds,
|
|
99
|
+
crowdinApiClient: data.client,
|
|
100
|
+
clientId: data.context.clientId,
|
|
101
|
+
});
|
|
102
|
+
if (owners.length) {
|
|
103
|
+
data.logInfo('Access denied: no integration access for this project');
|
|
104
|
+
return (0, integration_access_denied_1.renderIntegrationAccessDenied)({
|
|
105
|
+
req,
|
|
106
|
+
res,
|
|
107
|
+
isApiCall: req.isApiCall,
|
|
108
|
+
owners,
|
|
109
|
+
debugLabel: 'crowdin-client',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
data.context.clientId = result.clientId;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
93
117
|
req.crowdinContext = data.context;
|
|
94
118
|
if (data.client) {
|
|
95
119
|
req.crowdinApiClient = data.client;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Crowdin from '@crowdin/crowdin-api-client';
|
|
2
|
+
import { Response } from 'express';
|
|
3
|
+
import { CrowdinClientRequest } from '../types';
|
|
4
|
+
import { IntegrationRequest } from '../modules/integration/types';
|
|
5
|
+
interface OwnerInfo {
|
|
6
|
+
name: string;
|
|
7
|
+
id: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function getIntegrationManagedBy({ ownerIds, crowdinApiClient, clientId, }: {
|
|
10
|
+
ownerIds: number[];
|
|
11
|
+
crowdinApiClient: Crowdin;
|
|
12
|
+
clientId: string;
|
|
13
|
+
}): Promise<OwnerInfo[]>;
|
|
14
|
+
export declare function renderIntegrationAccessDenied({ req, res, isApiCall, owners, debugLabel, allowLogout, }: {
|
|
15
|
+
req: IntegrationRequest | CrowdinClientRequest;
|
|
16
|
+
res: Response;
|
|
17
|
+
isApiCall?: boolean;
|
|
18
|
+
owners: OwnerInfo[];
|
|
19
|
+
debugLabel: string;
|
|
20
|
+
allowLogout?: boolean;
|
|
21
|
+
}): Response<any, Record<string, any>>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.getIntegrationManagedBy = getIntegrationManagedBy;
|
|
46
|
+
exports.renderIntegrationAccessDenied = renderIntegrationAccessDenied;
|
|
47
|
+
const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
|
|
48
|
+
const jsx_renderer_1 = require("../util/jsx-renderer");
|
|
49
|
+
const logger_1 = require("../util/logger");
|
|
50
|
+
function getIntegrationManagedBy(_a) {
|
|
51
|
+
return __awaiter(this, arguments, void 0, function* ({ ownerIds, crowdinApiClient, clientId, }) {
|
|
52
|
+
if (!ownerIds.length) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
const projectId = crowdinAppFunctions.getProjectId(clientId);
|
|
56
|
+
let owners = [];
|
|
57
|
+
try {
|
|
58
|
+
owners =
|
|
59
|
+
ownerIds.length > 1
|
|
60
|
+
? (yield crowdinApiClient.usersApi.listProjectMembers(projectId)).data.filter((member) => ownerIds.includes(member.data.id))
|
|
61
|
+
: [yield crowdinApiClient.usersApi.getProjectMemberPermissions(projectId, ownerIds[0])];
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
console.warn('Failed to get project members', e);
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
return owners.map((owner) => {
|
|
68
|
+
const ownerFullName = 'fullName' in owner.data
|
|
69
|
+
? owner.data.fullName
|
|
70
|
+
: `${owner.data.firstName || ''} ${owner.data.lastName || ''}`.trim();
|
|
71
|
+
return {
|
|
72
|
+
id: owner.data.id,
|
|
73
|
+
name: !!ownerFullName && owner.data.username !== ownerFullName
|
|
74
|
+
? `${ownerFullName} (${owner.data.username})`
|
|
75
|
+
: owner.data.username,
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function renderIntegrationAccessDenied({ req, res, isApiCall, owners, debugLabel, allowLogout = false, }) {
|
|
81
|
+
const errorOptions = {
|
|
82
|
+
code: 403,
|
|
83
|
+
message: 'Access denied',
|
|
84
|
+
owners: null,
|
|
85
|
+
hideActions: false,
|
|
86
|
+
allowLogout: false,
|
|
87
|
+
};
|
|
88
|
+
if (isApiCall) {
|
|
89
|
+
return res.status(errorOptions.code).json({
|
|
90
|
+
error: {
|
|
91
|
+
message: errorOptions.message,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (owners.length) {
|
|
96
|
+
errorOptions.message = 'Looks like you don’t have access';
|
|
97
|
+
errorOptions.hideActions = true;
|
|
98
|
+
errorOptions.owners = owners;
|
|
99
|
+
errorOptions.allowLogout = allowLogout;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
(0, logger_1.temporaryErrorDebug)(`Access denied: ${debugLabel}`, req);
|
|
103
|
+
}
|
|
104
|
+
const html = (0, jsx_renderer_1.renderJSXOnClient)({ name: 'error', props: errorOptions });
|
|
105
|
+
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
106
|
+
return res.send(html);
|
|
107
|
+
}
|
|
@@ -1,37 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -43,88 +10,57 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
43
10
|
};
|
|
44
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
12
|
exports.default = handle;
|
|
46
|
-
const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
|
|
47
13
|
const users_1 = require("../modules/integration/handlers/users");
|
|
48
14
|
const storage_1 = require("../storage");
|
|
49
15
|
const util_1 = require("../util");
|
|
50
16
|
const connection_1 = require("../util/connection");
|
|
51
|
-
const
|
|
52
|
-
const logger_1 = require("../util/logger");
|
|
17
|
+
const integration_access_denied_1 = require("./integration-access-denied");
|
|
53
18
|
function handle({ config, integration, optional = false, isLogout = false, }) {
|
|
54
19
|
return (0, util_1.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
55
|
-
let clientId = req.crowdinContext.clientId;
|
|
56
20
|
const isApiCall = req === null || req === void 0 ? void 0 : req.isApiCall;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
let integrationCredentials =
|
|
60
|
-
let
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (projectIntegrationCredentials.length) {
|
|
69
|
-
for (const credentials of projectIntegrationCredentials) {
|
|
70
|
-
ownerIds.push(crowdinAppFunctions.parseCrowdinId(credentials.id).userId);
|
|
71
|
-
if (checkUserAccessToIntegration(credentials, `${userId}`)) {
|
|
72
|
-
integrationCredentials = credentials;
|
|
73
|
-
clientId = credentials.id;
|
|
74
|
-
req.crowdinContext.clientId = clientId;
|
|
75
|
-
break;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
if (!integrationCredentials && isLogout && projectIntegrationCredentials.length) {
|
|
80
|
-
const canForceLogout = yield isCrowdinProjectManager({
|
|
21
|
+
req.logInfo(`Loading integration credentials for client ${req.crowdinContext.clientId}`);
|
|
22
|
+
const { integrationCredentials: resolvedIntegrationCredentials, projectIntegrationCredentials, projectId, clientId: resolvedClientId, ownerIds, } = yield (0, connection_1.resolveIntegrationAccess)(req.crowdinContext.clientId);
|
|
23
|
+
let integrationCredentials = resolvedIntegrationCredentials;
|
|
24
|
+
let clientId = resolvedClientId;
|
|
25
|
+
if (integrationCredentials) {
|
|
26
|
+
req.crowdinContext.clientId = clientId;
|
|
27
|
+
}
|
|
28
|
+
let canForceLogout = null;
|
|
29
|
+
const getCanForceLogout = () => __awaiter(this, void 0, void 0, function* () {
|
|
30
|
+
if (canForceLogout === null) {
|
|
31
|
+
canForceLogout = yield isCrowdinProjectManager({
|
|
81
32
|
req,
|
|
82
33
|
projectId,
|
|
83
34
|
memberId: req.crowdinContext.jwtPayload.context.user_id,
|
|
84
35
|
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
36
|
+
}
|
|
37
|
+
return canForceLogout;
|
|
38
|
+
});
|
|
39
|
+
if (!integrationCredentials && isLogout && projectIntegrationCredentials.length) {
|
|
40
|
+
if (yield getCanForceLogout()) {
|
|
41
|
+
integrationCredentials = projectIntegrationCredentials[0];
|
|
42
|
+
clientId = integrationCredentials.id;
|
|
43
|
+
req.crowdinContext.clientId = clientId;
|
|
44
|
+
req.canForceIntegrationLogout = true;
|
|
91
45
|
}
|
|
92
46
|
}
|
|
93
47
|
if (!integrationCredentials) {
|
|
94
|
-
const owners = yield
|
|
48
|
+
const owners = yield (0, integration_access_denied_1.getIntegrationManagedBy)({
|
|
49
|
+
ownerIds,
|
|
50
|
+
crowdinApiClient: req.crowdinApiClient,
|
|
51
|
+
clientId: req.crowdinContext.clientId,
|
|
52
|
+
});
|
|
95
53
|
if (optional && !owners.length) {
|
|
96
54
|
return next();
|
|
97
55
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return res.status(errorOptions.code).json({
|
|
107
|
-
error: {
|
|
108
|
-
message: errorOptions.message,
|
|
109
|
-
},
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
if (owners) {
|
|
113
|
-
errorOptions.message = 'Looks like you don’t have access';
|
|
114
|
-
errorOptions.hideActions = true;
|
|
115
|
-
errorOptions.owners = owners;
|
|
116
|
-
errorOptions.allowLogout = yield isCrowdinProjectManager({
|
|
117
|
-
req,
|
|
118
|
-
projectId,
|
|
119
|
-
memberId: req.crowdinContext.jwtPayload.context.user_id,
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
(0, logger_1.temporaryErrorDebug)('Access denied: integration-credentials', req);
|
|
124
|
-
}
|
|
125
|
-
const html = (0, jsx_renderer_1.renderJSXOnClient)({ name: 'error', props: errorOptions });
|
|
126
|
-
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
127
|
-
return res.send(html);
|
|
56
|
+
return (0, integration_access_denied_1.renderIntegrationAccessDenied)({
|
|
57
|
+
req,
|
|
58
|
+
res,
|
|
59
|
+
isApiCall,
|
|
60
|
+
owners,
|
|
61
|
+
debugLabel: 'integration-credentials',
|
|
62
|
+
allowLogout: yield getCanForceLogout(),
|
|
63
|
+
});
|
|
128
64
|
}
|
|
129
65
|
try {
|
|
130
66
|
req.integrationCredentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
|
|
@@ -158,43 +94,6 @@ function handle({ config, integration, optional = false, isLogout = false, }) {
|
|
|
158
94
|
next();
|
|
159
95
|
}));
|
|
160
96
|
}
|
|
161
|
-
function checkUserAccessToIntegration(integrationCredentials, userId) {
|
|
162
|
-
if (integrationCredentials === null || integrationCredentials === void 0 ? void 0 : integrationCredentials.managers) {
|
|
163
|
-
const managers = JSON.parse(integrationCredentials.managers);
|
|
164
|
-
return (managers || []).includes(userId);
|
|
165
|
-
}
|
|
166
|
-
return false;
|
|
167
|
-
}
|
|
168
|
-
function getIntegrationManagedBy(ownerIds, req) {
|
|
169
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
170
|
-
if (!ownerIds.length) {
|
|
171
|
-
return [];
|
|
172
|
-
}
|
|
173
|
-
const projectId = crowdinAppFunctions.getProjectId(req.crowdinContext.clientId);
|
|
174
|
-
let owners = [];
|
|
175
|
-
try {
|
|
176
|
-
owners =
|
|
177
|
-
ownerIds.length > 1
|
|
178
|
-
? (yield req.crowdinApiClient.usersApi.listProjectMembers(projectId)).data.filter((member) => ownerIds.includes(member.data.id))
|
|
179
|
-
: [yield req.crowdinApiClient.usersApi.getProjectMemberPermissions(projectId, ownerIds[0])];
|
|
180
|
-
}
|
|
181
|
-
catch (e) {
|
|
182
|
-
console.warn('Failed to get project members', e);
|
|
183
|
-
return [];
|
|
184
|
-
}
|
|
185
|
-
return owners.map((owner) => {
|
|
186
|
-
const ownerFullName = 'fullName' in owner.data
|
|
187
|
-
? owner.data.fullName
|
|
188
|
-
: `${owner.data.firstName || ''} ${owner.data.lastName || ''}`.trim();
|
|
189
|
-
return {
|
|
190
|
-
id: owner.data.id,
|
|
191
|
-
name: !!ownerFullName && owner.data.username !== ownerFullName
|
|
192
|
-
? `${ownerFullName} (${owner.data.username})`
|
|
193
|
-
: owner.data.username,
|
|
194
|
-
};
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
97
|
function isCrowdinProjectManager(_a) {
|
|
199
98
|
return __awaiter(this, arguments, void 0, function* ({ req, projectId, memberId, }) {
|
|
200
99
|
try {
|
|
@@ -37,7 +37,7 @@ function getHumanETA(ms) {
|
|
|
37
37
|
}
|
|
38
38
|
function handle(config) {
|
|
39
39
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
40
|
-
var _a, _b;
|
|
40
|
+
var _a, _b, _c;
|
|
41
41
|
const isApi = req.isApiCall;
|
|
42
42
|
const id = ((_a = req.query) === null || _a === void 0 ? void 0 : _a.jobId) || ((_b = req.body) === null || _b === void 0 ? void 0 : _b.jobId);
|
|
43
43
|
if (!id) {
|
|
@@ -85,7 +85,15 @@ function handle(config) {
|
|
|
85
85
|
res.send([filteredJob]);
|
|
86
86
|
return;
|
|
87
87
|
}
|
|
88
|
-
|
|
88
|
+
const jobTimestamp = (_c = job === null || job === void 0 ? void 0 : job.updatedAt) !== null && _c !== void 0 ? _c : job === null || job === void 0 ? void 0 : job.createdAt;
|
|
89
|
+
const isJobStuck = !!job && !!jobTimestamp && Date.now() - jobTimestamp >= MINUTES * 60 * 1000;
|
|
90
|
+
if (isJobStuck) {
|
|
91
|
+
const settingsJobTypes = [types_1.JobType.CROWDIN_SYNC_SETTINGS_SAVE, types_1.JobType.INTEGRATION_SYNC_SETTINGS_SAVE];
|
|
92
|
+
if (settingsJobTypes.includes(job.type)) {
|
|
93
|
+
req.logInfo(`Canceling stuck settings job '${job.id}' after no updates for more than '${MINUTES}' minutes.`);
|
|
94
|
+
yield (0, storage_1.getStorage)().updateJob({ id: job.id, status: types_1.JobStatus.CANCELED });
|
|
95
|
+
return res.send(Object.assign(Object.assign({}, job), { status: types_1.JobStatus.CANCELED }));
|
|
96
|
+
}
|
|
89
97
|
const context = req.crowdinContext;
|
|
90
98
|
const projectId = context.jwtPayload.context.project_id;
|
|
91
99
|
const integration = config.projectIntegration;
|
|
@@ -85,7 +85,7 @@ function handle(config, integration) {
|
|
|
85
85
|
((_a = integration.syncNewElements) === null || _a === void 0 ? void 0 : _a[provider]) &&
|
|
86
86
|
(settings[`new-${provider}-files`] || hasSyncedFolders);
|
|
87
87
|
if (needsSnapshot) {
|
|
88
|
-
yield (0, snapshot_1.createOrUpdateFileSnapshot)(config, integration, req, provider);
|
|
88
|
+
yield (0, snapshot_1.createOrUpdateFileSnapshot)(config, integration, req, provider, job);
|
|
89
89
|
}
|
|
90
90
|
}),
|
|
91
91
|
});
|
|
@@ -68,102 +68,119 @@ function register({ config, app }) {
|
|
|
68
68
|
optional: false,
|
|
69
69
|
checkSubscriptionExpiration: true,
|
|
70
70
|
moduleKey: integrationLogic.key,
|
|
71
|
+
isIntegration: true,
|
|
71
72
|
}), (0, subscription_info_1.default)(config));
|
|
72
73
|
app.get('/api/all-jobs', json_response_1.default, (0, crowdin_client_1.default)({
|
|
73
74
|
config,
|
|
74
75
|
optional: false,
|
|
75
76
|
checkSubscriptionExpiration: true,
|
|
76
77
|
moduleKey: integrationLogic.key,
|
|
78
|
+
isIntegration: true,
|
|
77
79
|
}), (0, job_list_1.default)());
|
|
78
80
|
app.get('/api/job-info', json_response_1.default, (0, crowdin_client_1.default)({
|
|
79
81
|
config,
|
|
80
82
|
optional: false,
|
|
81
83
|
checkSubscriptionExpiration: true,
|
|
82
84
|
moduleKey: integrationLogic.key,
|
|
85
|
+
isIntegration: true,
|
|
83
86
|
}), (0, job_info_1.default)());
|
|
84
87
|
app.get('/api/jobs', json_response_1.default, (0, crowdin_client_1.default)({
|
|
85
88
|
config,
|
|
86
89
|
optional: false,
|
|
87
90
|
checkSubscriptionExpiration: true,
|
|
88
91
|
moduleKey: integrationLogic.key,
|
|
92
|
+
isIntegration: true,
|
|
89
93
|
}), (0, job_info_deprecated_1.default)(config));
|
|
90
94
|
app.delete('/api/jobs', json_response_1.default, (0, crowdin_client_1.default)({
|
|
91
95
|
config,
|
|
92
96
|
optional: false,
|
|
93
97
|
checkSubscriptionExpiration: true,
|
|
94
98
|
moduleKey: integrationLogic.key,
|
|
99
|
+
isIntegration: true,
|
|
95
100
|
}), (0, job_cancel_1.default)());
|
|
96
101
|
app.post('/api/settings', (0, crowdin_client_1.default)({
|
|
97
102
|
config,
|
|
98
103
|
optional: false,
|
|
99
104
|
checkSubscriptionExpiration: true,
|
|
100
105
|
moduleKey: integrationLogic.key,
|
|
106
|
+
isIntegration: true,
|
|
101
107
|
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, settings_save_1.default)(config, integrationLogic));
|
|
102
108
|
app.post('/api/login', (0, crowdin_client_1.default)({
|
|
103
109
|
config,
|
|
104
110
|
optional: false,
|
|
105
111
|
checkSubscriptionExpiration: false,
|
|
106
112
|
moduleKey: integrationLogic.key,
|
|
113
|
+
isIntegration: true,
|
|
107
114
|
}), (0, integration_login_1.default)(config, integrationLogic));
|
|
108
115
|
app.post('/api/logout', (0, crowdin_client_1.default)({
|
|
109
116
|
config,
|
|
110
117
|
optional: false,
|
|
111
118
|
checkSubscriptionExpiration: false,
|
|
112
119
|
moduleKey: integrationLogic.key,
|
|
120
|
+
isIntegration: true,
|
|
113
121
|
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic, isLogout: true }), (0, integration_logout_1.default)(config, integrationLogic));
|
|
114
122
|
app.get('/api/crowdin/files', json_response_1.default, (0, crowdin_client_1.default)({
|
|
115
123
|
config,
|
|
116
124
|
optional: false,
|
|
117
125
|
checkSubscriptionExpiration: true,
|
|
118
126
|
moduleKey: integrationLogic.key,
|
|
127
|
+
isIntegration: true,
|
|
119
128
|
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, crowdin_files_1.default)(config, integrationLogic));
|
|
120
129
|
app.get('/api/crowdin/project', json_response_1.default, (0, crowdin_client_1.default)({
|
|
121
130
|
config,
|
|
122
131
|
optional: false,
|
|
123
132
|
checkSubscriptionExpiration: true,
|
|
124
133
|
moduleKey: integrationLogic.key,
|
|
134
|
+
isIntegration: true,
|
|
125
135
|
}), (0, crowdin_project_1.default)());
|
|
126
136
|
app.get('/api/crowdin/file-progress/:fileId', (0, crowdin_client_1.default)({
|
|
127
137
|
config,
|
|
128
138
|
optional: false,
|
|
129
139
|
checkSubscriptionExpiration: true,
|
|
130
140
|
moduleKey: integrationLogic.key,
|
|
141
|
+
isIntegration: true,
|
|
131
142
|
}), (0, crowdin_file_progress_1.default)(integrationLogic));
|
|
132
143
|
app.get('/api/integration/data', json_response_1.default, (0, crowdin_client_1.default)({
|
|
133
144
|
config,
|
|
134
145
|
optional: false,
|
|
135
146
|
checkSubscriptionExpiration: true,
|
|
136
147
|
moduleKey: integrationLogic.key,
|
|
148
|
+
isIntegration: true,
|
|
137
149
|
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, integration_data_1.default)(integrationLogic));
|
|
138
150
|
app.post('/api/crowdin/update', json_response_1.default, (0, crowdin_client_1.default)({
|
|
139
151
|
config,
|
|
140
152
|
optional: false,
|
|
141
153
|
checkSubscriptionExpiration: true,
|
|
142
154
|
moduleKey: integrationLogic.key,
|
|
155
|
+
isIntegration: true,
|
|
143
156
|
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, crowdin_update_1.default)(config, integrationLogic));
|
|
144
157
|
app.post('/api/crowdin/files-target-languages', json_response_1.default, (0, crowdin_client_1.default)({
|
|
145
158
|
config,
|
|
146
159
|
optional: false,
|
|
147
160
|
checkSubscriptionExpiration: true,
|
|
148
161
|
moduleKey: integrationLogic.key,
|
|
162
|
+
isIntegration: true,
|
|
149
163
|
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, crowdin_files_target_languages_1.default)(config, integrationLogic));
|
|
150
164
|
app.post('/api/integration/update', json_response_1.default, (0, crowdin_client_1.default)({
|
|
151
165
|
config,
|
|
152
166
|
optional: false,
|
|
153
167
|
checkSubscriptionExpiration: true,
|
|
154
168
|
moduleKey: integrationLogic.key,
|
|
169
|
+
isIntegration: true,
|
|
155
170
|
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, integration_update_1.default)(config, integrationLogic));
|
|
156
171
|
app.get('/api/sync-settings/:provider', json_response_1.default, (0, crowdin_client_1.default)({
|
|
157
172
|
config,
|
|
158
173
|
optional: false,
|
|
159
174
|
checkSubscriptionExpiration: true,
|
|
160
175
|
moduleKey: integrationLogic.key,
|
|
176
|
+
isIntegration: true,
|
|
161
177
|
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, sync_settings_1.default)());
|
|
162
178
|
app.post('/api/sync-settings', json_response_1.default, (0, crowdin_client_1.default)({
|
|
163
179
|
config,
|
|
164
180
|
optional: false,
|
|
165
181
|
checkSubscriptionExpiration: true,
|
|
166
182
|
moduleKey: integrationLogic.key,
|
|
183
|
+
isIntegration: true,
|
|
167
184
|
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, sync_settings_save_1.default)(config, integrationLogic));
|
|
168
185
|
if (integrationLogic.oauthLogin) {
|
|
169
186
|
app.get((0, defaults_1.getOauthRoute)(integrationLogic), (0, oauth_login_1.default)(config, integrationLogic));
|
|
@@ -172,6 +189,7 @@ function register({ config, app }) {
|
|
|
172
189
|
optional: false,
|
|
173
190
|
checkSubscriptionExpiration: false,
|
|
174
191
|
moduleKey: integrationLogic.key,
|
|
192
|
+
isIntegration: true,
|
|
175
193
|
}), (0, oauth_url_1.default)(config, integrationLogic));
|
|
176
194
|
if (integrationLogic.oauthLogin.mode === 'polling') {
|
|
177
195
|
app.post('/api/oauth-polling', json_response_1.default, (0, crowdin_client_1.default)({
|
|
@@ -179,6 +197,7 @@ function register({ config, app }) {
|
|
|
179
197
|
optional: false,
|
|
180
198
|
checkSubscriptionExpiration: false,
|
|
181
199
|
moduleKey: integrationLogic.key,
|
|
200
|
+
isIntegration: true,
|
|
182
201
|
}), (0, oauth_polling_1.default)(config, integrationLogic));
|
|
183
202
|
}
|
|
184
203
|
}
|
|
@@ -226,17 +245,20 @@ function register({ config, app }) {
|
|
|
226
245
|
optional: false,
|
|
227
246
|
checkSubscriptionExpiration: true,
|
|
228
247
|
moduleKey: integrationLogic.key,
|
|
248
|
+
isIntegration: true,
|
|
229
249
|
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, user_errors_1.default)());
|
|
230
250
|
app.get('/api/users', json_response_1.default, (0, crowdin_client_1.default)({
|
|
231
251
|
config,
|
|
232
252
|
optional: false,
|
|
233
253
|
checkSubscriptionExpiration: true,
|
|
234
254
|
moduleKey: integrationLogic.key,
|
|
255
|
+
isIntegration: true,
|
|
235
256
|
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, users_1.default)());
|
|
236
257
|
app.post('/api/invite-users', json_response_1.default, (0, crowdin_client_1.default)({
|
|
237
258
|
config,
|
|
238
259
|
optional: false,
|
|
239
260
|
checkSubscriptionExpiration: true,
|
|
240
261
|
moduleKey: integrationLogic.key,
|
|
262
|
+
isIntegration: true,
|
|
241
263
|
}), (0, integration_credentials_1.default)({ config, integration: integrationLogic }), (0, invite_users_1.default)());
|
|
242
264
|
}
|
|
@@ -65,7 +65,7 @@ function expandFilesTree(nodes, req, integration, job) {
|
|
|
65
65
|
}
|
|
66
66
|
const files = nodes.filter((file) => file.nodeType === undefined || file.nodeType === '1');
|
|
67
67
|
const folders = nodes.filter((folder) => folder.nodeType === '0' && !nodes.find((node) => node.parentId === folder.id));
|
|
68
|
-
for (const { id } of folders) {
|
|
68
|
+
for (const { id, name } of folders) {
|
|
69
69
|
let integrationData = [];
|
|
70
70
|
try {
|
|
71
71
|
integrationData = yield integration.getIntegrationFiles({
|
|
@@ -75,6 +75,9 @@ function expandFilesTree(nodes, req, integration, job) {
|
|
|
75
75
|
settings: req.integrationSettings,
|
|
76
76
|
parentId: id,
|
|
77
77
|
});
|
|
78
|
+
if (job) {
|
|
79
|
+
yield job.update({ info: `Loading files from '${name}'` });
|
|
80
|
+
}
|
|
78
81
|
}
|
|
79
82
|
catch (e) {
|
|
80
83
|
if (job) {
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import Crowdin from '@crowdin/crowdin-api-client';
|
|
2
2
|
import { Config } from '../../../types';
|
|
3
3
|
import { IntegrationLogic, IntegrationRequest, Provider, TreeItem } from '../types';
|
|
4
|
+
import { JobClient } from './types';
|
|
4
5
|
export declare function getCrowdinSnapshot(config: Config, integration: IntegrationLogic, crowdinApiClient: Crowdin, projectId: number, integrationSettings: any): Promise<TreeItem[]>;
|
|
5
|
-
export declare function getIntegrationSnapshot({ integration, integrationCredentials, integrationSettings, client, projectId, }: {
|
|
6
|
+
export declare function getIntegrationSnapshot({ integration, integrationCredentials, integrationSettings, client, projectId, job, }: {
|
|
6
7
|
integration: IntegrationLogic;
|
|
7
8
|
integrationCredentials: any;
|
|
8
9
|
integrationSettings: any;
|
|
9
10
|
client?: Crowdin;
|
|
10
11
|
projectId?: number;
|
|
12
|
+
job?: JobClient;
|
|
11
13
|
}): Promise<TreeItem[]>;
|
|
12
|
-
export declare function createOrUpdateFileSnapshot(config: Config, integration: IntegrationLogic, req: IntegrationRequest, provider: Provider): Promise<void>;
|
|
14
|
+
export declare function createOrUpdateFileSnapshot(config: Config, integration: IntegrationLogic, req: IntegrationRequest, provider: Provider, job?: JobClient): Promise<void>;
|
|
@@ -16,6 +16,7 @@ const types_1 = require("../types");
|
|
|
16
16
|
const storage_1 = require("../../../storage");
|
|
17
17
|
const defaults_1 = require("./defaults");
|
|
18
18
|
const files_1 = require("./files");
|
|
19
|
+
const types_2 = require("./types");
|
|
19
20
|
const DEFAULT_SNAPSHOT_FETCH_CONCURRENCY = 1;
|
|
20
21
|
function getCrowdinSnapshot(config, integration, crowdinApiClient, projectId, integrationSettings) {
|
|
21
22
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -42,10 +43,10 @@ function getTreeItems(integrationData) {
|
|
|
42
43
|
}
|
|
43
44
|
return files;
|
|
44
45
|
}
|
|
45
|
-
function getOneLevelFetchingFiles(
|
|
46
|
-
return __awaiter(this,
|
|
46
|
+
function getOneLevelFetchingFiles(integration_1, integrationCredentials_1, integrationSettings_1, parentFiles_1, client_1, projectId_1, job_1) {
|
|
47
|
+
return __awaiter(this, arguments, void 0, function* (integration, integrationCredentials, integrationSettings, parentFiles, client, projectId, job, visitedIds = new Set()) {
|
|
47
48
|
var _a;
|
|
48
|
-
const folders = parentFiles.filter((file) => !file.type);
|
|
49
|
+
const folders = parentFiles.filter((file) => !file.type && !visitedIds.has(file.id));
|
|
49
50
|
if (folders.length === 0) {
|
|
50
51
|
return parentFiles;
|
|
51
52
|
}
|
|
@@ -54,6 +55,11 @@ function getOneLevelFetchingFiles(integration, integrationCredentials, integrati
|
|
|
54
55
|
for (let i = 0; i < folders.length; i += concurrency) {
|
|
55
56
|
const batch = folders.slice(i, i + concurrency);
|
|
56
57
|
const batchResults = yield Promise.all(batch.map((folder) => __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
var _a;
|
|
59
|
+
if (job && types_2.JobStatus.CANCELED === ((_a = (yield job.get())) === null || _a === void 0 ? void 0 : _a.status)) {
|
|
60
|
+
throw new Error('Job canceled');
|
|
61
|
+
}
|
|
62
|
+
visitedIds.add(folder.id);
|
|
57
63
|
const childs = getTreeItems(yield integration.getIntegrationFiles({
|
|
58
64
|
credentials: integrationCredentials,
|
|
59
65
|
client,
|
|
@@ -63,10 +69,13 @@ function getOneLevelFetchingFiles(integration, integrationCredentials, integrati
|
|
|
63
69
|
search: '',
|
|
64
70
|
page: 0,
|
|
65
71
|
}));
|
|
72
|
+
if (job) {
|
|
73
|
+
yield job.update({ info: `Loading snapshot from ${folder.name}` });
|
|
74
|
+
}
|
|
66
75
|
if (childs.length === 0) {
|
|
67
76
|
return [];
|
|
68
77
|
}
|
|
69
|
-
return getOneLevelFetchingFiles(integration, integrationCredentials, integrationSettings, childs, client, projectId);
|
|
78
|
+
return getOneLevelFetchingFiles(integration, integrationCredentials, integrationSettings, childs, client, projectId, job, visitedIds);
|
|
70
79
|
})));
|
|
71
80
|
results.push(...batchResults.flat());
|
|
72
81
|
}
|
|
@@ -74,7 +83,7 @@ function getOneLevelFetchingFiles(integration, integrationCredentials, integrati
|
|
|
74
83
|
});
|
|
75
84
|
}
|
|
76
85
|
function getIntegrationSnapshot(_a) {
|
|
77
|
-
return __awaiter(this, arguments, void 0, function* ({ integration, integrationCredentials, integrationSettings, client, projectId, }) {
|
|
86
|
+
return __awaiter(this, arguments, void 0, function* ({ integration, integrationCredentials, integrationSettings, client, projectId, job, }) {
|
|
78
87
|
var _b;
|
|
79
88
|
let files = [];
|
|
80
89
|
let integrationData = [];
|
|
@@ -88,7 +97,7 @@ function getIntegrationSnapshot(_a) {
|
|
|
88
97
|
});
|
|
89
98
|
files = getTreeItems(integrationData);
|
|
90
99
|
if (integration.integrationOneLevelFetching) {
|
|
91
|
-
files = yield getOneLevelFetchingFiles(integration, integrationCredentials, integrationSettings, files, client, projectId);
|
|
100
|
+
files = yield getOneLevelFetchingFiles(integration, integrationCredentials, integrationSettings, files, client, projectId, job);
|
|
92
101
|
}
|
|
93
102
|
if ((integrationSettings === null || integrationSettings === void 0 ? void 0 : integrationSettings.skipIntegrationNodesToggle) === true ||
|
|
94
103
|
((integrationSettings === null || integrationSettings === void 0 ? void 0 : integrationSettings.skipIntegrationNodesToggle) === null && ((_b = integration.skipIntegrationNodesToggle) === null || _b === void 0 ? void 0 : _b.value))) {
|
|
@@ -99,7 +108,7 @@ function getIntegrationSnapshot(_a) {
|
|
|
99
108
|
return files;
|
|
100
109
|
});
|
|
101
110
|
}
|
|
102
|
-
function createOrUpdateFileSnapshot(config, integration, req, provider) {
|
|
111
|
+
function createOrUpdateFileSnapshot(config, integration, req, provider, job) {
|
|
103
112
|
return __awaiter(this, void 0, void 0, function* () {
|
|
104
113
|
let files = [];
|
|
105
114
|
const existingSnapshot = yield (0, storage_1.getStorage)().getFilesSnapshot(req.crowdinContext.clientId, req.crowdinContext.crowdinId, provider);
|
|
@@ -113,6 +122,7 @@ function createOrUpdateFileSnapshot(config, integration, req, provider) {
|
|
|
113
122
|
integrationSettings: req.integrationSettings,
|
|
114
123
|
client: req.crowdinApiClient,
|
|
115
124
|
projectId: req.crowdinContext.jwtPayload.context.project_id,
|
|
125
|
+
job,
|
|
116
126
|
});
|
|
117
127
|
}
|
|
118
128
|
if (existingSnapshot) {
|
package/out/util/connection.d.ts
CHANGED
|
@@ -10,4 +10,12 @@ export declare function prepareCrowdinClient({ config, credentials, autoRenew, c
|
|
|
10
10
|
client: Crowdin;
|
|
11
11
|
token: string;
|
|
12
12
|
}>;
|
|
13
|
+
export interface IntegrationAccessResult {
|
|
14
|
+
integrationCredentials: IntegrationCredentials | null;
|
|
15
|
+
projectIntegrationCredentials: IntegrationCredentials[];
|
|
16
|
+
projectId: number;
|
|
17
|
+
clientId: string;
|
|
18
|
+
ownerIds: number[];
|
|
19
|
+
}
|
|
20
|
+
export declare function resolveIntegrationAccess(clientId: string): Promise<IntegrationAccessResult>;
|
|
13
21
|
export declare function prepareIntegrationCredentials(config: Config, integration: IntegrationLogic, integrationCredentials: IntegrationCredentials): Promise<any>;
|
package/out/util/connection.js
CHANGED
|
@@ -46,6 +46,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
48
|
exports.prepareCrowdinClient = prepareCrowdinClient;
|
|
49
|
+
exports.resolveIntegrationAccess = resolveIntegrationAccess;
|
|
49
50
|
exports.prepareIntegrationCredentials = prepareIntegrationCredentials;
|
|
50
51
|
const crowdin_api_client_1 = __importDefault(require("@crowdin/crowdin-api-client"));
|
|
51
52
|
const crowdin_apps_functions_1 = require("@crowdin/crowdin-apps-functions");
|
|
@@ -259,6 +260,38 @@ function prepareCrowdinClient(_a) {
|
|
|
259
260
|
};
|
|
260
261
|
});
|
|
261
262
|
}
|
|
263
|
+
function resolveIntegrationAccess(clientId) {
|
|
264
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
265
|
+
const { organization, projectId, userId } = crowdinAppFunctions.parseCrowdinId(clientId);
|
|
266
|
+
let integrationCredentials = yield (0, storage_1.getStorage)().getIntegrationCredentials(clientId);
|
|
267
|
+
const ownerIds = [];
|
|
268
|
+
let projectIntegrationCredentials = [];
|
|
269
|
+
if (!integrationCredentials) {
|
|
270
|
+
projectIntegrationCredentials = (yield (0, storage_1.getStorage)().getAllIntegrationCredentials(organization)).filter((item) => {
|
|
271
|
+
const { organization: itemOrganization, projectId: itemProjectId } = crowdinAppFunctions.parseCrowdinId(item.id);
|
|
272
|
+
return itemOrganization === organization && itemProjectId === projectId;
|
|
273
|
+
});
|
|
274
|
+
for (const credentials of projectIntegrationCredentials) {
|
|
275
|
+
ownerIds.push(crowdinAppFunctions.parseCrowdinId(credentials.id).userId);
|
|
276
|
+
if (credentials.managers) {
|
|
277
|
+
const managers = JSON.parse(credentials.managers) || [];
|
|
278
|
+
if (managers.includes(`${userId}`)) {
|
|
279
|
+
integrationCredentials = credentials;
|
|
280
|
+
clientId = credentials.id;
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
integrationCredentials: integrationCredentials || null,
|
|
288
|
+
projectIntegrationCredentials,
|
|
289
|
+
projectId,
|
|
290
|
+
clientId,
|
|
291
|
+
ownerIds,
|
|
292
|
+
};
|
|
293
|
+
});
|
|
294
|
+
}
|
|
262
295
|
function prepareIntegrationCredentials(config, integration, integrationCredentials) {
|
|
263
296
|
return __awaiter(this, void 0, void 0, function* () {
|
|
264
297
|
const credentials = JSON.parse((0, _1.decryptData)(config, integrationCredentials.credentials));
|
package/package.json
CHANGED