109 lines
3.0 KiB
TypeScript
109 lines
3.0 KiB
TypeScript
import { SharedContainer } from "./container";
|
|
import { Storable } from "./storage";
|
|
import { VaultItemCollection } from "./collection";
|
|
import { AccountID, UnlockedAccount } from "./account";
|
|
import { OrgInfo } from "./org";
|
|
import { Exclude, AsDate } from "./encoding";
|
|
import { Err } from "./error";
|
|
|
|
/** Unique identifier for [[Vault]] objects */
|
|
export type VaultID = string;
|
|
|
|
/**
|
|
* Container for securely storing a collection of [[VaultItem]]s. Vaults can be owned by a single
|
|
* user ("private" vaults) or shared between multiple users ("shared" vaults). Shared vaults are
|
|
* provisioned and managed through [[Org]]s.
|
|
*/
|
|
export class Vault extends SharedContainer implements Storable {
|
|
/** unique identifier */
|
|
id: VaultID = "";
|
|
|
|
/** The [[Org]] this vault belongs to (if a shared vault) */
|
|
org?: OrgInfo = undefined;
|
|
|
|
/** Vault name */
|
|
name = "";
|
|
|
|
/** The vault owner (the [[Account]] that created this vault) */
|
|
owner: AccountID = "";
|
|
|
|
/** Time of creation */
|
|
@AsDate()
|
|
created = new Date(0);
|
|
|
|
/** Time of last update */
|
|
@AsDate()
|
|
updated = new Date(0);
|
|
|
|
/**
|
|
* Revision id used for ensuring continuity when synchronizing the vault
|
|
* object between client and server
|
|
*/
|
|
revision: string = "";
|
|
|
|
/**
|
|
* A collection [[VaultItem]]s representing the senstive data store in this vault
|
|
*
|
|
* @secret
|
|
*
|
|
* **IMPORTANT**: This property is considered **secret**
|
|
* and should never stored or transmitted in plain text
|
|
*/
|
|
@Exclude()
|
|
items = new VaultItemCollection();
|
|
|
|
@Exclude()
|
|
error?: Err;
|
|
|
|
/**
|
|
* Unlocks the vault with the given `account`, decrypting the data stored in the vault
|
|
* and populating the [[items]] property. For this to be successful, the `account` object
|
|
* needs to be unlocked and the account must have access to this vault.
|
|
*/
|
|
async unlock(account: UnlockedAccount) {
|
|
if (!this.accessors.length) {
|
|
await this.updateAccessors([account]);
|
|
await this.commit();
|
|
} else {
|
|
await super.unlock(account);
|
|
this.items.fromBytes(await this.getData());
|
|
}
|
|
}
|
|
|
|
async lock() {
|
|
await super.lock();
|
|
this.items = new VaultItemCollection();
|
|
}
|
|
|
|
/**
|
|
* Commit changes to `items` by reencrypting the data.
|
|
*/
|
|
async commit() {
|
|
await this.setData(this.items.toBytes());
|
|
}
|
|
|
|
/**
|
|
* Merges in changes from another `vault`. This requires both vaults to be unlocked.
|
|
*/
|
|
merge(vault: Vault) {
|
|
this.items.merge(vault.items);
|
|
this.name = vault.name;
|
|
this.revision = vault.revision;
|
|
this.org = vault.org;
|
|
this.accessors = vault.accessors;
|
|
this._key = vault._key;
|
|
this.encryptedData = vault.encryptedData;
|
|
this.updated = vault.updated;
|
|
}
|
|
|
|
toString() {
|
|
return this.org ? `${this.org.name} / ${this.name}` : this.name;
|
|
}
|
|
|
|
clone() {
|
|
const clone = super.clone();
|
|
clone.items = this.items.clone();
|
|
return clone;
|
|
}
|
|
}
|