Fix key verification dependencies for prod build

This commit is contained in:
mab 2025-03-19 15:01:15 +01:00
parent 55f6a39ca6
commit 7e78fccce1
22 changed files with 10177 additions and 79 deletions

View file

@ -22,6 +22,10 @@
android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature
android:name="android.hardware.camera"
android:required="false"/>
<!-- We have to enable cleartext (non-HTTPS) traffic because of the external email content
which might still be served or HTTP. The only alternative is to proxy all of it. -->

View file

@ -17,6 +17,7 @@ export const dependencyMap = {
"better-sqlite3": path.normalize("./libs/better-sqlite3.mjs"),
winreg: path.normalize("./libs/winreg.mjs"),
undici: path.normalize("./libs/undici.mjs"),
jsqr: path.normalize("./libs/jsQR.js"),
}
/**
@ -276,7 +277,7 @@ export function getChunkName(moduleId, { getModuleInfo }) {
moduleId.includes("commonjs-dynamic-modules")
) {
return "polyfill-helpers"
} else if (isIn("src/common/settings") || isIn("src/common/subscription") || isIn("libs/qrcode") || isIn("src/common/termination")) {
} else if (isIn("src/common/settings") || isIn("src/common/subscription") || isIn("libs/qrcode") || isIn("libs/jsQR") || isIn("src/common/termination")) {
// subscription and settings depend on each other right now.
// subscription is also a kitchen sink with signup, utils and views, we should break it up
return "settings"

View file

@ -35,6 +35,7 @@ const clientDependencies = [
{ src: "../node_modules/linkifyjs/dist/linkify.es.js", target: "linkify.js", bundling: "copy" },
{ src: "../node_modules/linkify-html/dist/linkify-html.es.js", target: "linkify-html.js", bundling: "copy" },
{ src: "../node_modules/luxon/build/es6/luxon.js", target: "luxon.js", bundling: "copy" },
{ src: "../node_modules/jsqr/dist/jsQR.js", target: "jsQR.js", bundling: "copy" },
{ src: "../node_modules/jszip/dist/jszip.js", target: "jszip.js", bundling: "rollupWeb" },
{ src: "../node_modules/cborg/cborg.js", target: "cborg.js", bundling: "rollupWeb" },
{ src: "../node_modules/qrcode-svg/lib/qrcode.js", target: "qrcode.js", bundling: "rollupWeb" },

10102
libs/jsQR.js vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,7 @@ import { PartialRecipient, Recipient, RecipientType } from "../../../../common/a
import { haveSameId, Stripped } from "../../../../common/api/common/utils/EntityUtils.js"
import { cleanMailAddress, findRecipientWithAddress } from "../../../../common/api/common/utils/CommonCalendarUtils.js"
import { assertNotNull, clone, defer, DeferredObject, findAll, lazy, noOp, trisectingDiff } from "@tutao/tutanota-utils"
import { CalendarAttendeeStatus, ConversationType, ShareCapability } from "../../../../common/api/common/TutanotaConstants.js"
import { CalendarAttendeeStatus, ConversationType, KeyVerificationState, ShareCapability } from "../../../../common/api/common/TutanotaConstants.js"
import { RecipientsModel, ResolveMode } from "../../../../common/api/main/RecipientsModel.js"
import { Guest } from "../../view/CalendarInvites.js"
import { isSecurePassword } from "../../../../common/misc/passwords/PasswordUtils.js"
@ -28,7 +28,6 @@ import { getContactDisplayName } from "../../../../common/contactsFunctionality/
import { RecipientField } from "../../../../common/mailFunctionality/SharedMailUtils.js"
import { hasSourceUrl } from "../../../../common/calendar/date/CalendarUtils"
import { lang } from "../../../../common/misc/LanguageViewModel.js"
import { KeyVerificationState } from "../../../../common/api/worker/facades/lazy/KeyVerificationFacade"
/** there is no point in returning recipients, the SendMailModel will re-resolve them anyway. */
type AttendanceModelResult = {

View file

@ -112,7 +112,6 @@ import { ContactSuggestion } from "../common/native/common/generatedipc/ContactS
import { MailImporter } from "../mail-app/mail/import/MailImporter.js"
import { SyncTracker } from "../common/api/main/SyncTracker.js"
import { KeyVerificationFacade } from "../common/api/worker/facades/lazy/KeyVerificationFacade"
import { PublicKeyProvider } from "../common/api/worker/facades/PublicKeyProvider"
assertMainOrNode()
@ -142,7 +141,6 @@ class CalendarLocator {
bookingFacade!: BookingFacade
mailAddressFacade!: MailAddressFacade
keyVerificationFacade!: KeyVerificationFacade
publicKeyProvider!: PublicKeyProvider
blobFacade!: BlobFacade
userManagementFacade!: UserManagementFacade
recoverCodeFacade!: RecoverCodeFacade
@ -176,15 +174,7 @@ class CalendarLocator {
readonly recipientsModel: lazyAsync<RecipientsModel> = lazyMemoized(async () => {
const { RecipientsModel } = await import("../common/api/main/RecipientsModel.js")
return new RecipientsModel(
this.contactModel,
this.logins,
this.mailFacade,
this.entityClient,
this.keyVerificationFacade,
this.serviceExecutor,
this.publicKeyProvider,
)
return new RecipientsModel(this.contactModel, this.logins, this.mailFacade, this.entityClient, this.keyVerificationFacade)
})
async noZoneDateProvider(): Promise<NoZoneDateProvider> {

View file

@ -514,6 +514,12 @@ export const enum KeyVerificationResultType {
QR_FINGERPRINT_MISMATCH = "3",
}
export enum KeyVerificationState {
NO_ENTRY, // Identity is not trusted by user
VERIFIED, // Identity is trusted and verified
MISMATCH, // Identity is trusted but not verified
}
export const MAX_ATTACHMENT_SIZE = 1024 * 1024 * 25
export const MAX_LOGO_SIZE = 1024 * 100
export const MAX_BASE64_IMAGE_SIZE = MAX_LOGO_SIZE

View file

@ -1,5 +1,5 @@
import { Contact } from "../../entities/tutanota/TypeRefs"
import { KeyVerificationState } from "../../worker/facades/lazy/KeyVerificationFacade"
import { KeyVerificationState } from "../TutanotaConstants"
export const enum RecipientType {
UNKNOWN = "unknown",

View file

@ -8,9 +8,8 @@ import { BoundedExecutor, LazyLoaded } from "@tutao/tutanota-utils"
import { Contact, ContactTypeRef } from "../entities/tutanota/TypeRefs"
import { cleanMailAddress } from "../common/utils/CommonCalendarUtils.js"
import { createNewContact, isTutaMailAddress } from "../../mailFunctionality/SharedMailUtils.js"
import { KeyVerificationFacade, KeyVerificationState } from "../worker/facades/lazy/KeyVerificationFacade"
import { IServiceExecutor } from "../common/ServiceRequest"
import { PublicKeyProvider } from "../worker/facades/PublicKeyProvider"
import type { KeyVerificationFacade } from "../worker/facades/lazy/KeyVerificationFacade"
import { KeyVerificationState } from "../common/TutanotaConstants.js"
/**
* A recipient that can be resolved to obtain contact and recipient type
@ -48,8 +47,6 @@ export class RecipientsModel {
private readonly mailFacade: MailFacade,
private readonly entityClient: EntityClient,
private readonly keyVerificationFacade: KeyVerificationFacade,
private readonly serviceExecutor: IServiceExecutor,
private readonly publicKeyProvider: PublicKeyProvider,
) {}
/**
@ -64,8 +61,6 @@ export class RecipientsModel {
(mailAddress) => this.executor.run(this.resolveRecipientType(mailAddress)),
this.entityClient,
this.keyVerificationFacade,
this.serviceExecutor,
this.publicKeyProvider,
resolveMode,
)
}
@ -116,8 +111,6 @@ class ResolvableRecipientImpl implements ResolvableRecipient {
private readonly typeResolver: (mailAddress: string) => Promise<RecipientType>,
private readonly entityClient: EntityClient,
private readonly keyVerificationFacade: KeyVerificationFacade,
private readonly serviceExecutor: IServiceExecutor,
private readonly publicKeyProvider: PublicKeyProvider,
resolveMode: ResolveMode,
) {
if (isTutaMailAddress(arg.address) || arg.type === RecipientType.INTERNAL) {

View file

@ -2,7 +2,6 @@ import { assertWorkerOrNode } from "../../common/Env"
import {
AesKey,
AsymmetricKeyPair,
PublicKey,
bitArrayToUint8Array,
EccKeyPair,
EccPublicKey,
@ -13,13 +12,20 @@ import {
isVersionedRsaEccPublicKey,
isVersionedRsaOrRsaEccPublicKey,
PQPublicKeys,
PublicKey,
RsaPrivateKey,
uint8ArrayToBitArray,
} from "@tutao/tutanota-crypto"
import type { RsaImplementation } from "./RsaImplementation"
import { PQFacade } from "../facades/PQFacade.js"
import { CryptoError } from "@tutao/tutanota-crypto/error.js"
import { asCryptoProtoocolVersion, CryptoProtocolVersion, EncryptionAuthStatus, PublicKeyIdentifierType } from "../../common/TutanotaConstants.js"
import {
asCryptoProtoocolVersion,
CryptoProtocolVersion,
EncryptionAuthStatus,
KeyVerificationState,
PublicKeyIdentifierType,
} from "../../common/TutanotaConstants.js"
import { arrayEquals, assertNotNull, lazyAsync, Versioned } from "@tutao/tutanota-utils"
import { KeyLoaderFacade, parseKeyVersion } from "../facades/KeyLoaderFacade.js"
import { ProgrammingError } from "../../common/error/ProgrammingError.js"
@ -27,7 +33,7 @@ import { createPublicKeyPutIn, PubEncKeyData } from "../../entities/sys/TypeRefs
import { CryptoWrapper } from "./CryptoWrapper.js"
import { PublicKeyService } from "../../entities/sys/Services.js"
import { IServiceExecutor } from "../../common/ServiceRequest.js"
import { KeyVerificationFacade, KeyVerificationState } from "../facades/lazy/KeyVerificationFacade"
import type { KeyVerificationFacade } from "../facades/lazy/KeyVerificationFacade"
import { PublicKeyIdentifier, PublicKeyProvider } from "../facades/PublicKeyProvider.js"
import { KeyVersion } from "@tutao/tutanota-utils/dist/Utils.js"

View file

@ -22,6 +22,7 @@ import {
CryptoProtocolVersion,
EncryptionAuthStatus,
GroupType,
KeyVerificationState,
PermissionType,
PublicKeyIdentifierType,
SYSTEM_GROUP_MAIL_ADDRESS,
@ -65,13 +66,13 @@ import {
aes256RandomKey,
aesEncrypt,
AesKey,
PublicKey,
bitArrayToUint8Array,
decryptKey,
EccPublicKey,
encryptKey,
isPqKeyPairs,
isVersionedPqPublicKey,
PublicKey,
sha256Hash,
} from "@tutao/tutanota-crypto"
import { RecipientNotResolvedError } from "../../common/error/RecipientNotResolvedError"
@ -87,7 +88,7 @@ import { CryptoError } from "@tutao/tutanota-crypto/error.js"
import { KeyLoaderFacade, parseKeyVersion } from "../facades/KeyLoaderFacade.js"
import { encryptKeyWithVersionedKey, VersionedEncryptedKey, VersionedKey } from "./CryptoWrapper.js"
import { AsymmetricCryptoFacade } from "./AsymmetricCryptoFacade.js"
import { KeyVerificationFacade, KeyVerificationState } from "../facades/lazy/KeyVerificationFacade"
import type { KeyVerificationFacade } from "../facades/lazy/KeyVerificationFacade"
import { UnverifiedRecipientError } from "../../common/error/UnverifiedRecipientError"
import { PublicKeyProvider } from "../facades/PublicKeyProvider.js"
import { KeyVersion } from "@tutao/tutanota-utils/dist/Utils.js"

View file

@ -1,5 +1,5 @@
import { assertWorkerOrNode, isBrowser } from "../../../common/Env"
import { FeatureType, KeyVerificationSourceOfTruth, PublicKeyIdentifierType } from "../../../common/TutanotaConstants"
import { FeatureType, KeyVerificationSourceOfTruth, KeyVerificationState, PublicKeyIdentifierType } from "../../../common/TutanotaConstants"
import { assertNotNull, base64ToUint8Array, concat, Hex, lazyAsync, stringToUtf8Uint8Array, uint8ArrayToHex, Versioned } from "@tutao/tutanota-utils"
import { isVersionedPqPublicKey, isVersionedRsaEccPublicKey, isVersionedRsaPublicKey, KeyPairType, PublicKey, sha256Hash } from "@tutao/tutanota-crypto"
import { NotFoundError } from "../../../common/error/RestError"
@ -12,12 +12,6 @@ import { CustomerFacade } from "./CustomerFacade"
assertWorkerOrNode()
export enum KeyVerificationState {
NO_ENTRY, // Identity is not trusted by user
VERIFIED, // Identity is trusted and verified
MISMATCH, // Identity is trusted but not verified
}
export interface PublicKeyFingerprint {
fingerprint: Hex
keyPairType: KeyPairType

View file

@ -14,7 +14,7 @@ import { SearchDropDown } from "./SearchDropDown.js"
import { Icons } from "./base/icons/Icons.js"
import { theme } from "./theme.js"
import { getMailAddressDisplayText } from "../mailFunctionality/SharedMailUtils.js"
import { KeyVerificationState } from "../api/worker/facades/lazy/KeyVerificationFacade"
import { KeyVerificationState } from "../api/common/TutanotaConstants.js"
export interface MailRecipientsTextFieldAttrs {
label: TranslationKey

View file

@ -9,7 +9,7 @@ import { Button, ButtonType } from "../gui/base/Button.js"
import { ExpanderButton, ExpanderPanel } from "../gui/base/Expander"
import { downcast, ErrorInfo, errorToString, neverNull, typedKeys, uint8ArrayToString } from "@tutao/tutanota-utils"
import { locator } from "../api/main/CommonLocator"
import { AccountType, ConversationType, Keys, MailMethod } from "../api/common/TutanotaConstants"
import { AccountType, ConversationType, Keys, KeyVerificationState, MailMethod } from "../api/common/TutanotaConstants"
import { copyToClipboard } from "./ClipboardUtils"
import { px } from "../gui/size"
import { isApp, isDesktop, Mode } from "../api/common/Env"
@ -23,7 +23,6 @@ import { ErrorReportClientType } from "./ClientConstants.js"
import { client } from "./ClientDetector.js"
import { BubbleButton } from "../gui/base/buttons/BubbleButton.js"
import { getTimeZone } from "../calendar/date/CalendarUtils.js"
import { KeyVerificationState } from "../api/worker/facades/lazy/KeyVerificationFacade"
type FeedbackContent = {
message: string

View file

@ -5,7 +5,6 @@ import { Icons } from "../../gui/base/icons/Icons"
import { ButtonSize } from "../../gui/base/ButtonSize"
import { MonospaceTextDisplay } from "../../gui/base/MonospaceTextDisplay"
import { PublicKeyFingerprint } from "../../api/worker/facades/lazy/KeyVerificationFacade"
import { KeyPairType } from "@tutao/tutanota-crypto"
import { Icon, IconSize } from "../../gui/base/Icon"
type FingerprintRowAttrs = {
@ -18,11 +17,25 @@ type FingerprintRowAttrs = {
* Component for displaying a verified public key fingerprint as a compact card,
* including key version, key type and a shield icon.
*/
// Hack because right now we cannot import enum KeyPairType
function getProtocolName(keyPairType: number): string {
if (keyPairType === 0) {
return "RSA"
} else if (keyPairType === 1) {
return "RSA and ECC"
} else if (keyPairType === 2) {
return "TutaCrypt"
} else {
return "unknown protocol"
}
}
export class FingerprintRow implements Component<FingerprintRowAttrs> {
view(vnode: Vnode<FingerprintRowAttrs>): Children {
const { mailAddress, publicKeyFingerprint, onRemoveFingerprint } = vnode.attrs
const protocol = KeyPairType[publicKeyFingerprint.keyPairType]
const protocol = getProtocolName(publicKeyFingerprint.keyPairType)
const version = publicKeyFingerprint.keyVersion
return m(Card, [

View file

@ -134,7 +134,6 @@ import { ExportFacade } from "../common/native/common/generatedipc/ExportFacade.
import { BulkMailLoader } from "./workerUtils/index/BulkMailLoader.js"
import { MailExportFacade } from "../common/api/worker/facades/lazy/MailExportFacade.js"
import { SyncTracker } from "../common/api/main/SyncTracker.js"
import { PublicKeyProvider } from "../common/api/worker/facades/PublicKeyProvider"
assertMainOrNode()
@ -169,7 +168,6 @@ class MailLocator {
bookingFacade!: BookingFacade
mailAddressFacade!: MailAddressFacade
keyVerificationFacade!: KeyVerificationFacade
publicKeyProvider!: PublicKeyProvider
blobFacade!: BlobFacade
userManagementFacade!: UserManagementFacade
recoverCodeFacade!: RecoverCodeFacade
@ -206,15 +204,7 @@ class MailLocator {
readonly recipientsModel: lazyAsync<RecipientsModel> = lazyMemoized(async () => {
const { RecipientsModel } = await import("../common/api/main/RecipientsModel.js")
return new RecipientsModel(
this.contactModel,
this.logins,
this.mailFacade,
this.entityClient,
this.keyVerificationFacade,
this.serviceExecutor,
this.publicKeyProvider,
)
return new RecipientsModel(this.contactModel, this.logins, this.mailFacade, this.entityClient, this.keyVerificationFacade)
})
async noZoneDateProvider(): Promise<NoZoneDateProvider> {
@ -754,7 +744,6 @@ class MailLocator {
this.bookingFacade = bookingFacade
this.mailAddressFacade = mailAddressFacade
this.keyVerificationFacade = keyVerificationFacade
this.publicKeyProvider = new PublicKeyProvider(serviceExecutor)
this.blobFacade = blobFacade
this.userManagementFacade = userManagementFacade
this.recoverCodeFacade = recoverCodeFacade

View file

@ -1,11 +1,16 @@
import o from "@tutao/otest"
import { KeyVerificationFacade, KeyVerificationState, PublicKeyFingerprint } from "../../../../../src/common/api/worker/facades/lazy/KeyVerificationFacade"
import { KeyVerificationFacade, PublicKeyFingerprint } from "../../../../../src/common/api/worker/facades/lazy/KeyVerificationFacade"
import { SqlCipherFacade } from "../../../../../src/common/native/common/generatedipc/SqlCipherFacade"
import { matchers, object, verify, when } from "testdouble"
import { SqlType, TaggedSqlValue } from "../../../../../src/common/api/worker/offline/SqlValue"
import { PublicKeyGetOut, PublicKeyGetOutTypeRef } from "../../../../../src/common/api/entities/sys/TypeRefs"
import { concat, lazyAsync, stringToUtf8Uint8Array, Versioned } from "@tutao/tutanota-utils"
import { FeatureType, KeyVerificationSourceOfTruth, PublicKeyIdentifierType } from "../../../../../src/common/api/common/TutanotaConstants"
import {
FeatureType,
KeyVerificationSourceOfTruth,
KeyVerificationState,
PublicKeyIdentifierType,
} from "../../../../../src/common/api/common/TutanotaConstants"
import { NotFoundError } from "../../../../../src/common/api/common/error/RestError"
import { KeyPairType, PQPublicKeys, PublicKey } from "@tutao/tutanota-crypto"
import { PublicKeyIdentifier, PublicKeyProvider } from "../../../../../src/common/api/worker/facades/PublicKeyProvider"

View file

@ -1,4 +1,12 @@
import { AccountType, ContactAddressType, FeatureType, GroupType, ShareCapability, TimeFormat } from "../../../src/common/api/common/TutanotaConstants.js"
import {
AccountType,
ContactAddressType,
FeatureType,
GroupType,
KeyVerificationState,
ShareCapability,
TimeFormat,
} from "../../../src/common/api/common/TutanotaConstants.js"
import type { UserController } from "../../../src/common/api/main/UserController.js"
import {
BookingsRefTypeRef,
@ -33,7 +41,6 @@ import { DateTime } from "luxon"
import { createTestEntity } from "../TestUtils.js"
import { matchers, object, when } from "testdouble"
import { AlarmScheduler } from "../../../src/common/calendar/date/AlarmScheduler.js"
import { KeyVerificationState } from "../../../src/common/api/worker/facades/lazy/KeyVerificationFacade"
export const ownerMailAddress = "calendarowner@tutanota.de" as const
export const ownerId = "ownerId" as const

View file

@ -9,7 +9,7 @@ import {
import { matchers, object, replace, verify, when } from "testdouble"
import { RecipientsModel } from "../../../../src/common/api/main/RecipientsModel.js"
import { Recipient, RecipientType } from "../../../../src/common/api/common/recipients/Recipient.js"
import { AccountType, CalendarAttendeeStatus, ShareCapability } from "../../../../src/common/api/common/TutanotaConstants.js"
import { AccountType, CalendarAttendeeStatus, KeyVerificationState, ShareCapability } from "../../../../src/common/api/common/TutanotaConstants.js"
import { UserTypeRef } from "../../../../src/common/api/entities/sys/TypeRefs.js"
import { UserController } from "../../../../src/common/api/main/UserController.js"
import { CalendarOperation, EventType } from "../../../../src/calendar-app/calendar/gui/eventeditor-model/CalendarEventModel.js"
@ -36,7 +36,6 @@ import { ProgrammingError } from "../../../../src/common/api/common/error/Progra
import { createTestEntity } from "../../TestUtils.js"
import { SendMailModel } from "../../../../src/common/mailFunctionality/SendMailModel.js"
import { CalendarEventWhoModel } from "../../../../src/calendar-app/calendar/gui/eventeditor-model/CalendarEventWhoModel.js"
import { KeyVerificationState } from "../../../../src/common/api/worker/facades/lazy/KeyVerificationFacade"
o.spec("CalendarEventWhoModel", function () {
const passwordStrengthModel = () => 1

View file

@ -4,7 +4,7 @@ import { LazyLoaded } from "@tutao/tutanota-utils"
import { Contact } from "../../../src/common/api/entities/tutanota/TypeRefs.js"
import { User } from "../../../src/common/api/entities/sys/TypeRefs.js"
import { createNewContact, isTutaMailAddress } from "../../../src/common/mailFunctionality/SharedMailUtils.js"
import { KeyVerificationState } from "../../../src/common/api/worker/facades/lazy/KeyVerificationFacade"
import { KeyVerificationState } from "../../../src/common/api/common/TutanotaConstants.js"
/**
* Creating actual ResolvableRecipients is annoying because you have to mock a bunch of stuff in other model classes

View file

@ -8,15 +8,12 @@ import { GroupInfoTypeRef, GroupMembershipTypeRef, UserTypeRef } from "../../../
import { Recipient, RecipientType } from "../../../src/common/api/common/recipients/Recipient.js"
import { ContactMailAddressTypeRef, ContactTypeRef } from "../../../src/common/api/entities/tutanota/TypeRefs.js"
import { UserController } from "../../../src/common/api/main/UserController.js"
import { GroupType } from "../../../src/common/api/common/TutanotaConstants.js"
import { GroupType, KeyVerificationState } from "../../../src/common/api/common/TutanotaConstants.js"
import { verify } from "@tutao/tutanota-test-utils"
import { defer, delay } from "@tutao/tutanota-utils"
import { createTestEntity } from "../TestUtils.js"
import { ContactModel } from "../../../src/common/contactsFunctionality/ContactModel.js"
import { KeyVerificationFacade, KeyVerificationState } from "../../../src/common/api/worker/facades/lazy/KeyVerificationFacade"
import { ServiceExecutor } from "../../../src/common/api/worker/rest/ServiceExecutor"
import { IServiceExecutor } from "../../../src/common/api/common/ServiceRequest"
import { PublicKeyProvider } from "../../../src/common/api/worker/facades/PublicKeyProvider"
import { KeyVerificationFacade } from "../../../src/common/api/worker/facades/lazy/KeyVerificationFacade"
o.spec("RecipientsModel", function () {
const contactListId = "contactListId"
@ -32,8 +29,6 @@ o.spec("RecipientsModel", function () {
let mailFacadeMock: MailFacade
let entityClientMock: EntityClient
let keyVerificationFacadeMock: KeyVerificationFacade
let serviceExecutorMock: IServiceExecutor
let publicKeyProviderMock: PublicKeyProvider
let model: RecipientsModel
@ -59,18 +54,8 @@ o.spec("RecipientsModel", function () {
mailFacadeMock = instance(MailFacade)
entityClientMock = instance(EntityClient)
keyVerificationFacadeMock = instance(KeyVerificationFacade)
serviceExecutorMock = instance(ServiceExecutor)
publicKeyProviderMock = object()
model = new RecipientsModel(
contactModelMock,
loginControllerMock,
mailFacadeMock,
entityClientMock,
keyVerificationFacadeMock,
serviceExecutorMock,
publicKeyProviderMock,
)
model = new RecipientsModel(contactModelMock, loginControllerMock, mailFacadeMock, entityClientMock, keyVerificationFacadeMock)
})
o("initializes with provided contact", function () {

View file

@ -54,4 +54,8 @@ Reference: https://github.com/mathiasbynens/quoted-printable/blob/master/LICENSE
language icon - MGalloway (WMF) via Wikimedia Commons - https://upload.wikimedia.org/wikipedia/commons/4/43/OOjs_UI_icon_language-ltr.svg
License: CC BY-SA 3.0
Reference: https://creativecommons.org/licenses/by-sa/3.0>,
Reference: https://creativecommons.org/licenses/by-sa/3.0>,
jsQR - https://github.com/cozmo/jsQR
License: Apache 2
Reference: https://github.com/cozmo/jsQR/blob/master/LICENSE