@crowdin/app-project-module 0.15.1 → 0.15.3

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.
@@ -20,8 +20,8 @@ function handle(config) {
20
20
  const token = yield (0, crowdin_apps_functions_1.generateOAuthToken)(config.clientId, config.clientSecret, event.code);
21
21
  const credentials = {
22
22
  id: (event.domain || event.organizationId).toString(),
23
- accessToken: (0, util_1.encryptData)(config.clientSecret, token.accessToken),
24
- refreshToken: (0, util_1.encryptData)(config.clientSecret, token.refreshToken),
23
+ accessToken: (0, util_1.encryptData)(config, token.accessToken),
24
+ refreshToken: (0, util_1.encryptData)(config, token.refreshToken),
25
25
  expire: (new Date().getTime() / 1000 + token.expiresIn).toString(),
26
26
  type: event.domain ? models_1.AccountType.ENTERPRISE : models_1.AccountType.NORMAL,
27
27
  };
@@ -23,7 +23,7 @@ function handle(config, integration) {
23
23
  (0, util_1.log)('Deleting old credentials', config.logger);
24
24
  yield (0, storage_1.deleteIntegrationCredentials)(req.crowdinContext.clientId);
25
25
  }
26
- yield (0, storage_1.saveIntegrationCredentials)(req.crowdinContext.clientId, (0, util_1.encryptData)(config.clientSecret, JSON.stringify(req.body.credentials)), req.crowdinContext.crowdinId);
26
+ yield (0, storage_1.saveIntegrationCredentials)(req.crowdinContext.clientId, (0, util_1.encryptData)(config, JSON.stringify(req.body.credentials)), req.crowdinContext.crowdinId);
27
27
  res.status(204).end();
28
28
  }), config.onError);
29
29
  }
@@ -11,10 +11,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const storage_1 = require("../storage");
13
13
  const util_1 = require("../util");
14
+ const connection_1 = require("../util/connection");
14
15
  function handle(config) {
15
16
  return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
16
17
  (0, util_1.log)('Recieved integration logout request', config.logger);
17
18
  yield (0, storage_1.deleteIntegrationCredentials)(req.crowdinContext.clientId);
19
+ (0, connection_1.clearCache)(req.crowdinContext.crowdinId);
18
20
  res.status(204).end();
19
21
  }), config.onError);
20
22
  }
@@ -10,6 +10,10 @@ export interface Config extends ImagePath {
10
10
  * client secret that we received when registering the app
11
11
  */
12
12
  clientSecret: string;
13
+ /**
14
+ * Secret to encrypt/decrypt credentials (by default @clientSecret will be used)
15
+ */
16
+ cryptoSecret?: string;
13
17
  /**
14
18
  * https url where an app is reachable from the internet (e.g. the one that ngrok generates for us)
15
19
  */
@@ -5,6 +5,7 @@ export declare function prepareCrowdinClient(config: Config, credentials: Crowdi
5
5
  token: string;
6
6
  }>;
7
7
  export declare function prepareIntegrationCredentials(config: Config, integration: IntegrationLogic, integrationCredentials: IntegrationCredentials): Promise<any>;
8
+ export declare function clearCache(organization: string): void;
8
9
  export declare function checkSubscription(config: Config, token: string, organization: string, accountType: AccountType): Promise<{
9
10
  expired: boolean;
10
11
  subscribeLink?: string;
@@ -31,7 +31,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
31
31
  return (mod && mod.__esModule) ? mod : { "default": mod };
32
32
  };
33
33
  Object.defineProperty(exports, "__esModule", { value: true });
34
- exports.checkSubscription = exports.prepareIntegrationCredentials = exports.prepareCrowdinClient = void 0;
34
+ exports.checkSubscription = exports.clearCache = exports.prepareIntegrationCredentials = exports.prepareCrowdinClient = void 0;
35
35
  const crowdin_api_client_1 = __importDefault(require("@crowdin/crowdin-api-client"));
36
36
  const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
37
37
  const axios_1 = __importDefault(require("axios"));
@@ -45,19 +45,19 @@ function prepareCrowdinClient(config, credentials) {
45
45
  let token;
46
46
  const organization = credentials.type === models_1.AccountType.ENTERPRISE ? credentials.id : undefined;
47
47
  if (!isExpired) {
48
- const token = (0, _1.decryptData)(config.clientSecret, credentials.accessToken);
48
+ const token = (0, _1.decryptData)(config, credentials.accessToken);
49
49
  return {
50
50
  client: new crowdin_api_client_1.default({ token, organization }),
51
51
  token,
52
52
  };
53
53
  }
54
54
  (0, _1.log)('Crowdin credentials have expired. Requesting a new credentials', config.logger);
55
- const newCredentials = yield crowdinAppFunctions.refreshOAuthToken(config.clientId, config.clientSecret, (0, _1.decryptData)(config.clientSecret, credentials.refreshToken));
55
+ const newCredentials = yield crowdinAppFunctions.refreshOAuthToken(config.clientId, config.clientSecret, (0, _1.decryptData)(config, credentials.refreshToken));
56
56
  (0, _1.log)('Saving updated crowdin credentials in the database', config.logger);
57
57
  yield (0, storage_1.updateCrowdinCredentials)({
58
58
  id: credentials.id,
59
- refreshToken: (0, _1.encryptData)(config.clientSecret, newCredentials.refreshToken),
60
- accessToken: (0, _1.encryptData)(config.clientSecret, newCredentials.accessToken),
59
+ refreshToken: (0, _1.encryptData)(config, newCredentials.refreshToken),
60
+ accessToken: (0, _1.encryptData)(config, newCredentials.accessToken),
61
61
  expire: (new Date().getTime() / 1000 + newCredentials.expiresIn).toString(),
62
62
  type: credentials.type,
63
63
  });
@@ -71,7 +71,7 @@ exports.prepareCrowdinClient = prepareCrowdinClient;
71
71
  function prepareIntegrationCredentials(config, integration, integrationCredentials) {
72
72
  var _a, _b, _c, _d, _e, _f, _g, _h;
73
73
  return __awaiter(this, void 0, void 0, function* () {
74
- const credentials = JSON.parse((0, _1.decryptData)(config.clientSecret, integrationCredentials.credentials));
74
+ const credentials = JSON.parse((0, _1.decryptData)(config, integrationCredentials.credentials));
75
75
  if ((_a = integration.oauthLogin) === null || _a === void 0 ? void 0 : _a.refresh) {
76
76
  (0, _1.log)('Checking if integration credentials need to be refreshed', config.logger);
77
77
  const oauthLogin = integration.oauthLogin;
@@ -104,7 +104,7 @@ function prepareIntegrationCredentials(config, integration, integrationCredentia
104
104
  credentials.refreshToken = newCredentials[((_h = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _h === void 0 ? void 0 : _h.refreshToken) || 'refresh_token'];
105
105
  }
106
106
  (0, _1.log)('Saving updated integration credentials in the database', config.logger);
107
- yield (0, storage_1.updateIntegrationCredentials)(integrationCredentials.id, (0, _1.encryptData)(config.clientSecret, JSON.stringify(credentials)));
107
+ yield (0, storage_1.updateIntegrationCredentials)(integrationCredentials.id, (0, _1.encryptData)(config, JSON.stringify(credentials)));
108
108
  }
109
109
  }
110
110
  return credentials;
@@ -112,18 +112,27 @@ function prepareIntegrationCredentials(config, integration, integrationCredentia
112
112
  }
113
113
  exports.prepareIntegrationCredentials = prepareIntegrationCredentials;
114
114
  const subscriptionCache = {};
115
- function addToCache(organization, validUntil, cachingSeconds, subscribeLink) {
115
+ function addToCache(organization, appIdenfifier, validUntil, cachingSeconds, subscribeLink) {
116
116
  if (!cachingSeconds) {
117
117
  return;
118
118
  }
119
+ const orgCache = subscriptionCache[organization] || {};
119
120
  const now = new Date();
120
121
  now.setSeconds(now.getSeconds() + cachingSeconds);
121
- subscriptionCache[organization] = {
122
+ orgCache[appIdenfifier] = {
122
123
  cacheValidUntil: now,
123
124
  validUntil,
124
125
  subscribeLink,
125
126
  };
127
+ subscriptionCache[organization] = orgCache;
126
128
  }
129
+ function getFromCache(organization, appIdenfifier) {
130
+ return (subscriptionCache[organization] || {})[appIdenfifier];
131
+ }
132
+ function clearCache(organization) {
133
+ delete subscriptionCache[organization];
134
+ }
135
+ exports.clearCache = clearCache;
127
136
  function checkSubscription(config, token, organization, accountType) {
128
137
  return __awaiter(this, void 0, void 0, function* () {
129
138
  if (!config.pricing || config.pricing.planType === 'free') {
@@ -139,8 +148,10 @@ function checkSubscription(config, token, organization, accountType) {
139
148
  days = config.pricing.trialCrowdin || config.pricing.trial || defaultSubscriptionPlan;
140
149
  }
141
150
  (0, _1.log)(`Checking subscription plan. Subscriptino plan ${days} days`, config.logger);
142
- if (subscriptionCache[organization]) {
143
- const { cacheValidUntil, validUntil, subscribeLink } = subscriptionCache[organization];
151
+ const appIdentifier = config.identifier;
152
+ const cacheEntry = getFromCache(organization, appIdentifier);
153
+ if (cacheEntry) {
154
+ const { cacheValidUntil, validUntil, subscribeLink } = cacheEntry;
144
155
  if (cacheValidUntil.getTime() > Date.now()) {
145
156
  (0, _1.log)(`Loaded data from cache. Subscription is vali until ${validUntil.toISOString()}`, config.logger);
146
157
  const expired = new Date(validUntil).getTime() < Date.now();
@@ -149,7 +160,6 @@ function checkSubscription(config, token, organization, accountType) {
149
160
  }
150
161
  }
151
162
  try {
152
- const appIdentifier = config.identifier;
153
163
  const subscription = yield crowdinAppFunctions.getSubscription({
154
164
  appIdentifier,
155
165
  organization: accountType === models_1.AccountType.ENTERPRISE ? organization : undefined,
@@ -158,7 +168,7 @@ function checkSubscription(config, token, organization, accountType) {
158
168
  (0, _1.log)(`Recieved subscription info. ${JSON.stringify(subscription)}`, config.logger);
159
169
  const expired = new Date(subscription.expires).getTime() < Date.now();
160
170
  (0, _1.log)(`expired ${expired}`, config.logger);
161
- addToCache(organization, new Date(subscription.expires), config.pricing.cachingSeconds);
171
+ addToCache(organization, appIdentifier, new Date(subscription.expires), config.pricing.cachingSeconds);
162
172
  return { expired };
163
173
  }
164
174
  catch (e) {
@@ -169,7 +179,7 @@ function checkSubscription(config, token, organization, accountType) {
169
179
  date.setDate(date.getDate() + days);
170
180
  const expired = date.getTime() < Date.now();
171
181
  (0, _1.log)(`expired ${expired}`, config.logger);
172
- addToCache(organization, new Date(date), config.pricing.cachingSeconds, subscribeLink);
182
+ addToCache(organization, appIdentifier, new Date(date), config.pricing.cachingSeconds, subscribeLink);
173
183
  return { expired, subscribeLink };
174
184
  }
175
185
  if (config.onError) {
@@ -1,5 +1,5 @@
1
1
  import { Request, Response } from 'express';
2
- import { Logger } from '../models';
2
+ import { Config, Logger } from '../models';
3
3
  export declare class CodeError extends Error {
4
4
  code: number | undefined;
5
5
  constructor(message: string, code?: number);
@@ -7,5 +7,5 @@ export declare class CodeError extends Error {
7
7
  export declare function log(message: string, logger?: Logger): void;
8
8
  export declare function getMessage(err: any): any;
9
9
  export declare function runAsyncWrapper(callback: Function, onError?: (e: any) => void): (req: Request, res: Response, next: Function) => void;
10
- export declare function encryptData(secret: string, data: string): string;
11
- export declare function decryptData(secret: string, data: string): string;
10
+ export declare function encryptData(config: Config, data: string): string;
11
+ export declare function decryptData(config: Config, data: string): string;
package/out/util/index.js CHANGED
@@ -95,11 +95,11 @@ function runAsyncWrapper(callback, onError) {
95
95
  };
96
96
  }
97
97
  exports.runAsyncWrapper = runAsyncWrapper;
98
- function encryptData(secret, data) {
99
- return crypto.AES.encrypt(data, secret).toString();
98
+ function encryptData(config, data) {
99
+ return crypto.AES.encrypt(data, config.cryptoSecret || config.clientSecret).toString();
100
100
  }
101
101
  exports.encryptData = encryptData;
102
- function decryptData(secret, data) {
103
- return crypto.AES.decrypt(data, secret).toString(crypto.enc.Utf8);
102
+ function decryptData(config, data) {
103
+ return crypto.AES.decrypt(data, config.cryptoSecret || config.clientSecret).toString(crypto.enc.Utf8);
104
104
  }
105
105
  exports.decryptData = decryptData;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdin/app-project-module",
3
- "version": "0.15.1",
3
+ "version": "0.15.3",
4
4
  "description": "Module that generates for you all common endpoints for serving standalone Crowdin App",
5
5
  "main": "out/index.js",
6
6
  "types": "out/index.d.ts",