@tellescope/sdk 1.248.0 → 1.249.1
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/.env +3 -0
- package/lib/cjs/sdk.d.ts +1 -0
- package/lib/cjs/sdk.d.ts.map +1 -1
- package/lib/cjs/sdk.js +1 -0
- package/lib/cjs/sdk.js.map +1 -1
- package/lib/cjs/tests/api_tests/chats_analytics.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/chats_analytics.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/chats_analytics.test.js +256 -0
- package/lib/cjs/tests/api_tests/chats_analytics.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/cross_org_api_key.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/cross_org_api_key.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/cross_org_api_key.test.js +748 -0
- package/lib/cjs/tests/api_tests/cross_org_api_key.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.js +426 -2
- package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/eom_billing_codes.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/eom_billing_codes.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/eom_billing_codes.test.js +162 -0
- package/lib/cjs/tests/api_tests/eom_billing_codes.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/eom_procedure_codes.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/eom_procedure_codes.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/eom_procedure_codes.test.js +339 -0
- package/lib/cjs/tests/api_tests/eom_procedure_codes.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/managed_content_file_access.test.d.ts +13 -0
- package/lib/cjs/tests/api_tests/managed_content_file_access.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/managed_content_file_access.test.js +385 -0
- package/lib/cjs/tests/api_tests/managed_content_file_access.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/organization_settings_duplicates.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/organization_settings_duplicates.test.js +25 -2
- package/lib/cjs/tests/api_tests/organization_settings_duplicates.test.js.map +1 -1
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +185 -134
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/sdk.d.ts +3 -2
- package/lib/esm/sdk.d.ts.map +1 -1
- package/lib/esm/sdk.js +1 -0
- package/lib/esm/sdk.js.map +1 -1
- package/lib/esm/tests/api_tests/chats_analytics.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/chats_analytics.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/chats_analytics.test.js +252 -0
- package/lib/esm/tests/api_tests/chats_analytics.test.js.map +1 -0
- package/lib/esm/tests/api_tests/cross_org_api_key.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/cross_org_api_key.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/cross_org_api_key.test.js +744 -0
- package/lib/esm/tests/api_tests/cross_org_api_key.test.js.map +1 -0
- package/lib/esm/tests/api_tests/enduser_session_invalidation.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/enduser_session_invalidation.test.js +426 -2
- package/lib/esm/tests/api_tests/enduser_session_invalidation.test.js.map +1 -1
- package/lib/esm/tests/api_tests/eom_billing_codes.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/eom_billing_codes.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/eom_billing_codes.test.js +158 -0
- package/lib/esm/tests/api_tests/eom_billing_codes.test.js.map +1 -0
- package/lib/esm/tests/api_tests/eom_procedure_codes.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/eom_procedure_codes.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/eom_procedure_codes.test.js +335 -0
- package/lib/esm/tests/api_tests/eom_procedure_codes.test.js.map +1 -0
- package/lib/esm/tests/api_tests/managed_content_file_access.test.d.ts +13 -0
- package/lib/esm/tests/api_tests/managed_content_file_access.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/managed_content_file_access.test.js +358 -0
- package/lib/esm/tests/api_tests/managed_content_file_access.test.js.map +1 -0
- package/lib/esm/tests/api_tests/organization_settings_duplicates.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/organization_settings_duplicates.test.js +25 -2
- package/lib/esm/tests/api_tests/organization_settings_duplicates.test.js.map +1 -1
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +186 -135
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/sdk.ts +4 -0
- package/src/tests/api_tests/chats_analytics.test.ts +182 -0
- package/src/tests/api_tests/cross_org_api_key.test.ts +665 -0
- package/src/tests/api_tests/enduser_session_invalidation.test.ts +223 -0
- package/src/tests/api_tests/eom_procedure_codes.test.ts +296 -0
- package/src/tests/api_tests/managed_content_file_access.test.ts +214 -0
- package/src/tests/api_tests/organization_settings_duplicates.test.ts +14 -0
- package/src/tests/tests.ts +93 -3
- package/test_generated.pdf +0 -0
|
@@ -0,0 +1,748 @@
|
|
|
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
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.cross_org_api_key_tests = void 0;
|
|
40
|
+
require('source-map-support').install();
|
|
41
|
+
var sdk_1 = require("../../sdk");
|
|
42
|
+
var testing_1 = require("@tellescope/testing");
|
|
43
|
+
var setup_1 = require("../setup");
|
|
44
|
+
var host = process.env.API_URL || 'http://localhost:8080';
|
|
45
|
+
var CROSS_ORG_API_KEY = process.env.CROSS_ORG_API_KEY;
|
|
46
|
+
var CROSS_ORG_TARGET_BUSINESS_ID = process.env.CROSS_ORG_TARGET_BUSINESS_ID;
|
|
47
|
+
var CROSS_ORG_UNAPPROVED_BUSINESS_ID = process.env.CROSS_ORG_UNAPPROVED_BUSINESS_ID;
|
|
48
|
+
var NON_ADMIN_EMAIL = process.env.NON_ADMIN_EMAIL;
|
|
49
|
+
var NON_ADMIN_PASSWORD = process.env.NON_ADMIN_PASSWORD;
|
|
50
|
+
var cross_org_api_key_tests = function (_a) {
|
|
51
|
+
var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
|
|
52
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
53
|
+
var sdkDefault, sdkCrossOrg, sdkUnapproved, sdkInvalidOrg, homeBusinessId, regularApiKeyRecord, regularApiKey, sdkRegularApiKey, sdkOwnOrgExplicit_1, crossOrgEnduserId_1, homeOrgEnduserId_1, sdkMalformedOrg_1, sdkEmptyHeader_1, sdkRegularKeyWithHeader_1, testKeyId_1, newKey, nonAdminKeyRecord_1, isolationIds, targetOrgEnduser_1, homeOrgEnduser_1, _i, isolationIds_1, _b, id, inTargetOrg, session, creatorTestId_1;
|
|
54
|
+
return __generator(this, function (_c) {
|
|
55
|
+
switch (_c.label) {
|
|
56
|
+
case 0:
|
|
57
|
+
(0, testing_1.log_header)("Cross-Organization API Key Tests");
|
|
58
|
+
if (!(CROSS_ORG_API_KEY && CROSS_ORG_TARGET_BUSINESS_ID && CROSS_ORG_UNAPPROVED_BUSINESS_ID)) {
|
|
59
|
+
console.log("Skipping cross-org API key tests — env vars not set");
|
|
60
|
+
return [2 /*return*/];
|
|
61
|
+
}
|
|
62
|
+
sdkDefault = new sdk_1.Session({ host: host, apiKey: CROSS_ORG_API_KEY });
|
|
63
|
+
sdkCrossOrg = new sdk_1.Session({
|
|
64
|
+
host: host,
|
|
65
|
+
apiKey: CROSS_ORG_API_KEY,
|
|
66
|
+
headers: { 'x-tellescope-organization': CROSS_ORG_TARGET_BUSINESS_ID },
|
|
67
|
+
});
|
|
68
|
+
sdkUnapproved = new sdk_1.Session({
|
|
69
|
+
host: host,
|
|
70
|
+
apiKey: CROSS_ORG_API_KEY,
|
|
71
|
+
headers: { 'x-tellescope-organization': CROSS_ORG_UNAPPROVED_BUSINESS_ID },
|
|
72
|
+
});
|
|
73
|
+
sdkInvalidOrg = new sdk_1.Session({
|
|
74
|
+
host: host,
|
|
75
|
+
apiKey: CROSS_ORG_API_KEY,
|
|
76
|
+
headers: { 'x-tellescope-organization': '000000000000000000000000' },
|
|
77
|
+
});
|
|
78
|
+
homeBusinessId = sdk.userInfo.businessId;
|
|
79
|
+
return [4 /*yield*/, sdk.api.api_keys.createOne({})];
|
|
80
|
+
case 1:
|
|
81
|
+
regularApiKeyRecord = _c.sent();
|
|
82
|
+
regularApiKey = regularApiKeyRecord.key;
|
|
83
|
+
sdkRegularApiKey = new sdk_1.Session({ host: host, apiKey: regularApiKey });
|
|
84
|
+
_c.label = 2;
|
|
85
|
+
case 2:
|
|
86
|
+
_c.trys.push([2, , 108, 110]);
|
|
87
|
+
// =============================================
|
|
88
|
+
// AUTHORIZED ACCESS TESTS
|
|
89
|
+
// =============================================
|
|
90
|
+
// 1. Default behavior (no header) still works — backward compatibility
|
|
91
|
+
return [4 /*yield*/, (0, testing_1.async_test)("API key without org header authenticates to home org", function () { return sdkDefault.test_authenticated(); }, { expectedResult: 'Authenticated!' })
|
|
92
|
+
// 2. Cross-org header with approved org works
|
|
93
|
+
];
|
|
94
|
+
case 3:
|
|
95
|
+
// =============================================
|
|
96
|
+
// AUTHORIZED ACCESS TESTS
|
|
97
|
+
// =============================================
|
|
98
|
+
// 1. Default behavior (no header) still works — backward compatibility
|
|
99
|
+
_c.sent();
|
|
100
|
+
// 2. Cross-org header with approved org works
|
|
101
|
+
return [4 /*yield*/, (0, testing_1.async_test)("API key with approved org header authenticates successfully", function () { return sdkCrossOrg.test_authenticated(); }, { expectedResult: 'Authenticated!' })
|
|
102
|
+
// 3. Targeting own org explicitly via header (should work as a no-op)
|
|
103
|
+
];
|
|
104
|
+
case 4:
|
|
105
|
+
// 2. Cross-org header with approved org works
|
|
106
|
+
_c.sent();
|
|
107
|
+
sdkOwnOrgExplicit_1 = new sdk_1.Session({
|
|
108
|
+
host: host,
|
|
109
|
+
apiKey: CROSS_ORG_API_KEY,
|
|
110
|
+
headers: { 'x-tellescope-organization': homeBusinessId },
|
|
111
|
+
});
|
|
112
|
+
return [4 /*yield*/, (0, testing_1.async_test)("API key targeting its own org explicitly via header still works", function () { return sdkOwnOrgExplicit_1.test_authenticated(); }, { expectedResult: 'Authenticated!' })
|
|
113
|
+
// 4. Can read data from target org
|
|
114
|
+
];
|
|
115
|
+
case 5:
|
|
116
|
+
_c.sent();
|
|
117
|
+
// 4. Can read data from target org
|
|
118
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Can read endusers from target org", function () { return sdkCrossOrg.api.endusers.getSome(); }, { onResult: function (r) { return Array.isArray(r); } })
|
|
119
|
+
// 5-9. Full CRUD in target org + cross-direction isolation
|
|
120
|
+
];
|
|
121
|
+
case 6:
|
|
122
|
+
// 4. Can read data from target org
|
|
123
|
+
_c.sent();
|
|
124
|
+
_c.label = 7;
|
|
125
|
+
case 7:
|
|
126
|
+
_c.trys.push([7, , 16, 21]);
|
|
127
|
+
// 5. Create in target org — verify record gets target org's businessId
|
|
128
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Can create enduser in target org with correct businessId", function () { return sdkCrossOrg.api.endusers.createOne({ fname: 'CrossOrgTest', lname: 'Enduser' }); }, { onResult: function (e) {
|
|
129
|
+
crossOrgEnduserId_1 = e.id;
|
|
130
|
+
return e.fname === 'CrossOrgTest' && e.businessId === CROSS_ORG_TARGET_BUSINESS_ID;
|
|
131
|
+
} })
|
|
132
|
+
// 6. Record created in target org is NOT visible from home org (data isolation)
|
|
133
|
+
];
|
|
134
|
+
case 8:
|
|
135
|
+
// 5. Create in target org — verify record gets target org's businessId
|
|
136
|
+
_c.sent();
|
|
137
|
+
if (!crossOrgEnduserId_1) return [3 /*break*/, 10];
|
|
138
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org record is NOT visible from home org session", function () { return sdkDefault.api.endusers.getOne(crossOrgEnduserId_1); }, testing_1.handleAnyError)];
|
|
139
|
+
case 9:
|
|
140
|
+
_c.sent();
|
|
141
|
+
_c.label = 10;
|
|
142
|
+
case 10:
|
|
143
|
+
// 7. Create a record in home org and verify it's NOT visible from cross-org session
|
|
144
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Home org record is NOT visible from cross-org session", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
145
|
+
var homeEnduser;
|
|
146
|
+
return __generator(this, function (_a) {
|
|
147
|
+
switch (_a.label) {
|
|
148
|
+
case 0: return [4 /*yield*/, sdkDefault.api.endusers.createOne({ fname: 'HomeOrgTest', lname: 'Enduser' })];
|
|
149
|
+
case 1:
|
|
150
|
+
homeEnduser = _a.sent();
|
|
151
|
+
homeOrgEnduserId_1 = homeEnduser.id;
|
|
152
|
+
return [2 /*return*/, sdkCrossOrg.api.endusers.getOne(homeEnduser.id)];
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}); }, testing_1.handleAnyError)
|
|
156
|
+
// 8. Update record in target org (full CRUD — update)
|
|
157
|
+
];
|
|
158
|
+
case 11:
|
|
159
|
+
// 7. Create a record in home org and verify it's NOT visible from cross-org session
|
|
160
|
+
_c.sent();
|
|
161
|
+
if (!crossOrgEnduserId_1) return [3 /*break*/, 13];
|
|
162
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Can update enduser in target org", function () { return sdkCrossOrg.api.endusers.updateOne(crossOrgEnduserId_1, { fname: 'CrossOrgUpdated' }); }, { onResult: function () { return true; } })];
|
|
163
|
+
case 12:
|
|
164
|
+
_c.sent();
|
|
165
|
+
_c.label = 13;
|
|
166
|
+
case 13:
|
|
167
|
+
if (!crossOrgEnduserId_1) return [3 /*break*/, 15];
|
|
168
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Can delete enduser in target org", function () { return sdkCrossOrg.api.endusers.deleteOne(crossOrgEnduserId_1); }, { onResult: function () { return true; } })];
|
|
169
|
+
case 14:
|
|
170
|
+
_c.sent();
|
|
171
|
+
crossOrgEnduserId_1 = undefined; // already deleted
|
|
172
|
+
_c.label = 15;
|
|
173
|
+
case 15: return [3 /*break*/, 21];
|
|
174
|
+
case 16:
|
|
175
|
+
if (!crossOrgEnduserId_1) return [3 /*break*/, 18];
|
|
176
|
+
return [4 /*yield*/, sdkCrossOrg.api.endusers.deleteOne(crossOrgEnduserId_1).catch(console.error)];
|
|
177
|
+
case 17:
|
|
178
|
+
_c.sent();
|
|
179
|
+
_c.label = 18;
|
|
180
|
+
case 18:
|
|
181
|
+
if (!homeOrgEnduserId_1) return [3 /*break*/, 20];
|
|
182
|
+
return [4 /*yield*/, sdkDefault.api.endusers.deleteOne(homeOrgEnduserId_1).catch(console.error)];
|
|
183
|
+
case 19:
|
|
184
|
+
_c.sent();
|
|
185
|
+
_c.label = 20;
|
|
186
|
+
case 20: return [7 /*endfinally*/];
|
|
187
|
+
case 21:
|
|
188
|
+
// =============================================
|
|
189
|
+
// UNAUTHORIZED ACCESS TESTS
|
|
190
|
+
// =============================================
|
|
191
|
+
// 10. Unapproved org ID is rejected
|
|
192
|
+
return [4 /*yield*/, (0, testing_1.async_test)("API key with unapproved org header is rejected", function () { return sdkUnapproved.test_authenticated(); }, testing_1.handleAnyError)
|
|
193
|
+
// 11. Nonexistent org ID is rejected
|
|
194
|
+
];
|
|
195
|
+
case 22:
|
|
196
|
+
// =============================================
|
|
197
|
+
// UNAUTHORIZED ACCESS TESTS
|
|
198
|
+
// =============================================
|
|
199
|
+
// 10. Unapproved org ID is rejected
|
|
200
|
+
_c.sent();
|
|
201
|
+
// 11. Nonexistent org ID is rejected
|
|
202
|
+
return [4 /*yield*/, (0, testing_1.async_test)("API key with nonexistent org header is rejected", function () { return sdkInvalidOrg.test_authenticated(); }, testing_1.handleAnyError)
|
|
203
|
+
// 12. Malformed (non-ObjectId) org header is rejected
|
|
204
|
+
];
|
|
205
|
+
case 23:
|
|
206
|
+
// 11. Nonexistent org ID is rejected
|
|
207
|
+
_c.sent();
|
|
208
|
+
sdkMalformedOrg_1 = new sdk_1.Session({
|
|
209
|
+
host: host,
|
|
210
|
+
apiKey: CROSS_ORG_API_KEY,
|
|
211
|
+
headers: { 'x-tellescope-organization': 'not-a-valid-id' },
|
|
212
|
+
});
|
|
213
|
+
return [4 /*yield*/, (0, testing_1.async_test)("API key with malformed org header is rejected", function () { return sdkMalformedOrg_1.test_authenticated(); }, testing_1.handleAnyError)
|
|
214
|
+
// 13. Empty string org header falls back to home org
|
|
215
|
+
];
|
|
216
|
+
case 24:
|
|
217
|
+
_c.sent();
|
|
218
|
+
sdkEmptyHeader_1 = new sdk_1.Session({
|
|
219
|
+
host: host,
|
|
220
|
+
apiKey: CROSS_ORG_API_KEY,
|
|
221
|
+
headers: { 'x-tellescope-organization': '' },
|
|
222
|
+
});
|
|
223
|
+
return [4 /*yield*/, (0, testing_1.async_test)("API key with empty org header falls back to home org", function () { return sdkEmptyHeader_1.test_authenticated(); }, { expectedResult: 'Authenticated!' })
|
|
224
|
+
// 14. Regular API key (no approvedBusinessIds) with org header is rejected
|
|
225
|
+
];
|
|
226
|
+
case 25:
|
|
227
|
+
_c.sent();
|
|
228
|
+
sdkRegularKeyWithHeader_1 = new sdk_1.Session({
|
|
229
|
+
host: host,
|
|
230
|
+
apiKey: regularApiKey,
|
|
231
|
+
headers: { 'x-tellescope-organization': CROSS_ORG_TARGET_BUSINESS_ID },
|
|
232
|
+
});
|
|
233
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Regular API key (no approvedBusinessIds) with org header is rejected", function () { return sdkRegularKeyWithHeader_1.test_authenticated(); }, testing_1.handleAnyError)
|
|
234
|
+
// 15. Password-auth session with org header is rejected
|
|
235
|
+
];
|
|
236
|
+
case 26:
|
|
237
|
+
_c.sent();
|
|
238
|
+
// 15. Password-auth session with org header is rejected
|
|
239
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Password-auth session with org header is rejected", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
240
|
+
var sdkPasswordWithOrgHeader;
|
|
241
|
+
return __generator(this, function (_a) {
|
|
242
|
+
switch (_a.label) {
|
|
243
|
+
case 0:
|
|
244
|
+
sdkPasswordWithOrgHeader = new sdk_1.Session({
|
|
245
|
+
host: host,
|
|
246
|
+
headers: { 'x-tellescope-organization': CROSS_ORG_TARGET_BUSINESS_ID },
|
|
247
|
+
});
|
|
248
|
+
return [4 /*yield*/, sdkPasswordWithOrgHeader.authenticate(process.env.TEST_EMAIL, process.env.TEST_PASSWORD)];
|
|
249
|
+
case 1:
|
|
250
|
+
_a.sent();
|
|
251
|
+
return [2 /*return*/, sdkPasswordWithOrgHeader.test_authenticated()];
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
}); }, testing_1.handleAnyError)
|
|
255
|
+
// =============================================
|
|
256
|
+
// READONLY ENFORCEMENT TESTS
|
|
257
|
+
// =============================================
|
|
258
|
+
// 16. approvedBusinessIds cannot be set when creating a new API key
|
|
259
|
+
];
|
|
260
|
+
case 27:
|
|
261
|
+
// 15. Password-auth session with org header is rejected
|
|
262
|
+
_c.sent();
|
|
263
|
+
// =============================================
|
|
264
|
+
// READONLY ENFORCEMENT TESTS
|
|
265
|
+
// =============================================
|
|
266
|
+
// 16. approvedBusinessIds cannot be set when creating a new API key
|
|
267
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cannot set approvedBusinessIds on API key creation", function () { return sdk.api.api_keys.createOne({ approvedBusinessIds: [CROSS_ORG_TARGET_BUSINESS_ID] }); }, testing_1.handleAnyError)
|
|
268
|
+
// 18. approvedBusinessIds cannot be set via bulk create
|
|
269
|
+
];
|
|
270
|
+
case 28:
|
|
271
|
+
// =============================================
|
|
272
|
+
// READONLY ENFORCEMENT TESTS
|
|
273
|
+
// =============================================
|
|
274
|
+
// 16. approvedBusinessIds cannot be set when creating a new API key
|
|
275
|
+
_c.sent();
|
|
276
|
+
// 18. approvedBusinessIds cannot be set via bulk create
|
|
277
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cannot set approvedBusinessIds via bulk create (createSome)", function () { return sdk.api.api_keys.createSome([{ approvedBusinessIds: [CROSS_ORG_TARGET_BUSINESS_ID] }]); }, testing_1.handleAnyError)
|
|
278
|
+
// 17a-c. approvedBusinessIds cannot be updated via API — all replaceObjectFields variants
|
|
279
|
+
];
|
|
280
|
+
case 29:
|
|
281
|
+
// 18. approvedBusinessIds cannot be set via bulk create
|
|
282
|
+
_c.sent();
|
|
283
|
+
_c.label = 30;
|
|
284
|
+
case 30:
|
|
285
|
+
_c.trys.push([30, , 35, 38]);
|
|
286
|
+
return [4 /*yield*/, sdk.api.api_keys.createOne({})];
|
|
287
|
+
case 31:
|
|
288
|
+
newKey = _c.sent();
|
|
289
|
+
testKeyId_1 = newKey.id;
|
|
290
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cannot update approvedBusinessIds on existing API key (no replaceObjectFields)", function () { return sdk.api.api_keys.updateOne(testKeyId_1, { approvedBusinessIds: [CROSS_ORG_TARGET_BUSINESS_ID] }); }, testing_1.handleAnyError)];
|
|
291
|
+
case 32:
|
|
292
|
+
_c.sent();
|
|
293
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cannot update approvedBusinessIds on existing API key (replaceObjectFields: false)", function () { return sdk.api.api_keys.updateOne(testKeyId_1, { approvedBusinessIds: [CROSS_ORG_TARGET_BUSINESS_ID] }, { replaceObjectFields: false }); }, testing_1.handleAnyError)];
|
|
294
|
+
case 33:
|
|
295
|
+
_c.sent();
|
|
296
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cannot update approvedBusinessIds on existing API key (replaceObjectFields: true)", function () { return sdk.api.api_keys.updateOne(testKeyId_1, { approvedBusinessIds: [CROSS_ORG_TARGET_BUSINESS_ID] }, { replaceObjectFields: true }); }, testing_1.handleAnyError)];
|
|
297
|
+
case 34:
|
|
298
|
+
_c.sent();
|
|
299
|
+
return [3 /*break*/, 38];
|
|
300
|
+
case 35:
|
|
301
|
+
if (!testKeyId_1) return [3 /*break*/, 37];
|
|
302
|
+
return [4 /*yield*/, sdk.api.api_keys.deleteOne(testKeyId_1).catch(console.error)];
|
|
303
|
+
case 36:
|
|
304
|
+
_c.sent();
|
|
305
|
+
_c.label = 37;
|
|
306
|
+
case 37: return [7 /*endfinally*/];
|
|
307
|
+
case 38:
|
|
308
|
+
// API key listing isolation — cross-org API key must not be visible to target org sessions,
|
|
309
|
+
// and target org's keys must not be visible to home org sessions
|
|
310
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org session cannot list home org API keys", function () { return sdkCrossOrg.api.api_keys.getSome(); }, { onResult: function (keys) { return keys.every(function (k) { return k.businessId !== homeBusinessId; }); } })];
|
|
311
|
+
case 39:
|
|
312
|
+
// API key listing isolation — cross-org API key must not be visible to target org sessions,
|
|
313
|
+
// and target org's keys must not be visible to home org sessions
|
|
314
|
+
_c.sent();
|
|
315
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Home org session cannot list target org API keys", function () { return sdkDefault.api.api_keys.getSome(); }, { onResult: function (keys) { return keys.every(function (k) { return k.businessId !== CROSS_ORG_TARGET_BUSINESS_ID; }); } })];
|
|
316
|
+
case 40:
|
|
317
|
+
_c.sent();
|
|
318
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Regular API key session cannot list target org API keys", function () { return sdkRegularApiKey.api.api_keys.getSome(); }, { onResult: function (keys) { return keys.every(function (k) { return k.businessId !== CROSS_ORG_TARGET_BUSINESS_ID; }); } })
|
|
319
|
+
// Direct ID lookup isolation — cross-org session cannot access home org API keys by specific ID.
|
|
320
|
+
// Distinct code path from getSome: a creator-only check firing before org-scope could expose home org keys.
|
|
321
|
+
];
|
|
322
|
+
case 41:
|
|
323
|
+
_c.sent();
|
|
324
|
+
// Direct ID lookup isolation — cross-org session cannot access home org API keys by specific ID.
|
|
325
|
+
// Distinct code path from getSome: a creator-only check firing before org-scope could expose home org keys.
|
|
326
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org session cannot getOne a home org API key by ID", function () { return sdkCrossOrg.api.api_keys.getOne(regularApiKeyRecord.id); }, testing_1.handleAnyError)];
|
|
327
|
+
case 42:
|
|
328
|
+
// Direct ID lookup isolation — cross-org session cannot access home org API keys by specific ID.
|
|
329
|
+
// Distinct code path from getSome: a creator-only check firing before org-scope could expose home org keys.
|
|
330
|
+
_c.sent();
|
|
331
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org session getByIds returns no matches for a home org API key", function () { return sdkCrossOrg.api.api_keys.getByIds({ ids: [regularApiKeyRecord.id] }); }, { onResult: function (r) { return r.matches.length === 0; } })];
|
|
332
|
+
case 43:
|
|
333
|
+
_c.sent();
|
|
334
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org session bulk_load contains no home org API keys", function () { return sdkCrossOrg.bulk_load({ load: [{ model: 'api_keys' }] }); }, { onResult: function (r) { var _a, _b; return ((_b = (_a = r.results[0]) === null || _a === void 0 ? void 0 : _a.records) !== null && _b !== void 0 ? _b : []).every(function (k) { return k.id !== regularApiKeyRecord.id; }); } })
|
|
335
|
+
// Creator-only access: only the user who created an API key can read it (intra-org isolation).
|
|
336
|
+
// Elevate sdkNonAdmin to Admin (full read permissions) so any test failure is clearly due to
|
|
337
|
+
// creator-only enforcement, not missing role permissions.
|
|
338
|
+
];
|
|
339
|
+
case 44:
|
|
340
|
+
_c.sent();
|
|
341
|
+
// Creator-only access: only the user who created an API key can read it (intra-org isolation).
|
|
342
|
+
// Elevate sdkNonAdmin to Admin (full read permissions) so any test failure is clearly due to
|
|
343
|
+
// creator-only enforcement, not missing role permissions.
|
|
344
|
+
return [4 /*yield*/, sdk.api.users.updateOne(sdkNonAdmin.userInfo.id, { roles: ['Admin'] }, { replaceObjectFields: true })];
|
|
345
|
+
case 45:
|
|
346
|
+
// Creator-only access: only the user who created an API key can read it (intra-org isolation).
|
|
347
|
+
// Elevate sdkNonAdmin to Admin (full read permissions) so any test failure is clearly due to
|
|
348
|
+
// creator-only enforcement, not missing role permissions.
|
|
349
|
+
_c.sent();
|
|
350
|
+
return [4 /*yield*/, (0, testing_1.wait)(undefined, 2000)]; // wait for role change to propagate
|
|
351
|
+
case 46:
|
|
352
|
+
_c.sent(); // wait for role change to propagate
|
|
353
|
+
return [4 /*yield*/, sdkNonAdmin.authenticate(NON_ADMIN_EMAIL, NON_ADMIN_PASSWORD)];
|
|
354
|
+
case 47:
|
|
355
|
+
_c.sent();
|
|
356
|
+
return [4 /*yield*/, sdkNonAdmin.api.api_keys.createOne({})];
|
|
357
|
+
case 48:
|
|
358
|
+
nonAdminKeyRecord_1 = _c.sent();
|
|
359
|
+
_c.label = 49;
|
|
360
|
+
case 49:
|
|
361
|
+
_c.trys.push([49, , 62, 67]);
|
|
362
|
+
// sdkNonAdmin (Admin) cannot read sdk's key
|
|
363
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Admin user cannot getOne another admin's API key", function () { return sdkNonAdmin.api.api_keys.getOne(regularApiKeyRecord.id); }, testing_1.handleAnyError)];
|
|
364
|
+
case 50:
|
|
365
|
+
// sdkNonAdmin (Admin) cannot read sdk's key
|
|
366
|
+
_c.sent();
|
|
367
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Admin user getSome excludes another admin's API key", function () { return sdkNonAdmin.api.api_keys.getSome(); }, { onResult: function (keys) { return keys.every(function (k) { return k.id !== regularApiKeyRecord.id; }); } })];
|
|
368
|
+
case 51:
|
|
369
|
+
_c.sent();
|
|
370
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Admin user getByIds returns no matches for another admin's API key", function () { return sdkNonAdmin.api.api_keys.getByIds({ ids: [regularApiKeyRecord.id] }); }, { onResult: function (r) { return r.matches.length === 0; } })];
|
|
371
|
+
case 52:
|
|
372
|
+
_c.sent();
|
|
373
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Admin user bulk_load excludes another admin's API key", function () { return sdkNonAdmin.bulk_load({ load: [{ model: 'api_keys' }] }); }, { onResult: function (r) { var _a, _b; return ((_b = (_a = r.results[0]) === null || _a === void 0 ? void 0 : _a.records) !== null && _b !== void 0 ? _b : []).every(function (k) { return k.id !== regularApiKeyRecord.id; }); } })
|
|
374
|
+
// sdk (Admin) cannot read sdkNonAdmin's key
|
|
375
|
+
];
|
|
376
|
+
case 53:
|
|
377
|
+
_c.sent();
|
|
378
|
+
// sdk (Admin) cannot read sdkNonAdmin's key
|
|
379
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Admin cannot getOne a key created by a different admin user", function () { return sdk.api.api_keys.getOne(nonAdminKeyRecord_1.id); }, testing_1.handleAnyError)];
|
|
380
|
+
case 54:
|
|
381
|
+
// sdk (Admin) cannot read sdkNonAdmin's key
|
|
382
|
+
_c.sent();
|
|
383
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Admin getSome excludes keys created by a different admin user", function () { return sdk.api.api_keys.getSome(); }, { onResult: function (keys) { return keys.every(function (k) { return k.id !== nonAdminKeyRecord_1.id; }); } })];
|
|
384
|
+
case 55:
|
|
385
|
+
_c.sent();
|
|
386
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Admin getByIds returns no matches for a key created by a different admin user", function () { return sdk.api.api_keys.getByIds({ ids: [nonAdminKeyRecord_1.id] }); }, { onResult: function (r) { return r.matches.length === 0; } })];
|
|
387
|
+
case 56:
|
|
388
|
+
_c.sent();
|
|
389
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Admin bulk_load excludes keys created by a different admin user", function () { return sdk.bulk_load({ load: [{ model: 'api_keys' }] }); }, { onResult: function (r) { var _a, _b; return ((_b = (_a = r.results[0]) === null || _a === void 0 ? void 0 : _a.records) !== null && _b !== void 0 ? _b : []).every(function (k) { return k.id !== nonAdminKeyRecord_1.id; }); } })
|
|
390
|
+
// Write isolation: neither admin can mutate the other's key.
|
|
391
|
+
// Use a non-empty body with a readonly field (hashedKey) so the test exercises a real payload,
|
|
392
|
+
// not just an empty-object rejection.
|
|
393
|
+
];
|
|
394
|
+
case 57:
|
|
395
|
+
_c.sent();
|
|
396
|
+
// Write isolation: neither admin can mutate the other's key.
|
|
397
|
+
// Use a non-empty body with a readonly field (hashedKey) so the test exercises a real payload,
|
|
398
|
+
// not just an empty-object rejection.
|
|
399
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Admin user cannot updateOne another admin's API key", function () { return sdkNonAdmin.api.api_keys.updateOne(regularApiKeyRecord.id, { hashedKey: 'attack' }); }, testing_1.handleAnyError)];
|
|
400
|
+
case 58:
|
|
401
|
+
// Write isolation: neither admin can mutate the other's key.
|
|
402
|
+
// Use a non-empty body with a readonly field (hashedKey) so the test exercises a real payload,
|
|
403
|
+
// not just an empty-object rejection.
|
|
404
|
+
_c.sent();
|
|
405
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Admin user cannot deleteOne another admin's API key", function () { return sdkNonAdmin.api.api_keys.deleteOne(regularApiKeyRecord.id); }, testing_1.handleAnyError)];
|
|
406
|
+
case 59:
|
|
407
|
+
_c.sent();
|
|
408
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Admin cannot updateOne a key created by a different admin user", function () { return sdk.api.api_keys.updateOne(nonAdminKeyRecord_1.id, { hashedKey: 'attack' }); }, testing_1.handleAnyError)];
|
|
409
|
+
case 60:
|
|
410
|
+
_c.sent();
|
|
411
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Admin cannot deleteOne a key created by a different admin user", function () { return sdk.api.api_keys.deleteOne(nonAdminKeyRecord_1.id); }, testing_1.handleAnyError)];
|
|
412
|
+
case 61:
|
|
413
|
+
_c.sent();
|
|
414
|
+
return [3 /*break*/, 67];
|
|
415
|
+
case 62: return [4 /*yield*/, sdkNonAdmin.api.api_keys.deleteOne(nonAdminKeyRecord_1.id).catch(console.error)
|
|
416
|
+
// Restore sdkNonAdmin to Non-Admin and reauthenticate so subsequent tests are unaffected
|
|
417
|
+
];
|
|
418
|
+
case 63:
|
|
419
|
+
_c.sent();
|
|
420
|
+
// Restore sdkNonAdmin to Non-Admin and reauthenticate so subsequent tests are unaffected
|
|
421
|
+
return [4 /*yield*/, sdk.api.users.updateOne(sdkNonAdmin.userInfo.id, { roles: ['Non-Admin'] }, { replaceObjectFields: true })];
|
|
422
|
+
case 64:
|
|
423
|
+
// Restore sdkNonAdmin to Non-Admin and reauthenticate so subsequent tests are unaffected
|
|
424
|
+
_c.sent();
|
|
425
|
+
return [4 /*yield*/, (0, testing_1.wait)(undefined, 1000)];
|
|
426
|
+
case 65:
|
|
427
|
+
_c.sent();
|
|
428
|
+
return [4 /*yield*/, sdkNonAdmin.authenticate(NON_ADMIN_EMAIL, NON_ADMIN_PASSWORD)];
|
|
429
|
+
case 66:
|
|
430
|
+
_c.sent();
|
|
431
|
+
return [7 /*endfinally*/];
|
|
432
|
+
case 67:
|
|
433
|
+
isolationIds = [];
|
|
434
|
+
_c.label = 68;
|
|
435
|
+
case 68:
|
|
436
|
+
_c.trys.push([68, , 93, 98]);
|
|
437
|
+
return [4 /*yield*/, sdkCrossOrg.api.endusers.createOne({ fname: 'IsolationTest', lname: 'TargetOrg' })];
|
|
438
|
+
case 69:
|
|
439
|
+
targetOrgEnduser_1 = _c.sent();
|
|
440
|
+
isolationIds.push({ id: targetOrgEnduser_1.id, inTargetOrg: true });
|
|
441
|
+
return [4 /*yield*/, sdkDefault.api.endusers.createOne({ fname: 'IsolationTest', lname: 'HomeOrg' })];
|
|
442
|
+
case 70:
|
|
443
|
+
homeOrgEnduser_1 = _c.sent();
|
|
444
|
+
isolationIds.push({ id: homeOrgEnduser_1.id, inTargetOrg: false });
|
|
445
|
+
// --- getOne isolation ---
|
|
446
|
+
// 18. Password-auth session cannot getOne a record from another org by ID
|
|
447
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Password-auth session cannot getOne a target org record by ID", function () { return sdk.api.endusers.getOne(targetOrgEnduser_1.id); }, testing_1.handleAnyError)
|
|
448
|
+
// 19. Regular API key session cannot getOne a record from another org by ID
|
|
449
|
+
];
|
|
450
|
+
case 71:
|
|
451
|
+
// --- getOne isolation ---
|
|
452
|
+
// 18. Password-auth session cannot getOne a record from another org by ID
|
|
453
|
+
_c.sent();
|
|
454
|
+
// 19. Regular API key session cannot getOne a record from another org by ID
|
|
455
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Regular API key session cannot getOne a target org record by ID", function () { return sdkRegularApiKey.api.endusers.getOne(targetOrgEnduser_1.id); }, testing_1.handleAnyError)
|
|
456
|
+
// 20. Cross-org session cannot getOne a home org record by ID (reverse direction)
|
|
457
|
+
];
|
|
458
|
+
case 72:
|
|
459
|
+
// 19. Regular API key session cannot getOne a record from another org by ID
|
|
460
|
+
_c.sent();
|
|
461
|
+
// 20. Cross-org session cannot getOne a home org record by ID (reverse direction)
|
|
462
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org session cannot getOne a home org record by ID", function () { return sdkCrossOrg.api.endusers.getOne(homeOrgEnduser_1.id); }, testing_1.handleAnyError)
|
|
463
|
+
// --- getSome isolation ---
|
|
464
|
+
// 21. getSome from home org (password-auth) never returns records belonging to the target org
|
|
465
|
+
];
|
|
466
|
+
case 73:
|
|
467
|
+
// 20. Cross-org session cannot getOne a home org record by ID (reverse direction)
|
|
468
|
+
_c.sent();
|
|
469
|
+
// --- getSome isolation ---
|
|
470
|
+
// 21. getSome from home org (password-auth) never returns records belonging to the target org
|
|
471
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Password-auth session getSome contains no target org records", function () { return sdk.api.endusers.getSome(); }, { onResult: function (endusers) {
|
|
472
|
+
return endusers.every(function (e) { return e.businessId !== CROSS_ORG_TARGET_BUSINESS_ID && e.id !== targetOrgEnduser_1.id; });
|
|
473
|
+
}
|
|
474
|
+
})
|
|
475
|
+
// 22. getSome via regular API key never returns records belonging to the target org
|
|
476
|
+
];
|
|
477
|
+
case 74:
|
|
478
|
+
// --- getSome isolation ---
|
|
479
|
+
// 21. getSome from home org (password-auth) never returns records belonging to the target org
|
|
480
|
+
_c.sent();
|
|
481
|
+
// 22. getSome via regular API key never returns records belonging to the target org
|
|
482
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Regular API key getSome contains no target org records", function () { return sdkRegularApiKey.api.endusers.getSome(); }, { onResult: function (endusers) {
|
|
483
|
+
return endusers.every(function (e) { return e.businessId !== CROSS_ORG_TARGET_BUSINESS_ID && e.id !== targetOrgEnduser_1.id; });
|
|
484
|
+
}
|
|
485
|
+
})
|
|
486
|
+
// 23. getSome from target org session never returns records belonging to the home org
|
|
487
|
+
];
|
|
488
|
+
case 75:
|
|
489
|
+
// 22. getSome via regular API key never returns records belonging to the target org
|
|
490
|
+
_c.sent();
|
|
491
|
+
// 23. getSome from target org session never returns records belonging to the home org
|
|
492
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org session getSome contains no home org records", function () { return sdkCrossOrg.api.endusers.getSome(); }, { onResult: function (endusers) {
|
|
493
|
+
return endusers.every(function (e) { return e.businessId !== homeBusinessId && e.id !== homeOrgEnduser_1.id; });
|
|
494
|
+
}
|
|
495
|
+
})
|
|
496
|
+
// --- getSome filter injection ---
|
|
497
|
+
// 24. Passing an explicit businessId filter cannot expose cross-tenant records
|
|
498
|
+
];
|
|
499
|
+
case 76:
|
|
500
|
+
// 23. getSome from target org session never returns records belonging to the home org
|
|
501
|
+
_c.sent();
|
|
502
|
+
// --- getSome filter injection ---
|
|
503
|
+
// 24. Passing an explicit businessId filter cannot expose cross-tenant records
|
|
504
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Regular API key getSome with explicit businessId filter cannot expose target org records", function () { return sdkRegularApiKey.api.endusers.getSome({ filter: { businessId: CROSS_ORG_TARGET_BUSINESS_ID } }); }, { onResult: function (endusers) {
|
|
505
|
+
return endusers.every(function (e) { return e.businessId !== CROSS_ORG_TARGET_BUSINESS_ID && e.id !== targetOrgEnduser_1.id; });
|
|
506
|
+
}
|
|
507
|
+
})
|
|
508
|
+
// 25. Cross-org session cannot use businessId filter to expose home org records
|
|
509
|
+
];
|
|
510
|
+
case 77:
|
|
511
|
+
// --- getSome filter injection ---
|
|
512
|
+
// 24. Passing an explicit businessId filter cannot expose cross-tenant records
|
|
513
|
+
_c.sent();
|
|
514
|
+
// 25. Cross-org session cannot use businessId filter to expose home org records
|
|
515
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org session getSome with explicit businessId filter cannot expose home org records", function () { return sdkCrossOrg.api.endusers.getSome({ filter: { businessId: homeBusinessId } }); }, { onResult: function (endusers) {
|
|
516
|
+
return endusers.every(function (e) { return e.businessId !== homeBusinessId && e.id !== homeOrgEnduser_1.id; });
|
|
517
|
+
}
|
|
518
|
+
})
|
|
519
|
+
// --- getByIds isolation ---
|
|
520
|
+
];
|
|
521
|
+
case 78:
|
|
522
|
+
// 25. Cross-org session cannot use businessId filter to expose home org records
|
|
523
|
+
_c.sent();
|
|
524
|
+
// --- getByIds isolation ---
|
|
525
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Password-auth session getByIds returns no matches for target org record", function () { return sdk.api.endusers.getByIds({ ids: [targetOrgEnduser_1.id] }); }, { onResult: function (r) { return r.matches.length === 0; } })];
|
|
526
|
+
case 79:
|
|
527
|
+
// --- getByIds isolation ---
|
|
528
|
+
_c.sent();
|
|
529
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Regular API key session getByIds returns no matches for target org record", function () { return sdkRegularApiKey.api.endusers.getByIds({ ids: [targetOrgEnduser_1.id] }); }, { onResult: function (r) { return r.matches.length === 0; } })];
|
|
530
|
+
case 80:
|
|
531
|
+
_c.sent();
|
|
532
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org session getByIds returns no matches for home org record", function () { return sdkCrossOrg.api.endusers.getByIds({ ids: [homeOrgEnduser_1.id] }); }, { onResult: function (r) { return r.matches.length === 0; } })
|
|
533
|
+
// --- bulk_load isolation ---
|
|
534
|
+
];
|
|
535
|
+
case 81:
|
|
536
|
+
_c.sent();
|
|
537
|
+
// --- bulk_load isolation ---
|
|
538
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Password-auth session bulk_load contains no target org endusers", function () { return sdk.bulk_load({ load: [{ model: 'endusers' }] }); }, { onResult: function (r) { var _a, _b; return ((_b = (_a = r.results[0]) === null || _a === void 0 ? void 0 : _a.records) !== null && _b !== void 0 ? _b : []).every(function (e) { return e.id !== targetOrgEnduser_1.id; }); } })];
|
|
539
|
+
case 82:
|
|
540
|
+
// --- bulk_load isolation ---
|
|
541
|
+
_c.sent();
|
|
542
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Regular API key session bulk_load contains no target org endusers", function () { return sdkRegularApiKey.bulk_load({ load: [{ model: 'endusers' }] }); }, { onResult: function (r) { var _a, _b; return ((_b = (_a = r.results[0]) === null || _a === void 0 ? void 0 : _a.records) !== null && _b !== void 0 ? _b : []).every(function (e) { return e.id !== targetOrgEnduser_1.id; }); } })];
|
|
543
|
+
case 83:
|
|
544
|
+
_c.sent();
|
|
545
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org session bulk_load contains no home org endusers", function () { return sdkCrossOrg.bulk_load({ load: [{ model: 'endusers' }] }); }, { onResult: function (r) { var _a, _b; return ((_b = (_a = r.results[0]) === null || _a === void 0 ? void 0 : _a.records) !== null && _b !== void 0 ? _b : []).every(function (e) { return e.id !== homeOrgEnduser_1.id; }); } })
|
|
546
|
+
// --- updateOne isolation ---
|
|
547
|
+
// 26. Password-auth session cannot updateOne a record from another org
|
|
548
|
+
];
|
|
549
|
+
case 84:
|
|
550
|
+
_c.sent();
|
|
551
|
+
// --- updateOne isolation ---
|
|
552
|
+
// 26. Password-auth session cannot updateOne a record from another org
|
|
553
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Password-auth session cannot updateOne a target org record", function () { return sdk.api.endusers.updateOne(targetOrgEnduser_1.id, { fname: 'ShouldNotUpdate' }); }, testing_1.handleAnyError)
|
|
554
|
+
// 27. Regular API key session cannot updateOne a record from another org
|
|
555
|
+
];
|
|
556
|
+
case 85:
|
|
557
|
+
// --- updateOne isolation ---
|
|
558
|
+
// 26. Password-auth session cannot updateOne a record from another org
|
|
559
|
+
_c.sent();
|
|
560
|
+
// 27. Regular API key session cannot updateOne a record from another org
|
|
561
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Regular API key session cannot updateOne a target org record", function () { return sdkRegularApiKey.api.endusers.updateOne(targetOrgEnduser_1.id, { fname: 'ShouldNotUpdate' }); }, testing_1.handleAnyError)
|
|
562
|
+
// 28. Cross-org session cannot updateOne a home org record
|
|
563
|
+
];
|
|
564
|
+
case 86:
|
|
565
|
+
// 27. Regular API key session cannot updateOne a record from another org
|
|
566
|
+
_c.sent();
|
|
567
|
+
// 28. Cross-org session cannot updateOne a home org record
|
|
568
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org session cannot updateOne a home org record", function () { return sdkCrossOrg.api.endusers.updateOne(homeOrgEnduser_1.id, { fname: 'ShouldNotUpdate' }); }, testing_1.handleAnyError)
|
|
569
|
+
// --- deleteOne isolation ---
|
|
570
|
+
// Records still exist at this point (prior deletes should have failed);
|
|
571
|
+
// cleanup in finally handles actual deletion via the correct sessions
|
|
572
|
+
// 29. Password-auth session cannot deleteOne a record from another org
|
|
573
|
+
];
|
|
574
|
+
case 87:
|
|
575
|
+
// 28. Cross-org session cannot updateOne a home org record
|
|
576
|
+
_c.sent();
|
|
577
|
+
// --- deleteOne isolation ---
|
|
578
|
+
// Records still exist at this point (prior deletes should have failed);
|
|
579
|
+
// cleanup in finally handles actual deletion via the correct sessions
|
|
580
|
+
// 29. Password-auth session cannot deleteOne a record from another org
|
|
581
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Password-auth session cannot deleteOne a target org record", function () { return sdk.api.endusers.deleteOne(targetOrgEnduser_1.id); }, testing_1.handleAnyError)
|
|
582
|
+
// 30. Regular API key session cannot deleteOne a record from another org
|
|
583
|
+
];
|
|
584
|
+
case 88:
|
|
585
|
+
// --- deleteOne isolation ---
|
|
586
|
+
// Records still exist at this point (prior deletes should have failed);
|
|
587
|
+
// cleanup in finally handles actual deletion via the correct sessions
|
|
588
|
+
// 29. Password-auth session cannot deleteOne a record from another org
|
|
589
|
+
_c.sent();
|
|
590
|
+
// 30. Regular API key session cannot deleteOne a record from another org
|
|
591
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Regular API key session cannot deleteOne a target org record", function () { return sdkRegularApiKey.api.endusers.deleteOne(targetOrgEnduser_1.id); }, testing_1.handleAnyError)
|
|
592
|
+
// 31. Cross-org session cannot deleteOne a home org record
|
|
593
|
+
];
|
|
594
|
+
case 89:
|
|
595
|
+
// 30. Regular API key session cannot deleteOne a record from another org
|
|
596
|
+
_c.sent();
|
|
597
|
+
// 31. Cross-org session cannot deleteOne a home org record
|
|
598
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org session cannot deleteOne a home org record", function () { return sdkCrossOrg.api.endusers.deleteOne(homeOrgEnduser_1.id); }, testing_1.handleAnyError)
|
|
599
|
+
// --- businessId spoofing on create ---
|
|
600
|
+
// 32. Cross-org session cannot plant a record in the home org by passing an explicit businessId
|
|
601
|
+
];
|
|
602
|
+
case 90:
|
|
603
|
+
// 31. Cross-org session cannot deleteOne a home org record
|
|
604
|
+
_c.sent();
|
|
605
|
+
// --- businessId spoofing on create ---
|
|
606
|
+
// 32. Cross-org session cannot plant a record in the home org by passing an explicit businessId
|
|
607
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org create with explicit home org businessId is rejected", function () { return sdkCrossOrg.api.endusers.createOne({ fname: 'SpoofTest', lname: 'CrossOrg', businessId: homeBusinessId }); }, testing_1.handleAnyError)
|
|
608
|
+
// 33. Home org session cannot plant a record in the target org by passing an explicit businessId
|
|
609
|
+
];
|
|
610
|
+
case 91:
|
|
611
|
+
// --- businessId spoofing on create ---
|
|
612
|
+
// 32. Cross-org session cannot plant a record in the home org by passing an explicit businessId
|
|
613
|
+
_c.sent();
|
|
614
|
+
// 33. Home org session cannot plant a record in the target org by passing an explicit businessId
|
|
615
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Home org create with explicit target org businessId is rejected", function () { return sdkDefault.api.endusers.createOne({ fname: 'SpoofTest', lname: 'HomeOrg', businessId: CROSS_ORG_TARGET_BUSINESS_ID }); }, testing_1.handleAnyError)];
|
|
616
|
+
case 92:
|
|
617
|
+
// 33. Home org session cannot plant a record in the target org by passing an explicit businessId
|
|
618
|
+
_c.sent();
|
|
619
|
+
return [3 /*break*/, 98];
|
|
620
|
+
case 93:
|
|
621
|
+
_i = 0, isolationIds_1 = isolationIds;
|
|
622
|
+
_c.label = 94;
|
|
623
|
+
case 94:
|
|
624
|
+
if (!(_i < isolationIds_1.length)) return [3 /*break*/, 97];
|
|
625
|
+
_b = isolationIds_1[_i], id = _b.id, inTargetOrg = _b.inTargetOrg;
|
|
626
|
+
session = inTargetOrg ? sdkCrossOrg : sdkDefault;
|
|
627
|
+
return [4 /*yield*/, session.api.endusers.deleteOne(id).catch(console.error)];
|
|
628
|
+
case 95:
|
|
629
|
+
_c.sent();
|
|
630
|
+
_c.label = 96;
|
|
631
|
+
case 96:
|
|
632
|
+
_i++;
|
|
633
|
+
return [3 /*break*/, 94];
|
|
634
|
+
case 97: return [7 /*endfinally*/];
|
|
635
|
+
case 98:
|
|
636
|
+
// =============================================
|
|
637
|
+
// ENDUSER SESSION TESTS
|
|
638
|
+
// =============================================
|
|
639
|
+
// 34. EnduserSession with org header is rejected
|
|
640
|
+
return [4 /*yield*/, (0, testing_1.async_test)("EnduserSession with org header is rejected", function () { return (new sdk_1.EnduserSession({
|
|
641
|
+
host: host,
|
|
642
|
+
businessId: homeBusinessId,
|
|
643
|
+
cacheKey: 'cross_org_test_enduser',
|
|
644
|
+
headers: { 'x-tellescope-organization': CROSS_ORG_TARGET_BUSINESS_ID },
|
|
645
|
+
})).test_authenticated(); }, testing_1.handleAnyError)
|
|
646
|
+
// =============================================
|
|
647
|
+
// USERS (STAFF) RESOURCE ISOLATION TESTS
|
|
648
|
+
// =============================================
|
|
649
|
+
// 35. Cross-org session getSome users contains no home org users
|
|
650
|
+
];
|
|
651
|
+
case 99:
|
|
652
|
+
// =============================================
|
|
653
|
+
// ENDUSER SESSION TESTS
|
|
654
|
+
// =============================================
|
|
655
|
+
// 34. EnduserSession with org header is rejected
|
|
656
|
+
_c.sent();
|
|
657
|
+
// =============================================
|
|
658
|
+
// USERS (STAFF) RESOURCE ISOLATION TESTS
|
|
659
|
+
// =============================================
|
|
660
|
+
// 35. Cross-org session getSome users contains no home org users
|
|
661
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org session getSome users contains no home org users", function () { return sdkCrossOrg.api.users.getSome(); }, { onResult: function (users) { return users.every(function (u) { return u.businessId !== homeBusinessId; }); } })
|
|
662
|
+
// 36. Regular API key getSome users contains no target org users
|
|
663
|
+
];
|
|
664
|
+
case 100:
|
|
665
|
+
// =============================================
|
|
666
|
+
// USERS (STAFF) RESOURCE ISOLATION TESTS
|
|
667
|
+
// =============================================
|
|
668
|
+
// 35. Cross-org session getSome users contains no home org users
|
|
669
|
+
_c.sent();
|
|
670
|
+
// 36. Regular API key getSome users contains no target org users
|
|
671
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Regular API key getSome users contains no target org users", function () { return sdkRegularApiKey.api.users.getSome(); }, { onResult: function (users) { return users.every(function (u) { return u.businessId !== CROSS_ORG_TARGET_BUSINESS_ID; }); } })
|
|
672
|
+
// =============================================
|
|
673
|
+
// CREATOR FIELD BEHAVIOR (CROSS-ORG)
|
|
674
|
+
// =============================================
|
|
675
|
+
// 37. Record created via cross-org session has creator set to home org user, not a target org user
|
|
676
|
+
];
|
|
677
|
+
case 101:
|
|
678
|
+
// 36. Regular API key getSome users contains no target org users
|
|
679
|
+
_c.sent();
|
|
680
|
+
_c.label = 102;
|
|
681
|
+
case 102:
|
|
682
|
+
_c.trys.push([102, , 104, 107]);
|
|
683
|
+
return [4 /*yield*/, (0, testing_1.async_test)("Cross-org created record has a creator from the home org, not the target org", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
684
|
+
var created, targetOrgUserIds, _a;
|
|
685
|
+
return __generator(this, function (_b) {
|
|
686
|
+
switch (_b.label) {
|
|
687
|
+
case 0: return [4 /*yield*/, sdkCrossOrg.api.endusers.createOne({ fname: 'CreatorTest', lname: 'CrossOrg' })];
|
|
688
|
+
case 1:
|
|
689
|
+
created = _b.sent();
|
|
690
|
+
creatorTestId_1 = created.id;
|
|
691
|
+
_a = Set.bind;
|
|
692
|
+
return [4 /*yield*/, sdkCrossOrg.api.users.getSome()];
|
|
693
|
+
case 2:
|
|
694
|
+
targetOrgUserIds = new (_a.apply(Set, [void 0, (_b.sent()).map(function (u) { return u.id; })]))();
|
|
695
|
+
return [2 /*return*/, created.creator !== undefined && !targetOrgUserIds.has(created.creator)];
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
}); }, { onResult: function (r) { return r === true; } })];
|
|
699
|
+
case 103:
|
|
700
|
+
_c.sent();
|
|
701
|
+
return [3 /*break*/, 107];
|
|
702
|
+
case 104:
|
|
703
|
+
if (!creatorTestId_1) return [3 /*break*/, 106];
|
|
704
|
+
return [4 /*yield*/, sdkCrossOrg.api.endusers.deleteOne(creatorTestId_1).catch(console.error)];
|
|
705
|
+
case 105:
|
|
706
|
+
_c.sent();
|
|
707
|
+
_c.label = 106;
|
|
708
|
+
case 106: return [7 /*endfinally*/];
|
|
709
|
+
case 107: return [3 /*break*/, 110];
|
|
710
|
+
case 108: return [4 /*yield*/, sdk.api.api_keys.deleteOne(regularApiKeyRecord.id).catch(console.error)];
|
|
711
|
+
case 109:
|
|
712
|
+
_c.sent();
|
|
713
|
+
return [7 /*endfinally*/];
|
|
714
|
+
case 110: return [2 /*return*/];
|
|
715
|
+
}
|
|
716
|
+
});
|
|
717
|
+
});
|
|
718
|
+
};
|
|
719
|
+
exports.cross_org_api_key_tests = cross_org_api_key_tests;
|
|
720
|
+
// Allow running independently
|
|
721
|
+
if (require.main === module) {
|
|
722
|
+
console.log("Using API URL: ".concat(host));
|
|
723
|
+
var sdk_2 = new sdk_1.Session({ host: host });
|
|
724
|
+
var sdkNonAdmin_1 = new sdk_1.Session({ host: host });
|
|
725
|
+
var runTests = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
726
|
+
return __generator(this, function (_a) {
|
|
727
|
+
switch (_a.label) {
|
|
728
|
+
case 0: return [4 /*yield*/, (0, setup_1.setup_tests)(sdk_2, sdkNonAdmin_1)];
|
|
729
|
+
case 1:
|
|
730
|
+
_a.sent();
|
|
731
|
+
return [4 /*yield*/, (0, exports.cross_org_api_key_tests)({ sdk: sdk_2, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
732
|
+
case 2:
|
|
733
|
+
_a.sent();
|
|
734
|
+
return [2 /*return*/];
|
|
735
|
+
}
|
|
736
|
+
});
|
|
737
|
+
}); };
|
|
738
|
+
runTests()
|
|
739
|
+
.then(function () {
|
|
740
|
+
console.log("Cross-org API key test suite completed successfully");
|
|
741
|
+
process.exit(0);
|
|
742
|
+
})
|
|
743
|
+
.catch(function (error) {
|
|
744
|
+
console.error("Cross-org API key test suite failed:", error);
|
|
745
|
+
process.exit(1);
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
//# sourceMappingURL=cross_org_api_key.test.js.map
|