mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 03:00:46 +03:00
176 lines
5.4 KiB
C++
176 lines
5.4 KiB
C++
// SPDX-FileCopyrightText: Nheko Contributors
|
|
//
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#include "VerificationManager.h"
|
|
|
|
#include <chrono>
|
|
|
|
#include "Cache.h"
|
|
#include "ChatPage.h"
|
|
#include "DeviceVerificationFlow.h"
|
|
#include "Logging.h"
|
|
#include "timeline/RoomlistModel.h"
|
|
#include "timeline/TimelineModel.h"
|
|
#include "timeline/TimelineViewManager.h"
|
|
|
|
VerificationManager::VerificationManager(TimelineViewManager *o)
|
|
: QObject(o)
|
|
, rooms_(o->rooms())
|
|
{
|
|
instance_ = this;
|
|
}
|
|
|
|
static bool
|
|
isValidTime(std::optional<uint64_t> t)
|
|
{
|
|
if (!t)
|
|
return false;
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
std::chrono::time_point<std::chrono::system_clock> time{std::chrono::milliseconds(*t)};
|
|
auto diff = std::chrono::system_clock::now() - time;
|
|
|
|
return diff < 10min && diff > -5min;
|
|
}
|
|
|
|
void
|
|
VerificationManager::receivedRoomDeviceVerificationRequest(
|
|
const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &message,
|
|
TimelineModel *model)
|
|
{
|
|
if (this->isInitialSync_)
|
|
return;
|
|
|
|
if (!isValidTime(message.origin_server_ts))
|
|
return;
|
|
|
|
auto event_id = QString::fromStdString(message.event_id);
|
|
if (!this->dvList.contains(event_id)) {
|
|
if (auto flow = DeviceVerificationFlow::NewInRoomVerification(
|
|
this, model, message.content, QString::fromStdString(message.sender), event_id)) {
|
|
dvList[event_id] = flow;
|
|
emit newDeviceVerificationRequest(flow.data());
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
VerificationManager::receivedDeviceVerificationRequest(
|
|
const mtx::events::msg::KeyVerificationRequest &msg,
|
|
std::string sender)
|
|
{
|
|
if (this->isInitialSync_)
|
|
return;
|
|
|
|
if (!isValidTime(msg.timestamp))
|
|
return;
|
|
|
|
if (!msg.transaction_id)
|
|
return;
|
|
|
|
auto txnid = QString::fromStdString(msg.transaction_id.value());
|
|
if (!this->dvList.contains(txnid)) {
|
|
if (auto flow = DeviceVerificationFlow::NewToDeviceVerification(
|
|
this, msg, QString::fromStdString(sender), txnid)) {
|
|
dvList[txnid] = flow;
|
|
emit newDeviceVerificationRequest(flow.data());
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
VerificationManager::receivedDeviceVerificationStart(
|
|
const mtx::events::msg::KeyVerificationStart &msg,
|
|
std::string sender)
|
|
{
|
|
if (this->isInitialSync_)
|
|
return;
|
|
|
|
// can't do this for start messages sent as to_device...
|
|
// if (!isValidTime(msg.timestamp))
|
|
// return;
|
|
|
|
if (!msg.transaction_id)
|
|
return;
|
|
|
|
auto txnid = QString::fromStdString(msg.transaction_id.value());
|
|
if (!this->dvList.contains(txnid)) {
|
|
if (auto flow = DeviceVerificationFlow::NewToDeviceVerification(
|
|
this, msg, QString::fromStdString(sender), txnid)) {
|
|
dvList[txnid] = flow;
|
|
emit newDeviceVerificationRequest(flow.data());
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
VerificationManager::verifyUser(QString userid)
|
|
{
|
|
auto joined_rooms = cache::joinedRooms();
|
|
auto room_infos = cache::getRoomInfo(joined_rooms);
|
|
|
|
for (const std::string &room_id : joined_rooms) {
|
|
if ((room_infos[QString::fromStdString(room_id)].member_count == 2) &&
|
|
cache::isRoomEncrypted(room_id)) {
|
|
auto room_members = cache::roomMembers(room_id);
|
|
if (std::find(room_members.begin(), room_members.end(), (userid).toStdString()) !=
|
|
room_members.end()) {
|
|
if (auto model = rooms_->getRoomById(QString::fromStdString(room_id))) {
|
|
auto flow =
|
|
DeviceVerificationFlow::InitiateUserVerification(this, model.data(), userid);
|
|
std::unique_ptr<QObject> context{new QObject(flow.get())};
|
|
QObject *pcontext = context.get();
|
|
connect(
|
|
model.data(),
|
|
&TimelineModel::updateFlowEventId,
|
|
pcontext,
|
|
[this, flow, context = std::move(context)](std::string eventId) mutable {
|
|
if (context->parent() == flow.get()) {
|
|
dvList[QString::fromStdString(eventId)] = flow;
|
|
context.reset();
|
|
}
|
|
});
|
|
emit newDeviceVerificationRequest(flow.data());
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
emit ChatPage::instance()->showNotification(
|
|
tr("No encrypted private chat found with this user. Create an "
|
|
"encrypted private chat with this user and try again."));
|
|
}
|
|
|
|
void
|
|
VerificationManager::removeVerificationFlow(DeviceVerificationFlow *flow)
|
|
{
|
|
nhlog::crypto()->debug("Removing verification flow {}", (void *)flow);
|
|
for (auto it = dvList.keyValueBegin(); it != dvList.keyValueEnd(); ++it) {
|
|
if (it->second == flow) {
|
|
dvList.remove((*it).first);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
VerificationManager::verifyDevice(QString userid, QString deviceid)
|
|
{
|
|
auto flow = DeviceVerificationFlow::InitiateDeviceVerification(this, userid, {deviceid});
|
|
this->dvList[flow->transactionId()] = flow;
|
|
emit newDeviceVerificationRequest(flow.data());
|
|
}
|
|
|
|
void
|
|
VerificationManager::verifyOneOfDevices(QString userid, std::vector<QString> deviceids)
|
|
{
|
|
auto flow =
|
|
DeviceVerificationFlow::InitiateDeviceVerification(this, userid, std::move(deviceids));
|
|
this->dvList[flow->transactionId()] = flow;
|
|
emit newDeviceVerificationRequest(flow.data());
|
|
}
|
|
|
|
#include "moc_VerificationManager.cpp"
|