Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / docs-core / lib / UseCase / DecryptMessage.ts
blob5a537a414584909d19f892f2153e3eefc702d9fc
1 import type { Event } from '@proton/docs-proto'
2 import { DocumentUpdate } from '@proton/docs-proto'
3 import type { EncryptionService } from '../Services/Encryption/EncryptionService'
4 import { GetAssociatedEncryptionDataForRealtimeMessage } from './GetAdditionalEncryptionData'
5 import type { EncryptionContext } from '../Services/Encryption/EncryptionContext'
6 import type { SessionKey } from '@proton/crypto'
7 import { VERIFICATION_STATUS } from '@proton/crypto'
8 import { DecryptedMessage } from '@proton/docs-shared'
9 import type { UseCaseInterface } from '../Domain/UseCase/UseCaseInterface'
10 import { Result } from '@proton/docs-shared'
12 export type DecryptMessageDTO = {
13   message: DocumentUpdate | Event
14   documentContentKey: SessionKey
15   verify: boolean
18 export class DecryptMessage implements UseCaseInterface<DecryptedMessage> {
19   constructor(private encryption: EncryptionService<EncryptionContext.RealtimeMessage>) {}
21   async execute(dto: DecryptMessageDTO): Promise<Result<DecryptedMessage>> {
22     const decrypted = await this.encryption.decryptData(
23       dto.message instanceof DocumentUpdate ? dto.message.encryptedContent : dto.message.content,
24       GetAssociatedEncryptionDataForRealtimeMessage(dto.message),
25       dto.documentContentKey,
26     )
28     if (decrypted.isFailed()) {
29       return Result.fail(decrypted.getError())
30     }
32     if (dto.verify) {
33       const verificationKey = await this.encryption.getVerificationKey(dto.message.authorAddress)
35       if (verificationKey.isFailed()) {
36         return Result.fail(verificationKey.getError())
37       }
39       const verifyResult = await this.encryption.verifyData(
40         decrypted.getValue().content,
41         decrypted.getValue().signature,
42         GetAssociatedEncryptionDataForRealtimeMessage(dto.message),
43         verificationKey.getValue(),
44       )
46       if (verifyResult.isFailed()) {
47         return Result.fail(verifyResult.getError())
48       }
50       if (verifyResult.getValue() !== VERIFICATION_STATUS.SIGNED_AND_VALID) {
51         return Result.fail(`Message content verification failed: ${verifyResult.getValue()}`)
52       }
53     }
55     const message = new DecryptedMessage({
56       content: decrypted.getValue().content,
57       signature: decrypted.getValue().signature,
58       aad: GetAssociatedEncryptionDataForRealtimeMessage(dto.message),
59       authorAddress: dto.message.authorAddress,
60       timestamp: dto.message.timestamp,
61     })
63     return Result.ok(message)
64   }