1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-28 10:33:31 +00:00

migrate all exports to strict types

This commit is contained in:
jaasen-livefront
2025-11-04 15:53:15 -08:00
parent e49c316317
commit 1e78820b8e
14 changed files with 123 additions and 112 deletions

View File

@@ -36,23 +36,23 @@ export class CardExport {
return domain;
}
cardholderName: string = "";
brand: string = "";
number: string = "";
expMonth: string = "";
expYear: string = "";
code: string = "";
cardholderName?: string;
brand?: string;
number?: string;
expMonth?: string;
expYear?: string;
code?: string;
constructor(o?: CardView | CardDomain) {
if (o == null) {
return;
}
this.cardholderName = safeGetString(o.cardholderName ?? "") ?? "";
this.brand = safeGetString(o.brand ?? "") ?? "";
this.number = safeGetString(o.number ?? "") ?? "";
this.expMonth = safeGetString(o.expMonth ?? "") ?? "";
this.expYear = safeGetString(o.expYear ?? "") ?? "";
this.code = safeGetString(o.code ?? "") ?? "";
this.cardholderName = safeGetString(o.cardholderName);
this.brand = safeGetString(o.brand);
this.number = safeGetString(o.number);
this.expMonth = safeGetString(o.expMonth);
this.expYear = safeGetString(o.expYear);
this.code = safeGetString(o.code);
}
}

View File

@@ -31,11 +31,6 @@ export class CipherExport {
req.notes = "Some notes about this item.";
req.favorite = false;
req.fields = [];
req.login = null;
req.secureNote = null;
req.card = null;
req.identity = null;
req.sshKey = null;
req.reprompt = CipherRepromptType.None;
req.passwordHistory = [];
req.creationDate = new Date();
@@ -170,35 +165,35 @@ export class CipherExport {
}
type: CipherType = CipherType.Login;
folderId: string = "";
organizationId: string = "";
folderId?: string;
organizationId?: string;
collectionIds: string[] = [];
name: string = "";
notes: string = "";
notes?: string;
favorite: boolean = false;
fields: FieldExport[] = [];
login: LoginExport | null = null;
secureNote: SecureNoteExport | null = null;
card: CardExport | null = null;
identity: IdentityExport | null = null;
sshKey: SshKeyExport | null = null;
login?: LoginExport;
secureNote?: SecureNoteExport;
card?: CardExport;
identity?: IdentityExport;
sshKey?: SshKeyExport;
reprompt: CipherRepromptType = CipherRepromptType.None;
passwordHistory: PasswordHistoryExport[] = [];
revisionDate: Date;
creationDate: Date;
deletedDate: Date;
archivedDate: Date;
key: string = "";
key?: string;
// Use build method instead of ctor so that we can control order of JSON stringify for pretty print
build(o: CipherView | CipherDomain) {
this.organizationId = o.organizationId ?? "";
this.folderId = o.folderId ?? "";
this.organizationId = o.organizationId;
this.folderId = o.folderId;
this.type = o.type;
this.reprompt = o.reprompt;
this.name = safeGetString(o.name) ?? "";
this.notes = safeGetString(o.notes ?? "") ?? "";
this.name = safeGetString(o.name);
this.notes = safeGetString(o.notes);
if ("key" in o) {
this.key = o.key?.encryptedString ?? "";
}

View File

@@ -43,12 +43,12 @@ export class CollectionExport {
organizationId: OrganizationId;
name: string;
externalId: string;
externalId?: string;
// Use build method instead of ctor so that we can control order of JSON stringify for pretty print
build(o: CollectionView | CollectionDomain) {
this.organizationId = o.organizationId;
this.name = safeGetString(o.name) ?? "";
this.externalId = o.externalId ?? "";
this.name = safeGetString(o.name);
this.externalId = o.externalId;
}
}

View File

@@ -82,11 +82,11 @@ export class Fido2CredentialExport {
keyCurve: string = "";
keyValue: string = "";
rpId: string = "";
userHandle: string = "";
userName: string = "";
userHandle?: string;
userName?: string;
counter: string = "";
rpName: string = "";
userDisplayName: string = "";
rpName?: string;
userDisplayName?: string;
discoverable: string = "";
creationDate: Date = new Date();
@@ -100,18 +100,18 @@ export class Fido2CredentialExport {
return;
}
this.credentialId = safeGetString(o.credentialId) ?? "";
this.keyType = safeGetString(o.keyType) ?? "";
this.keyAlgorithm = safeGetString(o.keyAlgorithm) ?? "";
this.keyCurve = safeGetString(o.keyCurve) ?? "";
this.keyValue = safeGetString(o.keyValue) ?? "";
this.rpId = safeGetString(o.rpId) ?? "";
this.userHandle = safeGetString(o.userHandle ?? "") ?? "";
this.userName = safeGetString(o.userName ?? "") ?? "";
this.counter = safeGetString(String(o.counter)) ?? "";
this.rpName = safeGetString(o.rpName ?? "") ?? "";
this.userDisplayName = safeGetString(o.userDisplayName ?? "") ?? "";
this.discoverable = safeGetString(String(o.discoverable)) ?? "";
this.credentialId = safeGetString(o.credentialId);
this.keyType = safeGetString(o.keyType);
this.keyAlgorithm = safeGetString(o.keyAlgorithm);
this.keyCurve = safeGetString(o.keyCurve);
this.keyValue = safeGetString(o.keyValue);
this.rpId = safeGetString(o.rpId);
this.userHandle = safeGetString(o.userHandle);
this.userName = safeGetString(o.userName);
this.counter = safeGetString(String(o.counter));
this.rpName = safeGetString(o.rpName);
this.userDisplayName = safeGetString(o.userDisplayName);
this.discoverable = safeGetString(String(o.discoverable));
this.creationDate = o.creationDate;
}
}

View File

@@ -40,8 +40,8 @@ export class FieldExport {
return;
}
this.name = safeGetString(o.name ?? "") ?? "";
this.value = safeGetString(o.value ?? "") ?? "";
this.name = safeGetString(o.name);
this.value = safeGetString(o.value);
this.type = o.type;
this.linkedId = o.linkedId;
}

View File

@@ -25,6 +25,6 @@ export class FolderExport {
// Use build method instead of ctor so that we can control order of JSON stringify for pretty print
build(o: FolderView | FolderDomain) {
this.name = safeGetString(o.name) ?? "";
this.name = safeGetString(o.name);
}
}

View File

@@ -72,47 +72,47 @@ export class IdentityExport {
return domain;
}
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 = "";
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(o?: IdentityView | IdentityDomain) {
if (o == null) {
return;
}
this.title = safeGetString(o.title ?? "") ?? "";
this.firstName = safeGetString(o.firstName ?? "") ?? "";
this.middleName = safeGetString(o.middleName ?? "") ?? "";
this.lastName = safeGetString(o.lastName ?? "") ?? "";
this.address1 = safeGetString(o.address1 ?? "") ?? "";
this.address2 = safeGetString(o.address2 ?? "") ?? "";
this.address3 = safeGetString(o.address3 ?? "") ?? "";
this.city = safeGetString(o.city ?? "") ?? "";
this.state = safeGetString(o.state ?? "") ?? "";
this.postalCode = safeGetString(o.postalCode ?? "") ?? "";
this.country = safeGetString(o.country ?? "") ?? "";
this.company = safeGetString(o.company ?? "") ?? "";
this.email = safeGetString(o.email ?? "") ?? "";
this.phone = safeGetString(o.phone ?? "") ?? "";
this.ssn = safeGetString(o.ssn ?? "") ?? "";
this.username = safeGetString(o.username ?? "") ?? "";
this.passportNumber = safeGetString(o.passportNumber ?? "") ?? "";
this.licenseNumber = safeGetString(o.licenseNumber ?? "") ?? "";
this.title = safeGetString(o.title);
this.firstName = safeGetString(o.firstName);
this.middleName = safeGetString(o.middleName);
this.lastName = safeGetString(o.lastName);
this.address1 = safeGetString(o.address1);
this.address2 = safeGetString(o.address2);
this.address3 = safeGetString(o.address3);
this.city = safeGetString(o.city);
this.state = safeGetString(o.state);
this.postalCode = safeGetString(o.postalCode);
this.country = safeGetString(o.country);
this.company = safeGetString(o.company);
this.email = safeGetString(o.email);
this.phone = safeGetString(o.phone);
this.ssn = safeGetString(o.ssn);
this.username = safeGetString(o.username);
this.passportNumber = safeGetString(o.passportNumber);
this.licenseNumber = safeGetString(o.licenseNumber);
}
}

View File

@@ -34,7 +34,7 @@ export class LoginUriExport {
return;
}
this.uri = safeGetString(o.uri ?? "") ?? "";
this.uri = safeGetString(o.uri);
if ("uriChecksum" in o) {
this.uriChecksum = o.uriChecksum?.encryptedString;
}

View File

@@ -34,8 +34,8 @@ export class LoginExport {
if (req.uris != null) {
domain.uris = req.uris.map((u) => LoginUriExport.toDomain(u));
}
domain.username = new EncString(req.username ?? "");
domain.password = new EncString(req.password ?? "");
domain.username = new EncString(req.username);
domain.password = new EncString(req.password);
domain.totp = new EncString(req.totp ?? "");
// Fido2credentials are currently not supported for exports.
@@ -61,8 +61,8 @@ export class LoginExport {
this.fido2Credentials = o.fido2Credentials.map((key) => new Fido2CredentialExport(key));
}
this.username = safeGetString(o.username ?? "") ?? "";
this.password = safeGetString(o.password ?? "") ?? "";
this.totp = safeGetString(o.totp ?? "") ?? "";
this.username = safeGetString(o.username);
this.password = safeGetString(o.password);
this.totp = safeGetString(o.totp);
}
}

View File

@@ -32,7 +32,7 @@ export class PasswordHistoryExport {
return;
}
this.password = safeGetString(o.password ?? "") ?? "";
this.password = safeGetString(o.password);
this.lastUsedDate = o.lastUsedDate ?? new Date();
}
}

View File

@@ -36,8 +36,8 @@ export class SshKeyExport {
return;
}
this.privateKey = safeGetString(o.privateKey ?? "") ?? "";
this.publicKey = safeGetString(o.publicKey ?? "") ?? "";
this.keyFingerprint = safeGetString(o.keyFingerprint ?? "") ?? "";
this.privateKey = safeGetString(o.privateKey);
this.publicKey = safeGetString(o.publicKey);
this.keyFingerprint = safeGetString(o.keyFingerprint);
}
}

View File

@@ -1,12 +1,12 @@
import { EncString } from "../../key-management/crypto/models/enc-string";
export function safeGetString(value: string | EncString) {
if (value == null) {
return null;
export function safeGetString(value?: string | EncString) {
if (!value) {
return "";
}
if (typeof value == "string") {
return value;
}
return value?.encryptedString;
return value?.encryptedString ?? "";
}

View File

@@ -78,8 +78,8 @@ function generateCipherView(deleted: boolean) {
},
LoginView,
),
collectionIds: null,
deletedDate: deleted ? new Date() : null,
collectionIds: [],
deletedDate: deleted ? new Date() : undefined,
},
CipherView,
);
@@ -98,8 +98,8 @@ function generateCipherDomain(deleted: boolean) {
},
Login,
),
collectionIds: null,
deletedDate: deleted ? new Date() : null,
collectionIds: [],
deletedDate: deleted ? new Date() : undefined,
},
Cipher,
);
@@ -126,15 +126,19 @@ function generateFolder() {
}
function expectEqualCiphers(ciphers: CipherView[] | Cipher[], jsonResult: string) {
const actual = JSON.stringify(JSON.parse(jsonResult).items);
const items: CipherWithIdExport[] = [];
const parsed = JSON.parse(jsonResult);
const actualItems = sanitizeDates(parsed.items);
const expected: CipherWithIdExport[] = [];
ciphers.forEach((c: CipherView | Cipher) => {
const item = new CipherWithIdExport();
item.build(c);
items.push(item);
expected.push(item);
});
expect(actual).toEqual(JSON.stringify(items));
const expectedSanitized = sanitizeDates(expected);
expect(JSON.stringify(actualItems)).toEqual(JSON.stringify(expectedSanitized));
}
function expectEqualFolderViews(folderViews: FolderView[] | Folder[], jsonResult: string) {
@@ -162,6 +166,18 @@ function expectEqualFolders(folders: Folder[], jsonResult: string) {
expect(actual).toMatchObject(expected);
}
function sanitizeDates<T>(obj: T): T {
const dateKeyRegex = /Date$/i;
return JSON.parse(
JSON.stringify(obj, (key, value) => {
if (key && dateKeyRegex.test(key)) {
return undefined; // omit this property
}
return value;
}),
);
}
describe("VaultExportService", () => {
let exportService: IndividualVaultExportService;
let cryptoFunctionService: MockProxy<CryptoFunctionService>;

View File

@@ -254,7 +254,7 @@ export class IndividualVaultExportService
}
const cipher = new CipherWithIdExport();
cipher.build(c);
cipher.collectionIds = null;
cipher.collectionIds = [];
jsonDoc.items.push(cipher);
});
@@ -316,7 +316,7 @@ export class IndividualVaultExportService
}
const cipher = new CipherWithIdExport();
cipher.build(c);
cipher.collectionIds = null;
cipher.collectionIds = [];
jsonDoc.items.push(cipher);
});