Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
PIM
Kleopatra
Commits
da3aef1b
Commit
da3aef1b
authored
Aug 09, 2022
by
Ingo Klöcker
Browse files
Add support for flagging a user ID as the primary user ID
GnuPG-bug-id: 5934
parent
83baac67
Pipeline
#215245
passed with stage
in 5 minutes
Changes
6
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
CMakeLists.txt
View file @
da3aef1b
...
...
@@ -123,6 +123,7 @@ if (QGpgme_VERSION VERSION_GREATER_EQUAL "1.17.2")
set
(
QGPGME_SUPPORTS_KEY_REVOCATION 1
)
set
(
QGPGME_SUPPORTS_KEY_REFRESH 1
)
set
(
QGPGME_SUPPORTS_SET_FILENAME 1
)
set
(
QGPGME_SUPPORTS_SET_PRIMARY_UID 1
)
endif
()
# Kdepimlibs packages
...
...
config-kleopatra.h.cmake
View file @
da3aef1b
...
...
@@ -56,3 +56,6 @@
/* Defined if QGpgME supports setting the file name of encrypted data */
#cmakedefine QGPGME_SUPPORTS_SET_FILENAME 1
/* Defined if QGpgME supports setting the primary user id of a key */
#cmakedefine QGPGME_SUPPORTS_SET_PRIMARY_UID 1
src/CMakeLists.txt
View file @
da3aef1b
...
...
@@ -201,6 +201,8 @@ set(_kleopatra_SRCS
commands/setinitialpincommand.h
commands/setpivcardapplicationadministrationkeycommand.cpp
commands/setpivcardapplicationadministrationkeycommand.h
commands/setprimaryuseridcommand.cpp
commands/setprimaryuseridcommand.h
commands/signclipboardcommand.cpp
commands/signclipboardcommand.h
commands/signencryptfilescommand.cpp
...
...
src/commands/setprimaryuseridcommand.cpp
0 → 100644
View file @
da3aef1b
/* -*- mode: c++; c-basic-offset:4 -*-
commands/setprimaryuseridcommand.cpp
This file is part of Kleopatra, the KDE keymanager
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
"setprimaryuseridcommand.h"
#include
"command_p.h"
#include
<KLocalizedString>
#include
<QGpgME/Protocol>
#ifdef QGPGME_SUPPORTS_SET_PRIMARY_UID
#include
<QGpgME/SetPrimaryUserIDJob>
#endif
#include
<gpgme++/key.h>
#include
"kleopatra_debug.h"
using
namespace
Kleo
;
using
namespace
Kleo
::
Commands
;
using
namespace
GpgME
;
class
SetPrimaryUserIDCommand
::
Private
:
public
Command
::
Private
{
friend
class
::
Kleo
::
Commands
::
SetPrimaryUserIDCommand
;
SetPrimaryUserIDCommand
*
q_func
()
const
{
return
static_cast
<
SetPrimaryUserIDCommand
*>
(
q
);
}
public:
explicit
Private
(
SetPrimaryUserIDCommand
*
qq
,
const
UserID
&
userId
);
~
Private
()
override
;
void
startJob
();
private:
void
createJob
();
void
slotResult
(
const
Error
&
err
);
void
showErrorDialog
(
const
Error
&
error
);
void
showSuccessDialog
();
private:
GpgME
::
UserID
userId
;
#ifdef QGPGME_SUPPORTS_SET_PRIMARY_UID
QPointer
<
QGpgME
::
SetPrimaryUserIDJob
>
job
;
#endif
};
SetPrimaryUserIDCommand
::
Private
*
SetPrimaryUserIDCommand
::
d_func
()
{
return
static_cast
<
Private
*>
(
d
.
get
());
}
const
SetPrimaryUserIDCommand
::
Private
*
SetPrimaryUserIDCommand
::
d_func
()
const
{
return
static_cast
<
const
Private
*>
(
d
.
get
());
}
#define d d_func()
#define q q_func()
SetPrimaryUserIDCommand
::
Private
::
Private
(
SetPrimaryUserIDCommand
*
qq
,
const
UserID
&
userId
)
:
Command
::
Private
{
qq
}
,
userId
{
userId
}
{
}
SetPrimaryUserIDCommand
::
Private
::~
Private
()
=
default
;
void
Commands
::
SetPrimaryUserIDCommand
::
Private
::
startJob
()
{
#ifdef QGPGME_SUPPORTS_SET_PRIMARY_UID
createJob
();
if
(
!
job
)
{
finished
();
return
;
}
job
->
start
(
userId
);
#else
error
(
i18nc
(
"@info"
,
"The backend does not support this operation."
));
#endif
}
void
SetPrimaryUserIDCommand
::
Private
::
createJob
()
{
#ifdef QGPGME_SUPPORTS_SET_PRIMARY_UID
Q_ASSERT
(
!
job
);
const
auto
backend
=
QGpgME
::
openpgp
();
if
(
!
backend
)
{
return
;
}
const
auto
j
=
backend
->
setPrimaryUserIDJob
();
if
(
!
j
)
{
return
;
}
connect
(
j
,
&
QGpgME
::
Job
::
progress
,
q
,
&
Command
::
progress
);
connect
(
j
,
&
QGpgME
::
SetPrimaryUserIDJob
::
result
,
q
,
[
this
](
const
GpgME
::
Error
&
err
)
{
slotResult
(
err
);
});
job
=
j
;
#endif
}
void
SetPrimaryUserIDCommand
::
Private
::
slotResult
(
const
Error
&
err
)
{
if
(
err
.
isCanceled
())
{
}
else
if
(
err
)
{
showErrorDialog
(
err
);
}
else
{
showSuccessDialog
();
}
finished
();
}
void
SetPrimaryUserIDCommand
::
Private
::
showErrorDialog
(
const
Error
&
err
)
{
error
(
xi18nc
(
"@info"
,
"<para>An error occurred while trying to flag the user ID<nl/><emphasis>%1</emphasis><nl/>as the primary user ID.</para>"
"<para><message>%2</message></para>"
,
QString
::
fromUtf8
(
userId
.
id
()),
QString
::
fromLocal8Bit
(
err
.
asString
())));
}
void
SetPrimaryUserIDCommand
::
Private
::
showSuccessDialog
()
{
success
(
xi18nc
(
"@info"
,
"<para>The user ID<nl/><emphasis>%1</emphasis><nl/>has been flagged successfully as the primary user ID.</para>"
,
QString
::
fromUtf8
(
userId
.
id
())));
}
SetPrimaryUserIDCommand
::
SetPrimaryUserIDCommand
(
const
GpgME
::
UserID
&
userId
)
:
Command
{
new
Private
{
this
,
userId
}}
{
}
SetPrimaryUserIDCommand
::~
SetPrimaryUserIDCommand
()
{
qCDebug
(
KLEOPATRA_LOG
).
nospace
()
<<
this
<<
"::"
<<
__func__
;
}
void
SetPrimaryUserIDCommand
::
doStart
()
{
if
(
d
->
userId
.
isNull
())
{
d
->
finished
();
return
;
}
const
auto
key
=
d
->
userId
.
parent
();
if
(
key
.
protocol
()
!=
GpgME
::
OpenPGP
||
!
key
.
hasSecret
())
{
d
->
finished
();
return
;
}
d
->
startJob
();
}
void
SetPrimaryUserIDCommand
::
doCancel
()
{
qCDebug
(
KLEOPATRA_LOG
).
nospace
()
<<
this
<<
"::"
<<
__func__
;
#ifdef QGPGME_SUPPORTS_SET_PRIMARY_UID
if
(
d
->
job
)
{
d
->
job
->
slotCancel
();
}
#endif
}
#undef d
#undef q
src/commands/setprimaryuseridcommand.h
0 → 100644
View file @
da3aef1b
/* -*- mode: c++; c-basic-offset:4 -*-
commands/setprimaryuseridcommand.h
This file is part of Kleopatra, the KDE keymanager
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
"command.h"
namespace
GpgME
{
class
UserID
;
}
namespace
Kleo
{
namespace
Commands
{
class
SetPrimaryUserIDCommand
:
public
Command
{
Q_OBJECT
public:
explicit
SetPrimaryUserIDCommand
(
const
GpgME
::
UserID
&
userId
);
~
SetPrimaryUserIDCommand
()
override
;
private:
void
doStart
()
override
;
void
doCancel
()
override
;
private:
class
Private
;
inline
Private
*
d_func
();
inline
const
Private
*
d_func
()
const
;
};
}
}
src/dialogs/certificatedetailswidget.cpp
View file @
da3aef1b
...
...
@@ -30,6 +30,7 @@
#include
"commands/refreshcertificatecommand.h"
#include
"commands/revokecertificationcommand.h"
#include
"commands/revokeuseridcommand.h"
#include
"commands/setprimaryuseridcommand.h"
#include
"commands/adduseridcommand.h"
#include
"commands/genrevokecommand.h"
#include
"commands/detailscommand.h"
...
...
@@ -247,6 +248,7 @@ public:
void
webOfTrustClicked
();
void
exportClicked
();
void
addUserID
();
void
setPrimaryUserID
(
const
GpgME
::
UserID
&
uid
=
{});
void
changePassphrase
();
void
changeExpiration
();
void
keysMayHaveChanged
();
...
...
@@ -290,6 +292,7 @@ private:
QLabel
*
userIDTableLabel
=
nullptr
;
NavigatableTreeWidget
*
userIDTable
=
nullptr
;
QPushButton
*
addUserIDBtn
=
nullptr
;
QPushButton
*
setPrimaryUserIDBtn
=
nullptr
;
QPushButton
*
certifyBtn
=
nullptr
;
QPushButton
*
revokeCertificationsBtn
=
nullptr
;
QPushButton
*
revokeUserIDBtn
=
nullptr
;
...
...
@@ -349,6 +352,10 @@ private:
addUserIDBtn
=
new
QPushButton
(
i18nc
(
"@action:button"
,
"Add User ID"
),
parent
);
buttonRow
->
addWidget
(
addUserIDBtn
);
setPrimaryUserIDBtn
=
new
QPushButton
{
i18nc
(
"@action:button"
,
"Flag as Primary"
),
parent
};
setPrimaryUserIDBtn
->
setToolTip
(
i18nc
(
"@info:tooltip"
,
"Flag the selected user ID as the primary user ID of this key."
));
buttonRow
->
addWidget
(
setPrimaryUserIDBtn
);
certifyBtn
=
new
QPushButton
(
i18nc
(
"@action:button"
,
"Certify User IDs"
),
parent
);
buttonRow
->
addWidget
(
certifyBtn
);
...
...
@@ -509,6 +516,8 @@ CertificateDetailsWidget::Private::Private(CertificateDetailsWidget *qq)
q
,
[
this
]()
{
updateUserIDActions
();
});
connect
(
ui
.
addUserIDBtn
,
&
QPushButton
::
clicked
,
q
,
[
this
]()
{
addUserID
();
});
connect
(
ui
.
setPrimaryUserIDBtn
,
&
QPushButton
::
clicked
,
q
,
[
this
]()
{
setPrimaryUserID
();
});
connect
(
ui
.
revokeUserIDBtn
,
&
QPushButton
::
clicked
,
q
,
[
this
]()
{
revokeSelectedUserID
();
});
connect
(
ui
.
changePassphraseBtn
,
&
QPushButton
::
clicked
,
...
...
@@ -551,6 +560,11 @@ void CertificateDetailsWidget::Private::setupCommonProperties()
// update visibility of UI elements
ui
.
userIDs
->
setVisible
(
isOpenPGP
);
ui
.
addUserIDBtn
->
setVisible
(
isOwnKey
);
#ifdef QGPGME_SUPPORTS_SET_PRIMARY_UID
ui
.
setPrimaryUserIDBtn
->
setVisible
(
isOwnKey
);
#else
ui
.
setPrimaryUserIDBtn
->
setVisible
(
false
);
#endif
// ui.certifyBtn->setVisible(true); // always visible (for OpenPGP keys)
// ui.webOfTrustBtn->setVisible(true); // always visible (for OpenPGP keys)
ui
.
revokeCertificationsBtn
->
setVisible
(
Kleo
::
Commands
::
RevokeCertificationCommand
::
isSupported
());
...
...
@@ -585,6 +599,7 @@ void CertificateDetailsWidget::Private::setupCommonProperties()
// update availability of buttons
const
auto
userCanSignUserIDs
=
userHasCertificationKey
();
ui
.
addUserIDBtn
->
setEnabled
(
canBeUsedForSecretKeyOperations
(
key
));
ui
.
setPrimaryUserIDBtn
->
setEnabled
(
false
);
// requires a selected user ID
ui
.
certifyBtn
->
setEnabled
(
userCanSignUserIDs
);
ui
.
revokeCertificationsBtn
->
setEnabled
(
userCanSignUserIDs
);
ui
.
revokeUserIDBtn
->
setEnabled
(
false
);
// requires a selected user ID
...
...
@@ -606,7 +621,13 @@ void CertificateDetailsWidget::Private::setupCommonProperties()
void
CertificateDetailsWidget
::
Private
::
updateUserIDActions
()
{
const
auto
userIDs
=
selectedUserIDs
(
ui
.
userIDTable
);
ui
.
revokeUserIDBtn
->
setEnabled
((
userIDs
.
size
()
==
1
)
&&
canCreateCertifications
(
key
)
&&
canRevokeUserID
(
userIDs
.
front
()));
const
auto
singleUserID
=
userIDs
.
size
()
==
1
?
userIDs
.
front
()
:
GpgME
::
UserID
{};
const
bool
isPrimaryUserID
=
!
singleUserID
.
isNull
()
&&
(
ui
.
userIDTable
->
selectedItems
().
front
()
==
ui
.
userIDTable
->
topLevelItem
(
0
));
ui
.
setPrimaryUserIDBtn
->
setEnabled
(
!
singleUserID
.
isNull
()
//
&&
!
isPrimaryUserID
//
&&
!
Kleo
::
isRevokedOrExpired
(
singleUserID
)
//
&&
canBeUsedForSecretKeyOperations
(
key
));
ui
.
revokeUserIDBtn
->
setEnabled
(
!
singleUserID
.
isNull
()
&&
canCreateCertifications
(
key
)
&&
canRevokeUserID
(
singleUserID
));
}
void
CertificateDetailsWidget
::
Private
::
setUpUserIDTable
()
...
...
@@ -850,6 +871,28 @@ void CertificateDetailsWidget::Private::addUserID()
cmd
->
start
();
}
void
CertificateDetailsWidget
::
Private
::
setPrimaryUserID
(
const
GpgME
::
UserID
&
uid
)
{
auto
userId
=
uid
;
if
(
userId
.
isNull
())
{
const
auto
userIDs
=
selectedUserIDs
(
ui
.
userIDTable
);
if
(
userIDs
.
size
()
!=
1
)
{
return
;
}
userId
=
userIDs
.
front
();
}
auto
cmd
=
new
Kleo
::
Commands
::
SetPrimaryUserIDCommand
(
userId
);
QObject
::
connect
(
cmd
,
&
Kleo
::
Commands
::
SetPrimaryUserIDCommand
::
finished
,
q
,
[
this
]()
{
ui
.
userIDTable
->
setEnabled
(
true
);
// the Flag As Primary button will be updated by the key update
updateKey
();
});
ui
.
userIDTable
->
setEnabled
(
false
);
ui
.
setPrimaryUserIDBtn
->
setEnabled
(
false
);
cmd
->
start
();
}
namespace
{
void
ensureThatKeyDetailsAreLoaded
(
GpgME
::
Key
&
key
)
...
...
@@ -880,9 +923,25 @@ void CertificateDetailsWidget::Private::userIDTableContextMenuRequested(const QP
{
const
auto
userIDs
=
selectedUserIDs
(
ui
.
userIDTable
);
const
auto
singleUserID
=
(
userIDs
.
size
()
==
1
)
?
userIDs
.
front
()
:
GpgME
::
UserID
{};
#ifdef QGPGME_SUPPORTS_SET_PRIMARY_UID
const
bool
isPrimaryUserID
=
!
singleUserID
.
isNull
()
&&
(
ui
.
userIDTable
->
selectedItems
().
front
()
==
ui
.
userIDTable
->
topLevelItem
(
0
));
#endif
const
bool
canSignUserIDs
=
userHasCertificationKey
();
auto
menu
=
new
QMenu
(
q
);
#ifdef QGPGME_SUPPORTS_SET_PRIMARY_UID
if
(
key
.
hasSecret
())
{
auto
action
=
menu
->
addAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"favorite"
)),
i18nc
(
"@action:inmenu"
,
"Flag as Primary User ID"
),
q
,
[
this
,
singleUserID
]()
{
setPrimaryUserID
(
singleUserID
);
});
action
->
setEnabled
(
!
singleUserID
.
isNull
()
//
&&
!
isPrimaryUserID
//
&&
!
Kleo
::
isRevokedOrExpired
(
singleUserID
)
//
&&
canBeUsedForSecretKeyOperations
(
key
));
}
#endif
{
const
auto
actionText
=
userIDs
.
empty
()
?
i18nc
(
"@action:inmenu"
,
"Certify User IDs..."
)
:
i18ncp
(
"@action:inmenu"
,
"Certify User ID..."
,
"Certify User IDs..."
,
userIDs
.
size
());
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment