@boxyhq/saml-jackson 0.3.8 → 0.4.2
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/dist/controller/admin.d.ts +8 -0
- package/dist/controller/admin.js +27 -0
- package/dist/controller/api.d.ts +112 -14
- package/dist/controller/api.js +182 -18
- package/dist/db/db.d.ts +1 -0
- package/dist/db/db.js +9 -0
- package/dist/db/mem.d.ts +1 -0
- package/dist/db/mem.js +19 -0
- package/dist/db/mongo.d.ts +1 -0
- package/dist/db/mongo.js +23 -2
- package/dist/db/redis.d.ts +1 -0
- package/dist/db/redis.js +20 -0
- package/dist/db/sql/entity/JacksonStore.d.ts +2 -0
- package/dist/db/sql/entity/JacksonStore.js +13 -0
- package/dist/db/sql/sql.d.ts +1 -0
- package/dist/db/sql/sql.js +18 -1
- package/dist/db/store.js +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/saml/saml.js +1 -11
- package/dist/typings.d.ts +9 -1
- package/migration/mariadb/1644332636666-createdAt.ts +16 -0
- package/migration/mysql/1644332641078-createdAt.ts +16 -0
- package/migration/postgres/1644332647279-createdAt.ts +16 -0
- package/package.json +5 -5
@@ -0,0 +1,27 @@
|
|
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;
|
package/dist/controller/api.d.ts
CHANGED
@@ -18,35 +18,42 @@ 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
|
+
* - name: description
|
26
|
+
* description: A short description for the config not more than 100 characters
|
27
|
+
* type: string
|
28
|
+
* in: formData
|
21
29
|
* - name: encodedRawMetadata
|
22
30
|
* description: Base64 encoding of the XML metadata
|
23
31
|
* in: formData
|
24
|
-
*
|
32
|
+
* type: string
|
33
|
+
* - name: rawMetadata
|
34
|
+
* description: Raw XML metadata
|
35
|
+
* in: formData
|
25
36
|
* type: string
|
26
37
|
* - name: defaultRedirectUrl
|
27
38
|
* description: The redirect URL to use in the IdP login flow
|
28
39
|
* in: formData
|
29
40
|
* required: true
|
30
41
|
* type: string
|
31
|
-
* example: http://localhost:3000/login/saml
|
32
42
|
* - name: redirectUrl
|
33
43
|
* description: JSON encoded array containing a list of allowed redirect URLs
|
34
44
|
* in: formData
|
35
45
|
* required: true
|
36
46
|
* type: string
|
37
|
-
* example: '["http://localhost:3000/*"]'
|
38
47
|
* - name: tenant
|
39
48
|
* description: Tenant
|
40
49
|
* in: formData
|
41
50
|
* required: true
|
42
51
|
* type: string
|
43
|
-
* example: boxyhq.com
|
44
52
|
* - name: product
|
45
53
|
* description: Product
|
46
54
|
* in: formData
|
47
55
|
* required: true
|
48
56
|
* type: string
|
49
|
-
* example: demo
|
50
57
|
* responses:
|
51
58
|
* 200:
|
52
59
|
* description: Success
|
@@ -63,10 +70,79 @@ export declare class APIController implements IAPIController {
|
|
63
70
|
* client_id: 8958e13053832b5af58fdf2ee83f35f5d013dc74
|
64
71
|
* client_secret: 13f01f4df5b01770c616e682d14d3ba23f20948cfa89b1d7
|
65
72
|
* type: accounts.google.com
|
73
|
+
* 400:
|
74
|
+
* description: Please provide rawMetadata or encodedRawMetadata | Please provide a defaultRedirectUrl | Please provide redirectUrl | Please provide tenant | Please provide product | Please provide a friendly name | Description should not exceed 100 characters
|
66
75
|
* 401:
|
67
76
|
* description: Unauthorized
|
68
77
|
*/
|
69
78
|
config(body: IdPConfig): Promise<OAuth>;
|
79
|
+
/**
|
80
|
+
* @swagger
|
81
|
+
*
|
82
|
+
* /api/v1/saml/config:
|
83
|
+
* patch:
|
84
|
+
* summary: Update SAML configuration
|
85
|
+
* operationId: update-saml-config
|
86
|
+
* tags: [SAML Config]
|
87
|
+
* consumes:
|
88
|
+
* - application/json
|
89
|
+
* - application/x-www-form-urlencoded
|
90
|
+
* parameters:
|
91
|
+
* - name: clientID
|
92
|
+
* description: Client ID for the config
|
93
|
+
* type: string
|
94
|
+
* in: formData
|
95
|
+
* required: true
|
96
|
+
* - name: clientSecret
|
97
|
+
* description: Client Secret for the config
|
98
|
+
* type: string
|
99
|
+
* in: formData
|
100
|
+
* required: true
|
101
|
+
* - name: name
|
102
|
+
* description: Name/identifier for the config
|
103
|
+
* type: string
|
104
|
+
* in: formData
|
105
|
+
* - name: description
|
106
|
+
* description: A short description for the config not more than 100 characters
|
107
|
+
* type: string
|
108
|
+
* in: formData
|
109
|
+
* - name: encodedRawMetadata
|
110
|
+
* description: Base64 encoding of the XML metadata
|
111
|
+
* in: formData
|
112
|
+
* type: string
|
113
|
+
* - name: rawMetadata
|
114
|
+
* description: Raw XML metadata
|
115
|
+
* in: formData
|
116
|
+
* type: string
|
117
|
+
* - name: defaultRedirectUrl
|
118
|
+
* description: The redirect URL to use in the IdP login flow
|
119
|
+
* in: formData
|
120
|
+
* required: true
|
121
|
+
* type: string
|
122
|
+
* - name: redirectUrl
|
123
|
+
* description: JSON encoded array containing a list of allowed redirect URLs
|
124
|
+
* in: formData
|
125
|
+
* required: true
|
126
|
+
* type: string
|
127
|
+
* - name: tenant
|
128
|
+
* description: Tenant
|
129
|
+
* in: formData
|
130
|
+
* required: true
|
131
|
+
* type: string
|
132
|
+
* - name: product
|
133
|
+
* description: Product
|
134
|
+
* in: formData
|
135
|
+
* required: true
|
136
|
+
* type: string
|
137
|
+
* responses:
|
138
|
+
* 204:
|
139
|
+
* description: Success
|
140
|
+
* 400:
|
141
|
+
* description: Please provide clientID | Please provide clientSecret | clientSecret mismatch | Tenant/Product config mismatch with IdP metadata | Description should not exceed 100 characters
|
142
|
+
* 401:
|
143
|
+
* description: Unauthorized
|
144
|
+
*/
|
145
|
+
updateConfig(body: any): Promise<void>;
|
70
146
|
/**
|
71
147
|
* @swagger
|
72
148
|
*
|
@@ -81,12 +157,10 @@ export declare class APIController implements IAPIController {
|
|
81
157
|
* name: tenant
|
82
158
|
* type: string
|
83
159
|
* description: Tenant
|
84
|
-
* example: boxyhq.com
|
85
160
|
* - in: query
|
86
161
|
* name: product
|
87
162
|
* type: string
|
88
163
|
* description: Product
|
89
|
-
* example: demo
|
90
164
|
* - in: query
|
91
165
|
* name: clientID
|
92
166
|
* type: string
|
@@ -96,11 +170,35 @@ export declare class APIController implements IAPIController {
|
|
96
170
|
* description: Success
|
97
171
|
* schema:
|
98
172
|
* type: object
|
99
|
-
* properties:
|
100
|
-
* provider:
|
101
|
-
* type: string
|
102
173
|
* example:
|
103
|
-
*
|
174
|
+
* {
|
175
|
+
* "config": {
|
176
|
+
* "idpMetadata": {
|
177
|
+
* "sso": {
|
178
|
+
* "postUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxxx/sso/saml",
|
179
|
+
* "redirectUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxxx/sso/saml"
|
180
|
+
* },
|
181
|
+
* "entityID": "http://www.okta.com/xxxxxxxxxxxxx",
|
182
|
+
* "thumbprint": "Eo+eUi3UM3XIMkFFtdVK3yJ5vO9f7YZdasdasdad",
|
183
|
+
* "loginType": "idp",
|
184
|
+
* "provider": "okta.com"
|
185
|
+
* },
|
186
|
+
* "defaultRedirectUrl": "https://hoppscotch.io/",
|
187
|
+
* "redirectUrl": ["https://hoppscotch.io/"],
|
188
|
+
* "tenant": "hoppscotch.io",
|
189
|
+
* "product": "API Engine",
|
190
|
+
* "name": "Hoppscotch-SP",
|
191
|
+
* "description": "SP for hoppscotch.io",
|
192
|
+
* "clientID": "Xq8AJt3yYAxmXizsCWmUBDRiVP1iTC8Y/otnvFIMitk",
|
193
|
+
* "clientSecret": "00e3e11a3426f97d8000000738300009130cd45419c5943",
|
194
|
+
* "certs": {
|
195
|
+
* "publicKey": "-----BEGIN CERTIFICATE-----.......-----END CERTIFICATE-----",
|
196
|
+
* "privateKey": "-----BEGIN PRIVATE KEY-----......-----END PRIVATE KEY-----"
|
197
|
+
* }
|
198
|
+
* }
|
199
|
+
* }
|
200
|
+
* '400':
|
201
|
+
* description: Please provide `clientID` or `tenant` and `product`.
|
104
202
|
* '401':
|
105
203
|
* description: Unauthorized
|
106
204
|
*/
|
@@ -108,7 +206,7 @@ export declare class APIController implements IAPIController {
|
|
108
206
|
clientID: string;
|
109
207
|
tenant: string;
|
110
208
|
product: string;
|
111
|
-
}): Promise<
|
209
|
+
}): Promise<any>;
|
112
210
|
/**
|
113
211
|
* @swagger
|
114
212
|
* /api/v1/saml/config:
|
@@ -134,15 +232,15 @@ export declare class APIController implements IAPIController {
|
|
134
232
|
* in: formData
|
135
233
|
* type: string
|
136
234
|
* description: Tenant
|
137
|
-
* example: boxyhq.com
|
138
235
|
* - name: product
|
139
236
|
* in: formData
|
140
237
|
* type: string
|
141
238
|
* description: Product
|
142
|
-
* example: demo
|
143
239
|
* responses:
|
144
240
|
* '200':
|
145
241
|
* description: Success
|
242
|
+
* '400':
|
243
|
+
* description: clientSecret mismatch | Please provide `clientID` and `clientSecret` or `tenant` and `product`.'
|
146
244
|
* '401':
|
147
245
|
* description: Unauthorized
|
148
246
|
*/
|
package/dist/controller/api.js
CHANGED
@@ -27,6 +27,17 @@ 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
|
+
};
|
30
41
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
31
42
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
32
43
|
};
|
@@ -44,7 +55,7 @@ class APIController {
|
|
44
55
|
this.configStore = configStore;
|
45
56
|
}
|
46
57
|
_validateIdPConfig(body) {
|
47
|
-
const { encodedRawMetadata, rawMetadata, defaultRedirectUrl, redirectUrl, tenant, product } = body;
|
58
|
+
const { encodedRawMetadata, rawMetadata, defaultRedirectUrl, redirectUrl, tenant, product, description } = body;
|
48
59
|
if (!rawMetadata && !encodedRawMetadata) {
|
49
60
|
throw new error_1.JacksonError('Please provide rawMetadata or encodedRawMetadata', 400);
|
50
61
|
}
|
@@ -60,6 +71,9 @@ class APIController {
|
|
60
71
|
if (!product) {
|
61
72
|
throw new error_1.JacksonError('Please provide product', 400);
|
62
73
|
}
|
74
|
+
if (description && description.length > 100) {
|
75
|
+
throw new error_1.JacksonError('Description should not exceed 100 characters', 400);
|
76
|
+
}
|
63
77
|
}
|
64
78
|
/**
|
65
79
|
* @swagger
|
@@ -74,35 +88,42 @@ class APIController {
|
|
74
88
|
* consumes:
|
75
89
|
* - application/x-www-form-urlencoded
|
76
90
|
* parameters:
|
91
|
+
* - name: name
|
92
|
+
* description: Name/identifier for the config
|
93
|
+
* type: string
|
94
|
+
* in: formData
|
95
|
+
* - name: description
|
96
|
+
* description: A short description for the config not more than 100 characters
|
97
|
+
* type: string
|
98
|
+
* in: formData
|
77
99
|
* - name: encodedRawMetadata
|
78
100
|
* description: Base64 encoding of the XML metadata
|
79
101
|
* in: formData
|
80
|
-
*
|
102
|
+
* type: string
|
103
|
+
* - name: rawMetadata
|
104
|
+
* description: Raw XML metadata
|
105
|
+
* in: formData
|
81
106
|
* type: string
|
82
107
|
* - name: defaultRedirectUrl
|
83
108
|
* description: The redirect URL to use in the IdP login flow
|
84
109
|
* in: formData
|
85
110
|
* required: true
|
86
111
|
* type: string
|
87
|
-
* example: http://localhost:3000/login/saml
|
88
112
|
* - name: redirectUrl
|
89
113
|
* description: JSON encoded array containing a list of allowed redirect URLs
|
90
114
|
* in: formData
|
91
115
|
* required: true
|
92
116
|
* type: string
|
93
|
-
* example: '["http://localhost:3000/*"]'
|
94
117
|
* - name: tenant
|
95
118
|
* description: Tenant
|
96
119
|
* in: formData
|
97
120
|
* required: true
|
98
121
|
* type: string
|
99
|
-
* example: boxyhq.com
|
100
122
|
* - name: product
|
101
123
|
* description: Product
|
102
124
|
* in: formData
|
103
125
|
* required: true
|
104
126
|
* type: string
|
105
|
-
* example: demo
|
106
127
|
* responses:
|
107
128
|
* 200:
|
108
129
|
* description: Success
|
@@ -119,12 +140,14 @@ class APIController {
|
|
119
140
|
* client_id: 8958e13053832b5af58fdf2ee83f35f5d013dc74
|
120
141
|
* client_secret: 13f01f4df5b01770c616e682d14d3ba23f20948cfa89b1d7
|
121
142
|
* type: accounts.google.com
|
143
|
+
* 400:
|
144
|
+
* description: Please provide rawMetadata or encodedRawMetadata | Please provide a defaultRedirectUrl | Please provide redirectUrl | Please provide tenant | Please provide product | Please provide a friendly name | Description should not exceed 100 characters
|
122
145
|
* 401:
|
123
146
|
* description: Unauthorized
|
124
147
|
*/
|
125
148
|
config(body) {
|
126
149
|
return __awaiter(this, void 0, void 0, function* () {
|
127
|
-
const { encodedRawMetadata, rawMetadata, defaultRedirectUrl, redirectUrl, tenant, product } = body;
|
150
|
+
const { encodedRawMetadata, rawMetadata, defaultRedirectUrl, redirectUrl, tenant, product, name, description, } = body;
|
128
151
|
metrics.increment('createConfig');
|
129
152
|
this._validateIdPConfig(body);
|
130
153
|
let metaData = rawMetadata;
|
@@ -157,6 +180,8 @@ class APIController {
|
|
157
180
|
redirectUrl: JSON.parse(redirectUrl),
|
158
181
|
tenant,
|
159
182
|
product,
|
183
|
+
name,
|
184
|
+
description,
|
160
185
|
clientID,
|
161
186
|
clientSecret,
|
162
187
|
certs,
|
@@ -176,6 +201,123 @@ class APIController {
|
|
176
201
|
};
|
177
202
|
});
|
178
203
|
}
|
204
|
+
/**
|
205
|
+
* @swagger
|
206
|
+
*
|
207
|
+
* /api/v1/saml/config:
|
208
|
+
* patch:
|
209
|
+
* summary: Update SAML configuration
|
210
|
+
* operationId: update-saml-config
|
211
|
+
* tags: [SAML Config]
|
212
|
+
* consumes:
|
213
|
+
* - application/json
|
214
|
+
* - application/x-www-form-urlencoded
|
215
|
+
* parameters:
|
216
|
+
* - name: clientID
|
217
|
+
* description: Client ID for the config
|
218
|
+
* type: string
|
219
|
+
* in: formData
|
220
|
+
* required: true
|
221
|
+
* - name: clientSecret
|
222
|
+
* description: Client Secret for the config
|
223
|
+
* type: string
|
224
|
+
* in: formData
|
225
|
+
* required: true
|
226
|
+
* - name: name
|
227
|
+
* description: Name/identifier for the config
|
228
|
+
* type: string
|
229
|
+
* in: formData
|
230
|
+
* - name: description
|
231
|
+
* description: A short description for the config not more than 100 characters
|
232
|
+
* type: string
|
233
|
+
* in: formData
|
234
|
+
* - name: encodedRawMetadata
|
235
|
+
* description: Base64 encoding of the XML metadata
|
236
|
+
* in: formData
|
237
|
+
* type: string
|
238
|
+
* - name: rawMetadata
|
239
|
+
* description: Raw XML metadata
|
240
|
+
* in: formData
|
241
|
+
* type: string
|
242
|
+
* - name: defaultRedirectUrl
|
243
|
+
* description: The redirect URL to use in the IdP login flow
|
244
|
+
* in: formData
|
245
|
+
* required: true
|
246
|
+
* type: string
|
247
|
+
* - name: redirectUrl
|
248
|
+
* description: JSON encoded array containing a list of allowed redirect URLs
|
249
|
+
* in: formData
|
250
|
+
* required: true
|
251
|
+
* type: string
|
252
|
+
* - name: tenant
|
253
|
+
* description: Tenant
|
254
|
+
* in: formData
|
255
|
+
* required: true
|
256
|
+
* type: string
|
257
|
+
* - name: product
|
258
|
+
* description: Product
|
259
|
+
* in: formData
|
260
|
+
* required: true
|
261
|
+
* type: string
|
262
|
+
* responses:
|
263
|
+
* 204:
|
264
|
+
* description: Success
|
265
|
+
* 400:
|
266
|
+
* description: Please provide clientID | Please provide clientSecret | clientSecret mismatch | Tenant/Product config mismatch with IdP metadata | Description should not exceed 100 characters
|
267
|
+
* 401:
|
268
|
+
* description: Unauthorized
|
269
|
+
*/
|
270
|
+
updateConfig(body) {
|
271
|
+
var _a;
|
272
|
+
return __awaiter(this, void 0, void 0, function* () {
|
273
|
+
const { encodedRawMetadata, // could be empty
|
274
|
+
rawMetadata, // could be empty
|
275
|
+
defaultRedirectUrl, redirectUrl, name, description } = body, clientInfo = __rest(body, ["encodedRawMetadata", "rawMetadata", "defaultRedirectUrl", "redirectUrl", "name", "description"]);
|
276
|
+
if (!(clientInfo === null || clientInfo === void 0 ? void 0 : clientInfo.clientID)) {
|
277
|
+
throw new error_1.JacksonError('Please provide clientID', 400);
|
278
|
+
}
|
279
|
+
if (!(clientInfo === null || clientInfo === void 0 ? void 0 : clientInfo.clientSecret)) {
|
280
|
+
throw new error_1.JacksonError('Please provide clientSecret', 400);
|
281
|
+
}
|
282
|
+
if (description && description.length > 100) {
|
283
|
+
throw new error_1.JacksonError('Description should not exceed 100 characters', 400);
|
284
|
+
}
|
285
|
+
const _currentConfig = (_a = (yield this.getConfig(clientInfo))) === null || _a === void 0 ? void 0 : _a.config;
|
286
|
+
if (_currentConfig.clientSecret !== (clientInfo === null || clientInfo === void 0 ? void 0 : clientInfo.clientSecret)) {
|
287
|
+
throw new error_1.JacksonError('clientSecret mismatch', 400);
|
288
|
+
}
|
289
|
+
let metaData = rawMetadata;
|
290
|
+
if (encodedRawMetadata) {
|
291
|
+
metaData = Buffer.from(encodedRawMetadata, 'base64').toString();
|
292
|
+
}
|
293
|
+
let newMetadata;
|
294
|
+
if (metaData) {
|
295
|
+
newMetadata = yield saml_1.default.parseMetadataAsync(metaData);
|
296
|
+
// extract provider
|
297
|
+
let providerName = extractHostName(newMetadata.entityID);
|
298
|
+
if (!providerName) {
|
299
|
+
providerName = extractHostName(newMetadata.sso.redirectUrl || newMetadata.sso.postUrl);
|
300
|
+
}
|
301
|
+
newMetadata.provider = providerName ? providerName : 'Unknown';
|
302
|
+
}
|
303
|
+
if (newMetadata) {
|
304
|
+
// check if clientID matches with new metadata payload
|
305
|
+
const clientID = dbutils.keyDigest(dbutils.keyFromParts(clientInfo.tenant, clientInfo.product, newMetadata.entityID));
|
306
|
+
if (clientID !== (clientInfo === null || clientInfo === void 0 ? void 0 : clientInfo.clientID)) {
|
307
|
+
throw new error_1.JacksonError('Tenant/Product config mismatch with IdP metadata', 400);
|
308
|
+
}
|
309
|
+
}
|
310
|
+
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 }), {
|
311
|
+
// secondary index on entityID
|
312
|
+
name: utils_1.IndexNames.EntityID,
|
313
|
+
value: _currentConfig.idpMetadata.entityID,
|
314
|
+
}, {
|
315
|
+
// secondary index on tenant + product
|
316
|
+
name: utils_1.IndexNames.TenantProduct,
|
317
|
+
value: dbutils.keyFromParts(_currentConfig.tenant, _currentConfig.product),
|
318
|
+
});
|
319
|
+
});
|
320
|
+
}
|
179
321
|
/**
|
180
322
|
* @swagger
|
181
323
|
*
|
@@ -190,12 +332,10 @@ class APIController {
|
|
190
332
|
* name: tenant
|
191
333
|
* type: string
|
192
334
|
* description: Tenant
|
193
|
-
* example: boxyhq.com
|
194
335
|
* - in: query
|
195
336
|
* name: product
|
196
337
|
* type: string
|
197
338
|
* description: Product
|
198
|
-
* example: demo
|
199
339
|
* - in: query
|
200
340
|
* name: clientID
|
201
341
|
* type: string
|
@@ -205,11 +345,35 @@ class APIController {
|
|
205
345
|
* description: Success
|
206
346
|
* schema:
|
207
347
|
* type: object
|
208
|
-
* properties:
|
209
|
-
* provider:
|
210
|
-
* type: string
|
211
348
|
* example:
|
212
|
-
*
|
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` and `product`.
|
213
377
|
* '401':
|
214
378
|
* description: Unauthorized
|
215
379
|
*/
|
@@ -219,7 +383,7 @@ class APIController {
|
|
219
383
|
metrics.increment('getConfig');
|
220
384
|
if (clientID) {
|
221
385
|
const samlConfig = yield this.configStore.get(clientID);
|
222
|
-
return samlConfig ? {
|
386
|
+
return samlConfig ? { config: samlConfig } : {};
|
223
387
|
}
|
224
388
|
if (tenant && product) {
|
225
389
|
const samlConfigs = yield this.configStore.getByIndex({
|
@@ -229,7 +393,7 @@ class APIController {
|
|
229
393
|
if (!samlConfigs || !samlConfigs.length) {
|
230
394
|
return {};
|
231
395
|
}
|
232
|
-
return {
|
396
|
+
return { config: samlConfigs[0] };
|
233
397
|
}
|
234
398
|
throw new error_1.JacksonError('Please provide `clientID` or `tenant` and `product`.', 400);
|
235
399
|
});
|
@@ -259,15 +423,15 @@ class APIController {
|
|
259
423
|
* in: formData
|
260
424
|
* type: string
|
261
425
|
* description: Tenant
|
262
|
-
* example: boxyhq.com
|
263
426
|
* - name: product
|
264
427
|
* in: formData
|
265
428
|
* type: string
|
266
429
|
* description: Product
|
267
|
-
* example: demo
|
268
430
|
* responses:
|
269
431
|
* '200':
|
270
432
|
* description: Success
|
433
|
+
* '400':
|
434
|
+
* description: clientSecret mismatch | Please provide `clientID` and `clientSecret` or `tenant` and `product`.'
|
271
435
|
* '401':
|
272
436
|
* description: Unauthorized
|
273
437
|
*/
|
@@ -284,7 +448,7 @@ class APIController {
|
|
284
448
|
yield this.configStore.delete(clientID);
|
285
449
|
}
|
286
450
|
else {
|
287
|
-
throw new error_1.JacksonError('clientSecret mismatch
|
451
|
+
throw new error_1.JacksonError('clientSecret mismatch', 400);
|
288
452
|
}
|
289
453
|
return;
|
290
454
|
}
|
package/dist/db/db.d.ts
CHANGED
@@ -4,6 +4,7 @@ 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[]>;
|
7
8
|
getByIndex(namespace: string, idx: Index): Promise<unknown[]>;
|
8
9
|
put(namespace: string, key: string, val: unknown, ttl?: number, ...indexes: Index[]): Promise<unknown>;
|
9
10
|
delete(namespace: string, key: string): Promise<unknown>;
|
package/dist/db/db.js
CHANGED
@@ -57,6 +57,15 @@ 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
|
+
}
|
60
69
|
getByIndex(namespace, idx) {
|
61
70
|
return __awaiter(this, void 0, void 0, function* () {
|
62
71
|
const res = yield this.db.getByIndex(namespace, idx);
|
package/dist/db/mem.d.ts
CHANGED
@@ -10,6 +10,7 @@ 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[]>;
|
13
14
|
getByIndex(namespace: string, idx: Index): Promise<any>;
|
14
15
|
put(namespace: string, key: string, val: Encrypted, ttl?: number, ...indexes: any[]): Promise<any>;
|
15
16
|
delete(namespace: string, key: string): Promise<any>;
|
package/dist/db/mem.js
CHANGED
@@ -66,6 +66,21 @@ 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
|
+
}
|
69
84
|
getByIndex(namespace, idx) {
|
70
85
|
return __awaiter(this, void 0, void 0, function* () {
|
71
86
|
const dbKeys = yield this.indexes[dbutils.keyForIndex(namespace, idx)];
|
@@ -80,6 +95,10 @@ class Mem {
|
|
80
95
|
return __awaiter(this, void 0, void 0, function* () {
|
81
96
|
const k = dbutils.key(namespace, key);
|
82
97
|
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)
|
83
102
|
if (ttl) {
|
84
103
|
this.ttlStore[k] = {
|
85
104
|
namespace,
|
package/dist/db/mongo.d.ts
CHANGED
@@ -7,6 +7,7 @@ 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[]>;
|
10
11
|
getByIndex(namespace: string, idx: Index): Promise<any>;
|
11
12
|
put(namespace: string, key: string, val: Encrypted, ttl?: number, ...indexes: any[]): Promise<void>;
|
12
13
|
delete(namespace: string, key: string): Promise<any>;
|
package/dist/db/mongo.js
CHANGED
@@ -36,8 +36,16 @@ class Mongo {
|
|
36
36
|
}
|
37
37
|
init() {
|
38
38
|
return __awaiter(this, void 0, void 0, function* () {
|
39
|
-
|
40
|
-
|
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
|
+
}
|
41
49
|
this.db = this.client.db();
|
42
50
|
this.collection = this.db.collection('jacksonStore');
|
43
51
|
yield this.collection.createIndex({ indexes: 1 });
|
@@ -56,6 +64,15 @@ class Mongo {
|
|
56
64
|
return null;
|
57
65
|
});
|
58
66
|
}
|
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
|
+
}
|
59
76
|
getByIndex(namespace, idx) {
|
60
77
|
return __awaiter(this, void 0, void 0, function* () {
|
61
78
|
const docs = yield this.collection
|
@@ -86,8 +103,12 @@ class Mongo {
|
|
86
103
|
}
|
87
104
|
doc.indexes.push(idxKey);
|
88
105
|
}
|
106
|
+
doc.modifiedAt = new Date().toISOString();
|
89
107
|
yield this.collection.updateOne({ _id: dbutils.key(namespace, key) }, {
|
90
108
|
$set: doc,
|
109
|
+
$setOnInsert: {
|
110
|
+
createdAt: new Date().toISOString(),
|
111
|
+
},
|
91
112
|
}, { upsert: true });
|
92
113
|
});
|
93
114
|
}
|
package/dist/db/redis.d.ts
CHANGED
@@ -5,6 +5,7 @@ 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[]>;
|
8
9
|
getByIndex(namespace: string, idx: Index): Promise<any>;
|
9
10
|
put(namespace: string, key: string, val: Encrypted, ttl?: number, ...indexes: any[]): Promise<void>;
|
10
11
|
delete(namespace: string, key: string): Promise<any>;
|
package/dist/db/redis.js
CHANGED
@@ -57,6 +57,26 @@ 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
|
+
}
|
60
80
|
getByIndex(namespace, idx) {
|
61
81
|
return __awaiter(this, void 0, void 0, function* () {
|
62
82
|
const dbKeys = yield this.client.sMembers(dbutils.keyForIndex(namespace, idx));
|
@@ -36,6 +36,19 @@ __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);
|
39
52
|
JacksonStore = __decorate([
|
40
53
|
(0, typeorm_1.Entity)()
|
41
54
|
], JacksonStore);
|
package/dist/db/sql/sql.d.ts
CHANGED
@@ -10,6 +10,7 @@ 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[]>;
|
13
14
|
getByIndex(namespace: string, idx: Index): Promise<any>;
|
14
15
|
put(namespace: string, key: string, val: Encrypted, ttl?: number, ...indexes: any[]): Promise<void>;
|
15
16
|
delete(namespace: string, key: string): Promise<any>;
|
package/dist/db/sql/sql.js
CHANGED
@@ -95,7 +95,7 @@ class Sql {
|
|
95
95
|
}
|
96
96
|
get(namespace, key) {
|
97
97
|
return __awaiter(this, void 0, void 0, function* () {
|
98
|
-
|
98
|
+
const res = yield this.storeRepository.findOne({
|
99
99
|
key: dbutils.key(namespace, key),
|
100
100
|
});
|
101
101
|
if (res && res.value) {
|
@@ -108,6 +108,22 @@ 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
|
+
}
|
111
127
|
getByIndex(namespace, idx) {
|
112
128
|
return __awaiter(this, void 0, void 0, function* () {
|
113
129
|
const res = yield this.indexRepository.find({
|
@@ -135,6 +151,7 @@ class Sql {
|
|
135
151
|
store.value = val.value;
|
136
152
|
store.iv = val.iv;
|
137
153
|
store.tag = val.tag;
|
154
|
+
store.modifiedAt = new Date().toISOString();
|
138
155
|
yield transactionalEntityManager.save(store);
|
139
156
|
if (ttl) {
|
140
157
|
const ttlRec = new JacksonTTL_1.JacksonTTL();
|
package/dist/db/store.js
CHANGED
@@ -40,6 +40,11 @@ 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
|
+
}
|
43
48
|
getByIndex(idx) {
|
44
49
|
return __awaiter(this, void 0, void 0, function* () {
|
45
50
|
idx.value = dbutils.keyDigest(idx.value);
|
package/dist/index.d.ts
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
import { APIController } from './controller/api';
|
2
2
|
import { OAuthController } from './controller/oauth';
|
3
|
+
import { AdminController } from './controller/admin';
|
3
4
|
import { JacksonOption } from './typings';
|
4
5
|
export declare const controllers: (opts: JacksonOption) => Promise<{
|
5
6
|
apiController: APIController;
|
6
7
|
oauthController: OAuthController;
|
8
|
+
adminController: AdminController;
|
7
9
|
}>;
|
8
10
|
export default controllers;
|
9
11
|
export * from './typings';
|
package/dist/index.js
CHANGED
@@ -25,6 +25,7 @@ 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");
|
28
29
|
const db_1 = __importDefault(require("./db/db"));
|
29
30
|
const read_config_1 = __importDefault(require("./read-config"));
|
30
31
|
const defaultOpts = (opts) => {
|
@@ -55,6 +56,7 @@ const controllers = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
55
56
|
const codeStore = db.store('oauth:code', opts.db.ttl);
|
56
57
|
const tokenStore = db.store('oauth:token', opts.db.ttl);
|
57
58
|
const apiController = new api_1.APIController({ configStore });
|
59
|
+
const adminController = new admin_1.AdminController({ configStore });
|
58
60
|
const oauthController = new oauth_1.OAuthController({
|
59
61
|
configStore,
|
60
62
|
sessionStore,
|
@@ -75,6 +77,7 @@ const controllers = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
75
77
|
return {
|
76
78
|
apiController,
|
77
79
|
oauthController,
|
80
|
+
adminController,
|
78
81
|
};
|
79
82
|
});
|
80
83
|
exports.controllers = controllers;
|
package/dist/saml/saml.js
CHANGED
@@ -55,17 +55,7 @@ function PubKeyInfo(pubKey) {
|
|
55
55
|
this.getKeyInfo = function (_key, prefix) {
|
56
56
|
prefix = prefix || '';
|
57
57
|
prefix = prefix ? prefix + ':' : prefix;
|
58
|
-
return
|
59
|
-
prefix +
|
60
|
-
'X509Data><' +
|
61
|
-
prefix +
|
62
|
-
'X509Certificate>' +
|
63
|
-
this.pubKey +
|
64
|
-
'</' +
|
65
|
-
prefix +
|
66
|
-
'X509Certificate></' +
|
67
|
-
prefix +
|
68
|
-
'X509Data>');
|
58
|
+
return `<${prefix}X509Data><${prefix}X509Certificate>${this.pubKey}</${prefix}X509Certificate</${prefix}X509Data>`;
|
69
59
|
};
|
70
60
|
}
|
71
61
|
const signRequest = (xml, signingKey, publicKey) => {
|
package/dist/typings.d.ts
CHANGED
@@ -3,6 +3,8 @@ export declare type IdPConfig = {
|
|
3
3
|
redirectUrl: string;
|
4
4
|
tenant: string;
|
5
5
|
product: string;
|
6
|
+
name: string;
|
7
|
+
description: string;
|
6
8
|
rawMetadata?: string;
|
7
9
|
encodedRawMetadata?: string;
|
8
10
|
};
|
@@ -13,11 +15,12 @@ export interface OAuth {
|
|
13
15
|
}
|
14
16
|
export interface IAPIController {
|
15
17
|
config(body: IdPConfig): Promise<OAuth>;
|
18
|
+
updateConfig(body: any): Promise<void>;
|
16
19
|
getConfig(body: {
|
17
20
|
clientID?: string;
|
18
21
|
tenant?: string;
|
19
22
|
product?: string;
|
20
|
-
}): Promise<
|
23
|
+
}): Promise<any>;
|
21
24
|
deleteConfig(body: {
|
22
25
|
clientID?: string;
|
23
26
|
clientSecret?: string;
|
@@ -36,6 +39,9 @@ export interface IOAuthController {
|
|
36
39
|
token(body: OAuthTokenReq): Promise<OAuthTokenRes>;
|
37
40
|
userInfo(token: string): Promise<Profile>;
|
38
41
|
}
|
42
|
+
export interface IAdminController {
|
43
|
+
getAllConfig(): any;
|
44
|
+
}
|
39
45
|
export interface OAuthReqBody {
|
40
46
|
response_type: 'code';
|
41
47
|
client_id: string;
|
@@ -74,12 +80,14 @@ export interface Index {
|
|
74
80
|
value: string;
|
75
81
|
}
|
76
82
|
export interface DatabaseDriver {
|
83
|
+
getAll(namespace: string): Promise<unknown[]>;
|
77
84
|
get(namespace: string, key: string): Promise<any>;
|
78
85
|
put(namespace: string, key: string, val: any, ttl: number, ...indexes: Index[]): Promise<any>;
|
79
86
|
delete(namespace: string, key: string): Promise<any>;
|
80
87
|
getByIndex(namespace: string, idx: Index): Promise<any>;
|
81
88
|
}
|
82
89
|
export interface Storable {
|
90
|
+
getAll(): Promise<unknown[]>;
|
83
91
|
get(key: string): Promise<any>;
|
84
92
|
put(key: string, val: any, ...indexes: Index[]): Promise<any>;
|
85
93
|
delete(key: string): Promise<any>;
|
@@ -0,0 +1,16 @@
|
|
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
|
+
}
|
@@ -0,0 +1,16 @@
|
|
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
|
+
}
|
@@ -0,0 +1,16 @@
|
|
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
|
+
}
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@boxyhq/saml-jackson",
|
3
|
-
"version": "0.
|
4
|
-
"description": "SAML
|
3
|
+
"version": "0.4.2",
|
4
|
+
"description": "SAML Jackson library",
|
5
5
|
"keywords": [
|
6
6
|
"SAML 2.0"
|
7
7
|
],
|
@@ -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
|
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
|
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
|
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",
|
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",
|