mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2025-02-02 11:24:50 -05:00
contact accept
This commit is contained in:
parent
b12cbcf684
commit
6f525843ff
@ -88,7 +88,9 @@
|
||||
"paste": "Paste",
|
||||
"message_from_contact": "Message from contact",
|
||||
"validating": "Validating...",
|
||||
"invalid_invitation": "Invalid invitation"
|
||||
"invalid_invitation": "Invalid invitation",
|
||||
"failed_to_accept": "Failed to accept contact invite",
|
||||
"failed_to_reject": "Failed to reject contact invite"
|
||||
},
|
||||
"enter_pin_dialog": {
|
||||
"enter_pin": "Enter PIN",
|
||||
|
@ -34,7 +34,7 @@
|
||||
3. Set ContactRequest unicastinbox DHT record writer subkey with SignedContactResponse, encrypted with writer secret
|
||||
|
||||
## Receiving an accept/reject
|
||||
1. Open and get SignedContactResponse from ContactRequest unicaseinbox DHT record
|
||||
1. Open and get SignedContactResponse from ContactRequest unicastinbox DHT record
|
||||
2. Decrypt with writer secret
|
||||
3. Get DHT record for contact's AccountMaster
|
||||
4. Validate the SignedContactResponse signature
|
||||
@ -42,8 +42,10 @@
|
||||
If accept == false:
|
||||
1. Announce rejection
|
||||
2. Delete local invitation from table
|
||||
3. Overwrite and delete ContactRequest inbox
|
||||
|
||||
If accept == true:
|
||||
1. Add a local contact with the remote chat dht record, updating from the remote profile in it.
|
||||
2. Delete local invitation from table
|
||||
3. Overwrite and delete ContactRequest inbox
|
||||
|
||||
|
@ -111,7 +111,24 @@ class PasteInviteDialogState extends ConsumerState<PasteInviteDialog> {
|
||||
}
|
||||
final validInvitation = _validInvitation;
|
||||
if (validInvitation != null) {
|
||||
final acceptedContact =
|
||||
await acceptContactInvitation(activeAccountInfo, validInvitation);
|
||||
if (acceptedContact != null) {
|
||||
await createContact(
|
||||
activeAccountInfo: activeAccountInfo,
|
||||
profile: acceptedContact.profile,
|
||||
remoteIdentity: acceptedContact.remoteIdentity,
|
||||
remoteConversation: acceptedContact.remoteConversation,
|
||||
localConversation: acceptedContact.localConversation,
|
||||
);
|
||||
ref
|
||||
..invalidate(fetchContactInvitationRecordsProvider)
|
||||
..invalidate(fetchContactListProvider);
|
||||
} else {
|
||||
if (context.mounted) {
|
||||
showErrorToast(context, 'paste_invite_dialog.failed_to_accept');
|
||||
}
|
||||
}
|
||||
}
|
||||
setState(() {
|
||||
_isAccepting = false;
|
||||
@ -135,7 +152,13 @@ class PasteInviteDialogState extends ConsumerState<PasteInviteDialog> {
|
||||
}
|
||||
final validInvitation = _validInvitation;
|
||||
if (validInvitation != null) {
|
||||
await rejectContactInvitation(activeAccountInfo, validInvitation);
|
||||
if (await rejectContactInvitation(activeAccountInfo, validInvitation)) {
|
||||
// do nothing right now
|
||||
} else {
|
||||
if (context.mounted) {
|
||||
showErrorToast(context, 'paste_invite_dialog.failed_to_reject');
|
||||
}
|
||||
}
|
||||
}
|
||||
setState(() {
|
||||
_isAccepting = false;
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
||||
@ -330,18 +331,40 @@ Future<ValidContactInvitation> validateContactInvitation(Uint8List inviteData,
|
||||
return out;
|
||||
}
|
||||
|
||||
Future<void> acceptContactInvitation(ActiveAccountInfo activeAccountInfo,
|
||||
class AcceptedContact {
|
||||
AcceptedContact({
|
||||
required this.profile,
|
||||
required this.remoteIdentity,
|
||||
required this.remoteConversation,
|
||||
required this.localConversation,
|
||||
});
|
||||
|
||||
proto.Profile profile;
|
||||
IdentityMaster remoteIdentity;
|
||||
TypedKey remoteConversation;
|
||||
OwnedDHTRecordPointer localConversation;
|
||||
}
|
||||
|
||||
Future<AcceptedContact?> acceptContactInvitation(
|
||||
ActiveAccountInfo activeAccountInfo,
|
||||
ValidContactInvitation validContactInvitation) async {
|
||||
final pool = await DHTRecordPool.instance();
|
||||
await (await pool.openWrite(validContactInvitation.contactRequestInboxKey,
|
||||
final accountRecordKey =
|
||||
activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
|
||||
|
||||
return (await pool.openWrite(validContactInvitation.contactRequestInboxKey,
|
||||
validContactInvitation.writer))
|
||||
.deleteScope((contactRequestInbox) async {
|
||||
final cs = await pool.veilid
|
||||
.getCryptoSystem(validContactInvitation.contactRequestInboxKey.kind);
|
||||
|
||||
// xxx
|
||||
// Create local conversation key for this
|
||||
// contact and send via contact response
|
||||
return (await pool.create(parent: accountRecordKey))
|
||||
.deleteScope((localConversation) async {
|
||||
final contactResponse = ContactResponse()
|
||||
..accept = false
|
||||
..accept = true
|
||||
..remoteConversationKey = localConversation.key.toProto()
|
||||
..identityMasterRecordKey = activeAccountInfo
|
||||
.localAccount.identityMaster.masterRecordKey
|
||||
.toProto();
|
||||
@ -356,20 +379,31 @@ Future<void> acceptContactInvitation(ActiveAccountInfo activeAccountInfo,
|
||||
..contactResponse = contactResponseBytes
|
||||
..identitySignature = identitySignature.toProto();
|
||||
|
||||
// Write the rejection to the invox
|
||||
// Write the acceptance to the inbox
|
||||
if (await contactRequestInbox.tryWriteProtobuf(
|
||||
SignedContactResponse.fromBuffer, signedContactResponse,
|
||||
subkey: 1) !=
|
||||
null) {
|
||||
log.error('failed to accept contact invitation');
|
||||
await localConversation.delete();
|
||||
await contactRequestInbox.delete();
|
||||
return null;
|
||||
}
|
||||
return AcceptedContact(
|
||||
profile: validContactInvitation.contactRequestPrivate.profile,
|
||||
remoteIdentity: validContactInvitation.contactIdentityMaster,
|
||||
remoteConversation: proto.TypedKeyProto.fromProto(
|
||||
validContactInvitation.contactRequestPrivate.chatRecordKey),
|
||||
localConversation: localConversation.ownedDHTRecordPointer,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> rejectContactInvitation(ActiveAccountInfo activeAccountInfo,
|
||||
Future<bool> rejectContactInvitation(ActiveAccountInfo activeAccountInfo,
|
||||
ValidContactInvitation validContactInvitation) async {
|
||||
final pool = await DHTRecordPool.instance();
|
||||
await (await pool.openWrite(validContactInvitation.contactRequestInboxKey,
|
||||
return (await pool.openWrite(validContactInvitation.contactRequestInboxKey,
|
||||
validContactInvitation.writer))
|
||||
.deleteScope((contactRequestInbox) async {
|
||||
final cs = await pool.veilid
|
||||
@ -397,6 +431,40 @@ Future<void> rejectContactInvitation(ActiveAccountInfo activeAccountInfo,
|
||||
subkey: 1) !=
|
||||
null) {
|
||||
log.error('failed to reject contact invitation');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> createContact({
|
||||
required ActiveAccountInfo activeAccountInfo,
|
||||
required proto.Profile profile,
|
||||
required IdentityMaster remoteIdentity,
|
||||
required TypedKey remoteConversation,
|
||||
required OwnedDHTRecordPointer localConversation,
|
||||
}) async {
|
||||
final accountRecordKey =
|
||||
activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
|
||||
|
||||
// Create Contact
|
||||
final contact = Contact()
|
||||
..editedProfile = profile
|
||||
..remoteProfile = profile
|
||||
..remoteIdentity = jsonEncode(remoteIdentity.toJson())
|
||||
..remoteConversationKey = remoteConversation.toProto()
|
||||
..localConversation = localConversation.toProto()
|
||||
..showAvailability = false;
|
||||
|
||||
// Add Contact to account's list
|
||||
// if this fails, don't keep retrying, user can try again later
|
||||
await (await DHTShortArray.openOwned(
|
||||
proto.OwnedDHTRecordPointerProto.fromProto(
|
||||
activeAccountInfo.account.contactList),
|
||||
parent: accountRecordKey))
|
||||
.scope((contactList) async {
|
||||
if (await contactList.tryAddItem(contact.writeToBuffer()) == false) {
|
||||
throw StateError('Failed to add contact');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user