tutanota/test/tests/api/common/mail/CommonMailUtilsTest.ts

323 lines
11 KiB
TypeScript
Raw Normal View History

import o from "@tutao/otest"
import { createMail, createMailAddress, Mail, MailAddressTypeRef, MailTypeRef } from "../../../../../src/common/api/entities/tutanota/TypeRefs.js"
import { EncryptionAuthStatus, MailState } from "../../../../../src/common/api/common/TutanotaConstants.js"
import { createTestEntity } from "../../../TestUtils.js"
import { Icons } from "../../../../../src/common/gui/base/icons/Icons.js"
import { ProgrammingError } from "../../../../../src/common/api/common/error/ProgrammingError.js"
import { getConfidentialIcon } from "../../../../../src/common/mailFunctionality/SharedMailUtils.js"
import { isSystemNotification } from "../../../../../src/common/mailFunctionality/SharedMailUtils.js"
import { getDisplayedSender } from "../../../../../src/common/api/common/CommonMailUtils.js"
import { isTutanotaTeamAddress, isTutanotaTeamMail } from "../../../../../src/mail-app/mail/view/MailGuiUtils.js"
o.spec("MailUtilsTest", function () {
function createSystemMail(overrides: Partial<Mail> = {}): Mail {
Support group key rotation (#6588) * Allow groups to have multiple key versions tutadb#1628 * Adapt to model changes * Fix CommonMailUtilsTest * Remove symEncBucketKey from SecureExternalRecipientKeyData * Remove deprecated types Also fix tests that relied on them as dummy types * Add userKeyVersion to RecoverCode * Remove clientKey Seems to be unused. * Remove CreateFolderService Unused. * Remove symEncSessionKey from DraftCreateData Unused. * Remove symEncShareBucketKey from MailBox Unused. * Add userKeyVersion to TutanotaProperties * Remove PasswordRetrievalService type The service itself had been long gone. * Remove userKeyVersion from CustomerAccountCreateData CreateMailGroupData * Fix customer account creation Set the key version that we actually need there: the *system* admin pub key version. The sender key version is not needed, because the system admin only has RSA keys. Also, this is a new customer, so that would be version zero anyway. * Fix resolving bucket key with group reference Get the right versions along the way. * Use current group key when encrypting instance session keys * Remove left-over key getting Also document a couple of current key usages * Pass group key providers to EntityClient instead of group key * Fix types and do not provide sender key version for rsa Fix resolveServiceSessionKey * Rename constant to avoid confusion There is another constant with the same name. * Use TutanotaModelV69 * Introduce client side mechanism to handle key rotation requests see tutadb 1771 * Do not export 128-bit key generator It is only needed for tests within the package. * Remove group key version when creating user area groups Plus some minor clarity improvements. * Fix version handling when updating drafts and sending to secure external * Remove versions when creating external users They are zero. * Fix changing the admin flag * Remove (almost) all local admin related code * Improve readability * Default to user key version zero when loading entropy * Decrypt current groupKey with correct userGroupKey version * Fix system application offline migrations * Fix tutanota application offline migrations * Improve offline migration functions * Use AesKey type * Minor improvements from review * Use AesKey type instead of Aes128Key where possible * Model update after rebase * Fix getting user group key Should never try to get from the cache like a normal group key. * Fix getting former group key Start ID was off-by-one. * Minor changes from review. We just checked all usages of all public methods of KeyLoaderFacade to make sure we're using the correct versions where we need them. * More minor changes from review. * Pass ownerKeyProvider instead of ownerKey when updating with the EntityClient * Pass ownerKeyProvider only when necessary * Document ownerKeyProvider parameter * Fix offline database migration * Fix unlocking the indexer data --------- Co-authored-by: vaf <vaf@tutao.de> Co-authored-by: bedhub <bedhub@users.noreply.github.com> Co-authored-by: bed <bed@tutao.de>
2024-04-17 10:34:33 +02:00
return createTestEntity(MailTypeRef, {
...{
Support group key rotation (#6588) * Allow groups to have multiple key versions tutadb#1628 * Adapt to model changes * Fix CommonMailUtilsTest * Remove symEncBucketKey from SecureExternalRecipientKeyData * Remove deprecated types Also fix tests that relied on them as dummy types * Add userKeyVersion to RecoverCode * Remove clientKey Seems to be unused. * Remove CreateFolderService Unused. * Remove symEncSessionKey from DraftCreateData Unused. * Remove symEncShareBucketKey from MailBox Unused. * Add userKeyVersion to TutanotaProperties * Remove PasswordRetrievalService type The service itself had been long gone. * Remove userKeyVersion from CustomerAccountCreateData CreateMailGroupData * Fix customer account creation Set the key version that we actually need there: the *system* admin pub key version. The sender key version is not needed, because the system admin only has RSA keys. Also, this is a new customer, so that would be version zero anyway. * Fix resolving bucket key with group reference Get the right versions along the way. * Use current group key when encrypting instance session keys * Remove left-over key getting Also document a couple of current key usages * Pass group key providers to EntityClient instead of group key * Fix types and do not provide sender key version for rsa Fix resolveServiceSessionKey * Rename constant to avoid confusion There is another constant with the same name. * Use TutanotaModelV69 * Introduce client side mechanism to handle key rotation requests see tutadb 1771 * Do not export 128-bit key generator It is only needed for tests within the package. * Remove group key version when creating user area groups Plus some minor clarity improvements. * Fix version handling when updating drafts and sending to secure external * Remove versions when creating external users They are zero. * Fix changing the admin flag * Remove (almost) all local admin related code * Improve readability * Default to user key version zero when loading entropy * Decrypt current groupKey with correct userGroupKey version * Fix system application offline migrations * Fix tutanota application offline migrations * Improve offline migration functions * Use AesKey type * Minor improvements from review * Use AesKey type instead of Aes128Key where possible * Model update after rebase * Fix getting user group key Should never try to get from the cache like a normal group key. * Fix getting former group key Start ID was off-by-one. * Minor changes from review. We just checked all usages of all public methods of KeyLoaderFacade to make sure we're using the correct versions where we need them. * More minor changes from review. * Pass ownerKeyProvider instead of ownerKey when updating with the EntityClient * Pass ownerKeyProvider only when necessary * Document ownerKeyProvider parameter * Fix offline database migration * Fix unlocking the indexer data --------- Co-authored-by: vaf <vaf@tutao.de> Co-authored-by: bedhub <bedhub@users.noreply.github.com> Co-authored-by: bed <bed@tutao.de>
2024-04-17 10:34:33 +02:00
sender: createTestEntity(MailAddressTypeRef, { address: "system@tutanota.de", name: "System" }),
replyTos: [],
state: MailState.RECEIVED,
authStatus: null,
_errors: {},
_id: ["", ""],
_ownerEncSessionKey: null,
_ownerGroup: "",
_permissions: "",
attachments: [],
bccRecipients: [],
body: null,
bucketKey: null,
ccRecipients: [],
confidential: true,
conversationEntry: ["", ""],
differentEnvelopeSender: null,
encryptionAuthStatus: null,
firstRecipient: null,
headers: null,
listUnsubscribe: false,
mailDetails: null,
mailDetailsDraft: null,
method: "",
movedTime: null,
phishingStatus: "",
receivedDate: new Date(),
recipientCount: "",
replyType: "",
subject: "",
toRecipients: [],
unread: false,
},
...overrides,
})
}
const tutanotaSender = () => createMailAddress({ address: "sender@tutanota.de", name: "Tutanota sender", contact: null })
const tutaoSender = () => createMailAddress({ address: "sender@tutao.de", name: "Tutao sender", contact: null })
const tutanotaNoReplySender = () => createMailAddress({ address: "no-reply@tutanota.de", name: "Tutanota no-reply", contact: null })
const tutaoNoReplySender = () => createMailAddress({ address: "no-reply@tutao.de", name: "Tutao no-reply", contact: null })
o("getDisplayedSender", function () {
const mail = createSystemMail()
o(getDisplayedSender(mail)).deepEquals({ address: "system@tutanota.de", name: "System" })
})
o("isTutanotaTeamAddress", function () {
o(isTutanotaTeamAddress("system@tutanota.de")).deepEquals(false)
o(isTutanotaTeamAddress("bed-free@tutanota.de")).deepEquals(false)
o(isTutanotaTeamAddress("admin@somesite.com")).deepEquals(false)
o(isTutanotaTeamAddress("no-reply@tutao.de")).deepEquals(true)
o(isTutanotaTeamAddress("sales@tutao.de")).deepEquals(true)
o(isTutanotaTeamAddress("no-reply@tutanota.de")).deepEquals(true)
})
o("getConfidentialIcon", function () {
const mail: Mail = createTestEntity(MailTypeRef, { confidential: true, encryptionAuthStatus: EncryptionAuthStatus.TUTACRYPT_AUTHENTICATION_SUCCEEDED })
o(getConfidentialIcon(mail)).equals(Icons.PQLock)
mail.encryptionAuthStatus = EncryptionAuthStatus.TUTACRYPT_AUTHENTICATION_FAILED
o(getConfidentialIcon(mail)).equals(Icons.PQLock)
mail.encryptionAuthStatus = EncryptionAuthStatus.AES_NO_AUTHENTICATION
o(getConfidentialIcon(mail)).equals(Icons.Lock)
mail.encryptionAuthStatus = null
o(getConfidentialIcon(mail)).equals(Icons.Lock)
mail.encryptionAuthStatus = EncryptionAuthStatus.RSA_NO_AUTHENTICATION
o(getConfidentialIcon(mail)).equals(Icons.Lock)
mail.encryptionAuthStatus = EncryptionAuthStatus.TUTACRYPT_SENDER
o(getConfidentialIcon(mail)).equals(Icons.PQLock)
mail.confidential = false
o(() => getConfidentialIcon(mail)).throws(ProgrammingError)
})
o.spec("isTutanotaTeamMail", function () {
o("regular non-confidential email is not", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: false,
state: MailState.RECEIVED,
sender: tutanotaSender(),
})
o(isTutanotaTeamMail(mail)).equals(false)
})
o("regular confidential email is not", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: true,
state: MailState.RECEIVED,
sender: tutanotaSender(),
})
o(isTutanotaTeamMail(mail)).equals(false)
})
o("system email without auth is", function () {
const mail = createSystemMail()
o(isTutanotaTeamMail(mail)).equals(true)
})
o("system email failing PQ auth is not", function () {
const mail = createSystemMail({ encryptionAuthStatus: EncryptionAuthStatus.TUTACRYPT_AUTHENTICATION_FAILED })
o(isTutanotaTeamMail(mail)).equals(false)
})
o("system email with RSA (no) auth is", function () {
const mail = createSystemMail({ encryptionAuthStatus: EncryptionAuthStatus.RSA_NO_AUTHENTICATION })
o(isTutanotaTeamMail(mail)).equals(true)
})
o("system email with AES (no) auth is not", function () {
const mail = createSystemMail({ encryptionAuthStatus: EncryptionAuthStatus.AES_NO_AUTHENTICATION })
o(isTutanotaTeamMail(mail)).equals(false)
})
o("confidential email from tutao without auth is", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: true,
state: MailState.RECEIVED,
sender: tutaoSender(),
encryptionAuthStatus: null,
})
o(isTutanotaTeamMail(mail)).equals(true)
})
o("confidential email from tutao with PQ auth is", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: true,
state: MailState.RECEIVED,
sender: tutaoSender(),
encryptionAuthStatus: EncryptionAuthStatus.TUTACRYPT_AUTHENTICATION_SUCCEEDED,
})
o(isTutanotaTeamMail(mail)).equals(true)
})
o("confidential email from tutao with failing PQ auth is not", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: true,
state: MailState.RECEIVED,
sender: tutaoSender(),
encryptionAuthStatus: EncryptionAuthStatus.TUTACRYPT_AUTHENTICATION_FAILED,
})
o(isTutanotaTeamMail(mail)).equals(false)
})
o("confidential email from tutao with RSA (no) auth is", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: true,
state: MailState.RECEIVED,
sender: tutaoSender(),
encryptionAuthStatus: EncryptionAuthStatus.RSA_NO_AUTHENTICATION,
})
o(isTutanotaTeamMail(mail)).equals(true)
})
o("confidential email from tutao with AES (no) auth is not", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: true,
state: MailState.RECEIVED,
sender: tutaoSender(),
encryptionAuthStatus: EncryptionAuthStatus.AES_NO_AUTHENTICATION,
})
o(isTutanotaTeamMail(mail)).equals(false)
})
o("confidential email from no-reply is", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: true,
state: MailState.RECEIVED,
sender: tutanotaNoReplySender(),
})
o(isTutanotaTeamMail(mail)).equals(true)
})
o(`non-confidential "system" email is not`, function () {
const mail = createMail({ ...createSystemMail(), confidential: false })
o(isTutanotaTeamMail(mail)).equals(false)
})
o("non-confidential email from tutao is not", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: false,
state: MailState.RECEIVED,
sender: tutaoSender(),
})
o(isTutanotaTeamMail(mail)).equals(false)
})
o("non confidential email from no-reply is not", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: false,
state: MailState.RECEIVED,
sender: tutanotaNoReplySender(),
})
o(isTutanotaTeamMail(mail)).equals(false)
})
})
o.spec("isSystemNotification", function () {
o("regular non-confidential email is not", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: false,
state: MailState.RECEIVED,
sender: tutanotaSender(),
})
o(isSystemNotification(mail)).equals(false)
})
o("regular confidential email is not", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: true,
state: MailState.RECEIVED,
sender: tutanotaSender(),
})
o(isSystemNotification(mail)).equals(false)
})
o("system email without auth is", function () {
const mail = createSystemMail()
o(isSystemNotification(mail)).equals(true)
})
o("system email with PQ auth is", function () {
const mail = createSystemMail({ encryptionAuthStatus: EncryptionAuthStatus.TUTACRYPT_AUTHENTICATION_SUCCEEDED })
o(isSystemNotification(mail)).equals(true)
})
o("system email with failing PQ auth is not", function () {
const mail = createSystemMail({ encryptionAuthStatus: EncryptionAuthStatus.TUTACRYPT_AUTHENTICATION_FAILED })
o(isSystemNotification(mail)).equals(false)
})
o("system email with RSA (no) auth is", function () {
const mail = createSystemMail({ encryptionAuthStatus: EncryptionAuthStatus.RSA_NO_AUTHENTICATION })
o(isSystemNotification(mail)).equals(true)
})
o("system email with AES (no) auth is not", function () {
const mail = createSystemMail({ encryptionAuthStatus: EncryptionAuthStatus.AES_NO_AUTHENTICATION })
o(isSystemNotification(mail)).equals(false)
})
o("confidential email from tutao is not", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: true,
state: MailState.RECEIVED,
sender: tutaoSender(),
authStatus: null,
})
o(isSystemNotification(mail)).equals(false)
})
o("confidential email from tutao with PQ auth is not", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: true,
state: MailState.RECEIVED,
sender: tutaoSender(),
authStatus: EncryptionAuthStatus.TUTACRYPT_AUTHENTICATION_SUCCEEDED,
})
o(isSystemNotification(mail)).equals(false)
})
o("confidential email from tutanota no-reply is", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: true,
state: MailState.RECEIVED,
sender: tutanotaNoReplySender(),
})
o(isSystemNotification(mail)).equals(true)
})
o("confidential email from tutao no-reply is", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: true,
state: MailState.RECEIVED,
sender: tutaoNoReplySender(),
})
o(isSystemNotification(mail)).equals(true)
})
o(`non-confidential "system" email is not`, function () {
const mail = createMail({ ...createSystemMail(), confidential: false })
o(isSystemNotification(mail)).equals(false)
})
o("non-confidential email from tutao is not", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: false,
state: MailState.RECEIVED,
sender: tutaoSender(),
})
o(isSystemNotification(mail)).equals(false)
})
o("non confidential email from no-reply is not", function () {
const mail = createTestEntity(MailTypeRef, {
confidential: false,
state: MailState.RECEIVED,
sender: tutanotaNoReplySender(),
})
o(isSystemNotification(mail)).equals(false)
})
})
})