Update new conditions for friend accepted and key exchange complete in conversations model.

pull/50/head
Mikunj 6 years ago
parent ef44a123ed
commit cf3e9716ed

@ -52,6 +52,26 @@
'blue_grey',
];
/**
* A few key things that need to be known in this is the difference
* between isFriend() and isKeyExhangeCompleted().
*
* `isFriend` returns whether we have accepted the other user as a friend.
* - This is implicitly checked by whether we have a session
* or we have the preKeyBundle of the user.
*
* `isKeyExchangeCompleted` return whether we know for certain
* that both of our preKeyBundles have been exhanged.
* - This will be set when we receive a valid CIPHER message from the other user.
* * Valid meaning we can decypher the message using the preKeys provided
* or the keys we have stored.
*
* `isFriend` will determine whether we should send a FRIEND_REQUEST message.
*
* `isKeyExhangeCompleted` will determine whether we keep
* sending preKeyBundle to the other user.
*/
Whisper.Conversation = Backbone.Model.extend({
storeName: 'conversations',
defaults() {
@ -59,7 +79,6 @@
unreadCount: 0,
verified: textsecure.storage.protocol.VerifiedStatus.DEFAULT,
keyExchangeCompleted: false,
friendRequestStatus: { allowSending: true, unlockTimestamp: null },
};
},
@ -444,48 +463,30 @@
return this.get('keyExchangeCompleted') || false;
},
getFriendRequestStatus() {
return this.get('friendRequestStatus');
},
waitingForFriendRequestApproval() {
const friendRequestStatus = this.getFriendRequestStatus();
if (!friendRequestStatus) {
return false;
}
return !friendRequestStatus.allowSending;
},
setFriendRequestTimer() {
const friendRequestStatus = this.getFriendRequestStatus();
if (friendRequestStatus) {
if (!friendRequestStatus.allowSending) {
const delay = Math.max(
friendRequestStatus.unlockTimestamp - Date.now(),
0
);
setTimeout(() => {
this.onFriendRequestTimedOut();
}, delay);
}
}
},
async onFriendRequestAccepted({ updateUnread }) {
// Make sure we don't keep incrementing the unread count
const unreadCount = !updateUnread || this.isKeyExchangeCompleted()
? {}
: { unreadCount: this.get('unreadCount') + 1 };
this.set({
friendRequestStatus: null,
keyExchangeCompleted: true,
...unreadCount,
});
async setKeyExchangeCompleted(value) {
this.set({ keyExchangeCompleted: value });
await window.Signal.Data.updateConversation(this.id, this.attributes, {
Conversation: Whisper.Conversation,
});
},
async isFriend() {
// We are a friend IF:
// - We have the preKey bundle of the user OR
// - We have a session with the user
const preKeys = await window.Signal.Data.getContactPreKeyByIdentityKey(this.id);
const session = await window.Signal.Data.getSessionsByNumber(this.id);
return !!(preKeys || session);
},
// Update any pending friend requests for the current user
async updateFriendRequestUI() {
// Enable the text inputs early
this.updateTextInputState();
// We only update our friend requests if we have the user as a friend
const isFriend = await this.isFriend();
if (!isFriend) return;
// Update any pending outgoing messages
const pending = await this.getPendingFriendRequests('outgoing');
await Promise.all(
@ -500,50 +501,14 @@
})
);
// Update our local state
await this.updatePendingFriendRequests();
// Send the notification
this.notifyFriendRequest(this.id, 'accepted')
},
async onFriendRequestTimedOut() {
this.updateTextInputState();
const friendRequestStatus = this.getFriendRequestStatus();
if (friendRequestStatus) {
friendRequestStatus.allowSending = true;
this.set({ friendRequestStatus });
await window.Signal.Data.updateConversation(this.id, this.attributes, {
Conversation: Whisper.Conversation,
});
}
},
async onFriendRequestSent() {
// Don't bother setting the friend request if we have already exchanged keys
if (this.isKeyExchangeCompleted()) return;
const friendRequestLockDuration = 72; // hours
let friendRequestStatus = this.getFriendRequestStatus();
if (!friendRequestStatus) {
friendRequestStatus = {};
}
friendRequestStatus.allowSending = false;
const delayMs = 60 * 60 * 1000 * friendRequestLockDuration;
friendRequestStatus.unlockTimestamp = Date.now() + delayMs;
// Update the text input state
this.updateTextInputState();
this.set({ friendRequestStatus });
await window.Signal.Data.updateConversation(this.id, this.attributes, {
Conversation: Whisper.Conversation,
});
setTimeout(() => {
this.onFriendRequestTimedOut();
}, delayMs);
return this.updateFriendRequestUI();
},
isUnverified() {
if (this.isPrivate()) {
@ -1012,8 +977,9 @@
let messageWithSchema = null;
// If we have exchanged keys then let the user send the message normally
if (this.isKeyExchangeCompleted()) {
// If we are a friend then let the user send the message normally
const isFriend = await this.isFriend();
if (isFriend) {
messageWithSchema = await upgradeMessageSchema({
type: 'outgoing',
body,
@ -1143,7 +1109,8 @@
},
async updateTextInputState() {
// Check if we need to disable the text field
if (!this.isKeyExchangeCompleted()) {
const isFriend = await this.isFriend();
if (isFriend) {
// Check if we have an incoming friend request
// Or any successful outgoing ones
const incoming = await this.getPendingFriendRequests('incoming');

@ -468,7 +468,7 @@ OutgoingMessage.prototype = {
.then(this.reloadDevicesAndSend(number, true))
.catch(error => {
if (this.fallBackEncryption && conversation) {
conversation.onFriendRequestTimedOut();
conversation.updateFriendRequestUI();
}
if (error.message === 'Identity key changed') {
// eslint-disable-next-line no-param-reassign

Loading…
Cancel
Save