@workos-inc/node 2.11.0 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/common/interfaces/workos-options.interface.d.ts +2 -0
- package/lib/organizations/interfaces/create-organization-options.interface.d.ts +3 -0
- package/lib/organizations/organizations.d.ts +2 -2
- package/lib/organizations/organizations.js +2 -2
- package/lib/organizations/organizations.spec.js +17 -0
- package/lib/portal/interfaces/generate-portal-link-intent.interface.d.ts +3 -2
- package/lib/portal/interfaces/generate-portal-link-intent.interface.js +2 -1
- package/lib/portal/portal.spec.js +17 -0
- package/lib/webhooks/fixtures/webhook.json +1 -1
- package/lib/webhooks/webhooks.d.ts +9 -4
- package/lib/webhooks/webhooks.spec.js +30 -7
- package/lib/workos.js +3 -8
- package/lib/workos.spec.js +16 -0
- package/package.json +4 -4
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { PostOptions } from '../../common/interfaces';
|
|
1
2
|
export interface CreateOrganizationOptions {
|
|
2
3
|
name: string;
|
|
3
4
|
allow_profiles_outside_organization?: boolean;
|
|
4
5
|
domains?: string[];
|
|
5
6
|
}
|
|
7
|
+
export interface CreateOrganizationRequestOptions extends Pick<PostOptions, 'idempotencyKey'> {
|
|
8
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { List } from '../common/interfaces/list.interface';
|
|
2
2
|
import { WorkOS } from '../workos';
|
|
3
|
-
import { CreateOrganizationOptions, ListOrganizationsOptions, Organization, UpdateOrganizationOptions } from './interfaces';
|
|
3
|
+
import { CreateOrganizationOptions, CreateOrganizationRequestOptions, ListOrganizationsOptions, Organization, UpdateOrganizationOptions } from './interfaces';
|
|
4
4
|
export declare class Organizations {
|
|
5
5
|
private readonly workos;
|
|
6
6
|
constructor(workos: WorkOS);
|
|
7
7
|
listOrganizations(options?: ListOrganizationsOptions): Promise<List<Organization>>;
|
|
8
|
-
createOrganization(payload: CreateOrganizationOptions): Promise<Organization>;
|
|
8
|
+
createOrganization(payload: CreateOrganizationOptions, requestOptions?: CreateOrganizationRequestOptions): Promise<Organization>;
|
|
9
9
|
deleteOrganization(id: string): Promise<void>;
|
|
10
10
|
getOrganization(id: string): Promise<Organization>;
|
|
11
11
|
updateOrganization(options: UpdateOrganizationOptions): Promise<Organization>;
|
|
@@ -33,9 +33,9 @@ class Organizations {
|
|
|
33
33
|
return data;
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
-
createOrganization(payload) {
|
|
36
|
+
createOrganization(payload, requestOptions = {}) {
|
|
37
37
|
return __awaiter(this, void 0, void 0, function* () {
|
|
38
|
-
const { data } = yield this.workos.post('/organizations', payload);
|
|
38
|
+
const { data } = yield this.workos.post('/organizations', payload, requestOptions);
|
|
39
39
|
return data;
|
|
40
40
|
});
|
|
41
41
|
}
|
|
@@ -108,6 +108,23 @@ describe('Organizations', () => {
|
|
|
108
108
|
});
|
|
109
109
|
});
|
|
110
110
|
describe('createOrganization', () => {
|
|
111
|
+
describe('with an idempotency key', () => {
|
|
112
|
+
it('includes an idempotency key with request', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
113
|
+
mock
|
|
114
|
+
.onPost('/organizations', {
|
|
115
|
+
domains: ['example.com'],
|
|
116
|
+
name: 'Test Organization',
|
|
117
|
+
})
|
|
118
|
+
.replyOnce(201, create_organization_json_1.default);
|
|
119
|
+
yield workos.organizations.createOrganization({
|
|
120
|
+
domains: ['example.com'],
|
|
121
|
+
name: 'Test Organization',
|
|
122
|
+
}, {
|
|
123
|
+
idempotencyKey: 'the-idempotency-key',
|
|
124
|
+
});
|
|
125
|
+
expect(mock.history.post[0].headers['Idempotency-Key']).toEqual('the-idempotency-key');
|
|
126
|
+
}));
|
|
127
|
+
});
|
|
111
128
|
describe('with a valid payload', () => {
|
|
112
129
|
it('creates an organization', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
113
130
|
mock
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.GeneratePortalLinkIntent = void 0;
|
|
4
4
|
var GeneratePortalLinkIntent;
|
|
5
5
|
(function (GeneratePortalLinkIntent) {
|
|
6
|
-
GeneratePortalLinkIntent["
|
|
6
|
+
GeneratePortalLinkIntent["AuditLogs"] = "audit_logs";
|
|
7
7
|
GeneratePortalLinkIntent["DSync"] = "dsync";
|
|
8
|
+
GeneratePortalLinkIntent["SSO"] = "sso";
|
|
8
9
|
})(GeneratePortalLinkIntent = exports.GeneratePortalLinkIntent || (exports.GeneratePortalLinkIntent = {}));
|
|
@@ -58,6 +58,23 @@ describe('Portal', () => {
|
|
|
58
58
|
expect(link).toEqual('https://id.workos.com/portal/launch?secret=secret');
|
|
59
59
|
}));
|
|
60
60
|
});
|
|
61
|
+
describe('with the `audit_logs` intent', () => {
|
|
62
|
+
it('returns an Admin Portal link', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
63
|
+
mock
|
|
64
|
+
.onPost('/portal/generate_link', {
|
|
65
|
+
intent: generate_portal_link_intent_interface_1.GeneratePortalLinkIntent.AuditLogs,
|
|
66
|
+
organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3',
|
|
67
|
+
return_url: 'https://www.example.com',
|
|
68
|
+
})
|
|
69
|
+
.reply(201, generate_link_json_1.default);
|
|
70
|
+
const { link } = yield workos.portal.generateLink({
|
|
71
|
+
intent: generate_portal_link_intent_interface_1.GeneratePortalLinkIntent.AuditLogs,
|
|
72
|
+
organization: 'org_01EHQMYV6MBK39QC5PZXHY59C3',
|
|
73
|
+
returnUrl: 'https://www.example.com',
|
|
74
|
+
});
|
|
75
|
+
expect(link).toEqual('https://id.workos.com/portal/launch?secret=secret');
|
|
76
|
+
}));
|
|
77
|
+
});
|
|
61
78
|
});
|
|
62
79
|
describe('with an invalid organization', () => {
|
|
63
80
|
it('throws an error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{ "id": "wh_123", "data": { "id": "directory_user_01FAEAJCR3ZBZ30D8BD1924TVG", "state": "active", "emails": [{ "type": "work", "value": "blair@foo-corp.com", "primary": true }], "idp_id": "00u1e8mutl6wlH3lL4x7", "object": "directory_user", "username": "blair@foo-corp.com", "last_name": "
|
|
1
|
+
{ "id": "wh_123", "data": { "id": "directory_user_01FAEAJCR3ZBZ30D8BD1924TVG", "state": "active", "emails": [{ "type": "work", "value": "blair@foo-corp.com", "primary": true }], "idp_id": "00u1e8mutl6wlH3lL4x7", "object": "directory_user", "username": "blair@foo-corp.com", "last_name": "Lunchford", "first_name": "Blair", "directory_id": "directory_01F9M7F68PZP8QXP8G7X5QRHS7", "raw_attributes": { "name": { "givenName": "Blair", "familyName": "Lunchford", "middleName": "Elizabeth", "honorificPrefix": "Ms." }, "title": "Developer Success Engineer", "active": true, "emails": [{ "type": "work", "value": "blair@foo-corp.com", "primary": true }], "groups": [], "locale": "en-US", "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User", "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"], "userName": "blair@foo-corp.com", "addresses": [{ "region": "CA", "primary": true, "locality": "San Francisco", "postalCode": "94016" }], "externalId": "00u1e8mutl6wlH3lL4x7", "displayName": "Blair Lunchford", "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": { "manager": { "value": "2", "displayName": "Kate Chapman" }, "division": "Engineering", "department": "Customer Success" } } }, "event": "dsync.user.created" }
|
|
@@ -6,8 +6,13 @@ export declare class Webhooks {
|
|
|
6
6
|
secret: string;
|
|
7
7
|
tolerance?: number;
|
|
8
8
|
}): Webhook;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
verifyHeader({ payload, sigHeader, secret, tolerance, }: {
|
|
10
|
+
payload: any;
|
|
11
|
+
sigHeader: string;
|
|
12
|
+
secret: string;
|
|
13
|
+
tolerance?: number;
|
|
14
|
+
}): boolean;
|
|
15
|
+
getTimestampAndSignatureHash(sigHeader: string): string[];
|
|
16
|
+
computeSignature(timestamp: any, payload: any, secret: string): string;
|
|
17
|
+
secureCompare(stringA: string, stringB: string): boolean;
|
|
13
18
|
}
|
|
@@ -38,13 +38,13 @@ describe('Webhooks', () => {
|
|
|
38
38
|
idp_id: '00u1e8mutl6wlH3lL4x7',
|
|
39
39
|
object: 'directory_user',
|
|
40
40
|
username: 'blair@foo-corp.com',
|
|
41
|
-
last_name: '
|
|
41
|
+
last_name: 'Lunchford',
|
|
42
42
|
first_name: 'Blair',
|
|
43
43
|
directory_id: 'directory_01F9M7F68PZP8QXP8G7X5QRHS7',
|
|
44
44
|
raw_attributes: {
|
|
45
45
|
name: {
|
|
46
46
|
givenName: 'Blair',
|
|
47
|
-
familyName: '
|
|
47
|
+
familyName: 'Lunchford',
|
|
48
48
|
middleName: 'Elizabeth',
|
|
49
49
|
honorificPrefix: 'Ms.',
|
|
50
50
|
},
|
|
@@ -66,18 +66,18 @@ describe('Webhooks', () => {
|
|
|
66
66
|
userName: 'blair@foo-corp.com',
|
|
67
67
|
addresses: [
|
|
68
68
|
{
|
|
69
|
-
region: '
|
|
69
|
+
region: 'CA',
|
|
70
70
|
primary: true,
|
|
71
|
-
locality: '
|
|
72
|
-
postalCode: '
|
|
71
|
+
locality: 'San Francisco',
|
|
72
|
+
postalCode: '94016',
|
|
73
73
|
},
|
|
74
74
|
],
|
|
75
75
|
externalId: '00u1e8mutl6wlH3lL4x7',
|
|
76
|
-
displayName: 'Blair
|
|
76
|
+
displayName: 'Blair Lunchford',
|
|
77
77
|
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User': {
|
|
78
78
|
manager: {
|
|
79
79
|
value: '2',
|
|
80
|
-
displayName: '
|
|
80
|
+
displayName: 'Kate Chapman',
|
|
81
81
|
},
|
|
82
82
|
division: 'Engineering',
|
|
83
83
|
department: 'Customer Success',
|
|
@@ -151,4 +151,27 @@ describe('Webhooks', () => {
|
|
|
151
151
|
});
|
|
152
152
|
});
|
|
153
153
|
});
|
|
154
|
+
describe('verifyHeader', () => {
|
|
155
|
+
it('returns true when the signature is valid', () => {
|
|
156
|
+
const sigHeader = `t=${timestamp}, v1=${signatureHash}`;
|
|
157
|
+
const options = { payload, sigHeader, secret };
|
|
158
|
+
expect(() => workos.webhooks.verifyHeader(options)).toBeTruthy();
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
describe('getTimestampAndSignatureHash', () => {
|
|
162
|
+
it('returns the timestamp and signature when the signature is valid', () => {
|
|
163
|
+
const sigHeader = `t=${timestamp}, v1=${signatureHash}`;
|
|
164
|
+
const timestampAndSignature = workos.webhooks.getTimestampAndSignatureHash(sigHeader);
|
|
165
|
+
expect(timestampAndSignature).toEqual([
|
|
166
|
+
timestamp.toString(),
|
|
167
|
+
signatureHash,
|
|
168
|
+
]);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
describe('computeSignature', () => {
|
|
172
|
+
it('returns the computed signature', () => {
|
|
173
|
+
const signature = workos.webhooks.computeSignature(timestamp, payload, secret);
|
|
174
|
+
expect(signature).toEqual(signatureHash);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
154
177
|
});
|
package/lib/workos.js
CHANGED
|
@@ -25,10 +25,11 @@ const webhooks_1 = require("./webhooks/webhooks");
|
|
|
25
25
|
const mfa_1 = require("./mfa/mfa");
|
|
26
26
|
const audit_logs_1 = require("./audit-logs/audit-logs");
|
|
27
27
|
const bad_request_exception_1 = require("./common/exceptions/bad-request.exception");
|
|
28
|
-
const VERSION = '2.
|
|
28
|
+
const VERSION = '2.13.0';
|
|
29
29
|
const DEFAULT_HOSTNAME = 'api.workos.com';
|
|
30
30
|
class WorkOS {
|
|
31
31
|
constructor(key, options = {}) {
|
|
32
|
+
var _a;
|
|
32
33
|
this.key = key;
|
|
33
34
|
this.options = options;
|
|
34
35
|
this.auditLogs = new audit_logs_1.AuditLogs(this);
|
|
@@ -56,13 +57,7 @@ class WorkOS {
|
|
|
56
57
|
if (port) {
|
|
57
58
|
this.baseURL = this.baseURL + `:${port}`;
|
|
58
59
|
}
|
|
59
|
-
this.client = axios_1.default.create({
|
|
60
|
-
baseURL: this.baseURL,
|
|
61
|
-
headers: {
|
|
62
|
-
Authorization: `Bearer ${this.key}`,
|
|
63
|
-
'User-Agent': `workos-node/${VERSION}`,
|
|
64
|
-
},
|
|
65
|
-
});
|
|
60
|
+
this.client = axios_1.default.create(Object.assign(Object.assign({}, options.axios), { baseURL: this.baseURL, headers: Object.assign(Object.assign({}, (_a = options.axios) === null || _a === void 0 ? void 0 : _a.headers), { Authorization: `Bearer ${this.key}`, 'User-Agent': `workos-node/${VERSION}` }) }));
|
|
66
61
|
}
|
|
67
62
|
post(path, entity, options = {}) {
|
|
68
63
|
return __awaiter(this, void 0, void 0, function* () {
|
package/lib/workos.spec.js
CHANGED
|
@@ -65,6 +65,22 @@ describe('WorkOS', () => {
|
|
|
65
65
|
expect(workos.baseURL).toEqual('https://localhost:4000');
|
|
66
66
|
});
|
|
67
67
|
});
|
|
68
|
+
describe('when the `axios` option is provided', () => {
|
|
69
|
+
it('applies the configuration to the Axios client', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
70
|
+
mock.onPost().reply(200, 'OK', { 'X-Request-ID': 'a-request-id' });
|
|
71
|
+
const workos = new workos_1.WorkOS('sk_test', {
|
|
72
|
+
axios: {
|
|
73
|
+
headers: {
|
|
74
|
+
'X-My-Custom-Header': 'Hey there!',
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
yield workos.post('/somewhere', {});
|
|
79
|
+
expect(mock.history.post[0].headers).toMatchObject({
|
|
80
|
+
'X-My-Custom-Header': 'Hey there!',
|
|
81
|
+
});
|
|
82
|
+
}));
|
|
83
|
+
});
|
|
68
84
|
});
|
|
69
85
|
describe('post', () => {
|
|
70
86
|
describe('when the api responds with a 404', () => {
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.13.0",
|
|
3
3
|
"name": "@workos-inc/node",
|
|
4
4
|
"author": "WorkOS",
|
|
5
5
|
"description": "A Node wrapper for the WorkOS API",
|
|
@@ -40,14 +40,14 @@
|
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/jest": "27.5.2",
|
|
43
|
-
"@types/node": "14.18.
|
|
43
|
+
"@types/node": "14.18.29",
|
|
44
44
|
"@types/pluralize": "0.0.29",
|
|
45
|
-
"axios-mock-adapter": "1.21.
|
|
45
|
+
"axios-mock-adapter": "1.21.2",
|
|
46
46
|
"jest": "27.5.1",
|
|
47
47
|
"prettier": "2.7.1",
|
|
48
48
|
"supertest": "6.2.3",
|
|
49
49
|
"ts-jest": "27.1.5",
|
|
50
50
|
"tslint": "6.1.3",
|
|
51
|
-
"typescript": "4.
|
|
51
|
+
"typescript": "4.8.3"
|
|
52
52
|
}
|
|
53
53
|
}
|