fix: remove legacy device pod grants authority (#906)
Co-authored-by: Codex Agent <codex@hwlab.local>
This commit is contained in:
@@ -73,6 +73,23 @@ test("Postgres workspace update query preserves parameter numbering", async () =
|
||||
assert.equal(update.params[17], "user");
|
||||
});
|
||||
|
||||
test("Postgres access schema removes legacy device_pod_grants authority", async () => {
|
||||
const calls = [];
|
||||
const accessController = createAccessController({
|
||||
runtimeStore: {
|
||||
query: async (sql, params = []) => {
|
||||
calls.push({ sql, params });
|
||||
return { rows: [] };
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await accessController.store.countUsers();
|
||||
|
||||
assert.ok(calls.some((call) => call.sql === "DROP TABLE IF EXISTS device_pod_grants"));
|
||||
assert.equal(calls.some((call) => /CREATE TABLE IF NOT EXISTS device_pod_grants\b/u.test(call.sql)), false);
|
||||
});
|
||||
|
||||
test("cloud api /auth/oidc/login returns 302 to Keycloak when issuer and client are configured", async () => {
|
||||
const server = createCloudApiServer({
|
||||
env: { HWLAB_ACCESS_CONTROL_REQUIRED: "1", HWLAB_KEYCLOAK_ISSUER: OIDC_ISSUER, HWLAB_KEYCLOAK_CLIENT_ID: OIDC_CLIENT_ID, HWLAB_PUBLIC_ENDPOINT },
|
||||
@@ -1088,11 +1105,6 @@ test("cloud api access control grants visible device pods and requires device-po
|
||||
assert.equal(emptyList.status, 200);
|
||||
assert.deepEqual(emptyList.body.devicePods, []);
|
||||
|
||||
const legacyGrant = await postJson(port, "/v1/admin/device-pod-grants", {
|
||||
devicePodId: "device-pod-71-freq",
|
||||
userId: userCreate.body.user.id
|
||||
}, adminCookie);
|
||||
assert.equal(legacyGrant.status, 404);
|
||||
await grantDevicePodAccess(port, adminCookie, userCreate.body.user.id, "device-pod-71-freq", ["viewer", "operator", "job_submitter"]);
|
||||
await grantDevicePodAccess(port, adminCookie, bobCreate.body.user.id, "device-pod-71-freq", ["viewer", "operator", "job_submitter"]);
|
||||
|
||||
@@ -1190,11 +1202,6 @@ test("cloud api access control grants visible device pods and requires device-po
|
||||
assert.equal(unsupported.status, 400);
|
||||
assert.equal(unsupported.body.error.code, "unsupported_device_job_intent");
|
||||
|
||||
const legacyRevoke = await fetch(`http://127.0.0.1:${port}/v1/admin/device-pod-grants/device-pod-71-freq/${bobCreate.body.user.id}`, {
|
||||
method: "DELETE",
|
||||
headers: { cookie: adminCookie }
|
||||
});
|
||||
assert.equal(legacyRevoke.status, 404);
|
||||
await revokeDevicePodAccess(port, adminCookie, bobCreate.body.user.id, "device-pod-71-freq", ["viewer", "operator", "job_submitter"]);
|
||||
|
||||
const afterRevoke = await getJson(port, "/v1/device-pods", bobLogin.cookie);
|
||||
|
||||
@@ -194,7 +194,8 @@ const ACCESS_SCHEMA_STATEMENTS = Object.freeze([
|
||||
PRIMARY KEY (user_id, relation, object)
|
||||
)`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_access_tuples_user ON access_tuples(user_id, object)`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_access_tuples_object ON access_tuples(object, relation)`
|
||||
`CREATE INDEX IF NOT EXISTS idx_access_tuples_object ON access_tuples(object, relation)`,
|
||||
`DROP TABLE IF EXISTS device_pod_grants`
|
||||
]);
|
||||
|
||||
const MUTATING_INTENTS = new Set([
|
||||
|
||||
@@ -184,13 +184,7 @@ CREATE TABLE IF NOT EXISTS device_pods (
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS device_pod_grants (
|
||||
device_pod_id TEXT NOT NULL REFERENCES device_pods(id) ON DELETE CASCADE,
|
||||
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
created_by_admin_id TEXT NOT NULL REFERENCES users(id),
|
||||
created_at TEXT NOT NULL,
|
||||
PRIMARY KEY (device_pod_id, user_id)
|
||||
);
|
||||
DROP TABLE IF EXISTS device_pod_grants;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS device_leases (
|
||||
device_pod_id TEXT PRIMARY KEY REFERENCES device_pods(id) ON DELETE CASCADE,
|
||||
|
||||
@@ -39,6 +39,8 @@ test("initial migration skeleton declares every frozen table", async () => {
|
||||
assert.match(sql, /\btarget\b/);
|
||||
assert.match(sql, /\bresult\b/);
|
||||
assert.match(sql, /\btimestamp\b/);
|
||||
assert.doesNotMatch(sql, /CREATE TABLE IF NOT EXISTS device_pod_grants\b/u);
|
||||
assert.match(sql, /DROP TABLE IF EXISTS device_pod_grants\b/u);
|
||||
});
|
||||
|
||||
test("initial migration exposes columns required by the durable runtime adapter", async () => {
|
||||
|
||||
@@ -106,12 +106,6 @@ test("cloud web proxies authenticated Admin Access write routes without legacy g
|
||||
publicRoute: false,
|
||||
routeKey: "DELETE /v1/admin/access/users/usr_alice/tools/hwpod/can-use"
|
||||
});
|
||||
assert.deepEqual(cloudWebProxyRoutePolicy("POST", "/v1/admin/device-pod-grants"), {
|
||||
proxy: false,
|
||||
authRequired: false,
|
||||
publicRoute: false,
|
||||
routeKey: "POST /v1/admin/device-pod-grants"
|
||||
});
|
||||
});
|
||||
|
||||
test("cloud web proxies only supported authenticated device-pod write routes", () => {
|
||||
|
||||
@@ -104,18 +104,6 @@ test("cloud web proxies Admin Access write routes and leaves legacy grants local
|
||||
});
|
||||
assert.equal(grantResponse.status, 200);
|
||||
|
||||
const legacyResponse = await fetch(`${serverUrl(cloudWeb)}/v1/admin/device-pod-grants`, {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({ userId: "usr_alice", devicePodId: "D601-71-FREQ" })
|
||||
});
|
||||
assert.equal(legacyResponse.status, 404);
|
||||
assert.deepEqual(await legacyResponse.json(), {
|
||||
error: "not_found",
|
||||
serviceId: "hwlab-cloud-web",
|
||||
path: "/v1/admin/device-pod-grants"
|
||||
});
|
||||
|
||||
assert.equal(upstreamRequests.length, 2);
|
||||
assert.deepEqual(upstreamRequests[0], {
|
||||
method: "POST",
|
||||
|
||||
Reference in New Issue
Block a user