Browse Source

Fix admin PKI validation (#766)

Admin PKI fields were falsely flagged as unchanged.

Co-authored-by: philon- <[email protected]>
pull/773/head
Jeremy Gallant 10 months ago
committed by GitHub
parent
commit
27ed4e58bd
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      packages/web/src/components/PageComponents/Config/Security/Security.tsx
  2. 45
      packages/web/src/core/utils/deepCompareConfig.test.ts
  3. 21
      packages/web/src/core/utils/deepCompareConfig.ts

6
packages/web/src/components/PageComponents/Config/Security/Security.tsx

@ -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,
},
},
{

45
packages/web/src/core/utils/deepCompareConfig.test.ts

@ -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);
});
});

21
packages/web/src/core/utils/deepCompareConfig.ts

@ -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;
}

Loading…
Cancel
Save