TASK22269: delegate fileClient signed get/post to signedRequestClient

This commit is contained in:
2026-03-25 13:47:46 +00:00
parent 7470975d0e
commit 85cc7d165e
3 changed files with 49 additions and 41 deletions
+3 -15
View File
@@ -1,17 +1,12 @@
import { getJson, requestJson } from "./endpointClient";
import { buildHashedQueryUrl } from "./relayClient";
import { getSignedJson, postSignedJson } from "./signedRequestClient";
export const getFileJson = (url) => {
return getJson(url);
};
export const getSignedFileJson = async (queryUrl) => {
const signedUrl = await buildHashedQueryUrl(queryUrl);
return requestJson({
method: "get",
url: signedUrl
});
return getSignedJson(queryUrl);
};
export const downloadFileBlob = (url) => {
@@ -23,12 +18,5 @@ export const downloadFileBlob = (url) => {
};
export const postSignedFileJson = async (queryUrl, data, config = {}) => {
const signedUrl = await buildHashedQueryUrl(queryUrl);
return requestJson({
method: "post",
url: signedUrl,
data,
...config
});
return postSignedJson(queryUrl, data, config);
};
+31
View File
@@ -2801,3 +2801,34 @@ Validation:
Follow-ups:
- Next bounded signed GET candidate in portal service is `sendRepCompleteMessage` (single signed URL + GET request path).
---
### CL-078: TASK22269 Slice B1.3 — fileClient signed helper delegation bundle
date: 2026-03-25
author: Cline
scope: `actions/clients/fileClient.js`, `tests/phase22/file-client-behaviour.test.cjs`
type: change
rationale: Continue grouped signed-request consolidation by reducing duplicate signing logic in `fileClient` and delegating signed GET/POST operations to shared `signedRequestClient` helpers.
impact: Centralizes signed method execution behavior in one helper layer and lowers drift risk across file-service call paths.
status: completed
Summary:
- Updated `actions/clients/fileClient.js`:
- replaced direct `buildHashedQueryUrl + requestJson` logic in:
- `getSignedFileJson` -> now delegates to `getSignedJson`
- `postSignedFileJson` -> now delegates to `postSignedJson`
- retained `downloadFileBlob` and `getFileJson` behavior unchanged.
- Updated `tests/phase22/file-client-behaviour.test.cjs` to assert delegation contracts for `getSignedJson` and `postSignedJson` rather than direct signing internals.
Validation:
- `npm run lint` -> pass with warnings only (pre-existing `react-hooks/exhaustive-deps`; no new lint errors)
- `node tests/phase22/index.test.cjs` -> pass
- `node tests/phase7/service-behaviour.test.cjs` -> pass (13/13)
Follow-ups:
- Candidate map now indicates remaining explicit signed request composition is primarily in account/portal signed GET edge paths (`getPortalLogin`, `sendRepCompleteMessage`, and signed suffix append flow in `sendCaseCompleteMessage`) for future bounded slices.
+15 -26
View File
@@ -24,8 +24,11 @@ const loadFileClientModule = (injected = {}) => {
requestJson: async () => {
throw new Error("requestJson not injected");
},
buildHashedQueryUrl: async () => {
throw new Error("buildHashedQueryUrl not injected");
getSignedJson: async () => {
throw new Error("getSignedJson not injected");
},
postSignedJson: async () => {
throw new Error("postSignedJson not injected");
},
...injected
};
@@ -56,15 +59,10 @@ test("clients/fileClient getFileJson delegates to getJson", async () => {
test("clients/fileClient getSignedFileJson signs url and requests json", async () => {
const signedCalls = [];
const requestCalls = [];
const mod = loadFileClientModule({
buildHashedQueryUrl: async (queryUrl) => {
getSignedJson: async (queryUrl) => {
signedCalls.push(queryUrl);
return queryUrl + "&hash=signed";
},
requestJson: async (config) => {
requestCalls.push(config);
return { deleted: true };
}
});
@@ -77,11 +75,9 @@ test("clients/fileClient getSignedFileJson signs url and requests json", async (
deleted: true
});
assert.strictEqual(signedCalls.length, 1);
assert.strictEqual(requestCalls.length, 1);
assert.strictEqual(requestCalls[0].method, "get");
assert.strictEqual(
requestCalls[0].url,
"/api/file/deleteblobcase?container=a&casefolderID=b&hash=signed"
signedCalls[0],
"/api/file/deleteblobcase?container=a&casefolderID=b"
);
});
@@ -106,15 +102,12 @@ test("clients/fileClient downloadFileBlob requests blob response", async () => {
test("clients/fileClient postSignedFileJson signs url and posts payload", async () => {
const signedCalls = [];
const requestCalls = [];
const postedCalls = [];
const mod = loadFileClientModule({
buildHashedQueryUrl: async (queryUrl) => {
postSignedJson: async (queryUrl, data, config) => {
signedCalls.push(queryUrl);
return queryUrl + "&hash=signed-post";
},
requestJson: async (config) => {
requestCalls.push(config);
postedCalls.push({ data, config });
return { uploaded: true };
}
});
@@ -132,18 +125,14 @@ test("clients/fileClient postSignedFileJson signs url and posts payload", async
uploaded: true
});
assert.strictEqual(signedCalls.length, 1);
assert.strictEqual(requestCalls.length, 1);
assert.strictEqual(requestCalls[0].method, "post");
assert.strictEqual(
requestCalls[0].url,
"/api/file/uploadsinglefile&hash=signed-post"
);
assert.strictEqual(postedCalls.length, 1);
assert.strictEqual(signedCalls[0], "/api/file/uploadsinglefile");
assert.deepStrictEqual(
JSON.parse(JSON.stringify(requestCalls[0].data)),
JSON.parse(JSON.stringify(postedCalls[0].data)),
payload
);
assert.strictEqual(
requestCalls[0].headers["content-type"],
postedCalls[0].config.headers["content-type"],
"multipart/form-data"
);
});