mirror of
https://github.com/Blah-IM/typescript-core.git
synced 2025-04-30 08:11:10 +00:00
refactor: identityFile -> identityDescription
This commit is contained in:
parent
79fbd17ff8
commit
25bab4374d
8 changed files with 66 additions and 57 deletions
|
@ -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.
|
||||
|
|
|
@ -23,5 +23,8 @@
|
|||
},
|
||||
"lint": {
|
||||
"exclude": ["npm/"]
|
||||
},
|
||||
"fmt": {
|
||||
"exclude": ["npm/"]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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", () => {
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
11
identity/identityDescription.test.ts
Normal file
11
identity/identityDescription.test.ts
Normal 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,
|
||||
);
|
||||
});
|
|
@ -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>;
|
|
@ -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);
|
||||
});
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue