Commit 83732575 authored by Ingo Klöcker's avatar Ingo Klöcker
Browse files

Offer separate actions for creating OpenPGP key pair resp. S/MIME CSR

Simplify the creation of a new OpenPGP certificate resp. an S/MIME CSR
by offering two separate actions instead of a single action which in the
first steps asks the user what kind of certificate them want to create.
The old NewCertificateCommand now always creates an S/MIME CSR.

GnuPG-bug-id: 5832
parent 95416fb1
......@@ -317,8 +317,6 @@ set(_kleopatra_SRCS
dialogs/certifycertificatedialog.h
dialogs/certifywidget.cpp
dialogs/certifywidget.h
dialogs/choosecertificateprotocoldialog.cpp
dialogs/choosecertificateprotocoldialog.h
dialogs/createcsrforcardkeydialog.cpp
dialogs/createcsrforcardkeydialog.h
dialogs/deletecertificatesdialog.cpp
......
......@@ -16,7 +16,6 @@
#include "command_p.h"
#include "newopenpgpcertificatecommand.h"
#include "dialogs/choosecertificateprotocoldialog.h"
#include "newcertificatewizard/newcertificatewizard.h"
#include <settings.h>
......@@ -40,20 +39,15 @@ public:
{
}
void chooseProtocol();
void createCertificate();
private:
void onProtocolChosen();
void slotDialogAccepted();
private:
void ensureDialogCreated();
private:
Protocol protocol = GpgME::UnknownProtocol;
QPointer<ChooseCertificateProtocolDialog> protocolDialog;
QPointer<NewCertificateWizard> dialog;
};
......@@ -69,65 +63,23 @@ const NewCertificateCommand::Private *NewCertificateCommand::d_func() const
#define d d_func()
#define q q_func()
void NewCertificateCommand::Private::chooseProtocol()
void NewCertificateCommand::Private::createCertificate()
{
Q_ASSERT(protocol == GpgME::UnknownProtocol);
Q_ASSERT(!protocolDialog);
Q_ASSERT(!dialog);
protocolDialog = new ChooseCertificateProtocolDialog;
applyWindowID(protocolDialog);
dialog = new NewCertificateWizard;
applyWindowID(dialog);
dialog->setAttribute(Qt::WA_DeleteOnClose);
connect(protocolDialog, &QDialog::accepted, q, [this]() {
onProtocolChosen();
connect(dialog, &QDialog::accepted, q, [this]() {
slotDialogAccepted();
});
connect(protocolDialog, &QDialog::rejected, q, [this]() {
connect(dialog, &QDialog::rejected, q, [this]() {
canceled();
protocolDialog->deleteLater();
});
protocolDialog->show();
}
void NewCertificateCommand::Private::onProtocolChosen()
{
protocol = protocolDialog->protocol();
protocolDialog->deleteLater();
createCertificate();
}
void Kleo::Commands::NewCertificateCommand::Private::createCertificate()
{
Q_ASSERT(protocol != GpgME::UnknownProtocol);
if (protocol == GpgME::OpenPGP) {
auto cmd = new NewOpenPGPCertificateCommand{view(), controller()};
if (parentWidgetOrView() != view()) {
cmd->setParentWidget(parentWidgetOrView());
}
cmd->setParentWId(parentWId());
connect(cmd, &NewOpenPGPCertificateCommand::finished,
q, [this]() { finished(); });
connect(cmd, &NewOpenPGPCertificateCommand::canceled,
q, [this]() { canceled(); });
cmd->start();
} else {
Q_ASSERT(!dialog);
dialog = new NewCertificateWizard;
applyWindowID(dialog);
dialog->setAttribute(Qt::WA_DeleteOnClose);
connect(dialog, &QDialog::accepted, q, [this]() {
slotDialogAccepted();
});
connect(dialog, &QDialog::rejected, q, [this]() {
canceled();
});
dialog->setProtocol(protocol);
dialog->show();
}
dialog->setProtocol(GpgME::CMS);
dialog->show();
}
void NewCertificateCommand::Private::slotDialogAccepted()
......@@ -152,28 +104,14 @@ NewCertificateCommand::NewCertificateCommand(QAbstractItemView *v, KeyListContro
NewCertificateCommand::~NewCertificateCommand() = default;
void NewCertificateCommand::setProtocol(Protocol proto)
{
d->protocol = proto;
}
Protocol NewCertificateCommand::protocol() const
{
return d->protocol;
}
void NewCertificateCommand::doStart()
{
const Kleo::Settings settings{};
const auto cmsAllowed = settings.cmsEnabled() && settings.cmsCertificateCreationAllowed();
if (d->protocol == UnknownProtocol && !cmsAllowed) {
d->protocol = GpgME::OpenPGP;
}
if (d->protocol == UnknownProtocol) {
d->chooseProtocol();
} else {
if (settings.cmsEnabled() && settings.cmsCertificateCreationAllowed()) {
d->createCertificate();
} else {
d->error(i18n("You are not allowed to create S/MIME certificate signing requests."));
d->finished();
}
}
......
......@@ -27,9 +27,6 @@ public:
explicit NewCertificateCommand();
~NewCertificateCommand() override;
void setProtocol(GpgME::Protocol proto);
GpgME::Protocol protocol() const;
private:
void doStart() override;
void doCancel() override;
......
/* -*- mode: c++; c-basic-offset:4 -*-
dialogs/choosecertificateprotocoldialog.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016, 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "choosecertificateprotocoldialog.h"
#include "utils/scrollarea.h"
#include <KLocalizedString>
#include <KSeparator>
#include <QDialogButtonBox>
#include <QGroupBox>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
using namespace Kleo;
class ChooseCertificateProtocolDialog::Private
{
friend class ::Kleo::ChooseCertificateProtocolDialog;
ChooseCertificateProtocolDialog *const q;
struct UI {
QPushButton *openpgpButton = nullptr;
QPushButton *x509Button = nullptr;
QDialogButtonBox *buttonBox = nullptr;
UI(QDialog *parent)
{
auto mainLayout = new QVBoxLayout{parent};
{
auto label = new QLabel{i18n("Choose which type of key pair you want to create."), parent};
label->setWordWrap(true);
mainLayout->addWidget(label);
}
mainLayout->addWidget(new KSeparator{Qt::Horizontal, parent});
auto scrollArea = new ScrollArea{parent};
scrollArea->setFocusPolicy(Qt::NoFocus);
scrollArea->setFrameStyle(QFrame::NoFrame);
scrollArea->setBackgroundRole(parent->backgroundRole());
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
auto scrollAreaLayout = qobject_cast<QBoxLayout *>(scrollArea->widget()->layout());
scrollAreaLayout->setContentsMargins(0, 0, 0, 0);
{
auto group = new QGroupBox{i18n("OpenPGP"), parent};
group->setFlat(true);
auto groupLayout = new QVBoxLayout{group};
const auto infoText = i18n("OpenPGP key pairs are certified by confirming the fingerprint of the public key.");
auto label = new QLabel{infoText, parent};
label->setWordWrap(true);
groupLayout->addWidget(label);
openpgpButton = new QPushButton{parent};
openpgpButton->setText(i18n("Create a Personal OpenPGP Key Pair"));
openpgpButton->setAccessibleDescription(infoText);
groupLayout->addWidget(openpgpButton);
scrollAreaLayout->addWidget(group);
}
scrollAreaLayout->addWidget(new KSeparator{Qt::Horizontal, parent});
{
auto group = new QGroupBox{i18n("X.509"), parent};
group->setFlat(true);
auto groupLayout = new QVBoxLayout{group};
const auto infoText = i18n("X.509 key pairs are certified by a certification authority (CA). The generated request needs to be sent to a CA to finalize creation.");
auto label = new QLabel{infoText, parent};
label->setWordWrap(true);
groupLayout->addWidget(label);
x509Button = new QPushButton{parent};
x509Button->setText(i18n("Create a Personal X.509 Key Pair and Certification Request"));
x509Button->setAccessibleDescription(infoText);
groupLayout->addWidget(x509Button);
scrollAreaLayout->addWidget(group);
}
mainLayout->addWidget(scrollArea);
mainLayout->addStretch(1);
mainLayout->addWidget(new KSeparator{Qt::Horizontal, parent});
buttonBox = new QDialogButtonBox{QDialogButtonBox::Cancel, parent};
buttonBox->button(QDialogButtonBox::Cancel)->setAutoDefault(false);
mainLayout->addWidget(buttonBox);
}
} ui;
public:
explicit Private(ChooseCertificateProtocolDialog *qq)
: q{qq}
, ui{qq}
{
q->setWindowTitle(i18nc("@title:window", "Choose Type of Key Pair"));
connect(ui.openpgpButton, &QAbstractButton::clicked, q, [this]() {
protocol = GpgME::OpenPGP;
q->accept();
});
connect(ui.x509Button, &QAbstractButton::clicked, q, [this]() {
protocol = GpgME::CMS;
q->accept();
});
connect(ui.buttonBox, &QDialogButtonBox::rejected, q, &QDialog::reject);
}
private:
GpgME::Protocol protocol = GpgME::UnknownProtocol;
};
ChooseCertificateProtocolDialog::ChooseCertificateProtocolDialog(QWidget *parent, Qt::WindowFlags f)
: QDialog{parent, f}
, d{new Private{this}}
{
}
ChooseCertificateProtocolDialog::~ChooseCertificateProtocolDialog() = default;
GpgME::Protocol ChooseCertificateProtocolDialog::protocol() const
{
return d->protocol;
}
void ChooseCertificateProtocolDialog::showEvent(QShowEvent *event)
{
// set WA_KeyboardFocusChange attribute to force visual focus of the
// focussed command link button when the dialog is shown (required
// for Breeze style and some other styles)
window()->setAttribute(Qt::WA_KeyboardFocusChange);
QDialog::showEvent(event);
}
/* -*- mode: c++; c-basic-offset:4 -*-
dialogs/choosecertificateprotocoldialog.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016, 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <QDialog>
#include <gpgme++/global.h>
#include <memory>
namespace Kleo
{
class ChooseCertificateProtocolDialog : public QDialog
{
Q_OBJECT
public:
explicit ChooseCertificateProtocolDialog(QWidget *parent = nullptr, Qt::WindowFlags f = {});
~ChooseCertificateProtocolDialog() override;
GpgME::Protocol protocol() const;
protected:
void showEvent(QShowEvent *event) override;
private:
class Private;
const std::unique_ptr<Private> d;
};
}
<!DOCTYPE gui >
<gui name="kleopatra" version="509" >
<gui name="kleopatra" version="510" >
<MenuBar>
<Menu name="file">
<text>&amp;File</text>
<Action name="file_new_certificate"/>
<Action name="file_new_certificate_signing_request"/>
<Separator/>
<Action name="file_lookup_certificates"/>
<Action name="file_import_certificates"/>
......
......@@ -474,7 +474,6 @@ QString KleopatraApplication::newInstance(const QCommandLineParser &parser,
if (settings.cmsEnabled() && settings.cmsCertificateCreationAllowed()) {
auto cmd = new NewCertificateCommand(nullptr);
cmd->setParentWId(parentId);
cmd->setProtocol(protocol);
cmd->start();
} else {
return i18n("You are not allowed to create S/MIME certificate signing requests.");
......
......@@ -52,6 +52,7 @@
#include "commands/revokecertificationcommand.h"
#include "commands/adduseridcommand.h"
#include "commands/newcertificatecommand.h"
#include "commands/newopenpgpcertificatecommand.h"
#include "commands/checksumverifyfilescommand.h"
#include "commands/checksumcreatefilescommand.h"
#include "commands/exportpaperkeycommand.h"
......@@ -356,7 +357,7 @@ void KeyListController::createActions(KActionCollection *coll)
const std::vector<action_data> common_and_openpgp_action_data = {
// File menu
{
"file_new_certificate", i18n("New Key Pair..."), QString(),
"file_new_certificate", i18n("New OpenPGP Key Pair..."), i18n("Create a new OpenPGP certificate"),
"view-certificate-add", nullptr, nullptr, QStringLiteral("Ctrl+N")
},
{
......@@ -468,6 +469,11 @@ void KeyListController::createActions(KActionCollection *coll)
// (come from MainWindow)
};
static const action_data cms_create_csr_action_data = {
"file_new_certificate_signing_request", i18n("New S/MIME Certification Request..."), i18n("Create a new S/MIME certificate signing request (CSR)"),
"view-certificate-add", nullptr, nullptr, {},
};
static const std::vector<action_data> cms_action_data = {
// Certificate menu
{
......@@ -503,7 +509,10 @@ void KeyListController::createActions(KActionCollection *coll)
std::vector<action_data> action_data = common_and_openpgp_action_data;
if (Settings{}.cmsEnabled()) {
if (const Kleo::Settings settings{}; settings.cmsEnabled()) {
if (settings.cmsCertificateCreationAllowed()) {
action_data.push_back(cms_create_csr_action_data);
}
action_data.reserve(action_data.size() + cms_action_data.size());
std::copy(std::begin(cms_action_data), std::end(cms_action_data),
std::back_inserter(action_data));
......@@ -516,7 +525,8 @@ void KeyListController::createActions(KActionCollection *coll)
}
// ### somehow make this better...
registerActionForCommand<NewCertificateCommand>(coll->action(QStringLiteral("file_new_certificate")));
registerActionForCommand<NewOpenPGPCertificateCommand>(coll->action(QStringLiteral("file_new_certificate")));
registerActionForCommand<NewCertificateCommand>(coll->action(QStringLiteral("file_new_certificate_signing_request")));
//---
registerActionForCommand<LookupCertificatesCommand>(coll->action(QStringLiteral("file_lookup_certificates")));
registerActionForCommand<ImportCertificateFromFileCommand>(coll->action(QStringLiteral("file_import_certificates")));
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment