@tellescope/sdk 1.256.15 → 1.256.16
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/tests/api_tests/security/file-link-session-confinement.test.d.ts +5 -0
- package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.js +357 -0
- package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.js.map +1 -0
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +2 -0
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/sdk.d.ts +2 -2
- package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.d.ts +5 -0
- package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.js +349 -0
- package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.js.map +1 -0
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +2 -0
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/tests/api_tests/security/file-link-session-confinement.test.ts +291 -0
- package/src/tests/tests.ts +2 -0
- package/test_generated.pdf +0 -0
package/lib/esm/sdk.d.ts
CHANGED
|
@@ -4193,7 +4193,7 @@ export declare class Session extends SessionManager {
|
|
|
4193
4193
|
iat: number;
|
|
4194
4194
|
exp: number;
|
|
4195
4195
|
requiresMFA?: boolean | undefined;
|
|
4196
|
-
sessionScopes?: ("video-join-link" | "video-start-link" | "public-form" | "appointment-booking" | "ics-download" | "embeddables-token" | "portal-preview")[] | undefined;
|
|
4196
|
+
sessionScopes?: ("video-join-link" | "video-start-link" | "public-form" | "appointment-booking" | "ics-download" | "embeddables-token" | "portal-preview" | "file-download-link" | "file-download-shared-link")[] | undefined;
|
|
4197
4197
|
scopeContext?: import("@tellescope/types-models").SessionScopeContext | undefined;
|
|
4198
4198
|
allowedPaths?: string[] | undefined;
|
|
4199
4199
|
inbox_threads?: number | undefined;
|
|
@@ -4358,7 +4358,7 @@ export declare class Session extends SessionManager {
|
|
|
4358
4358
|
iat: number;
|
|
4359
4359
|
exp: number;
|
|
4360
4360
|
requiresMFA?: boolean | undefined;
|
|
4361
|
-
sessionScopes?: ("video-join-link" | "video-start-link" | "public-form" | "appointment-booking" | "ics-download" | "embeddables-token" | "portal-preview")[] | undefined;
|
|
4361
|
+
sessionScopes?: ("video-join-link" | "video-start-link" | "public-form" | "appointment-booking" | "ics-download" | "embeddables-token" | "portal-preview" | "file-download-link" | "file-download-shared-link")[] | undefined;
|
|
4362
4362
|
scopeContext?: import("@tellescope/types-models").SessionScopeContext | undefined;
|
|
4363
4363
|
allowedPaths?: string[] | undefined;
|
|
4364
4364
|
inbox_threads?: number | undefined;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Check } from "../../setup_isolated";
|
|
2
|
+
export declare const file_link_session_confinement_checks: () => Promise<Check[]>;
|
|
3
|
+
/** Asserting wrapper, for standalone runs and for sequential use in the suite. */
|
|
4
|
+
export declare const file_link_session_confinement_tests: () => Promise<void>;
|
|
5
|
+
//# sourceMappingURL=file-link-session-confinement.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-link-session-confinement.test.d.ts","sourceRoot":"","sources":["../../../../../src/tests/api_tests/security/file-link-session-confinement.test.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,EAEN,MAAM,sBAAsB,CAAA;AA2D7B,eAAO,MAAM,oCAAoC,QAAa,QAAQ,KAAK,EAAE,CA4M5E,CAAA;AAED,kFAAkF;AAClF,eAAO,MAAM,mCAAmC,qBAE/C,CAAA"}
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
12
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
+
function step(op) {
|
|
15
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
17
|
+
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;
|
|
18
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
19
|
+
switch (op[0]) {
|
|
20
|
+
case 0: case 1: t = op; break;
|
|
21
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
+
default:
|
|
25
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
+
if (t[2]) _.ops.pop();
|
|
30
|
+
_.trys.pop(); continue;
|
|
31
|
+
}
|
|
32
|
+
op = body.call(thisArg, _);
|
|
33
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
require('source-map-support').install();
|
|
38
|
+
import axios from "axios";
|
|
39
|
+
import { assert_checks, setup_isolated_tenant, } from "../../setup_isolated";
|
|
40
|
+
var host = process.env.API_URL || 'http://localhost:8080';
|
|
41
|
+
var RAND = function () { return Math.random().toString(36).slice(2, 10); };
|
|
42
|
+
var probe = function (method, path, o) {
|
|
43
|
+
if (o === void 0) { o = {}; }
|
|
44
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
45
|
+
var r;
|
|
46
|
+
return __generator(this, function (_a) {
|
|
47
|
+
switch (_a.label) {
|
|
48
|
+
case 0: return [4 /*yield*/, axios.request({
|
|
49
|
+
method: method,
|
|
50
|
+
url: "".concat(host, "/v1").concat(path),
|
|
51
|
+
params: o.params,
|
|
52
|
+
data: o.data,
|
|
53
|
+
headers: o.token ? { Authorization: "Bearer ".concat(o.token) } : undefined,
|
|
54
|
+
validateStatus: function () { return true; },
|
|
55
|
+
})];
|
|
56
|
+
case 1:
|
|
57
|
+
r = _a.sent();
|
|
58
|
+
return [2 /*return*/, { status: r.status, body: r.data }];
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
export var file_link_session_confinement_checks = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
64
|
+
var checks, record, tenant, sdk_1, enduser_1, newFile, fileA_1, fileB_1, mint, adminFiles, confinement_probes, plain, shared, methods, send, verify, _a, header, payload, decoded, forged, forgedSend, send, e_1;
|
|
65
|
+
return __generator(this, function (_b) {
|
|
66
|
+
switch (_b.label) {
|
|
67
|
+
case 0:
|
|
68
|
+
checks = [];
|
|
69
|
+
record = function (label, pass, detail) { return checks.push({ label: label, pass: pass, detail: detail }); };
|
|
70
|
+
_b.label = 1;
|
|
71
|
+
case 1:
|
|
72
|
+
_b.trys.push([1, , 22, 27]);
|
|
73
|
+
return [4 /*yield*/, setup_isolated_tenant({
|
|
74
|
+
name: "FileLink ".concat(RAND()), users: [{ isAdmin: true }], apiKeys: 0,
|
|
75
|
+
})];
|
|
76
|
+
case 2:
|
|
77
|
+
tenant = _b.sent();
|
|
78
|
+
sdk_1 = tenant.sdk;
|
|
79
|
+
return [4 /*yield*/, sdk_1.api.endusers.createOne({
|
|
80
|
+
fname: 'FileLink', lname: 'Recipient',
|
|
81
|
+
email: "dontsend-filelink-".concat(RAND(), "@tellescope.com"),
|
|
82
|
+
phone: '+15555550100',
|
|
83
|
+
dateOfBirth: '01-01-1990',
|
|
84
|
+
})
|
|
85
|
+
// No S3 upload needed: prepare_file_upload inserts the files record with its secureName
|
|
86
|
+
// immediately, and file_download_URL only SIGNS a GET url — it never checks the object exists.
|
|
87
|
+
];
|
|
88
|
+
case 3:
|
|
89
|
+
enduser_1 = _b.sent();
|
|
90
|
+
newFile = function (name) { return __awaiter(void 0, void 0, void 0, function () {
|
|
91
|
+
return __generator(this, function (_a) {
|
|
92
|
+
switch (_a.label) {
|
|
93
|
+
case 0: return [4 /*yield*/, sdk_1.api.files.prepare_file_upload({
|
|
94
|
+
name: name,
|
|
95
|
+
type: 'application/pdf', size: 1000, enduserId: enduser_1.id,
|
|
96
|
+
})];
|
|
97
|
+
case 1: return [2 /*return*/, ((_a.sent()).file)];
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}); };
|
|
101
|
+
return [4 /*yield*/, newFile("shared-".concat(RAND(), ".pdf"))]; // the one that gets shared
|
|
102
|
+
case 4:
|
|
103
|
+
fileA_1 = _b.sent() // the one that gets shared
|
|
104
|
+
;
|
|
105
|
+
return [4 /*yield*/, newFile("private-".concat(RAND(), ".pdf"))
|
|
106
|
+
/**
|
|
107
|
+
* Mints a token exactly the way a real send does — get_templated_message is the endpoint the
|
|
108
|
+
* worker calls (worker/app.js handleOutgoingEmail).
|
|
109
|
+
*
|
|
110
|
+
* replaceLinks always rewrites the resolved link into a tracking redirect, so `plaintext` holds
|
|
111
|
+
* `doc (${API_URL}/r/<redirectToken>)` rather than the portal URL. Follow the 302 to recover it.
|
|
112
|
+
*/
|
|
113
|
+
]; // the rest of the patient's chart
|
|
114
|
+
case 5:
|
|
115
|
+
fileB_1 = _b.sent() // the rest of the patient's chart
|
|
116
|
+
;
|
|
117
|
+
mint = function (verb) { return __awaiter(void 0, void 0, void 0, function () {
|
|
118
|
+
var plaintext, redirectURL, r, location, token;
|
|
119
|
+
var _a, _b;
|
|
120
|
+
return __generator(this, function (_c) {
|
|
121
|
+
switch (_c.label) {
|
|
122
|
+
case 0: return [4 /*yield*/, sdk_1.api.templates.get_templated_message({
|
|
123
|
+
channel: 'Email',
|
|
124
|
+
userId: tenant.users[0].id,
|
|
125
|
+
enduserId: enduser_1.id,
|
|
126
|
+
message: "{{files.".concat(fileA_1.id, ".").concat(verb, ":doc}}"),
|
|
127
|
+
})];
|
|
128
|
+
case 1:
|
|
129
|
+
plaintext = (_c.sent()).plaintext;
|
|
130
|
+
redirectURL = (_a = plaintext.match(/\((https?:\/\/[^)\s]+)\)/)) === null || _a === void 0 ? void 0 : _a[1];
|
|
131
|
+
if (!redirectURL)
|
|
132
|
+
return [2 /*return*/, { token: undefined, detail: "no link resolved from: ".concat(plaintext) }];
|
|
133
|
+
return [4 /*yield*/, axios.get(redirectURL, { maxRedirects: 0, validateStatus: function () { return true; } })];
|
|
134
|
+
case 2:
|
|
135
|
+
r = _c.sent();
|
|
136
|
+
location = r.headers['location'];
|
|
137
|
+
if (!location)
|
|
138
|
+
return [2 /*return*/, { token: undefined, detail: "redirect did not 302 (".concat(r.status, ")") }];
|
|
139
|
+
token = (_b = new URL(location).searchParams.get('token')) !== null && _b !== void 0 ? _b : undefined;
|
|
140
|
+
return [2 /*return*/, { token: token, detail: token ? 'minted' : "no token in ".concat(location) }];
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}); };
|
|
144
|
+
return [4 /*yield*/, probe('get', '/files', { token: tenant.users[0].authToken })];
|
|
145
|
+
case 6:
|
|
146
|
+
adminFiles = _b.sent();
|
|
147
|
+
record('control: admin session lists files', adminFiles.status === 200, "status ".concat(adminFiles.status));
|
|
148
|
+
confinement_probes = function (variant, token) { return __awaiter(void 0, void 0, void 0, function () {
|
|
149
|
+
var p, _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, refreshed, leaked, refreshedToken, _s, _t, _u, _v;
|
|
150
|
+
var _w;
|
|
151
|
+
return __generator(this, function (_x) {
|
|
152
|
+
switch (_x.label) {
|
|
153
|
+
case 0:
|
|
154
|
+
p = function (label, expected, r) { return record("".concat(variant, " \u2014 ").concat(label), r.status === expected, "status ".concat(r.status, " (expected ").concat(expected, ")")); };
|
|
155
|
+
_a = p;
|
|
156
|
+
_b = ['1: downloads the shared file', 200];
|
|
157
|
+
return [4 /*yield*/, probe('get', '/file-download-URL', { token: token, params: { secureName: fileA_1.secureName } })];
|
|
158
|
+
case 1:
|
|
159
|
+
_a.apply(void 0, _b.concat([_x.sent()]));
|
|
160
|
+
_c = p;
|
|
161
|
+
_d = ['2: cannot download another file on the same patient', 403];
|
|
162
|
+
return [4 /*yield*/, probe('get', '/file-download-URL', { token: token, params: { secureName: fileB_1.secureName } })];
|
|
163
|
+
case 2:
|
|
164
|
+
_c.apply(void 0, _d.concat([_x.sent()]));
|
|
165
|
+
// validateInput merges query, then body, then params — body wins over query, so a pin checked
|
|
166
|
+
// against req.query rather than req.validated would be sidesteppable exactly like this.
|
|
167
|
+
_e = p;
|
|
168
|
+
_f = ['3: cannot smuggle another secureName through the body', 403];
|
|
169
|
+
return [4 /*yield*/, probe('get', '/file-download-URL', {
|
|
170
|
+
token: token,
|
|
171
|
+
params: { secureName: fileA_1.secureName }, data: { secureName: fileB_1.secureName },
|
|
172
|
+
})];
|
|
173
|
+
case 3:
|
|
174
|
+
// validateInput merges query, then body, then params — body wins over query, so a pin checked
|
|
175
|
+
// against req.query rather than req.validated would be sidesteppable exactly like this.
|
|
176
|
+
_e.apply(void 0, _f.concat([_x.sent()]));
|
|
177
|
+
// a listing would turn the pin into a directory of the patient's chart
|
|
178
|
+
_g = p;
|
|
179
|
+
_h = ['4: cannot list files', 403];
|
|
180
|
+
return [4 /*yield*/, probe('get', '/files', { token: token })];
|
|
181
|
+
case 4:
|
|
182
|
+
// a listing would turn the pin into a directory of the patient's chart
|
|
183
|
+
_g.apply(void 0, _h.concat([_x.sent()]));
|
|
184
|
+
_j = p;
|
|
185
|
+
_k = ['5a: cannot read chats', 403];
|
|
186
|
+
return [4 /*yield*/, probe('get', '/chats', { token: token })];
|
|
187
|
+
case 5:
|
|
188
|
+
_j.apply(void 0, _k.concat([_x.sent()]));
|
|
189
|
+
_l = p;
|
|
190
|
+
_m = ['5b: cannot read form responses', 403];
|
|
191
|
+
return [4 /*yield*/, probe('get', '/form-responses', { token: token })];
|
|
192
|
+
case 6:
|
|
193
|
+
_l.apply(void 0, _m.concat([_x.sent()]));
|
|
194
|
+
_o = p;
|
|
195
|
+
_p = ['5c: cannot read observations', 403];
|
|
196
|
+
return [4 /*yield*/, probe('get', '/enduser-observations', { token: token })];
|
|
197
|
+
case 7:
|
|
198
|
+
_o.apply(void 0, _p.concat([_x.sent()]));
|
|
199
|
+
_q = p;
|
|
200
|
+
_r = ['6: cannot update the patient', 403];
|
|
201
|
+
return [4 /*yield*/, probe('patch', "/enduser/".concat(enduser_1.id), { token: token, data: { updates: { fname: 'Overwritten' } } })];
|
|
202
|
+
case 8:
|
|
203
|
+
_q.apply(void 0, _r.concat([_x.sent()]));
|
|
204
|
+
return [4 /*yield*/, probe('post', '/refresh-enduser-session', { token: token })];
|
|
205
|
+
case 9:
|
|
206
|
+
refreshed = _x.sent();
|
|
207
|
+
p('7: can refresh its own session', 200, refreshed);
|
|
208
|
+
leaked = ['dateOfBirth', 'email', 'phone', 'fields', 'insurance', 'lname']
|
|
209
|
+
.filter(function (f) { var _a, _b; return ((_b = (_a = refreshed.body) === null || _a === void 0 ? void 0 : _a.enduser) !== null && _b !== void 0 ? _b : {})[f] !== undefined; });
|
|
210
|
+
record("".concat(variant, " \u2014 7b: refresh response withholds patient fields"), refreshed.status === 200 && leaked.length === 0, leaked.length ? "leaked: ".concat(leaked.join(', ')) : 'no patient fields in payload');
|
|
211
|
+
refreshedToken = (_w = refreshed.body) === null || _w === void 0 ? void 0 : _w.authToken;
|
|
212
|
+
if (!(typeof refreshedToken === 'string' && refreshedToken)) return [3 /*break*/, 12];
|
|
213
|
+
_s = p;
|
|
214
|
+
_t = ['8a: refreshed token still cannot download another file', 403];
|
|
215
|
+
return [4 /*yield*/, probe('get', '/file-download-URL', {
|
|
216
|
+
token: refreshedToken, params: { secureName: fileB_1.secureName },
|
|
217
|
+
})];
|
|
218
|
+
case 10:
|
|
219
|
+
_s.apply(void 0, _t.concat([_x.sent()]));
|
|
220
|
+
_u = p;
|
|
221
|
+
_v = ['8b: refreshed token still cannot update the patient', 403];
|
|
222
|
+
return [4 /*yield*/, probe('patch', "/enduser/".concat(enduser_1.id), {
|
|
223
|
+
token: refreshedToken, data: { updates: { fname: 'Overwritten' } },
|
|
224
|
+
})];
|
|
225
|
+
case 11:
|
|
226
|
+
_u.apply(void 0, _v.concat([_x.sent()]));
|
|
227
|
+
return [3 /*break*/, 13];
|
|
228
|
+
case 12:
|
|
229
|
+
record("".concat(variant, " \u2014 8: refreshed token available"), false, 'refresh returned no authToken');
|
|
230
|
+
_x.label = 13;
|
|
231
|
+
case 13: return [2 /*return*/];
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}); };
|
|
235
|
+
return [4 /*yield*/, mint('link')];
|
|
236
|
+
case 7:
|
|
237
|
+
plain = _b.sent();
|
|
238
|
+
if (!plain.token) return [3 /*break*/, 9];
|
|
239
|
+
return [4 /*yield*/, confinement_probes('link', plain.token)];
|
|
240
|
+
case 8:
|
|
241
|
+
_b.sent();
|
|
242
|
+
return [3 /*break*/, 10];
|
|
243
|
+
case 9:
|
|
244
|
+
record('link — minted', false, plain.detail);
|
|
245
|
+
_b.label = 10;
|
|
246
|
+
case 10: return [4 /*yield*/, mint('shared-link')];
|
|
247
|
+
case 11:
|
|
248
|
+
shared = _b.sent();
|
|
249
|
+
if (!shared.token) return [3 /*break*/, 13];
|
|
250
|
+
return [4 /*yield*/, confinement_probes('shared-link', shared.token)];
|
|
251
|
+
case 12:
|
|
252
|
+
_b.sent();
|
|
253
|
+
return [3 /*break*/, 14];
|
|
254
|
+
case 13:
|
|
255
|
+
// Before the shared-link verb exists the merge field does not resolve. Record it and skip the
|
|
256
|
+
// shared probes rather than throwing, so the first run reports the whole picture at once.
|
|
257
|
+
record('shared-link — minted', false, shared.detail);
|
|
258
|
+
_b.label = 14;
|
|
259
|
+
case 14:
|
|
260
|
+
if (!shared.token) return [3 /*break*/, 19];
|
|
261
|
+
return [4 /*yield*/, probe('get', '/endusers/otp-methods', { params: { token: shared.token } })];
|
|
262
|
+
case 15:
|
|
263
|
+
methods = _b.sent();
|
|
264
|
+
record('shared-link — 9: OTP methods are not offered', methods.status === 403, "status ".concat(methods.status, " (expected 403)"));
|
|
265
|
+
return [4 /*yield*/, probe('post', '/endusers/send-otp-code', {
|
|
266
|
+
data: { token: shared.token, method: 'email' },
|
|
267
|
+
})];
|
|
268
|
+
case 16:
|
|
269
|
+
send = _b.sent();
|
|
270
|
+
record('shared-link — 10: cannot make us send the patient a login code', send.status === 403, "status ".concat(send.status, " (expected 403)"));
|
|
271
|
+
return [4 /*yield*/, probe('post', '/endusers/verify-otp-code', {
|
|
272
|
+
data: { token: shared.token, code: '000000' },
|
|
273
|
+
})];
|
|
274
|
+
case 17:
|
|
275
|
+
verify = _b.sent();
|
|
276
|
+
record('shared-link — 11: OTP verification refuses the scope before checking the code', verify.status === 403, "status ".concat(verify.status, " (expected 403, 400 = reached the code check)"));
|
|
277
|
+
_a = shared.token.split('.'), header = _a[0], payload = _a[1];
|
|
278
|
+
decoded = JSON.parse(Buffer.from(payload, 'base64url').toString());
|
|
279
|
+
delete decoded.sessionScopes;
|
|
280
|
+
delete decoded.scopeContext;
|
|
281
|
+
forged = [
|
|
282
|
+
header,
|
|
283
|
+
Buffer.from(JSON.stringify(decoded)).toString('base64url'),
|
|
284
|
+
'not-a-real-signature',
|
|
285
|
+
].join('.');
|
|
286
|
+
return [4 /*yield*/, probe('post', '/endusers/send-otp-code', {
|
|
287
|
+
data: { token: forged, method: 'email' },
|
|
288
|
+
})];
|
|
289
|
+
case 18:
|
|
290
|
+
forgedSend = _b.sent();
|
|
291
|
+
record('shared-link — 12: a forged token cannot strip the scope to unlock OTP', forgedSend.status === 403 || forgedSend.status === 401 || forgedSend.status === 404, "status ".concat(forgedSend.status, " (expected 401/403/404; 204 = signature never verified)"));
|
|
292
|
+
_b.label = 19;
|
|
293
|
+
case 19:
|
|
294
|
+
if (!plain.token) return [3 /*break*/, 21];
|
|
295
|
+
return [4 /*yield*/, probe('post', '/endusers/send-otp-code', {
|
|
296
|
+
data: { token: plain.token, method: 'email' },
|
|
297
|
+
})];
|
|
298
|
+
case 20:
|
|
299
|
+
send = _b.sent();
|
|
300
|
+
record('link — 13: patient OTP recovery still works', send.status === 204, "status ".concat(send.status, " (expected 204)"));
|
|
301
|
+
_b.label = 21;
|
|
302
|
+
case 21: return [3 /*break*/, 27];
|
|
303
|
+
case 22:
|
|
304
|
+
if (!tenant) return [3 /*break*/, 26];
|
|
305
|
+
_b.label = 23;
|
|
306
|
+
case 23:
|
|
307
|
+
_b.trys.push([23, 25, , 26]);
|
|
308
|
+
return [4 /*yield*/, tenant.teardown()];
|
|
309
|
+
case 24:
|
|
310
|
+
_b.sent();
|
|
311
|
+
return [3 /*break*/, 26];
|
|
312
|
+
case 25:
|
|
313
|
+
e_1 = _b.sent();
|
|
314
|
+
console.error('teardown failed', e_1);
|
|
315
|
+
return [3 /*break*/, 26];
|
|
316
|
+
case 26: return [7 /*endfinally*/];
|
|
317
|
+
case 27: return [2 /*return*/, checks];
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}); };
|
|
321
|
+
/** Asserting wrapper, for standalone runs and for sequential use in the suite. */
|
|
322
|
+
export var file_link_session_confinement_tests = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
323
|
+
var _a, _b;
|
|
324
|
+
return __generator(this, function (_c) {
|
|
325
|
+
switch (_c.label) {
|
|
326
|
+
case 0:
|
|
327
|
+
_a = assert_checks;
|
|
328
|
+
_b = ['Shared file link session confinement'];
|
|
329
|
+
return [4 /*yield*/, file_link_session_confinement_checks()];
|
|
330
|
+
case 1:
|
|
331
|
+
_a.apply(void 0, _b.concat([_c.sent()]));
|
|
332
|
+
return [2 /*return*/];
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
}); };
|
|
336
|
+
// Allow running this test file independently
|
|
337
|
+
if (require.main === module) {
|
|
338
|
+
console.log("\uD83C\uDF10 Using API URL: ".concat(host));
|
|
339
|
+
file_link_session_confinement_tests()
|
|
340
|
+
.then(function () {
|
|
341
|
+
console.log("✅ file link session confinement test suite completed successfully");
|
|
342
|
+
process.exit(0);
|
|
343
|
+
})
|
|
344
|
+
.catch(function (error) {
|
|
345
|
+
console.error("❌ file link session confinement test suite failed:", error);
|
|
346
|
+
process.exit(1);
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
//# sourceMappingURL=file-link-session-confinement.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-link-session-confinement.test.js","sourceRoot":"","sources":["../../../../../src/tests/api_tests/security/file-link-session-confinement.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tests.d.ts","sourceRoot":"","sources":["../../../src/tests/tests.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tests.d.ts","sourceRoot":"","sources":["../../../src/tests/tests.ts"],"names":[],"mappings":"AA03EA,eAAO,MAAM,kCAAkC,qBAgJ9C,CAAA;AAED,eAAO,MAAM,mCAAmC,qBA2K/C,CAAA;AAGD,eAAO,MAAM,oBAAoB,qBAoHhC,CAAA;AAED,eAAO,MAAM,+BAA+B,qBAsF3C,CAAA;AAID,eAAO,MAAM,0BAA0B,qBAqCtC,CAAA;AAy1FD,eAAO,MAAM,cAAc,qBAqC1B,CAAA;AAotBD,eAAO,MAAM,0BAA0B,qBAmFtC,CAAA;AAqED,eAAO,MAAM,eAAe,qBAmD3B,CAAA;AAED,eAAO,MAAM,oBAAoB,6BAsBhC,CAAA;AAED,eAAO,MAAM,oCAAoC,qBAiqBhD,CAAA;AAED,eAAO,MAAM,mCAAmC,qBAkE/C,CAAA;AAqlDD,eAAO,MAAM,yBAAyB,qBA0DrC,CAAA;AAED,eAAO,MAAM,kBAAkB,qBAmK9B,CAAA;AAED,eAAO,MAAM,sBAAsB,qBA0BlC,CAAA;AAGD,eAAO,MAAM,mBAAmB,qBAmC/B,CAAA;AAED,eAAO,MAAM,gCAAgC,mCA8C5C,CAAA;AAED,eAAO,MAAM,cAAc,qBA+b1B,CAAA;AAGD,eAAO,MAAM,oBAAoB,uBAuBhC,CAAA;AA4wBD,eAAO,MAAM,4BAA4B,qBAiFxC,CAAA;AAED,eAAO,MAAM,+BAA+B,qBA4U3C,CAAA;AAED,eAAO,MAAM,gDAAgD,qBAyD5D,CAAA;AAED,eAAO,MAAM,qBAAqB,qBAwIjC,CAAA"}
|
package/lib/esm/tests/tests.js
CHANGED
|
@@ -181,6 +181,7 @@ import { organization_signup_checks } from "./api_tests/organization_signup.test
|
|
|
181
181
|
import { add_to_journey_foreign_enduserid_checks } from "./api_tests/security/add-to-journey-foreign-enduserid.test";
|
|
182
182
|
import { tickets_bulk_assign_from_queue_checks } from "./api_tests/tickets_bulk_assign_from_queue.test";
|
|
183
183
|
import { enduser_observations_auto_review_checks } from "./api_tests/enduser_observations_auto_review.test";
|
|
184
|
+
import { file_link_session_confinement_checks } from "./api_tests/security/file-link-session-confinement.test";
|
|
184
185
|
import { run_isolated_in_parallel } from "./setup_isolated";
|
|
185
186
|
import { elation_user_id_tests } from "./api_tests/elation_user_id.test";
|
|
186
187
|
import { organization_settings_duplicates_tests } from "./api_tests/organization_settings_duplicates.test";
|
|
@@ -17447,6 +17448,7 @@ var ip_address_form_tests = function () { return __awaiter(void 0, void 0, void
|
|
|
17447
17448
|
{ name: 'Tickets bulk assign from queue', run: tickets_bulk_assign_from_queue_checks },
|
|
17448
17449
|
{ name: 'Vital auto-review on create', run: enduser_observations_auto_review_checks },
|
|
17449
17450
|
{ name: '$JS in stored conditional logic', run: form_logic_js_execution_checks },
|
|
17451
|
+
{ name: 'Shared file link session confinement', run: file_link_session_confinement_checks },
|
|
17450
17452
|
])];
|
|
17451
17453
|
case 23:
|
|
17452
17454
|
// Isolated, tenant-provisioned suites run first and CONCURRENTLY: each provisions its own
|