mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-05 23:53:21 +00:00
[PM-23631] Delete unused jslib models and misc code (#819)
* Remove unused cipher-related code from jslib - Delete cipher.ts, cipherView.ts, sortedCiphersCache.ts - Delete search-ciphers.pipe.ts and icon.component files - Delete cipherData.ts, cipherResponse.ts, linkedIdType.ts - Delete field-related files (fieldData.ts, field.ts, fieldApi.ts, fieldView.ts) - Delete sync, emergency access, and attachment upload response files - Delete card and identity view files - Delete linkedFieldOption decorator - Remove cipher methods from StateService abstractions and implementations - Preserve ciphers property in AccountData as 'any' type for data compatibility * Remove unused Send feature and related password manager code from jslib - Delete Send domain models: send.ts, sendAccess.ts, sendFile.ts, sendText.ts - Delete Send data models: sendData.ts, sendFileData.ts, sendTextData.ts - Delete Send view models: sendView.ts, sendAccessView.ts, sendFileView.ts, sendTextView.ts - Delete Send API models: sendFileApi.ts, sendTextApi.ts - Delete Send response models: sendAccessResponse.ts, sendFileDownloadDataResponse.ts, sendFileUploadDataResponse.ts, sendResponse.ts - Delete Send enum: sendType.ts - Delete Send specs: send.spec.ts, sendAccess.spec.ts, sendFile.spec.ts, sendText.spec.ts - Remove Send methods from StateService abstractions and implementations - Remove getDecryptedSends/setDecryptedSends and getEncryptedSends/setEncryptedSends methods - Change sends property in AccountData to 'any' type for data compatibility - Fix import formatting and remove empty lines * Remove misc unused password manager models from jslib - Delete Core domain models: card.ts, identity.ts, secureNote.ts, attachment.ts - Delete Core data models: cardData.ts, identityData.ts, secureNoteData.ts, attachmentData.ts - Delete Core view models: secureNoteView.ts, attachmentView.ts - Delete Core API models: cardApi.ts, identityApi.ts, secureNoteApi.ts - Delete Core response models: attachmentResponse.ts - Delete Core enum: secureNoteType.ts - Delete Core specs: card.spec.ts, identity.spec.ts, secureNote.spec.ts, attachment.spec.ts * Remove unused Organization files (folders/collections) - Delete folder and collection domain models, data models, view models, response models, and spec files * Remove unused UI/UX settings methods from state service - Remove 20 password manager specific interface methods: - Autofill methods (4): getAutoFillOnPageLoadDefault, setAutoFillOnPageLoadDefault, getEnableAutoFillOnPageLoad, setEnableAutoFillOnPageLoad - Browser integration methods (4): getEnableBrowserIntegration, setEnableBrowserIntegration, getEnableBrowserIntegrationFingerprint, setEnableBrowserIntegrationFingerprint - Notification methods (4): getDisableAddLoginNotification, setDisableAddLoginNotification, getDisableChangedPasswordNotification, setDisableChangedPasswordNotification - Favicon methods (2): getDisableFavicon, setDisableFavicon - Gravatar methods (2): getEnableGravitars, setEnableGravitars - Card/Identity tab methods (4): getDontShowCardsCurrentTab, setDontShowCardsCurrentTab, getDontShowIdentitiesCurrentTab, setDontShowIdentitiesCurrentTab * Fix build errors * Delete leftover data models and stateService methods * Delete iframes and passwordReprompt
This commit is contained in:
@@ -1,35 +0,0 @@
|
||||
<div
|
||||
#callout
|
||||
class="callout callout-{{ calloutStyle }}"
|
||||
[ngClass]="{ clickable: clickable }"
|
||||
[attr.role]="useAlertRole ? 'alert' : null"
|
||||
>
|
||||
<h3 class="callout-heading" *ngIf="title">
|
||||
<i class="bwi {{ icon }}" *ngIf="icon" aria-hidden="true"></i>
|
||||
{{ title }}
|
||||
</h3>
|
||||
<div class="enforced-policy-options" *ngIf="enforcedPolicyOptions">
|
||||
{{ enforcedPolicyMessage }}
|
||||
<ul>
|
||||
<li *ngIf="enforcedPolicyOptions?.minComplexity > 0">
|
||||
{{ "policyInEffectMinComplexity" | i18n: getPasswordScoreAlertDisplay() }}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.minLength > 0">
|
||||
{{ "policyInEffectMinLength" | i18n: enforcedPolicyOptions?.minLength.toString() }}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireUpper">
|
||||
{{ "policyInEffectUppercase" | i18n }}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireLower">
|
||||
{{ "policyInEffectLowercase" | i18n }}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireNumbers">
|
||||
{{ "policyInEffectNumbers" | i18n }}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireSpecial">
|
||||
{{ "policyInEffectSpecial" | i18n: "!@#$%^&*" }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
@@ -1,78 +0,0 @@
|
||||
import { Component, Input, OnInit } from "@angular/core";
|
||||
|
||||
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
|
||||
import { MasterPasswordPolicyOptions } from "@/jslib/common/src/models/domain/masterPasswordPolicyOptions";
|
||||
|
||||
@Component({
|
||||
selector: "app-callout",
|
||||
templateUrl: "callout.component.html",
|
||||
})
|
||||
export class CalloutComponent implements OnInit {
|
||||
@Input() type = "info";
|
||||
@Input() icon: string;
|
||||
@Input() title: string;
|
||||
@Input() clickable: boolean;
|
||||
@Input() enforcedPolicyOptions: MasterPasswordPolicyOptions;
|
||||
@Input() enforcedPolicyMessage: string;
|
||||
@Input() useAlertRole = false;
|
||||
|
||||
calloutStyle: string;
|
||||
|
||||
constructor(private i18nService: I18nService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.calloutStyle = this.type;
|
||||
|
||||
if (this.enforcedPolicyMessage === undefined) {
|
||||
this.enforcedPolicyMessage = this.i18nService.t("masterPasswordPolicyInEffect");
|
||||
}
|
||||
|
||||
if (this.type === "warning" || this.type === "danger") {
|
||||
if (this.type === "danger") {
|
||||
this.calloutStyle = "danger";
|
||||
}
|
||||
if (this.title === undefined) {
|
||||
this.title = this.i18nService.t("warning");
|
||||
}
|
||||
if (this.icon === undefined) {
|
||||
this.icon = "bwi-exclamation-triangle";
|
||||
}
|
||||
} else if (this.type === "error") {
|
||||
this.calloutStyle = "danger";
|
||||
if (this.title === undefined) {
|
||||
this.title = this.i18nService.t("error");
|
||||
}
|
||||
if (this.icon === undefined) {
|
||||
this.icon = "bwi-error";
|
||||
}
|
||||
} else if (this.type === "tip") {
|
||||
this.calloutStyle = "success";
|
||||
if (this.title === undefined) {
|
||||
this.title = this.i18nService.t("tip");
|
||||
}
|
||||
if (this.icon === undefined) {
|
||||
this.icon = "bwi-lightbulb";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getPasswordScoreAlertDisplay() {
|
||||
if (this.enforcedPolicyOptions == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
let str: string;
|
||||
switch (this.enforcedPolicyOptions.minComplexity) {
|
||||
case 4:
|
||||
str = this.i18nService.t("strong");
|
||||
break;
|
||||
case 3:
|
||||
str = this.i18nService.t("good");
|
||||
break;
|
||||
default:
|
||||
str = this.i18nService.t("weak");
|
||||
break;
|
||||
}
|
||||
return str + " (" + this.enforcedPolicyOptions.minComplexity + ")";
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<div class="icon" aria-hidden="true">
|
||||
<img
|
||||
[src]="image"
|
||||
appFallbackSrc="{{ fallbackImage }}"
|
||||
*ngIf="imageEnabled && image"
|
||||
alt=""
|
||||
decoding="async"
|
||||
loading="lazy"
|
||||
/>
|
||||
<i class="bwi bwi-fw bwi-lg {{ icon }}" *ngIf="!imageEnabled || !image"></i>
|
||||
</div>
|
||||
@@ -1,115 +0,0 @@
|
||||
import { Component, Input, OnChanges } from "@angular/core";
|
||||
|
||||
import { EnvironmentService } from "@/jslib/common/src/abstractions/environment.service";
|
||||
import { StateService } from "@/jslib/common/src/abstractions/state.service";
|
||||
import { CipherType } from "@/jslib/common/src/enums/cipherType";
|
||||
import { Utils } from "@/jslib/common/src/misc/utils";
|
||||
import { CipherView } from "@/jslib/common/src/models/view/cipherView";
|
||||
|
||||
/**
|
||||
* Provides a mapping from supported card brands to
|
||||
* the filenames of icon that should be present in images/cards folder of clients.
|
||||
*/
|
||||
const cardIcons: Record<string, string> = {
|
||||
Visa: "card-visa",
|
||||
Mastercard: "card-mastercard",
|
||||
Amex: "card-amex",
|
||||
Discover: "card-discover",
|
||||
"Diners Club": "card-diners-club",
|
||||
JCB: "card-jcb",
|
||||
Maestro: "card-maestro",
|
||||
UnionPay: "card-union-pay",
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: "app-vault-icon",
|
||||
templateUrl: "icon.component.html",
|
||||
})
|
||||
export class IconComponent implements OnChanges {
|
||||
@Input() cipher: CipherView;
|
||||
icon: string;
|
||||
image: string;
|
||||
fallbackImage: string;
|
||||
imageEnabled: boolean;
|
||||
|
||||
private iconsUrl: string;
|
||||
|
||||
constructor(
|
||||
environmentService: EnvironmentService,
|
||||
private stateService: StateService,
|
||||
) {
|
||||
this.iconsUrl = environmentService.getIconsUrl();
|
||||
}
|
||||
|
||||
async ngOnChanges() {
|
||||
// Components may be re-used when using cdk-virtual-scroll. Which puts the component in a weird state,
|
||||
// to avoid this we reset all state variables.
|
||||
this.image = null;
|
||||
this.fallbackImage = null;
|
||||
this.imageEnabled = !(await this.stateService.getDisableFavicon());
|
||||
this.load();
|
||||
}
|
||||
|
||||
protected load() {
|
||||
switch (this.cipher.type) {
|
||||
case CipherType.Login:
|
||||
this.icon = "bwi-globe";
|
||||
this.setLoginIcon();
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
this.icon = "bwi-sticky-note";
|
||||
break;
|
||||
case CipherType.Card:
|
||||
this.icon = "bwi-credit-card";
|
||||
this.setCardIcon();
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
this.icon = "bwi-id-card";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private setLoginIcon() {
|
||||
if (this.cipher.login.uri) {
|
||||
let hostnameUri = this.cipher.login.uri;
|
||||
let isWebsite = false;
|
||||
|
||||
if (hostnameUri.indexOf("androidapp://") === 0) {
|
||||
this.icon = "bwi-android";
|
||||
this.image = null;
|
||||
} else if (hostnameUri.indexOf("iosapp://") === 0) {
|
||||
this.icon = "bwi-apple";
|
||||
this.image = null;
|
||||
} else if (
|
||||
this.imageEnabled &&
|
||||
hostnameUri.indexOf("://") === -1 &&
|
||||
hostnameUri.indexOf(".") > -1
|
||||
) {
|
||||
hostnameUri = "http://" + hostnameUri;
|
||||
isWebsite = true;
|
||||
} else if (this.imageEnabled) {
|
||||
isWebsite = hostnameUri.indexOf("http") === 0 && hostnameUri.indexOf(".") > -1;
|
||||
}
|
||||
|
||||
if (this.imageEnabled && isWebsite) {
|
||||
try {
|
||||
this.image = this.iconsUrl + "/" + Utils.getHostname(hostnameUri) + "/icon.png";
|
||||
this.fallbackImage = "images/bwi-globe.png";
|
||||
} catch (e) {
|
||||
// Ignore error since the fallback icon will be shown if image is null.
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.image = null;
|
||||
}
|
||||
}
|
||||
|
||||
private setCardIcon() {
|
||||
const brand = this.cipher.card.brand;
|
||||
if (this.imageEnabled && brand in cardIcons) {
|
||||
this.icon = "credit-card-icon " + cardIcons[brand];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import { Directive } from "@angular/core";
|
||||
|
||||
import { CryptoService } from "@/jslib/common/src/abstractions/crypto.service";
|
||||
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@/jslib/common/src/abstractions/platformUtils.service";
|
||||
|
||||
import { ModalRef } from "./modal/modal.ref";
|
||||
|
||||
/**
|
||||
* Used to verify the user's Master Password for the "Master Password Re-prompt" feature only.
|
||||
* See UserVerificationComponent for any other situation where you need to verify the user's identity.
|
||||
*/
|
||||
@Directive()
|
||||
export class PasswordRepromptComponent {
|
||||
showPassword = false;
|
||||
masterPassword = "";
|
||||
|
||||
constructor(
|
||||
private modalRef: ModalRef,
|
||||
private cryptoService: CryptoService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
) {}
|
||||
|
||||
togglePassword() {
|
||||
this.showPassword = !this.showPassword;
|
||||
}
|
||||
|
||||
async submit() {
|
||||
if (!(await this.cryptoService.compareAndUpdateKeyHash(this.masterPassword, null))) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("invalidMasterPassword"),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.modalRef.close(true);
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import { Pipe, PipeTransform } from "@angular/core";
|
||||
|
||||
import { CipherView } from "@/jslib/common/src/models/view/cipherView";
|
||||
|
||||
@Pipe({
|
||||
name: "searchCiphers",
|
||||
})
|
||||
export class SearchCiphersPipe implements PipeTransform {
|
||||
transform(ciphers: CipherView[], searchText: string, deleted = false): CipherView[] {
|
||||
if (ciphers == null || ciphers.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (searchText == null || searchText.length < 2) {
|
||||
return ciphers.filter((c) => {
|
||||
return deleted !== c.isDeleted;
|
||||
});
|
||||
}
|
||||
|
||||
searchText = searchText.trim().toLowerCase();
|
||||
return ciphers.filter((c) => {
|
||||
if (deleted !== c.isDeleted) {
|
||||
return false;
|
||||
}
|
||||
if (c.name != null && c.name.toLowerCase().indexOf(searchText) > -1) {
|
||||
return true;
|
||||
}
|
||||
if (searchText.length >= 8 && c.id.startsWith(searchText)) {
|
||||
return true;
|
||||
}
|
||||
if (c.subTitle != null && c.subTitle.toLowerCase().indexOf(searchText) > -1) {
|
||||
return true;
|
||||
}
|
||||
if (c.login && c.login.uri != null && c.login.uri.toLowerCase().indexOf(searchText) > -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
import { Substitute, Arg } from "@fluffy-spoon/substitute";
|
||||
|
||||
import { CryptoService } from "@/jslib/common/src/abstractions/crypto.service";
|
||||
import { AttachmentData } from "@/jslib/common/src/models/data/attachmentData";
|
||||
import { Attachment } from "@/jslib/common/src/models/domain/attachment";
|
||||
import { SymmetricCryptoKey } from "@/jslib/common/src/models/domain/symmetricCryptoKey";
|
||||
import { ContainerService } from "@/jslib/common/src/services/container.service";
|
||||
|
||||
import { makeStaticByteArray, mockEnc } from "../utils";
|
||||
|
||||
describe("Attachment", () => {
|
||||
let data: AttachmentData;
|
||||
|
||||
beforeEach(() => {
|
||||
data = {
|
||||
id: "id",
|
||||
url: "url",
|
||||
fileName: "fileName",
|
||||
key: "key",
|
||||
size: "1100",
|
||||
sizeName: "1.1 KB",
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert from empty", () => {
|
||||
const data = new AttachmentData();
|
||||
const attachment = new Attachment(data);
|
||||
|
||||
expect(attachment).toEqual({
|
||||
id: null,
|
||||
url: null,
|
||||
size: undefined,
|
||||
sizeName: null,
|
||||
key: null,
|
||||
fileName: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const attachment = new Attachment(data);
|
||||
|
||||
expect(attachment).toEqual({
|
||||
size: "1100",
|
||||
id: "id",
|
||||
url: "url",
|
||||
sizeName: "1.1 KB",
|
||||
fileName: { encryptedString: "fileName", encryptionType: 0 },
|
||||
key: { encryptedString: "key", encryptionType: 0 },
|
||||
});
|
||||
});
|
||||
|
||||
it("toAttachmentData", () => {
|
||||
const attachment = new Attachment(data);
|
||||
expect(attachment.toAttachmentData()).toEqual(data);
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const attachment = new Attachment();
|
||||
attachment.id = "id";
|
||||
attachment.url = "url";
|
||||
attachment.size = "1100";
|
||||
attachment.sizeName = "1.1 KB";
|
||||
attachment.key = mockEnc("key");
|
||||
attachment.fileName = mockEnc("fileName");
|
||||
|
||||
const cryptoService = Substitute.for<CryptoService>();
|
||||
cryptoService.getOrgKey(null).resolves(null);
|
||||
cryptoService.decryptToBytes(Arg.any(), Arg.any()).resolves(makeStaticByteArray(32));
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService);
|
||||
|
||||
const view = await attachment.decrypt(null);
|
||||
|
||||
expect(view).toEqual({
|
||||
id: "id",
|
||||
url: "url",
|
||||
size: "1100",
|
||||
sizeName: "1.1 KB",
|
||||
fileName: "fileName",
|
||||
key: expect.any(SymmetricCryptoKey),
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,73 +0,0 @@
|
||||
import { CardData } from "@/jslib/common/src/models/data/cardData";
|
||||
import { Card } from "@/jslib/common/src/models/domain/card";
|
||||
|
||||
import { mockEnc } from "../utils";
|
||||
|
||||
describe("Card", () => {
|
||||
let data: CardData;
|
||||
|
||||
beforeEach(() => {
|
||||
data = {
|
||||
cardholderName: "encHolder",
|
||||
brand: "encBrand",
|
||||
number: "encNumber",
|
||||
expMonth: "encMonth",
|
||||
expYear: "encYear",
|
||||
code: "encCode",
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert from empty", () => {
|
||||
const data = new CardData();
|
||||
const card = new Card(data);
|
||||
|
||||
expect(card).toEqual({
|
||||
cardholderName: null,
|
||||
brand: null,
|
||||
number: null,
|
||||
expMonth: null,
|
||||
expYear: null,
|
||||
code: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const card = new Card(data);
|
||||
|
||||
expect(card).toEqual({
|
||||
cardholderName: { encryptedString: "encHolder", encryptionType: 0 },
|
||||
brand: { encryptedString: "encBrand", encryptionType: 0 },
|
||||
number: { encryptedString: "encNumber", encryptionType: 0 },
|
||||
expMonth: { encryptedString: "encMonth", encryptionType: 0 },
|
||||
expYear: { encryptedString: "encYear", encryptionType: 0 },
|
||||
code: { encryptedString: "encCode", encryptionType: 0 },
|
||||
});
|
||||
});
|
||||
|
||||
it("toCardData", () => {
|
||||
const card = new Card(data);
|
||||
expect(card.toCardData()).toEqual(data);
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const card = new Card();
|
||||
card.cardholderName = mockEnc("cardHolder");
|
||||
card.brand = mockEnc("brand");
|
||||
card.number = mockEnc("number");
|
||||
card.expMonth = mockEnc("expMonth");
|
||||
card.expYear = mockEnc("expYear");
|
||||
card.code = mockEnc("code");
|
||||
|
||||
const view = await card.decrypt(null);
|
||||
|
||||
expect(view).toEqual({
|
||||
_brand: "brand",
|
||||
_number: "number",
|
||||
_subTitle: null,
|
||||
cardholderName: "cardHolder",
|
||||
code: "code",
|
||||
expMonth: "expMonth",
|
||||
expYear: "expYear",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,599 +0,0 @@
|
||||
import { Substitute, Arg } from "@fluffy-spoon/substitute";
|
||||
|
||||
import { CipherRepromptType } from "@/jslib/common/src/enums/cipherRepromptType";
|
||||
import { CipherType } from "@/jslib/common/src/enums/cipherType";
|
||||
import { FieldType } from "@/jslib/common/src/enums/fieldType";
|
||||
import { SecureNoteType } from "@/jslib/common/src/enums/secureNoteType";
|
||||
import { UriMatchType } from "@/jslib/common/src/enums/uriMatchType";
|
||||
import { CipherData } from "@/jslib/common/src/models/data/cipherData";
|
||||
import { Card } from "@/jslib/common/src/models/domain/card";
|
||||
import { Cipher } from "@/jslib/common/src/models/domain/cipher";
|
||||
import { Identity } from "@/jslib/common/src/models/domain/identity";
|
||||
import { Login } from "@/jslib/common/src/models/domain/login";
|
||||
import { SecureNote } from "@/jslib/common/src/models/domain/secureNote";
|
||||
import { CardView } from "@/jslib/common/src/models/view/cardView";
|
||||
import { IdentityView } from "@/jslib/common/src/models/view/identityView";
|
||||
import { LoginView } from "@/jslib/common/src/models/view/loginView";
|
||||
|
||||
import { mockEnc } from "../utils";
|
||||
|
||||
describe("Cipher DTO", () => {
|
||||
it("Convert from empty CipherData", () => {
|
||||
const data = new CipherData();
|
||||
const cipher = new Cipher(data);
|
||||
|
||||
expect(cipher).toEqual({
|
||||
id: null,
|
||||
userId: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: null,
|
||||
notes: null,
|
||||
type: undefined,
|
||||
favorite: undefined,
|
||||
organizationUseTotp: undefined,
|
||||
edit: undefined,
|
||||
viewPassword: true,
|
||||
revisionDate: null,
|
||||
collectionIds: undefined,
|
||||
localData: null,
|
||||
deletedDate: null,
|
||||
reprompt: undefined,
|
||||
attachments: null,
|
||||
fields: null,
|
||||
passwordHistory: null,
|
||||
});
|
||||
});
|
||||
|
||||
describe("LoginCipher", () => {
|
||||
let cipherData: CipherData;
|
||||
|
||||
beforeEach(() => {
|
||||
cipherData = {
|
||||
id: "id",
|
||||
organizationId: "orgId",
|
||||
folderId: "folderId",
|
||||
userId: "userId",
|
||||
edit: true,
|
||||
viewPassword: true,
|
||||
organizationUseTotp: true,
|
||||
favorite: false,
|
||||
revisionDate: "2022-01-31T12:00:00.000Z",
|
||||
type: CipherType.Login,
|
||||
name: "EncryptedString",
|
||||
notes: "EncryptedString",
|
||||
deletedDate: null,
|
||||
reprompt: CipherRepromptType.None,
|
||||
login: {
|
||||
uris: [{ uri: "EncryptedString", match: UriMatchType.Domain }],
|
||||
username: "EncryptedString",
|
||||
password: "EncryptedString",
|
||||
passwordRevisionDate: "2022-01-31T12:00:00.000Z",
|
||||
totp: "EncryptedString",
|
||||
autofillOnPageLoad: false,
|
||||
},
|
||||
passwordHistory: [
|
||||
{ password: "EncryptedString", lastUsedDate: "2022-01-31T12:00:00.000Z" },
|
||||
],
|
||||
attachments: [
|
||||
{
|
||||
id: "a1",
|
||||
url: "url",
|
||||
size: "1100",
|
||||
sizeName: "1.1 KB",
|
||||
fileName: "file",
|
||||
key: "EncKey",
|
||||
},
|
||||
{
|
||||
id: "a2",
|
||||
url: "url",
|
||||
size: "1100",
|
||||
sizeName: "1.1 KB",
|
||||
fileName: "file",
|
||||
key: "EncKey",
|
||||
},
|
||||
],
|
||||
fields: [
|
||||
{
|
||||
name: "EncryptedString",
|
||||
value: "EncryptedString",
|
||||
type: FieldType.Text,
|
||||
linkedId: null,
|
||||
},
|
||||
{
|
||||
name: "EncryptedString",
|
||||
value: "EncryptedString",
|
||||
type: FieldType.Hidden,
|
||||
linkedId: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const cipher = new Cipher(cipherData);
|
||||
|
||||
expect(cipher).toEqual({
|
||||
id: "id",
|
||||
userId: "userId",
|
||||
organizationId: "orgId",
|
||||
folderId: "folderId",
|
||||
name: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
notes: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
type: 1,
|
||||
favorite: false,
|
||||
organizationUseTotp: true,
|
||||
edit: true,
|
||||
viewPassword: true,
|
||||
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
collectionIds: undefined,
|
||||
localData: null,
|
||||
deletedDate: null,
|
||||
reprompt: 0,
|
||||
login: {
|
||||
passwordRevisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
autofillOnPageLoad: false,
|
||||
username: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
password: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
totp: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
uris: [{ match: 0, uri: { encryptedString: "EncryptedString", encryptionType: 0 } }],
|
||||
},
|
||||
attachments: [
|
||||
{
|
||||
fileName: { encryptedString: "file", encryptionType: 0 },
|
||||
id: "a1",
|
||||
key: { encryptedString: "EncKey", encryptionType: 0 },
|
||||
size: "1100",
|
||||
sizeName: "1.1 KB",
|
||||
url: "url",
|
||||
},
|
||||
{
|
||||
fileName: { encryptedString: "file", encryptionType: 0 },
|
||||
id: "a2",
|
||||
key: { encryptedString: "EncKey", encryptionType: 0 },
|
||||
size: "1100",
|
||||
sizeName: "1.1 KB",
|
||||
url: "url",
|
||||
},
|
||||
],
|
||||
fields: [
|
||||
{
|
||||
linkedId: null,
|
||||
name: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
type: 0,
|
||||
value: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
},
|
||||
{
|
||||
linkedId: null,
|
||||
name: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
type: 1,
|
||||
value: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
},
|
||||
],
|
||||
passwordHistory: [
|
||||
{
|
||||
lastUsedDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
password: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("toCipherData", () => {
|
||||
const cipher = new Cipher(cipherData);
|
||||
expect(cipher.toCipherData("userId")).toEqual(cipherData);
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const cipher = new Cipher();
|
||||
cipher.id = "id";
|
||||
cipher.organizationId = "orgId";
|
||||
cipher.folderId = "folderId";
|
||||
cipher.edit = true;
|
||||
cipher.viewPassword = true;
|
||||
cipher.organizationUseTotp = true;
|
||||
cipher.favorite = false;
|
||||
cipher.revisionDate = new Date("2022-01-31T12:00:00.000Z");
|
||||
cipher.type = CipherType.Login;
|
||||
cipher.name = mockEnc("EncryptedString");
|
||||
cipher.notes = mockEnc("EncryptedString");
|
||||
cipher.deletedDate = null;
|
||||
cipher.reprompt = CipherRepromptType.None;
|
||||
|
||||
const loginView = new LoginView();
|
||||
loginView.username = "username";
|
||||
loginView.password = "password";
|
||||
|
||||
const login = Substitute.for<Login>();
|
||||
login.decrypt(Arg.any(), Arg.any()).resolves(loginView);
|
||||
cipher.login = login;
|
||||
|
||||
const cipherView = await cipher.decrypt();
|
||||
|
||||
expect(cipherView).toMatchObject({
|
||||
id: "id",
|
||||
organizationId: "orgId",
|
||||
folderId: "folderId",
|
||||
name: "EncryptedString",
|
||||
notes: "EncryptedString",
|
||||
type: 1,
|
||||
favorite: false,
|
||||
organizationUseTotp: true,
|
||||
edit: true,
|
||||
viewPassword: true,
|
||||
login: loginView,
|
||||
attachments: null,
|
||||
fields: null,
|
||||
passwordHistory: null,
|
||||
collectionIds: undefined,
|
||||
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
deletedDate: null,
|
||||
reprompt: 0,
|
||||
localData: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("SecureNoteCipher", () => {
|
||||
let cipherData: CipherData;
|
||||
|
||||
beforeEach(() => {
|
||||
cipherData = {
|
||||
id: "id",
|
||||
organizationId: "orgId",
|
||||
folderId: "folderId",
|
||||
userId: "userId",
|
||||
edit: true,
|
||||
viewPassword: true,
|
||||
organizationUseTotp: true,
|
||||
favorite: false,
|
||||
revisionDate: "2022-01-31T12:00:00.000Z",
|
||||
type: CipherType.SecureNote,
|
||||
name: "EncryptedString",
|
||||
notes: "EncryptedString",
|
||||
deletedDate: null,
|
||||
reprompt: CipherRepromptType.None,
|
||||
secureNote: {
|
||||
type: SecureNoteType.Generic,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const cipher = new Cipher(cipherData);
|
||||
|
||||
expect(cipher).toEqual({
|
||||
id: "id",
|
||||
userId: "userId",
|
||||
organizationId: "orgId",
|
||||
folderId: "folderId",
|
||||
name: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
notes: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
type: 2,
|
||||
favorite: false,
|
||||
organizationUseTotp: true,
|
||||
edit: true,
|
||||
viewPassword: true,
|
||||
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
collectionIds: undefined,
|
||||
localData: null,
|
||||
deletedDate: null,
|
||||
reprompt: 0,
|
||||
secureNote: { type: SecureNoteType.Generic },
|
||||
attachments: null,
|
||||
fields: null,
|
||||
passwordHistory: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("toCipherData", () => {
|
||||
const cipher = new Cipher(cipherData);
|
||||
expect(cipher.toCipherData("userId")).toEqual(cipherData);
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const cipher = new Cipher();
|
||||
cipher.id = "id";
|
||||
cipher.organizationId = "orgId";
|
||||
cipher.folderId = "folderId";
|
||||
cipher.edit = true;
|
||||
cipher.viewPassword = true;
|
||||
cipher.organizationUseTotp = true;
|
||||
cipher.favorite = false;
|
||||
cipher.revisionDate = new Date("2022-01-31T12:00:00.000Z");
|
||||
cipher.type = CipherType.SecureNote;
|
||||
cipher.name = mockEnc("EncryptedString");
|
||||
cipher.notes = mockEnc("EncryptedString");
|
||||
cipher.deletedDate = null;
|
||||
cipher.reprompt = CipherRepromptType.None;
|
||||
cipher.secureNote = new SecureNote();
|
||||
cipher.secureNote.type = SecureNoteType.Generic;
|
||||
|
||||
const cipherView = await cipher.decrypt();
|
||||
|
||||
expect(cipherView).toMatchObject({
|
||||
id: "id",
|
||||
organizationId: "orgId",
|
||||
folderId: "folderId",
|
||||
name: "EncryptedString",
|
||||
notes: "EncryptedString",
|
||||
type: 2,
|
||||
favorite: false,
|
||||
organizationUseTotp: true,
|
||||
edit: true,
|
||||
viewPassword: true,
|
||||
secureNote: { type: 0 },
|
||||
attachments: null,
|
||||
fields: null,
|
||||
passwordHistory: null,
|
||||
collectionIds: undefined,
|
||||
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
deletedDate: null,
|
||||
reprompt: 0,
|
||||
localData: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("CardCipher", () => {
|
||||
let cipherData: CipherData;
|
||||
|
||||
beforeEach(() => {
|
||||
cipherData = {
|
||||
id: "id",
|
||||
organizationId: "orgId",
|
||||
folderId: "folderId",
|
||||
userId: "userId",
|
||||
edit: true,
|
||||
viewPassword: true,
|
||||
organizationUseTotp: true,
|
||||
favorite: false,
|
||||
revisionDate: "2022-01-31T12:00:00.000Z",
|
||||
type: CipherType.Card,
|
||||
name: "EncryptedString",
|
||||
notes: "EncryptedString",
|
||||
deletedDate: null,
|
||||
reprompt: CipherRepromptType.None,
|
||||
card: {
|
||||
cardholderName: "EncryptedString",
|
||||
brand: "EncryptedString",
|
||||
number: "EncryptedString",
|
||||
expMonth: "EncryptedString",
|
||||
expYear: "EncryptedString",
|
||||
code: "EncryptedString",
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const cipher = new Cipher(cipherData);
|
||||
|
||||
expect(cipher).toEqual({
|
||||
id: "id",
|
||||
userId: "userId",
|
||||
organizationId: "orgId",
|
||||
folderId: "folderId",
|
||||
name: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
notes: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
type: 3,
|
||||
favorite: false,
|
||||
organizationUseTotp: true,
|
||||
edit: true,
|
||||
viewPassword: true,
|
||||
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
collectionIds: undefined,
|
||||
localData: null,
|
||||
deletedDate: null,
|
||||
reprompt: 0,
|
||||
card: {
|
||||
cardholderName: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
brand: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
number: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
expMonth: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
expYear: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
code: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
},
|
||||
attachments: null,
|
||||
fields: null,
|
||||
passwordHistory: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("toCipherData", () => {
|
||||
const cipher = new Cipher(cipherData);
|
||||
expect(cipher.toCipherData("userId")).toEqual(cipherData);
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const cipher = new Cipher();
|
||||
cipher.id = "id";
|
||||
cipher.organizationId = "orgId";
|
||||
cipher.folderId = "folderId";
|
||||
cipher.edit = true;
|
||||
cipher.viewPassword = true;
|
||||
cipher.organizationUseTotp = true;
|
||||
cipher.favorite = false;
|
||||
cipher.revisionDate = new Date("2022-01-31T12:00:00.000Z");
|
||||
cipher.type = CipherType.Card;
|
||||
cipher.name = mockEnc("EncryptedString");
|
||||
cipher.notes = mockEnc("EncryptedString");
|
||||
cipher.deletedDate = null;
|
||||
cipher.reprompt = CipherRepromptType.None;
|
||||
|
||||
const cardView = new CardView();
|
||||
cardView.cardholderName = "cardholderName";
|
||||
cardView.number = "4111111111111111";
|
||||
|
||||
const card = Substitute.for<Card>();
|
||||
card.decrypt(Arg.any(), Arg.any()).resolves(cardView);
|
||||
cipher.card = card;
|
||||
|
||||
const cipherView = await cipher.decrypt();
|
||||
|
||||
expect(cipherView).toMatchObject({
|
||||
id: "id",
|
||||
organizationId: "orgId",
|
||||
folderId: "folderId",
|
||||
name: "EncryptedString",
|
||||
notes: "EncryptedString",
|
||||
type: 3,
|
||||
favorite: false,
|
||||
organizationUseTotp: true,
|
||||
edit: true,
|
||||
viewPassword: true,
|
||||
card: cardView,
|
||||
attachments: null,
|
||||
fields: null,
|
||||
passwordHistory: null,
|
||||
collectionIds: undefined,
|
||||
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
deletedDate: null,
|
||||
reprompt: 0,
|
||||
localData: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("IdentityCipher", () => {
|
||||
let cipherData: CipherData;
|
||||
|
||||
beforeEach(() => {
|
||||
cipherData = {
|
||||
id: "id",
|
||||
organizationId: "orgId",
|
||||
folderId: "folderId",
|
||||
userId: "userId",
|
||||
edit: true,
|
||||
viewPassword: true,
|
||||
organizationUseTotp: true,
|
||||
favorite: false,
|
||||
revisionDate: "2022-01-31T12:00:00.000Z",
|
||||
type: CipherType.Identity,
|
||||
name: "EncryptedString",
|
||||
notes: "EncryptedString",
|
||||
deletedDate: null,
|
||||
reprompt: CipherRepromptType.None,
|
||||
identity: {
|
||||
title: "EncryptedString",
|
||||
firstName: "EncryptedString",
|
||||
middleName: "EncryptedString",
|
||||
lastName: "EncryptedString",
|
||||
address1: "EncryptedString",
|
||||
address2: "EncryptedString",
|
||||
address3: "EncryptedString",
|
||||
city: "EncryptedString",
|
||||
state: "EncryptedString",
|
||||
postalCode: "EncryptedString",
|
||||
country: "EncryptedString",
|
||||
company: "EncryptedString",
|
||||
email: "EncryptedString",
|
||||
phone: "EncryptedString",
|
||||
ssn: "EncryptedString",
|
||||
username: "EncryptedString",
|
||||
passportNumber: "EncryptedString",
|
||||
licenseNumber: "EncryptedString",
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const cipher = new Cipher(cipherData);
|
||||
|
||||
expect(cipher).toEqual({
|
||||
id: "id",
|
||||
userId: "userId",
|
||||
organizationId: "orgId",
|
||||
folderId: "folderId",
|
||||
name: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
notes: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
type: 4,
|
||||
favorite: false,
|
||||
organizationUseTotp: true,
|
||||
edit: true,
|
||||
viewPassword: true,
|
||||
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
collectionIds: undefined,
|
||||
localData: null,
|
||||
deletedDate: null,
|
||||
reprompt: 0,
|
||||
identity: {
|
||||
title: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
firstName: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
middleName: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
lastName: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
address1: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
address2: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
address3: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
city: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
state: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
postalCode: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
country: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
company: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
email: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
phone: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
ssn: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
username: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
passportNumber: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
licenseNumber: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
},
|
||||
attachments: null,
|
||||
fields: null,
|
||||
passwordHistory: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("toCipherData", () => {
|
||||
const cipher = new Cipher(cipherData);
|
||||
expect(cipher.toCipherData("userId")).toEqual(cipherData);
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const cipher = new Cipher();
|
||||
cipher.id = "id";
|
||||
cipher.organizationId = "orgId";
|
||||
cipher.folderId = "folderId";
|
||||
cipher.edit = true;
|
||||
cipher.viewPassword = true;
|
||||
cipher.organizationUseTotp = true;
|
||||
cipher.favorite = false;
|
||||
cipher.revisionDate = new Date("2022-01-31T12:00:00.000Z");
|
||||
cipher.type = CipherType.Identity;
|
||||
cipher.name = mockEnc("EncryptedString");
|
||||
cipher.notes = mockEnc("EncryptedString");
|
||||
cipher.deletedDate = null;
|
||||
cipher.reprompt = CipherRepromptType.None;
|
||||
|
||||
const identityView = new IdentityView();
|
||||
identityView.firstName = "firstName";
|
||||
identityView.lastName = "lastName";
|
||||
|
||||
const identity = Substitute.for<Identity>();
|
||||
identity.decrypt(Arg.any(), Arg.any()).resolves(identityView);
|
||||
cipher.identity = identity;
|
||||
|
||||
const cipherView = await cipher.decrypt();
|
||||
|
||||
expect(cipherView).toMatchObject({
|
||||
id: "id",
|
||||
organizationId: "orgId",
|
||||
folderId: "folderId",
|
||||
name: "EncryptedString",
|
||||
notes: "EncryptedString",
|
||||
type: 4,
|
||||
favorite: false,
|
||||
organizationUseTotp: true,
|
||||
edit: true,
|
||||
viewPassword: true,
|
||||
identity: identityView,
|
||||
attachments: null,
|
||||
fields: null,
|
||||
passwordHistory: null,
|
||||
collectionIds: undefined,
|
||||
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
deletedDate: null,
|
||||
reprompt: 0,
|
||||
localData: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,66 +0,0 @@
|
||||
import { CollectionData } from "@/jslib/common/src/models/data/collectionData";
|
||||
import { Collection } from "@/jslib/common/src/models/domain/collection";
|
||||
|
||||
import { mockEnc } from "../utils";
|
||||
|
||||
describe("Collection", () => {
|
||||
let data: CollectionData;
|
||||
|
||||
beforeEach(() => {
|
||||
data = {
|
||||
id: "id",
|
||||
organizationId: "orgId",
|
||||
name: "encName",
|
||||
externalId: "extId",
|
||||
readOnly: true,
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert from empty", () => {
|
||||
const data = new CollectionData({} as any);
|
||||
const card = new Collection(data);
|
||||
|
||||
expect(card).toEqual({
|
||||
externalId: null,
|
||||
hidePasswords: null,
|
||||
id: null,
|
||||
name: null,
|
||||
organizationId: null,
|
||||
readOnly: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const collection = new Collection(data);
|
||||
|
||||
expect(collection).toEqual({
|
||||
id: "id",
|
||||
organizationId: "orgId",
|
||||
name: { encryptedString: "encName", encryptionType: 0 },
|
||||
externalId: "extId",
|
||||
readOnly: true,
|
||||
hidePasswords: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const collection = new Collection();
|
||||
collection.id = "id";
|
||||
collection.organizationId = "orgId";
|
||||
collection.name = mockEnc("encName");
|
||||
collection.externalId = "extId";
|
||||
collection.readOnly = false;
|
||||
collection.hidePasswords = false;
|
||||
|
||||
const view = await collection.decrypt();
|
||||
|
||||
expect(view).toEqual({
|
||||
externalId: "extId",
|
||||
hidePasswords: false,
|
||||
id: "id",
|
||||
name: "encName",
|
||||
organizationId: "orgId",
|
||||
readOnly: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,64 +0,0 @@
|
||||
import { FieldType } from "@/jslib/common/src/enums/fieldType";
|
||||
import { FieldData } from "@/jslib/common/src/models/data/fieldData";
|
||||
import { Field } from "@/jslib/common/src/models/domain/field";
|
||||
|
||||
import { mockEnc } from "../utils";
|
||||
|
||||
describe("Field", () => {
|
||||
let data: FieldData;
|
||||
|
||||
beforeEach(() => {
|
||||
data = {
|
||||
type: FieldType.Text,
|
||||
name: "encName",
|
||||
value: "encValue",
|
||||
linkedId: null,
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert from empty", () => {
|
||||
const data = new FieldData();
|
||||
const field = new Field(data);
|
||||
|
||||
expect(field).toEqual({
|
||||
type: undefined,
|
||||
name: null,
|
||||
value: null,
|
||||
linkedId: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const field = new Field(data);
|
||||
|
||||
expect(field).toEqual({
|
||||
type: FieldType.Text,
|
||||
name: { encryptedString: "encName", encryptionType: 0 },
|
||||
value: { encryptedString: "encValue", encryptionType: 0 },
|
||||
linkedId: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("toFieldData", () => {
|
||||
const field = new Field(data);
|
||||
expect(field.toFieldData()).toEqual(data);
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const field = new Field();
|
||||
field.type = FieldType.Text;
|
||||
field.name = mockEnc("encName");
|
||||
field.value = mockEnc("encValue");
|
||||
|
||||
const view = await field.decrypt(null);
|
||||
|
||||
expect(view).toEqual({
|
||||
type: 0,
|
||||
name: "encName",
|
||||
value: "encValue",
|
||||
newField: false,
|
||||
showCount: false,
|
||||
showValue: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,42 +0,0 @@
|
||||
import { FolderData } from "@/jslib/common/src/models/data/folderData";
|
||||
import { Folder } from "@/jslib/common/src/models/domain/folder";
|
||||
|
||||
import { mockEnc } from "../utils";
|
||||
|
||||
describe("Folder", () => {
|
||||
let data: FolderData;
|
||||
|
||||
beforeEach(() => {
|
||||
data = {
|
||||
id: "id",
|
||||
userId: "userId",
|
||||
name: "encName",
|
||||
revisionDate: "2022-01-31T12:00:00.000Z",
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const field = new Folder(data);
|
||||
|
||||
expect(field).toEqual({
|
||||
id: "id",
|
||||
name: { encryptedString: "encName", encryptionType: 0 },
|
||||
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
});
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const folder = new Folder();
|
||||
folder.id = "id";
|
||||
folder.name = mockEnc("encName");
|
||||
folder.revisionDate = new Date("2022-01-31T12:00:00.000Z");
|
||||
|
||||
const view = await folder.decrypt();
|
||||
|
||||
expect(view).toEqual({
|
||||
id: "id",
|
||||
name: "encName",
|
||||
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,134 +0,0 @@
|
||||
import { IdentityData } from "@/jslib/common/src/models/data/identityData";
|
||||
import { Identity } from "@/jslib/common/src/models/domain/identity";
|
||||
|
||||
import { mockEnc } from "../utils";
|
||||
|
||||
describe("Identity", () => {
|
||||
let data: IdentityData;
|
||||
|
||||
beforeEach(() => {
|
||||
data = {
|
||||
title: "enctitle",
|
||||
firstName: "encfirstName",
|
||||
middleName: "encmiddleName",
|
||||
lastName: "enclastName",
|
||||
address1: "encaddress1",
|
||||
address2: "encaddress2",
|
||||
address3: "encaddress3",
|
||||
city: "enccity",
|
||||
state: "encstate",
|
||||
postalCode: "encpostalCode",
|
||||
country: "enccountry",
|
||||
company: "enccompany",
|
||||
email: "encemail",
|
||||
phone: "encphone",
|
||||
ssn: "encssn",
|
||||
username: "encusername",
|
||||
passportNumber: "encpassportNumber",
|
||||
licenseNumber: "enclicenseNumber",
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert from empty", () => {
|
||||
const data = new IdentityData();
|
||||
const identity = new Identity(data);
|
||||
|
||||
expect(identity).toEqual({
|
||||
address1: null,
|
||||
address2: null,
|
||||
address3: null,
|
||||
city: null,
|
||||
company: null,
|
||||
country: null,
|
||||
email: null,
|
||||
firstName: null,
|
||||
lastName: null,
|
||||
licenseNumber: null,
|
||||
middleName: null,
|
||||
passportNumber: null,
|
||||
phone: null,
|
||||
postalCode: null,
|
||||
ssn: null,
|
||||
state: null,
|
||||
title: null,
|
||||
username: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const identity = new Identity(data);
|
||||
|
||||
expect(identity).toEqual({
|
||||
title: { encryptedString: "enctitle", encryptionType: 0 },
|
||||
firstName: { encryptedString: "encfirstName", encryptionType: 0 },
|
||||
middleName: { encryptedString: "encmiddleName", encryptionType: 0 },
|
||||
lastName: { encryptedString: "enclastName", encryptionType: 0 },
|
||||
address1: { encryptedString: "encaddress1", encryptionType: 0 },
|
||||
address2: { encryptedString: "encaddress2", encryptionType: 0 },
|
||||
address3: { encryptedString: "encaddress3", encryptionType: 0 },
|
||||
city: { encryptedString: "enccity", encryptionType: 0 },
|
||||
state: { encryptedString: "encstate", encryptionType: 0 },
|
||||
postalCode: { encryptedString: "encpostalCode", encryptionType: 0 },
|
||||
country: { encryptedString: "enccountry", encryptionType: 0 },
|
||||
company: { encryptedString: "enccompany", encryptionType: 0 },
|
||||
email: { encryptedString: "encemail", encryptionType: 0 },
|
||||
phone: { encryptedString: "encphone", encryptionType: 0 },
|
||||
ssn: { encryptedString: "encssn", encryptionType: 0 },
|
||||
username: { encryptedString: "encusername", encryptionType: 0 },
|
||||
passportNumber: { encryptedString: "encpassportNumber", encryptionType: 0 },
|
||||
licenseNumber: { encryptedString: "enclicenseNumber", encryptionType: 0 },
|
||||
});
|
||||
});
|
||||
|
||||
it("toIdentityData", () => {
|
||||
const identity = new Identity(data);
|
||||
expect(identity.toIdentityData()).toEqual(data);
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const identity = new Identity();
|
||||
|
||||
identity.title = mockEnc("mockTitle");
|
||||
identity.firstName = mockEnc("mockFirstName");
|
||||
identity.middleName = mockEnc("mockMiddleName");
|
||||
identity.lastName = mockEnc("mockLastName");
|
||||
identity.address1 = mockEnc("mockAddress1");
|
||||
identity.address2 = mockEnc("mockAddress2");
|
||||
identity.address3 = mockEnc("mockAddress3");
|
||||
identity.city = mockEnc("mockCity");
|
||||
identity.state = mockEnc("mockState");
|
||||
identity.postalCode = mockEnc("mockPostalCode");
|
||||
identity.country = mockEnc("mockCountry");
|
||||
identity.company = mockEnc("mockCompany");
|
||||
identity.email = mockEnc("mockEmail");
|
||||
identity.phone = mockEnc("mockPhone");
|
||||
identity.ssn = mockEnc("mockSsn");
|
||||
identity.username = mockEnc("mockUsername");
|
||||
identity.passportNumber = mockEnc("mockPassportNumber");
|
||||
identity.licenseNumber = mockEnc("mockLicenseNumber");
|
||||
|
||||
const view = await identity.decrypt(null);
|
||||
|
||||
expect(view).toEqual({
|
||||
_firstName: "mockFirstName",
|
||||
_lastName: "mockLastName",
|
||||
_subTitle: null,
|
||||
address1: "mockAddress1",
|
||||
address2: "mockAddress2",
|
||||
address3: "mockAddress3",
|
||||
city: "mockCity",
|
||||
company: "mockCompany",
|
||||
country: "mockCountry",
|
||||
email: "mockEmail",
|
||||
licenseNumber: "mockLicenseNumber",
|
||||
middleName: "mockMiddleName",
|
||||
passportNumber: "mockPassportNumber",
|
||||
phone: "mockPhone",
|
||||
postalCode: "mockPostalCode",
|
||||
ssn: "mockSsn",
|
||||
state: "mockState",
|
||||
title: "mockTitle",
|
||||
username: "mockUsername",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,101 +0,0 @@
|
||||
import { Substitute, Arg } from "@fluffy-spoon/substitute";
|
||||
|
||||
import { UriMatchType } from "@/jslib/common/src/enums/uriMatchType";
|
||||
import { LoginData } from "@/jslib/common/src/models/data/loginData";
|
||||
import { Login } from "@/jslib/common/src/models/domain/login";
|
||||
import { LoginUri } from "@/jslib/common/src/models/domain/loginUri";
|
||||
import { LoginUriView } from "@/jslib/common/src/models/view/loginUriView";
|
||||
|
||||
import { mockEnc } from "../utils";
|
||||
|
||||
describe("Login DTO", () => {
|
||||
it("Convert from empty LoginData", () => {
|
||||
const data = new LoginData();
|
||||
const login = new Login(data);
|
||||
|
||||
expect(login).toEqual({
|
||||
passwordRevisionDate: null,
|
||||
autofillOnPageLoad: undefined,
|
||||
username: null,
|
||||
password: null,
|
||||
totp: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("Convert from full LoginData", () => {
|
||||
const data: LoginData = {
|
||||
uris: [{ uri: "uri", match: UriMatchType.Domain }],
|
||||
username: "username",
|
||||
password: "password",
|
||||
passwordRevisionDate: "2022-01-31T12:00:00.000Z",
|
||||
totp: "123",
|
||||
autofillOnPageLoad: false,
|
||||
};
|
||||
const login = new Login(data);
|
||||
|
||||
expect(login).toEqual({
|
||||
passwordRevisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
autofillOnPageLoad: false,
|
||||
username: { encryptedString: "username", encryptionType: 0 },
|
||||
password: { encryptedString: "password", encryptionType: 0 },
|
||||
totp: { encryptedString: "123", encryptionType: 0 },
|
||||
uris: [{ match: 0, uri: { encryptedString: "uri", encryptionType: 0 } }],
|
||||
});
|
||||
});
|
||||
|
||||
it("Initialize without LoginData", () => {
|
||||
const login = new Login();
|
||||
|
||||
expect(login).toEqual({});
|
||||
});
|
||||
|
||||
it("Decrypts correctly", async () => {
|
||||
const loginUri = Substitute.for<LoginUri>();
|
||||
const loginUriView = new LoginUriView();
|
||||
loginUriView.uri = "decrypted uri";
|
||||
loginUri.decrypt(Arg.any()).resolves(loginUriView);
|
||||
|
||||
const login = new Login();
|
||||
login.uris = [loginUri];
|
||||
login.username = mockEnc("encrypted username");
|
||||
login.password = mockEnc("encrypted password");
|
||||
login.passwordRevisionDate = new Date("2022-01-31T12:00:00.000Z");
|
||||
login.totp = mockEnc("encrypted totp");
|
||||
login.autofillOnPageLoad = true;
|
||||
|
||||
const loginView = await login.decrypt(null);
|
||||
expect(loginView).toEqual({
|
||||
username: "encrypted username",
|
||||
password: "encrypted password",
|
||||
passwordRevisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
totp: "encrypted totp",
|
||||
uris: [
|
||||
{
|
||||
match: null,
|
||||
_uri: "decrypted uri",
|
||||
_domain: null,
|
||||
_hostname: null,
|
||||
_host: null,
|
||||
_canLaunch: null,
|
||||
},
|
||||
],
|
||||
autofillOnPageLoad: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("Converts from LoginData and back", () => {
|
||||
const data: LoginData = {
|
||||
uris: [{ uri: "uri", match: UriMatchType.Domain }],
|
||||
username: "username",
|
||||
password: "password",
|
||||
passwordRevisionDate: "2022-01-31T12:00:00.000Z",
|
||||
totp: "123",
|
||||
autofillOnPageLoad: false,
|
||||
};
|
||||
const login = new Login(data);
|
||||
|
||||
const loginData = login.toLoginData();
|
||||
|
||||
expect(loginData).toEqual(data);
|
||||
});
|
||||
});
|
||||
@@ -1,57 +0,0 @@
|
||||
import { UriMatchType } from "@/jslib/common/src/enums/uriMatchType";
|
||||
import { LoginUriData } from "@/jslib/common/src/models/data/loginUriData";
|
||||
import { LoginUri } from "@/jslib/common/src/models/domain/loginUri";
|
||||
|
||||
import { mockEnc } from "../utils";
|
||||
|
||||
describe("LoginUri", () => {
|
||||
let data: LoginUriData;
|
||||
|
||||
beforeEach(() => {
|
||||
data = {
|
||||
uri: "encUri",
|
||||
match: UriMatchType.Domain,
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert from empty", () => {
|
||||
const data = new LoginUriData();
|
||||
const loginUri = new LoginUri(data);
|
||||
|
||||
expect(loginUri).toEqual({
|
||||
match: null,
|
||||
uri: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const loginUri = new LoginUri(data);
|
||||
|
||||
expect(loginUri).toEqual({
|
||||
match: 0,
|
||||
uri: { encryptedString: "encUri", encryptionType: 0 },
|
||||
});
|
||||
});
|
||||
|
||||
it("toLoginUriData", () => {
|
||||
const loginUri = new LoginUri(data);
|
||||
expect(loginUri.toLoginUriData()).toEqual(data);
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const loginUri = new LoginUri();
|
||||
loginUri.match = UriMatchType.Exact;
|
||||
loginUri.uri = mockEnc("uri");
|
||||
|
||||
const view = await loginUri.decrypt(null);
|
||||
|
||||
expect(view).toEqual({
|
||||
_canLaunch: null,
|
||||
_domain: null,
|
||||
_host: null,
|
||||
_hostname: null,
|
||||
_uri: "uri",
|
||||
match: 3,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,51 +0,0 @@
|
||||
import { PasswordHistoryData } from "@/jslib/common/src/models/data/passwordHistoryData";
|
||||
import { Password } from "@/jslib/common/src/models/domain/password";
|
||||
|
||||
import { mockEnc } from "../utils";
|
||||
|
||||
describe("Password", () => {
|
||||
let data: PasswordHistoryData;
|
||||
|
||||
beforeEach(() => {
|
||||
data = {
|
||||
password: "encPassword",
|
||||
lastUsedDate: "2022-01-31T12:00:00.000Z",
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert from empty", () => {
|
||||
const data = new PasswordHistoryData();
|
||||
const password = new Password(data);
|
||||
|
||||
expect(password).toMatchObject({
|
||||
password: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const password = new Password(data);
|
||||
|
||||
expect(password).toEqual({
|
||||
password: { encryptedString: "encPassword", encryptionType: 0 },
|
||||
lastUsedDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
});
|
||||
});
|
||||
|
||||
it("toPasswordHistoryData", () => {
|
||||
const password = new Password(data);
|
||||
expect(password.toPasswordHistoryData()).toEqual(data);
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const password = new Password();
|
||||
password.password = mockEnc("password");
|
||||
password.lastUsedDate = new Date("2022-01-31T12:00:00.000Z");
|
||||
|
||||
const view = await password.decrypt(null);
|
||||
|
||||
expect(view).toEqual({
|
||||
password: "password",
|
||||
lastUsedDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,46 +0,0 @@
|
||||
import { SecureNoteType } from "@/jslib/common/src/enums/secureNoteType";
|
||||
import { SecureNoteData } from "@/jslib/common/src/models/data/secureNoteData";
|
||||
import { SecureNote } from "@/jslib/common/src/models/domain/secureNote";
|
||||
|
||||
describe("SecureNote", () => {
|
||||
let data: SecureNoteData;
|
||||
|
||||
beforeEach(() => {
|
||||
data = {
|
||||
type: SecureNoteType.Generic,
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert from empty", () => {
|
||||
const data = new SecureNoteData();
|
||||
const secureNote = new SecureNote(data);
|
||||
|
||||
expect(secureNote).toEqual({
|
||||
type: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const secureNote = new SecureNote(data);
|
||||
|
||||
expect(secureNote).toEqual({
|
||||
type: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it("toSecureNoteData", () => {
|
||||
const secureNote = new SecureNote(data);
|
||||
expect(secureNote.toSecureNoteData()).toEqual(data);
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const secureNote = new SecureNote();
|
||||
secureNote.type = SecureNoteType.Generic;
|
||||
|
||||
const view = await secureNote.decrypt(null);
|
||||
|
||||
expect(view).toEqual({
|
||||
type: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,144 +0,0 @@
|
||||
import { Substitute, Arg, SubstituteOf } from "@fluffy-spoon/substitute";
|
||||
|
||||
import { CryptoService } from "@/jslib/common/src/abstractions/crypto.service";
|
||||
import { SendType } from "@/jslib/common/src/enums/sendType";
|
||||
import { SendData } from "@/jslib/common/src/models/data/sendData";
|
||||
import { EncString } from "@/jslib/common/src/models/domain/encString";
|
||||
import { Send } from "@/jslib/common/src/models/domain/send";
|
||||
import { SendText } from "@/jslib/common/src/models/domain/sendText";
|
||||
import { ContainerService } from "@/jslib/common/src/services/container.service";
|
||||
|
||||
import { makeStaticByteArray, mockEnc } from "../utils";
|
||||
|
||||
describe("Send", () => {
|
||||
let data: SendData;
|
||||
|
||||
beforeEach(() => {
|
||||
data = {
|
||||
id: "id",
|
||||
accessId: "accessId",
|
||||
userId: "userId",
|
||||
type: SendType.Text,
|
||||
name: "encName",
|
||||
notes: "encNotes",
|
||||
text: {
|
||||
text: "encText",
|
||||
hidden: true,
|
||||
},
|
||||
file: null,
|
||||
key: "encKey",
|
||||
maxAccessCount: null,
|
||||
accessCount: 10,
|
||||
revisionDate: "2022-01-31T12:00:00.000Z",
|
||||
expirationDate: "2022-01-31T12:00:00.000Z",
|
||||
deletionDate: "2022-01-31T12:00:00.000Z",
|
||||
password: "password",
|
||||
disabled: false,
|
||||
hideEmail: true,
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert from empty", () => {
|
||||
const data = new SendData();
|
||||
const send = new Send(data);
|
||||
|
||||
expect(send).toEqual({
|
||||
id: null,
|
||||
accessId: null,
|
||||
userId: null,
|
||||
type: undefined,
|
||||
name: null,
|
||||
notes: null,
|
||||
text: undefined,
|
||||
file: undefined,
|
||||
key: null,
|
||||
maxAccessCount: undefined,
|
||||
accessCount: undefined,
|
||||
revisionDate: null,
|
||||
expirationDate: null,
|
||||
deletionDate: null,
|
||||
password: undefined,
|
||||
disabled: undefined,
|
||||
hideEmail: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const send = new Send(data);
|
||||
|
||||
expect(send).toEqual({
|
||||
id: "id",
|
||||
accessId: "accessId",
|
||||
userId: "userId",
|
||||
type: SendType.Text,
|
||||
name: { encryptedString: "encName", encryptionType: 0 },
|
||||
notes: { encryptedString: "encNotes", encryptionType: 0 },
|
||||
text: {
|
||||
text: { encryptedString: "encText", encryptionType: 0 },
|
||||
hidden: true,
|
||||
},
|
||||
key: { encryptedString: "encKey", encryptionType: 0 },
|
||||
maxAccessCount: null,
|
||||
accessCount: 10,
|
||||
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
expirationDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
deletionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
password: "password",
|
||||
disabled: false,
|
||||
hideEmail: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const text = Substitute.for<SendText>();
|
||||
text.decrypt(Arg.any()).resolves("textView" as any);
|
||||
|
||||
const send = new Send();
|
||||
send.id = "id";
|
||||
send.accessId = "accessId";
|
||||
send.userId = "userId";
|
||||
send.type = SendType.Text;
|
||||
send.name = mockEnc("name");
|
||||
send.notes = mockEnc("notes");
|
||||
send.text = text;
|
||||
send.key = mockEnc("key");
|
||||
send.accessCount = 10;
|
||||
send.revisionDate = new Date("2022-01-31T12:00:00.000Z");
|
||||
send.expirationDate = new Date("2022-01-31T12:00:00.000Z");
|
||||
send.deletionDate = new Date("2022-01-31T12:00:00.000Z");
|
||||
send.password = "password";
|
||||
send.disabled = false;
|
||||
send.hideEmail = true;
|
||||
|
||||
const cryptoService = Substitute.for<CryptoService>();
|
||||
cryptoService.decryptToBytes(send.key, null).resolves(makeStaticByteArray(32));
|
||||
cryptoService.makeSendKey(Arg.any()).resolves("cryptoKey" as any);
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService);
|
||||
|
||||
const view = await send.decrypt();
|
||||
|
||||
text.received(1).decrypt("cryptoKey" as any);
|
||||
(send.name as SubstituteOf<EncString>).received(1).decrypt(null, "cryptoKey" as any);
|
||||
|
||||
expect(view).toMatchObject({
|
||||
id: "id",
|
||||
accessId: "accessId",
|
||||
name: "name",
|
||||
notes: "notes",
|
||||
type: 0,
|
||||
key: expect.anything(),
|
||||
cryptoKey: "cryptoKey",
|
||||
file: expect.anything(),
|
||||
text: "textView",
|
||||
maxAccessCount: undefined,
|
||||
accessCount: 10,
|
||||
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
expirationDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
deletionDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
password: "password",
|
||||
disabled: false,
|
||||
hideEmail: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,84 +0,0 @@
|
||||
import { Substitute, Arg } from "@fluffy-spoon/substitute";
|
||||
|
||||
import { SendType } from "@/jslib/common/src/enums/sendType";
|
||||
import { SendAccess } from "@/jslib/common/src/models/domain/sendAccess";
|
||||
import { SendText } from "@/jslib/common/src/models/domain/sendText";
|
||||
import { SendAccessResponse } from "@/jslib/common/src/models/response/sendAccessResponse";
|
||||
|
||||
import { mockEnc } from "../utils";
|
||||
|
||||
describe("SendAccess", () => {
|
||||
let request: SendAccessResponse;
|
||||
|
||||
beforeEach(() => {
|
||||
request = {
|
||||
id: "id",
|
||||
type: SendType.Text,
|
||||
name: "encName",
|
||||
file: null,
|
||||
text: {
|
||||
text: "encText",
|
||||
hidden: true,
|
||||
},
|
||||
expirationDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
creatorIdentifier: "creatorIdentifier",
|
||||
} as SendAccessResponse;
|
||||
});
|
||||
|
||||
it("Convert from empty", () => {
|
||||
const request = new SendAccessResponse({});
|
||||
const sendAccess = new SendAccess(request);
|
||||
|
||||
expect(sendAccess).toEqual({
|
||||
id: null,
|
||||
type: undefined,
|
||||
name: null,
|
||||
creatorIdentifier: null,
|
||||
expirationDate: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const sendAccess = new SendAccess(request);
|
||||
|
||||
expect(sendAccess).toEqual({
|
||||
id: "id",
|
||||
type: 0,
|
||||
name: { encryptedString: "encName", encryptionType: 0 },
|
||||
text: {
|
||||
hidden: true,
|
||||
text: { encryptedString: "encText", encryptionType: 0 },
|
||||
},
|
||||
expirationDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
creatorIdentifier: "creatorIdentifier",
|
||||
});
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const sendAccess = new SendAccess();
|
||||
sendAccess.id = "id";
|
||||
sendAccess.type = SendType.Text;
|
||||
sendAccess.name = mockEnc("name");
|
||||
|
||||
const text = Substitute.for<SendText>();
|
||||
text.decrypt(Arg.any()).resolves({} as any);
|
||||
sendAccess.text = text;
|
||||
|
||||
sendAccess.expirationDate = new Date("2022-01-31T12:00:00.000Z");
|
||||
sendAccess.creatorIdentifier = "creatorIdentifier";
|
||||
|
||||
const view = await sendAccess.decrypt(null);
|
||||
|
||||
text.received(1).decrypt(Arg.any());
|
||||
|
||||
expect(view).toEqual({
|
||||
id: "id",
|
||||
type: 0,
|
||||
name: "name",
|
||||
text: {},
|
||||
file: expect.anything(),
|
||||
expirationDate: new Date("2022-01-31T12:00:00.000Z"),
|
||||
creatorIdentifier: "creatorIdentifier",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,57 +0,0 @@
|
||||
import { SendFileData } from "@/jslib/common/src/models/data/sendFileData";
|
||||
import { SendFile } from "@/jslib/common/src/models/domain/sendFile";
|
||||
|
||||
import { mockEnc } from "../utils";
|
||||
|
||||
describe("SendFile", () => {
|
||||
let data: SendFileData;
|
||||
|
||||
beforeEach(() => {
|
||||
data = {
|
||||
id: "id",
|
||||
size: "1100",
|
||||
sizeName: "1.1 KB",
|
||||
fileName: "encFileName",
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert from empty", () => {
|
||||
const data = new SendFileData();
|
||||
const sendFile = new SendFile(data);
|
||||
|
||||
expect(sendFile).toEqual({
|
||||
fileName: null,
|
||||
id: null,
|
||||
size: undefined,
|
||||
sizeName: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const sendFile = new SendFile(data);
|
||||
|
||||
expect(sendFile).toEqual({
|
||||
id: "id",
|
||||
size: "1100",
|
||||
sizeName: "1.1 KB",
|
||||
fileName: { encryptedString: "encFileName", encryptionType: 0 },
|
||||
});
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const sendFile = new SendFile();
|
||||
sendFile.id = "id";
|
||||
sendFile.size = "1100";
|
||||
sendFile.sizeName = "1.1 KB";
|
||||
sendFile.fileName = mockEnc("fileName");
|
||||
|
||||
const view = await sendFile.decrypt(null);
|
||||
|
||||
expect(view).toEqual({
|
||||
fileName: "fileName",
|
||||
id: "id",
|
||||
size: "1100",
|
||||
sizeName: "1.1 KB",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,47 +0,0 @@
|
||||
import { SendTextData } from "@/jslib/common/src/models/data/sendTextData";
|
||||
import { SendText } from "@/jslib/common/src/models/domain/sendText";
|
||||
|
||||
import { mockEnc } from "../utils";
|
||||
|
||||
describe("SendText", () => {
|
||||
let data: SendTextData;
|
||||
|
||||
beforeEach(() => {
|
||||
data = {
|
||||
text: "encText",
|
||||
hidden: false,
|
||||
};
|
||||
});
|
||||
|
||||
it("Convert from empty", () => {
|
||||
const data = new SendTextData();
|
||||
const secureNote = new SendText(data);
|
||||
|
||||
expect(secureNote).toEqual({
|
||||
hidden: undefined,
|
||||
text: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("Convert", () => {
|
||||
const secureNote = new SendText(data);
|
||||
|
||||
expect(secureNote).toEqual({
|
||||
hidden: false,
|
||||
text: { encryptedString: "encText", encryptionType: 0 },
|
||||
});
|
||||
});
|
||||
|
||||
it("Decrypt", async () => {
|
||||
const secureNote = new SendText();
|
||||
secureNote.text = mockEnc("text");
|
||||
secureNote.hidden = true;
|
||||
|
||||
const view = await secureNote.decrypt(null);
|
||||
|
||||
expect(view).toEqual({
|
||||
text: "text",
|
||||
hidden: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -3,26 +3,14 @@ import { Observable } from "rxjs";
|
||||
import { KdfType } from "../enums/kdfType";
|
||||
import { ThemeType } from "../enums/themeType";
|
||||
import { UriMatchType } from "../enums/uriMatchType";
|
||||
import { CipherData } from "../models/data/cipherData";
|
||||
import { CollectionData } from "../models/data/collectionData";
|
||||
import { EventData } from "../models/data/eventData";
|
||||
import { FolderData } from "../models/data/folderData";
|
||||
import { OrganizationData } from "../models/data/organizationData";
|
||||
import { PolicyData } from "../models/data/policyData";
|
||||
import { ProviderData } from "../models/data/providerData";
|
||||
import { SendData } from "../models/data/sendData";
|
||||
import { Account } from "../models/domain/account";
|
||||
import { EncString } from "../models/domain/encString";
|
||||
import { EnvironmentUrls } from "../models/domain/environmentUrls";
|
||||
import { GeneratedPasswordHistory } from "../models/domain/generatedPasswordHistory";
|
||||
import { Policy } from "../models/domain/policy";
|
||||
import { StorageOptions } from "../models/domain/storageOptions";
|
||||
import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey";
|
||||
import { WindowState } from "../models/domain/windowState";
|
||||
import { CipherView } from "../models/view/cipherView";
|
||||
import { CollectionView } from "../models/view/collectionView";
|
||||
import { FolderView } from "../models/view/folderView";
|
||||
import { SendView } from "../models/view/sendView";
|
||||
|
||||
export abstract class StateService<T extends Account = Account> {
|
||||
accounts$: Observable<{ [userId: string]: T }>;
|
||||
@@ -45,8 +33,6 @@ export abstract class StateService<T extends Account = Account> {
|
||||
setApiKeyClientSecret: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
getAutoConfirmFingerPrints: (options?: StorageOptions) => Promise<boolean>;
|
||||
setAutoConfirmFingerprints: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getAutoFillOnPageLoadDefault: (options?: StorageOptions) => Promise<boolean>;
|
||||
setAutoFillOnPageLoadDefault: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getBiometricAwaitingAcceptance: (options?: StorageOptions) => Promise<boolean>;
|
||||
setBiometricAwaitingAcceptance: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getBiometricFingerprintValidated: (options?: StorageOptions) => Promise<boolean>;
|
||||
@@ -75,17 +61,11 @@ export abstract class StateService<T extends Account = Account> {
|
||||
setCryptoMasterKeyBiometric: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
getDecodedToken: (options?: StorageOptions) => Promise<any>;
|
||||
setDecodedToken: (value: any, options?: StorageOptions) => Promise<void>;
|
||||
getDecryptedCiphers: (options?: StorageOptions) => Promise<CipherView[]>;
|
||||
setDecryptedCiphers: (value: CipherView[], options?: StorageOptions) => Promise<void>;
|
||||
getDecryptedCollections: (options?: StorageOptions) => Promise<CollectionView[]>;
|
||||
setDecryptedCollections: (value: CollectionView[], options?: StorageOptions) => Promise<void>;
|
||||
getDecryptedCryptoSymmetricKey: (options?: StorageOptions) => Promise<SymmetricCryptoKey>;
|
||||
setDecryptedCryptoSymmetricKey: (
|
||||
value: SymmetricCryptoKey,
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getDecryptedFolders: (options?: StorageOptions) => Promise<FolderView[]>;
|
||||
setDecryptedFolders: (value: FolderView[], options?: StorageOptions) => Promise<void>;
|
||||
getDecryptedOrganizationKeys: (
|
||||
options?: StorageOptions,
|
||||
) => Promise<Map<string, SymmetricCryptoKey>>;
|
||||
@@ -93,17 +73,8 @@ export abstract class StateService<T extends Account = Account> {
|
||||
value: Map<string, SymmetricCryptoKey>,
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getDecryptedPasswordGenerationHistory: (
|
||||
options?: StorageOptions,
|
||||
) => Promise<GeneratedPasswordHistory[]>;
|
||||
setDecryptedPasswordGenerationHistory: (
|
||||
value: GeneratedPasswordHistory[],
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getDecryptedPinProtected: (options?: StorageOptions) => Promise<EncString>;
|
||||
setDecryptedPinProtected: (value: EncString, options?: StorageOptions) => Promise<void>;
|
||||
getDecryptedPolicies: (options?: StorageOptions) => Promise<Policy[]>;
|
||||
setDecryptedPolicies: (value: Policy[], options?: StorageOptions) => Promise<void>;
|
||||
getDecryptedPrivateKey: (options?: StorageOptions) => Promise<ArrayBuffer>;
|
||||
setDecryptedPrivateKey: (value: ArrayBuffer, options?: StorageOptions) => Promise<void>;
|
||||
getDecryptedProviderKeys: (options?: StorageOptions) => Promise<Map<string, SymmetricCryptoKey>>;
|
||||
@@ -111,111 +82,54 @@ export abstract class StateService<T extends Account = Account> {
|
||||
value: Map<string, SymmetricCryptoKey>,
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getDecryptedSends: (options?: StorageOptions) => Promise<SendView[]>;
|
||||
setDecryptedSends: (value: SendView[], options?: StorageOptions) => Promise<void>;
|
||||
getDefaultUriMatch: (options?: StorageOptions) => Promise<UriMatchType>;
|
||||
setDefaultUriMatch: (value: UriMatchType, options?: StorageOptions) => Promise<void>;
|
||||
getDisableAddLoginNotification: (options?: StorageOptions) => Promise<boolean>;
|
||||
setDisableAddLoginNotification: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getDisableAutoBiometricsPrompt: (options?: StorageOptions) => Promise<boolean>;
|
||||
setDisableAutoBiometricsPrompt: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getDisableAutoTotpCopy: (options?: StorageOptions) => Promise<boolean>;
|
||||
setDisableAutoTotpCopy: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getDisableBadgeCounter: (options?: StorageOptions) => Promise<boolean>;
|
||||
setDisableBadgeCounter: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getDisableChangedPasswordNotification: (options?: StorageOptions) => Promise<boolean>;
|
||||
setDisableChangedPasswordNotification: (
|
||||
value: boolean,
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getDisableContextMenuItem: (options?: StorageOptions) => Promise<boolean>;
|
||||
setDisableContextMenuItem: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getDisableFavicon: (options?: StorageOptions) => Promise<boolean>;
|
||||
setDisableFavicon: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getDisableGa: (options?: StorageOptions) => Promise<boolean>;
|
||||
setDisableGa: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getDontShowCardsCurrentTab: (options?: StorageOptions) => Promise<boolean>;
|
||||
setDontShowCardsCurrentTab: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getDontShowIdentitiesCurrentTab: (options?: StorageOptions) => Promise<boolean>;
|
||||
setDontShowIdentitiesCurrentTab: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getEmail: (options?: StorageOptions) => Promise<string>;
|
||||
setEmail: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
getEmailVerified: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEmailVerified: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getEnableAlwaysOnTop: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableAlwaysOnTop: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getEnableAutoFillOnPageLoad: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableAutoFillOnPageLoad: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getEnableBiometric: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableBiometric: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getEnableBrowserIntegration: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableBrowserIntegration: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getEnableBrowserIntegrationFingerprint: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableBrowserIntegrationFingerprint: (
|
||||
value: boolean,
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEnableCloseToTray: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableCloseToTray: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getEnableFullWidth: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableFullWidth: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getEnableGravitars: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableGravitars: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getEnableMinimizeToTray: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableMinimizeToTray: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getEnableStartToTray: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableStartToTray: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getEnableTray: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableTray: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getEncryptedCiphers: (options?: StorageOptions) => Promise<{ [id: string]: CipherData }>;
|
||||
setEncryptedCiphers: (
|
||||
value: { [id: string]: CipherData },
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEncryptedCollections: (options?: StorageOptions) => Promise<{ [id: string]: CollectionData }>;
|
||||
setEncryptedCollections: (
|
||||
value: { [id: string]: CollectionData },
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEncryptedCryptoSymmetricKey: (options?: StorageOptions) => Promise<string>;
|
||||
setEncryptedCryptoSymmetricKey: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
getEncryptedFolders: (options?: StorageOptions) => Promise<{ [id: string]: FolderData }>;
|
||||
setEncryptedFolders: (
|
||||
value: { [id: string]: FolderData },
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEncryptedOrganizationKeys: (options?: StorageOptions) => Promise<any>;
|
||||
setEncryptedOrganizationKeys: (
|
||||
value: Map<string, SymmetricCryptoKey>,
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEncryptedPasswordGenerationHistory: (
|
||||
options?: StorageOptions,
|
||||
) => Promise<GeneratedPasswordHistory[]>;
|
||||
setEncryptedPasswordGenerationHistory: (
|
||||
value: GeneratedPasswordHistory[],
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEncryptedPinProtected: (options?: StorageOptions) => Promise<string>;
|
||||
setEncryptedPinProtected: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
getEncryptedPolicies: (options?: StorageOptions) => Promise<{ [id: string]: PolicyData }>;
|
||||
setEncryptedPolicies: (
|
||||
value: { [id: string]: PolicyData },
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEncryptedPrivateKey: (options?: StorageOptions) => Promise<string>;
|
||||
setEncryptedPrivateKey: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
getEncryptedProviderKeys: (options?: StorageOptions) => Promise<any>;
|
||||
setEncryptedProviderKeys: (value: any, options?: StorageOptions) => Promise<void>;
|
||||
getEncryptedSends: (options?: StorageOptions) => Promise<{ [id: string]: SendData }>;
|
||||
setEncryptedSends: (value: { [id: string]: SendData }, options?: StorageOptions) => Promise<void>;
|
||||
getEntityId: (options?: StorageOptions) => Promise<string>;
|
||||
getEnvironmentUrls: (options?: StorageOptions) => Promise<EnvironmentUrls>;
|
||||
setEnvironmentUrls: (value: EnvironmentUrls, options?: StorageOptions) => Promise<void>;
|
||||
getEquivalentDomains: (options?: StorageOptions) => Promise<any>;
|
||||
setEquivalentDomains: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
getEventCollection: (options?: StorageOptions) => Promise<EventData[]>;
|
||||
setEventCollection: (value: EventData[], options?: StorageOptions) => Promise<void>;
|
||||
getEverBeenUnlocked: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEverBeenUnlocked: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getForcePasswordReset: (options?: StorageOptions) => Promise<boolean>;
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
export enum EventType {
|
||||
User_LoggedIn = 1000,
|
||||
User_ChangedPassword = 1001,
|
||||
User_Updated2fa = 1002,
|
||||
User_Disabled2fa = 1003,
|
||||
User_Recovered2fa = 1004,
|
||||
User_FailedLogIn = 1005,
|
||||
User_FailedLogIn2fa = 1006,
|
||||
User_ClientExportedVault = 1007,
|
||||
User_UpdatedTempPassword = 1008,
|
||||
User_MigratedKeyToKeyConnector = 1009,
|
||||
|
||||
Cipher_Created = 1100,
|
||||
Cipher_Updated = 1101,
|
||||
Cipher_Deleted = 1102,
|
||||
Cipher_AttachmentCreated = 1103,
|
||||
Cipher_AttachmentDeleted = 1104,
|
||||
Cipher_Shared = 1105,
|
||||
Cipher_UpdatedCollections = 1106,
|
||||
Cipher_ClientViewed = 1107,
|
||||
Cipher_ClientToggledPasswordVisible = 1108,
|
||||
Cipher_ClientToggledHiddenFieldVisible = 1109,
|
||||
Cipher_ClientToggledCardCodeVisible = 1110,
|
||||
Cipher_ClientCopiedPassword = 1111,
|
||||
Cipher_ClientCopiedHiddenField = 1112,
|
||||
Cipher_ClientCopiedCardCode = 1113,
|
||||
Cipher_ClientAutofilled = 1114,
|
||||
Cipher_SoftDeleted = 1115,
|
||||
Cipher_Restored = 1116,
|
||||
Cipher_ClientToggledCardNumberVisible = 1117,
|
||||
|
||||
Collection_Created = 1300,
|
||||
Collection_Updated = 1301,
|
||||
Collection_Deleted = 1302,
|
||||
|
||||
Group_Created = 1400,
|
||||
Group_Updated = 1401,
|
||||
Group_Deleted = 1402,
|
||||
|
||||
OrganizationUser_Invited = 1500,
|
||||
OrganizationUser_Confirmed = 1501,
|
||||
OrganizationUser_Updated = 1502,
|
||||
OrganizationUser_Removed = 1503,
|
||||
OrganizationUser_UpdatedGroups = 1504,
|
||||
OrganizationUser_UnlinkedSso = 1505,
|
||||
OrganizationUser_ResetPassword_Enroll = 1506,
|
||||
OrganizationUser_ResetPassword_Withdraw = 1507,
|
||||
OrganizationUser_AdminResetPassword = 1508,
|
||||
OrganizationUser_ResetSsoLink = 1509,
|
||||
OrganizationUser_FirstSsoLogin = 1510,
|
||||
|
||||
Organization_Updated = 1600,
|
||||
Organization_PurgedVault = 1601,
|
||||
// Organization_ClientExportedVault = 1602,
|
||||
Organization_VaultAccessed = 1603,
|
||||
Organization_EnabledSso = 1604,
|
||||
Organization_DisabledSso = 1605,
|
||||
Organization_EnabledKeyConnector = 1606,
|
||||
Organization_DisabledKeyConnector = 1607,
|
||||
|
||||
Policy_Updated = 1700,
|
||||
|
||||
ProviderUser_Invited = 1800,
|
||||
ProviderUser_Confirmed = 1801,
|
||||
ProviderUser_Updated = 1802,
|
||||
ProviderUser_Removed = 1803,
|
||||
|
||||
ProviderOrganization_Created = 1900,
|
||||
ProviderOrganization_Added = 1901,
|
||||
ProviderOrganization_Removed = 1902,
|
||||
ProviderOrganization_VaultAccessed = 1903,
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
export type LinkedIdType = LoginLinkedId | CardLinkedId | IdentityLinkedId;
|
||||
|
||||
// LoginView
|
||||
export enum LoginLinkedId {
|
||||
Username = 100,
|
||||
Password = 101,
|
||||
}
|
||||
|
||||
// CardView
|
||||
export enum CardLinkedId {
|
||||
CardholderName = 300,
|
||||
ExpMonth = 301,
|
||||
ExpYear = 302,
|
||||
Code = 303,
|
||||
Brand = 304,
|
||||
Number = 305,
|
||||
}
|
||||
|
||||
// IdentityView
|
||||
export enum IdentityLinkedId {
|
||||
Title = 400,
|
||||
MiddleName = 401,
|
||||
Address1 = 402,
|
||||
Address2 = 403,
|
||||
Address3 = 404,
|
||||
City = 405,
|
||||
State = 406,
|
||||
PostalCode = 407,
|
||||
Country = 408,
|
||||
Company = 409,
|
||||
Email = 410,
|
||||
Phone = 411,
|
||||
Ssn = 412,
|
||||
Username = 413,
|
||||
PassportNumber = 414,
|
||||
LicenseNumber = 415,
|
||||
FirstName = 416,
|
||||
LastName = 417,
|
||||
FullName = 418,
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
export enum PolicyType {
|
||||
TwoFactorAuthentication = 0, // Requires users to have 2fa enabled
|
||||
MasterPassword = 1, // Sets minimum requirements for master password complexity
|
||||
PasswordGenerator = 2, // Sets minimum requirements/default type for generated passwords/passphrases
|
||||
SingleOrg = 3, // Allows users to only be apart of one organization
|
||||
RequireSso = 4, // Requires users to authenticate with SSO
|
||||
PersonalOwnership = 5, // Disables personal vault ownership for adding/cloning items
|
||||
DisableSend = 6, // Disables the ability to create and edit Bitwarden Sends
|
||||
SendOptions = 7, // Sets restrictions or defaults for Bitwarden Sends
|
||||
ResetPassword = 8, // Allows orgs to use reset password : also can enable auto-enrollment during invite flow
|
||||
MaximumVaultTimeout = 9, // Sets the maximum allowed vault timeout
|
||||
DisablePersonalVaultExport = 10, // Disable personal vault export
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export enum SecureNoteType {
|
||||
Generic = 0,
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
export enum SendType {
|
||||
Text = 0,
|
||||
File = 1,
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
import { I18nService } from "../abstractions/i18n.service";
|
||||
|
||||
import { IFrameComponent } from "./iframe_component";
|
||||
|
||||
export class CaptchaIFrame extends IFrameComponent {
|
||||
constructor(
|
||||
win: Window,
|
||||
webVaultUrl: string,
|
||||
private i18nService: I18nService,
|
||||
successCallback: (message: string) => any,
|
||||
errorCallback: (message: string) => any,
|
||||
infoCallback: (message: string) => any,
|
||||
) {
|
||||
super(
|
||||
win,
|
||||
webVaultUrl,
|
||||
"captcha-connector.html",
|
||||
"hcaptcha_iframe",
|
||||
successCallback,
|
||||
errorCallback,
|
||||
(message: string) => {
|
||||
const parsedMessage = JSON.parse(message);
|
||||
if (typeof parsedMessage !== "string") {
|
||||
this.iframe.height = parsedMessage.height.toString();
|
||||
this.iframe.width = parsedMessage.width.toString();
|
||||
} else {
|
||||
infoCallback(parsedMessage);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
init(siteKey: string): void {
|
||||
super.initComponent(
|
||||
this.createParams({ siteKey: siteKey, locale: this.i18nService.translationLocale }, 1),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
export abstract class IFrameComponent {
|
||||
iframe: HTMLIFrameElement;
|
||||
private connectorLink: HTMLAnchorElement;
|
||||
private parseFunction = this.parseMessage.bind(this);
|
||||
|
||||
constructor(
|
||||
private win: Window,
|
||||
protected webVaultUrl: string,
|
||||
private path: string,
|
||||
private iframeId: string,
|
||||
public successCallback?: (message: string) => any,
|
||||
public errorCallback?: (message: string) => any,
|
||||
public infoCallback?: (message: string) => any,
|
||||
) {
|
||||
this.connectorLink = win.document.createElement("a");
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.sendMessage("stop");
|
||||
}
|
||||
|
||||
start() {
|
||||
this.sendMessage("start");
|
||||
}
|
||||
|
||||
sendMessage(message: any) {
|
||||
if (!this.iframe || !this.iframe.src || !this.iframe.contentWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.iframe.contentWindow.postMessage(message, this.iframe.src);
|
||||
}
|
||||
|
||||
base64Encode(str: string): string {
|
||||
return btoa(
|
||||
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => {
|
||||
return String.fromCharCode(("0x" + p1) as any);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
this.win.removeEventListener("message", this.parseFunction, false);
|
||||
}
|
||||
|
||||
protected createParams(data: any, version: number) {
|
||||
return new URLSearchParams({
|
||||
data: this.base64Encode(JSON.stringify(data)),
|
||||
parent: encodeURIComponent(this.win.document.location.href),
|
||||
v: version.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
protected initComponent(params: URLSearchParams): void {
|
||||
this.connectorLink.href = `${this.webVaultUrl}/${this.path}?${params}`;
|
||||
this.iframe = this.win.document.getElementById(this.iframeId) as HTMLIFrameElement;
|
||||
this.iframe.src = this.connectorLink.href;
|
||||
|
||||
this.win.addEventListener("message", this.parseFunction, false);
|
||||
}
|
||||
|
||||
private parseMessage(event: MessageEvent) {
|
||||
if (!this.validMessage(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const parts: string[] = event.data.split("|");
|
||||
if (parts[0] === "success" && this.successCallback) {
|
||||
this.successCallback(parts[1]);
|
||||
} else if (parts[0] === "error" && this.errorCallback) {
|
||||
this.errorCallback(parts[1]);
|
||||
} else if (parts[0] === "info" && this.infoCallback) {
|
||||
this.infoCallback(parts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
private validMessage(event: MessageEvent) {
|
||||
if (
|
||||
event.origin == null ||
|
||||
event.origin === "" ||
|
||||
event.origin !== (this.connectorLink as any).origin ||
|
||||
event.data == null ||
|
||||
typeof event.data !== "string"
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
event.data.indexOf("success|") === 0 ||
|
||||
event.data.indexOf("error|") === 0 ||
|
||||
event.data.indexOf("info|") === 0
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import { LinkedIdType } from "../enums/linkedIdType";
|
||||
import { ItemView } from "../models/view/itemView";
|
||||
|
||||
export class LinkedMetadata {
|
||||
constructor(
|
||||
readonly propertyKey: string,
|
||||
private readonly _i18nKey?: string,
|
||||
) {}
|
||||
|
||||
get i18nKey() {
|
||||
return this._i18nKey ?? this.propertyKey;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A decorator used to set metadata used by Linked custom fields. Apply it to a class property or getter to make it
|
||||
* available as a Linked custom field option.
|
||||
* @param id - A unique value that is saved in the Field model. It is used to look up the decorated class property.
|
||||
* @param i18nKey - The i18n key used to describe the decorated class property in the UI. If it is null, then the name
|
||||
* of the class property will be used as the i18n key.
|
||||
*/
|
||||
export function linkedFieldOption(id: LinkedIdType, i18nKey?: string) {
|
||||
return (prototype: ItemView, propertyKey: string) => {
|
||||
if (prototype.linkedFieldOptions == null) {
|
||||
prototype.linkedFieldOptions = new Map<LinkedIdType, LinkedMetadata>();
|
||||
}
|
||||
|
||||
prototype.linkedFieldOptions.set(id, new LinkedMetadata(propertyKey, i18nKey));
|
||||
};
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
import { I18nService } from "../abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "../abstractions/platformUtils.service";
|
||||
|
||||
export class WebAuthnIFrame {
|
||||
private iframe: HTMLIFrameElement = null;
|
||||
private connectorLink: HTMLAnchorElement;
|
||||
private parseFunction = this.parseMessage.bind(this);
|
||||
|
||||
constructor(
|
||||
private win: Window,
|
||||
private webVaultUrl: string,
|
||||
private webAuthnNewTab: boolean,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private successCallback: Function, // eslint-disable-line
|
||||
private errorCallback: Function, // eslint-disable-line
|
||||
private infoCallback: Function, // eslint-disable-line
|
||||
) {
|
||||
this.connectorLink = win.document.createElement("a");
|
||||
}
|
||||
|
||||
init(data: any): void {
|
||||
const params = new URLSearchParams({
|
||||
data: this.base64Encode(JSON.stringify(data)),
|
||||
parent: encodeURIComponent(this.win.document.location.href),
|
||||
btnText: encodeURIComponent(this.i18nService.t("webAuthnAuthenticate")),
|
||||
v: "1",
|
||||
});
|
||||
|
||||
if (this.webAuthnNewTab) {
|
||||
// Firefox fallback which opens the webauthn page in a new tab
|
||||
params.append("locale", this.i18nService.translationLocale);
|
||||
this.platformUtilsService.launchUri(
|
||||
`${this.webVaultUrl}/webauthn-fallback-connector.html?${params}`,
|
||||
);
|
||||
} else {
|
||||
this.connectorLink.href = `${this.webVaultUrl}/webauthn-connector.html?${params}`;
|
||||
this.iframe = this.win.document.getElementById("webauthn_iframe") as HTMLIFrameElement;
|
||||
this.iframe.allow = "publickey-credentials-get " + new URL(this.webVaultUrl).origin;
|
||||
this.iframe.src = this.connectorLink.href;
|
||||
|
||||
this.win.addEventListener("message", this.parseFunction, false);
|
||||
}
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.sendMessage("stop");
|
||||
}
|
||||
|
||||
start() {
|
||||
this.sendMessage("start");
|
||||
}
|
||||
|
||||
sendMessage(message: any) {
|
||||
if (!this.iframe || !this.iframe.src || !this.iframe.contentWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.iframe.contentWindow.postMessage(message, this.iframe.src);
|
||||
}
|
||||
|
||||
base64Encode(str: string): string {
|
||||
return btoa(
|
||||
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => {
|
||||
return String.fromCharCode(("0x" + p1) as any);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
this.win.removeEventListener("message", this.parseFunction, false);
|
||||
}
|
||||
|
||||
private parseMessage(event: MessageEvent) {
|
||||
if (!this.validMessage(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const parts: string[] = event.data.split("|");
|
||||
if (parts[0] === "success" && this.successCallback) {
|
||||
this.successCallback(parts[1]);
|
||||
} else if (parts[0] === "error" && this.errorCallback) {
|
||||
this.errorCallback(parts[1]);
|
||||
} else if (parts[0] === "info" && this.infoCallback) {
|
||||
this.infoCallback(parts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
private validMessage(event: MessageEvent) {
|
||||
if (
|
||||
event.origin == null ||
|
||||
event.origin === "" ||
|
||||
event.origin !== (this.connectorLink as any).origin ||
|
||||
event.data == null ||
|
||||
typeof event.data !== "string"
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
event.data.indexOf("success|") === 0 ||
|
||||
event.data.indexOf("error|") === 0 ||
|
||||
event.data.indexOf("info|") === 0
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import { BaseResponse } from "../response/baseResponse";
|
||||
|
||||
export class CardApi extends BaseResponse {
|
||||
cardholderName: string;
|
||||
brand: string;
|
||||
number: string;
|
||||
expMonth: string;
|
||||
expYear: string;
|
||||
code: string;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.cardholderName = this.getResponseProperty("CardholderName");
|
||||
this.brand = this.getResponseProperty("Brand");
|
||||
this.number = this.getResponseProperty("Number");
|
||||
this.expMonth = this.getResponseProperty("ExpMonth");
|
||||
this.expYear = this.getResponseProperty("ExpYear");
|
||||
this.code = this.getResponseProperty("Code");
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import { FieldType } from "../../enums/fieldType";
|
||||
import { LinkedIdType } from "../../enums/linkedIdType";
|
||||
import { BaseResponse } from "../response/baseResponse";
|
||||
|
||||
export class FieldApi extends BaseResponse {
|
||||
name: string;
|
||||
value: string;
|
||||
type: FieldType;
|
||||
linkedId: LinkedIdType;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.type = this.getResponseProperty("Type");
|
||||
this.name = this.getResponseProperty("Name");
|
||||
this.value = this.getResponseProperty("Value");
|
||||
this.linkedId = this.getResponseProperty("linkedId");
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import { BaseResponse } from "../response/baseResponse";
|
||||
|
||||
export class IdentityApi extends BaseResponse {
|
||||
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: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.title = this.getResponseProperty("Title");
|
||||
this.firstName = this.getResponseProperty("FirstName");
|
||||
this.middleName = this.getResponseProperty("MiddleName");
|
||||
this.lastName = this.getResponseProperty("LastName");
|
||||
this.address1 = this.getResponseProperty("Address1");
|
||||
this.address2 = this.getResponseProperty("Address2");
|
||||
this.address3 = this.getResponseProperty("Address3");
|
||||
this.city = this.getResponseProperty("City");
|
||||
this.state = this.getResponseProperty("State");
|
||||
this.postalCode = this.getResponseProperty("PostalCode");
|
||||
this.country = this.getResponseProperty("Country");
|
||||
this.company = this.getResponseProperty("Company");
|
||||
this.email = this.getResponseProperty("Email");
|
||||
this.phone = this.getResponseProperty("Phone");
|
||||
this.ssn = this.getResponseProperty("SSN");
|
||||
this.username = this.getResponseProperty("Username");
|
||||
this.passportNumber = this.getResponseProperty("PassportNumber");
|
||||
this.licenseNumber = this.getResponseProperty("LicenseNumber");
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { BaseResponse } from "../response/baseResponse";
|
||||
|
||||
import { LoginUriApi } from "./loginUriApi";
|
||||
|
||||
export class LoginApi extends BaseResponse {
|
||||
uris: LoginUriApi[];
|
||||
username: string;
|
||||
password: string;
|
||||
passwordRevisionDate: string;
|
||||
totp: string;
|
||||
autofillOnPageLoad: boolean;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.username = this.getResponseProperty("Username");
|
||||
this.password = this.getResponseProperty("Password");
|
||||
this.passwordRevisionDate = this.getResponseProperty("PasswordRevisionDate");
|
||||
this.totp = this.getResponseProperty("Totp");
|
||||
this.autofillOnPageLoad = this.getResponseProperty("AutofillOnPageLoad");
|
||||
|
||||
const uris = this.getResponseProperty("Uris");
|
||||
if (uris != null) {
|
||||
this.uris = uris.map((u: any) => new LoginUriApi(u));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { UriMatchType } from "../../enums/uriMatchType";
|
||||
import { BaseResponse } from "../response/baseResponse";
|
||||
|
||||
export class LoginUriApi extends BaseResponse {
|
||||
uri: string;
|
||||
match: UriMatchType = null;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.uri = this.getResponseProperty("Uri");
|
||||
const match = this.getResponseProperty("Match");
|
||||
this.match = match != null ? match : null;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { SecureNoteType } from "../../enums/secureNoteType";
|
||||
import { BaseResponse } from "../response/baseResponse";
|
||||
|
||||
export class SecureNoteApi extends BaseResponse {
|
||||
type: SecureNoteType;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.type = this.getResponseProperty("Type");
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { BaseResponse } from "../response/baseResponse";
|
||||
|
||||
export class SendFileApi extends BaseResponse {
|
||||
id: string;
|
||||
fileName: string;
|
||||
size: string;
|
||||
sizeName: string;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.id = this.getResponseProperty("Id");
|
||||
this.fileName = this.getResponseProperty("FileName");
|
||||
this.size = this.getResponseProperty("Size");
|
||||
this.sizeName = this.getResponseProperty("SizeName");
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { BaseResponse } from "../response/baseResponse";
|
||||
|
||||
export class SendTextApi extends BaseResponse {
|
||||
text: string;
|
||||
hidden: boolean;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.text = this.getResponseProperty("Text");
|
||||
this.hidden = this.getResponseProperty("Hidden") || false;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { AttachmentResponse } from "../response/attachmentResponse";
|
||||
|
||||
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/cardApi";
|
||||
|
||||
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/cipherResponse";
|
||||
|
||||
import { AttachmentData } from "./attachmentData";
|
||||
import { CardData } from "./cardData";
|
||||
import { FieldData } from "./fieldData";
|
||||
import { IdentityData } from "./identityData";
|
||||
import { LoginData } from "./loginData";
|
||||
import { PasswordHistoryData } from "./passwordHistoryData";
|
||||
import { SecureNoteData } from "./secureNoteData";
|
||||
|
||||
export class CipherData {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
folderId: string;
|
||||
userId: 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[];
|
||||
deletedDate: string;
|
||||
reprompt: CipherRepromptType;
|
||||
|
||||
constructor(response?: CipherResponse, userId?: string, collectionIds?: string[]) {
|
||||
if (response == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.id = response.id;
|
||||
this.organizationId = response.organizationId;
|
||||
this.folderId = response.folderId;
|
||||
this.userId = userId;
|
||||
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.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,17 +0,0 @@
|
||||
import { CollectionDetailsResponse } from "../response/collectionResponse";
|
||||
|
||||
export class CollectionData {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
name: string;
|
||||
externalId: string;
|
||||
readOnly: boolean;
|
||||
|
||||
constructor(response: CollectionDetailsResponse) {
|
||||
this.id = response.id;
|
||||
this.organizationId = response.organizationId;
|
||||
this.name = response.name;
|
||||
this.externalId = response.externalId;
|
||||
this.readOnly = response.readOnly;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { EventType } from "../../enums/eventType";
|
||||
|
||||
export class EventData {
|
||||
type: EventType;
|
||||
cipherId: string;
|
||||
date: string;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { FieldType } from "../../enums/fieldType";
|
||||
import { LinkedIdType } from "../../enums/linkedIdType";
|
||||
import { FieldApi } from "../api/fieldApi";
|
||||
|
||||
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,15 +0,0 @@
|
||||
import { FolderResponse } from "../response/folderResponse";
|
||||
|
||||
export class FolderData {
|
||||
id: string;
|
||||
userId: string;
|
||||
name: string;
|
||||
revisionDate: string;
|
||||
|
||||
constructor(response: FolderResponse, userId: string) {
|
||||
this.userId = userId;
|
||||
this.name = response.name;
|
||||
this.id = response.id;
|
||||
this.revisionDate = response.revisionDate;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import { IdentityApi } from "../api/identityApi";
|
||||
|
||||
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,28 +0,0 @@
|
||||
import { LoginApi } from "../api/loginApi";
|
||||
|
||||
import { LoginUriData } from "./loginUriData";
|
||||
|
||||
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 { UriMatchType } from "../../enums/uriMatchType";
|
||||
import { LoginUriApi } from "../api/loginUriApi";
|
||||
|
||||
export class LoginUriData {
|
||||
uri: string;
|
||||
match: UriMatchType = null;
|
||||
|
||||
constructor(data?: LoginUriApi) {
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.uri = data.uri;
|
||||
this.match = data.match;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { PasswordHistoryResponse } from "../response/passwordHistoryResponse";
|
||||
|
||||
export class PasswordHistoryData {
|
||||
password: string;
|
||||
lastUsedDate: string;
|
||||
|
||||
constructor(response?: PasswordHistoryResponse) {
|
||||
if (response == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.password = response.password;
|
||||
this.lastUsedDate = response.lastUsedDate;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { PolicyType } from "../../enums/policyType";
|
||||
import { PolicyResponse } from "../response/policyResponse";
|
||||
|
||||
export class PolicyData {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
type: PolicyType;
|
||||
data: any;
|
||||
enabled: boolean;
|
||||
|
||||
constructor(response: PolicyResponse) {
|
||||
this.id = response.id;
|
||||
this.organizationId = response.organizationId;
|
||||
this.type = response.type;
|
||||
this.data = response.data;
|
||||
this.enabled = response.enabled;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { SecureNoteType } from "../../enums/secureNoteType";
|
||||
import { SecureNoteApi } from "../api/secureNoteApi";
|
||||
|
||||
export class SecureNoteData {
|
||||
type: SecureNoteType;
|
||||
|
||||
constructor(data?: SecureNoteApi) {
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.type = data.type;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import { SendType } from "../../enums/sendType";
|
||||
import { SendResponse } from "../response/sendResponse";
|
||||
|
||||
import { SendFileData } from "./sendFileData";
|
||||
import { SendTextData } from "./sendTextData";
|
||||
|
||||
export class SendData {
|
||||
id: string;
|
||||
accessId: string;
|
||||
userId: string;
|
||||
type: SendType;
|
||||
name: string;
|
||||
notes: string;
|
||||
file: SendFileData;
|
||||
text: SendTextData;
|
||||
key: string;
|
||||
maxAccessCount?: number;
|
||||
accessCount: number;
|
||||
revisionDate: string;
|
||||
expirationDate: string;
|
||||
deletionDate: string;
|
||||
password: string;
|
||||
disabled: boolean;
|
||||
hideEmail: boolean;
|
||||
|
||||
constructor(response?: SendResponse, userId?: string) {
|
||||
if (response == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.id = response.id;
|
||||
this.accessId = response.accessId;
|
||||
this.userId = userId;
|
||||
this.type = response.type;
|
||||
this.name = response.name;
|
||||
this.notes = response.notes;
|
||||
this.key = response.key;
|
||||
this.maxAccessCount = response.maxAccessCount;
|
||||
this.accessCount = response.accessCount;
|
||||
this.revisionDate = response.revisionDate;
|
||||
this.expirationDate = response.expirationDate;
|
||||
this.deletionDate = response.deletionDate;
|
||||
this.password = response.password;
|
||||
this.disabled = response.disable;
|
||||
this.hideEmail = response.hideEmail;
|
||||
|
||||
switch (this.type) {
|
||||
case SendType.Text:
|
||||
this.text = new SendTextData(response.text);
|
||||
break;
|
||||
case SendType.File:
|
||||
this.file = new SendFileData(response.file);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { SendFileApi } from "../api/sendFileApi";
|
||||
|
||||
export class SendFileData {
|
||||
id: string;
|
||||
fileName: string;
|
||||
size: string;
|
||||
sizeName: string;
|
||||
|
||||
constructor(data?: SendFileApi) {
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.id = data.id;
|
||||
this.fileName = data.fileName;
|
||||
this.size = data.size;
|
||||
this.sizeName = data.sizeName;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { SendTextApi } from "../api/sendTextApi";
|
||||
|
||||
export class SendTextData {
|
||||
text: string;
|
||||
hidden: boolean;
|
||||
|
||||
constructor(data?: SendTextApi) {
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.text = data.text;
|
||||
this.hidden = data.hidden;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,11 @@
|
||||
import { AuthenticationStatus } from "../../enums/authenticationStatus";
|
||||
import { KdfType } from "../../enums/kdfType";
|
||||
import { UriMatchType } from "../../enums/uriMatchType";
|
||||
import { CipherData } from "../data/cipherData";
|
||||
import { CollectionData } from "../data/collectionData";
|
||||
import { EventData } from "../data/eventData";
|
||||
import { FolderData } from "../data/folderData";
|
||||
import { OrganizationData } from "../data/organizationData";
|
||||
import { PolicyData } from "../data/policyData";
|
||||
import { ProviderData } from "../data/providerData";
|
||||
import { SendData } from "../data/sendData";
|
||||
import { CipherView } from "../view/cipherView";
|
||||
import { CollectionView } from "../view/collectionView";
|
||||
import { FolderView } from "../view/folderView";
|
||||
import { SendView } from "../view/sendView";
|
||||
|
||||
import { EncString } from "./encString";
|
||||
import { EnvironmentUrls } from "./environmentUrls";
|
||||
import { GeneratedPasswordHistory } from "./generatedPasswordHistory";
|
||||
import { Policy } from "./policy";
|
||||
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
|
||||
|
||||
export class EncryptionPair<TEncrypted, TDecrypted> {
|
||||
@@ -31,27 +19,15 @@ export class DataEncryptionPair<TEncrypted, TDecrypted> {
|
||||
}
|
||||
|
||||
export class AccountData {
|
||||
ciphers?: DataEncryptionPair<CipherData, CipherView> = new DataEncryptionPair<
|
||||
CipherData,
|
||||
CipherView
|
||||
>();
|
||||
folders?: DataEncryptionPair<FolderData, FolderView> = new DataEncryptionPair<
|
||||
FolderData,
|
||||
FolderView
|
||||
>();
|
||||
ciphers?: any = new DataEncryptionPair<any, any>();
|
||||
folders?: DataEncryptionPair<any, any> = new DataEncryptionPair<any, any>();
|
||||
localData?: any;
|
||||
sends?: DataEncryptionPair<SendData, SendView> = new DataEncryptionPair<SendData, SendView>();
|
||||
collections?: DataEncryptionPair<CollectionData, CollectionView> = new DataEncryptionPair<
|
||||
CollectionData,
|
||||
CollectionView
|
||||
>();
|
||||
policies?: DataEncryptionPair<PolicyData, Policy> = new DataEncryptionPair<PolicyData, Policy>();
|
||||
passwordGenerationHistory?: EncryptionPair<
|
||||
GeneratedPasswordHistory[],
|
||||
GeneratedPasswordHistory[]
|
||||
> = new EncryptionPair<GeneratedPasswordHistory[], GeneratedPasswordHistory[]>();
|
||||
sends?: any = new DataEncryptionPair<any, any>();
|
||||
collections?: DataEncryptionPair<any, any> = new DataEncryptionPair<any, any>();
|
||||
policies?: DataEncryptionPair<any, any> = new DataEncryptionPair<any, any>();
|
||||
passwordGenerationHistory?: EncryptionPair<any[], any[]> = new EncryptionPair<any[], any[]>();
|
||||
addEditCipherInfo?: any;
|
||||
eventCollection?: EventData[];
|
||||
eventCollection?: any[];
|
||||
organizations?: { [id: string]: OrganizationData };
|
||||
providers?: { [id: string]: ProviderData };
|
||||
}
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
import { CryptoService } from "../../abstractions/crypto.service";
|
||||
import { Utils } from "../../misc/utils";
|
||||
import { AttachmentData } from "../data/attachmentData";
|
||||
import { AttachmentView } from "../view/attachmentView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
|
||||
|
||||
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) {
|
||||
let cryptoService: CryptoService;
|
||||
const containerService = (Utils.global as any).bitwardenContainerService;
|
||||
if (containerService) {
|
||||
cryptoService = containerService.getCryptoService();
|
||||
} else {
|
||||
throw new Error("global bitwardenContainerService not initialized.");
|
||||
}
|
||||
|
||||
try {
|
||||
const orgKey = await cryptoService.getOrgKey(orgId);
|
||||
const decValue = await cryptoService.decryptToBytes(this.key, orgKey ?? encKey);
|
||||
view.key = new SymmetricCryptoKey(decValue);
|
||||
} catch (e) {
|
||||
// TODO: error?
|
||||
}
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
import { CardData } from "../data/cardData";
|
||||
import { CardView } from "../view/cardView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,238 +0,0 @@
|
||||
import { CipherRepromptType } from "../../enums/cipherRepromptType";
|
||||
import { CipherType } from "../../enums/cipherType";
|
||||
import { CipherData } from "../data/cipherData";
|
||||
import { CipherView } from "../view/cipherView";
|
||||
|
||||
import { Attachment } from "./attachment";
|
||||
import { Card } from "./card";
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
import { Field } from "./field";
|
||||
import { Identity } from "./identity";
|
||||
import { Login } from "./login";
|
||||
import { Password } from "./password";
|
||||
import { SecureNote } from "./secureNote";
|
||||
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
|
||||
|
||||
export class Cipher extends Domain {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
folderId: string;
|
||||
name: EncString;
|
||||
notes: EncString;
|
||||
type: CipherType;
|
||||
favorite: boolean;
|
||||
organizationUseTotp: boolean;
|
||||
edit: boolean;
|
||||
viewPassword: boolean;
|
||||
revisionDate: Date;
|
||||
localData: any;
|
||||
login: Login;
|
||||
identity: Identity;
|
||||
card: Card;
|
||||
secureNote: SecureNote;
|
||||
attachments: Attachment[];
|
||||
fields: Field[];
|
||||
passwordHistory: Password[];
|
||||
collectionIds: string[];
|
||||
deletedDate: Date;
|
||||
reprompt: CipherRepromptType;
|
||||
|
||||
constructor(obj?: CipherData, localData: any = null) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
id: null,
|
||||
userId: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: null,
|
||||
notes: null,
|
||||
},
|
||||
["id", "userId", "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.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(userId: string): CipherData {
|
||||
const c = new CipherData();
|
||||
c.id = this.id;
|
||||
c.organizationId = this.organizationId;
|
||||
c.folderId = this.folderId;
|
||||
c.userId = this.organizationId != null ? userId : null;
|
||||
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.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;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import { CollectionData } from "../data/collectionData";
|
||||
import { CollectionView } from "../view/collectionView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
|
||||
export class Collection extends Domain {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
name: EncString;
|
||||
externalId: string;
|
||||
readOnly: boolean;
|
||||
hidePasswords: boolean;
|
||||
|
||||
constructor(obj?: CollectionData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
id: null,
|
||||
organizationId: null,
|
||||
name: null,
|
||||
externalId: null,
|
||||
readOnly: null,
|
||||
hidePasswords: null,
|
||||
},
|
||||
["id", "organizationId", "externalId", "readOnly", "hidePasswords"],
|
||||
);
|
||||
}
|
||||
|
||||
decrypt(): Promise<CollectionView> {
|
||||
return this.decryptObj(
|
||||
new CollectionView(this),
|
||||
{
|
||||
name: null,
|
||||
},
|
||||
this.organizationId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
import { FieldType } from "../../enums/fieldType";
|
||||
import { LinkedIdType } from "../../enums/linkedIdType";
|
||||
import { FieldData } from "../data/fieldData";
|
||||
import { FieldView } from "../view/fieldView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import { FolderData } from "../data/folderData";
|
||||
import { FolderView } from "../view/folderView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
export class GeneratedPasswordHistory {
|
||||
password: string;
|
||||
date: number;
|
||||
|
||||
constructor(password: string, date: number) {
|
||||
this.password = password;
|
||||
this.date = date;
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
import { IdentityData } from "../data/identityData";
|
||||
import { IdentityView } from "../view/identityView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
import { LoginData } from "../data/loginData";
|
||||
import { LoginView } from "../view/loginView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
import { LoginUri } from "./loginUri";
|
||||
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import { UriMatchType } from "../../enums/uriMatchType";
|
||||
import { LoginUriData } from "../data/loginUriData";
|
||||
import { LoginUriView } from "../view/loginUriView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import Domain from "./domainBase";
|
||||
|
||||
export class MasterPasswordPolicyOptions extends Domain {
|
||||
minComplexity = 0;
|
||||
minLength = 0;
|
||||
requireUpper = false;
|
||||
requireLower = false;
|
||||
requireNumbers = false;
|
||||
requireSpecial = false;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import { PasswordHistoryData } from "../data/passwordHistoryData";
|
||||
import { PasswordHistoryView } from "../view/passwordHistoryView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import Domain from "./domainBase";
|
||||
|
||||
export class PasswordGeneratorPolicyOptions extends Domain {
|
||||
defaultType = "";
|
||||
minLength = 0;
|
||||
useUppercase = false;
|
||||
useLowercase = false;
|
||||
useNumbers = false;
|
||||
numberCount = 0;
|
||||
useSpecial = false;
|
||||
specialCount = 0;
|
||||
minNumberWords = 0;
|
||||
capitalize = false;
|
||||
includeNumber = false;
|
||||
|
||||
inEffect() {
|
||||
return (
|
||||
this.defaultType !== "" ||
|
||||
this.minLength > 0 ||
|
||||
this.numberCount > 0 ||
|
||||
this.specialCount > 0 ||
|
||||
this.useUppercase ||
|
||||
this.useLowercase ||
|
||||
this.useNumbers ||
|
||||
this.useSpecial ||
|
||||
this.minNumberWords > 0 ||
|
||||
this.capitalize ||
|
||||
this.includeNumber
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { PolicyType } from "../../enums/policyType";
|
||||
import { PolicyData } from "../data/policyData";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
|
||||
export class Policy extends Domain {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
type: PolicyType;
|
||||
data: any;
|
||||
enabled: boolean;
|
||||
|
||||
constructor(obj?: PolicyData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.id = obj.id;
|
||||
this.organizationId = obj.organizationId;
|
||||
this.type = obj.type;
|
||||
this.data = obj.data;
|
||||
this.enabled = obj.enabled;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import Domain from "./domainBase";
|
||||
|
||||
export class ResetPasswordPolicyOptions extends Domain {
|
||||
autoEnrollEnabled = false;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { SecureNoteType } from "../../enums/secureNoteType";
|
||||
import { SecureNoteData } from "../data/secureNoteData";
|
||||
import { SecureNoteView } from "../view/secureNoteView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
import { CryptoService } from "../../abstractions/crypto.service";
|
||||
import { SendType } from "../../enums/sendType";
|
||||
import { Utils } from "../../misc/utils";
|
||||
import { SendData } from "../data/sendData";
|
||||
import { SendView } from "../view/sendView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
import { SendFile } from "./sendFile";
|
||||
import { SendText } from "./sendText";
|
||||
|
||||
export class Send extends Domain {
|
||||
id: string;
|
||||
accessId: string;
|
||||
userId: string;
|
||||
type: SendType;
|
||||
name: EncString;
|
||||
notes: EncString;
|
||||
file: SendFile;
|
||||
text: SendText;
|
||||
key: EncString;
|
||||
maxAccessCount?: number;
|
||||
accessCount: number;
|
||||
revisionDate: Date;
|
||||
expirationDate: Date;
|
||||
deletionDate: Date;
|
||||
password: string;
|
||||
disabled: boolean;
|
||||
hideEmail: boolean;
|
||||
|
||||
constructor(obj?: SendData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
id: null,
|
||||
accessId: null,
|
||||
userId: null,
|
||||
name: null,
|
||||
notes: null,
|
||||
key: null,
|
||||
},
|
||||
["id", "accessId", "userId"],
|
||||
);
|
||||
|
||||
this.type = obj.type;
|
||||
this.maxAccessCount = obj.maxAccessCount;
|
||||
this.accessCount = obj.accessCount;
|
||||
this.password = obj.password;
|
||||
this.disabled = obj.disabled;
|
||||
this.revisionDate = obj.revisionDate != null ? new Date(obj.revisionDate) : null;
|
||||
this.deletionDate = obj.deletionDate != null ? new Date(obj.deletionDate) : null;
|
||||
this.expirationDate = obj.expirationDate != null ? new Date(obj.expirationDate) : null;
|
||||
this.hideEmail = obj.hideEmail;
|
||||
|
||||
switch (this.type) {
|
||||
case SendType.Text:
|
||||
this.text = new SendText(obj.text);
|
||||
break;
|
||||
case SendType.File:
|
||||
this.file = new SendFile(obj.file);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async decrypt(): Promise<SendView> {
|
||||
const model = new SendView(this);
|
||||
|
||||
let cryptoService: CryptoService;
|
||||
const containerService = (Utils.global as any).bitwardenContainerService;
|
||||
if (containerService) {
|
||||
cryptoService = containerService.getCryptoService();
|
||||
} else {
|
||||
throw new Error("global bitwardenContainerService not initialized.");
|
||||
}
|
||||
|
||||
try {
|
||||
model.key = await cryptoService.decryptToBytes(this.key, null);
|
||||
model.cryptoKey = await cryptoService.makeSendKey(model.key);
|
||||
} catch (e) {
|
||||
// TODO: error?
|
||||
}
|
||||
|
||||
await this.decryptObj(
|
||||
model,
|
||||
{
|
||||
name: null,
|
||||
notes: null,
|
||||
},
|
||||
null,
|
||||
model.cryptoKey,
|
||||
);
|
||||
|
||||
switch (this.type) {
|
||||
case SendType.File:
|
||||
model.file = await this.file.decrypt(model.cryptoKey);
|
||||
break;
|
||||
case SendType.Text:
|
||||
model.text = await this.text.decrypt(model.cryptoKey);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
import { SendType } from "../../enums/sendType";
|
||||
import { SendAccessResponse } from "../response/sendAccessResponse";
|
||||
import { SendAccessView } from "../view/sendAccessView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
import { SendFile } from "./sendFile";
|
||||
import { SendText } from "./sendText";
|
||||
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
|
||||
|
||||
export class SendAccess extends Domain {
|
||||
id: string;
|
||||
type: SendType;
|
||||
name: EncString;
|
||||
file: SendFile;
|
||||
text: SendText;
|
||||
expirationDate: Date;
|
||||
creatorIdentifier: string;
|
||||
|
||||
constructor(obj?: SendAccessResponse) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
id: null,
|
||||
name: null,
|
||||
expirationDate: null,
|
||||
creatorIdentifier: null,
|
||||
},
|
||||
["id", "expirationDate", "creatorIdentifier"],
|
||||
);
|
||||
|
||||
this.type = obj.type;
|
||||
|
||||
switch (this.type) {
|
||||
case SendType.Text:
|
||||
this.text = new SendText(obj.text);
|
||||
break;
|
||||
case SendType.File:
|
||||
this.file = new SendFile(obj.file);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async decrypt(key: SymmetricCryptoKey): Promise<SendAccessView> {
|
||||
const model = new SendAccessView(this);
|
||||
|
||||
await this.decryptObj(
|
||||
model,
|
||||
{
|
||||
name: null,
|
||||
},
|
||||
null,
|
||||
key,
|
||||
);
|
||||
|
||||
switch (this.type) {
|
||||
case SendType.File:
|
||||
model.file = await this.file.decrypt(key);
|
||||
break;
|
||||
case SendType.Text:
|
||||
model.text = await this.text.decrypt(key);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
import { SendFileData } from "../data/sendFileData";
|
||||
import { SendFileView } from "../view/sendFileView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
|
||||
|
||||
export class SendFile extends Domain {
|
||||
id: string;
|
||||
size: string;
|
||||
sizeName: string;
|
||||
fileName: EncString;
|
||||
|
||||
constructor(obj?: SendFileData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.size = obj.size;
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
id: null,
|
||||
sizeName: null,
|
||||
fileName: null,
|
||||
},
|
||||
["id", "sizeName"],
|
||||
);
|
||||
}
|
||||
|
||||
async decrypt(key: SymmetricCryptoKey): Promise<SendFileView> {
|
||||
const view = await this.decryptObj(
|
||||
new SendFileView(this),
|
||||
{
|
||||
fileName: null,
|
||||
},
|
||||
null,
|
||||
key,
|
||||
);
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import { SendTextData } from "../data/sendTextData";
|
||||
import { SendTextView } from "../view/sendTextView";
|
||||
|
||||
import Domain from "./domainBase";
|
||||
import { EncString } from "./encString";
|
||||
import { SymmetricCryptoKey } from "./symmetricCryptoKey";
|
||||
|
||||
export class SendText extends Domain {
|
||||
text: EncString;
|
||||
hidden: boolean;
|
||||
|
||||
constructor(obj?: SendTextData) {
|
||||
super();
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.hidden = obj.hidden;
|
||||
this.buildDomainModel(
|
||||
this,
|
||||
obj,
|
||||
{
|
||||
text: null,
|
||||
},
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
decrypt(key: SymmetricCryptoKey): Promise<SendTextView> {
|
||||
return this.decryptObj(
|
||||
new SendTextView(this),
|
||||
{
|
||||
text: null,
|
||||
},
|
||||
null,
|
||||
key,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
import { CipherView } from "../view/cipherView";
|
||||
|
||||
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,20 +0,0 @@
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
|
||||
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,23 +0,0 @@
|
||||
import { FileUploadType } from "../../enums/fileUploadType";
|
||||
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
import { CipherResponse } from "./cipherResponse";
|
||||
|
||||
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,92 +0,0 @@
|
||||
import { CipherRepromptType } from "../../enums/cipherRepromptType";
|
||||
import { CardApi } from "../api/cardApi";
|
||||
import { FieldApi } from "../api/fieldApi";
|
||||
import { IdentityApi } from "../api/identityApi";
|
||||
import { LoginApi } from "../api/loginApi";
|
||||
import { SecureNoteApi } from "../api/secureNoteApi";
|
||||
|
||||
import { AttachmentResponse } from "./attachmentResponse";
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
import { PasswordHistoryResponse } from "./passwordHistoryResponse";
|
||||
|
||||
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[];
|
||||
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.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,38 +0,0 @@
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
import { SelectionReadOnlyResponse } from "./selectionReadOnlyResponse";
|
||||
|
||||
export class CollectionResponse extends BaseResponse {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
name: string;
|
||||
externalId: string;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.id = this.getResponseProperty("Id");
|
||||
this.organizationId = this.getResponseProperty("OrganizationId");
|
||||
this.name = this.getResponseProperty("Name");
|
||||
this.externalId = this.getResponseProperty("ExternalId");
|
||||
}
|
||||
}
|
||||
|
||||
export class CollectionDetailsResponse extends CollectionResponse {
|
||||
readOnly: boolean;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.readOnly = this.getResponseProperty("ReadOnly") || false;
|
||||
}
|
||||
}
|
||||
|
||||
export class CollectionGroupDetailsResponse extends CollectionResponse {
|
||||
groups: SelectionReadOnlyResponse[] = [];
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
const groups = this.getResponseProperty("Groups");
|
||||
if (groups != null) {
|
||||
this.groups = groups.map((g: any) => new SelectionReadOnlyResponse(g));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
import { EmergencyAccessStatusType } from "../../enums/emergencyAccessStatusType";
|
||||
import { EmergencyAccessType } from "../../enums/emergencyAccessType";
|
||||
import { KdfType } from "../../enums/kdfType";
|
||||
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
import { CipherResponse } from "./cipherResponse";
|
||||
|
||||
export class EmergencyAccessGranteeDetailsResponse extends BaseResponse {
|
||||
id: string;
|
||||
granteeId: string;
|
||||
name: string;
|
||||
email: string;
|
||||
type: EmergencyAccessType;
|
||||
status: EmergencyAccessStatusType;
|
||||
waitTimeDays: number;
|
||||
creationDate: string;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.id = this.getResponseProperty("Id");
|
||||
this.granteeId = this.getResponseProperty("GranteeId");
|
||||
this.name = this.getResponseProperty("Name");
|
||||
this.email = this.getResponseProperty("Email");
|
||||
this.type = this.getResponseProperty("Type");
|
||||
this.status = this.getResponseProperty("Status");
|
||||
this.waitTimeDays = this.getResponseProperty("WaitTimeDays");
|
||||
this.creationDate = this.getResponseProperty("CreationDate");
|
||||
}
|
||||
}
|
||||
|
||||
export class EmergencyAccessGrantorDetailsResponse extends BaseResponse {
|
||||
id: string;
|
||||
grantorId: string;
|
||||
name: string;
|
||||
email: string;
|
||||
type: EmergencyAccessType;
|
||||
status: EmergencyAccessStatusType;
|
||||
waitTimeDays: number;
|
||||
creationDate: string;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.id = this.getResponseProperty("Id");
|
||||
this.grantorId = this.getResponseProperty("GrantorId");
|
||||
this.name = this.getResponseProperty("Name");
|
||||
this.email = this.getResponseProperty("Email");
|
||||
this.type = this.getResponseProperty("Type");
|
||||
this.status = this.getResponseProperty("Status");
|
||||
this.waitTimeDays = this.getResponseProperty("WaitTimeDays");
|
||||
this.creationDate = this.getResponseProperty("CreationDate");
|
||||
}
|
||||
}
|
||||
|
||||
export class EmergencyAccessTakeoverResponse extends BaseResponse {
|
||||
keyEncrypted: string;
|
||||
kdf: KdfType;
|
||||
kdfIterations: number;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
|
||||
this.keyEncrypted = this.getResponseProperty("KeyEncrypted");
|
||||
this.kdf = this.getResponseProperty("Kdf");
|
||||
this.kdfIterations = this.getResponseProperty("KdfIterations");
|
||||
}
|
||||
}
|
||||
|
||||
export class EmergencyAccessViewResponse extends BaseResponse {
|
||||
keyEncrypted: string;
|
||||
ciphers: CipherResponse[] = [];
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
|
||||
this.keyEncrypted = this.getResponseProperty("KeyEncrypted");
|
||||
|
||||
const ciphers = this.getResponseProperty("Ciphers");
|
||||
if (ciphers != null) {
|
||||
this.ciphers = ciphers.map((c: any) => new CipherResponse(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import { DeviceType } from "../../enums/deviceType";
|
||||
import { EventType } from "../../enums/eventType";
|
||||
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
|
||||
export class EventResponse extends BaseResponse {
|
||||
type: EventType;
|
||||
userId: string;
|
||||
organizationId: string;
|
||||
providerId: string;
|
||||
cipherId: string;
|
||||
collectionId: string;
|
||||
groupId: string;
|
||||
policyId: string;
|
||||
organizationUserId: string;
|
||||
providerUserId: string;
|
||||
providerOrganizationId: string;
|
||||
actingUserId: string;
|
||||
date: string;
|
||||
deviceType: DeviceType;
|
||||
ipAddress: string;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.type = this.getResponseProperty("Type");
|
||||
this.userId = this.getResponseProperty("UserId");
|
||||
this.organizationId = this.getResponseProperty("OrganizationId");
|
||||
this.providerId = this.getResponseProperty("ProviderId");
|
||||
this.cipherId = this.getResponseProperty("CipherId");
|
||||
this.collectionId = this.getResponseProperty("CollectionId");
|
||||
this.groupId = this.getResponseProperty("GroupId");
|
||||
this.policyId = this.getResponseProperty("PolicyId");
|
||||
this.organizationUserId = this.getResponseProperty("OrganizationUserId");
|
||||
this.providerUserId = this.getResponseProperty("ProviderUserId");
|
||||
this.providerOrganizationId = this.getResponseProperty("ProviderOrganizationId");
|
||||
this.actingUserId = this.getResponseProperty("ActingUserId");
|
||||
this.date = this.getResponseProperty("Date");
|
||||
this.deviceType = this.getResponseProperty("DeviceType");
|
||||
this.ipAddress = this.getResponseProperty("IpAddress");
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
|
||||
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,12 +0,0 @@
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
|
||||
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,20 +0,0 @@
|
||||
import { PolicyType } from "../../enums/policyType";
|
||||
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
|
||||
export class PolicyResponse extends BaseResponse {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
type: PolicyType;
|
||||
data: any;
|
||||
enabled: boolean;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.id = this.getResponseProperty("Id");
|
||||
this.organizationId = this.getResponseProperty("OrganizationId");
|
||||
this.type = this.getResponseProperty("Type");
|
||||
this.data = this.getResponseProperty("Data");
|
||||
this.enabled = this.getResponseProperty("Enabled");
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import { SendType } from "../../enums/sendType";
|
||||
import { SendFileApi } from "../api/sendFileApi";
|
||||
import { SendTextApi } from "../api/sendTextApi";
|
||||
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
|
||||
export class SendAccessResponse extends BaseResponse {
|
||||
id: string;
|
||||
type: SendType;
|
||||
name: string;
|
||||
file: SendFileApi;
|
||||
text: SendTextApi;
|
||||
expirationDate: Date;
|
||||
creatorIdentifier: string;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.id = this.getResponseProperty("Id");
|
||||
this.type = this.getResponseProperty("Type");
|
||||
this.name = this.getResponseProperty("Name");
|
||||
|
||||
const text = this.getResponseProperty("Text");
|
||||
if (text != null) {
|
||||
this.text = new SendTextApi(text);
|
||||
}
|
||||
|
||||
const file = this.getResponseProperty("File");
|
||||
if (file != null) {
|
||||
this.file = new SendFileApi(file);
|
||||
}
|
||||
|
||||
this.expirationDate = this.getResponseProperty("ExpirationDate");
|
||||
this.creatorIdentifier = this.getResponseProperty("CreatorIdentifier");
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
|
||||
export class SendFileDownloadDataResponse extends BaseResponse {
|
||||
id: string = null;
|
||||
url: string = null;
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.id = this.getResponseProperty("Id");
|
||||
this.url = this.getResponseProperty("Url");
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { FileUploadType } from "../../enums/fileUploadType";
|
||||
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
import { SendResponse } from "./sendResponse";
|
||||
|
||||
export class SendFileUploadDataResponse extends BaseResponse {
|
||||
fileUploadType: FileUploadType;
|
||||
sendResponse: SendResponse;
|
||||
url: string = null;
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.fileUploadType = this.getResponseProperty("FileUploadType");
|
||||
const sendResponse = this.getResponseProperty("SendResponse");
|
||||
this.sendResponse = sendResponse == null ? null : new SendResponse(sendResponse);
|
||||
this.url = this.getResponseProperty("Url");
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import { SendType } from "../../enums/sendType";
|
||||
import { SendFileApi } from "../api/sendFileApi";
|
||||
import { SendTextApi } from "../api/sendTextApi";
|
||||
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
|
||||
export class SendResponse extends BaseResponse {
|
||||
id: string;
|
||||
accessId: string;
|
||||
type: SendType;
|
||||
name: string;
|
||||
notes: string;
|
||||
file: SendFileApi;
|
||||
text: SendTextApi;
|
||||
key: string;
|
||||
maxAccessCount?: number;
|
||||
accessCount: number;
|
||||
revisionDate: string;
|
||||
expirationDate: string;
|
||||
deletionDate: string;
|
||||
password: string;
|
||||
disable: boolean;
|
||||
hideEmail: boolean;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.id = this.getResponseProperty("Id");
|
||||
this.accessId = this.getResponseProperty("AccessId");
|
||||
this.type = this.getResponseProperty("Type");
|
||||
this.name = this.getResponseProperty("Name");
|
||||
this.notes = this.getResponseProperty("Notes");
|
||||
this.key = this.getResponseProperty("Key");
|
||||
this.maxAccessCount = this.getResponseProperty("MaxAccessCount");
|
||||
this.accessCount = this.getResponseProperty("AccessCount");
|
||||
this.revisionDate = this.getResponseProperty("RevisionDate");
|
||||
this.expirationDate = this.getResponseProperty("ExpirationDate");
|
||||
this.deletionDate = this.getResponseProperty("DeletionDate");
|
||||
this.password = this.getResponseProperty("Password");
|
||||
this.disable = this.getResponseProperty("Disabled") || false;
|
||||
this.hideEmail = this.getResponseProperty("HideEmail") || false;
|
||||
|
||||
const text = this.getResponseProperty("Text");
|
||||
if (text != null) {
|
||||
this.text = new SendTextApi(text);
|
||||
}
|
||||
|
||||
const file = this.getResponseProperty("File");
|
||||
if (file != null) {
|
||||
this.file = new SendFileApi(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import { BaseResponse } from "./baseResponse";
|
||||
import { CipherResponse } from "./cipherResponse";
|
||||
import { CollectionDetailsResponse } from "./collectionResponse";
|
||||
import { DomainsResponse } from "./domainsResponse";
|
||||
import { FolderResponse } from "./folderResponse";
|
||||
import { PolicyResponse } from "./policyResponse";
|
||||
import { ProfileResponse } from "./profileResponse";
|
||||
import { SendResponse } from "./sendResponse";
|
||||
|
||||
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,35 +0,0 @@
|
||||
import { Attachment } from "../domain/attachment";
|
||||
import { SymmetricCryptoKey } from "../domain/symmetricCryptoKey";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
import { CardLinkedId as LinkedId } from "../../enums/linkedIdType";
|
||||
import { linkedFieldOption } from "../../misc/linkedFieldOption.decorator";
|
||||
|
||||
import { ItemView } from "./itemView";
|
||||
|
||||
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;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
import { CipherRepromptType } from "../../enums/cipherRepromptType";
|
||||
import { CipherType } from "../../enums/cipherType";
|
||||
import { LinkedIdType } from "../../enums/linkedIdType";
|
||||
import { Cipher } from "../domain/cipher";
|
||||
|
||||
import { AttachmentView } from "./attachmentView";
|
||||
import { CardView } from "./cardView";
|
||||
import { FieldView } from "./fieldView";
|
||||
import { IdentityView } from "./identityView";
|
||||
import { LoginView } from "./loginView";
|
||||
import { PasswordHistoryView } from "./passwordHistoryView";
|
||||
import { SecureNoteView } from "./secureNoteView";
|
||||
import { View } from "./view";
|
||||
|
||||
export class CipherView implements View {
|
||||
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: any;
|
||||
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;
|
||||
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.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;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import { Collection } from "../domain/collection";
|
||||
import { ITreeNodeObject } from "../domain/treeNode";
|
||||
import { CollectionGroupDetailsResponse } from "../response/collectionResponse";
|
||||
|
||||
import { View } from "./view";
|
||||
|
||||
export class CollectionView implements View, ITreeNodeObject {
|
||||
id: string = null;
|
||||
organizationId: string = null;
|
||||
name: string = null;
|
||||
externalId: string = null;
|
||||
readOnly: boolean = null;
|
||||
hidePasswords: boolean = null;
|
||||
|
||||
constructor(c?: Collection | CollectionGroupDetailsResponse) {
|
||||
if (!c) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.id = c.id;
|
||||
this.organizationId = c.organizationId;
|
||||
this.externalId = c.externalId;
|
||||
if (c instanceof Collection) {
|
||||
this.readOnly = c.readOnly;
|
||||
this.hidePasswords = c.hidePasswords;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { EventType } from "../../enums/eventType";
|
||||
|
||||
export class EventView {
|
||||
message: string;
|
||||
humanReadableMessage: string;
|
||||
appIcon: string;
|
||||
appName: string;
|
||||
userId: string;
|
||||
userName: string;
|
||||
userEmail: string;
|
||||
date: string;
|
||||
ip: string;
|
||||
type: EventType;
|
||||
|
||||
constructor(data: Required<EventView>) {
|
||||
this.message = data.message;
|
||||
this.humanReadableMessage = data.humanReadableMessage;
|
||||
this.appIcon = data.appIcon;
|
||||
this.appName = data.appName;
|
||||
this.userId = data.userId;
|
||||
this.userName = data.userName;
|
||||
this.userEmail = data.userEmail;
|
||||
this.date = data.date;
|
||||
this.ip = data.ip;
|
||||
this.type = data.type;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { Folder } from "../domain/folder";
|
||||
import { ITreeNodeObject } from "../domain/treeNode";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
import { IdentityLinkedId as LinkedId } from "../../enums/linkedIdType";
|
||||
import { linkedFieldOption } from "../../misc/linkedFieldOption.decorator";
|
||||
import { Utils } from "../../misc/utils";
|
||||
|
||||
import { ItemView } from "./itemView";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user