Skip to content

Commit

Permalink
feat: Convert papers/contacts to CipherData instead of CipherResponse
Browse files Browse the repository at this point in the history
We were converting papers/contacts to CipherResponse because it is the model used by default during the sync.

Here we choose to convert to CipherData instead because :
- it will help us add a fallback to the sync. When papers/contacts sync will fail, we will be able to use the previous papers/contacts stored locally (they are stored as CipherData)
- the conversion is simplier (it involves less classes)
- we can still inject our papers/contacts during the sync thanks to the upsert method
  • Loading branch information
zatteo committed Apr 19, 2024
1 parent db487cf commit 52bfa43
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 122 deletions.
6 changes: 3 additions & 3 deletions libs/common/src/vault/services/sync/sync.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export class SyncService implements SyncServiceAbstraction {
await this.syncProfile(response.profile);
await this.syncFolders(response.folders);
await this.syncCollections(response.collections);
await this.syncCiphers(response.ciphers);

// Cozy customization
await this.cozyClientService.getClientInstance();
Expand All @@ -132,15 +133,14 @@ export class SyncService implements SyncServiceAbstraction {
const [papersPromise, contactsPromise] = await Promise.allSettled(fetchPromises);

if (papersPromise.status === "fulfilled") {
response.ciphers.push(...papersPromise.value);
await this.cipherService.upsert(papersPromise.value);
}

if (contactsPromise.status === "fulfilled") {
response.ciphers.push(...contactsPromise.value);
await this.cipherService.upsert(contactsPromise.value);
}
// Cozy customization end

await this.syncCiphers(response.ciphers);
await this.syncSends(response.sends);
await this.syncSettings(response.domains);
await this.syncPolicies(response.policies);
Expand Down
31 changes: 9 additions & 22 deletions libs/cozy/contact.helper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { models } from "cozy-client";

import { ContactApi } from "@bitwarden/common/models/api/contact.api";
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key";
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
import { CipherResponse } from "@bitwarden/common/vault/models/response/cipher.response";
Expand All @@ -9,7 +8,7 @@ import { ContactView } from "@bitwarden/common/vault/models/view/contact.view";

const { getInitials } = models.contact;

import { buildFieldsFromContact, copyEncryptedFields } from "./fields.helper";
import { buildFieldsFromContact } from "./fields.helper";

const getPrimaryEmail = (contact: any): string | undefined => {
return contact.email?.find((email: any) => email.primary)?.address;
Expand All @@ -19,7 +18,7 @@ const getPrimaryPhone = (contact: any): string | undefined => {
return contact.phone?.find((phone: any) => phone.primary)?.number;
};

export const convertContactToCipherResponse = async (
export const convertContactToCipherData = async (
cipherService: any,
i18nService: any,
contact: any,
Expand All @@ -36,25 +35,13 @@ export const convertContactToCipherResponse = async (
cipherView.contact.primaryPhone = getPrimaryPhone(contact);
cipherView.favorite = !!contact.cozyMetadata?.favorite;
cipherView.fields = buildFieldsFromContact(i18nService, contact);
cipherView.contact.me = contact.me;
cipherView.creationDate = new Date(contact.cozyMetadata?.createdAt);
cipherView.revisionDate = new Date(contact.cozyMetadata?.updatedAt);

const cipherEncrypted = await cipherService.encrypt(cipherView, key);
const cipherViewEncrypted = new CipherView(cipherEncrypted);
const cipherViewResponse = new CipherResponse(cipherViewEncrypted);
cipherViewResponse.id = cipherEncrypted.id;
cipherViewResponse.name = cipherEncrypted.name?.encryptedString ?? "";
cipherViewResponse.contact = new ContactApi();
cipherViewResponse.contact.displayName =
cipherEncrypted.contact.displayName?.encryptedString ?? "";
cipherViewResponse.contact.initials = cipherEncrypted.contact.initials?.encryptedString ?? "";
cipherViewResponse.contact.primaryEmail =
cipherEncrypted.contact.primaryEmail?.encryptedString ?? "";
cipherViewResponse.contact.primaryPhone =
cipherEncrypted.contact.primaryPhone?.encryptedString ?? "";
cipherViewResponse.favorite = cipherEncrypted.favorite;
cipherViewResponse.creationDate = contact.cozyMetadata?.createdAt;
cipherViewResponse.revisionDate = contact.cozyMetadata?.updatedAt;
cipherViewResponse.fields = copyEncryptedFields(cipherEncrypted.fields ?? []);
cipherViewResponse.contact.me = contact.me;

return cipherViewResponse;

const cipherData = cipherEncrypted.toCipherData();

return cipherData;
};
28 changes: 8 additions & 20 deletions libs/cozy/contactCipher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,26 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data";
import { CipherResponse } from "@bitwarden/common/vault/models/response/cipher.response";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";

import { convertContactToCipherResponse } from "./contact.helper";
import { convertContactToCipherData } from "./contact.helper";
import { fetchContacts, fetchContact } from "./queries";

const convertContactsAsCiphers = async (
cipherService: any,
cryptoService: CryptoService,
i18nService: any,
contacts: any
): Promise<CipherResponse[]> => {
): Promise<CipherData[]> => {
const contactsCiphers = [];

const key = await cryptoService.getKeyForUserEncryption();

for (const contact of contacts) {
try {
const cipherResponse = await convertContactToCipherResponse(
cipherService,
i18nService,
contact,
key
);

contactsCiphers.push(cipherResponse);
const cipherData = await convertContactToCipherData(cipherService, i18nService, contact, key);

contactsCiphers.push(cipherData);
} catch (e) {
console.log(`Error during conversion of contact ${contact.id}`, contact, e);
}
Expand All @@ -45,7 +39,7 @@ export const fetchContactsAndConvertAsCiphers = async (
cryptoService: CryptoService,
cozyClientService: any,
i18nService: any
): Promise<CipherResponse[]> => {
): Promise<CipherData[]> => {
const client = await cozyClientService.getClientInstance();

try {
Expand Down Expand Up @@ -86,15 +80,9 @@ export const favoriteContactCipher = async (
},
});

const cipherResponse = await convertContactToCipherResponse(
cipherService,
i18nService,
updatedContact
);

const cipherData = new CipherData(cipherResponse);
const cipherData = await convertContactToCipherData(cipherService, i18nService, updatedContact);

await cipherService.upsert([cipherData]);
await cipherService.upsert(cipherData);

return true;
};
Expand Down
23 changes: 0 additions & 23 deletions libs/cozy/fields.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ import { models } from "cozy-client";

import { FieldSubType } from "@bitwarden/common/enums/fieldSubType";
import { FieldType } from "@bitwarden/common/enums/fieldType";
import { FieldApi } from "@bitwarden/common/models/api/field.api";
import { ExpirationDateData } from "@bitwarden/common/vault/models/data/expiration-date.data";
import { LabelData } from "@bitwarden/common/vault/models/data/label.data";
import { Field } from "@bitwarden/common/vault/models/domain/field";
import { FieldView } from "@bitwarden/common/vault/models/view/field.view";

import {
Expand Down Expand Up @@ -52,27 +50,6 @@ export const buildField = (name: string, value: string, options: FieldOptions =
return field;
};

export const copyEncryptedFields = (fields: Field[]): FieldApi[] => {
const encryptedFields = [];

for (const field of fields) {
encryptedFields.push(
new FieldApi({
Id: field.id,
ParentId: field.parentId,
Type: field.type,
Subtype: field.subtype,
ExpirationData: field.expirationData,
Label: field.label,
Name: field.name?.encryptedString || "",
Value: field.value?.encryptedString || "",
})
);
}

return encryptedFields;
};

// Paper fields

export const buildFieldsFromPaper = (i18nService: any, paper: any): FieldView[] => {
Expand Down
29 changes: 8 additions & 21 deletions libs/cozy/note.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ import { Node, Schema } from "prosemirror-model";
import { EditorState } from "prosemirror-state";

import { PaperType } from "@bitwarden/common/enums/paperType";
import { PaperApi } from "@bitwarden/common/models/api/paper.api";
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key";
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
import { CipherResponse } from "@bitwarden/common/vault/models/response/cipher.response";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { PaperView } from "@bitwarden/common/vault/models/view/paper.view";

import { buildFieldsFromPaper, copyEncryptedFields, buildField } from "./fields.helper";
import { buildFieldsFromPaper, buildField } from "./fields.helper";

interface NoteConversionOptions {
noteIllustrationUrl: string;
Expand Down Expand Up @@ -52,7 +51,7 @@ export const noteToText = (note: any): string => {

return textOnly;
};
export const convertNoteToCipherResponse = async (
export const convertNoteToCipherData = async (
cipherService: any,
i18nService: any,
paper: any,
Expand All @@ -74,24 +73,12 @@ export const convertNoteToCipherResponse = async (
cipherView.paper.qualificationLabel = paper.metadata.qualification.label;
cipherView.fields = buildFieldsFromPaper(i18nService, paper);
cipherView.fields.push(buildField(i18nService.t("content"), cipherView.paper.noteContent));
cipherView.creationDate = new Date(paper.cozyMetadata.createdAt);
cipherView.revisionDate = new Date(paper.cozyMetadata.updatedAt);

const cipherEncrypted = await cipherService.encrypt(cipherView, key);
const cipherViewEncrypted = new CipherView(cipherEncrypted);
const cipherViewResponse = new CipherResponse(cipherViewEncrypted);
cipherViewResponse.id = cipherEncrypted.id;
cipherViewResponse.name = cipherEncrypted.name.encryptedString;

cipherViewResponse.paper = new PaperApi();
cipherViewResponse.paper.type = cipherView.paper.type;
cipherViewResponse.paper.noteContent = cipherEncrypted.paper.noteContent?.encryptedString ?? "";
cipherViewResponse.paper.illustrationThumbnailUrl =
cipherEncrypted.paper.illustrationThumbnailUrl.encryptedString;
cipherViewResponse.paper.illustrationUrl = cipherEncrypted.paper.illustrationUrl.encryptedString;
cipherViewResponse.paper.qualificationLabel =
cipherEncrypted.paper.qualificationLabel.encryptedString;
cipherViewResponse.fields = copyEncryptedFields(cipherEncrypted.fields);
cipherViewResponse.creationDate = paper.cozyMetadata.createdAt;
cipherViewResponse.revisionDate = paper.cozyMetadata.updatedAt;

return cipherViewResponse;

const cipherData = cipherEncrypted.toCipherData();

return cipherData;
};
26 changes: 6 additions & 20 deletions libs/cozy/paper.helper.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { PaperType } from "@bitwarden/common/enums/paperType";
import { PaperApi } from "@bitwarden/common/models/api/paper.api";
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key";
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
import { CipherResponse } from "@bitwarden/common/vault/models/response/cipher.response";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { PaperView } from "@bitwarden/common/vault/models/view/paper.view";

import { buildFieldsFromPaper, copyEncryptedFields } from "./fields.helper";
import { buildFieldsFromPaper } from "./fields.helper";

interface PaperConversionOptions {
baseUrl: string;
Expand Down Expand Up @@ -36,7 +35,7 @@ const buildIllustrationUrl = (paper: any, baseUrl: string) => {
: DEFAULT_THUMBNAIL_URL;
};

export const convertPaperToCipherResponse = async (
export const convertPaperToCipherData = async (
cipherService: any,
i18nService: any,
paper: any,
Expand All @@ -57,25 +56,12 @@ export const convertPaperToCipherResponse = async (
cipherView.paper.qualificationLabel = paper.metadata.qualification.label;
cipherView.fields = buildFieldsFromPaper(i18nService, paper);
cipherView.favorite = !!paper.cozyMetadata.favorite;
cipherView.creationDate = new Date(paper.cozyMetadata.createdAt);
cipherView.revisionDate = new Date(paper.cozyMetadata.updatedAt);

const cipherEncrypted = await cipherService.encrypt(cipherView, key);
const cipherViewEncrypted = new CipherView(cipherEncrypted);
const cipherViewResponse = new CipherResponse(cipherViewEncrypted);
cipherViewResponse.id = cipherEncrypted.id;
cipherViewResponse.name = cipherEncrypted.name.encryptedString;

cipherViewResponse.paper = new PaperApi();
cipherViewResponse.paper.type = cipherView.paper.type;
cipherViewResponse.paper.ownerName = cipherEncrypted.paper.ownerName?.encryptedString ?? "";
cipherViewResponse.paper.illustrationThumbnailUrl =
cipherEncrypted.paper.illustrationThumbnailUrl.encryptedString;
cipherViewResponse.paper.illustrationUrl = cipherEncrypted.paper.illustrationUrl.encryptedString;
cipherViewResponse.paper.qualificationLabel =
cipherEncrypted.paper.qualificationLabel.encryptedString;
cipherViewResponse.fields = copyEncryptedFields(cipherEncrypted.fields);
cipherViewResponse.favorite = cipherEncrypted.favorite;
cipherViewResponse.creationDate = paper.cozyMetadata.createdAt;
cipherViewResponse.revisionDate = paper.cozyMetadata.updatedAt;
const cipherData = cipherEncrypted.toCipherData();

return cipherViewResponse;
return cipherData;
};
23 changes: 10 additions & 13 deletions libs/cozy/paperCipher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data";
import { CipherResponse } from "@bitwarden/common/vault/models/response/cipher.response";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";

import { convertNoteToCipherResponse, isNote, fetchNoteIllustrationUrl } from "./note.helper";
import { convertPaperToCipherResponse } from "./paper.helper";
import { convertNoteToCipherData, isNote, fetchNoteIllustrationUrl } from "./note.helper";
import { convertPaperToCipherData } from "./paper.helper";
import { fetchPapers, fetchPaper } from "./queries";

const convertPapersAsCiphers = async (
Expand All @@ -21,7 +20,7 @@ const convertPapersAsCiphers = async (
i18nService: any,
client: CozyClient,
papers: any
): Promise<CipherResponse[]> => {
): Promise<CipherData[]> => {
const baseUrl = client.getStackClient().uri;

const papersCiphers = [];
Expand All @@ -31,10 +30,10 @@ const convertPapersAsCiphers = async (
const key = await cryptoService.getKeyForUserEncryption();

for (const paper of papers) {
let cipherResponse: CipherResponse;
let cipherData: CipherData;
try {
if (isNote(paper)) {
cipherResponse = await convertNoteToCipherResponse(
cipherData = await convertNoteToCipherData(
cipherService,
i18nService,
paper,
Expand All @@ -44,7 +43,7 @@ const convertPapersAsCiphers = async (
key
);
} else {
cipherResponse = await convertPaperToCipherResponse(
cipherData = await convertPaperToCipherData(
cipherService,
i18nService,
paper,
Expand All @@ -55,7 +54,7 @@ const convertPapersAsCiphers = async (
);
}

papersCiphers.push(cipherResponse);
papersCiphers.push(cipherData);
} catch (e) {
console.log(`Error during conversion of paper ${paper.id}`, paper, e);
}
Expand All @@ -69,7 +68,7 @@ export const fetchPapersAndConvertAsCiphers = async (
cryptoService: CryptoService,
cozyClientService: any,
i18nService: any
): Promise<CipherResponse[]> => {
): Promise<CipherData[]> => {
const client = await cozyClientService.getClientInstance();

try {
Expand Down Expand Up @@ -113,7 +112,7 @@ export const favoritePaperCipher = async (

const [updatePaperWithContacts] = client.hydrateDocuments("io.cozy.files", [updatedPaper]);

const cipherResponse = await convertPaperToCipherResponse(
const cipherData = await convertPaperToCipherData(
cipherService,
i18nService,
updatePaperWithContacts,
Expand All @@ -122,9 +121,7 @@ export const favoritePaperCipher = async (
}
);

const cipherData = new CipherData(cipherResponse);

await cipherService.upsert([cipherData]);
await cipherService.upsert(cipherData);

return true;
};
Expand Down

0 comments on commit 52bfa43

Please sign in to comment.