feat(Contacts): Handle cancel identity verification on the reciever side

Close #8437
This commit is contained in:
MishkaRogachev 2022-12-02 17:02:41 +04:00 committed by Mikhail Rogachev
parent a584a31818
commit ddf27d3038
13 changed files with 105 additions and 79 deletions

View File

@ -73,6 +73,10 @@ proc init*(self: Controller) =
var args = ContactArgs(e)
self.delegate.onVerificationRequestDeclined(args.contactId)
self.events.on(SIGNAL_CONTACT_VERIFICATION_CANCELLED) do(e: Args):
var args = ContactArgs(e)
self.delegate.onVerificationRequestCanceled(args.contactId)
self.events.on(SIGNAL_CONTACT_VERIFICATION_ADDED) do(e: Args):
var args = VerificationRequestArgs(e)
self.delegate.onVerificationRequestUpdatedOrAdded(args.verificationRequest)
@ -161,5 +165,3 @@ proc getReceivedVerificationRequests*(self: Controller): seq[VerificationRequest
proc getStatusForContactWithId*(self: Controller, publicKey: string): StatusUpdateDto =
return self.contactsService.getStatusForContactWithId(publicKey)
proc hasReceivedVerificationRequestFrom*(self: Controller, fromId: string): bool =
self.contactsService.hasReceivedVerificationRequestFrom(fromId)

View File

@ -116,10 +116,10 @@ method contactRequestRejectionRemoved*(self: AccessInterface, publicKey: string)
method getReceivedVerificationRequests*(self: AccessInterface): seq[VerificationRequest] {.base.} =
raise newException(ValueError, "No implementation available")
method hasReceivedVerificationRequestFrom*(self: AccessInterface, fromId: string): bool {.base.} =
method onVerificationRequestDeclined*(self: AccessInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onVerificationRequestDeclined*(self: AccessInterface, publicKey: string) {.base.} =
method onVerificationRequestCanceled*(self: AccessInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onVerificationRequestUpdatedOrAdded*(self: AccessInterface, VerificationRequest: VerificationRequest) {.base.} =

View File

@ -257,12 +257,12 @@ method acceptVerificationRequest*(self: Module, publicKey: string, response: str
method getReceivedVerificationRequests*(self: Module): seq[VerificationRequest] =
self.controller.getReceivedVerificationRequests()
method hasReceivedVerificationRequestFrom*(self: Module, fromId: string): bool =
result = self.controller.hasReceivedVerificationRequestFrom(fromId)
method onVerificationRequestDeclined*(self: Module, publicKey: string) =
self.view.receivedContactRequestsModel.removeItemById(publicKey)
method onVerificationRequestCanceled*(self: Module, publicKey: string) =
self.view.receivedContactRequestsModel.removeItemById(publicKey)
method onVerificationRequestUpdatedOrAdded*(self: Module, request: VerificationRequest) =
let item = self.createItemFromPublicKey(request.fromID)
item.incomingVerificationStatus = VerificationRequestStatus(request.status)

View File

@ -186,5 +186,3 @@ QtObject:
proc acceptVerificationRequest*(self: View, publicKey: string, response: string) {.slot.} =
self.delegate.acceptVerificationRequest(publicKey, response)
proc hasReceivedVerificationRequestFrom*(self: View, fromId: string): bool {.slot.} =
result = self.delegate.hasReceivedVerificationRequestFrom(fromId)

View File

@ -140,7 +140,6 @@ proc toContactsDto*(jsonObj: JsonNode): ContactsDto =
discard jsonObj.getProp("lastUpdatedLocally", result.lastUpdatedLocally)
discard jsonObj.getProp("localNickname", result.localNickname)
discard jsonObj.getProp("bio", result.bio)
result.requestState = ContactRequestState.None
var requestState: int

View File

@ -192,10 +192,15 @@ QtObject:
if self.contacts.hasKey(request.fromId):
self.contacts[request.fromId].trustStatus = TrustStatus.Trusted
self.contacts[request.fromId].verificationStatus = VerificationStatus.Trusted
self.events.emit(SIGNAL_CONTACT_TRUSTED,
TrustArgs(publicKey: request.fromId, isUntrustworthy: false))
self.events.emit(SIGNAL_CONTACT_VERIFIED, ContactArgs(contactId: request.fromId))
if request.status == VerificationStatus.Canceled:
if self.contacts.hasKey(request.fromId):
self.contacts[request.fromId].verificationStatus = VerificationStatus.Canceled
self.events.emit(SIGNAL_CONTACT_VERIFICATION_CANCELLED, ContactArgs(contactId: request.fromId))
else:
self.events.emit(SIGNAL_CONTACT_VERIFICATION_ADDED, data)
@ -664,9 +669,6 @@ QtObject:
proc getReceivedVerificationRequests*(self: Service): seq[VerificationRequest] =
result = toSeq(self.receivedIdentityRequests.values)
proc hasReceivedVerificationRequestFrom*(self: Service, fromId: string): bool =
result = self.receivedIdentityRequests.contains(fromId)
proc sendVerificationRequest*(self: Service, publicKey: string, challenge: string) =
try:
let response = status_contacts.sendVerificationRequest(publicKey, challenge)
@ -685,8 +687,15 @@ QtObject:
proc cancelVerificationRequest*(self: Service, publicKey: string) =
try:
let response = status_contacts.cancelVerificationRequest(publicKey)
if(not response.error.isNil):
var response = status_contacts.getVerificationRequestSentTo(publicKey)
if not response.error.isNil:
let msg = response.error.message
raise newException(RpcException, msg)
let request = response.result.toVerificationRequest()
response = status_contacts.cancelVerificationRequest(request.id)
if not response.error.isNil:
let msg = response.error.message
error "error sending contact verification request", msg
return
@ -694,7 +703,7 @@ QtObject:
var contact = self.getContactById(publicKey)
contact.verificationStatus = VerificationStatus.Unverified
self.saveContact(contact)
self.events.emit(SIGNAL_CONTACT_VERIFICATION_CANCELLED, ContactArgs(contactId: publicKey))
except Exception as e:
error "Error canceling verification request", msg = e.msg

View File

@ -103,8 +103,8 @@ proc getReceivedVerificationRequests*(): RpcResponse[JsonNode] {.raises: [Except
let payload = %* []
result = callPrivateRPC("getReceivedVerificationRequests".prefix, payload)
proc cancelVerificationRequest*(pubkey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [pubkey]
proc cancelVerificationRequest*(requestId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [requestId]
result = callPrivateRPC("cancelVerificationRequest".prefix, payload)
proc retractContactRequest*(pubkey: string): RpcResponse[JsonNode] {.raises: [Exception].} =

View File

@ -133,10 +133,6 @@ SplitView {
contactsStore: QtObject {
readonly property string myPublicKey: "0xdeadbeef"
function hasReceivedVerificationRequestFrom(publicKey) {
return false
}
function joinPrivateChat(publicKey) {
logs.logEvent("contactsStore::joinPrivateChat", ["publicKey"], arguments)
}

View File

@ -115,10 +115,6 @@ QtObject {
return JSON.parse(resp);
}
function hasReceivedVerificationRequestFrom(pubKey) {
return root.contactsModule.hasReceivedVerificationRequestFrom(pubKey);
}
function verifiedTrusted(pubKey) {
root.contactsModule.verifiedTrusted(pubKey);
}

View File

@ -47,23 +47,14 @@ QtObject {
}
function openIncomingIDRequestPopup(publicKey, cb) {
try {
const request = root.rootStore.profileSectionStore.contactsStore.getVerificationDetailsFromAsJson(publicKey)
const popupProperties = {
senderPublicKey: request.from,
senderDisplayName: request.displayName,
senderIcon: request.icon,
challengeText: request.challenge,
responseText: request.response,
messageTimestamp: request.requestedAt,
responseTimestamp: request.repliedAt
}
const popupProperties = {
contactsStore: root.rootStore.profileSectionStore.contactsStore,
publicKey: publicKey
}
const popup = Global.openPopup(contactVerificationRequestPopupComponent, popupProperties)
if (cb)
cb(popup)
} catch (e) {
console.error("Error getting or parsing verification data", e)
const popup = Global.openPopup(contactVerificationRequestPopupComponent, popupProperties)
if (cb) {
cb(popup)
}
}

View File

@ -14,18 +14,52 @@ import shared.views.chat 1.0
StatusModal {
id: root
property string senderPublicKey: ""
property string senderDisplayName: ""
property string senderIcon: ""
property string challengeText: ""
property string responseText: ""
property string messageTimestamp: ""
property string responseTimestamp: ""
property var contactsStore
property string publicKey
signal verificationRefused(string senderPublicKey)
signal responseSent(string senderPublicKey, string response)
header.title: qsTr("%1 is asking you to verify your identity").arg(root.senderDisplayName)
function updateContactDetails() {
try {
const request = root.contactsStore.getVerificationDetailsFromAsJson(root.publicKey)
if (request.requestStatus === Constants.verificationStatus.canceled) {
root.close()
}
d.senderPublicKey = request.from,
d.senderDisplayName = request.displayName
d.senderIcon = request.icon
d.challengeText = request.challenge
d.responseText = request.response
d.messageTimestamp = request.requestedAt
d.responseTimestamp = request.repliedAt
} catch (e) {
console.error("Error getting or parsing verification data", e)
}
}
Connections {
target: root.contactsStore.receivedContactRequestsModel
function onCountChanged() {
root.updateContactDetails()
}
}
QtObject {
id: d
property string senderPublicKey: ""
property string senderDisplayName: ""
property string senderIcon: ""
property string challengeText: ""
property string responseText: ""
property string messageTimestamp: ""
property string responseTimestamp: ""
}
header.title: qsTr("%1 is asking you to verify your identity").arg(d.senderDisplayName)
x: Math.round(((parent ? parent.width : 0) - width) / 2)
y: Math.round(((parent ? parent.height : 0) - height) / 2)
@ -34,6 +68,7 @@ StatusModal {
height: 230 + verificationMessage.height + verificationResponse.height
onOpened: {
root.updateContactDetails()
verificationResponse.input.edit.forceActiveFocus(Qt.MouseFocusReason)
}
@ -51,7 +86,7 @@ StatusModal {
anchors.top: parent.top
anchors.topMargin: Style.current.padding
text: qsTr("%1 would like to verify your identity. Answer the question to prove your identity to %2")
.arg(root.senderDisplayName).arg(root.senderDisplayName)
.arg(d.senderDisplayName).arg(d.senderDisplayName)
font.pixelSize: 15
}
@ -62,19 +97,19 @@ StatusModal {
width: parent.width
isMessage: true
shouldRepeatHeader: true
messageTimestamp: root.messageTimestamp
senderId: root.senderPublicKey
senderDisplayName: root.senderDisplayName
senderIsEnsVerified: Utils.isEnsVerified(root.senderPublicKey)
senderIcon: root.senderIcon
messageText: root.challengeText
messageTimestamp: d.messageTimestamp
senderId: d.senderPublicKey
senderDisplayName: d.senderDisplayName
senderIsEnsVerified: d.senderPublicKey !== "" && Utils.isEnsVerified(d.senderPublicKey)
senderIcon: d.senderIcon
messageText: d.challengeText
messageContentType: Constants.messageContentType.messageType
placeholderMessage: true
}
StatusInput {
id: verificationResponse
visible: !responseText
visible: !d.responseText
anchors.top: verificationMessage.bottom
anchors.topMargin: 5
input.multiline: true
@ -90,30 +125,30 @@ StatusModal {
MessageView {
id: responseMessage
visible: !!root.responseText
visible: !!d.responseText
anchors.top: verificationMessage.bottom
width: parent.width
isMessage: true
shouldRepeatHeader: true
messageTimestamp: root.responseTimestamp
messageTimestamp: d.responseTimestamp
senderId: userProfile.pubKey
senderDisplayName: userProfile.displayName
senderIsEnsVerified: !!userProfile.preferredName
senderIcon: userProfile.icon
messageText: root.responseText
messageText: d.responseText
messageContentType: Constants.messageContentType.messageType
placeholderMessage: true
}
StatusBaseText {
id: responseSent
visible: !!root.responseText
visible: !!d.responseText
width: parent.width
color: Theme.palette.baseColor1
wrapMode: Text.WordWrap
anchors.top: responseMessage.bottom
anchors.topMargin: 58
text: qsTr("Your answer has been sent to %1.").arg(root.senderDisplayName)
text: qsTr("Your answer has been sent to %1.").arg(d.senderDisplayName)
font.pixelSize: 13
horizontalAlignment: Text.AlignHCenter
}
@ -121,32 +156,32 @@ StatusModal {
rightButtons: [
StatusButton {
visible: !root.responseText
visible: !d.responseText
text: qsTr("Refuse Verification")
onClicked: {
root.verificationRefused(root.senderPublicKey)
root.verificationRefused(d.senderPublicKey)
root.close();
}
},
StatusButton {
text: qsTr("Send Answer")
visible: !root.responseText
visible: !d.responseText
enabled: verificationResponse.text !== ""
onClicked: {
root.responseSent(root.senderPublicKey, Utils.escapeHtml(verificationResponse.text))
root.responseText = verificationResponse.text
root.responseTimestamp = Date.now()
root.responseSent(d.senderPublicKey, Utils.escapeHtml(verificationResponse.text))
d.responseText = verificationResponse.text
d.responseTimestamp = Date.now()
}
},
StatusFlatButton {
visible: root.responseText
visible: d.responseText
text: qsTr("Change answer")
onClicked: {
root.responseText = ""
d.responseText = ""
}
},
StatusButton {
visible: root.responseText
visible: d.responseText
text: qsTr("Close")
onClicked: root.close()
}

View File

@ -68,7 +68,7 @@ Pane {
outgoingVerificationStatus !== Constants.verificationStatus.unverified &&
outgoingVerificationStatus !== Constants.verificationStatus.verified &&
outgoingVerificationStatus !== Constants.verificationStatus.trusted
readonly property bool isVerificationRequestReceived: d.isCurrentUser ? false : root.contactsStore.hasReceivedVerificationRequestFrom(root.publicKey)
readonly property bool isVerificationRequestReceived: incomingVerificationStatus === Constants.verificationStatus.verifying
readonly property bool isTrusted: outgoingVerificationStatus === Constants.verificationStatus.trusted ||
incomingVerificationStatus === Constants.verificationStatus.trusted

View File

@ -79,11 +79,11 @@ StatusMenu {
return !root.isMe && root.selectedUserPublicKey !== "" &&
root.store.contactsStore.hasPendingContactRequest(root.selectedUserPublicKey);
}
readonly property bool hasReceivedVerificationRequestFrom: {
readonly property bool hasActiveReceivedVerificationRequestFrom: {
if (!root.selectedUserPublicKey || root.isMe || !root.isContact) {
return false
}
return root.store.contactsStore.hasReceivedVerificationRequestFrom(root.selectedUserPublicKey)
return contactDetails.incomingVerificationStatus === Constants.verificationStatus.verifying
}
readonly property bool isVerificationRequestSent: {
if (!root.selectedUserPublicKey || root.isMe || !root.isContact) {
@ -254,7 +254,7 @@ StatusMenu {
enabled: root.isProfile && !root.isMe && root.isContact
&& !root.isBlockedContact
&& root.outgoingVerificationStatus === Constants.verificationStatus.unverified
&& !root.hasReceivedVerificationRequestFrom
&& !root.hasActiveReceivedVerificationRequestFrom
onTriggered: {
Global.openSendIDRequestPopup(root.selectedUserPublicKey, null)
root.close()
@ -269,10 +269,10 @@ StatusMenu {
icon.name: "checkmark-circle"
enabled: root.isProfile && !root.isMe && root.isContact
&& !root.isBlockedContact && !root.isTrusted
&& (root.hasReceivedVerificationRequestFrom
&& (root.hasActiveReceivedVerificationRequestFrom
|| root.isVerificationRequestSent)
onTriggered: {
if (hasReceivedVerificationRequestFrom) {
if (hasActiveReceivedVerificationRequestFrom) {
Global.openIncomingIDRequestPopup(root.selectedUserPublicKey, null)
} else if (root.isVerificationRequestSent) {
Global.openOutgoingIDRequestPopup(root.selectedUserPublicKey, null)