mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:40:44 +00:00
test(matrix): share legacy credential setup helper
This commit is contained in:
@@ -14,6 +14,13 @@ import {
|
||||
touchMatrixCredentials,
|
||||
} from "./credentials.js";
|
||||
|
||||
const DEFAULT_LEGACY_CREDENTIALS = {
|
||||
homeserver: "https://matrix.example.org",
|
||||
userId: "@bot:example.org",
|
||||
accessToken: "legacy-token",
|
||||
createdAt: "2026-03-01T10:00:00.000Z",
|
||||
};
|
||||
|
||||
describe("matrix credentials storage", () => {
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
@@ -37,6 +44,19 @@ describe("matrix credentials storage", () => {
|
||||
return dir;
|
||||
}
|
||||
|
||||
function setupLegacyCredentialsFile(params: {
|
||||
cfg: Record<string, unknown>;
|
||||
accountId: string;
|
||||
credentials?: Record<string, unknown>;
|
||||
}) {
|
||||
const stateDir = setupStateDir(params.cfg);
|
||||
const legacyPath = path.join(stateDir, "credentials", "matrix", "credentials.json");
|
||||
const currentPath = resolveMatrixCredentialsPath({}, params.accountId);
|
||||
fs.mkdirSync(path.dirname(legacyPath), { recursive: true });
|
||||
fs.writeFileSync(legacyPath, JSON.stringify(params.credentials ?? DEFAULT_LEGACY_CREDENTIALS));
|
||||
return { stateDir, legacyPath, currentPath };
|
||||
}
|
||||
|
||||
it("writes credentials atomically with secure file permissions", async () => {
|
||||
const stateDir = setupStateDir();
|
||||
await saveMatrixCredentials(
|
||||
@@ -216,27 +236,18 @@ describe("matrix credentials storage", () => {
|
||||
});
|
||||
|
||||
it("migrates legacy matrix credential files on read", async () => {
|
||||
const stateDir = setupStateDir({
|
||||
channels: {
|
||||
matrix: {
|
||||
accounts: {
|
||||
ops: {},
|
||||
const { legacyPath, currentPath } = setupLegacyCredentialsFile({
|
||||
cfg: {
|
||||
channels: {
|
||||
matrix: {
|
||||
accounts: {
|
||||
ops: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
accountId: "ops",
|
||||
});
|
||||
const legacyPath = path.join(stateDir, "credentials", "matrix", "credentials.json");
|
||||
const currentPath = resolveMatrixCredentialsPath({}, "ops");
|
||||
fs.mkdirSync(path.dirname(legacyPath), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
legacyPath,
|
||||
JSON.stringify({
|
||||
homeserver: "https://matrix.example.org",
|
||||
userId: "@bot:example.org",
|
||||
accessToken: "legacy-token",
|
||||
createdAt: "2026-03-01T10:00:00.000Z",
|
||||
}),
|
||||
);
|
||||
|
||||
const loaded = loadMatrixCredentials({}, "ops");
|
||||
|
||||
@@ -246,33 +257,24 @@ describe("matrix credentials storage", () => {
|
||||
});
|
||||
|
||||
it("returns migrated credentials when another process moves the legacy file mid-read", () => {
|
||||
const stateDir = setupStateDir({
|
||||
channels: {
|
||||
matrix: {
|
||||
accounts: {
|
||||
ops: {},
|
||||
const { legacyPath, currentPath } = setupLegacyCredentialsFile({
|
||||
cfg: {
|
||||
channels: {
|
||||
matrix: {
|
||||
accounts: {
|
||||
ops: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
accountId: "ops",
|
||||
});
|
||||
const legacyPath = path.join(stateDir, "credentials", "matrix", "credentials.json");
|
||||
const currentPath = resolveMatrixCredentialsPath({}, "ops");
|
||||
fs.mkdirSync(path.dirname(legacyPath), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
legacyPath,
|
||||
JSON.stringify({
|
||||
homeserver: "https://matrix.example.org",
|
||||
userId: "@bot:example.org",
|
||||
accessToken: "legacy-token",
|
||||
createdAt: "2026-03-01T10:00:00.000Z",
|
||||
}),
|
||||
);
|
||||
|
||||
const originalReadFileSync = fs.readFileSync.bind(fs);
|
||||
let moved = false;
|
||||
const readFileSpy = vi.spyOn(fs, "readFileSync").mockImplementation(((
|
||||
filePath: fs.PathOrFileDescriptor,
|
||||
options?: fs.ObjectEncodingOptions | BufferEncoding | null,
|
||||
options?: Parameters<typeof fs.readFileSync>[1],
|
||||
) => {
|
||||
if (!moved && filePath === legacyPath) {
|
||||
fs.renameSync(legacyPath, currentPath);
|
||||
@@ -293,27 +295,18 @@ describe("matrix credentials storage", () => {
|
||||
});
|
||||
|
||||
it("does not rename the legacy path after falling back to already-migrated current credentials", () => {
|
||||
const stateDir = setupStateDir({
|
||||
channels: {
|
||||
matrix: {
|
||||
accounts: {
|
||||
ops: {},
|
||||
const { legacyPath, currentPath } = setupLegacyCredentialsFile({
|
||||
cfg: {
|
||||
channels: {
|
||||
matrix: {
|
||||
accounts: {
|
||||
ops: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
accountId: "ops",
|
||||
});
|
||||
const legacyPath = path.join(stateDir, "credentials", "matrix", "credentials.json");
|
||||
const currentPath = resolveMatrixCredentialsPath({}, "ops");
|
||||
fs.mkdirSync(path.dirname(legacyPath), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
legacyPath,
|
||||
JSON.stringify({
|
||||
homeserver: "https://matrix.example.org",
|
||||
userId: "@bot:example.org",
|
||||
accessToken: "legacy-token",
|
||||
createdAt: "2026-03-01T10:00:00.000Z",
|
||||
}),
|
||||
);
|
||||
|
||||
const originalReadFileSync = fs.readFileSync.bind(fs);
|
||||
const originalRenameSync = fs.renameSync.bind(fs);
|
||||
@@ -321,7 +314,7 @@ describe("matrix credentials storage", () => {
|
||||
let migrated = false;
|
||||
const readFileSpy = vi.spyOn(fs, "readFileSync").mockImplementation(((
|
||||
filePath: fs.PathOrFileDescriptor,
|
||||
options?: fs.ObjectEncodingOptions | BufferEncoding | null,
|
||||
options?: Parameters<typeof fs.readFileSync>[1],
|
||||
) => {
|
||||
if (!migrated && filePath === legacyPath && fs.existsSync(legacyPath)) {
|
||||
originalRenameSync(legacyPath, currentPath);
|
||||
@@ -374,32 +367,29 @@ describe("matrix credentials storage", () => {
|
||||
});
|
||||
|
||||
it("does not migrate legacy default credentials during a non-selected account read", () => {
|
||||
const stateDir = setupStateDir({
|
||||
channels: {
|
||||
matrix: {
|
||||
defaultAccount: "default",
|
||||
accounts: {
|
||||
default: {
|
||||
homeserver: "https://matrix.default.example.org",
|
||||
accessToken: "default-token",
|
||||
const { legacyPath, currentPath } = setupLegacyCredentialsFile({
|
||||
cfg: {
|
||||
channels: {
|
||||
matrix: {
|
||||
defaultAccount: "default",
|
||||
accounts: {
|
||||
default: {
|
||||
homeserver: "https://matrix.default.example.org",
|
||||
accessToken: "default-token",
|
||||
},
|
||||
ops: {},
|
||||
},
|
||||
ops: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const legacyPath = path.join(stateDir, "credentials", "matrix", "credentials.json");
|
||||
const currentPath = resolveMatrixCredentialsPath({}, "ops");
|
||||
fs.mkdirSync(path.dirname(legacyPath), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
legacyPath,
|
||||
JSON.stringify({
|
||||
accountId: "ops",
|
||||
credentials: {
|
||||
homeserver: "https://matrix.default.example.org",
|
||||
userId: "@default:example.org",
|
||||
accessToken: "default-token",
|
||||
createdAt: "2026-03-01T10:00:00.000Z",
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const loaded = loadMatrixCredentials({}, "ops");
|
||||
|
||||
@@ -409,31 +399,28 @@ describe("matrix credentials storage", () => {
|
||||
});
|
||||
|
||||
it("migrates legacy credentials to the named account when top-level auth is only a shared default", () => {
|
||||
const stateDir = setupStateDir({
|
||||
channels: {
|
||||
matrix: {
|
||||
accessToken: "shared-token",
|
||||
accounts: {
|
||||
ops: {
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "ops-token",
|
||||
const { legacyPath, currentPath } = setupLegacyCredentialsFile({
|
||||
cfg: {
|
||||
channels: {
|
||||
matrix: {
|
||||
accessToken: "shared-token",
|
||||
accounts: {
|
||||
ops: {
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "ops-token",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const legacyPath = path.join(stateDir, "credentials", "matrix", "credentials.json");
|
||||
const currentPath = resolveMatrixCredentialsPath({}, "ops");
|
||||
fs.mkdirSync(path.dirname(legacyPath), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
legacyPath,
|
||||
JSON.stringify({
|
||||
accountId: "ops",
|
||||
credentials: {
|
||||
homeserver: "https://matrix.example.org",
|
||||
userId: "@ops:example.org",
|
||||
accessToken: "legacy-token",
|
||||
createdAt: "2026-03-01T10:00:00.000Z",
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const loaded = loadMatrixCredentials({}, "ops");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user