Prompt user when there are unverified devices

This commit is contained in:
Nicolas Werner 2021-11-01 22:20:15 +01:00
parent 5bd6208c43
commit 2aabe9dcac
No known key found for this signature in database
GPG key ID: C8D75E610773F2D9
9 changed files with 120 additions and 10 deletions

View file

@ -502,6 +502,86 @@ Page {
Layout.fillWidth: true
}
Rectangle {
id: unverifiedStuffBubble
color: Qt.lighter(Nheko.theme.orange, verifyButtonHovered.hovered ? 1.2 : 1.0)
Layout.fillWidth: true
implicitHeight: explanation.height + Nheko.paddingMedium * 2
visible: SelfVerificationStatus.status != SelfVerificationStatus.AllVerified
RowLayout {
id: unverifiedStuffBubbleContainer
width: parent.width
height: explanation.height + Nheko.paddingMedium * 2
spacing: 0
Label {
id: explanation
Layout.margins: Nheko.paddingMedium
Layout.rightMargin: Nheko.paddingSmall
color: Nheko.colors.buttonText
Layout.fillWidth: true
text: switch(SelfVerificationStatus.status) {
case SelfVerificationStatus.NoMasterKey:
//: Cross-signing setup has not run yet.
return qsTr("Encryption not set up");
case SelfVerificationStatus.UnverifiedMasterKey:
//: The user just signed in with this device and hasn't verified their master key.
return qsTr("Unverified login");
case SelfVerificationStatus.UnverifiedDevices:
//: There are unverified devices signed in to this account.
return qsTr("Please verify your other devices");
default:
return ""
}
textFormat: Text.PlainText
wrapMode: Text.Wrap
}
ImageButton {
id: closeUnverifiedBubble
Layout.rightMargin: Nheko.paddingMedium
Layout.topMargin: Nheko.paddingMedium
Layout.alignment: Qt.AlignRight | Qt.AlignTop
hoverEnabled: true
width: fontMetrics.font.pixelSize
height: fontMetrics.font.pixelSize
image: ":/icons/icons/ui/remove-symbol.png"
ToolTip.visible: closeUnverifiedBubble.hovered
ToolTip.text: qsTr("Close")
onClicked: unverifiedStuffBubble.visible = false
}
}
HoverHandler {
id: verifyButtonHovered
enabled: !closeUnverifiedBubble.hovered
acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus | PointerDevice.TouchPad
}
TapHandler {
enabled: !closeUnverifiedBubble.hovered
acceptedButtons: Qt.LeftButton
onSingleTapped: {
if (SelfVerificationStatus.status == SelfVerificationStatus.UnverifiedDevices) {
SelfVerificationStatus.verifyUnverifiedDevices();
} else {
SelfVerificationStatus.statusChanged();
}
}
}
}
Rectangle {
color: Nheko.theme.separator
height: 1
Layout.fillWidth: true
visible: unverifiedStuffBubble.visible
}
}
footer: ColumnLayout {

View file

@ -277,6 +277,10 @@ Item {
bootstrapCrosssigning.open();
else if (SelfVerificationStatus.status == SelfVerificationStatus.UnverifiedMasterKey)
verifyMasterKey.open();
else {
bootstrapCrosssigning.close();
verifyMasterKey.close();
}
}

View file

@ -23,7 +23,10 @@ Pane {
text: {
if (flow.sender) {
if (flow.isSelfVerification)
return qsTr("To allow other users to see, which of your devices actually belong to you, you can verify them. This also allows key backup to work automatically. Verify %1 now?").arg(flow.deviceId);
if (flow.isMultiDeviceVerification)
return qsTr("To allow other users to see, which of your devices actually belong to you, you can verify them. This also allows key backup to work automatically. Verify an unverified device now? (Please make sure you have one of those devices available.)");
else
return qsTr("To allow other users to see, which of your devices actually belong to you, you can verify them. This also allows key backup to work automatically. Verify %1 now?").arg(flow.deviceId);
else
return qsTr("To ensure that no malicious user can eavesdrop on your encrypted communications you can verify the other party.");
} else {

View file

@ -208,8 +208,7 @@ Cache::Cache(const QString &userId, QObject *parent)
[this](const std::string &u) {
if (u == localUserId_.toStdString()) {
auto status = verificationStatus(u);
if (status.unverified_device_count || !status.user_verified)
emit selfUnverified();
emit selfVerificationStatusChanged();
}
},
Qt::QueuedConnection);
@ -4265,6 +4264,7 @@ Cache::markDeviceVerified(const std::string &user_id, const std::string &key)
std::unique_lock<std::mutex> lock(verification_storage.verification_storage_mtx);
if (user_id == local_user) {
std::swap(tmp, verification_storage.status);
verification_storage.status.clear();
} else {
verification_storage.status.erase(user_id);
}
@ -4274,9 +4274,8 @@ Cache::markDeviceVerified(const std::string &user_id, const std::string &key)
(void)status;
emit verificationStatusChanged(user);
}
} else {
emit verificationStatusChanged(user_id);
}
emit verificationStatusChanged(user_id);
}
void
@ -4316,9 +4315,8 @@ Cache::markDeviceUnverified(const std::string &user_id, const std::string &key)
(void)status;
emit verificationStatusChanged(user);
}
} else {
emit verificationStatusChanged(user_id);
}
emit verificationStatusChanged(user_id);
}
VerificationStatus

View file

@ -310,7 +310,7 @@ signals:
void removeNotification(const QString &room_id, const QString &event_id);
void userKeysUpdate(const std::string &sync_token, const mtx::responses::QueryKeys &keyQuery);
void verificationStatusChanged(const std::string &userid);
void selfUnverified();
void selfVerificationStatusChanged();
void secretChanged(const std::string name);
private:

View file

@ -69,6 +69,7 @@ class DeviceVerificationFlow : public QObject
Q_PROPERTY(std::vector<int> sasList READ getSasList CONSTANT)
Q_PROPERTY(bool isDeviceVerification READ isDeviceVerification CONSTANT)
Q_PROPERTY(bool isSelfVerification READ isSelfVerification CONSTANT)
Q_PROPERTY(bool isMultiDeviceVerification READ isMultiDeviceVerification CONSTANT)
public:
enum State
@ -139,6 +140,7 @@ public:
return this->type == DeviceVerificationFlow::Type::ToDevice;
}
bool isSelfVerification() const;
bool isMultiDeviceVerification() const { return deviceIds.size() > 1; }
void callback_fn(const UserKeyCache &res, mtx::http::RequestErr err, std::string user_id);

View file

@ -20,7 +20,7 @@ SelfVerificationStatus::SelfVerificationStatus(QObject *o)
{
connect(MainWindow::instance(), &MainWindow::reload, this, [this] {
connect(cache::client(),
&Cache::selfUnverified,
&Cache::selfVerificationStatusChanged,
this,
&SelfVerificationStatus::invalidate,
Qt::UniqueConnection);
@ -233,6 +233,24 @@ void
SelfVerificationStatus::verifyUnverifiedDevices()
{
nhlog::db()->info("Clicked verify unverified devices");
const auto this_user = http::client()->user_id().to_string();
auto keys = cache::client()->userKeys(this_user);
auto verif = cache::client()->verificationStatus(this_user);
if (!keys)
return;
std::vector<QString> devices;
for (const auto &[device, keys] : keys->device_keys) {
(void)keys;
if (!verif.verified_devices.count(device))
devices.push_back(QString::fromStdString(device));
}
if (!devices.empty())
ChatPage::instance()->timelineManager()->verificationManager()->verifyOneOfDevices(
QString::fromStdString(this_user), std::move(devices));
}
void

View file

@ -62,13 +62,16 @@ Theme::Theme(std::string_view theme)
sidebarBackground_ = QColor("#233649");
alternateButton_ = QColor("#ccc");
red_ = QColor("#a82353");
orange_ = QColor("#fcbe05");
} else if (theme == "dark") {
sidebarBackground_ = QColor("#2d3139");
alternateButton_ = QColor("#414A59");
red_ = QColor("#a82353");
orange_ = QColor("#fcc53a");
} else {
sidebarBackground_ = p.window().color();
alternateButton_ = p.dark().color();
red_ = QColor("red");
orange_ = QColor("orange");
}
}

View file

@ -62,6 +62,7 @@ class Theme : public QPalette
Q_PROPERTY(QColor alternateButton READ alternateButton CONSTANT)
Q_PROPERTY(QColor separator READ separator CONSTANT)
Q_PROPERTY(QColor red READ red CONSTANT)
Q_PROPERTY(QColor orange READ orange CONSTANT)
public:
Theme() {}
explicit Theme(std::string_view theme);
@ -71,7 +72,8 @@ public:
QColor alternateButton() const { return alternateButton_; }
QColor separator() const { return separator_; }
QColor red() const { return red_; }
QColor orange() const { return orange_; }
private:
QColor sidebarBackground_, separator_, red_, alternateButton_;
QColor sidebarBackground_, separator_, red_, orange_, alternateButton_;
};