mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
refactor(cli): dedupe device role validation for token ops
This commit is contained in:
@@ -192,3 +192,64 @@ describe("devices cli clear", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("devices cli tokens", () => {
|
||||
afterEach(() => {
|
||||
callGateway.mockReset();
|
||||
withProgress.mockClear();
|
||||
runtime.log.mockReset();
|
||||
runtime.error.mockReset();
|
||||
runtime.exit.mockReset();
|
||||
});
|
||||
|
||||
it("rotates a token for a device role", async () => {
|
||||
callGateway.mockResolvedValueOnce({ ok: true });
|
||||
|
||||
await runDevicesCommand([
|
||||
"rotate",
|
||||
"--device",
|
||||
"device-1",
|
||||
"--role",
|
||||
"main",
|
||||
"--scope",
|
||||
"messages:send",
|
||||
"--scope",
|
||||
"messages:read",
|
||||
]);
|
||||
|
||||
expect(callGateway).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
method: "device.token.rotate",
|
||||
params: {
|
||||
deviceId: "device-1",
|
||||
role: "main",
|
||||
scopes: ["messages:send", "messages:read"],
|
||||
},
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("revokes a token for a device role", async () => {
|
||||
callGateway.mockResolvedValueOnce({ ok: true });
|
||||
|
||||
await runDevicesCommand(["revoke", "--device", "device-1", "--role", "main"]);
|
||||
|
||||
expect(callGateway).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
method: "device.token.revoke",
|
||||
params: {
|
||||
deviceId: "device-1",
|
||||
role: "main",
|
||||
},
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects blank device or role values", async () => {
|
||||
await runDevicesCommand(["rotate", "--device", " ", "--role", "main"]);
|
||||
|
||||
expect(callGateway).not.toHaveBeenCalled();
|
||||
expect(runtime.error).toHaveBeenCalledWith("--device and --role required");
|
||||
expect(runtime.exit).toHaveBeenCalledWith(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -110,6 +110,19 @@ function formatTokenSummary(tokens: DeviceTokenSummary[] | undefined) {
|
||||
return parts.join(", ");
|
||||
}
|
||||
|
||||
function resolveRequiredDeviceRole(
|
||||
opts: DevicesRpcOpts,
|
||||
): { deviceId: string; role: string } | null {
|
||||
const deviceId = String(opts.device ?? "").trim();
|
||||
const role = String(opts.role ?? "").trim();
|
||||
if (deviceId && role) {
|
||||
return { deviceId, role };
|
||||
}
|
||||
defaultRuntime.error("--device and --role required");
|
||||
defaultRuntime.exit(1);
|
||||
return null;
|
||||
}
|
||||
|
||||
export function registerDevicesCli(program: Command) {
|
||||
const devices = program.command("devices").description("Device pairing and auth tokens");
|
||||
|
||||
@@ -318,16 +331,13 @@ export function registerDevicesCli(program: Command) {
|
||||
.requiredOption("--role <role>", "Role name")
|
||||
.option("--scope <scope...>", "Scopes to attach to the token (repeatable)")
|
||||
.action(async (opts: DevicesRpcOpts) => {
|
||||
const deviceId = String(opts.device ?? "").trim();
|
||||
const role = String(opts.role ?? "").trim();
|
||||
if (!deviceId || !role) {
|
||||
defaultRuntime.error("--device and --role required");
|
||||
defaultRuntime.exit(1);
|
||||
const required = resolveRequiredDeviceRole(opts);
|
||||
if (!required) {
|
||||
return;
|
||||
}
|
||||
const result = await callGatewayCli("device.token.rotate", opts, {
|
||||
deviceId,
|
||||
role,
|
||||
deviceId: required.deviceId,
|
||||
role: required.role,
|
||||
scopes: Array.isArray(opts.scope) ? opts.scope : undefined,
|
||||
});
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
@@ -341,16 +351,13 @@ export function registerDevicesCli(program: Command) {
|
||||
.requiredOption("--device <id>", "Device id")
|
||||
.requiredOption("--role <role>", "Role name")
|
||||
.action(async (opts: DevicesRpcOpts) => {
|
||||
const deviceId = String(opts.device ?? "").trim();
|
||||
const role = String(opts.role ?? "").trim();
|
||||
if (!deviceId || !role) {
|
||||
defaultRuntime.error("--device and --role required");
|
||||
defaultRuntime.exit(1);
|
||||
const required = resolveRequiredDeviceRole(opts);
|
||||
if (!required) {
|
||||
return;
|
||||
}
|
||||
const result = await callGatewayCli("device.token.revoke", opts, {
|
||||
deviceId,
|
||||
role,
|
||||
deviceId: required.deviceId,
|
||||
role: required.role,
|
||||
});
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user