Fix admin PKI validation (#766)

Admin PKI fields were falsely flagged as unchanged.

Co-authored-by: philon- <philon-@users.noreply.github.com>
This commit is contained in:
Jeremy Gallant
2025-08-10 04:38:59 +02:00
committed by GitHub
parent a7f56c0bd5
commit 27ed4e58bd
3 changed files with 65 additions and 7 deletions

View File

@@ -197,14 +197,12 @@ export const Security = ({ onFormInit }: SecurityConfigProps) => {
description: t("security.primaryAdminKey.description"),
bits,
devicePSKBitCount: 32,
hide: true,
actionButtons: [],
disabledBy: [
{ fieldName: "adminChannelEnabled", invert: true },
],
properties: {
showCopyButton: true,
showPasswordToggle: true,
},
},
{
@@ -215,14 +213,12 @@ export const Security = ({ onFormInit }: SecurityConfigProps) => {
description: t("security.secondaryAdminKey.description"),
bits,
devicePSKBitCount: 32,
hide: true,
actionButtons: [],
disabledBy: [
{ fieldName: "adminChannelEnabled", invert: true },
],
properties: {
showCopyButton: true,
showPasswordToggle: true,
},
},
{
@@ -233,14 +229,12 @@ export const Security = ({ onFormInit }: SecurityConfigProps) => {
description: t("security.tertiaryAdminKey.description"),
bits,
devicePSKBitCount: 32,
hide: true,
actionButtons: [],
disabledBy: [
{ fieldName: "adminChannelEnabled", invert: true },
],
properties: {
showCopyButton: true,
showPasswordToggle: true,
},
},
{

View File

@@ -57,4 +57,49 @@ describe("deepCompareConfig", () => {
expect(deepCompareConfig([1, 2, 3, 4], [1, 2], true)).toBe(true);
expect(deepCompareConfig([1, 2, 3, 4], [1, 2], false)).toBe(false);
});
it("compares Uint8Array strictly: equal bytes -> true", () => {
const a = new Uint8Array([1, 2, 3]);
const b = new Uint8Array([1, 2, 3]);
expect(deepCompareConfig(a, b)).toBe(true);
});
it("compares Uint8Array strictly: different bytes -> false", () => {
const a = new Uint8Array([1, 2, 3]);
const b = new Uint8Array([1, 2, 4]);
expect(deepCompareConfig(a, b)).toBe(false);
});
it("Uint8Array vs undefined is false even when allowUndefined is true", () => {
const a = new Uint8Array([1, 2, 3]);
expect(deepCompareConfig(a, undefined, true)).toBe(false);
expect(deepCompareConfig(undefined, a, true)).toBe(false);
});
it("nested Uint8Array fields must match exactly", () => {
const existing = { data: new Uint8Array([9, 8, 7]) };
const workingEqual = { data: new Uint8Array([9, 8, 7]) };
const workingDiff = { data: new Uint8Array([9, 8, 6]) };
const workingUndef = { data: undefined as unknown };
expect(deepCompareConfig(existing, workingEqual)).toBe(true);
expect(deepCompareConfig(existing, workingDiff)).toBe(false);
// still false even with allowUndefined
expect(deepCompareConfig(existing, workingUndef, true)).toBe(false);
});
it("arrays containing Uint8Array: element must match exactly", () => {
const a = [new Uint8Array([1, 2]), new Uint8Array([3, 4])];
const b = [new Uint8Array([1, 2]), new Uint8Array([3, 4])];
const c = [new Uint8Array([1, 2]), new Uint8Array([3, 9])];
expect(deepCompareConfig(a, b)).toBe(true);
expect(deepCompareConfig(a, c)).toBe(false);
});
it("shorter working array with missing Uint8Array element -> false even with allowUndefined", () => {
const existing = [new Uint8Array([1, 2]), new Uint8Array([3, 4])];
const workingShort = [new Uint8Array([1, 2])]; // missing the second byte array
expect(deepCompareConfig(existing, workingShort, true)).toBe(false);
});
});

View File

@@ -2,6 +2,22 @@ function isObject(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function isUint8Array(v: unknown): v is Uint8Array {
return v instanceof Uint8Array;
}
function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {
if (a.byteLength !== b.byteLength) {
return false;
}
for (let i = 0; i < a.byteLength; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
export function deepCompareConfig(
a: unknown,
b: unknown,
@@ -11,7 +27,10 @@ export function deepCompareConfig(
return true;
}
// If allowUndefined is true, and one is undefined, they are considered equal. // This check is placed early to simplify subsequent logic.
if (isUint8Array(a) || isUint8Array(b)) {
return isUint8Array(a) && isUint8Array(b) && bytesEqual(a, b);
}
if (allowUndefined && (a === undefined || b === undefined)) {
return true;
}