refactor: identityFile -> identityDescription

This commit is contained in:
Shibo Lyu 2024-10-31 01:51:34 +08:00
parent 79fbd17ff8
commit 25bab4374d
8 changed files with 66 additions and 57 deletions

View file

@ -18,4 +18,6 @@ deno add jsr:@blah/core
A symbol API document is available on JSR: https://jsr.io/@blah/core/doc
## License
This project is licensed under GNU General Public License v3.0. See [LICENSE](LICENSE) for more details.
This project is licensed under GNU General Public License v3.0. See
[LICENSE](LICENSE) for more details.

View file

@ -23,5 +23,8 @@
},
"lint": {
"exclude": ["npm/"]
},
"fmt": {
"exclude": ["npm/"]
}
}

View file

@ -1,7 +1,7 @@
import { expect } from "@std/expect";
import { BlahKeyPair } from "../crypto/mod.ts";
import { BlahIdentity } from "./identity.ts";
import type { BlahIdentityFile, BlahProfile } from "./mod.ts";
import type { BlahIdentityDescription, BlahProfile } from "./mod.ts";
let idKeyPair: BlahKeyPair;
let actKeyPair: BlahKeyPair;
@ -13,7 +13,7 @@ const profile: BlahProfile = {
};
let identity: BlahIdentity;
let identityFile: BlahIdentityFile;
let identityDesc: BlahIdentityDescription;
let identityFromFile: BlahIdentity;
Deno.test("create identity", async () => {
@ -22,13 +22,13 @@ Deno.test("create identity", async () => {
identity = await BlahIdentity.create(idKeyPair, actKeyPair, profile);
});
Deno.test("generate identity file", () => {
identityFile = identity.generateIdentityFile();
Deno.test("generate identity description", () => {
identityDesc = identity.generateidentityDescription();
});
Deno.test("created identity act key signed correctly", async () => {
const record = await identity.idPublicKey.verifyPayload(
identityFile.act_keys[0],
identityDesc.act_keys[0],
);
expect(record.typ).toBe("user_act_key");
expect(record.expire_time).toBeGreaterThan(Date.now() / 1000);
@ -38,7 +38,7 @@ Deno.test("created identity act key signed correctly", async () => {
Deno.test("created identity profile signed correctly", async () => {
const record = await actKeyPair.publicKey.verifyPayload(
identityFile.profile,
identityDesc.profile,
);
expect(record.typ).toBe("profile");
expect(record.name).toBe("Shibo Lyu");
@ -46,35 +46,35 @@ Deno.test("created identity profile signed correctly", async () => {
expect(record.id_urls).toEqual([]);
});
Deno.test("parse identity file", async () => {
identityFromFile = await BlahIdentity.fromIdentityFile(identityFile);
Deno.test("parse identity description", async () => {
identityFromFile = await BlahIdentity.fromidentityDescription(identityDesc);
});
Deno.test("identity file profile sigs are properly verfied", async () => {
const identityFileWithProfileInvalidProfileSig: BlahIdentityFile = {
...identityFile,
profile: { ...identityFile.profile, sig: "_ obviously not a valid sig _" },
Deno.test("identity description profile sigs are properly verfied", async () => {
const identityDescWithProfileInvalidProfileSig: BlahIdentityDescription = {
...identityDesc,
profile: { ...identityDesc.profile, sig: "_ obviously not a valid sig _" },
};
const identityWithProfileInvalidProfileSig = await BlahIdentity
.fromIdentityFile(
identityFileWithProfileInvalidProfileSig,
.fromidentityDescription(
identityDescWithProfileInvalidProfileSig,
);
expect(identityWithProfileInvalidProfileSig.profileSigValid).toBe(false);
});
Deno.test("identity file act key sigs are properly verfied", async () => {
const identityFileWithActKeyInvalidActKeySig: BlahIdentityFile = {
...identityFile,
Deno.test("identity description act key sigs are properly verfied", async () => {
const identityDescWithActKeyInvalidActKeySig: BlahIdentityDescription = {
...identityDesc,
act_keys: [
{
...identityFile.act_keys[0],
...identityDesc.act_keys[0],
sig: "_ obviously not a valid sig _",
},
],
};
const identityWithActKeyInvalidActKeySig = await BlahIdentity
.fromIdentityFile(
identityFileWithActKeyInvalidActKeySig,
.fromidentityDescription(
identityDescWithActKeyInvalidActKeySig,
);
expect(identityWithActKeyInvalidActKeySig.actKeys[0].isSigValid).toBe(false);
});
@ -82,10 +82,10 @@ Deno.test("identity file act key sigs are properly verfied", async () => {
Deno.test("add a second act key", async () => {
const actKeyPair2 = await BlahKeyPair.generate();
await identity.addActKey(actKeyPair2, { comment: "test" });
identityFile = identity.generateIdentityFile();
identityDesc = identity.generateidentityDescription();
const record = await identity.idPublicKey.verifyPayload(
identityFile.act_keys[1],
identityDesc.act_keys[1],
);
expect(record.typ).toBe("user_act_key");
@ -96,10 +96,10 @@ Deno.test("add a second act key", async () => {
Deno.test("update first act key", async () => {
await identity.updateActKey(actKeyPair.id, { comment: "test2" });
identityFile = identity.generateIdentityFile();
identityDesc = identity.generateidentityDescription();
const record = await identity.idPublicKey.verifyPayload(
identityFile.act_keys[0],
identityDesc.act_keys[0],
);
expect(record.comment).toBe("test2");
@ -120,9 +120,9 @@ Deno.test("update profile", async () => {
};
await identity.updateProfile(newProfile);
identityFile = identity.generateIdentityFile();
identityDesc = identity.generateidentityDescription();
expect(identityFile.profile.signee.payload).toEqual(newProfile);
expect(identityDesc.profile.signee.payload).toEqual(newProfile);
});
Deno.test("throw when try writing to identity without id key pair", () => {

View file

@ -4,8 +4,8 @@ import {
type BlahSignedPayload,
} from "../crypto/mod.ts";
import { type ActKeyUpdate, BlahActKey } from "./actKey.ts";
import { blahIdentityFileSchema } from "./identityFile.ts";
import type { BlahIdentityFile } from "./mod.ts";
import { blahIdentityDescriptionSchema } from "./identityDescription.ts";
import type { BlahIdentityDescription } from "./mod.ts";
import type { BlahProfile } from "./profile.ts";
export class BlahIdentity {
@ -44,22 +44,24 @@ export class BlahIdentity {
return this.internalActKeys;
}
static async fromIdentityFile(
identityFile: unknown,
static async fromidentityDescription(
identityDesc: unknown,
idKeyPair?: BlahKeyPair,
actingKeyPair?: BlahKeyPair,
): Promise<BlahIdentity> {
let identityFileJson = identityFile;
if (typeof identityFile === "string") {
identityFileJson = JSON.parse(identityFile);
let identityDescJson = identityDesc;
if (typeof identityDesc === "string") {
identityDescJson = JSON.parse(identityDesc);
}
const { id_key, act_keys, profile } = blahIdentityFileSchema.parse(
identityFileJson,
const { id_key, act_keys, profile } = blahIdentityDescriptionSchema.parse(
identityDescJson,
);
const idKey = idKeyPair ?? await BlahPublicKey.fromID(id_key);
if (idKey.id !== id_key) {
throw new Error("ID key pair does not match ID key in identity file.");
throw new Error(
"ID key pair does not match ID key in identity description.",
);
}
const idKeyPublic = idKey instanceof BlahKeyPair ? idKey.publicKey : idKey;
@ -108,13 +110,13 @@ export class BlahIdentity {
return new BlahIdentity(idKeyPair, [actKey], profileRecord, true);
}
generateIdentityFile(): BlahIdentityFile {
return blahIdentityFileSchema.parse(
generateidentityDescription(): BlahIdentityDescription {
return blahIdentityDescriptionSchema.parse(
{
id_key: this.idPublicKey.id,
act_keys: this.internalActKeys.map((k) => k.toSignedRecord()),
profile: this.rawProfile,
} satisfies BlahIdentityFile,
} satisfies BlahIdentityDescription,
);
}

View file

@ -0,0 +1,11 @@
import {
type BlahIdentityDescription,
blahIdentityDescriptionSchema,
} from "./identityDescription.ts";
import { assertTypeMatchesZodSchema } from "../test/utils.ts";
Deno.test("type BlahidentityDescription is accurate", () => {
assertTypeMatchesZodSchema<BlahIdentityDescription>(
blahIdentityDescriptionSchema,
);
});

View file

@ -4,13 +4,13 @@ import { type BlahActKeyRecord, blahActKeyRecordSchema } from "./actKey.ts";
import { type BlahProfile, blahProfileSchema } from "./profile.ts";
import type { BlahSignedPayload } from "../crypto/mod.ts";
export const blahIdentityFileSchema = z.object({
export const blahIdentityDescriptionSchema = z.object({
id_key: z.string(),
act_keys: z.array(blahSignedPayloadSchemaOf(blahActKeyRecordSchema)).min(1),
profile: blahSignedPayloadSchemaOf(blahProfileSchema),
});
export type BlahIdentityFile = {
export type BlahIdentityDescription = {
id_key: string;
act_keys: Array<BlahSignedPayload<BlahActKeyRecord>>;
profile: BlahSignedPayload<BlahProfile>;

View file

@ -1,9 +0,0 @@
import {
type BlahIdentityFile,
blahIdentityFileSchema,
} from "./identityFile.ts";
import { assertTypeMatchesZodSchema } from "../test/utils.ts";
Deno.test("type BlahIdentityFile is accurate", () => {
assertTypeMatchesZodSchema<BlahIdentityFile>(blahIdentityFileSchema);
});

View file

@ -10,12 +10,12 @@ const blahProfileSchema: z.ZodType<BlahProfile> = internalBlahProfileSchema;
export { type BlahProfile, blahProfileSchema };
import {
type BlahIdentityFile,
blahIdentityFileSchema as internalBlahIdentityFileSchema,
} from "./identityFile.ts";
const blahIdentityFileSchema: z.ZodType<BlahIdentityFile> =
internalBlahIdentityFileSchema;
export { type BlahIdentityFile, blahIdentityFileSchema };
type BlahIdentityDescription,
blahIdentityDescriptionSchema as internalBlahidentityDescriptionSchema,
} from "./identityDescription.ts";
const blahidentityDescriptionSchema: z.ZodType<BlahIdentityDescription> =
internalBlahidentityDescriptionSchema;
export { type BlahIdentityDescription, blahidentityDescriptionSchema };
import {
type BlahActKeyRecord,