Add ability to remove local encryption keys through settings

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
This commit is contained in:
Claudio Cambra 2022-11-11 16:01:04 +01:00
parent 689dee6a16
commit cc6bdc9bd5
No known key found for this signature in database
GPG Key ID: C839200C384636B0
4 changed files with 67 additions and 17 deletions

View File

@ -66,6 +66,7 @@ constexpr auto propertyFolder = "folder";
constexpr auto propertyPath = "path";
constexpr auto e2eUiActionIdKey = "id";
constexpr auto e2EeUiActionEnableEncryptionId = "enable_encryption";
constexpr auto e2EeUiActionDisableEncryptionId = "disable_encryption";
constexpr auto e2EeUiActionDisplayMnemonicId = "display_mnemonic";
}
@ -243,7 +244,12 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent)
void AccountSettings::slotE2eEncryptionMnemonicReady()
{
auto *const actionDisplayMnemonic = addActionToEncryptionMessage(tr("Display mnemonic"), e2EeUiActionDisplayMnemonicId);
const auto actionDisableEncryption = addActionToEncryptionMessage(tr("Disable encryption"), e2EeUiActionDisableEncryptionId);
connect(actionDisableEncryption, &QAction::triggered, this, [this] {
disableEncryptionForAccount(_accountState->account());
});
const auto actionDisplayMnemonic = addActionToEncryptionMessage(tr("Display mnemonic"), e2EeUiActionDisplayMnemonicId);
connect(actionDisplayMnemonic, &QAction::triggered, this, [this]() {
displayMnemonic(_accountState->account()->e2e()->_mnemonic);
});
@ -1024,6 +1030,31 @@ void AccountSettings::displayMnemonic(const QString &mnemonic)
widget.exec();
}
void AccountSettings::disableEncryptionForAccount(const AccountPtr &account) const
{
QMessageBox dialog;
dialog.setWindowTitle(tr("Disable end-to-end encryption"));
dialog.setText(tr("Disable end-to-end encryption for %1?").arg(account->davUser()));
dialog.setInformativeText(tr("Removing end-to-end encryption will remove locally-synced files that are encrypted."
"<br>"
"Encrypted files will remain on the server."));
dialog.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
dialog.setDefaultButton(QMessageBox::Ok);
dialog.adjustSize();
const auto ret = dialog.exec();
switch(ret) {
case QMessageBox::Ok:
connect(account->e2e(), &ClientSideEncryption::sensitiveDataForgotten,
this, &AccountSettings::resetE2eEncryption);
account->e2e()->forgetSensitiveData(account);
break;
case QMessageBox::Cancel:
break;
Q_UNREACHABLE();
}
}
void AccountSettings::showConnectionLabel(const QString &message, QStringList errors)
{
const auto errStyle = QLatin1String("color:#ffffff; background-color:#bb4d4d;padding:5px;"
@ -1257,16 +1288,21 @@ void AccountSettings::slotAccountStateChanged()
refreshSelectiveSyncStatus();
if (state == AccountState::State::Connected) {
/* TODO: We should probably do something better here.
* Verify if the user has a private key already uploaded to the server,
* if it has, do not offer to create one.
*/
qCInfo(lcAccountSettings) << "Account" << accountsState()->account()->displayName()
<< "Client Side Encryption" << accountsState()->account()->capabilities().clientSideEncryptionAvailable();
checkClientSideEncryptionState();
}
}
if (_accountState->account()->capabilities().clientSideEncryptionAvailable()) {
_ui->encryptionMessage->show();
}
void AccountSettings::checkClientSideEncryptionState()
{
/* TODO: We should probably do something better here.
* Verify if the user has a private key already uploaded to the server,
* if it has, do not offer to create one.
*/
qCInfo(lcAccountSettings) << "Account" << accountsState()->account()->displayName()
<< "Client Side Encryption" << accountsState()->account()->capabilities().clientSideEncryptionAvailable();
if (_accountState->account()->capabilities().clientSideEncryptionAvailable()) {
_ui->encryptionMessage->show();
}
}
@ -1569,6 +1605,17 @@ void AccountSettings::initializeE2eEncryption()
}
}
void AccountSettings::resetE2eEncryption()
{
for (const auto action : _ui->encryptionMessage->actions()) {
_ui->encryptionMessage->removeAction(action);
}
_ui->encryptionMessage->setText({});
_ui->encryptionMessage->setIcon({});
initializeE2eEncryption();
checkClientSideEncryptionState();
}
void AccountSettings::removeActionFromEncryptionMessage(const QString &actionId)
{
const auto foundEnableEncryptionActionIt = std::find_if(std::cbegin(_ui->encryptionMessage->actions()), std::cend(_ui->encryptionMessage->actions()), [&actionId](const QAction *action) {

View File

@ -119,11 +119,14 @@ private slots:
private slots:
void displayMnemonic(const QString &mnemonic);
void disableEncryptionForAccount(const AccountPtr &account) const;
void showConnectionLabel(const QString &message, QStringList errors = QStringList());
void openIgnoredFilesDialog(const QString & absFolderPath);
void customizeStyle();
void initializeE2eEncryption();
void resetE2eEncryption();
void checkClientSideEncryptionState();
void removeActionFromEncryptionMessage(const QString &actionId);
private:

View File

@ -1066,7 +1066,7 @@ void ClientSideEncryption::forgetSensitiveData(const AccountPtr &account)
{
_publicKey = QSslKey();
const auto createDeleteJob = [account](QString user) {
const auto createDeleteJob = [account](const QString user) {
auto *job = new DeletePasswordJob(Theme::instance()->appName());
job->setInsecureFallback(false);
job->setKey(AbstractCredentials::keychainKey(account->url().toString(), user, account->id()));
@ -1086,7 +1086,7 @@ void ClientSideEncryption::forgetSensitiveData(const AccountPtr &account)
deleteMnemonicJob->start();
}
void ClientSideEncryption::handlePrivateKeyDeleted(QKeychain::Job *incoming)
void ClientSideEncryption::handlePrivateKeyDeleted(const QKeychain::Job* const incoming)
{
if (incoming->error() != QKeychain::NoError) {
qCWarning(lcCse) << "Private key could not be deleted:" << incoming->errorString();
@ -1099,7 +1099,7 @@ void ClientSideEncryption::handlePrivateKeyDeleted(QKeychain::Job *incoming)
checkAllSensitiveDataDeleted();
}
void ClientSideEncryption::handleCertificateDeleted(QKeychain::Job *incoming)
void ClientSideEncryption::handleCertificateDeleted(const QKeychain::Job* const incoming)
{
if (incoming->error() != QKeychain::NoError) {
qCWarning(lcCse) << "Certificate could not be deleted:" << incoming->errorString();
@ -1112,7 +1112,7 @@ void ClientSideEncryption::handleCertificateDeleted(QKeychain::Job *incoming)
checkAllSensitiveDataDeleted();
}
void ClientSideEncryption::handleMnemonicDeleted(QKeychain::Job *incoming)
void ClientSideEncryption::handleMnemonicDeleted(const QKeychain::Job* const incoming)
{
if (incoming->error() != QKeychain::NoError) {
qCWarning(lcCse) << "Mnemonic could not be deleted:" << incoming->errorString();

View File

@ -145,9 +145,9 @@ private slots:
void privateKeyFetched(QKeychain::Job *incoming);
void mnemonicKeyFetched(QKeychain::Job *incoming);
void handlePrivateKeyDeleted(QKeychain::Job *incoming);
void handleCertificateDeleted(QKeychain::Job *incoming);
void handleMnemonicDeleted(QKeychain::Job *incoming);
void handlePrivateKeyDeleted(const QKeychain::Job* const incoming);
void handleCertificateDeleted(const QKeychain::Job* const incoming);
void handleMnemonicDeleted(const QKeychain::Job* const incoming);
void checkAllSensitiveDataDeleted();
void getPrivateKeyFromServer(const AccountPtr &account);