import encryptHelpers from './helpers/index';
import messagingHelpers from '../helpers/index';
import { dispatchEvent } from '../../../utils/skylinkEventManager';
import { encryptionSecretsUpdated } from '../../../skylink-events';
import MESSAGES from '../../../messages';
import getUserInfo from '../../../peer-data/helpers/getUserInfo';
import { getParamValidity, getRoomStateByName } from '../../../utils/helpers';
import SkylinkError from '../../../utils/skylinkError';
import logger from '../../../logger';
import { TAGS } from '../../../constants';
const instance = {};
/**
* @classdesc Class used for handling encryption
* @class
* @private
*/
class EncryptedMessaging {
constructor(roomState) {
const { room, user } = roomState;
if (!instance[room.id]) {
instance[room.id] = this;
}
this.room = room;
this.peerId = user.sid;
/**
* The secret id and encrypt secret key-value pair.
* @type {Object|{}}
*/
this.encryptSecrets = {};
/**
* The selected secret id.
* @type {String}
*/
this.selectedSecretId = '';
return instance[room.id];
}
setEncryptSecret(secret, secretId) {
try {
this.encryptSecrets = encryptHelpers.setEncryptSecret(this.encryptSecrets, secret, secretId);
this.dispatchEncryptSecretEvent();
} catch (error) {
SkylinkError.throwError(MESSAGES.MESSAGING.ENCRYPTION.ERRORS.SET_ENCRYPT_SECRET, error.message);
}
}
getEncryptSecrets() {
return this.encryptSecrets;
}
deleteEncryptSecrets(secretId) {
try {
const updatedData = encryptHelpers.deleteEncryptSecrets(this.encryptSecrets, this.selectedSecretId, secretId);
this.encryptSecrets = updatedData.encryptSecrets;
this.selectedSecretId = updatedData.selectedSecretId;
this.dispatchEncryptSecretEvent();
} catch (error) {
SkylinkError.throwError(MESSAGES.MESSAGING.ENCRYPTION.ERRORS.DELETE_ENCRYPT_SECRETS, error.message);
}
}
setSelectedSecretId(secretId) {
try {
this.selectedSecretId = encryptHelpers.setSelectedSecretId(this.encryptSecrets, secretId);
this.dispatchEncryptSecretEvent();
} catch (error) {
SkylinkError.throwError(MESSAGES.MESSAGING.ENCRYPTION.ERRORS.SET_SELECTED_SECRET, error.message);
}
}
getSelectedSecretId() {
return this.selectedSecretId;
}
dispatchEncryptSecretEvent() {
dispatchEvent(encryptionSecretsUpdated({
room: this.room,
encryptSecrets: this.encryptSecrets,
selectedSecretId: this.selectedSecretId,
peerInfo: getUserInfo(this.room),
peerId: this.peerId,
}));
}
canEncrypt(throwError) {
try {
if (encryptHelpers.utils.canEncrypt(this.selectedSecretId, this.encryptSecrets)) {
return encryptHelpers.utils.isValidString(this.selectedSecretId) && encryptHelpers.utils.isValidString(this.encryptSecrets[this.selectedSecretId]);
}
return false;
} catch (err) {
if (throwError) {
throw new Error(err.message);
}
return false;
}
}
decryptStoredMessages(message, secretId) {
if (encryptHelpers.utils.canEncrypt(secretId, this.encryptSecrets) && !Object.keys(this.encryptSecrets).filter(key => key === secretId).length) {
throw new Error(MESSAGES.MESSAGING.ENCRYPTION.ERRORS.SECRET_ID_NOT_FOUND);
}
return this.decryptMessage(message, secretId);
}
decryptMessage(message, secretId = '') {
if (secretId && encryptHelpers.utils.canDecrypt(this.encryptSecrets)) {
return encryptHelpers.tryDecryptMessage(message, secretId, this.encryptSecrets);
}
throw new Error(MESSAGES.MESSAGING.ENCRYPTION.ERRORS.INVALID_SECRETS);
}
sendMessage(roomName, message, targetPeerId, isPersistent = false) {
const roomState = getRoomStateByName(roomName);
if (getParamValidity(message, 'message', 'sendMessage') && roomState) {
try {
logger.log.DEBUG([null, TAGS.ASYNC_MESSAGING, null, MESSAGES.MESSAGING.ENCRYPTION.SEND_MESSAGE]);
const config = encryptHelpers.getMessageConfig(roomState, targetPeerId, this.encryptSecrets, this.selectedSecretId, isPersistent);
const encryptedMessage = encryptHelpers.encryptMessage(message, this.encryptSecrets[this.selectedSecretId]);
messagingHelpers.sendMessageToSig(roomState, config, message, encryptedMessage, targetPeerId);
} catch (error) {
SkylinkError.throwError(MESSAGES.MESSAGING.ERRORS.DROPPING_MESSAGE, error.message);
}
}
}
}
export default EncryptedMessaging;