feat: release authentication diagnostics 0.2.0
This commit is contained in:
@@ -2,10 +2,11 @@ import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
exportCsv,
|
||||
importCsv,
|
||||
importGoogleMigrationBatch,
|
||||
importOtpAuthList,
|
||||
importPlainPskc,
|
||||
} from "../../src/otp/migration";
|
||||
import { utf8ToBytes } from "../../src/crypto/encoding";
|
||||
import { bytesToBase64Url, utf8ToBytes } from "../../src/crypto/encoding";
|
||||
import type { OtpProfile } from "../../src/otp/profile";
|
||||
|
||||
const profile: OtpProfile = {
|
||||
@@ -20,6 +21,43 @@ const profile: OtpProfile = {
|
||||
extensions: new Map(),
|
||||
};
|
||||
|
||||
function varint(value: number): number[] {
|
||||
const output: number[] = [];
|
||||
let remaining = value;
|
||||
do {
|
||||
let byte = remaining & 0x7f;
|
||||
remaining >>>= 7;
|
||||
if (remaining) byte |= 0x80;
|
||||
output.push(byte);
|
||||
} while (remaining);
|
||||
return output;
|
||||
}
|
||||
|
||||
function field(number: number, value: number | Uint8Array): number[] {
|
||||
return typeof value === "number"
|
||||
? [...varint(number << 3), ...varint(value)]
|
||||
: [...varint((number << 3) | 2), ...varint(value.length), ...value];
|
||||
}
|
||||
|
||||
function googlePart(index: number, size = 2, id = 73): string {
|
||||
const credential = Uint8Array.from([
|
||||
...field(1, utf8ToBytes("12345678901234567890")),
|
||||
...field(2, utf8ToBytes(`user-${index}`)),
|
||||
...field(3, utf8ToBytes("Example")),
|
||||
...field(4, 1),
|
||||
...field(5, 1),
|
||||
...field(6, 2),
|
||||
]);
|
||||
const payload = Uint8Array.from([
|
||||
...field(1, credential),
|
||||
...field(2, 1),
|
||||
...field(3, size),
|
||||
...field(4, index),
|
||||
...field(5, id),
|
||||
]);
|
||||
return `otpauth-migration://offline?data=${bytesToBase64Url(payload)}`;
|
||||
}
|
||||
|
||||
describe("OTP migrations", () => {
|
||||
it("round-trips the documented CSV including quoting", () => {
|
||||
const result = importCsv(exportCsv([profile]));
|
||||
@@ -63,4 +101,18 @@ describe("OTP migrations", () => {
|
||||
),
|
||||
).toThrow(/encrypted/iu);
|
||||
});
|
||||
|
||||
it("assembles Google multi-QR batches in index order", () => {
|
||||
const result = importGoogleMigrationBatch([googlePart(1), googlePart(0)]);
|
||||
expect(result.profiles.map((item) => item.account)).toEqual([
|
||||
"user-0",
|
||||
"user-1",
|
||||
]);
|
||||
expect(() => importGoogleMigrationBatch([googlePart(0)])).toThrow(
|
||||
/missing part 2/iu,
|
||||
);
|
||||
expect(() =>
|
||||
importGoogleMigrationBatch([googlePart(0), googlePart(1, 2, 99)]),
|
||||
).toThrow(/different batches/iu);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user