veilidchat/lib/contact_invitation/models/valid_contact_invitation.dart
Christien Rioux 20047a956f more refactor
2024-01-27 20:10:30 -05:00

148 lines
5.9 KiB
Dart

import 'package:meta/meta.dart';
import 'package:veilid_support/veilid_support.dart';
import '../../account_manager/account_manager.dart';
import '../../proto/proto.dart' as proto;
import '../../tools/tools.dart';
import '../models/models.dart';
import 'contact_invitation_repository.dart';
//////////////////////////////////////////////////
///
class ValidContactInvitation {
@internal
ValidContactInvitation(
{required ActiveAccountInfo activeAccountInfo,
required proto.SignedContactInvitation signedContactInvitation,
required proto.ContactInvitation contactInvitation,
required TypedKey contactRequestInboxKey,
required proto.ContactRequest contactRequest,
required proto.ContactRequestPrivate contactRequestPrivate,
required IdentityMaster contactIdentityMaster,
required KeyPair writer})
: _activeAccountInfo = activeAccountInfo,
_signedContactInvitation = signedContactInvitation,
_contactInvitation = contactInvitation,
_contactRequestInboxKey = contactRequestInboxKey,
_contactRequest = contactRequest,
_contactRequestPrivate = contactRequestPrivate,
_contactIdentityMaster = contactIdentityMaster,
_writer = writer;
Future<AcceptedContact?> accept() async {
final pool = DHTRecordPool.instance;
try {
// Ensure we don't delete this if we're trying to chat to self
final isSelf = _contactIdentityMaster.identityPublicKey ==
_activeAccountInfo.localAccount.identityMaster.identityPublicKey;
final accountRecordKey = _activeAccountInfo.accountRecordKey;
return (await pool.openWrite(_contactRequestInboxKey, _writer,
parent: accountRecordKey))
// ignore: prefer_expression_function_bodies
.maybeDeleteScope(!isSelf, (contactRequestInbox) async {
// Create local conversation key for this
// contact and send via contact response
return createConversation(
activeAccountInfo: _activeAccountInfo,
remoteIdentityPublicKey:
_contactIdentityMaster.identityPublicTypedKey(),
callback: (localConversation) async {
final contactResponse = proto.ContactResponse()
..accept = true
..remoteConversationRecordKey = localConversation.key.toProto()
..identityMasterRecordKey = _activeAccountInfo
.localAccount.identityMaster.masterRecordKey
.toProto();
final contactResponseBytes = contactResponse.writeToBuffer();
final cs = await pool.veilid
.getCryptoSystem(_contactRequestInboxKey.kind);
final identitySignature = await cs.sign(
_activeAccountInfo.conversationWriter.key,
_activeAccountInfo.conversationWriter.secret,
contactResponseBytes);
final signedContactResponse = proto.SignedContactResponse()
..contactResponse = contactResponseBytes
..identitySignature = identitySignature.toProto();
// Write the acceptance to the inbox
if (await contactRequestInbox.tryWriteProtobuf(
proto.SignedContactResponse.fromBuffer,
signedContactResponse,
subkey: 1) !=
null) {
throw Exception('failed to accept contact invitation');
}
return AcceptedContact(
profile: _contactRequestPrivate.profile,
remoteIdentity: _contactIdentityMaster,
remoteConversationRecordKey: proto.TypedKeyProto.fromProto(
_contactRequestPrivate.chatRecordKey),
localConversationRecordKey: localConversation.key,
);
});
});
} on Exception catch (e) {
log.debug('exception: $e', e);
return null;
}
}
Future<bool> reject() async {
final pool = DHTRecordPool.instance;
// Ensure we don't delete this if we're trying to chat to self
final isSelf = _contactIdentityMaster.identityPublicKey ==
_activeAccountInfo.localAccount.identityMaster.identityPublicKey;
final accountRecordKey =
_activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
return (await pool.openWrite(_contactRequestInboxKey, _writer,
parent: accountRecordKey))
.maybeDeleteScope(!isSelf, (contactRequestInbox) async {
final cs =
await pool.veilid.getCryptoSystem(_contactRequestInboxKey.kind);
final contactResponse = proto.ContactResponse()
..accept = false
..identityMasterRecordKey = _activeAccountInfo
.localAccount.identityMaster.masterRecordKey
.toProto();
final contactResponseBytes = contactResponse.writeToBuffer();
final identitySignature = await cs.sign(
_activeAccountInfo.conversationWriter.key,
_activeAccountInfo.conversationWriter.secret,
contactResponseBytes);
final signedContactResponse = proto.SignedContactResponse()
..contactResponse = contactResponseBytes
..identitySignature = identitySignature.toProto();
// Write the rejection to the inbox
if (await contactRequestInbox.tryWriteProtobuf(
proto.SignedContactResponse.fromBuffer, signedContactResponse,
subkey: 1) !=
null) {
log.error('failed to reject contact invitation');
return false;
}
return true;
});
}
//
final ActiveAccountInfo _activeAccountInfo;
final TypedKey _contactRequestInboxKey;
final IdentityMaster _contactIdentityMaster;
final KeyPair _writer;
proto.SignedContactInvitation _signedContactInvitation;
proto.ContactInvitation _contactInvitation;
proto.ContactRequest _contactRequest;
proto.ContactRequestPrivate _contactRequestPrivate;
}