@tellescope/sdk 1.255.6 → 1.255.8
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/cjs/sdk.d.ts +2 -2
- package/lib/cjs/session.d.ts +1 -0
- package/lib/cjs/session.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/custom_dashboards.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/custom_dashboards.test.js +258 -32
- package/lib/cjs/tests/api_tests/custom_dashboards.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/gmail_sync_related_contact_emails.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/gmail_sync_related_contact_emails.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/gmail_sync_related_contact_emails.test.js +183 -0
- package/lib/cjs/tests/api_tests/gmail_sync_related_contact_emails.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/journey_delete_cancels_actions.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/journey_delete_cancels_actions.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/journey_delete_cancels_actions.test.js +250 -0
- package/lib/cjs/tests/api_tests/journey_delete_cancels_actions.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/register_business_id_injection.test.d.ts +36 -0
- package/lib/cjs/tests/api_tests/security/register_business_id_injection.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/register_business_id_injection.test.js +203 -0
- package/lib/cjs/tests/api_tests/security/register_business_id_injection.test.js.map +1 -0
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +174 -166
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/enduser.d.ts +0 -1
- package/lib/esm/enduser.d.ts.map +1 -1
- package/lib/esm/sdk.d.ts +2 -3
- package/lib/esm/sdk.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/gmail_sync_related_contact_emails.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/gmail_sync_related_contact_emails.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/gmail_sync_related_contact_emails.test.js +179 -0
- package/lib/esm/tests/api_tests/gmail_sync_related_contact_emails.test.js.map +1 -0
- package/lib/esm/tests/api_tests/journey_delete_cancels_actions.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/journey_delete_cancels_actions.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/journey_delete_cancels_actions.test.js +223 -0
- package/lib/esm/tests/api_tests/journey_delete_cancels_actions.test.js.map +1 -0
- package/lib/esm/tests/api_tests/medication_added_trigger.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/medication_added_trigger.test.js +136 -206
- package/lib/esm/tests/api_tests/medication_added_trigger.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts +0 -10
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js +41 -184
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/register_business_id_injection.test.d.ts +36 -0
- package/lib/esm/tests/api_tests/security/register_business_id_injection.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/register_business_id_injection.test.js +196 -0
- package/lib/esm/tests/api_tests/security/register_business_id_injection.test.js.map +1 -0
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +127 -131
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/src/tests/api_tests/custom_dashboards.test.ts +208 -0
- package/src/tests/api_tests/journey_delete_cancels_actions.test.ts +152 -0
- package/src/tests/api_tests/security/register_business_id_injection.test.ts +140 -0
- package/src/tests/tests.ts +5 -1
- package/test_generated.pdf +0 -0
|
@@ -0,0 +1,183 @@
|
|
|
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.gmail_sync_related_contact_emails_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
|
+
// Builds the same related-contact-scoped mdbFilter the EnduserProfile Emails tab (useEmailThreads)
|
|
46
|
+
// constructs on the client — anchored on enduserId so the address scan only runs across a related
|
|
47
|
+
// contact's emails. This exercises the display/read path for CU-86e23ffay without a live Gmail sync.
|
|
48
|
+
var buildRelatedContactFilter = function (_a) {
|
|
49
|
+
var enduserId = _a.enduserId, relatedIds = _a.relatedIds, addresses = _a.addresses;
|
|
50
|
+
return ({
|
|
51
|
+
$and: [{
|
|
52
|
+
$or: [
|
|
53
|
+
{ enduserId: enduserId },
|
|
54
|
+
{ enduserId: { $in: relatedIds }, $or: [
|
|
55
|
+
{ source: { $in: addresses } },
|
|
56
|
+
{ destination: { $in: addresses } },
|
|
57
|
+
{ cc: { $in: addresses } },
|
|
58
|
+
] },
|
|
59
|
+
],
|
|
60
|
+
}],
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
// Main test function that can be called independently
|
|
64
|
+
var gmail_sync_related_contact_emails_tests = function (_a) {
|
|
65
|
+
var sdk = _a.sdk;
|
|
66
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
67
|
+
var unique, careAddress, husbandAddress, wifeAddress, strangerAddress, createdEnduserIds, createdEmailIds, wife, husband, stranger, wifeReloaded, relatedIds, husbandEmail_1, strangerEmail_1, wifeFilter, wifeEmails, husbandOwn;
|
|
68
|
+
var _b;
|
|
69
|
+
return __generator(this, function (_c) {
|
|
70
|
+
switch (_c.label) {
|
|
71
|
+
case 0:
|
|
72
|
+
(0, testing_1.log_header)("Gmail Sync — Related Contact Email Association Tests");
|
|
73
|
+
unique = Date.now();
|
|
74
|
+
careAddress = "care-team+".concat(unique, "@example.com").toLowerCase();
|
|
75
|
+
husbandAddress = "husband+".concat(unique, "@example.com").toLowerCase();
|
|
76
|
+
wifeAddress = "wife+".concat(unique, "@example.com").toLowerCase();
|
|
77
|
+
strangerAddress = "stranger+".concat(unique, "@example.com").toLowerCase();
|
|
78
|
+
createdEnduserIds = [];
|
|
79
|
+
createdEmailIds = [];
|
|
80
|
+
_c.label = 1;
|
|
81
|
+
case 1:
|
|
82
|
+
_c.trys.push([1, , 10, 13]);
|
|
83
|
+
return [4 /*yield*/, sdk.api.endusers.createOne({ fname: 'Wife', email: wifeAddress })];
|
|
84
|
+
case 2:
|
|
85
|
+
wife = _c.sent();
|
|
86
|
+
return [4 /*yield*/, sdk.api.endusers.createOne({
|
|
87
|
+
fname: 'Husband', email: husbandAddress,
|
|
88
|
+
relationships: [{ type: 'Spouse', id: wife.id }],
|
|
89
|
+
})
|
|
90
|
+
// An unrelated third contact who also appears (CC'd) on an unrelated email
|
|
91
|
+
];
|
|
92
|
+
case 3:
|
|
93
|
+
husband = _c.sent();
|
|
94
|
+
return [4 /*yield*/, sdk.api.endusers.createOne({ fname: 'Stranger', email: strangerAddress })];
|
|
95
|
+
case 4:
|
|
96
|
+
stranger = _c.sent();
|
|
97
|
+
createdEnduserIds.push(wife.id, husband.id, stranger.id);
|
|
98
|
+
return [4 /*yield*/, sdk.api.endusers.getOne(wife.id)];
|
|
99
|
+
case 5:
|
|
100
|
+
wifeReloaded = _c.sent();
|
|
101
|
+
relatedIds = ((_b = wifeReloaded.relationships) !== null && _b !== void 0 ? _b : []).map(function (r) { return r.id; });
|
|
102
|
+
(0, testing_1.assert)(relatedIds.includes(husband.id), "Wife's relationships did not include Husband after bidirectional sync", "Relationship bidirectionally synced onto Wife");
|
|
103
|
+
return [4 /*yield*/, sdk.api.emails.createOne({
|
|
104
|
+
enduserId: husband.id,
|
|
105
|
+
subject: "Husband to care team ".concat(unique),
|
|
106
|
+
textContent: 'inbound from husband, wife cc',
|
|
107
|
+
cc: [wifeAddress],
|
|
108
|
+
inbound: true,
|
|
109
|
+
logOnly: true,
|
|
110
|
+
})];
|
|
111
|
+
case 6:
|
|
112
|
+
husbandEmail_1 = _c.sent();
|
|
113
|
+
createdEmailIds.push(husbandEmail_1.id);
|
|
114
|
+
return [4 /*yield*/, sdk.api.emails.createOne({
|
|
115
|
+
enduserId: stranger.id,
|
|
116
|
+
subject: "Stranger email ".concat(unique),
|
|
117
|
+
textContent: 'unrelated contact, wife cc',
|
|
118
|
+
cc: [wifeAddress],
|
|
119
|
+
inbound: true,
|
|
120
|
+
logOnly: true,
|
|
121
|
+
})];
|
|
122
|
+
case 7:
|
|
123
|
+
strangerEmail_1 = _c.sent();
|
|
124
|
+
createdEmailIds.push(strangerEmail_1.id);
|
|
125
|
+
wifeFilter = buildRelatedContactFilter({
|
|
126
|
+
enduserId: wife.id,
|
|
127
|
+
relatedIds: relatedIds,
|
|
128
|
+
addresses: [wifeAddress],
|
|
129
|
+
});
|
|
130
|
+
return [4 /*yield*/, sdk.api.emails.getSome({ mdbFilter: wifeFilter })];
|
|
131
|
+
case 8:
|
|
132
|
+
wifeEmails = _c.sent();
|
|
133
|
+
(0, testing_1.assert)(!!wifeEmails.find(function (e) { return e.id === husbandEmail_1.id; }), "Husband's email (Wife CC'd) did NOT surface on Wife's related-contact query", "Husband's CC'd email cross-surfaces on Wife via related-contact match");
|
|
134
|
+
(0, testing_1.assert)(!wifeEmails.find(function (e) { return e.id === strangerEmail_1.id; }), "Unrelated stranger email incorrectly cross-surfaced on Wife", "Unrelated contact's email does NOT cross-surface (control)");
|
|
135
|
+
return [4 /*yield*/, sdk.api.emails.getSome({ filter: { enduserId: husband.id } })];
|
|
136
|
+
case 9:
|
|
137
|
+
husbandOwn = _c.sent();
|
|
138
|
+
(0, testing_1.assert)(!!husbandOwn.find(function (e) { return e.id === husbandEmail_1.id; }), "Husband's own email missing from his single-enduserId load", "Normal 1:1 load still returns the email on its owning contact");
|
|
139
|
+
return [3 /*break*/, 13];
|
|
140
|
+
case 10:
|
|
141
|
+
// Cleanup
|
|
142
|
+
return [4 /*yield*/, Promise.all(createdEmailIds.map(function (id) { return sdk.api.emails.deleteOne(id).catch(function () { }); }))];
|
|
143
|
+
case 11:
|
|
144
|
+
// Cleanup
|
|
145
|
+
_c.sent();
|
|
146
|
+
return [4 /*yield*/, Promise.all(createdEnduserIds.map(function (id) { return sdk.api.endusers.deleteOne(id).catch(function () { }); }))];
|
|
147
|
+
case 12:
|
|
148
|
+
_c.sent();
|
|
149
|
+
return [7 /*endfinally*/];
|
|
150
|
+
case 13: return [2 /*return*/];
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
exports.gmail_sync_related_contact_emails_tests = gmail_sync_related_contact_emails_tests;
|
|
156
|
+
// Allow running this test file independently
|
|
157
|
+
if (require.main === module) {
|
|
158
|
+
var sdk_2 = new sdk_1.Session({ host: host });
|
|
159
|
+
var sdkNonAdmin_1 = new sdk_1.Session({ host: host });
|
|
160
|
+
var runTests = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
161
|
+
return __generator(this, function (_a) {
|
|
162
|
+
switch (_a.label) {
|
|
163
|
+
case 0: return [4 /*yield*/, (0, setup_1.setup_tests)(sdk_2, sdkNonAdmin_1)];
|
|
164
|
+
case 1:
|
|
165
|
+
_a.sent();
|
|
166
|
+
return [4 /*yield*/, (0, exports.gmail_sync_related_contact_emails_tests)({ sdk: sdk_2, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
167
|
+
case 2:
|
|
168
|
+
_a.sent();
|
|
169
|
+
return [2 /*return*/];
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}); };
|
|
173
|
+
runTests()
|
|
174
|
+
.then(function () {
|
|
175
|
+
console.log("✅ Gmail sync related contact emails test suite completed successfully");
|
|
176
|
+
process.exit(0);
|
|
177
|
+
})
|
|
178
|
+
.catch(function (error) {
|
|
179
|
+
console.error("❌ Gmail sync related contact emails test suite failed:", error);
|
|
180
|
+
process.exit(1);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=gmail_sync_related_contact_emails.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gmail_sync_related_contact_emails.test.js","sourceRoot":"","sources":["../../../../src/tests/api_tests/gmail_sync_related_contact_emails.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journey_delete_cancels_actions.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/api_tests/journey_delete_cancels_actions.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAMnC,eAAO,MAAM,oCAAoC;SAAuC,OAAO;iBAAe,OAAO;mBAmGpH,CAAA"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
35
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
36
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
37
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
38
|
+
function step(op) {
|
|
39
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
40
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
41
|
+
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;
|
|
42
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
43
|
+
switch (op[0]) {
|
|
44
|
+
case 0: case 1: t = op; break;
|
|
45
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
46
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
47
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
48
|
+
default:
|
|
49
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
50
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
51
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
52
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
53
|
+
if (t[2]) _.ops.pop();
|
|
54
|
+
_.trys.pop(); continue;
|
|
55
|
+
}
|
|
56
|
+
op = body.call(thisArg, _);
|
|
57
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
58
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
62
|
+
exports.journey_delete_cancels_actions_tests = void 0;
|
|
63
|
+
var sdk_1 = require("../../sdk");
|
|
64
|
+
var testing_1 = require("@tellescope/testing");
|
|
65
|
+
var constants_1 = require("@tellescope/constants");
|
|
66
|
+
var host = process.env.API_URL || 'http://localhost:8080';
|
|
67
|
+
var journey_delete_cancels_actions_tests = function (_a) {
|
|
68
|
+
var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
|
|
69
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
70
|
+
var journeyId, enduserId, stepId, journey, step, enduser_1, activeAction_1, finishedAction_1, before, expectedReason_1, finishedAfter;
|
|
71
|
+
return __generator(this, function (_b) {
|
|
72
|
+
switch (_b.label) {
|
|
73
|
+
case 0:
|
|
74
|
+
(0, testing_1.log_header)("Journey Delete Cancels Pending Actions Tests");
|
|
75
|
+
_b.label = 1;
|
|
76
|
+
case 1:
|
|
77
|
+
_b.trys.push([1, , 11, 13]);
|
|
78
|
+
return [4 /*yield*/, sdk.api.journeys.createOne({ title: "Cascade Cancel Journey " + Date.now() })];
|
|
79
|
+
case 2:
|
|
80
|
+
journey = _b.sent();
|
|
81
|
+
journeyId = journey.id;
|
|
82
|
+
return [4 /*yield*/, sdk.api.automation_steps.createOne({
|
|
83
|
+
journeyId: journey.id,
|
|
84
|
+
action: { type: 'setEnduserStatus', info: { status: 'Test Status' } },
|
|
85
|
+
events: [{ type: 'onJourneyStart', info: {} }],
|
|
86
|
+
})];
|
|
87
|
+
case 3:
|
|
88
|
+
step = _b.sent();
|
|
89
|
+
stepId = step.id;
|
|
90
|
+
return [4 /*yield*/, sdk.api.endusers.createOne({
|
|
91
|
+
fname: 'Cascade',
|
|
92
|
+
lname: 'Cancel',
|
|
93
|
+
email: 'test-cascade-cancel-' + Date.now() + '@example.com',
|
|
94
|
+
})];
|
|
95
|
+
case 4:
|
|
96
|
+
enduser_1 = _b.sent();
|
|
97
|
+
enduserId = enduser_1.id;
|
|
98
|
+
return [4 /*yield*/, sdk.api.automated_actions.createOne({
|
|
99
|
+
journeyId: journey.id,
|
|
100
|
+
automationStepId: step.id,
|
|
101
|
+
enduserId: enduser_1.id,
|
|
102
|
+
processAfter: Date.now() + 1000000,
|
|
103
|
+
status: 'active',
|
|
104
|
+
event: { type: 'onJourneyStart', info: {} },
|
|
105
|
+
action: { type: 'setEnduserStatus', info: { status: 'Test Status' } },
|
|
106
|
+
})
|
|
107
|
+
// Create a finished action to confirm it is left untouched by the cascade
|
|
108
|
+
];
|
|
109
|
+
case 5:
|
|
110
|
+
activeAction_1 = _b.sent();
|
|
111
|
+
return [4 /*yield*/, sdk.api.automated_actions.createOne({
|
|
112
|
+
journeyId: journey.id,
|
|
113
|
+
automationStepId: step.id,
|
|
114
|
+
enduserId: enduser_1.id,
|
|
115
|
+
processAfter: Date.now() + 1000000,
|
|
116
|
+
status: 'finished',
|
|
117
|
+
event: { type: 'onJourneyStart', info: {} },
|
|
118
|
+
action: { type: 'setEnduserStatus', info: { status: 'Test Status' } },
|
|
119
|
+
})
|
|
120
|
+
// Assert the action starts active
|
|
121
|
+
];
|
|
122
|
+
case 6:
|
|
123
|
+
finishedAction_1 = _b.sent();
|
|
124
|
+
return [4 /*yield*/, sdk.api.automated_actions.getOne(activeAction_1.id)];
|
|
125
|
+
case 7:
|
|
126
|
+
before = _b.sent();
|
|
127
|
+
if (before.status !== 'active') {
|
|
128
|
+
throw new Error("Expected action to start 'active', got '".concat(before.status, "'"));
|
|
129
|
+
}
|
|
130
|
+
console.log("✓ Action is active before journey deletion");
|
|
131
|
+
// Delete the journey — this should cascade cancel the pending action
|
|
132
|
+
return [4 /*yield*/, sdk.api.journeys.deleteOne(journey.id)];
|
|
133
|
+
case 8:
|
|
134
|
+
// Delete the journey — this should cascade cancel the pending action
|
|
135
|
+
_b.sent();
|
|
136
|
+
journeyId = undefined; // already deleted, skip in cleanup
|
|
137
|
+
expectedReason_1 = constants_1.AUTOMATED_ACTION_CANCEL_REASONS.indexOf('Journey Deleted');
|
|
138
|
+
return [4 /*yield*/, pollForResults(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
139
|
+
var actions, active, finished;
|
|
140
|
+
return __generator(this, function (_a) {
|
|
141
|
+
switch (_a.label) {
|
|
142
|
+
case 0: return [4 /*yield*/, sdk.api.automated_actions.getSome({ filter: { enduserId: enduser_1.id } })];
|
|
143
|
+
case 1:
|
|
144
|
+
actions = _a.sent();
|
|
145
|
+
active = actions.find(function (a) { return a.id === activeAction_1.id; });
|
|
146
|
+
finished = actions.find(function (a) { return a.id === finishedAction_1.id; });
|
|
147
|
+
return [2 /*return*/, { active: active, finished: finished }];
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}); }, function (_a) {
|
|
151
|
+
var active = _a.active;
|
|
152
|
+
return ((active === null || active === void 0 ? void 0 : active.status) === 'cancelled'
|
|
153
|
+
&& (active === null || active === void 0 ? void 0 : active.cancelReason) === expectedReason_1
|
|
154
|
+
&& (active === null || active === void 0 ? void 0 : active.cancelledBy) === sdk.userInfo.id);
|
|
155
|
+
}, 'Active action should be cancelled with Journey Deleted reason and cancelledBy after journey deletion')];
|
|
156
|
+
case 9:
|
|
157
|
+
_b.sent();
|
|
158
|
+
console.log("✓ Active action cancelled with Journey Deleted reason and cancelledBy set to deleting user");
|
|
159
|
+
return [4 /*yield*/, sdk.api.automated_actions.getOne(finishedAction_1.id)];
|
|
160
|
+
case 10:
|
|
161
|
+
finishedAfter = _b.sent();
|
|
162
|
+
if (finishedAfter.status !== 'finished') {
|
|
163
|
+
throw new Error("Expected finished action to remain 'finished', got '".concat(finishedAfter.status, "'"));
|
|
164
|
+
}
|
|
165
|
+
console.log("✓ Finished action left untouched");
|
|
166
|
+
console.log("✅ Journey Delete Cancels Pending Actions tests completed successfully");
|
|
167
|
+
return [3 /*break*/, 13];
|
|
168
|
+
case 11:
|
|
169
|
+
// Cleanup — journey is already deleted if the flow completed
|
|
170
|
+
return [4 /*yield*/, Promise.all([
|
|
171
|
+
enduserId ? sdk.api.endusers.deleteOne(enduserId).catch(function () { }) : undefined,
|
|
172
|
+
stepId ? sdk.api.automation_steps.deleteOne(stepId).catch(function () { }) : undefined,
|
|
173
|
+
journeyId ? sdk.api.journeys.deleteOne(journeyId).catch(function () { }) : undefined,
|
|
174
|
+
])];
|
|
175
|
+
case 12:
|
|
176
|
+
// Cleanup — journey is already deleted if the flow completed
|
|
177
|
+
_b.sent();
|
|
178
|
+
return [7 /*endfinally*/];
|
|
179
|
+
case 13: return [2 /*return*/];
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
exports.journey_delete_cancels_actions_tests = journey_delete_cancels_actions_tests;
|
|
185
|
+
var pollForResults = function (fetchFn, evaluateFn, description, intervalMs, maxIterations) {
|
|
186
|
+
if (intervalMs === void 0) { intervalMs = 500; }
|
|
187
|
+
if (maxIterations === void 0) { maxIterations = 30; }
|
|
188
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
189
|
+
var lastResult, i;
|
|
190
|
+
return __generator(this, function (_a) {
|
|
191
|
+
switch (_a.label) {
|
|
192
|
+
case 0:
|
|
193
|
+
i = 0;
|
|
194
|
+
_a.label = 1;
|
|
195
|
+
case 1:
|
|
196
|
+
if (!(i < maxIterations)) return [3 /*break*/, 5];
|
|
197
|
+
return [4 /*yield*/, (0, testing_1.wait)(undefined, intervalMs)];
|
|
198
|
+
case 2:
|
|
199
|
+
_a.sent();
|
|
200
|
+
return [4 /*yield*/, fetchFn()];
|
|
201
|
+
case 3:
|
|
202
|
+
lastResult = _a.sent();
|
|
203
|
+
if (evaluateFn(lastResult)) {
|
|
204
|
+
console.log("\u2713 ".concat(description, " - completed after ").concat((i + 1) * intervalMs, "ms"));
|
|
205
|
+
return [2 /*return*/];
|
|
206
|
+
}
|
|
207
|
+
_a.label = 4;
|
|
208
|
+
case 4:
|
|
209
|
+
i++;
|
|
210
|
+
return [3 /*break*/, 1];
|
|
211
|
+
case 5:
|
|
212
|
+
console.log('Final polling result:', lastResult);
|
|
213
|
+
throw new Error("Polling timeout: ".concat(description, " - waited ").concat(maxIterations * intervalMs, "ms"));
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
};
|
|
218
|
+
// Allow running this test file independently
|
|
219
|
+
if (require.main === module) {
|
|
220
|
+
console.log("\uD83C\uDF10 Using API URL: ".concat(host));
|
|
221
|
+
var sdk_2 = new sdk_1.Session({ host: host });
|
|
222
|
+
var sdkNonAdmin_1 = new sdk_1.Session({ host: host });
|
|
223
|
+
var runTests = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
224
|
+
var setup_tests;
|
|
225
|
+
return __generator(this, function (_a) {
|
|
226
|
+
switch (_a.label) {
|
|
227
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("../setup")); })];
|
|
228
|
+
case 1:
|
|
229
|
+
setup_tests = (_a.sent()).setup_tests;
|
|
230
|
+
return [4 /*yield*/, setup_tests(sdk_2, sdkNonAdmin_1)];
|
|
231
|
+
case 2:
|
|
232
|
+
_a.sent();
|
|
233
|
+
return [4 /*yield*/, (0, exports.journey_delete_cancels_actions_tests)({ sdk: sdk_2, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
234
|
+
case 3:
|
|
235
|
+
_a.sent();
|
|
236
|
+
return [2 /*return*/];
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}); };
|
|
240
|
+
runTests()
|
|
241
|
+
.then(function () {
|
|
242
|
+
console.log("✅ Journey Delete Cancels Pending Actions test suite completed successfully");
|
|
243
|
+
process.exit(0);
|
|
244
|
+
})
|
|
245
|
+
.catch(function (error) {
|
|
246
|
+
console.error("❌ Journey Delete Cancels Pending Actions test suite failed:", error);
|
|
247
|
+
process.exit(1);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=journey_delete_cancels_actions.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journey_delete_cancels_actions.test.js","sourceRoot":"","sources":["../../../../src/tests/api_tests/journey_delete_cancels_actions.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Session } from "../../../sdk";
|
|
2
|
+
/**
|
|
3
|
+
* Reproduction + regression test for the reported vulnerability:
|
|
4
|
+
*
|
|
5
|
+
* A @wearehackerone.com email "joined" a customer's organization without being invited, and
|
|
6
|
+
* duplicate user records existed for that email — each bound to a different businessId.
|
|
7
|
+
*
|
|
8
|
+
* Root cause: the public `POST /v1/users/register` endpoint. `addPublicEndpoint` accepts an
|
|
9
|
+
* OPTIONAL, caller-supplied `businessId` (routing.ts) and bakes it into the handler's DB. The
|
|
10
|
+
* register handler's only duplicate guard (`DB.users.findOne({ email })`) is therefore scoped to
|
|
11
|
+
* whatever org the caller named, and the subsequent `DB.users.insertOne(...)` stamps that
|
|
12
|
+
* caller-supplied businessId onto a new `accountType: 'Business'` user — bypassing the
|
|
13
|
+
* globalUnique: ['email'] enforcement that only runs in the generic create route.
|
|
14
|
+
*
|
|
15
|
+
* The "victim org" here is the test admin's own org (sdk.userInfo.businessId): an org the
|
|
16
|
+
* anonymous caller was never invited to. The admin is used purely to OBSERVE whether an
|
|
17
|
+
* uninvited user record materialized inside their org (getOne({ email }) is org-scoped and
|
|
18
|
+
* throws when the email is absent from the caller's tenant).
|
|
19
|
+
*
|
|
20
|
+
* Expected results:
|
|
21
|
+
* - VULNERABLE code: the assertions FAIL — the planted user appears inside the victim org,
|
|
22
|
+
* proving the exploit ("EXPLOIT CONFIRMED" in the failure message).
|
|
23
|
+
* - FIXED code: register ignores the caller-supplied businessId (self-signups are created
|
|
24
|
+
* org-less and duplicates are rejected globally), so nothing appears in the victim org and
|
|
25
|
+
* the assertions PASS.
|
|
26
|
+
*
|
|
27
|
+
* Uses unique emails per run (Date.now()) so re-runs never collide on the platform-wide unique
|
|
28
|
+
* email constraint. NOTE: on the FIXED path these registrations create org-less user records
|
|
29
|
+
* that an org-scoped admin cannot delete — harmless residue (unique emails), inherent to the
|
|
30
|
+
* legitimate "root register, no org" signup behavior.
|
|
31
|
+
*/
|
|
32
|
+
export declare const register_business_id_injection_tests: ({ sdk }: {
|
|
33
|
+
sdk: Session;
|
|
34
|
+
sdkNonAdmin: Session;
|
|
35
|
+
}) => Promise<void>;
|
|
36
|
+
//# sourceMappingURL=register_business_id_injection.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register_business_id_injection.test.d.ts","sourceRoot":"","sources":["../../../../../src/tests/api_tests/security/register_business_id_injection.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAsBtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,oCAAoC;SAA2B,OAAO;iBAAe,OAAO;mBA+DxG,CAAA"}
|