mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
[SG-998] and [SG-999] Vault and Autofill team refactor (#4542)
* Move DeprecatedVaultFilterService to vault folder * [libs] move VaultItemsComponent * [libs] move AddEditComponent * [libs] move AddEditCustomFields * [libs] move attachmentsComponent * [libs] folderAddEditComponent * [libs] IconComponent * [libs] PasswordRepormptComponent * [libs] PremiumComponent * [libs] ViewCustomFieldsComponent * [libs] ViewComponent * [libs] PasswordRepromptService * [libs] Move FolderService and FolderApiService abstractions * [libs] FolderService imports * [libs] PasswordHistoryComponent * [libs] move Sync and SyncNotifier abstractions * [libs] SyncService imports * [libs] fix file casing for passwordReprompt abstraction * [libs] SyncNotifier import fix * [libs] CipherServiceAbstraction * [libs] PasswordRepromptService abstraction * [libs] Fix file casing for angular passwordReprompt service * [libs] fix file casing for SyncNotifierService * [libs] CipherRepromptType * [libs] rename CipherRepromptType * [libs] CipherType * [libs] Rename CipherType * [libs] CipherData * [libs] FolderData * [libs] PasswordHistoryData * [libs] AttachmentData * [libs] CardData * [libs] FieldData * [libs] IdentityData * [libs] LocalData * [libs] LoginData * [libs] SecureNoteData * [libs] LoginUriData * [libs] Domain classes * [libs] SecureNote * [libs] Request models * [libs] Response models * [libs] View part 1 * [libs] Views part 2 * [libs] Move folder services * [libs] Views fixes * [libs] Move sync services * [libs] cipher service * [libs] Types * [libs] Sync file casing * [libs] Fix folder service import * [libs] Move spec files * [libs] casing fixes on spec files * [browser] Autofill background, clipboard, commands * [browser] Fix ContextMenusBackground casing * [browser] Rename fix * [browser] Autofill content * [browser] autofill.js * [libs] enpass importer spec fix * [browser] autofill models * [browser] autofill manifest path updates * [browser] Autofill notification files * [browser] autofill services * [browser] Fix file casing * [browser] Vault popup loose components * [browser] Vault components * [browser] Manifest fixes * [browser] Vault services * [cli] vault commands and models * [browser] File capitilization fixes * [desktop] Vault components and services * [web] vault loose components * [web] Vault components * [browser] Fix misc-utils import * [libs] Fix psono spec imports * [fix] Add comments to address lint rules
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
import { AttachmentResponse } from "../response/attachment.response";
|
||||
|
||||
export class AttachmentData {
|
||||
id: string;
|
||||
url: string;
|
||||
fileName: string;
|
||||
key: string;
|
||||
size: string;
|
||||
sizeName: string;
|
||||
|
||||
constructor(response?: AttachmentResponse) {
|
||||
if (response == null) {
|
||||
return;
|
||||
}
|
||||
this.id = response.id;
|
||||
this.url = response.url;
|
||||
this.fileName = response.fileName;
|
||||
this.key = response.key;
|
||||
this.size = response.size;
|
||||
this.sizeName = response.sizeName;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import { CardApi } from "../api/card.api";
|
||||
|
||||
export class CardData {
|
||||
cardholderName: string;
|
||||
brand: string;
|
||||
number: string;
|
||||
expMonth: string;
|
||||
expYear: string;
|
||||
code: string;
|
||||
|
||||
constructor(data?: CardApi) {
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.cardholderName = data.cardholderName;
|
||||
this.brand = data.brand;
|
||||
this.number = data.number;
|
||||
this.expMonth = data.expMonth;
|
||||
this.expYear = data.expYear;
|
||||
this.code = data.code;
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
import { CipherRepromptType } from "../../enums/cipherRepromptType";
|
||||
import { CipherType } from "../../enums/cipherType";
|
||||
import { CipherResponse } from "../response/cipher.response";
|
||||
|
||||
import { AttachmentData } from "./attachment.data";
|
||||
import { CardData } from "./card.data";
|
||||
import { FieldData } from "./field.data";
|
||||
import { IdentityData } from "./identity.data";
|
||||
import { LoginData } from "./login.data";
|
||||
import { PasswordHistoryData } from "./password-history.data";
|
||||
import { SecureNoteData } from "./secure-note.data";
|
||||
|
||||
export class CipherData {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
folderId: string;
|
||||
edit: boolean;
|
||||
viewPassword: boolean;
|
||||
organizationUseTotp: boolean;
|
||||
favorite: boolean;
|
||||
revisionDate: string;
|
||||
type: CipherType;
|
||||
name: string;
|
||||
notes: string;
|
||||
login?: LoginData;
|
||||
secureNote?: SecureNoteData;
|
||||
card?: CardData;
|
||||
identity?: IdentityData;
|
||||
fields?: FieldData[];
|
||||
attachments?: AttachmentData[];
|
||||
passwordHistory?: PasswordHistoryData[];
|
||||
collectionIds?: string[];
|
||||
creationDate: string;
|
||||
deletedDate: string;
|
||||
reprompt: CipherRepromptType;
|
||||
|
||||
constructor(response?: CipherResponse, collectionIds?: string[]) {
|
||||
if (response == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.id = response.id;
|
||||
this.organizationId = response.organizationId;
|
||||
this.folderId = response.folderId;
|
||||
this.edit = response.edit;
|
||||
this.viewPassword = response.viewPassword;
|
||||
this.organizationUseTotp = response.organizationUseTotp;
|
||||
this.favorite = response.favorite;
|
||||
this.revisionDate = response.revisionDate;
|
||||
this.type = response.type;
|
||||
this.name = response.name;
|
||||
this.notes = response.notes;
|
||||
this.collectionIds = collectionIds != null ? collectionIds : response.collectionIds;
|
||||
this.creationDate = response.creationDate;
|
||||
this.deletedDate = response.deletedDate;
|
||||
this.reprompt = response.reprompt;
|
||||
|
||||
switch (this.type) {
|
||||
case CipherType.Login:
|
||||
this.login = new LoginData(response.login);
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
this.secureNote = new SecureNoteData(response.secureNote);
|
||||
break;
|
||||
case CipherType.Card:
|
||||
this.card = new CardData(response.card);
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
this.identity = new IdentityData(response.identity);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (response.fields != null) {
|
||||
this.fields = response.fields.map((f) => new FieldData(f));
|
||||
}
|
||||
if (response.attachments != null) {
|
||||
this.attachments = response.attachments.map((a) => new AttachmentData(a));
|
||||
}
|
||||
if (response.passwordHistory != null) {
|
||||
this.passwordHistory = response.passwordHistory.map((ph) => new PasswordHistoryData(ph));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { FieldType } from "../../enums/fieldType";
|
||||
import { LinkedIdType } from "../../enums/linkedIdType";
|
||||
import { FieldApi } from "../api/field.api";
|
||||
|
||||
export class FieldData {
|
||||
type: FieldType;
|
||||
name: string;
|
||||
value: string;
|
||||
linkedId: LinkedIdType;
|
||||
|
||||
constructor(response?: FieldApi) {
|
||||
if (response == null) {
|
||||
return;
|
||||
}
|
||||
this.type = response.type;
|
||||
this.name = response.name;
|
||||
this.value = response.value;
|
||||
this.linkedId = response.linkedId;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { FolderResponse } from "../response/folder.response";
|
||||
|
||||
export class FolderData {
|
||||
id: string;
|
||||
name: string;
|
||||
revisionDate: string;
|
||||
|
||||
constructor(response: FolderResponse) {
|
||||
this.name = response.name;
|
||||
this.id = response.id;
|
||||
this.revisionDate = response.revisionDate;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import { IdentityApi } from "../api/identity.api";
|
||||
|
||||
export class IdentityData {
|
||||
title: string;
|
||||
firstName: string;
|
||||
middleName: string;
|
||||
lastName: string;
|
||||
address1: string;
|
||||
address2: string;
|
||||
address3: string;
|
||||
city: string;
|
||||
state: string;
|
||||
postalCode: string;
|
||||
country: string;
|
||||
company: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
ssn: string;
|
||||
username: string;
|
||||
passportNumber: string;
|
||||
licenseNumber: string;
|
||||
|
||||
constructor(data?: IdentityApi) {
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.title = data.title;
|
||||
this.firstName = data.firstName;
|
||||
this.middleName = data.middleName;
|
||||
this.lastName = data.lastName;
|
||||
this.address1 = data.address1;
|
||||
this.address2 = data.address2;
|
||||
this.address3 = data.address3;
|
||||
this.city = data.city;
|
||||
this.state = data.state;
|
||||
this.postalCode = data.postalCode;
|
||||
this.country = data.country;
|
||||
this.company = data.company;
|
||||
this.email = data.email;
|
||||
this.phone = data.phone;
|
||||
this.ssn = data.ssn;
|
||||
this.username = data.username;
|
||||
this.passportNumber = data.passportNumber;
|
||||
this.licenseNumber = data.licenseNumber;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
export type LocalData = {
|
||||
lastUsedDate?: number;
|
||||
lastLaunched?: number;
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
import { UriMatchType } from "../../enums/uriMatchType";
|
||||
import { LoginUriApi } from "../api/login-uri.api";
|
||||
|
||||
export class LoginUriData {
|
||||
uri: string;
|
||||
match: UriMatchType = null;
|
||||
|
||||
constructor(data?: LoginUriApi) {
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.uri = data.uri;
|
||||
this.match = data.match;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import { LoginApi } from "../api/login.api";
|
||||
|
||||
import { LoginUriData } from "./login-uri.data";
|
||||
|
||||
export class LoginData {
|
||||
uris: LoginUriData[];
|
||||
username: string;
|
||||
password: string;
|
||||
passwordRevisionDate: string;
|
||||
totp: string;
|
||||
autofillOnPageLoad: boolean;
|
||||
|
||||
constructor(data?: LoginApi) {
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.username = data.username;
|
||||
this.password = data.password;
|
||||
this.passwordRevisionDate = data.passwordRevisionDate;
|
||||
this.totp = data.totp;
|
||||
this.autofillOnPageLoad = data.autofillOnPageLoad;
|
||||
|
||||
if (data.uris) {
|
||||
this.uris = data.uris.map((u) => new LoginUriData(u));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { PasswordHistoryResponse } from "../response/password-history.response";
|
||||
|
||||
export class PasswordHistoryData {
|
||||
password: string;
|
||||
lastUsedDate: string;
|
||||
|
||||
constructor(response?: PasswordHistoryResponse) {
|
||||
if (response == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.password = response.password;
|
||||
this.lastUsedDate = response.lastUsedDate;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { SecureNoteType } from "../../enums/secureNoteType";
|
||||
import { SecureNoteApi } from "../api/secure-note.api";
|
||||
|
||||
export class SecureNoteData {
|
||||
type: SecureNoteType;
|
||||
|
||||
constructor(data?: SecureNoteApi) {
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.type = data.type;
|
||||
}
|
||||
}
|
||||
@@ -5,17 +5,17 @@ import { KdfType } from "../../enums/kdfType";
|
||||
import { UriMatchType } from "../../enums/uriMatchType";
|
||||
import { Utils } from "../../misc/utils";
|
||||
import { DeepJsonify } from "../../types/deep-jsonify";
|
||||
import { CipherData } from "../data/cipher.data";
|
||||
import { CipherData } from "../../vault/models/data/cipher.data";
|
||||
import { FolderData } from "../../vault/models/data/folder.data";
|
||||
import { CipherView } from "../../vault/models/view/cipher.view";
|
||||
import { CollectionData } from "../data/collection.data";
|
||||
import { EncryptedOrganizationKeyData } from "../data/encrypted-organization-key.data";
|
||||
import { EventData } from "../data/event.data";
|
||||
import { FolderData } from "../data/folder.data";
|
||||
import { OrganizationData } from "../data/organization.data";
|
||||
import { PolicyData } from "../data/policy.data";
|
||||
import { ProviderData } from "../data/provider.data";
|
||||
import { SendData } from "../data/send.data";
|
||||
import { ServerConfigData } from "../data/server-config.data";
|
||||
import { CipherView } from "../view/cipher.view";
|
||||
import { CollectionView } from "../view/collection.view";
|
||||
import { SendView } from "../view/send.view";
|
||||
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { Utils } from "../../misc/utils";
|
||||
import { AttachmentData } from "../data/attachment.data";
|
||||
import { AttachmentView } from "../view/attachment.view";
|
||||
|
||||
import Domain from "./domain-base";
|
||||
import { EncString } from "./enc-string";
|
||||
import { SymmetricCryptoKey } from "./symmetric-crypto-key";
|
||||
|
||||
export class Attachment extends Domain {
|
||||
id: string;
|
||||
url: string;
|
||||
size: string;
|
||||
sizeName: string; // Readable size, ex: "4.2 KB" or "1.43 GB"
|
||||
key: EncString;
|
||||
fileName: EncString;
|
||||
|
||||
constructor(obj?: AttachmentData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.size = obj.size;
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
id: null,
|
||||
url: null,
|
||||
sizeName: null,
|
||||
fileName: null,
|
||||
key: null,
|
||||
},
|
||||
["id", "url", "sizeName"]
|
||||
);
|
||||
}
|
||||
|
||||
async decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<AttachmentView> {
|
||||
const view = await this.decryptObj(
|
||||
new AttachmentView(this),
|
||||
{
|
||||
fileName: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
);
|
||||
|
||||
if (this.key != null) {
|
||||
view.key = await this.decryptAttachmentKey(orgId, encKey);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private async decryptAttachmentKey(orgId: string, encKey?: SymmetricCryptoKey) {
|
||||
try {
|
||||
if (encKey == null) {
|
||||
encKey = await this.getKeyForDecryption(orgId);
|
||||
}
|
||||
|
||||
const encryptService = Utils.getContainerService().getEncryptService();
|
||||
const decValue = await encryptService.decryptToBytes(this.key, encKey);
|
||||
return new SymmetricCryptoKey(decValue);
|
||||
} catch (e) {
|
||||
// TODO: error?
|
||||
}
|
||||
}
|
||||
|
||||
private async getKeyForDecryption(orgId: string) {
|
||||
const cryptoService = Utils.getContainerService().getCryptoService();
|
||||
return orgId != null
|
||||
? await cryptoService.getOrgKey(orgId)
|
||||
: await cryptoService.getKeyForUserEncryption();
|
||||
}
|
||||
|
||||
toAttachmentData(): AttachmentData {
|
||||
const a = new AttachmentData();
|
||||
a.size = this.size;
|
||||
this.buildDataModel(
|
||||
this,
|
||||
a,
|
||||
{
|
||||
id: null,
|
||||
url: null,
|
||||
sizeName: null,
|
||||
fileName: null,
|
||||
key: null,
|
||||
},
|
||||
["id", "url", "sizeName"]
|
||||
);
|
||||
return a;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<Attachment>>): Attachment {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const key = EncString.fromJSON(obj.key);
|
||||
const fileName = EncString.fromJSON(obj.fileName);
|
||||
|
||||
return Object.assign(new Attachment(), obj, {
|
||||
key,
|
||||
fileName,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { CardData } from "../data/card.data";
|
||||
import { CardView } from "../view/card.view";
|
||||
|
||||
import Domain from "./domain-base";
|
||||
import { EncString } from "./enc-string";
|
||||
import { SymmetricCryptoKey } from "./symmetric-crypto-key";
|
||||
|
||||
export class Card extends Domain {
|
||||
cardholderName: EncString;
|
||||
brand: EncString;
|
||||
number: EncString;
|
||||
expMonth: EncString;
|
||||
expYear: EncString;
|
||||
code: EncString;
|
||||
|
||||
constructor(obj?: CardData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
cardholderName: null,
|
||||
brand: null,
|
||||
number: null,
|
||||
expMonth: null,
|
||||
expYear: null,
|
||||
code: null,
|
||||
},
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<CardView> {
|
||||
return this.decryptObj(
|
||||
new CardView(),
|
||||
{
|
||||
cardholderName: null,
|
||||
brand: null,
|
||||
number: null,
|
||||
expMonth: null,
|
||||
expYear: null,
|
||||
code: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
);
|
||||
}
|
||||
|
||||
toCardData(): CardData {
|
||||
const c = new CardData();
|
||||
this.buildDataModel(this, c, {
|
||||
cardholderName: null,
|
||||
brand: null,
|
||||
number: null,
|
||||
expMonth: null,
|
||||
expYear: null,
|
||||
code: null,
|
||||
});
|
||||
return c;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<Card>>): Card {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const cardholderName = EncString.fromJSON(obj.cardholderName);
|
||||
const brand = EncString.fromJSON(obj.brand);
|
||||
const number = EncString.fromJSON(obj.number);
|
||||
const expMonth = EncString.fromJSON(obj.expMonth);
|
||||
const expYear = EncString.fromJSON(obj.expYear);
|
||||
const code = EncString.fromJSON(obj.code);
|
||||
return Object.assign(new Card(), obj, {
|
||||
cardholderName,
|
||||
brand,
|
||||
number,
|
||||
expMonth,
|
||||
expYear,
|
||||
code,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,290 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { CipherRepromptType } from "../../enums/cipherRepromptType";
|
||||
import { CipherType } from "../../enums/cipherType";
|
||||
import { Decryptable } from "../../interfaces/decryptable.interface";
|
||||
import { InitializerKey } from "../../services/cryptography/initializer-key";
|
||||
import { CipherData } from "../data/cipher.data";
|
||||
import { LocalData } from "../data/local.data";
|
||||
import { CipherView } from "../view/cipher.view";
|
||||
|
||||
import { Attachment } from "./attachment";
|
||||
import { Card } from "./card";
|
||||
import Domain from "./domain-base";
|
||||
import { EncString } from "./enc-string";
|
||||
import { Field } from "./field";
|
||||
import { Identity } from "./identity";
|
||||
import { Login } from "./login";
|
||||
import { Password } from "./password";
|
||||
import { SecureNote } from "./secure-note";
|
||||
import { SymmetricCryptoKey } from "./symmetric-crypto-key";
|
||||
|
||||
export class Cipher extends Domain implements Decryptable<CipherView> {
|
||||
readonly initializerKey = InitializerKey.Cipher;
|
||||
|
||||
id: string;
|
||||
organizationId: string;
|
||||
folderId: string;
|
||||
name: EncString;
|
||||
notes: EncString;
|
||||
type: CipherType;
|
||||
favorite: boolean;
|
||||
organizationUseTotp: boolean;
|
||||
edit: boolean;
|
||||
viewPassword: boolean;
|
||||
revisionDate: Date;
|
||||
localData: LocalData;
|
||||
login: Login;
|
||||
identity: Identity;
|
||||
card: Card;
|
||||
secureNote: SecureNote;
|
||||
attachments: Attachment[];
|
||||
fields: Field[];
|
||||
passwordHistory: Password[];
|
||||
collectionIds: string[];
|
||||
creationDate: Date;
|
||||
deletedDate: Date;
|
||||
reprompt: CipherRepromptType;
|
||||
|
||||
constructor(obj?: CipherData, localData: LocalData = null) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
id: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: null,
|
||||
notes: null,
|
||||
},
|
||||
["id", "organizationId", "folderId"]
|
||||
);
|
||||
|
||||
this.type = obj.type;
|
||||
this.favorite = obj.favorite;
|
||||
this.organizationUseTotp = obj.organizationUseTotp;
|
||||
this.edit = obj.edit;
|
||||
if (obj.viewPassword != null) {
|
||||
this.viewPassword = obj.viewPassword;
|
||||
} else {
|
||||
this.viewPassword = true; // Default for already synced Ciphers without viewPassword
|
||||
}
|
||||
this.revisionDate = obj.revisionDate != null ? new Date(obj.revisionDate) : null;
|
||||
this.collectionIds = obj.collectionIds;
|
||||
this.localData = localData;
|
||||
this.creationDate = obj.creationDate != null ? new Date(obj.creationDate) : null;
|
||||
this.deletedDate = obj.deletedDate != null ? new Date(obj.deletedDate) : null;
|
||||
this.reprompt = obj.reprompt;
|
||||
|
||||
switch (this.type) {
|
||||
case CipherType.Login:
|
||||
this.login = new Login(obj.login);
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
this.secureNote = new SecureNote(obj.secureNote);
|
||||
break;
|
||||
case CipherType.Card:
|
||||
this.card = new Card(obj.card);
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
this.identity = new Identity(obj.identity);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (obj.attachments != null) {
|
||||
this.attachments = obj.attachments.map((a) => new Attachment(a));
|
||||
} else {
|
||||
this.attachments = null;
|
||||
}
|
||||
|
||||
if (obj.fields != null) {
|
||||
this.fields = obj.fields.map((f) => new Field(f));
|
||||
} else {
|
||||
this.fields = null;
|
||||
}
|
||||
|
||||
if (obj.passwordHistory != null) {
|
||||
this.passwordHistory = obj.passwordHistory.map((ph) => new Password(ph));
|
||||
} else {
|
||||
this.passwordHistory = null;
|
||||
}
|
||||
}
|
||||
|
||||
async decrypt(encKey?: SymmetricCryptoKey): Promise<CipherView> {
|
||||
const model = new CipherView(this);
|
||||
|
||||
await this.decryptObj(
|
||||
model,
|
||||
{
|
||||
name: null,
|
||||
notes: null,
|
||||
},
|
||||
this.organizationId,
|
||||
encKey
|
||||
);
|
||||
|
||||
switch (this.type) {
|
||||
case CipherType.Login:
|
||||
model.login = await this.login.decrypt(this.organizationId, encKey);
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
model.secureNote = await this.secureNote.decrypt(this.organizationId, encKey);
|
||||
break;
|
||||
case CipherType.Card:
|
||||
model.card = await this.card.decrypt(this.organizationId, encKey);
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
model.identity = await this.identity.decrypt(this.organizationId, encKey);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const orgId = this.organizationId;
|
||||
|
||||
if (this.attachments != null && this.attachments.length > 0) {
|
||||
const attachments: any[] = [];
|
||||
await this.attachments.reduce((promise, attachment) => {
|
||||
return promise
|
||||
.then(() => {
|
||||
return attachment.decrypt(orgId, encKey);
|
||||
})
|
||||
.then((decAttachment) => {
|
||||
attachments.push(decAttachment);
|
||||
});
|
||||
}, Promise.resolve());
|
||||
model.attachments = attachments;
|
||||
}
|
||||
|
||||
if (this.fields != null && this.fields.length > 0) {
|
||||
const fields: any[] = [];
|
||||
await this.fields.reduce((promise, field) => {
|
||||
return promise
|
||||
.then(() => {
|
||||
return field.decrypt(orgId, encKey);
|
||||
})
|
||||
.then((decField) => {
|
||||
fields.push(decField);
|
||||
});
|
||||
}, Promise.resolve());
|
||||
model.fields = fields;
|
||||
}
|
||||
|
||||
if (this.passwordHistory != null && this.passwordHistory.length > 0) {
|
||||
const passwordHistory: any[] = [];
|
||||
await this.passwordHistory.reduce((promise, ph) => {
|
||||
return promise
|
||||
.then(() => {
|
||||
return ph.decrypt(orgId, encKey);
|
||||
})
|
||||
.then((decPh) => {
|
||||
passwordHistory.push(decPh);
|
||||
});
|
||||
}, Promise.resolve());
|
||||
model.passwordHistory = passwordHistory;
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
toCipherData(): CipherData {
|
||||
const c = new CipherData();
|
||||
c.id = this.id;
|
||||
c.organizationId = this.organizationId;
|
||||
c.folderId = this.folderId;
|
||||
c.edit = this.edit;
|
||||
c.viewPassword = this.viewPassword;
|
||||
c.organizationUseTotp = this.organizationUseTotp;
|
||||
c.favorite = this.favorite;
|
||||
c.revisionDate = this.revisionDate != null ? this.revisionDate.toISOString() : null;
|
||||
c.type = this.type;
|
||||
c.collectionIds = this.collectionIds;
|
||||
c.creationDate = this.creationDate != null ? this.creationDate.toISOString() : null;
|
||||
c.deletedDate = this.deletedDate != null ? this.deletedDate.toISOString() : null;
|
||||
c.reprompt = this.reprompt;
|
||||
|
||||
this.buildDataModel(this, c, {
|
||||
name: null,
|
||||
notes: null,
|
||||
});
|
||||
|
||||
switch (c.type) {
|
||||
case CipherType.Login:
|
||||
c.login = this.login.toLoginData();
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
c.secureNote = this.secureNote.toSecureNoteData();
|
||||
break;
|
||||
case CipherType.Card:
|
||||
c.card = this.card.toCardData();
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
c.identity = this.identity.toIdentityData();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.fields != null) {
|
||||
c.fields = this.fields.map((f) => f.toFieldData());
|
||||
}
|
||||
if (this.attachments != null) {
|
||||
c.attachments = this.attachments.map((a) => a.toAttachmentData());
|
||||
}
|
||||
if (this.passwordHistory != null) {
|
||||
c.passwordHistory = this.passwordHistory.map((ph) => ph.toPasswordHistoryData());
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Jsonify<Cipher>) {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const domain = new Cipher();
|
||||
const name = EncString.fromJSON(obj.name);
|
||||
const notes = EncString.fromJSON(obj.notes);
|
||||
const revisionDate = obj.revisionDate == null ? null : new Date(obj.revisionDate);
|
||||
const deletedDate = obj.deletedDate == null ? null : new Date(obj.deletedDate);
|
||||
const attachments = obj.attachments?.map((a: any) => Attachment.fromJSON(a));
|
||||
const fields = obj.fields?.map((f: any) => Field.fromJSON(f));
|
||||
const passwordHistory = obj.passwordHistory?.map((ph: any) => Password.fromJSON(ph));
|
||||
|
||||
Object.assign(domain, obj, {
|
||||
name,
|
||||
notes,
|
||||
revisionDate,
|
||||
deletedDate,
|
||||
attachments,
|
||||
fields,
|
||||
passwordHistory,
|
||||
});
|
||||
|
||||
switch (obj.type) {
|
||||
case CipherType.Card:
|
||||
domain.card = Card.fromJSON(obj.card);
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
domain.identity = Identity.fromJSON(obj.identity);
|
||||
break;
|
||||
case CipherType.Login:
|
||||
domain.login = Login.fromJSON(obj.login);
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
domain.secureNote = SecureNote.fromJSON(obj.secureNote);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return domain;
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { FieldType } from "../../enums/fieldType";
|
||||
import { LinkedIdType } from "../../enums/linkedIdType";
|
||||
import { FieldData } from "../data/field.data";
|
||||
import { FieldView } from "../view/field.view";
|
||||
|
||||
import Domain from "./domain-base";
|
||||
import { EncString } from "./enc-string";
|
||||
import { SymmetricCryptoKey } from "./symmetric-crypto-key";
|
||||
|
||||
export class Field extends Domain {
|
||||
name: EncString;
|
||||
value: EncString;
|
||||
type: FieldType;
|
||||
linkedId: LinkedIdType;
|
||||
|
||||
constructor(obj?: FieldData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.type = obj.type;
|
||||
this.linkedId = obj.linkedId;
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
name: null,
|
||||
value: null,
|
||||
},
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<FieldView> {
|
||||
return this.decryptObj(
|
||||
new FieldView(this),
|
||||
{
|
||||
name: null,
|
||||
value: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
);
|
||||
}
|
||||
|
||||
toFieldData(): FieldData {
|
||||
const f = new FieldData();
|
||||
this.buildDataModel(
|
||||
this,
|
||||
f,
|
||||
{
|
||||
name: null,
|
||||
value: null,
|
||||
type: null,
|
||||
linkedId: null,
|
||||
},
|
||||
["type", "linkedId"]
|
||||
);
|
||||
return f;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<Field>>): Field {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const name = EncString.fromJSON(obj.name);
|
||||
const value = EncString.fromJSON(obj.value);
|
||||
|
||||
return Object.assign(new Field(), obj, {
|
||||
name,
|
||||
value,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { FolderData } from "../data/folder.data";
|
||||
import { FolderView } from "../view/folder.view";
|
||||
|
||||
import Domain from "./domain-base";
|
||||
import { EncString } from "./enc-string";
|
||||
|
||||
export class Folder extends Domain {
|
||||
id: string;
|
||||
name: EncString;
|
||||
revisionDate: Date;
|
||||
|
||||
constructor(obj?: FolderData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
id: null,
|
||||
name: null,
|
||||
},
|
||||
["id"]
|
||||
);
|
||||
|
||||
this.revisionDate = obj.revisionDate != null ? new Date(obj.revisionDate) : null;
|
||||
}
|
||||
|
||||
decrypt(): Promise<FolderView> {
|
||||
return this.decryptObj(
|
||||
new FolderView(this),
|
||||
{
|
||||
name: null,
|
||||
},
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
static fromJSON(obj: Jsonify<Folder>) {
|
||||
const revisionDate = obj.revisionDate == null ? null : new Date(obj.revisionDate);
|
||||
return Object.assign(new Folder(), obj, { name: EncString.fromJSON(obj.name), revisionDate });
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { IdentityData } from "../data/identity.data";
|
||||
import { IdentityView } from "../view/identity.view";
|
||||
|
||||
import Domain from "./domain-base";
|
||||
import { EncString } from "./enc-string";
|
||||
import { SymmetricCryptoKey } from "./symmetric-crypto-key";
|
||||
|
||||
export class Identity extends Domain {
|
||||
title: EncString;
|
||||
firstName: EncString;
|
||||
middleName: EncString;
|
||||
lastName: EncString;
|
||||
address1: EncString;
|
||||
address2: EncString;
|
||||
address3: EncString;
|
||||
city: EncString;
|
||||
state: EncString;
|
||||
postalCode: EncString;
|
||||
country: EncString;
|
||||
company: EncString;
|
||||
email: EncString;
|
||||
phone: EncString;
|
||||
ssn: EncString;
|
||||
username: EncString;
|
||||
passportNumber: EncString;
|
||||
licenseNumber: EncString;
|
||||
|
||||
constructor(obj?: IdentityData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
title: null,
|
||||
firstName: null,
|
||||
middleName: null,
|
||||
lastName: null,
|
||||
address1: null,
|
||||
address2: null,
|
||||
address3: null,
|
||||
city: null,
|
||||
state: null,
|
||||
postalCode: null,
|
||||
country: null,
|
||||
company: null,
|
||||
email: null,
|
||||
phone: null,
|
||||
ssn: null,
|
||||
username: null,
|
||||
passportNumber: null,
|
||||
licenseNumber: null,
|
||||
},
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<IdentityView> {
|
||||
return this.decryptObj(
|
||||
new IdentityView(),
|
||||
{
|
||||
title: null,
|
||||
firstName: null,
|
||||
middleName: null,
|
||||
lastName: null,
|
||||
address1: null,
|
||||
address2: null,
|
||||
address3: null,
|
||||
city: null,
|
||||
state: null,
|
||||
postalCode: null,
|
||||
country: null,
|
||||
company: null,
|
||||
email: null,
|
||||
phone: null,
|
||||
ssn: null,
|
||||
username: null,
|
||||
passportNumber: null,
|
||||
licenseNumber: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
);
|
||||
}
|
||||
|
||||
toIdentityData(): IdentityData {
|
||||
const i = new IdentityData();
|
||||
this.buildDataModel(this, i, {
|
||||
title: null,
|
||||
firstName: null,
|
||||
middleName: null,
|
||||
lastName: null,
|
||||
address1: null,
|
||||
address2: null,
|
||||
address3: null,
|
||||
city: null,
|
||||
state: null,
|
||||
postalCode: null,
|
||||
country: null,
|
||||
company: null,
|
||||
email: null,
|
||||
phone: null,
|
||||
ssn: null,
|
||||
username: null,
|
||||
passportNumber: null,
|
||||
licenseNumber: null,
|
||||
});
|
||||
return i;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Jsonify<Identity>): Identity {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const title = EncString.fromJSON(obj.title);
|
||||
const firstName = EncString.fromJSON(obj.firstName);
|
||||
const middleName = EncString.fromJSON(obj.middleName);
|
||||
const lastName = EncString.fromJSON(obj.lastName);
|
||||
const address1 = EncString.fromJSON(obj.address1);
|
||||
const address2 = EncString.fromJSON(obj.address2);
|
||||
const address3 = EncString.fromJSON(obj.address3);
|
||||
const city = EncString.fromJSON(obj.city);
|
||||
const state = EncString.fromJSON(obj.state);
|
||||
const postalCode = EncString.fromJSON(obj.postalCode);
|
||||
const country = EncString.fromJSON(obj.country);
|
||||
const company = EncString.fromJSON(obj.company);
|
||||
const email = EncString.fromJSON(obj.email);
|
||||
const phone = EncString.fromJSON(obj.phone);
|
||||
const ssn = EncString.fromJSON(obj.ssn);
|
||||
const username = EncString.fromJSON(obj.username);
|
||||
const passportNumber = EncString.fromJSON(obj.passportNumber);
|
||||
const licenseNumber = EncString.fromJSON(obj.licenseNumber);
|
||||
|
||||
return Object.assign(new Identity(), obj, {
|
||||
title,
|
||||
firstName,
|
||||
middleName,
|
||||
lastName,
|
||||
address1,
|
||||
address2,
|
||||
address3,
|
||||
city,
|
||||
state,
|
||||
postalCode,
|
||||
country,
|
||||
company,
|
||||
email,
|
||||
phone,
|
||||
ssn,
|
||||
username,
|
||||
passportNumber,
|
||||
licenseNumber,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CipherView } from "../view/cipher.view";
|
||||
import { CipherView } from "../../vault/models/view/cipher.view";
|
||||
import { FolderView } from "../../vault/models/view/folder.view";
|
||||
import { CollectionView } from "../view/collection.view";
|
||||
import { FolderView } from "../view/folder.view";
|
||||
|
||||
export class ImportResult {
|
||||
success = false;
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { UriMatchType } from "../../enums/uriMatchType";
|
||||
import { LoginUriData } from "../data/login-uri.data";
|
||||
import { LoginUriView } from "../view/login-uri.view";
|
||||
|
||||
import Domain from "./domain-base";
|
||||
import { EncString } from "./enc-string";
|
||||
import { SymmetricCryptoKey } from "./symmetric-crypto-key";
|
||||
|
||||
export class LoginUri extends Domain {
|
||||
uri: EncString;
|
||||
match: UriMatchType;
|
||||
|
||||
constructor(obj?: LoginUriData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.match = obj.match;
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
uri: null,
|
||||
},
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<LoginUriView> {
|
||||
return this.decryptObj(
|
||||
new LoginUriView(this),
|
||||
{
|
||||
uri: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
);
|
||||
}
|
||||
|
||||
toLoginUriData(): LoginUriData {
|
||||
const u = new LoginUriData();
|
||||
this.buildDataModel(
|
||||
this,
|
||||
u,
|
||||
{
|
||||
uri: null,
|
||||
match: null,
|
||||
},
|
||||
["match"]
|
||||
);
|
||||
return u;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Jsonify<LoginUri>): LoginUri {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const uri = EncString.fromJSON(obj.uri);
|
||||
return Object.assign(new LoginUri(), obj, {
|
||||
uri,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { LoginData } from "../data/login.data";
|
||||
import { LoginView } from "../view/login.view";
|
||||
|
||||
import Domain from "./domain-base";
|
||||
import { EncString } from "./enc-string";
|
||||
import { LoginUri } from "./login-uri";
|
||||
import { SymmetricCryptoKey } from "./symmetric-crypto-key";
|
||||
|
||||
export class Login extends Domain {
|
||||
uris: LoginUri[];
|
||||
username: EncString;
|
||||
password: EncString;
|
||||
passwordRevisionDate?: Date;
|
||||
totp: EncString;
|
||||
autofillOnPageLoad: boolean;
|
||||
|
||||
constructor(obj?: LoginData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.passwordRevisionDate =
|
||||
obj.passwordRevisionDate != null ? new Date(obj.passwordRevisionDate) : null;
|
||||
this.autofillOnPageLoad = obj.autofillOnPageLoad;
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
username: null,
|
||||
password: null,
|
||||
totp: null,
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
if (obj.uris) {
|
||||
this.uris = [];
|
||||
obj.uris.forEach((u) => {
|
||||
this.uris.push(new LoginUri(u));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<LoginView> {
|
||||
const view = await this.decryptObj(
|
||||
new LoginView(this),
|
||||
{
|
||||
username: null,
|
||||
password: null,
|
||||
totp: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
);
|
||||
|
||||
if (this.uris != null) {
|
||||
view.uris = [];
|
||||
for (let i = 0; i < this.uris.length; i++) {
|
||||
const uri = await this.uris[i].decrypt(orgId, encKey);
|
||||
view.uris.push(uri);
|
||||
}
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
toLoginData(): LoginData {
|
||||
const l = new LoginData();
|
||||
l.passwordRevisionDate =
|
||||
this.passwordRevisionDate != null ? this.passwordRevisionDate.toISOString() : null;
|
||||
l.autofillOnPageLoad = this.autofillOnPageLoad;
|
||||
this.buildDataModel(this, l, {
|
||||
username: null,
|
||||
password: null,
|
||||
totp: null,
|
||||
});
|
||||
|
||||
if (this.uris != null && this.uris.length > 0) {
|
||||
l.uris = [];
|
||||
this.uris.forEach((u) => {
|
||||
l.uris.push(u.toLoginUriData());
|
||||
});
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<Login>>): Login {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const username = EncString.fromJSON(obj.username);
|
||||
const password = EncString.fromJSON(obj.password);
|
||||
const totp = EncString.fromJSON(obj.totp);
|
||||
const passwordRevisionDate =
|
||||
obj.passwordRevisionDate == null ? null : new Date(obj.passwordRevisionDate);
|
||||
const uris = obj.uris?.map((uri: any) => LoginUri.fromJSON(uri));
|
||||
|
||||
return Object.assign(new Login(), obj, {
|
||||
username,
|
||||
password,
|
||||
totp,
|
||||
passwordRevisionDate: passwordRevisionDate,
|
||||
uris: uris,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { PasswordHistoryData } from "../data/password-history.data";
|
||||
import { PasswordHistoryView } from "../view/password-history.view";
|
||||
|
||||
import Domain from "./domain-base";
|
||||
import { EncString } from "./enc-string";
|
||||
import { SymmetricCryptoKey } from "./symmetric-crypto-key";
|
||||
|
||||
export class Password extends Domain {
|
||||
password: EncString;
|
||||
lastUsedDate: Date;
|
||||
|
||||
constructor(obj?: PasswordHistoryData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.buildDomainModel(this, obj, {
|
||||
password: null,
|
||||
});
|
||||
this.lastUsedDate = new Date(obj.lastUsedDate);
|
||||
}
|
||||
|
||||
decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<PasswordHistoryView> {
|
||||
return this.decryptObj(
|
||||
new PasswordHistoryView(this),
|
||||
{
|
||||
password: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
);
|
||||
}
|
||||
|
||||
toPasswordHistoryData(): PasswordHistoryData {
|
||||
const ph = new PasswordHistoryData();
|
||||
ph.lastUsedDate = this.lastUsedDate.toISOString();
|
||||
this.buildDataModel(this, ph, {
|
||||
password: null,
|
||||
});
|
||||
return ph;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<Password>>): Password {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const password = EncString.fromJSON(obj.password);
|
||||
const lastUsedDate = obj.lastUsedDate == null ? null : new Date(obj.lastUsedDate);
|
||||
|
||||
return Object.assign(new Password(), obj, {
|
||||
password,
|
||||
lastUsedDate,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { SecureNoteType } from "../../enums/secureNoteType";
|
||||
import { SecureNoteData } from "../data/secure-note.data";
|
||||
import { SecureNoteView } from "../view/secure-note.view";
|
||||
|
||||
import Domain from "./domain-base";
|
||||
import { SymmetricCryptoKey } from "./symmetric-crypto-key";
|
||||
|
||||
export class SecureNote extends Domain {
|
||||
type: SecureNoteType;
|
||||
|
||||
constructor(obj?: SecureNoteData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.type = obj.type;
|
||||
}
|
||||
|
||||
decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise<SecureNoteView> {
|
||||
return Promise.resolve(new SecureNoteView(this));
|
||||
}
|
||||
|
||||
toSecureNoteData(): SecureNoteData {
|
||||
const n = new SecureNoteData();
|
||||
n.type = this.type;
|
||||
return n;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Jsonify<SecureNote>): SecureNote {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Object.assign(new SecureNote(), obj);
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
import { CipherView } from "../view/cipher.view";
|
||||
|
||||
const CacheTTL = 3000;
|
||||
|
||||
export class SortedCiphersCache {
|
||||
private readonly sortedCiphersByUrl: Map<string, Ciphers> = new Map<string, Ciphers>();
|
||||
private readonly timeouts: Map<string, any> = new Map<string, any>();
|
||||
|
||||
constructor(private readonly comparator: (a: CipherView, b: CipherView) => number) {}
|
||||
|
||||
isCached(url: string) {
|
||||
return this.sortedCiphersByUrl.has(url);
|
||||
}
|
||||
|
||||
addCiphers(url: string, ciphers: CipherView[]) {
|
||||
ciphers.sort(this.comparator);
|
||||
this.sortedCiphersByUrl.set(url, new Ciphers(ciphers));
|
||||
this.resetTimer(url);
|
||||
}
|
||||
|
||||
getLastUsed(url: string) {
|
||||
this.resetTimer(url);
|
||||
return this.isCached(url) ? this.sortedCiphersByUrl.get(url).getLastUsed() : null;
|
||||
}
|
||||
|
||||
getLastLaunched(url: string) {
|
||||
return this.isCached(url) ? this.sortedCiphersByUrl.get(url).getLastLaunched() : null;
|
||||
}
|
||||
|
||||
getNext(url: string) {
|
||||
this.resetTimer(url);
|
||||
return this.isCached(url) ? this.sortedCiphersByUrl.get(url).getNext() : null;
|
||||
}
|
||||
|
||||
updateLastUsedIndex(url: string) {
|
||||
if (this.isCached(url)) {
|
||||
this.sortedCiphersByUrl.get(url).updateLastUsedIndex();
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.sortedCiphersByUrl.clear();
|
||||
this.timeouts.clear();
|
||||
}
|
||||
|
||||
private resetTimer(url: string) {
|
||||
clearTimeout(this.timeouts.get(url));
|
||||
this.timeouts.set(
|
||||
url,
|
||||
setTimeout(() => {
|
||||
this.sortedCiphersByUrl.delete(url);
|
||||
this.timeouts.delete(url);
|
||||
}, CacheTTL)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Ciphers {
|
||||
lastUsedIndex = -1;
|
||||
|
||||
constructor(private readonly ciphers: CipherView[]) {}
|
||||
|
||||
getLastUsed() {
|
||||
this.lastUsedIndex = Math.max(this.lastUsedIndex, 0);
|
||||
return this.ciphers[this.lastUsedIndex];
|
||||
}
|
||||
|
||||
getLastLaunched() {
|
||||
const usedCiphers = this.ciphers.filter((cipher) => cipher.localData?.lastLaunched);
|
||||
const sortedCiphers = usedCiphers.sort(
|
||||
(x, y) => y.localData.lastLaunched.valueOf() - x.localData.lastLaunched.valueOf()
|
||||
);
|
||||
return sortedCiphers[0];
|
||||
}
|
||||
|
||||
getNextIndex() {
|
||||
return (this.lastUsedIndex + 1) % this.ciphers.length;
|
||||
}
|
||||
|
||||
getNext() {
|
||||
return this.ciphers[this.getNextIndex()];
|
||||
}
|
||||
|
||||
updateLastUsedIndex() {
|
||||
this.lastUsedIndex = this.getNextIndex();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Card as CardDomain } from "../domain/card";
|
||||
import { Card as CardDomain } from "../../vault/models/domain/card";
|
||||
import { CardView } from "../../vault/models/view/card.view";
|
||||
import { EncString } from "../domain/enc-string";
|
||||
import { CardView } from "../view/card.view";
|
||||
|
||||
export class CardExport {
|
||||
static template(): CardExport {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Cipher as CipherDomain } from "../domain/cipher";
|
||||
import { CipherView } from "../view/cipher.view";
|
||||
import { Cipher as CipherDomain } from "../../vault/models/domain/cipher";
|
||||
import { CipherView } from "../../vault/models/view/cipher.view";
|
||||
|
||||
import { CipherExport } from "./cipher.export";
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { CipherRepromptType } from "../../enums/cipherRepromptType";
|
||||
import { CipherType } from "../../enums/cipherType";
|
||||
import { Cipher as CipherDomain } from "../domain/cipher";
|
||||
import { CipherRepromptType } from "../../vault/enums/cipher-reprompt-type";
|
||||
import { CipherType } from "../../vault/enums/cipher-type";
|
||||
import { Cipher as CipherDomain } from "../../vault/models/domain/cipher";
|
||||
import { CipherView } from "../../vault/models/view/cipher.view";
|
||||
import { EncString } from "../domain/enc-string";
|
||||
import { CipherView } from "../view/cipher.view";
|
||||
|
||||
import { CardExport } from "./card.export";
|
||||
import { FieldExport } from "./field.export";
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { FieldType } from "../../enums/fieldType";
|
||||
import { LinkedIdType } from "../../enums/linkedIdType";
|
||||
import { Field as FieldDomain } from "../../vault/models/domain/field";
|
||||
import { FieldView } from "../../vault/models/view/field.view";
|
||||
import { EncString } from "../domain/enc-string";
|
||||
import { Field as FieldDomain } from "../domain/field";
|
||||
import { FieldView } from "../view/field.view";
|
||||
|
||||
export class FieldExport {
|
||||
static template(): FieldExport {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Folder as FolderDomain } from "../domain/folder";
|
||||
import { FolderView } from "../view/folder.view";
|
||||
import { Folder as FolderDomain } from "../../vault/models/domain/folder";
|
||||
import { FolderView } from "../../vault/models/view/folder.view";
|
||||
|
||||
import { FolderExport } from "./folder.export";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Folder as FolderDomain } from "../../vault/models/domain/folder";
|
||||
import { FolderView } from "../../vault/models/view/folder.view";
|
||||
import { EncString } from "../domain/enc-string";
|
||||
import { Folder as FolderDomain } from "../domain/folder";
|
||||
import { FolderView } from "../view/folder.view";
|
||||
|
||||
export class FolderExport {
|
||||
static template(): FolderExport {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Identity as IdentityDomain } from "../../vault/models/domain/identity";
|
||||
import { IdentityView } from "../../vault/models/view/identity.view";
|
||||
import { EncString } from "../domain/enc-string";
|
||||
import { Identity as IdentityDomain } from "../domain/identity";
|
||||
import { IdentityView } from "../view/identity.view";
|
||||
|
||||
export class IdentityExport {
|
||||
static template(): IdentityExport {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { UriMatchType } from "../../enums/uriMatchType";
|
||||
import { LoginUri as LoginUriDomain } from "../../vault/models/domain/login-uri";
|
||||
import { LoginUriView } from "../../vault/models/view/login-uri.view";
|
||||
import { EncString } from "../domain/enc-string";
|
||||
import { LoginUri as LoginUriDomain } from "../domain/login-uri";
|
||||
import { LoginUriView } from "../view/login-uri.view";
|
||||
|
||||
export class LoginUriExport {
|
||||
static template(): LoginUriExport {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Login as LoginDomain } from "../../vault/models/domain/login";
|
||||
import { LoginView } from "../../vault/models/view/login.view";
|
||||
import { EncString } from "../domain/enc-string";
|
||||
import { Login as LoginDomain } from "../domain/login";
|
||||
import { LoginView } from "../view/login.view";
|
||||
|
||||
import { LoginUriExport } from "./login-uri.export";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SecureNoteType } from "../../enums/secureNoteType";
|
||||
import { SecureNote as SecureNoteDomain } from "../domain/secure-note";
|
||||
import { SecureNoteView } from "../view/secure-note.view";
|
||||
import { SecureNote as SecureNoteDomain } from "../../vault/models/domain/secure-note";
|
||||
import { SecureNoteView } from "../../vault/models/view/secure-note.view";
|
||||
|
||||
export class SecureNoteExport {
|
||||
static template(): SecureNoteExport {
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
export class AttachmentRequest {
|
||||
fileName: string;
|
||||
key: string;
|
||||
fileSize: number;
|
||||
adminRequest: boolean;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
export class CipherBulkDeleteRequest {
|
||||
ids: string[];
|
||||
organizationId: string;
|
||||
|
||||
constructor(ids: string[], organizationId?: string) {
|
||||
this.ids = ids == null ? [] : ids;
|
||||
this.organizationId = organizationId;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
export class CipherBulkMoveRequest {
|
||||
ids: string[];
|
||||
folderId: string;
|
||||
|
||||
constructor(ids: string[], folderId: string) {
|
||||
this.ids = ids == null ? [] : ids;
|
||||
this.folderId = folderId;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
export class CipherBulkRestoreRequest {
|
||||
ids: string[];
|
||||
|
||||
constructor(ids: string[]) {
|
||||
this.ids = ids == null ? [] : ids;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { Cipher } from "../domain/cipher";
|
||||
|
||||
import { CipherWithIdRequest } from "./cipher-with-id.request";
|
||||
|
||||
export class CipherBulkShareRequest {
|
||||
ciphers: CipherWithIdRequest[];
|
||||
collectionIds: string[];
|
||||
|
||||
constructor(ciphers: Cipher[], collectionIds: string[]) {
|
||||
if (ciphers != null) {
|
||||
this.ciphers = [];
|
||||
ciphers.forEach((c) => {
|
||||
this.ciphers.push(new CipherWithIdRequest(c));
|
||||
});
|
||||
}
|
||||
this.collectionIds = collectionIds;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
export class CipherCollectionsRequest {
|
||||
collectionIds: string[];
|
||||
|
||||
constructor(collectionIds: string[]) {
|
||||
this.collectionIds = collectionIds == null ? [] : collectionIds;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Cipher } from "../domain/cipher";
|
||||
|
||||
import { CipherRequest } from "./cipher.request";
|
||||
|
||||
export class CipherCreateRequest {
|
||||
cipher: CipherRequest;
|
||||
collectionIds: string[];
|
||||
|
||||
constructor(cipher: Cipher) {
|
||||
this.cipher = new CipherRequest(cipher);
|
||||
this.collectionIds = cipher.collectionIds;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { Cipher } from "../domain/cipher";
|
||||
|
||||
export class CipherPartialRequest {
|
||||
folderId: string;
|
||||
favorite: boolean;
|
||||
|
||||
constructor(cipher: Cipher) {
|
||||
this.folderId = cipher.folderId;
|
||||
this.favorite = cipher.favorite;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Cipher } from "../domain/cipher";
|
||||
|
||||
import { CipherRequest } from "./cipher.request";
|
||||
|
||||
export class CipherShareRequest {
|
||||
cipher: CipherRequest;
|
||||
collectionIds: string[];
|
||||
|
||||
constructor(cipher: Cipher) {
|
||||
this.cipher = new CipherRequest(cipher);
|
||||
this.collectionIds = cipher.collectionIds;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { Cipher } from "../domain/cipher";
|
||||
|
||||
import { CipherRequest } from "./cipher.request";
|
||||
|
||||
export class CipherWithIdRequest extends CipherRequest {
|
||||
id: string;
|
||||
|
||||
constructor(cipher: Cipher) {
|
||||
super(cipher);
|
||||
this.id = cipher.id;
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
import { CipherRepromptType } from "../../enums/cipherRepromptType";
|
||||
import { CipherType } from "../../enums/cipherType";
|
||||
import { CardApi } from "../api/card.api";
|
||||
import { FieldApi } from "../api/field.api";
|
||||
import { IdentityApi } from "../api/identity.api";
|
||||
import { LoginUriApi } from "../api/login-uri.api";
|
||||
import { LoginApi } from "../api/login.api";
|
||||
import { SecureNoteApi } from "../api/secure-note.api";
|
||||
import { Cipher } from "../domain/cipher";
|
||||
|
||||
import { AttachmentRequest } from "./attachment.request";
|
||||
import { PasswordHistoryRequest } from "./password-history.request";
|
||||
|
||||
export class CipherRequest {
|
||||
type: CipherType;
|
||||
folderId: string;
|
||||
organizationId: string;
|
||||
name: string;
|
||||
notes: string;
|
||||
favorite: boolean;
|
||||
login: LoginApi;
|
||||
secureNote: SecureNoteApi;
|
||||
card: CardApi;
|
||||
identity: IdentityApi;
|
||||
fields: FieldApi[];
|
||||
passwordHistory: PasswordHistoryRequest[];
|
||||
// Deprecated, remove at some point and rename attachments2 to attachments
|
||||
attachments: { [id: string]: string };
|
||||
attachments2: { [id: string]: AttachmentRequest };
|
||||
lastKnownRevisionDate: Date;
|
||||
reprompt: CipherRepromptType;
|
||||
|
||||
constructor(cipher: Cipher) {
|
||||
this.type = cipher.type;
|
||||
this.folderId = cipher.folderId;
|
||||
this.organizationId = cipher.organizationId;
|
||||
this.name = cipher.name ? cipher.name.encryptedString : null;
|
||||
this.notes = cipher.notes ? cipher.notes.encryptedString : null;
|
||||
this.favorite = cipher.favorite;
|
||||
this.lastKnownRevisionDate = cipher.revisionDate;
|
||||
this.reprompt = cipher.reprompt;
|
||||
|
||||
switch (this.type) {
|
||||
case CipherType.Login:
|
||||
this.login = new LoginApi();
|
||||
this.login.uris = null;
|
||||
this.login.username = cipher.login.username ? cipher.login.username.encryptedString : null;
|
||||
this.login.password = cipher.login.password ? cipher.login.password.encryptedString : null;
|
||||
this.login.passwordRevisionDate =
|
||||
cipher.login.passwordRevisionDate != null
|
||||
? cipher.login.passwordRevisionDate.toISOString()
|
||||
: null;
|
||||
this.login.totp = cipher.login.totp ? cipher.login.totp.encryptedString : null;
|
||||
this.login.autofillOnPageLoad = cipher.login.autofillOnPageLoad;
|
||||
|
||||
if (cipher.login.uris != null) {
|
||||
this.login.uris = cipher.login.uris.map((u) => {
|
||||
const uri = new LoginUriApi();
|
||||
uri.uri = u.uri != null ? u.uri.encryptedString : null;
|
||||
uri.match = u.match != null ? u.match : null;
|
||||
return uri;
|
||||
});
|
||||
}
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
this.secureNote = new SecureNoteApi();
|
||||
this.secureNote.type = cipher.secureNote.type;
|
||||
break;
|
||||
case CipherType.Card:
|
||||
this.card = new CardApi();
|
||||
this.card.cardholderName =
|
||||
cipher.card.cardholderName != null ? cipher.card.cardholderName.encryptedString : null;
|
||||
this.card.brand = cipher.card.brand != null ? cipher.card.brand.encryptedString : null;
|
||||
this.card.number = cipher.card.number != null ? cipher.card.number.encryptedString : null;
|
||||
this.card.expMonth =
|
||||
cipher.card.expMonth != null ? cipher.card.expMonth.encryptedString : null;
|
||||
this.card.expYear =
|
||||
cipher.card.expYear != null ? cipher.card.expYear.encryptedString : null;
|
||||
this.card.code = cipher.card.code != null ? cipher.card.code.encryptedString : null;
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
this.identity = new IdentityApi();
|
||||
this.identity.title =
|
||||
cipher.identity.title != null ? cipher.identity.title.encryptedString : null;
|
||||
this.identity.firstName =
|
||||
cipher.identity.firstName != null ? cipher.identity.firstName.encryptedString : null;
|
||||
this.identity.middleName =
|
||||
cipher.identity.middleName != null ? cipher.identity.middleName.encryptedString : null;
|
||||
this.identity.lastName =
|
||||
cipher.identity.lastName != null ? cipher.identity.lastName.encryptedString : null;
|
||||
this.identity.address1 =
|
||||
cipher.identity.address1 != null ? cipher.identity.address1.encryptedString : null;
|
||||
this.identity.address2 =
|
||||
cipher.identity.address2 != null ? cipher.identity.address2.encryptedString : null;
|
||||
this.identity.address3 =
|
||||
cipher.identity.address3 != null ? cipher.identity.address3.encryptedString : null;
|
||||
this.identity.city =
|
||||
cipher.identity.city != null ? cipher.identity.city.encryptedString : null;
|
||||
this.identity.state =
|
||||
cipher.identity.state != null ? cipher.identity.state.encryptedString : null;
|
||||
this.identity.postalCode =
|
||||
cipher.identity.postalCode != null ? cipher.identity.postalCode.encryptedString : null;
|
||||
this.identity.country =
|
||||
cipher.identity.country != null ? cipher.identity.country.encryptedString : null;
|
||||
this.identity.company =
|
||||
cipher.identity.company != null ? cipher.identity.company.encryptedString : null;
|
||||
this.identity.email =
|
||||
cipher.identity.email != null ? cipher.identity.email.encryptedString : null;
|
||||
this.identity.phone =
|
||||
cipher.identity.phone != null ? cipher.identity.phone.encryptedString : null;
|
||||
this.identity.ssn =
|
||||
cipher.identity.ssn != null ? cipher.identity.ssn.encryptedString : null;
|
||||
this.identity.username =
|
||||
cipher.identity.username != null ? cipher.identity.username.encryptedString : null;
|
||||
this.identity.passportNumber =
|
||||
cipher.identity.passportNumber != null
|
||||
? cipher.identity.passportNumber.encryptedString
|
||||
: null;
|
||||
this.identity.licenseNumber =
|
||||
cipher.identity.licenseNumber != null
|
||||
? cipher.identity.licenseNumber.encryptedString
|
||||
: null;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cipher.fields != null) {
|
||||
this.fields = cipher.fields.map((f) => {
|
||||
const field = new FieldApi();
|
||||
field.type = f.type;
|
||||
field.name = f.name ? f.name.encryptedString : null;
|
||||
field.value = f.value ? f.value.encryptedString : null;
|
||||
field.linkedId = f.linkedId;
|
||||
return field;
|
||||
});
|
||||
}
|
||||
|
||||
if (cipher.passwordHistory != null) {
|
||||
this.passwordHistory = [];
|
||||
cipher.passwordHistory.forEach((ph) => {
|
||||
this.passwordHistory.push({
|
||||
lastUsedDate: ph.lastUsedDate,
|
||||
password: ph.password ? ph.password.encryptedString : null,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (cipher.attachments != null) {
|
||||
this.attachments = {};
|
||||
this.attachments2 = {};
|
||||
cipher.attachments.forEach((attachment) => {
|
||||
const fileName = attachment.fileName ? attachment.fileName.encryptedString : null;
|
||||
this.attachments[attachment.id] = fileName;
|
||||
const attachmentRequest = new AttachmentRequest();
|
||||
attachmentRequest.fileName = fileName;
|
||||
if (attachment.key != null) {
|
||||
attachmentRequest.key = attachment.key.encryptedString;
|
||||
}
|
||||
this.attachments2[attachment.id] = attachmentRequest;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { Folder } from "../domain/folder";
|
||||
|
||||
import { FolderRequest } from "./folder.request";
|
||||
|
||||
export class FolderWithIdRequest extends FolderRequest {
|
||||
id: string;
|
||||
|
||||
constructor(folder: Folder) {
|
||||
super(folder);
|
||||
this.id = folder.id;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Folder } from "../domain/folder";
|
||||
|
||||
export class FolderRequest {
|
||||
name: string;
|
||||
|
||||
constructor(folder: Folder) {
|
||||
this.name = folder.name ? folder.name.encryptedString : null;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { CipherRequest } from "./cipher.request";
|
||||
import { FolderRequest } from "./folder.request";
|
||||
import { CipherRequest } from "../../vault/models/request/cipher.request";
|
||||
import { FolderRequest } from "../../vault/models/request/folder.request";
|
||||
|
||||
import { KvpRequest } from "./kvp.request";
|
||||
|
||||
export class ImportCiphersRequest {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { CipherRequest } from "./cipher.request";
|
||||
import { CipherRequest } from "../../vault/models/request/cipher.request";
|
||||
|
||||
import { CollectionRequest } from "./collection.request";
|
||||
import { KvpRequest } from "./kvp.request";
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
export class PasswordHistoryRequest {
|
||||
password: string;
|
||||
lastUsedDate: Date;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { CipherWithIdRequest } from "./cipher-with-id.request";
|
||||
import { FolderWithIdRequest } from "./folder-with-id.request";
|
||||
import { CipherWithIdRequest } from "../../vault/models/request/cipher-with-id.request";
|
||||
import { FolderWithIdRequest } from "../../vault/models/request/folder-with-id.request";
|
||||
|
||||
import { SendWithIdRequest } from "./send-with-id.request";
|
||||
|
||||
export class UpdateKeyRequest {
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { FileUploadType } from "../../enums/fileUploadType";
|
||||
|
||||
import { BaseResponse } from "./base.response";
|
||||
import { CipherResponse } from "./cipher.response";
|
||||
|
||||
export class AttachmentUploadDataResponse extends BaseResponse {
|
||||
attachmentId: string;
|
||||
fileUploadType: FileUploadType;
|
||||
cipherResponse: CipherResponse;
|
||||
cipherMiniResponse: CipherResponse;
|
||||
url: string = null;
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.attachmentId = this.getResponseProperty("AttachmentId");
|
||||
this.fileUploadType = this.getResponseProperty("FileUploadType");
|
||||
const cipherResponse = this.getResponseProperty("CipherResponse");
|
||||
const cipherMiniResponse = this.getResponseProperty("CipherMiniResponse");
|
||||
this.cipherResponse = cipherResponse == null ? null : new CipherResponse(cipherResponse);
|
||||
this.cipherMiniResponse =
|
||||
cipherMiniResponse == null ? null : new CipherResponse(cipherMiniResponse);
|
||||
this.url = this.getResponseProperty("Url");
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { BaseResponse } from "./base.response";
|
||||
|
||||
export class AttachmentResponse extends BaseResponse {
|
||||
id: string;
|
||||
url: string;
|
||||
fileName: string;
|
||||
key: string;
|
||||
size: string;
|
||||
sizeName: string;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.id = this.getResponseProperty("Id");
|
||||
this.url = this.getResponseProperty("Url");
|
||||
this.fileName = this.getResponseProperty("FileName");
|
||||
this.key = this.getResponseProperty("Key");
|
||||
this.size = this.getResponseProperty("Size");
|
||||
this.sizeName = this.getResponseProperty("SizeName");
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
import { CipherRepromptType } from "../../enums/cipherRepromptType";
|
||||
import { CardApi } from "../api/card.api";
|
||||
import { FieldApi } from "../api/field.api";
|
||||
import { IdentityApi } from "../api/identity.api";
|
||||
import { LoginApi } from "../api/login.api";
|
||||
import { SecureNoteApi } from "../api/secure-note.api";
|
||||
|
||||
import { AttachmentResponse } from "./attachment.response";
|
||||
import { BaseResponse } from "./base.response";
|
||||
import { PasswordHistoryResponse } from "./password-history.response";
|
||||
|
||||
export class CipherResponse extends BaseResponse {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
folderId: string;
|
||||
type: number;
|
||||
name: string;
|
||||
notes: string;
|
||||
fields: FieldApi[];
|
||||
login: LoginApi;
|
||||
card: CardApi;
|
||||
identity: IdentityApi;
|
||||
secureNote: SecureNoteApi;
|
||||
favorite: boolean;
|
||||
edit: boolean;
|
||||
viewPassword: boolean;
|
||||
organizationUseTotp: boolean;
|
||||
revisionDate: string;
|
||||
attachments: AttachmentResponse[];
|
||||
passwordHistory: PasswordHistoryResponse[];
|
||||
collectionIds: string[];
|
||||
creationDate: string;
|
||||
deletedDate: string;
|
||||
reprompt: CipherRepromptType;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.id = this.getResponseProperty("Id");
|
||||
this.organizationId = this.getResponseProperty("OrganizationId");
|
||||
this.folderId = this.getResponseProperty("FolderId") || null;
|
||||
this.type = this.getResponseProperty("Type");
|
||||
this.name = this.getResponseProperty("Name");
|
||||
this.notes = this.getResponseProperty("Notes");
|
||||
this.favorite = this.getResponseProperty("Favorite") || false;
|
||||
this.edit = !!this.getResponseProperty("Edit");
|
||||
if (this.getResponseProperty("ViewPassword") == null) {
|
||||
this.viewPassword = true;
|
||||
} else {
|
||||
this.viewPassword = this.getResponseProperty("ViewPassword");
|
||||
}
|
||||
this.organizationUseTotp = this.getResponseProperty("OrganizationUseTotp");
|
||||
this.revisionDate = this.getResponseProperty("RevisionDate");
|
||||
this.collectionIds = this.getResponseProperty("CollectionIds");
|
||||
this.creationDate = this.getResponseProperty("CreationDate");
|
||||
this.deletedDate = this.getResponseProperty("DeletedDate");
|
||||
|
||||
const login = this.getResponseProperty("Login");
|
||||
if (login != null) {
|
||||
this.login = new LoginApi(login);
|
||||
}
|
||||
|
||||
const card = this.getResponseProperty("Card");
|
||||
if (card != null) {
|
||||
this.card = new CardApi(card);
|
||||
}
|
||||
|
||||
const identity = this.getResponseProperty("Identity");
|
||||
if (identity != null) {
|
||||
this.identity = new IdentityApi(identity);
|
||||
}
|
||||
|
||||
const secureNote = this.getResponseProperty("SecureNote");
|
||||
if (secureNote != null) {
|
||||
this.secureNote = new SecureNoteApi(secureNote);
|
||||
}
|
||||
|
||||
const fields = this.getResponseProperty("Fields");
|
||||
if (fields != null) {
|
||||
this.fields = fields.map((f: any) => new FieldApi(f));
|
||||
}
|
||||
|
||||
const attachments = this.getResponseProperty("Attachments");
|
||||
if (attachments != null) {
|
||||
this.attachments = attachments.map((a: any) => new AttachmentResponse(a));
|
||||
}
|
||||
|
||||
const passwordHistory = this.getResponseProperty("PasswordHistory");
|
||||
if (passwordHistory != null) {
|
||||
this.passwordHistory = passwordHistory.map((h: any) => new PasswordHistoryResponse(h));
|
||||
}
|
||||
|
||||
this.reprompt = this.getResponseProperty("Reprompt") || CipherRepromptType.None;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import { EmergencyAccessStatusType } from "../../enums/emergencyAccessStatusType";
|
||||
import { EmergencyAccessType } from "../../enums/emergencyAccessType";
|
||||
import { KdfType } from "../../enums/kdfType";
|
||||
import { CipherResponse } from "../../vault/models/response/cipher.response";
|
||||
|
||||
import { BaseResponse } from "./base.response";
|
||||
import { CipherResponse } from "./cipher.response";
|
||||
|
||||
export class EmergencyAccessGranteeDetailsResponse extends BaseResponse {
|
||||
id: string;
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import { BaseResponse } from "./base.response";
|
||||
|
||||
export class FolderResponse extends BaseResponse {
|
||||
id: string;
|
||||
name: string;
|
||||
revisionDate: string;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.id = this.getResponseProperty("Id");
|
||||
this.name = this.getResponseProperty("Name");
|
||||
this.revisionDate = this.getResponseProperty("RevisionDate");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { CipherResponse } from "../../vault/models/response/cipher.response";
|
||||
|
||||
import { BaseResponse } from "./base.response";
|
||||
import { CipherResponse } from "./cipher.response";
|
||||
import { CollectionResponse } from "./collection.response";
|
||||
|
||||
export class OrganizationExportResponse extends BaseResponse {
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import { BaseResponse } from "./base.response";
|
||||
|
||||
export class PasswordHistoryResponse extends BaseResponse {
|
||||
password: string;
|
||||
lastUsedDate: string;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.password = this.getResponseProperty("Password");
|
||||
this.lastUsedDate = this.getResponseProperty("LastUsedDate");
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import { BaseResponse } from "./base.response";
|
||||
import { CipherResponse } from "./cipher.response";
|
||||
import { CollectionDetailsResponse } from "./collection.response";
|
||||
import { DomainsResponse } from "./domains.response";
|
||||
import { FolderResponse } from "./folder.response";
|
||||
import { PolicyResponse } from "./policy.response";
|
||||
import { ProfileResponse } from "./profile.response";
|
||||
import { SendResponse } from "./send.response";
|
||||
|
||||
export class SyncResponse extends BaseResponse {
|
||||
profile?: ProfileResponse;
|
||||
folders: FolderResponse[] = [];
|
||||
collections: CollectionDetailsResponse[] = [];
|
||||
ciphers: CipherResponse[] = [];
|
||||
domains?: DomainsResponse;
|
||||
policies?: PolicyResponse[] = [];
|
||||
sends: SendResponse[] = [];
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
|
||||
const profile = this.getResponseProperty("Profile");
|
||||
if (profile != null) {
|
||||
this.profile = new ProfileResponse(profile);
|
||||
}
|
||||
|
||||
const folders = this.getResponseProperty("Folders");
|
||||
if (folders != null) {
|
||||
this.folders = folders.map((f: any) => new FolderResponse(f));
|
||||
}
|
||||
|
||||
const collections = this.getResponseProperty("Collections");
|
||||
if (collections != null) {
|
||||
this.collections = collections.map((c: any) => new CollectionDetailsResponse(c));
|
||||
}
|
||||
|
||||
const ciphers = this.getResponseProperty("Ciphers");
|
||||
if (ciphers != null) {
|
||||
this.ciphers = ciphers.map((c: any) => new CipherResponse(c));
|
||||
}
|
||||
|
||||
const domains = this.getResponseProperty("Domains");
|
||||
if (domains != null) {
|
||||
this.domains = new DomainsResponse(domains);
|
||||
}
|
||||
|
||||
const policies = this.getResponseProperty("Policies");
|
||||
if (policies != null) {
|
||||
this.policies = policies.map((p: any) => new PolicyResponse(p));
|
||||
}
|
||||
|
||||
const sends = this.getResponseProperty("Sends");
|
||||
if (sends != null) {
|
||||
this.sends = sends.map((s: any) => new SendResponse(s));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { Attachment } from "../domain/attachment";
|
||||
import { SymmetricCryptoKey } from "../domain/symmetric-crypto-key";
|
||||
|
||||
import { View } from "./view";
|
||||
|
||||
export class AttachmentView implements View {
|
||||
id: string = null;
|
||||
url: string = null;
|
||||
size: string = null;
|
||||
sizeName: string = null;
|
||||
fileName: string = null;
|
||||
key: SymmetricCryptoKey = null;
|
||||
|
||||
constructor(a?: Attachment) {
|
||||
if (!a) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.id = a.id;
|
||||
this.url = a.url;
|
||||
this.size = a.size;
|
||||
this.sizeName = a.sizeName;
|
||||
}
|
||||
|
||||
get fileSize(): number {
|
||||
try {
|
||||
if (this.size != null) {
|
||||
return parseInt(this.size, null);
|
||||
}
|
||||
} catch {
|
||||
// Invalid file size.
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<AttachmentView>>): AttachmentView {
|
||||
const key = obj.key == null ? null : SymmetricCryptoKey.fromJSON(obj.key);
|
||||
return Object.assign(new AttachmentView(), obj, { key: key });
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { CardLinkedId as LinkedId } from "../../enums/linkedIdType";
|
||||
import { linkedFieldOption } from "../../misc/linkedFieldOption.decorator";
|
||||
|
||||
import { ItemView } from "./item.view";
|
||||
|
||||
export class CardView extends ItemView {
|
||||
@linkedFieldOption(LinkedId.CardholderName)
|
||||
cardholderName: string = null;
|
||||
@linkedFieldOption(LinkedId.ExpMonth, "expirationMonth")
|
||||
expMonth: string = null;
|
||||
@linkedFieldOption(LinkedId.ExpYear, "expirationYear")
|
||||
expYear: string = null;
|
||||
@linkedFieldOption(LinkedId.Code, "securityCode")
|
||||
code: string = null;
|
||||
|
||||
private _brand: string = null;
|
||||
private _number: string = null;
|
||||
private _subTitle: string = null;
|
||||
|
||||
get maskedCode(): string {
|
||||
return this.code != null ? "•".repeat(this.code.length) : null;
|
||||
}
|
||||
|
||||
get maskedNumber(): string {
|
||||
return this.number != null ? "•".repeat(this.number.length) : null;
|
||||
}
|
||||
|
||||
@linkedFieldOption(LinkedId.Brand)
|
||||
get brand(): string {
|
||||
return this._brand;
|
||||
}
|
||||
set brand(value: string) {
|
||||
this._brand = value;
|
||||
this._subTitle = null;
|
||||
}
|
||||
|
||||
@linkedFieldOption(LinkedId.Number)
|
||||
get number(): string {
|
||||
return this._number;
|
||||
}
|
||||
set number(value: string) {
|
||||
this._number = value;
|
||||
this._subTitle = null;
|
||||
}
|
||||
|
||||
get subTitle(): string {
|
||||
if (this._subTitle == null) {
|
||||
this._subTitle = this.brand;
|
||||
if (this.number != null && this.number.length >= 4) {
|
||||
if (this._subTitle != null && this._subTitle !== "") {
|
||||
this._subTitle += ", ";
|
||||
} else {
|
||||
this._subTitle = "";
|
||||
}
|
||||
|
||||
// Show last 5 on amex, last 4 for all others
|
||||
const count =
|
||||
this.number.length >= 5 && this.number.match(new RegExp("^3[47]")) != null ? 5 : 4;
|
||||
this._subTitle += "*" + this.number.substr(this.number.length - count);
|
||||
}
|
||||
}
|
||||
return this._subTitle;
|
||||
}
|
||||
|
||||
get expiration(): string {
|
||||
if (!this.expMonth && !this.expYear) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let exp = this.expMonth != null ? ("0" + this.expMonth).slice(-2) : "__";
|
||||
exp += " / " + (this.expYear != null ? this.formatYear(this.expYear) : "____");
|
||||
return exp;
|
||||
}
|
||||
|
||||
private formatYear(year: string): string {
|
||||
return year.length === 2 ? "20" + year : year;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<CardView>>): CardView {
|
||||
return Object.assign(new CardView(), obj);
|
||||
}
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { CipherRepromptType } from "../../enums/cipherRepromptType";
|
||||
import { CipherType } from "../../enums/cipherType";
|
||||
import { LinkedIdType } from "../../enums/linkedIdType";
|
||||
import { InitializerMetadata } from "../../interfaces/initializer-metadata.interface";
|
||||
import { InitializerKey } from "../../services/cryptography/initializer-key";
|
||||
import { LocalData } from "../data/local.data";
|
||||
import { Cipher } from "../domain/cipher";
|
||||
|
||||
import { AttachmentView } from "./attachment.view";
|
||||
import { CardView } from "./card.view";
|
||||
import { FieldView } from "./field.view";
|
||||
import { IdentityView } from "./identity.view";
|
||||
import { LoginView } from "./login.view";
|
||||
import { PasswordHistoryView } from "./password-history.view";
|
||||
import { SecureNoteView } from "./secure-note.view";
|
||||
import { View } from "./view";
|
||||
|
||||
export class CipherView implements View, InitializerMetadata {
|
||||
readonly initializerKey = InitializerKey.CipherView;
|
||||
|
||||
id: string = null;
|
||||
organizationId: string = null;
|
||||
folderId: string = null;
|
||||
name: string = null;
|
||||
notes: string = null;
|
||||
type: CipherType = null;
|
||||
favorite = false;
|
||||
organizationUseTotp = false;
|
||||
edit = false;
|
||||
viewPassword = true;
|
||||
localData: LocalData;
|
||||
login = new LoginView();
|
||||
identity = new IdentityView();
|
||||
card = new CardView();
|
||||
secureNote = new SecureNoteView();
|
||||
attachments: AttachmentView[] = null;
|
||||
fields: FieldView[] = null;
|
||||
passwordHistory: PasswordHistoryView[] = null;
|
||||
collectionIds: string[] = null;
|
||||
revisionDate: Date = null;
|
||||
creationDate: Date = null;
|
||||
deletedDate: Date = null;
|
||||
reprompt: CipherRepromptType = CipherRepromptType.None;
|
||||
|
||||
constructor(c?: Cipher) {
|
||||
if (!c) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.id = c.id;
|
||||
this.organizationId = c.organizationId;
|
||||
this.folderId = c.folderId;
|
||||
this.favorite = c.favorite;
|
||||
this.organizationUseTotp = c.organizationUseTotp;
|
||||
this.edit = c.edit;
|
||||
this.viewPassword = c.viewPassword;
|
||||
this.type = c.type;
|
||||
this.localData = c.localData;
|
||||
this.collectionIds = c.collectionIds;
|
||||
this.revisionDate = c.revisionDate;
|
||||
this.creationDate = c.creationDate;
|
||||
this.deletedDate = c.deletedDate;
|
||||
// Old locally stored ciphers might have reprompt == null. If so set it to None.
|
||||
this.reprompt = c.reprompt ?? CipherRepromptType.None;
|
||||
}
|
||||
|
||||
private get item() {
|
||||
switch (this.type) {
|
||||
case CipherType.Login:
|
||||
return this.login;
|
||||
case CipherType.SecureNote:
|
||||
return this.secureNote;
|
||||
case CipherType.Card:
|
||||
return this.card;
|
||||
case CipherType.Identity:
|
||||
return this.identity;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
get subTitle(): string {
|
||||
return this.item.subTitle;
|
||||
}
|
||||
|
||||
get hasPasswordHistory(): boolean {
|
||||
return this.passwordHistory && this.passwordHistory.length > 0;
|
||||
}
|
||||
|
||||
get hasAttachments(): boolean {
|
||||
return this.attachments && this.attachments.length > 0;
|
||||
}
|
||||
|
||||
get hasOldAttachments(): boolean {
|
||||
if (this.hasAttachments) {
|
||||
for (let i = 0; i < this.attachments.length; i++) {
|
||||
if (this.attachments[i].key == null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
get hasFields(): boolean {
|
||||
return this.fields && this.fields.length > 0;
|
||||
}
|
||||
|
||||
get passwordRevisionDisplayDate(): Date {
|
||||
if (this.type !== CipherType.Login || this.login == null) {
|
||||
return null;
|
||||
} else if (this.login.password == null || this.login.password === "") {
|
||||
return null;
|
||||
}
|
||||
return this.login.passwordRevisionDate;
|
||||
}
|
||||
|
||||
get isDeleted(): boolean {
|
||||
return this.deletedDate != null;
|
||||
}
|
||||
|
||||
get linkedFieldOptions() {
|
||||
return this.item.linkedFieldOptions;
|
||||
}
|
||||
|
||||
linkedFieldValue(id: LinkedIdType) {
|
||||
const linkedFieldOption = this.linkedFieldOptions?.get(id);
|
||||
if (linkedFieldOption == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const item = this.item;
|
||||
return this.item[linkedFieldOption.propertyKey as keyof typeof item];
|
||||
}
|
||||
|
||||
linkedFieldI18nKey(id: LinkedIdType): string {
|
||||
return this.linkedFieldOptions.get(id)?.i18nKey;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<CipherView>>): CipherView {
|
||||
const view = new CipherView();
|
||||
const revisionDate = obj.revisionDate == null ? null : new Date(obj.revisionDate);
|
||||
const deletedDate = obj.deletedDate == null ? null : new Date(obj.deletedDate);
|
||||
const attachments = obj.attachments?.map((a: any) => AttachmentView.fromJSON(a));
|
||||
const fields = obj.fields?.map((f: any) => FieldView.fromJSON(f));
|
||||
const passwordHistory = obj.passwordHistory?.map((ph: any) => PasswordHistoryView.fromJSON(ph));
|
||||
|
||||
Object.assign(view, obj, {
|
||||
revisionDate: revisionDate,
|
||||
deletedDate: deletedDate,
|
||||
attachments: attachments,
|
||||
fields: fields,
|
||||
passwordHistory: passwordHistory,
|
||||
});
|
||||
|
||||
switch (obj.type) {
|
||||
case CipherType.Card:
|
||||
view.card = CardView.fromJSON(obj.card);
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
view.identity = IdentityView.fromJSON(obj.identity);
|
||||
break;
|
||||
case CipherType.Login:
|
||||
view.login = LoginView.fromJSON(obj.login);
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
view.secureNote = SecureNoteView.fromJSON(obj.secureNote);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { FieldType } from "../../enums/fieldType";
|
||||
import { LinkedIdType } from "../../enums/linkedIdType";
|
||||
import { Field } from "../domain/field";
|
||||
|
||||
import { View } from "./view";
|
||||
|
||||
export class FieldView implements View {
|
||||
name: string = null;
|
||||
value: string = null;
|
||||
type: FieldType = null;
|
||||
newField = false; // Marks if the field is new and hasn't been saved
|
||||
showValue = false;
|
||||
showCount = false;
|
||||
linkedId: LinkedIdType = null;
|
||||
|
||||
constructor(f?: Field) {
|
||||
if (!f) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.type = f.type;
|
||||
this.linkedId = f.linkedId;
|
||||
}
|
||||
|
||||
get maskedValue(): string {
|
||||
return this.value != null ? "••••••••" : null;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<FieldView>>): FieldView {
|
||||
return Object.assign(new FieldView(), obj);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { Folder } from "../domain/folder";
|
||||
import { ITreeNodeObject } from "../domain/tree-node";
|
||||
|
||||
import { View } from "./view";
|
||||
|
||||
export class FolderView implements View, ITreeNodeObject {
|
||||
id: string = null;
|
||||
name: string = null;
|
||||
revisionDate: Date = null;
|
||||
|
||||
constructor(f?: Folder) {
|
||||
if (!f) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.id = f.id;
|
||||
this.revisionDate = f.revisionDate;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Jsonify<FolderView>) {
|
||||
const revisionDate = obj.revisionDate == null ? null : new Date(obj.revisionDate);
|
||||
return Object.assign(new FolderView(), obj, { revisionDate });
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { IdentityLinkedId as LinkedId } from "../../enums/linkedIdType";
|
||||
import { linkedFieldOption } from "../../misc/linkedFieldOption.decorator";
|
||||
import { Utils } from "../../misc/utils";
|
||||
|
||||
import { ItemView } from "./item.view";
|
||||
|
||||
export class IdentityView extends ItemView {
|
||||
@linkedFieldOption(LinkedId.Title)
|
||||
title: string = null;
|
||||
@linkedFieldOption(LinkedId.MiddleName)
|
||||
middleName: string = null;
|
||||
@linkedFieldOption(LinkedId.Address1)
|
||||
address1: string = null;
|
||||
@linkedFieldOption(LinkedId.Address2)
|
||||
address2: string = null;
|
||||
@linkedFieldOption(LinkedId.Address3)
|
||||
address3: string = null;
|
||||
@linkedFieldOption(LinkedId.City, "cityTown")
|
||||
city: string = null;
|
||||
@linkedFieldOption(LinkedId.State, "stateProvince")
|
||||
state: string = null;
|
||||
@linkedFieldOption(LinkedId.PostalCode, "zipPostalCode")
|
||||
postalCode: string = null;
|
||||
@linkedFieldOption(LinkedId.Country)
|
||||
country: string = null;
|
||||
@linkedFieldOption(LinkedId.Company)
|
||||
company: string = null;
|
||||
@linkedFieldOption(LinkedId.Email)
|
||||
email: string = null;
|
||||
@linkedFieldOption(LinkedId.Phone)
|
||||
phone: string = null;
|
||||
@linkedFieldOption(LinkedId.Ssn)
|
||||
ssn: string = null;
|
||||
@linkedFieldOption(LinkedId.Username)
|
||||
username: string = null;
|
||||
@linkedFieldOption(LinkedId.PassportNumber)
|
||||
passportNumber: string = null;
|
||||
@linkedFieldOption(LinkedId.LicenseNumber)
|
||||
licenseNumber: string = null;
|
||||
|
||||
private _firstName: string = null;
|
||||
private _lastName: string = null;
|
||||
private _subTitle: string = null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
@linkedFieldOption(LinkedId.FirstName)
|
||||
get firstName(): string {
|
||||
return this._firstName;
|
||||
}
|
||||
set firstName(value: string) {
|
||||
this._firstName = value;
|
||||
this._subTitle = null;
|
||||
}
|
||||
|
||||
@linkedFieldOption(LinkedId.LastName)
|
||||
get lastName(): string {
|
||||
return this._lastName;
|
||||
}
|
||||
set lastName(value: string) {
|
||||
this._lastName = value;
|
||||
this._subTitle = null;
|
||||
}
|
||||
|
||||
get subTitle(): string {
|
||||
if (this._subTitle == null && (this.firstName != null || this.lastName != null)) {
|
||||
this._subTitle = "";
|
||||
if (this.firstName != null) {
|
||||
this._subTitle = this.firstName;
|
||||
}
|
||||
if (this.lastName != null) {
|
||||
if (this._subTitle !== "") {
|
||||
this._subTitle += " ";
|
||||
}
|
||||
this._subTitle += this.lastName;
|
||||
}
|
||||
}
|
||||
|
||||
return this._subTitle;
|
||||
}
|
||||
|
||||
@linkedFieldOption(LinkedId.FullName)
|
||||
get fullName(): string {
|
||||
if (
|
||||
this.title != null ||
|
||||
this.firstName != null ||
|
||||
this.middleName != null ||
|
||||
this.lastName != null
|
||||
) {
|
||||
let name = "";
|
||||
if (this.title != null) {
|
||||
name += this.title + " ";
|
||||
}
|
||||
if (this.firstName != null) {
|
||||
name += this.firstName + " ";
|
||||
}
|
||||
if (this.middleName != null) {
|
||||
name += this.middleName + " ";
|
||||
}
|
||||
if (this.lastName != null) {
|
||||
name += this.lastName;
|
||||
}
|
||||
return name.trim();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
get fullAddress(): string {
|
||||
let address = this.address1;
|
||||
if (!Utils.isNullOrWhitespace(this.address2)) {
|
||||
if (!Utils.isNullOrWhitespace(address)) {
|
||||
address += ", ";
|
||||
}
|
||||
address += this.address2;
|
||||
}
|
||||
if (!Utils.isNullOrWhitespace(this.address3)) {
|
||||
if (!Utils.isNullOrWhitespace(address)) {
|
||||
address += ", ";
|
||||
}
|
||||
address += this.address3;
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
get fullAddressPart2(): string {
|
||||
if (this.city == null && this.state == null && this.postalCode == null) {
|
||||
return null;
|
||||
}
|
||||
const city = this.city || "-";
|
||||
const state = this.state;
|
||||
const postalCode = this.postalCode || "-";
|
||||
let addressPart2 = city;
|
||||
if (!Utils.isNullOrWhitespace(state)) {
|
||||
addressPart2 += ", " + state;
|
||||
}
|
||||
addressPart2 += ", " + postalCode;
|
||||
return addressPart2;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<IdentityView>>): IdentityView {
|
||||
return Object.assign(new IdentityView(), obj);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { LinkedMetadata } from "../../misc/linkedFieldOption.decorator";
|
||||
|
||||
import { View } from "./view";
|
||||
|
||||
export abstract class ItemView implements View {
|
||||
linkedFieldOptions: Map<number, LinkedMetadata>;
|
||||
abstract get subTitle(): string;
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { UriMatchType } from "../../enums/uriMatchType";
|
||||
import { Utils } from "../../misc/utils";
|
||||
import { LoginUri } from "../domain/login-uri";
|
||||
|
||||
import { View } from "./view";
|
||||
|
||||
const CanLaunchWhitelist = [
|
||||
"https://",
|
||||
"http://",
|
||||
"ssh://",
|
||||
"ftp://",
|
||||
"sftp://",
|
||||
"irc://",
|
||||
"vnc://",
|
||||
// https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/remote-desktop-uri
|
||||
"rdp://", // Legacy RDP URI scheme
|
||||
"ms-rd:", // Preferred RDP URI scheme
|
||||
"chrome://",
|
||||
"iosapp://",
|
||||
"androidapp://",
|
||||
];
|
||||
|
||||
export class LoginUriView implements View {
|
||||
match: UriMatchType = null;
|
||||
|
||||
private _uri: string = null;
|
||||
private _domain: string = null;
|
||||
private _hostname: string = null;
|
||||
private _host: string = null;
|
||||
private _canLaunch: boolean = null;
|
||||
|
||||
constructor(u?: LoginUri) {
|
||||
if (!u) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.match = u.match;
|
||||
}
|
||||
|
||||
get uri(): string {
|
||||
return this._uri;
|
||||
}
|
||||
set uri(value: string) {
|
||||
this._uri = value;
|
||||
this._domain = null;
|
||||
this._canLaunch = null;
|
||||
}
|
||||
|
||||
get domain(): string {
|
||||
if (this._domain == null && this.uri != null) {
|
||||
this._domain = Utils.getDomain(this.uri);
|
||||
if (this._domain === "") {
|
||||
this._domain = null;
|
||||
}
|
||||
}
|
||||
|
||||
return this._domain;
|
||||
}
|
||||
|
||||
get hostname(): string {
|
||||
if (this.match === UriMatchType.RegularExpression) {
|
||||
return null;
|
||||
}
|
||||
if (this._hostname == null && this.uri != null) {
|
||||
this._hostname = Utils.getHostname(this.uri);
|
||||
if (this._hostname === "") {
|
||||
this._hostname = null;
|
||||
}
|
||||
}
|
||||
|
||||
return this._hostname;
|
||||
}
|
||||
|
||||
get host(): string {
|
||||
if (this.match === UriMatchType.RegularExpression) {
|
||||
return null;
|
||||
}
|
||||
if (this._host == null && this.uri != null) {
|
||||
this._host = Utils.getHost(this.uri);
|
||||
if (this._host === "") {
|
||||
this._host = null;
|
||||
}
|
||||
}
|
||||
|
||||
return this._host;
|
||||
}
|
||||
|
||||
get hostnameOrUri(): string {
|
||||
return this.hostname != null ? this.hostname : this.uri;
|
||||
}
|
||||
|
||||
get hostOrUri(): string {
|
||||
return this.host != null ? this.host : this.uri;
|
||||
}
|
||||
|
||||
get isWebsite(): boolean {
|
||||
return (
|
||||
this.uri != null &&
|
||||
(this.uri.indexOf("http://") === 0 ||
|
||||
this.uri.indexOf("https://") === 0 ||
|
||||
(this.uri.indexOf("://") < 0 && !Utils.isNullOrWhitespace(Utils.getDomain(this.uri))))
|
||||
);
|
||||
}
|
||||
|
||||
get canLaunch(): boolean {
|
||||
if (this._canLaunch != null) {
|
||||
return this._canLaunch;
|
||||
}
|
||||
if (this.uri != null && this.match !== UriMatchType.RegularExpression) {
|
||||
const uri = this.launchUri;
|
||||
for (let i = 0; i < CanLaunchWhitelist.length; i++) {
|
||||
if (uri.indexOf(CanLaunchWhitelist[i]) === 0) {
|
||||
this._canLaunch = true;
|
||||
return this._canLaunch;
|
||||
}
|
||||
}
|
||||
}
|
||||
this._canLaunch = false;
|
||||
return this._canLaunch;
|
||||
}
|
||||
|
||||
get launchUri(): string {
|
||||
return this.uri.indexOf("://") < 0 && !Utils.isNullOrWhitespace(Utils.getDomain(this.uri))
|
||||
? "http://" + this.uri
|
||||
: this.uri;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<LoginUriView>>): LoginUriView {
|
||||
return Object.assign(new LoginUriView(), obj);
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { LoginLinkedId as LinkedId } from "../../enums/linkedIdType";
|
||||
import { linkedFieldOption } from "../../misc/linkedFieldOption.decorator";
|
||||
import { Utils } from "../../misc/utils";
|
||||
import { Login } from "../domain/login";
|
||||
|
||||
import { ItemView } from "./item.view";
|
||||
import { LoginUriView } from "./login-uri.view";
|
||||
|
||||
export class LoginView extends ItemView {
|
||||
@linkedFieldOption(LinkedId.Username)
|
||||
username: string = null;
|
||||
@linkedFieldOption(LinkedId.Password)
|
||||
password: string = null;
|
||||
|
||||
passwordRevisionDate?: Date = null;
|
||||
totp: string = null;
|
||||
uris: LoginUriView[] = null;
|
||||
autofillOnPageLoad: boolean = null;
|
||||
|
||||
constructor(l?: Login) {
|
||||
super();
|
||||
if (!l) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.passwordRevisionDate = l.passwordRevisionDate;
|
||||
this.autofillOnPageLoad = l.autofillOnPageLoad;
|
||||
}
|
||||
|
||||
get uri(): string {
|
||||
return this.hasUris ? this.uris[0].uri : null;
|
||||
}
|
||||
|
||||
get maskedPassword(): string {
|
||||
return this.password != null ? "••••••••" : null;
|
||||
}
|
||||
|
||||
get subTitle(): string {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
get canLaunch(): boolean {
|
||||
return this.hasUris && this.uris.some((u) => u.canLaunch);
|
||||
}
|
||||
|
||||
get hasTotp(): boolean {
|
||||
return !Utils.isNullOrWhitespace(this.totp);
|
||||
}
|
||||
|
||||
get launchUri(): string {
|
||||
if (this.hasUris) {
|
||||
const uri = this.uris.find((u) => u.canLaunch);
|
||||
if (uri != null) {
|
||||
return uri.launchUri;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
get hasUris(): boolean {
|
||||
return this.uris != null && this.uris.length > 0;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<LoginView>>): LoginView {
|
||||
const passwordRevisionDate =
|
||||
obj.passwordRevisionDate == null ? null : new Date(obj.passwordRevisionDate);
|
||||
const uris = obj.uris?.map((uri: any) => LoginUriView.fromJSON(uri));
|
||||
|
||||
return Object.assign(new LoginView(), obj, {
|
||||
passwordRevisionDate: passwordRevisionDate,
|
||||
uris: uris,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { Password } from "../domain/password";
|
||||
|
||||
import { View } from "./view";
|
||||
|
||||
export class PasswordHistoryView implements View {
|
||||
password: string = null;
|
||||
lastUsedDate: Date = null;
|
||||
|
||||
constructor(ph?: Password) {
|
||||
if (!ph) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastUsedDate = ph.lastUsedDate;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<PasswordHistoryView>>): PasswordHistoryView {
|
||||
const lastUsedDate = obj.lastUsedDate == null ? null : new Date(obj.lastUsedDate);
|
||||
|
||||
return Object.assign(new PasswordHistoryView(), obj, {
|
||||
lastUsedDate: lastUsedDate,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { SecureNoteType } from "../../enums/secureNoteType";
|
||||
import { SecureNote } from "../domain/secure-note";
|
||||
|
||||
import { ItemView } from "./item.view";
|
||||
|
||||
export class SecureNoteView extends ItemView {
|
||||
type: SecureNoteType = null;
|
||||
|
||||
constructor(n?: SecureNote) {
|
||||
super();
|
||||
if (!n) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.type = n.type;
|
||||
}
|
||||
|
||||
get subTitle(): string {
|
||||
return null;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<SecureNoteView>>): SecureNoteView {
|
||||
return Object.assign(new SecureNoteView(), obj);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user