mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:40:44 +00:00
fix(matrix): pass loaded cfg to verify CLI subcommands (#70992)
The verify CLI subcommands (status, backup status, backup reset, backup restore, bootstrap, device <key>) all crashed with 'Matrix runtime client requires a resolved runtime config' because resolveMatrixCliAccountId loaded the runtime config to resolve the account ID but discarded it, so the action functions were called without cfg. Introduce resolveMatrixCliAccountContext which returns both accountId and cfg, and use it in the 6 verify subcommand handlers. Add unit tests in cli.test.ts that lock in the contract. Closes #70992
This commit is contained in:
committed by
Gustavo Madeira Santana
parent
8226a3f8fe
commit
dfbf51791b
@@ -211,7 +211,9 @@ describe("matrix CLI verification commands", () => {
|
||||
});
|
||||
const program = buildProgram();
|
||||
|
||||
await program.parseAsync(["matrix", "verify", "bootstrap", "--json"], { from: "user" });
|
||||
await program.parseAsync(["matrix", "verify", "bootstrap", "--json"], {
|
||||
from: "user",
|
||||
});
|
||||
|
||||
expect(process.exitCode).toBe(1);
|
||||
});
|
||||
@@ -267,6 +269,76 @@ describe("matrix CLI verification commands", () => {
|
||||
expect(process.exitCode).toBe(1);
|
||||
});
|
||||
|
||||
it("passes loaded cfg to verify status action", async () => {
|
||||
const fakeCfg = { channels: { matrix: {} } };
|
||||
matrixRuntimeLoadConfigMock.mockReturnValue(fakeCfg);
|
||||
mockMatrixVerificationStatus({ recoveryKeyCreatedAt: null });
|
||||
const program = buildProgram();
|
||||
|
||||
await program.parseAsync(["matrix", "verify", "status"], { from: "user" });
|
||||
|
||||
expect(getMatrixVerificationStatusMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ cfg: fakeCfg }),
|
||||
);
|
||||
});
|
||||
|
||||
it("passes loaded cfg to all verify subcommands", async () => {
|
||||
const fakeCfg = { channels: { matrix: {} } };
|
||||
matrixRuntimeLoadConfigMock.mockReturnValue(fakeCfg);
|
||||
|
||||
// verify bootstrap
|
||||
const program1 = buildProgram();
|
||||
await program1.parseAsync(["matrix", "verify", "bootstrap"], {
|
||||
from: "user",
|
||||
});
|
||||
expect(bootstrapMatrixVerificationMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ cfg: fakeCfg }),
|
||||
);
|
||||
|
||||
// verify device
|
||||
verifyMatrixRecoveryKeyMock.mockResolvedValue({ success: true });
|
||||
const program2 = buildProgram();
|
||||
await program2.parseAsync(["matrix", "verify", "device", "test-key"], {
|
||||
from: "user",
|
||||
});
|
||||
expect(verifyMatrixRecoveryKeyMock).toHaveBeenCalledWith(
|
||||
"test-key",
|
||||
expect.objectContaining({ cfg: fakeCfg }),
|
||||
);
|
||||
|
||||
// verify backup status
|
||||
getMatrixRoomKeyBackupStatusMock.mockResolvedValue({});
|
||||
const program3 = buildProgram();
|
||||
await program3.parseAsync(["matrix", "verify", "backup", "status"], {
|
||||
from: "user",
|
||||
});
|
||||
expect(getMatrixRoomKeyBackupStatusMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ cfg: fakeCfg }),
|
||||
);
|
||||
|
||||
// verify backup reset
|
||||
const program4 = buildProgram();
|
||||
await program4.parseAsync(["matrix", "verify", "backup", "reset", "--yes"], { from: "user" });
|
||||
expect(resetMatrixRoomKeyBackupMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ cfg: fakeCfg }),
|
||||
);
|
||||
|
||||
// verify backup restore
|
||||
restoreMatrixRoomKeyBackupMock.mockResolvedValue({
|
||||
success: true,
|
||||
imported: 0,
|
||||
total: 0,
|
||||
backup: {},
|
||||
});
|
||||
const program5 = buildProgram();
|
||||
await program5.parseAsync(["matrix", "verify", "backup", "restore"], {
|
||||
from: "user",
|
||||
});
|
||||
expect(restoreMatrixRoomKeyBackupMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ cfg: fakeCfg }),
|
||||
);
|
||||
});
|
||||
|
||||
it("lists matrix devices", async () => {
|
||||
listMatrixOwnDevicesMock.mockResolvedValue([
|
||||
{
|
||||
@@ -332,7 +404,9 @@ describe("matrix CLI verification commands", () => {
|
||||
from: "user",
|
||||
});
|
||||
|
||||
expect(pruneMatrixStaleGatewayDevicesMock).toHaveBeenCalledWith({ accountId: "poe" });
|
||||
expect(pruneMatrixStaleGatewayDevicesMock).toHaveBeenCalledWith({
|
||||
accountId: "poe",
|
||||
});
|
||||
expect(console.log).toHaveBeenCalledWith("Deleted stale OpenClaw devices: BritdXC6iL");
|
||||
expect(console.log).toHaveBeenCalledWith("Current device: A7hWrQ70ea");
|
||||
expect(console.log).toHaveBeenCalledWith("Remaining devices: 1");
|
||||
@@ -452,7 +526,9 @@ describe("matrix CLI verification commands", () => {
|
||||
{ from: "user" },
|
||||
);
|
||||
|
||||
expect(bootstrapMatrixVerificationMock).toHaveBeenCalledWith({ accountId: "ops" });
|
||||
expect(bootstrapMatrixVerificationMock).toHaveBeenCalledWith({
|
||||
accountId: "ops",
|
||||
});
|
||||
expect(console.log).toHaveBeenCalledWith("Matrix verification bootstrap: complete");
|
||||
expect(console.log).toHaveBeenCalledWith(
|
||||
`Recovery key created at: ${formatExpectedLocalTimestamp("2026-03-09T06:00:00.000Z")}`,
|
||||
@@ -705,7 +781,9 @@ describe("matrix CLI verification commands", () => {
|
||||
});
|
||||
const program = buildProgram();
|
||||
|
||||
await program.parseAsync(["matrix", "verify", "bootstrap", "--json"], { from: "user" });
|
||||
await program.parseAsync(["matrix", "verify", "bootstrap", "--json"], {
|
||||
from: "user",
|
||||
});
|
||||
|
||||
expect(process.exitCode).toBe(0);
|
||||
});
|
||||
@@ -715,7 +793,9 @@ describe("matrix CLI verification commands", () => {
|
||||
mockMatrixVerificationStatus({ recoveryKeyCreatedAt: recoveryCreatedAt });
|
||||
const program = buildProgram();
|
||||
|
||||
await program.parseAsync(["matrix", "verify", "status", "--verbose"], { from: "user" });
|
||||
await program.parseAsync(["matrix", "verify", "status", "--verbose"], {
|
||||
from: "user",
|
||||
});
|
||||
|
||||
expect(console.log).toHaveBeenCalledWith(
|
||||
`Recovery key created at: ${formatExpectedLocalTimestamp(recoveryCreatedAt)}`,
|
||||
@@ -920,7 +1000,9 @@ describe("matrix CLI verification commands", () => {
|
||||
it("requires --yes before resetting the Matrix room-key backup", async () => {
|
||||
const program = buildProgram();
|
||||
|
||||
await program.parseAsync(["matrix", "verify", "backup", "reset"], { from: "user" });
|
||||
await program.parseAsync(["matrix", "verify", "backup", "reset"], {
|
||||
from: "user",
|
||||
});
|
||||
|
||||
expect(process.exitCode).toBe(1);
|
||||
expect(resetMatrixRoomKeyBackupMock).not.toHaveBeenCalled();
|
||||
@@ -936,7 +1018,10 @@ describe("matrix CLI verification commands", () => {
|
||||
from: "user",
|
||||
});
|
||||
|
||||
expect(resetMatrixRoomKeyBackupMock).toHaveBeenCalledWith({ accountId: "default" });
|
||||
expect(resetMatrixRoomKeyBackupMock).toHaveBeenCalledWith({
|
||||
accountId: "default",
|
||||
cfg: {},
|
||||
});
|
||||
expect(console.log).toHaveBeenCalledWith("Reset success: yes");
|
||||
expect(console.log).toHaveBeenCalledWith("Previous backup version: 1");
|
||||
expect(console.log).toHaveBeenCalledWith("Deleted backup version: 1");
|
||||
@@ -981,6 +1066,7 @@ describe("matrix CLI verification commands", () => {
|
||||
|
||||
expect(getMatrixVerificationStatusMock).toHaveBeenCalledWith({
|
||||
accountId: "assistant",
|
||||
cfg: {},
|
||||
includeRecoveryKey: false,
|
||||
});
|
||||
expect(console.log).toHaveBeenCalledWith("Account: assistant");
|
||||
|
||||
@@ -96,6 +96,17 @@ function resolveMatrixCliAccountId(accountId?: string): string {
|
||||
return resolveMatrixAuthContext({ cfg, accountId }).accountId;
|
||||
}
|
||||
|
||||
function resolveMatrixCliAccountContext(accountId?: string): {
|
||||
accountId: string;
|
||||
cfg: CoreConfig;
|
||||
} {
|
||||
const cfg = getMatrixRuntime().config.loadConfig() as CoreConfig;
|
||||
return {
|
||||
accountId: resolveMatrixAuthContext({ cfg, accountId }).accountId,
|
||||
cfg,
|
||||
};
|
||||
}
|
||||
|
||||
function formatMatrixCliCommand(command: string, accountId?: string): string {
|
||||
const normalizedAccountId = normalizeAccountId(accountId);
|
||||
const suffix = normalizedAccountId === "default" ? "" : ` --account ${normalizedAccountId}`;
|
||||
@@ -925,13 +936,14 @@ export function registerMatrixCli(params: { program: Command }): void {
|
||||
includeRecoveryKey?: boolean;
|
||||
json?: boolean;
|
||||
}) => {
|
||||
const accountId = resolveMatrixCliAccountId(options.account);
|
||||
const { accountId, cfg } = resolveMatrixCliAccountContext(options.account);
|
||||
await runMatrixCliCommand({
|
||||
verbose: options.verbose === true,
|
||||
json: options.json === true,
|
||||
run: async () =>
|
||||
await getMatrixVerificationStatus({
|
||||
accountId,
|
||||
cfg,
|
||||
includeRecoveryKey: options.includeRecoveryKey === true,
|
||||
}),
|
||||
onText: (status, verbose) => {
|
||||
@@ -952,11 +964,11 @@ export function registerMatrixCli(params: { program: Command }): void {
|
||||
.option("--verbose", "Show detailed diagnostics")
|
||||
.option("--json", "Output as JSON")
|
||||
.action(async (options: { account?: string; verbose?: boolean; json?: boolean }) => {
|
||||
const accountId = resolveMatrixCliAccountId(options.account);
|
||||
const { accountId, cfg } = resolveMatrixCliAccountContext(options.account);
|
||||
await runMatrixCliCommand({
|
||||
verbose: options.verbose === true,
|
||||
json: options.json === true,
|
||||
run: async () => await getMatrixRoomKeyBackupStatus({ accountId }),
|
||||
run: async () => await getMatrixRoomKeyBackupStatus({ accountId, cfg }),
|
||||
onText: (status, verbose) => {
|
||||
printAccountLabel(accountId);
|
||||
printBackupSummary(status);
|
||||
@@ -979,7 +991,7 @@ export function registerMatrixCli(params: { program: Command }): void {
|
||||
.option("--json", "Output as JSON")
|
||||
.action(
|
||||
async (options: { account?: string; yes?: boolean; verbose?: boolean; json?: boolean }) => {
|
||||
const accountId = resolveMatrixCliAccountId(options.account);
|
||||
const { accountId, cfg } = resolveMatrixCliAccountContext(options.account);
|
||||
await runMatrixCliCommand({
|
||||
verbose: options.verbose === true,
|
||||
json: options.json === true,
|
||||
@@ -987,7 +999,7 @@ export function registerMatrixCli(params: { program: Command }): void {
|
||||
if (options.yes !== true) {
|
||||
throw new Error("Refusing to reset Matrix room-key backup without --yes");
|
||||
}
|
||||
return await resetMatrixRoomKeyBackup({ accountId });
|
||||
return await resetMatrixRoomKeyBackup({ accountId, cfg });
|
||||
},
|
||||
onText: (result, verbose) => {
|
||||
printAccountLabel(accountId);
|
||||
@@ -1025,13 +1037,14 @@ export function registerMatrixCli(params: { program: Command }): void {
|
||||
verbose?: boolean;
|
||||
json?: boolean;
|
||||
}) => {
|
||||
const accountId = resolveMatrixCliAccountId(options.account);
|
||||
const { accountId, cfg } = resolveMatrixCliAccountContext(options.account);
|
||||
await runMatrixCliCommand({
|
||||
verbose: options.verbose === true,
|
||||
json: options.json === true,
|
||||
run: async () =>
|
||||
await restoreMatrixRoomKeyBackup({
|
||||
accountId,
|
||||
cfg,
|
||||
recoveryKey: options.recoveryKey,
|
||||
}),
|
||||
onText: (result, verbose) => {
|
||||
@@ -1074,13 +1087,14 @@ export function registerMatrixCli(params: { program: Command }): void {
|
||||
verbose?: boolean;
|
||||
json?: boolean;
|
||||
}) => {
|
||||
const accountId = resolveMatrixCliAccountId(options.account);
|
||||
const { accountId, cfg } = resolveMatrixCliAccountContext(options.account);
|
||||
await runMatrixCliCommand({
|
||||
verbose: options.verbose === true,
|
||||
json: options.json === true,
|
||||
run: async () =>
|
||||
await bootstrapMatrixVerification({
|
||||
accountId,
|
||||
cfg,
|
||||
recoveryKey: options.recoveryKey,
|
||||
forceResetCrossSigning: options.forceResetCrossSigning === true,
|
||||
}),
|
||||
@@ -1129,11 +1143,11 @@ export function registerMatrixCli(params: { program: Command }): void {
|
||||
.option("--json", "Output as JSON")
|
||||
.action(
|
||||
async (key: string, options: { account?: string; verbose?: boolean; json?: boolean }) => {
|
||||
const accountId = resolveMatrixCliAccountId(options.account);
|
||||
const { accountId, cfg } = resolveMatrixCliAccountContext(options.account);
|
||||
await runMatrixCliCommand({
|
||||
verbose: options.verbose === true,
|
||||
json: options.json === true,
|
||||
run: async () => await verifyMatrixRecoveryKey(key, { accountId }),
|
||||
run: async () => await verifyMatrixRecoveryKey(key, { accountId, cfg }),
|
||||
onText: (result, verbose) => {
|
||||
printAccountLabel(accountId);
|
||||
if (!result.success) {
|
||||
|
||||
Reference in New Issue
Block a user