feat(model): add credential model

This commit is contained in:
Julien Oculi 2024-05-13 17:01:17 +02:00
parent f9016ffc10
commit 0d78bc48ae

View file

@ -0,0 +1,103 @@
import { ToJson } from '@/types.ts'
import { Ressource } from '@models/ressource.ts'
export class Credential extends Ressource {
static fromJSON(
json: ToJson<Credential>,
): Credential {
return new Credential(json)
}
static create(
{ category, store, name }: Pick<Credential, 'category' | 'store' | 'name'>,
): Credential {
const { uuid, createdAt, updatedAt } = super.create({ name })
return new Credential({ uuid, createdAt, updatedAt, name, category, store })
}
#category: 'password' | 'ssh' | 'passkey'
#store: CredentialCategory<Credential['category']>
private constructor(
{ category, store, ...props }:
& Pick<Credential, 'category' | 'store'>
& Pick<Ressource, 'name' | 'uuid' | 'createdAt' | 'updatedAt'>,
) {
super(props)
if (!['password', 'ssh', 'passkey'].includes(category)) {
throw new TypeError(
`category is "${category}" but ('password' | 'ssh' | 'passkey') is required`,
)
}
this.#category = category
this.#store = Object.freeze(store)
}
get type(): 'credential' {
return 'credential'
}
get category() {
return this.#category
}
get store() {
return Object.freeze(this.#store)
}
update(
props: Partial<Omit<Credential, 'type' | 'uuid' | 'createdAt'>>,
): Credential {
const { updatedAt } = super.update(props)
const credential = new Credential({ ...this, ...props, updatedAt })
return credential
}
toJSON() {
return {
...super.toJSON(),
type: this.type,
category: this.category,
store: Object.freeze(this.store),
} as const
}
toString(): string {
return `Credential (${JSON.stringify(this)})`
}
}
export interface Credential extends Ressource {
type: 'credential'
category: 'password' | 'ssh' | 'passkey'
store: Readonly<CredentialCategory<Credential['category']>>
}
type CredentialCategory<T extends 'password' | 'ssh' | 'passkey'> = T extends
'password' ? {
store: {
hash: Uint8Array
alg: string
salt: Uint8Array
}
}
: T extends 'ssh' ? {
store: {
publicKey: string
}
}
: T extends 'passkey' ? {
store: Record<string, unknown>
}
: never
/*
PassKey store:
{
publicKey: Uint8Array
keyId: string
transport: string
counter: number
}
*/