@boxyhq/saml-jackson 0.3.6-beta.638 → 0.3.6-beta.644

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.
@@ -18,25 +18,10 @@ export declare class APIController implements IAPIController {
18
18
  * consumes:
19
19
  * - application/x-www-form-urlencoded
20
20
  * parameters:
21
- * - name: name
22
- * description: Name/identifier for the config
23
- * type: string
24
- * in: formData
25
- * required: true
26
- * example: cal-saml-config
27
- * - name: description
28
- * description: A short description for the config not more than 50 characters
29
- * type: string
30
- * in: formData
31
- * required: true
32
- * example: SAML login for cal.com app
33
21
  * - name: encodedRawMetadata
34
22
  * description: Base64 encoding of the XML metadata
35
23
  * in: formData
36
- * type: string
37
- * - name: rawMetadata
38
- * description: Raw XML metadata
39
- * in: formData
24
+ * required: true
40
25
  * type: string
41
26
  * - name: defaultRedirectUrl
42
27
  * description: The redirect URL to use in the IdP login flow
@@ -82,76 +67,6 @@ export declare class APIController implements IAPIController {
82
67
  * description: Unauthorized
83
68
  */
84
69
  config(body: IdPConfig): Promise<OAuth>;
85
- /**
86
- * @swagger
87
- *
88
- * /api/v1/saml/config:
89
- * patch:
90
- * summary: Update SAML configuration
91
- * operationId: update-saml-config
92
- * tags: [SAML Config]
93
- * consumes:
94
- * - application/json
95
- * - application/x-www-form-urlencoded
96
- * parameters:
97
- * - name: clientID
98
- * description: Client ID for the config
99
- * type: string
100
- * in: formData
101
- * required: true
102
- * - name: name
103
- * description: Name/identifier for the config
104
- * type: string
105
- * in: formData
106
- * required: true
107
- * example: cal-saml-config
108
- * - name: description
109
- * description: A short description for the config not more than 50 characters
110
- * type: string
111
- * in: formData
112
- * required: true
113
- * example: SAML login for cal.com app
114
- * - name: encodedRawMetadata
115
- * description: Base64 encoding of the XML metadata
116
- * in: formData
117
- * type: string
118
- * - name: rawMetadata
119
- * description: Raw XML metadata
120
- * in: formData
121
- * type: string
122
- * - name: defaultRedirectUrl
123
- * description: The redirect URL to use in the IdP login flow
124
- * in: formData
125
- * required: true
126
- * type: string
127
- * example: http://localhost:3000/login/saml
128
- * - name: redirectUrl
129
- * description: JSON encoded array containing a list of allowed redirect URLs
130
- * in: formData
131
- * required: true
132
- * type: string
133
- * example: '["http://localhost:3000/*"]'
134
- * - name: tenant
135
- * description: Tenant
136
- * in: formData
137
- * required: true
138
- * type: string
139
- * example: boxyhq.com
140
- * - name: product
141
- * description: Product
142
- * in: formData
143
- * required: true
144
- * type: string
145
- * example: demo
146
- * responses:
147
- * 204:
148
- * description: Success
149
- * 400:
150
- * description: Please provide clientID
151
- * 401:
152
- * description: Unauthorized
153
- */
154
- updateConfig(body: any): Promise<void>;
155
70
  /**
156
71
  * @swagger
157
72
  *
@@ -181,35 +96,11 @@ export declare class APIController implements IAPIController {
181
96
  * description: Success
182
97
  * schema:
183
98
  * type: object
99
+ * properties:
100
+ * provider:
101
+ * type: string
184
102
  * example:
185
- * {
186
- * "config": {
187
- * "idpMetadata": {
188
- * "sso": {
189
- * "postUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxxx/sso/saml",
190
- * "redirectUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxxx/sso/saml"
191
- * },
192
- * "entityID": "http://www.okta.com/xxxxxxxxxxxxx",
193
- * "thumbprint": "Eo+eUi3UM3XIMkFFtdVK3yJ5vO9f7YZdasdasdad",
194
- * "loginType": "idp",
195
- * "provider": "okta.com"
196
- * },
197
- * "defaultRedirectUrl": "https://hoppscotch.io/",
198
- * "redirectUrl": ["https://hoppscotch.io/"],
199
- * "tenant": "hoppscotch.io",
200
- * "product": "API Engine",
201
- * "name": "Hoppscotch-SP",
202
- * "description": "SP for hoppscotch.io",
203
- * "clientID": "Xq8AJt3yYAxmXizsCWmUBDRiVP1iTC8Y/otnvFIMitk",
204
- * "clientSecret": "00e3e11a3426f97d8000000738300009130cd45419c5943",
205
- * "certs": {
206
- * "publicKey": "-----BEGIN CERTIFICATE-----.......-----END CERTIFICATE-----",
207
- * "privateKey": "-----BEGIN PRIVATE KEY-----......-----END PRIVATE KEY-----"
208
- * }
209
- * }
210
- * }
211
- * '400':
212
- * description: Please provide `clientID` or `tenant`/`product`.
103
+ * type: accounts.google.com
213
104
  * '401':
214
105
  * description: Unauthorized
215
106
  */
@@ -217,7 +108,7 @@ export declare class APIController implements IAPIController {
217
108
  clientID: string;
218
109
  tenant: string;
219
110
  product: string;
220
- }): Promise<any>;
111
+ }): Promise<Partial<OAuth>>;
221
112
  /**
222
113
  * @swagger
223
114
  * /api/v1/saml/config:
@@ -27,17 +27,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
27
27
  step((generator = generator.apply(thisArg, _arguments || [])).next());
28
28
  });
29
29
  };
30
- var __rest = (this && this.__rest) || function (s, e) {
31
- var t = {};
32
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
33
- t[p] = s[p];
34
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
35
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
36
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
37
- t[p[i]] = s[p[i]];
38
- }
39
- return t;
40
- };
41
30
  var __importDefault = (this && this.__importDefault) || function (mod) {
42
31
  return (mod && mod.__esModule) ? mod : { "default": mod };
43
32
  };
@@ -45,6 +34,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
45
34
  exports.APIController = void 0;
46
35
  const crypto_1 = __importDefault(require("crypto"));
47
36
  const dbutils = __importStar(require("../db/utils"));
37
+ const metrics = __importStar(require("../opentelemetry/metrics"));
48
38
  const saml_1 = __importDefault(require("../saml/saml"));
49
39
  const x509_1 = __importDefault(require("../saml/x509"));
50
40
  const error_1 = require("./error");
@@ -54,7 +44,7 @@ class APIController {
54
44
  this.configStore = configStore;
55
45
  }
56
46
  _validateIdPConfig(body) {
57
- const { encodedRawMetadata, rawMetadata, defaultRedirectUrl, redirectUrl, tenant, product, name } = body;
47
+ const { encodedRawMetadata, rawMetadata, defaultRedirectUrl, redirectUrl, tenant, product } = body;
58
48
  if (!rawMetadata && !encodedRawMetadata) {
59
49
  throw new error_1.JacksonError('Please provide rawMetadata or encodedRawMetadata', 400);
60
50
  }
@@ -70,9 +60,6 @@ class APIController {
70
60
  if (!product) {
71
61
  throw new error_1.JacksonError('Please provide product', 400);
72
62
  }
73
- if (!name) {
74
- throw new error_1.JacksonError('Please provide a friendly name', 400);
75
- }
76
63
  }
77
64
  /**
78
65
  * @swagger
@@ -87,25 +74,10 @@ class APIController {
87
74
  * consumes:
88
75
  * - application/x-www-form-urlencoded
89
76
  * parameters:
90
- * - name: name
91
- * description: Name/identifier for the config
92
- * type: string
93
- * in: formData
94
- * required: true
95
- * example: cal-saml-config
96
- * - name: description
97
- * description: A short description for the config not more than 50 characters
98
- * type: string
99
- * in: formData
100
- * required: true
101
- * example: SAML login for cal.com app
102
77
  * - name: encodedRawMetadata
103
78
  * description: Base64 encoding of the XML metadata
104
79
  * in: formData
105
- * type: string
106
- * - name: rawMetadata
107
- * description: Raw XML metadata
108
- * in: formData
80
+ * required: true
109
81
  * type: string
110
82
  * - name: defaultRedirectUrl
111
83
  * description: The redirect URL to use in the IdP login flow
@@ -152,7 +124,8 @@ class APIController {
152
124
  */
153
125
  config(body) {
154
126
  return __awaiter(this, void 0, void 0, function* () {
155
- const { encodedRawMetadata, rawMetadata, defaultRedirectUrl, redirectUrl, tenant, product, name, description, } = body;
127
+ const { encodedRawMetadata, rawMetadata, defaultRedirectUrl, redirectUrl, tenant, product } = body;
128
+ metrics.increment('createConfig');
156
129
  this._validateIdPConfig(body);
157
130
  let metaData = rawMetadata;
158
131
  if (encodedRawMetadata) {
@@ -184,8 +157,6 @@ class APIController {
184
157
  redirectUrl: JSON.parse(redirectUrl),
185
158
  tenant,
186
159
  product,
187
- name,
188
- description,
189
160
  clientID,
190
161
  clientSecret,
191
162
  certs,
@@ -205,117 +176,6 @@ class APIController {
205
176
  };
206
177
  });
207
178
  }
208
- /**
209
- * @swagger
210
- *
211
- * /api/v1/saml/config:
212
- * patch:
213
- * summary: Update SAML configuration
214
- * operationId: update-saml-config
215
- * tags: [SAML Config]
216
- * consumes:
217
- * - application/json
218
- * - application/x-www-form-urlencoded
219
- * parameters:
220
- * - name: clientID
221
- * description: Client ID for the config
222
- * type: string
223
- * in: formData
224
- * required: true
225
- * - name: name
226
- * description: Name/identifier for the config
227
- * type: string
228
- * in: formData
229
- * required: true
230
- * example: cal-saml-config
231
- * - name: description
232
- * description: A short description for the config not more than 50 characters
233
- * type: string
234
- * in: formData
235
- * required: true
236
- * example: SAML login for cal.com app
237
- * - name: encodedRawMetadata
238
- * description: Base64 encoding of the XML metadata
239
- * in: formData
240
- * type: string
241
- * - name: rawMetadata
242
- * description: Raw XML metadata
243
- * in: formData
244
- * type: string
245
- * - name: defaultRedirectUrl
246
- * description: The redirect URL to use in the IdP login flow
247
- * in: formData
248
- * required: true
249
- * type: string
250
- * example: http://localhost:3000/login/saml
251
- * - name: redirectUrl
252
- * description: JSON encoded array containing a list of allowed redirect URLs
253
- * in: formData
254
- * required: true
255
- * type: string
256
- * example: '["http://localhost:3000/*"]'
257
- * - name: tenant
258
- * description: Tenant
259
- * in: formData
260
- * required: true
261
- * type: string
262
- * example: boxyhq.com
263
- * - name: product
264
- * description: Product
265
- * in: formData
266
- * required: true
267
- * type: string
268
- * example: demo
269
- * responses:
270
- * 204:
271
- * description: Success
272
- * 400:
273
- * description: Please provide clientID
274
- * 401:
275
- * description: Unauthorized
276
- */
277
- updateConfig(body) {
278
- var _a;
279
- return __awaiter(this, void 0, void 0, function* () {
280
- const { encodedRawMetadata, // could be omitted
281
- rawMetadata, // could be omitted
282
- defaultRedirectUrl, redirectUrl, name, description } = body, clientInfo = __rest(body, ["encodedRawMetadata", "rawMetadata", "defaultRedirectUrl", "redirectUrl", "name", "description"]);
283
- if (!(clientInfo === null || clientInfo === void 0 ? void 0 : clientInfo.clientID)) {
284
- throw new error_1.JacksonError('Please provide clientID', 400);
285
- }
286
- let metaData = rawMetadata;
287
- if (encodedRawMetadata) {
288
- metaData = Buffer.from(encodedRawMetadata, 'base64').toString();
289
- }
290
- let newMetadata;
291
- if (metaData) {
292
- newMetadata = yield saml_1.default.parseMetadataAsync(metaData);
293
- // extract provider
294
- let providerName = extractHostName(newMetadata.entityID);
295
- if (!providerName) {
296
- providerName = extractHostName(newMetadata.sso.redirectUrl || newMetadata.sso.postUrl);
297
- }
298
- newMetadata.provider = providerName ? providerName : 'Unknown';
299
- }
300
- if (newMetadata) {
301
- // check if clientID matches with new metadata payload
302
- const clientID = dbutils.keyDigest(dbutils.keyFromParts(clientInfo.tenant, clientInfo.product, newMetadata.entityID));
303
- if (clientID !== (clientInfo === null || clientInfo === void 0 ? void 0 : clientInfo.clientID)) {
304
- throw new error_1.JacksonError('Tenant/Product config mismatch with IdP metadata');
305
- }
306
- }
307
- const _currentConfig = (_a = (yield this.getConfig(clientInfo))) === null || _a === void 0 ? void 0 : _a.config;
308
- yield this.configStore.put(clientInfo === null || clientInfo === void 0 ? void 0 : clientInfo.clientID, Object.assign(Object.assign({}, _currentConfig), { name: name ? name : _currentConfig.name, description: description ? description : _currentConfig.description, idpMetadata: newMetadata ? newMetadata : _currentConfig.idpMetadata, defaultRedirectUrl: defaultRedirectUrl ? defaultRedirectUrl : _currentConfig.defaultRedirectUrl, redirectUrl: redirectUrl ? JSON.parse(redirectUrl) : _currentConfig.redirectUrl }), {
309
- // secondary index on entityID
310
- name: utils_1.IndexNames.EntityID,
311
- value: _currentConfig.idpMetadata.entityID,
312
- }, {
313
- // secondary index on tenant + product
314
- name: utils_1.IndexNames.TenantProduct,
315
- value: dbutils.keyFromParts(_currentConfig.tenant, _currentConfig.product),
316
- });
317
- });
318
- }
319
179
  /**
320
180
  * @swagger
321
181
  *
@@ -345,44 +205,21 @@ class APIController {
345
205
  * description: Success
346
206
  * schema:
347
207
  * type: object
208
+ * properties:
209
+ * provider:
210
+ * type: string
348
211
  * example:
349
- * {
350
- * "config": {
351
- * "idpMetadata": {
352
- * "sso": {
353
- * "postUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxxx/sso/saml",
354
- * "redirectUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxxx/sso/saml"
355
- * },
356
- * "entityID": "http://www.okta.com/xxxxxxxxxxxxx",
357
- * "thumbprint": "Eo+eUi3UM3XIMkFFtdVK3yJ5vO9f7YZdasdasdad",
358
- * "loginType": "idp",
359
- * "provider": "okta.com"
360
- * },
361
- * "defaultRedirectUrl": "https://hoppscotch.io/",
362
- * "redirectUrl": ["https://hoppscotch.io/"],
363
- * "tenant": "hoppscotch.io",
364
- * "product": "API Engine",
365
- * "name": "Hoppscotch-SP",
366
- * "description": "SP for hoppscotch.io",
367
- * "clientID": "Xq8AJt3yYAxmXizsCWmUBDRiVP1iTC8Y/otnvFIMitk",
368
- * "clientSecret": "00e3e11a3426f97d8000000738300009130cd45419c5943",
369
- * "certs": {
370
- * "publicKey": "-----BEGIN CERTIFICATE-----.......-----END CERTIFICATE-----",
371
- * "privateKey": "-----BEGIN PRIVATE KEY-----......-----END PRIVATE KEY-----"
372
- * }
373
- * }
374
- * }
375
- * '400':
376
- * description: Please provide `clientID` or `tenant`/`product`.
212
+ * type: accounts.google.com
377
213
  * '401':
378
214
  * description: Unauthorized
379
215
  */
380
216
  getConfig(body) {
381
217
  return __awaiter(this, void 0, void 0, function* () {
382
218
  const { clientID, tenant, product } = body;
219
+ metrics.increment('getConfig');
383
220
  if (clientID) {
384
221
  const samlConfig = yield this.configStore.get(clientID);
385
- return samlConfig ? { config: samlConfig } : {};
222
+ return samlConfig ? { provider: samlConfig.idpMetadata.provider } : {};
386
223
  }
387
224
  if (tenant && product) {
388
225
  const samlConfigs = yield this.configStore.getByIndex({
@@ -392,7 +229,7 @@ class APIController {
392
229
  if (!samlConfigs || !samlConfigs.length) {
393
230
  return {};
394
231
  }
395
- return { config: samlConfigs[0] };
232
+ return { provider: samlConfigs[0].idpMetadata.provider };
396
233
  }
397
234
  throw new error_1.JacksonError('Please provide `clientID` or `tenant` and `product`.', 400);
398
235
  });
@@ -437,6 +274,7 @@ class APIController {
437
274
  deleteConfig(body) {
438
275
  return __awaiter(this, void 0, void 0, function* () {
439
276
  const { clientID, clientSecret, tenant, product } = body;
277
+ metrics.increment('deleteConfig');
440
278
  if (clientID && clientSecret) {
441
279
  const samlConfig = yield this.configStore.get(clientID);
442
280
  if (!samlConfig) {
@@ -33,15 +33,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
33
33
  Object.defineProperty(exports, "__esModule", { value: true });
34
34
  exports.OAuthController = void 0;
35
35
  const crypto_1 = __importDefault(require("crypto"));
36
+ const util_1 = require("util");
37
+ const zlib_1 = require("zlib");
36
38
  const dbutils = __importStar(require("../db/utils"));
39
+ const metrics = __importStar(require("../opentelemetry/metrics"));
37
40
  const saml_1 = __importDefault(require("../saml/saml"));
38
41
  const error_1 = require("./error");
39
42
  const allowed = __importStar(require("./oauth/allowed"));
40
43
  const codeVerifier = __importStar(require("./oauth/code-verifier"));
41
44
  const redirect = __importStar(require("./oauth/redirect"));
42
45
  const utils_1 = require("./utils");
43
- const util_1 = require("util");
44
- const zlib_1 = require("zlib");
45
46
  const deflateRawAsync = (0, util_1.promisify)(zlib_1.deflateRaw);
46
47
  const relayStatePrefix = 'boxyhq_jackson_';
47
48
  function getEncodedClientId(client_id) {
@@ -74,6 +75,7 @@ class OAuthController {
74
75
  const { response_type = 'code', client_id, redirect_uri, state, tenant, product, code_challenge, code_challenge_method = '',
75
76
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
76
77
  provider = 'saml', } = body;
78
+ metrics.increment('oauthAuthorize');
77
79
  if (!redirect_uri) {
78
80
  throw new error_1.JacksonError('Please specify a redirect URL.', 400);
79
81
  }
@@ -262,6 +264,7 @@ class OAuthController {
262
264
  token(body) {
263
265
  return __awaiter(this, void 0, void 0, function* () {
264
266
  const { client_id, client_secret, code_verifier, code, grant_type = 'authorization_code' } = body;
267
+ metrics.increment('oauthToken');
265
268
  if (grant_type !== 'authorization_code') {
266
269
  throw new error_1.JacksonError('Unsupported grant_type', 400);
267
270
  }
@@ -339,6 +342,7 @@ class OAuthController {
339
342
  userInfo(token) {
340
343
  return __awaiter(this, void 0, void 0, function* () {
341
344
  const rsp = yield this.tokenStore.get(token);
345
+ metrics.increment('oauthUserInfo');
342
346
  if (!rsp || !rsp.claims) {
343
347
  throw new error_1.JacksonError('Invalid token', 403);
344
348
  }
package/dist/db/db.d.ts CHANGED
@@ -4,7 +4,6 @@ declare class DB implements DatabaseDriver {
4
4
  private encryptionKey;
5
5
  constructor(db: DatabaseDriver, encryptionKey: EncryptionKey);
6
6
  get(namespace: string, key: string): Promise<unknown>;
7
- getAll(namespace: any): Promise<unknown[]>;
8
7
  getByIndex(namespace: string, idx: Index): Promise<unknown[]>;
9
8
  put(namespace: string, key: string, val: unknown, ttl?: number, ...indexes: Index[]): Promise<unknown>;
10
9
  delete(namespace: string, key: string): Promise<unknown>;
package/dist/db/db.js CHANGED
@@ -57,15 +57,6 @@ class DB {
57
57
  return decrypt(res, this.encryptionKey);
58
58
  });
59
59
  }
60
- getAll(namespace) {
61
- return __awaiter(this, void 0, void 0, function* () {
62
- const res = (yield this.db.getAll(namespace));
63
- const encryptionKey = this.encryptionKey;
64
- return res.map((r) => {
65
- return decrypt(r, encryptionKey);
66
- });
67
- });
68
- }
69
60
  getByIndex(namespace, idx) {
70
61
  return __awaiter(this, void 0, void 0, function* () {
71
62
  const res = yield this.db.getByIndex(namespace, idx);
package/dist/db/mem.d.ts CHANGED
@@ -10,7 +10,6 @@ declare class Mem implements DatabaseDriver {
10
10
  constructor(options: DatabaseOption);
11
11
  init(): Promise<Mem>;
12
12
  get(namespace: string, key: string): Promise<any>;
13
- getAll(namespace: string): Promise<unknown[]>;
14
13
  getByIndex(namespace: string, idx: Index): Promise<any>;
15
14
  put(namespace: string, key: string, val: Encrypted, ttl?: number, ...indexes: any[]): Promise<any>;
16
15
  delete(namespace: string, key: string): Promise<any>;
package/dist/db/mem.js CHANGED
@@ -66,21 +66,6 @@ class Mem {
66
66
  return null;
67
67
  });
68
68
  }
69
- getAll(namespace) {
70
- return __awaiter(this, void 0, void 0, function* () {
71
- const returnValue = [];
72
- if (namespace) {
73
- for (const key in this.store) {
74
- if (key.startsWith(namespace)) {
75
- returnValue.push(this.store[key]);
76
- }
77
- }
78
- }
79
- if (returnValue)
80
- return returnValue;
81
- return [];
82
- });
83
- }
84
69
  getByIndex(namespace, idx) {
85
70
  return __awaiter(this, void 0, void 0, function* () {
86
71
  const dbKeys = yield this.indexes[dbutils.keyForIndex(namespace, idx)];
@@ -95,10 +80,6 @@ class Mem {
95
80
  return __awaiter(this, void 0, void 0, function* () {
96
81
  const k = dbutils.key(namespace, key);
97
82
  this.store[k] = val;
98
- if (!Date.parse(this.store['createdAt']))
99
- this.store['createdAt'] = new Date().toISOString();
100
- this.store['modifiedAt'] = new Date().toISOString();
101
- // console.log(this.store)
102
83
  if (ttl) {
103
84
  this.ttlStore[k] = {
104
85
  namespace,
@@ -7,7 +7,6 @@ declare class Mongo implements DatabaseDriver {
7
7
  constructor(options: DatabaseOption);
8
8
  init(): Promise<Mongo>;
9
9
  get(namespace: string, key: string): Promise<any>;
10
- getAll(namespace: string): Promise<unknown[]>;
11
10
  getByIndex(namespace: string, idx: Index): Promise<any>;
12
11
  put(namespace: string, key: string, val: Encrypted, ttl?: number, ...indexes: any[]): Promise<void>;
13
12
  delete(namespace: string, key: string): Promise<any>;
package/dist/db/mongo.js CHANGED
@@ -36,16 +36,8 @@ class Mongo {
36
36
  }
37
37
  init() {
38
38
  return __awaiter(this, void 0, void 0, function* () {
39
- try {
40
- if (!this.options.url) {
41
- throw Error('Please specify a db url');
42
- }
43
- this.client = new mongodb_1.MongoClient(this.options.url);
44
- yield this.client.connect();
45
- }
46
- catch (err) {
47
- console.error(`error connecting to ${this.options.type} db: ${err}`);
48
- }
39
+ this.client = new mongodb_1.MongoClient(this.options.url);
40
+ yield this.client.connect();
49
41
  this.db = this.client.db();
50
42
  this.collection = this.db.collection('jacksonStore');
51
43
  yield this.collection.createIndex({ indexes: 1 });
@@ -64,15 +56,6 @@ class Mongo {
64
56
  return null;
65
57
  });
66
58
  }
67
- getAll(namespace) {
68
- return __awaiter(this, void 0, void 0, function* () {
69
- const _namespaceMatch = new RegExp(`^${namespace}:.*`);
70
- const docs = yield this.collection.find({ _id: _namespaceMatch }).toArray();
71
- if (docs)
72
- return docs.map(({ value }) => value);
73
- return [];
74
- });
75
- }
76
59
  getByIndex(namespace, idx) {
77
60
  return __awaiter(this, void 0, void 0, function* () {
78
61
  const docs = yield this.collection
@@ -103,12 +86,8 @@ class Mongo {
103
86
  }
104
87
  doc.indexes.push(idxKey);
105
88
  }
106
- doc.modifiedAt = new Date().toISOString();
107
89
  yield this.collection.updateOne({ _id: dbutils.key(namespace, key) }, {
108
90
  $set: doc,
109
- $setOnInsert: {
110
- createdAt: new Date().toISOString(),
111
- },
112
91
  }, { upsert: true });
113
92
  });
114
93
  }
@@ -5,7 +5,6 @@ declare class Redis implements DatabaseDriver {
5
5
  constructor(options: DatabaseOption);
6
6
  init(): Promise<Redis>;
7
7
  get(namespace: string, key: string): Promise<any>;
8
- getAll(namespace: string): Promise<unknown[]>;
9
8
  getByIndex(namespace: string, idx: Index): Promise<any>;
10
9
  put(namespace: string, key: string, val: Encrypted, ttl?: number, ...indexes: any[]): Promise<void>;
11
10
  delete(namespace: string, key: string): Promise<any>;
package/dist/db/redis.js CHANGED
@@ -57,26 +57,6 @@ class Redis {
57
57
  return null;
58
58
  });
59
59
  }
60
- getAll(namespace) {
61
- return __awaiter(this, void 0, void 0, function* () {
62
- const keys = yield this.client.sendCommand(['keys', namespace + ':*']);
63
- const returnValue = [];
64
- for (let i = 0; i < keys.length; i++) {
65
- try {
66
- if (this.client.get(keys[i])) {
67
- const value = yield this.client.get(keys[i]);
68
- returnValue.push(JSON.parse(value));
69
- }
70
- }
71
- catch (error) {
72
- console.error(error);
73
- }
74
- }
75
- if (returnValue)
76
- return returnValue;
77
- return [];
78
- });
79
- }
80
60
  getByIndex(namespace, idx) {
81
61
  return __awaiter(this, void 0, void 0, function* () {
82
62
  const dbKeys = yield this.client.sMembers(dbutils.keyForIndex(namespace, idx));
@@ -3,6 +3,4 @@ export declare class JacksonStore {
3
3
  value: string;
4
4
  iv?: string;
5
5
  tag?: string;
6
- createdAt?: Date;
7
- modifiedAt?: string;
8
6
  }
@@ -36,19 +36,6 @@ __decorate([
36
36
  nullable: true,
37
37
  })
38
38
  ], JacksonStore.prototype, "tag", void 0);
39
- __decorate([
40
- (0, typeorm_1.Column)({
41
- type: 'timestamp',
42
- default: () => 'CURRENT_TIMESTAMP',
43
- nullable: false,
44
- })
45
- ], JacksonStore.prototype, "createdAt", void 0);
46
- __decorate([
47
- (0, typeorm_1.Column)({
48
- type: 'timestamp',
49
- nullable: true,
50
- })
51
- ], JacksonStore.prototype, "modifiedAt", void 0);
52
39
  JacksonStore = __decorate([
53
40
  (0, typeorm_1.Entity)()
54
41
  ], JacksonStore);
@@ -10,7 +10,6 @@ declare class Sql implements DatabaseDriver {
10
10
  constructor(options: DatabaseOption);
11
11
  init(): Promise<Sql>;
12
12
  get(namespace: string, key: string): Promise<any>;
13
- getAll(namespace: string): Promise<unknown[]>;
14
13
  getByIndex(namespace: string, idx: Index): Promise<any>;
15
14
  put(namespace: string, key: string, val: Encrypted, ttl?: number, ...indexes: any[]): Promise<void>;
16
15
  delete(namespace: string, key: string): Promise<any>;
@@ -95,7 +95,7 @@ class Sql {
95
95
  }
96
96
  get(namespace, key) {
97
97
  return __awaiter(this, void 0, void 0, function* () {
98
- const res = yield this.storeRepository.findOne({
98
+ let res = yield this.storeRepository.findOne({
99
99
  key: dbutils.key(namespace, key),
100
100
  });
101
101
  if (res && res.value) {
@@ -108,22 +108,6 @@ class Sql {
108
108
  return null;
109
109
  });
110
110
  }
111
- getAll(namespace) {
112
- return __awaiter(this, void 0, void 0, function* () {
113
- const response = yield this.storeRepository.find({
114
- where: { key: (0, typeorm_1.Like)(`%${namespace}%`) },
115
- select: ['value', 'iv', 'tag'],
116
- order: {
117
- ['createdAt']: 'DESC',
118
- // ['createdAt']: 'ASC',
119
- },
120
- });
121
- const returnValue = JSON.parse(JSON.stringify(response));
122
- if (returnValue)
123
- return returnValue;
124
- return [];
125
- });
126
- }
127
111
  getByIndex(namespace, idx) {
128
112
  return __awaiter(this, void 0, void 0, function* () {
129
113
  const res = yield this.indexRepository.find({
@@ -151,7 +135,6 @@ class Sql {
151
135
  store.value = val.value;
152
136
  store.iv = val.iv;
153
137
  store.tag = val.tag;
154
- store.modifiedAt = new Date().toISOString();
155
138
  yield transactionalEntityManager.save(store);
156
139
  if (ttl) {
157
140
  const ttlRec = new JacksonTTL_1.JacksonTTL();
package/dist/db/store.js CHANGED
@@ -40,11 +40,6 @@ class Store {
40
40
  return yield this.db.get(this.namespace, dbutils.keyDigest(key));
41
41
  });
42
42
  }
43
- getAll() {
44
- return __awaiter(this, void 0, void 0, function* () {
45
- return yield this.db.getAll(this.namespace);
46
- });
47
- }
48
43
  getByIndex(idx) {
49
44
  return __awaiter(this, void 0, void 0, function* () {
50
45
  idx.value = dbutils.keyDigest(idx.value);
package/dist/index.d.ts CHANGED
@@ -1,11 +1,9 @@
1
- import { JacksonOption } from './typings';
2
1
  import { APIController } from './controller/api';
3
2
  import { OAuthController } from './controller/oauth';
4
- import { AdminController } from './controller/admin';
3
+ import { JacksonOption } from './typings';
5
4
  export declare const controllers: (opts: JacksonOption) => Promise<{
6
5
  apiController: APIController;
7
6
  oauthController: OAuthController;
8
- adminController: AdminController;
9
7
  }>;
10
8
  export default controllers;
11
9
  export * from './typings';
package/dist/index.js CHANGED
@@ -25,7 +25,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.controllers = void 0;
26
26
  const api_1 = require("./controller/api");
27
27
  const oauth_1 = require("./controller/oauth");
28
- const admin_1 = require("./controller/admin");
29
28
  const db_1 = __importDefault(require("./db/db"));
30
29
  const read_config_1 = __importDefault(require("./read-config"));
31
30
  const defaultOpts = (opts) => {
@@ -55,7 +54,6 @@ const controllers = (opts) => __awaiter(void 0, void 0, void 0, function* () {
55
54
  const codeStore = db.store('oauth:code', opts.db.ttl);
56
55
  const tokenStore = db.store('oauth:token', opts.db.ttl);
57
56
  const apiController = new api_1.APIController({ configStore });
58
- const adminController = new admin_1.AdminController({ configStore });
59
57
  const oauthController = new oauth_1.OAuthController({
60
58
  configStore,
61
59
  sessionStore,
@@ -76,7 +74,6 @@ const controllers = (opts) => __awaiter(void 0, void 0, void 0, function* () {
76
74
  return {
77
75
  apiController,
78
76
  oauthController,
79
- adminController,
80
77
  };
81
78
  });
82
79
  exports.controllers = controllers;
@@ -0,0 +1,2 @@
1
+ declare const increment: (action: string) => void;
2
+ export { increment };
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.increment = void 0;
4
+ const api_metrics_1 = require("@opentelemetry/api-metrics");
5
+ const counters = {
6
+ createConfig: {
7
+ name: 'saml.config.create',
8
+ description: 'Number of SAML config create requests',
9
+ },
10
+ getConfig: {
11
+ name: 'saml.config.get',
12
+ description: 'Number of SAML config get requests',
13
+ },
14
+ deleteConfig: {
15
+ name: 'saml.config.delete',
16
+ description: 'Number of SAML config delete requests',
17
+ },
18
+ oauthAuthorize: {
19
+ name: 'saml.oauth.authorize',
20
+ description: 'Number of SAML oauth authorize requests',
21
+ },
22
+ oauthToken: {
23
+ name: 'saml.oauth.token',
24
+ description: 'Number of SAML oauth token requests',
25
+ },
26
+ oauthUserInfo: {
27
+ name: 'saml.oauth.userinfo',
28
+ description: 'Number of SAML oauth user info requests',
29
+ }
30
+ };
31
+ const createCounter = (action) => {
32
+ const meter = api_metrics_1.metrics.getMeterProvider().getMeter('saml-jackson');
33
+ const counter = counters[action];
34
+ return meter.createCounter(counter.name, {
35
+ description: counter.description,
36
+ });
37
+ };
38
+ const increment = (action) => {
39
+ const counter = createCounter(action);
40
+ counter.add(1);
41
+ };
42
+ exports.increment = increment;
package/dist/typings.d.ts CHANGED
@@ -3,8 +3,6 @@ export declare type IdPConfig = {
3
3
  redirectUrl: string;
4
4
  tenant: string;
5
5
  product: string;
6
- name: string;
7
- description: string;
8
6
  rawMetadata?: string;
9
7
  encodedRawMetadata?: string;
10
8
  };
@@ -15,12 +13,11 @@ export interface OAuth {
15
13
  }
16
14
  export interface IAPIController {
17
15
  config(body: IdPConfig): Promise<OAuth>;
18
- updateConfig(body: any): Promise<void>;
19
16
  getConfig(body: {
20
17
  clientID?: string;
21
18
  tenant?: string;
22
19
  product?: string;
23
- }): Promise<any>;
20
+ }): Promise<Partial<OAuth>>;
24
21
  deleteConfig(body: {
25
22
  clientID?: string;
26
23
  clientSecret?: string;
@@ -38,9 +35,6 @@ export interface IOAuthController {
38
35
  token(body: OAuthTokenReq): Promise<OAuthTokenRes>;
39
36
  userInfo(token: string): Promise<Profile>;
40
37
  }
41
- export interface IAdminController {
42
- getAllConfig(): any;
43
- }
44
38
  export interface OAuthReqBody {
45
39
  response_type: 'code';
46
40
  client_id: string;
@@ -79,14 +73,12 @@ export interface Index {
79
73
  value: string;
80
74
  }
81
75
  export interface DatabaseDriver {
82
- getAll(namespace: string): Promise<unknown[]>;
83
76
  get(namespace: string, key: string): Promise<any>;
84
77
  put(namespace: string, key: string, val: any, ttl: number, ...indexes: Index[]): Promise<any>;
85
78
  delete(namespace: string, key: string): Promise<any>;
86
79
  getByIndex(namespace: string, idx: Index): Promise<any>;
87
80
  }
88
81
  export interface Storable {
89
- getAll(): Promise<unknown[]>;
90
82
  get(key: string): Promise<any>;
91
83
  put(key: string, val: any, ...indexes: Index[]): Promise<any>;
92
84
  delete(key: string): Promise<any>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boxyhq/saml-jackson",
3
- "version": "0.3.6-beta.638",
3
+ "version": "0.3.6-beta.644",
4
4
  "description": "SAML 2.0 service",
5
5
  "keywords": [
6
6
  "SAML 2.0"
@@ -18,9 +18,9 @@
18
18
  ],
19
19
  "scripts": {
20
20
  "build": "tsc -p tsconfig.build.json",
21
- "db:migration:generate:postgres": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js migration:generate --config ormconfig.js -n createdAt",
22
- "db:migration:generate:mysql": "cross-env DB_TYPE=mysql DB_URL=mysql://root:mysql@localhost:3307/mysql ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js migration:generate --config ormconfig.js -n createdAt",
23
- "db:migration:generate:mariadb": "cross-env DB_TYPE=mariadb DB_URL=mariadb://root@localhost:3306/mysql ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js migration:generate --config ormconfig.js -n createdAt",
21
+ "db:migration:generate:postgres": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js migration:generate --config ormconfig.js -n Initial",
22
+ "db:migration:generate:mysql": "cross-env DB_TYPE=mysql DB_URL=mysql://root:mysql@localhost:3307/mysql ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js migration:generate --config ormconfig.js -n Initial",
23
+ "db:migration:generate:mariadb": "cross-env DB_TYPE=mariadb DB_URL=mariadb://root@localhost:3306/mysql ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js migration:generate --config ormconfig.js -n Initial",
24
24
  "db:migration:run:postgres": "ts-node --transpile-only ./node_modules/typeorm/cli.js migration:run",
25
25
  "db:migration:run:mysql": "cross-env DB_TYPE=mysql DB_URL=mysql://root:mysql@localhost:3307/mysql ts-node --transpile-only ./node_modules/typeorm/cli.js migration:run",
26
26
  "db:migration:run:mariadb": "cross-env DB_TYPE=mariadb DB_URL=mariadb://root@localhost:3306/mysql ts-node --transpile-only ./node_modules/typeorm/cli.js migration:run",
@@ -37,15 +37,16 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@boxyhq/saml20": "0.2.0",
40
+ "@opentelemetry/api-metrics": "0.27.0",
40
41
  "@peculiar/webcrypto": "1.2.3",
41
42
  "@peculiar/x509": "1.6.1",
42
43
  "cors": "2.8.5",
43
44
  "express": "4.17.2",
44
- "mongodb": "4.3.0",
45
+ "mongodb": "4.3.1",
45
46
  "mysql2": "2.3.3",
46
- "pg": "8.7.1",
47
- "rambda": "7.0.1",
48
- "redis": "4.0.1",
47
+ "pg": "8.7.3",
48
+ "rambda": "7.0.2",
49
+ "redis": "4.0.3",
49
50
  "reflect-metadata": "0.1.13",
50
51
  "ripemd160": "2.0.2",
51
52
  "thumbprint": "0.0.1",
@@ -56,20 +57,20 @@
56
57
  },
57
58
  "devDependencies": {
58
59
  "@types/express": "4.17.13",
59
- "@types/node": "16.11.17",
60
- "@types/sinon": "10.0.6",
60
+ "@types/node": "17.0.16",
61
+ "@types/sinon": "10.0.11",
61
62
  "@types/tap": "15.0.5",
62
- "@typescript-eslint/eslint-plugin": "5.8.1",
63
- "@typescript-eslint/parser": "5.8.1",
63
+ "@typescript-eslint/eslint-plugin": "5.11.0",
64
+ "@typescript-eslint/parser": "5.11.0",
64
65
  "cross-env": "7.0.3",
65
- "eslint": "8.5.0",
66
+ "eslint": "8.8.0",
66
67
  "eslint-config-prettier": "8.3.0",
67
68
  "prettier": "2.5.1",
68
- "sinon": "12.0.1",
69
+ "sinon": "13.0.1",
69
70
  "tap": "15.1.6",
70
- "ts-node": "10.4.0",
71
+ "ts-node": "10.5.0",
71
72
  "tsconfig-paths": "3.12.0",
72
- "typescript": "4.5.4"
73
+ "typescript": "4.5.5"
73
74
  },
74
75
  "engines": {
75
76
  "node": ">=14.x"
@@ -1,8 +0,0 @@
1
- import { IAdminController, Storable, OAuth } from '../typings';
2
- export declare class AdminController implements IAdminController {
3
- configStore: Storable;
4
- constructor({ configStore }: {
5
- configStore: any;
6
- });
7
- getAllConfig(): Promise<Partial<OAuth>[]>;
8
- }
@@ -1,27 +0,0 @@
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
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.AdminController = void 0;
13
- class AdminController {
14
- constructor({ configStore }) {
15
- this.configStore = configStore;
16
- }
17
- getAllConfig() {
18
- return __awaiter(this, void 0, void 0, function* () {
19
- const configList = (yield this.configStore.getAll());
20
- if (!configList || !configList.length) {
21
- return [];
22
- }
23
- return configList;
24
- });
25
- }
26
- }
27
- exports.AdminController = AdminController;
@@ -1,16 +0,0 @@
1
- import {MigrationInterface, QueryRunner} from "typeorm";
2
-
3
- export class createdAt1644332636666 implements MigrationInterface {
4
- name = 'createdAt1644332636666'
5
-
6
- public async up(queryRunner: QueryRunner): Promise<void> {
7
- await queryRunner.query(`ALTER TABLE \`jackson_store\` ADD \`createdAt\` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP()`);
8
- await queryRunner.query(`ALTER TABLE \`jackson_store\` ADD \`modifiedAt\` timestamp NULL`);
9
- }
10
-
11
- public async down(queryRunner: QueryRunner): Promise<void> {
12
- await queryRunner.query(`ALTER TABLE \`jackson_store\` DROP COLUMN \`modifiedAt\``);
13
- await queryRunner.query(`ALTER TABLE \`jackson_store\` DROP COLUMN \`createdAt\``);
14
- }
15
-
16
- }
@@ -1,16 +0,0 @@
1
- import {MigrationInterface, QueryRunner} from "typeorm";
2
-
3
- export class createdAt1644332641078 implements MigrationInterface {
4
- name = 'createdAt1644332641078'
5
-
6
- public async up(queryRunner: QueryRunner): Promise<void> {
7
- await queryRunner.query(`ALTER TABLE \`jackson_store\` ADD \`createdAt\` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP`);
8
- await queryRunner.query(`ALTER TABLE \`jackson_store\` ADD \`modifiedAt\` timestamp NULL`);
9
- }
10
-
11
- public async down(queryRunner: QueryRunner): Promise<void> {
12
- await queryRunner.query(`ALTER TABLE \`jackson_store\` DROP COLUMN \`modifiedAt\``);
13
- await queryRunner.query(`ALTER TABLE \`jackson_store\` DROP COLUMN \`createdAt\``);
14
- }
15
-
16
- }
@@ -1,16 +0,0 @@
1
- import {MigrationInterface, QueryRunner} from "typeorm";
2
-
3
- export class createdAt1644332647279 implements MigrationInterface {
4
- name = 'createdAt1644332647279'
5
-
6
- public async up(queryRunner: QueryRunner): Promise<void> {
7
- await queryRunner.query(`ALTER TABLE "jackson_store" ADD "createdAt" TIMESTAMP NOT NULL DEFAULT now()`);
8
- await queryRunner.query(`ALTER TABLE "jackson_store" ADD "modifiedAt" TIMESTAMP`);
9
- }
10
-
11
- public async down(queryRunner: QueryRunner): Promise<void> {
12
- await queryRunner.query(`ALTER TABLE "jackson_store" DROP COLUMN "modifiedAt"`);
13
- await queryRunner.query(`ALTER TABLE "jackson_store" DROP COLUMN "createdAt"`);
14
- }
15
-
16
- }