fix(edp): resolve managed reader source scope
This commit is contained in:
@@ -196,7 +196,7 @@ try {
|
||||
|
||||
const managedReaderToken = "ndc_edprb_managed_api_test_0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
const managedReaderBody = {
|
||||
source: scope,
|
||||
source: { ...scope, connectionId: "api-consumer-connection" },
|
||||
allowedDataProductIds: [productId],
|
||||
expiresAt: null,
|
||||
generation: 1,
|
||||
@@ -209,12 +209,25 @@ try {
|
||||
]);
|
||||
assert.deepEqual(managedReaderResults.map(({ value }) => value.idempotent).sort(), [false, true]);
|
||||
assert.equal(managedReaderResults[0].value.readerBinding.id, managedReaderResults[1].value.readerBinding.id);
|
||||
assert.equal(managedReaderResults[0].value.readerBinding.connectionId, "api-consumer-connection");
|
||||
assert.equal("token" in managedReaderResults[0].value, false);
|
||||
assert.equal(JSON.stringify(managedReaderResults[0].value).includes(managedReaderBody.capabilityDigest), false);
|
||||
assert.deepEqual(
|
||||
(await jsonRequest("/internal/data-plane/v1/reader/data-products", { token: managedReaderToken })).dataProducts.map((value) => value.id),
|
||||
[productId],
|
||||
);
|
||||
const managedSourcePublish = await jsonRequest(`/internal/data-plane/v1/data-products/${productId}/publish`, {
|
||||
method: "POST",
|
||||
token: managedTokenGeneration2,
|
||||
body: publish("api-managed-reader-source", "2026-07-15T11:00:00.000Z", 37.60),
|
||||
});
|
||||
assert.equal(managedSourcePublish.currentUpdatedCount, 1);
|
||||
const managedReaderSnapshot = await jsonRequest(
|
||||
`/internal/data-plane/v1/data-products/${productId}/snapshot`,
|
||||
{ token: managedReaderToken },
|
||||
);
|
||||
assert.equal(validateDataProductSnapshot(managedReaderSnapshot).ok, true);
|
||||
assert.equal(managedReaderSnapshot.facts.length, 1);
|
||||
const legacyManagedReaderRevoke = await fetch(
|
||||
`${baseUrl}/internal/data-plane/v1/reader-bindings/${managedReaderResults[0].value.readerBinding.id}/revoke`,
|
||||
{ method: "POST", headers: { Authorization: `Bearer ${provisionerSecret}` } },
|
||||
@@ -236,6 +249,31 @@ try {
|
||||
});
|
||||
assert.equal(rejectedManagedReader.status, 401);
|
||||
|
||||
const secondWriterToken = "ndc_edpwb_second_source_api_test_0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
await jsonRequest("/internal/data-plane/v1/writer-bindings/by-key/engine.api-connection-2.positions", {
|
||||
method: "PUT",
|
||||
managedSignature: true,
|
||||
body: {
|
||||
...managedBody,
|
||||
source: { ...scope, connectionId: "api-connection-2" },
|
||||
capabilityDigest: createHash("sha256").update(secondWriterToken, "utf8").digest("hex"),
|
||||
},
|
||||
});
|
||||
const ambiguousReaderToken = "ndc_edprb_ambiguous_api_test_0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
const ambiguousReader = await signedFetch(
|
||||
"/internal/data-plane/v1/reader-bindings/by-key/engine.api-ambiguous.positions-reader",
|
||||
{
|
||||
method: "PUT",
|
||||
body: {
|
||||
...managedReaderBody,
|
||||
source: { ...scope, connectionId: "api-other-consumer" },
|
||||
capabilityDigest: createHash("sha256").update(ambiguousReaderToken, "utf8").digest("hex"),
|
||||
},
|
||||
},
|
||||
);
|
||||
assert.equal(ambiguousReader.status, 409);
|
||||
assert.equal((await ambiguousReader.json()).error, "managed_reader_source_scope_ambiguous");
|
||||
|
||||
const manualWriterBody = { source: scope, allowedDataProductIds: [productId], expiresAt: expiry };
|
||||
const signedOnlyManualProvisioning = await signedFetch("/internal/data-plane/v1/writer-bindings", {
|
||||
method: "POST",
|
||||
|
||||
@@ -49,8 +49,10 @@ try {
|
||||
const storedDefinition = await loadDataProductDefinition(pool, definition.id);
|
||||
const binding = {
|
||||
id: "reader-binding-test",
|
||||
bindingKey: "managed-reader-binding-test",
|
||||
tenantId: "tenant-test",
|
||||
connectionId: "connection-test",
|
||||
connectionId: "consumer-connection-test",
|
||||
sourceConnectionId: "connection-test",
|
||||
providerId: "provider-test",
|
||||
allowedDataProductIds: [definition.id],
|
||||
active: true,
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { resolveManagedReaderSourceConnection } from "../src/reader-source-scope.mjs";
|
||||
|
||||
const policy = {
|
||||
tenantId: "tenant-01",
|
||||
connectionId: "consumer-connection",
|
||||
providerId: "provider-01",
|
||||
allowedDataProductIds: ["fleet.positions.current.v1"],
|
||||
};
|
||||
|
||||
assert.equal(
|
||||
await resolveManagedReaderSourceConnection(db(["producer-connection"]), policy),
|
||||
"producer-connection",
|
||||
);
|
||||
assert.equal(
|
||||
await resolveManagedReaderSourceConnection(db(["producer-connection", "consumer-connection"]), policy),
|
||||
"consumer-connection",
|
||||
);
|
||||
await assert.rejects(
|
||||
resolveManagedReaderSourceConnection(db([]), policy),
|
||||
(error) => error?.status === 409 && error?.code === "managed_reader_source_scope_not_found",
|
||||
);
|
||||
await assert.rejects(
|
||||
resolveManagedReaderSourceConnection(db(["producer-a", "producer-b"]), policy),
|
||||
(error) => error?.status === 409 && error?.code === "managed_reader_source_scope_ambiguous",
|
||||
);
|
||||
await assert.rejects(
|
||||
resolveManagedReaderSourceConnection(db(["producer-connection"]), { ...policy, allowedDataProductIds: [] }),
|
||||
(error) => error?.status === 400 && error?.code === "managed_reader_source_scope_request_invalid",
|
||||
);
|
||||
|
||||
function db(connectionIds) {
|
||||
return {
|
||||
async query(sql, values) {
|
||||
assert.match(sql, /external_data_plane_writer_bindings/);
|
||||
assert.deepEqual(values, [policy.tenantId, policy.providerId, policy.allowedDataProductIds]);
|
||||
return { rows: connectionIds.map((connectionId) => ({ connectionId })) };
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
console.log("external-data-plane reader source scope: ok");
|
||||
Reference in New Issue
Block a user