1
0
mirror of https://github.com/QRouland/UTPass.git synced 2025-01-24 07:36:39 +00:00

Add docsting for pass plugin

This commit is contained in:
Quentin Rouland 2025-01-15 23:40:35 +01:00
parent e589abd10c
commit beaad58af2
11 changed files with 510 additions and 122 deletions

View File

@ -53,7 +53,8 @@ Gpg::Gpg(QObject* windows)
qDebug() << "GNUPG Home is :" << engineInfo(OpenPGP).homeDirectory(); qDebug() << "GNUPG Home is :" << engineInfo(OpenPGP).homeDirectory();
} }
Gpg::~Gpg(){ Gpg::~Gpg()
{
delete this->m_passphrase_provider; delete this->m_passphrase_provider;
} }
@ -141,7 +142,7 @@ Error Gpg::decrypt(QByteArray cipher_text)
ctx->setPinentryMode(Context::PinentryLoopback); ctx->setPinentryMode(Context::PinentryLoopback);
QObject::connect(job, &DecryptJob::result, QObject::connect(job, &DecryptJob::result,
this, &Gpg::decryptResultSlot); this, &Gpg::decryptResultSlot);
return job->start(cipher_text); return job->start(cipher_text);
} }
@ -161,7 +162,8 @@ Error Gpg::decryptFromFile(QString path)
void Gpg::decryptResultSlot(const GpgME::DecryptionResult &result, const QByteArray &plainText, const QString &auditLogAsHtml, const GpgME::Error &auditLogError) void Gpg::decryptResultSlot(const GpgME::DecryptionResult &result, const QByteArray &plainText,
const QString &auditLogAsHtml, const GpgME::Error &auditLogError)
{ {
if (result.error()) { if (result.error()) {
qWarning() << "Something gone wrong on decrypt"; qWarning() << "Something gone wrong on decrypt";
@ -210,13 +212,13 @@ void Gpg::decryptResultSlot(const GpgME::DecryptionResult &result, const QByteAr
Error Gpg::getAllKeys ( bool remote, const bool include_sigs, Error Gpg::getAllKeys ( bool remote, const bool include_sigs,
bool validate ) bool validate )
{ {
return getKeys(QString(""), remote, include_sigs, validate); return getKeys(QString(""), remote, include_sigs, validate);
} }
Error Gpg::getKeys(QString pattern_uid, bool remote, bool include_sigs, Error Gpg::getKeys(QString pattern_uid, bool remote, bool include_sigs,
bool validate) bool validate)
{ {
qDebug() << "Getting the keys " << pattern_uid; qDebug() << "Getting the keys " << pattern_uid;
auto job = openpgp()->keyListJob(remote, include_sigs, validate); auto job = openpgp()->keyListJob(remote, include_sigs, validate);
@ -227,7 +229,8 @@ Error Gpg::getKeys(QString pattern_uid, bool remote, bool include_sigs,
return job->start(QStringList() << pattern_uid, false); return job->start(QStringList() << pattern_uid, false);
} }
void Gpg::getKeysJobResultSlot(const GpgME::KeyListResult &result, const std::vector<GpgME::Key> &keys, const QString &auditLogAsHtml , const GpgME::Error &auditLogError) void Gpg::getKeysJobResultSlot(const GpgME::KeyListResult &result, const std::vector<GpgME::Key> &keys,
const QString &auditLogAsHtml, const GpgME::Error &auditLogError)
{ {
if (result.error()) { if (result.error()) {
qWarning() << "Something gone wrong on decrypt"; qWarning() << "Something gone wrong on decrypt";
@ -258,7 +261,8 @@ Error Gpg::importKeysFromFile(QString path)
return job->start(data); return job->start(data);
} }
void Gpg::importKeysFromFileSlot(const GpgME::ImportResult &result, const QString &auditLogAsHtml, const GpgME::Error &auditLogError) void Gpg::importKeysFromFileSlot(const GpgME::ImportResult &result, const QString &auditLogAsHtml,
const GpgME::Error &auditLogError)
{ {
qDebug() << "numImported" << result.numImported(); qDebug() << "numImported" << result.numImported();
qDebug() << "numSecretKeysImported" << result.numSecretKeysImported(); qDebug() << "numSecretKeysImported" << result.numSecretKeysImported();
@ -285,7 +289,8 @@ Error Gpg::deleteKey(const Key key)
return openpgp()->deleteJob()->start(key, true); return openpgp()->deleteJob()->start(key, true);
} }
void Gpg::deleteKeySlot(const GpgME::Error &error, const QString &auditLogAsHtml, const GpgME::Error &auditLogError) { void Gpg::deleteKeySlot(const GpgME::Error &error, const QString &auditLogAsHtml, const GpgME::Error &auditLogError)
{
if (error) { if (error) {
qWarning() << "Something gone wrong on decrypt"; qWarning() << "Something gone wrong on decrypt";

View File

@ -22,31 +22,67 @@
using namespace GpgME; using namespace GpgME;
using namespace QGpgME; using namespace QGpgME;
/**
* @class Gpg
* @brief A class for managing GPG key operations such as key import, decryption, and deletion.
*
* This class integrates with the GPGME (GnuPG Made Easy) library to provide functionalities
* for interacting with GPG keys, including decrypting messages, importing keys from files,
* listing keys, and deleting keys. The class also provides slots for handling results
* of asynchronous GPG operations and communicates with the user via signals.
*/
class Gpg: public QObject class Gpg: public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(UTPassphraseProvider* passphrase_provider READ passphrase_provider MEMBER m_passphrase_provider ) Q_PROPERTY(UTPassphraseProvider* passphrase_provider READ passphrase_provider MEMBER m_passphrase_provider )
private slots: private slots:
/**
* @brief Slot to handle the result of a decryption operation.
* @param result The result of the decryption operation.
* @param plain_text The decrypted text.
* @param auditLogAsHtml The HTML formatted audit log for the operation.
* @param auditLogError The error associated with the audit log, if any.
*/
void decryptResultSlot( void decryptResultSlot(
const DecryptionResult &result, const DecryptionResult &result,
const QByteArray &plain_text, const QByteArray &plain_text,
const QString &auditLogAsHtml, const QString &auditLogAsHtml,
const Error &auditLogError const Error &auditLogError
); );
/**
* @brief Slot to handle the result of a key retrieval operation.
* @param result The result of the key retrieval operation.
* @param keys A vector of keys retrieved.
* @param auditLogAsHtml The HTML formatted audit log for the operation, if any.
* @param auditLogError The error associated with the audit log, if any.
*/
void getKeysJobResultSlot( void getKeysJobResultSlot(
const GpgME::KeyListResult &result, const GpgME::KeyListResult &result,
const std::vector<GpgME::Key> &keys, const std::vector<GpgME::Key> &keys,
const QString &auditLogAsHtml , const QString &auditLogAsHtml,
const GpgME::Error &auditLogError const GpgME::Error &auditLogError
); );
/**
* @brief Slot to handle the result of a key import operation.
* @param result The result of the import operation.
* @param auditLogAsHtml The HTML formatted audit log for the operation, if any.
* @param auditLogError The error associated with the audit log, if any.
*/
void importKeysFromFileSlot( void importKeysFromFileSlot(
const GpgME::ImportResult &result, const GpgME::ImportResult &result,
const QString &auditLogAsHtml, const QString &auditLogAsHtml,
const GpgME::Error &auditLogError const GpgME::Error &auditLogError
); );
/**
* @brief Slot to handle the result of a key deletion operation.
* @param result The error result of the deletion operation.
* @param auditLogAsHtml The HTML formatted audit log for the operation, if any.
* @param auditLogError The error associated with the audit log, if any.
*/
void deleteKeySlot( void deleteKeySlot(
const GpgME::Error &result, const GpgME::Error &result,
const QString &auditLogAsHtml, const QString &auditLogAsHtml,
@ -54,42 +90,139 @@ private slots:
); );
signals: signals:
/**
* @brief Signal emitted when keys are imported from a file.
* @param err The error that occurred during the import operation, if any.
*/
void importKeysFromFileResult(Error err); void importKeysFromFileResult(Error err);
/**
* @brief Signal emitted when keys are retrieved.
* @param err The error that occurred during the retrieval operation, if any.
* @param keys A vector of keys retrieved.
*/
void getKeysResult(Error err, std::vector<GpgME::Key> keys); void getKeysResult(Error err, std::vector<GpgME::Key> keys);
/**
* @brief Signal emitted when a key is deleted.
* @param err The error that occurred during the deletion operation, if any.
*/
void deleteKeyResult(Error err); void deleteKeyResult(Error err);
/**
* @brief Signal emitted when a decryption operation completes.
* @param err The error that occurred during decryption, if any.
* @param plain_text The decrypted message.
*/
void decryptResult(Error err, QString plain_text); void decryptResult(Error err, QString plain_text);
private: private:
UTPassphraseProvider* m_passphrase_provider; UTPassphraseProvider *m_passphrase_provider; /**< The passphrase provider used for authentication. */
/**
* @brief Finds the path of a command in the system's environment.
* @param command The name of the command to find.
* @return The full path to the command.
*/
QString findCommandPath(const QString &command); QString findCommandPath(const QString &command);
/**
* @brief Initializes the GPG home directory.
* @return The path to the GPG home directory.
*/
QString initGpgHome(); QString initGpgHome();
/**
* @brief Initializes the GPG executable path.
* @return The path to the GPG executable.
*/
QString initGpgExec(); QString initGpgExec();
/**
* @brief Initializes the GPG configuration.
*/
void initGpgConfig(); void initGpgConfig();
Error getKey(QString uid, bool remote = false, bool include_sigs = false,
bool validate = false); /**
* @brief Retrieves a GPG key by UID.
* @param uid The UID of the key to retrieve.
* @param remote Whether to fetch the key from a remote keyserver (default: false).
* @param include_sigs Whether to include signatures (default: false).
* @param validate Whether to validate the key (default: false).
* @return The error result of the operation.
*/
Error getKey(QString uid, bool remote = false, bool include_sigs = false, bool validate = false);
public: public:
/**
* @brief Constructs a Gpg object and initializes necessary resources.
* @param window The window object for interacting with the user interface.
*/
Gpg(QObject* window); Gpg(QObject* window);
/**
* @brief Destroys the Gpg object and cleans up resources.
*/
~Gpg(); ~Gpg();
UTPassphraseProvider* passphrase_provider() const /**
* @brief Gets the passphrase provider used for GPG authentication.
* @return The passphrase provider.
*/
UTPassphraseProvider *passphrase_provider() const
{ {
return m_passphrase_provider; return m_passphrase_provider;
} }
Error importKeysFromFile(const QString path);
Error getKeys(const QString pattern_uid, const bool remote = false,
const bool include_sigs = false,
const bool validate = false);
Error getAllKeys (bool remote = false, bool include_sigs = {}, bool
validate = false);
Error deleteKey(const Key key);
Error decrypt(const QByteArray cipher_text);
Error decryptFromFile(const QString path);
//Error encrypt (QString str, QString uid, bool ascii_armor = true,
// bool text_mode = true);
/**
* @brief Imports GPG keys from a file.
* @param path The path to the file containing the keys.
* @return The error result of the import operation.
*/
Error importKeysFromFile(const QString path);
/**
* @brief Retrieves keys matching the provided UID pattern.
* @param pattern_uid The UID pattern to search for.
* @param remote Whether to fetch the key from a remote keyserver (default: false).
* @param include_sigs Whether to include signatures (default: false).
* @param validate Whether to validate the key (default: false).
* @return The error result of the operation.
*/
Error getKeys(const QString pattern_uid, bool remote = false, bool include_sigs = false, bool validate = false);
/**
* @brief Retrieves all keys from the GPG keyring.
* @param remote Whether to fetch the keys from a remote keyserver (default: false).
* @param include_sigs Whether to include signatures (default: false).
* @param validate Whether to validate the keys (default: false).
* @return The error result of the operation.
*/
Error getAllKeys(bool remote = false, bool include_sigs = false, bool validate = false);
/**
* @brief Deletes a specified GPG key.
* @param key The key to delete.
* @return The error result of the deletion operation.
*/
Error deleteKey(const Key key);
/**
* @brief Decrypts a given ciphertext.
* @param cipher_text The ciphertext to decrypt.
* @return The error result of the decryption operation.
*/
Error decrypt(const QByteArray cipher_text);
/**
* @brief Decrypts the contents of a file.
* @param path The path to the file to decrypt.
* @return The error result of the decryption operation.
*/
Error decryptFromFile(const QString path);
// Error encrypt (QString str, QString uid, bool ascii_armor = true, bool text_mode = true);
}; };
#endif #endif

View File

@ -10,7 +10,7 @@
Pass::Pass(): Pass::Pass():
m_password_store (QStandardPaths::writableLocation( m_password_store (QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation).append("/.password-store")), QStandardPaths::AppDataLocation).append("/.password-store")),
m_sem(std::unique_ptr<QSemaphore>(new QSemaphore(1))), m_sem(std::unique_ptr<QSemaphore>(new QSemaphore(1))),
m_show_filename(QString()) m_show_filename(QString())
{} {}
@ -23,7 +23,8 @@ void Pass::initialize(QObject *window)
this->m_gpg = std::unique_ptr<Gpg>(new Gpg(window)); this->m_gpg = std::unique_ptr<Gpg>(new Gpg(window));
QObject::connect(this, &Pass::responsePassphraseDialogPropagate, this->m_gpg->passphrase_provider(), &UTPassphraseProvider::handleResponse); QObject::connect(this, &Pass::responsePassphraseDialogPropagate, this->m_gpg->passphrase_provider(),
&UTPassphraseProvider::handleResponse);
QObject::connect(this->m_gpg.get(), &Gpg::importKeysFromFileResult, this, &Pass::importGPGKeyResult); QObject::connect(this->m_gpg.get(), &Gpg::importKeysFromFileResult, this, &Pass::importGPGKeyResult);
QObject::connect(this->m_gpg.get(), &Gpg::getKeysResult, this, &Pass::getAllGPGKeysResult); QObject::connect(this->m_gpg.get(), &Gpg::getKeysResult, this, &Pass::getAllGPGKeysResult);
QObject::connect(this->m_gpg.get(), &Gpg::deleteKeyResult, this, &Pass::deleteGPGKeyResult); QObject::connect(this->m_gpg.get(), &Gpg::deleteKeyResult, this, &Pass::deleteGPGKeyResult);
@ -38,7 +39,9 @@ void Pass::initialize(QObject *window)
bool Pass::show(QUrl url) bool Pass::show(QUrl url)
{ {
if (!this->m_sem->tryAcquire(1, 500)){ return false; } if (!this->m_sem->tryAcquire(1, 500)) {
return false;
}
auto path = url.toLocalFile(); auto path = url.toLocalFile();
qInfo() << "Staring decrypting job for " << path; qInfo() << "Staring decrypting job for " << path;
QFileInfo file_info(path); QFileInfo file_info(path);
@ -46,7 +49,8 @@ bool Pass::show(QUrl url)
return this->m_gpg->decryptFromFile(path); return this->m_gpg->decryptFromFile(path);
} }
void Pass::showResult(Error err, QString plain_text) { void Pass::showResult(Error err, QString plain_text)
{
qInfo() << "Result for decrypting job"; qInfo() << "Result for decrypting job";
if (err) { if (err) {
qInfo() << "Decrypt Failed"; qInfo() << "Decrypt Failed";
@ -61,13 +65,16 @@ void Pass::showResult(Error err, QString plain_text) {
bool Pass::deleteGPGKey(Key key) bool Pass::deleteGPGKey(Key key)
{ {
if (!this->m_sem->tryAcquire(1, 500)){ return false;} if (!this->m_sem->tryAcquire(1, 500)) {
return false;
}
qInfo() << "Deleting Key"; qInfo() << "Deleting Key";
return this->m_gpg->deleteKey(key); return this->m_gpg->deleteKey(key);
} }
void Pass::deleteGPGKeyResult(Error err) { void Pass::deleteGPGKeyResult(Error err)
if(err) { {
if (err) {
emit deleteGPGKeyFailed(err.asString()); emit deleteGPGKeyFailed(err.asString());
} else { } else {
emit deleteGPGKeySucceed(); emit deleteGPGKeySucceed();
@ -77,13 +84,16 @@ void Pass::deleteGPGKeyResult(Error err) {
bool Pass::importGPGKey(QUrl url) bool Pass::importGPGKey(QUrl url)
{ {
if (!this->m_sem->tryAcquire(1, 500)){ return false;} if (!this->m_sem->tryAcquire(1, 500)) {
return false;
}
qInfo() << "Importing Key from " << url; qInfo() << "Importing Key from " << url;
return this->m_gpg->importKeysFromFile(url.toLocalFile()); return this->m_gpg->importKeysFromFile(url.toLocalFile());
} }
void Pass::importGPGKeyResult(Error err) { void Pass::importGPGKeyResult(Error err)
if(err) { {
if (err) {
emit importGPGKeyFailed(err.asString()); emit importGPGKeyFailed(err.asString());
} else { } else {
emit importGPGKeySucceed(); emit importGPGKeySucceed();
@ -93,13 +103,16 @@ void Pass::importGPGKeyResult(Error err) {
bool Pass::getAllGPGKeys() bool Pass::getAllGPGKeys()
{ {
if (!this->m_sem->tryAcquire(1, 500)){ return false; } if (!this->m_sem->tryAcquire(1, 500)) {
return false;
}
qInfo() << "Getting all key form gpg "; qInfo() << "Getting all key form gpg ";
return this->m_gpg->getAllKeys(); return this->m_gpg->getAllKeys();
} }
void Pass::getAllGPGKeysResult(Error err, std::vector<GpgME::Key> keys_info) { void Pass::getAllGPGKeysResult(Error err, std::vector<GpgME::Key> keys_info)
if(err) { {
if (err) {
emit getAllGPGKeysFailed(err.asString()); emit getAllGPGKeysFailed(err.asString());
} else { } else {
emit getAllGPGKeysSucceed(QVariant::fromValue(PassKeyModel::keysToPassKey(keys_info))); emit getAllGPGKeysSucceed(QVariant::fromValue(PassKeyModel::keysToPassKey(keys_info)));
@ -107,7 +120,8 @@ void Pass::getAllGPGKeysResult(Error err, std::vector<GpgME::Key> keys_info) {
this->m_sem->release(1); this->m_sem->release(1);
} }
void Pass::responsePassphraseDialog(bool cancel, QString passphrase) { void Pass::responsePassphraseDialog(bool cancel, QString passphrase)
{
qDebug() << "responsePassphraseDialog"; qDebug() << "responsePassphraseDialog";
emit responsePassphraseDialogPropagate(cancel, passphrase); emit responsePassphraseDialogPropagate(cancel, passphrase);
} }

View File

@ -10,59 +10,174 @@
using namespace GpgME; using namespace GpgME;
/**
* @class Pass
* @brief A class for managing password storage using GPG encryption.
*
* This class provides functionalities for interacting with password storage, including
* storing, showing, importing, and deleting passwords securely using GPG encryption.
* It communicates asynchronously with GPG operations, using signals and slots to propagate results.
* The class interacts with the `Gpg` class to perform GPG key operations and provides an interface
* for the user to manage the passwords.
*/
class Pass : public QObject class Pass : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString password_store READ password_store MEMBER m_password_store CONSTANT) Q_PROPERTY(QString password_store READ password_store MEMBER m_password_store CONSTANT)
private slots: private slots:
/**
* @brief Slot to handle the result of a GPG decryption operation (to show password).
* @param err The error that occurred during the operation.
* @param plain_text The decrypted plain text (password).
*/
void showResult(Error err, QString plain_text); void showResult(Error err, QString plain_text);
/**
* @brief Slot to handle the result of a GPG key deletion operation.
* @param err The error that occurred during the operation.
*/
void deleteGPGKeyResult(Error err); void deleteGPGKeyResult(Error err);
/**
* @brief Slot to handle the result of a GPG key import operation.
* @param err The error that occurred during the operation.
*/
void importGPGKeyResult(Error err); void importGPGKeyResult(Error err);
void getAllGPGKeysResult(Error err, std::vector< GpgME::Key > keys_info);
/**
* @brief Slot to handle the result of retrieving all GPG keys.
* @param err The error that occurred during the operation.
* @param keys_info The list of GPG keys retrieved.
*/
void getAllGPGKeysResult(Error err, std::vector<GpgME::Key> keys_info);
signals: signals:
// GPG // GPG-related signals
/**
* @brief Emitted when a GPG key is successfully deleted.
*/
void deleteGPGKeySucceed(); void deleteGPGKeySucceed();
/**
* @brief Emitted when a GPG key deletion fails.
* @param message The error message describing the failure.
*/
void deleteGPGKeyFailed(QString message); void deleteGPGKeyFailed(QString message);
/**
* @brief Emitted when a GPG key is successfully imported.
*/
void importGPGKeySucceed(); void importGPGKeySucceed();
/**
* @brief Emitted when a GPG key import fails.
* @param message The error message describing the failure.
*/
void importGPGKeyFailed(QString message); void importGPGKeyFailed(QString message);
/**
* @brief Emitted when all GPG keys are successfully retrieved.
* @param keys_info The list of retrieved keys.
*/
void getAllGPGKeysSucceed(QVariant keys_info); void getAllGPGKeysSucceed(QVariant keys_info);
/**
* @brief Emitted when retrieving GPG keys fails.
* @param message The error message describing the failure.
*/
void getAllGPGKeysFailed(QString message); void getAllGPGKeysFailed(QString message);
// Pass-related signals
/**
* @brief Emitted to propagate passphrase dialog response.
* @param cancel Whether the dialog was cancelled.
* @param passphrase The passphrase entered, if not cancelled.
*/
void responsePassphraseDialogPropagate(bool cancel, QString passphrase); void responsePassphraseDialogPropagate(bool cancel, QString passphrase);
// pass show /**
* @brief Emitted when a password is successfully retrieved and shown.
* @param name The name of the password (e.g., service).
* @param text The password text.
*/
void showSucceed(QString name, QString text); void showSucceed(QString name, QString text);
/**
* @brief Emitted when showing a password fails.
* @param message The error message describing the failure.
*/
void showFailed(QString message); void showFailed(QString message);
private: private:
QString m_password_store; QString m_password_store; /**< The path to the password store. */
std::unique_ptr<Gpg> m_gpg; std::unique_ptr<Gpg> m_gpg; /**< The GPG instance used for encryption/decryption. */
std::unique_ptr<QSemaphore> m_sem; std::unique_ptr<QSemaphore> m_sem; /**< Semaphore for managing concurrent operations. */
QString m_show_filename; QString m_show_filename; /**< The filename associated with the password to show. */
public: public:
/**
* @brief Constructs the Pass object and initializes necessary resources.
*/
Pass(); Pass();
/**
* @brief Destructor for cleaning up resources used by the Pass object.
*/
~Pass() override = default; ~Pass() override = default;
/**
* @brief Gets the path to the password store.
* @return The path to the password store.
*/
QString password_store() const QString password_store() const
{ {
return m_password_store; return m_password_store;
} };
/**
* @brief Initializes the Pass object with the given window.
* @param window The QObject window to interact with.
*/
Q_INVOKABLE void initialize(QObject *window); Q_INVOKABLE void initialize(QObject *window);
// GPG // GPG-related methods
/**
* @brief Deletes the specified GPG key.
* @param key The GPG key to delete.
* @return True if the operation was successful, false otherwise.
*/
Q_INVOKABLE bool deleteGPGKey(Key key); Q_INVOKABLE bool deleteGPGKey(Key key);
/**
* @brief Imports a GPG key from the given URL.
* @param url The URL to import the GPG key from.
* @return True if the operation was successful, false otherwise.
*/
Q_INVOKABLE bool importGPGKey(QUrl url); Q_INVOKABLE bool importGPGKey(QUrl url);
/**
* @brief Retrieves all GPG keys.
* @return True if the operation was successful, false otherwise.
*/
Q_INVOKABLE bool getAllGPGKeys(); Q_INVOKABLE bool getAllGPGKeys();
/**
* @brief Return the response from the passphrase dialog.
* @param cancel Whether the dialog was cancelled.
* @param passphrase The passphrase entered, if not cancelled.
*/
Q_INVOKABLE void responsePassphraseDialog(bool cancel, QString passphrase); Q_INVOKABLE void responsePassphraseDialog(bool cancel, QString passphrase);
// PASS // Password store-related methods
Q_INVOKABLE bool show(QUrl url);
/**
* @brief Shows the password associated with the specified URL.
* @param url The URL pointing to the password store entry.
* @return True if the operation was successful, false otherwise.
*/
Q_INVOKABLE bool show(QUrl url);
}; };
#endif #endif

View File

@ -6,6 +6,14 @@
using namespace GpgME; using namespace GpgME;
/**
* @class UserIdModel
* @brief A model representing a user ID associated with a GPG key.
*
* This class encapsulates the user ID information (UID) for a GPG key, providing access
* to the UID's identifier, name, and email. It is used as a model for user IDs in the
* `PassKeyModel` class.
*/
class UserIdModel : public QObject class UserIdModel : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -14,26 +22,51 @@ class UserIdModel : public QObject
Q_PROPERTY(QString email READ email CONSTANT) Q_PROPERTY(QString email READ email CONSTANT)
private: private:
UserID m_user_id; UserID m_user_id; /**< The GPG UserID associated with the model. */
public:
UserIdModel(UserID key):
m_user_id(key)
{};
public:
/**
* @brief Constructs a UserIdModel for the given UserID.
* @param key The GPG UserID to model.
*/
UserIdModel(UserID key) : m_user_id(key) {}
/**
* @brief Gets the unique identifier (UID) for this user ID.
* @return The UID as a QString.
*/
QString uid() const QString uid() const
{ {
return QString::fromUtf8(m_user_id.id()); return QString::fromUtf8(m_user_id.id());
}; };
/**
* @brief Gets the name associated with this user ID.
* @return The name as a QString.
*/
QString name() const QString name() const
{ {
return QString::fromUtf8(m_user_id.name()); return QString::fromUtf8(m_user_id.name());
}; };
/**
* @brief Gets the email associated with this user ID.
* @return The email as a QString.
*/
QString email() const QString email() const
{ {
return QString::fromUtf8(m_user_id.email()); return QString::fromUtf8(m_user_id.email());
}; };
}; };
/**
* @class PassKeyModel
* @brief A model representing a GPG key.
*
* This class encapsulates the properties of a GPG key, including its key ID, associated
* user IDs, secret key status, and expiration status. It is used as a model for managing
* GPG keys within an application, providing access to the key's data and its associated user IDs.
*/
class PassKeyModel : public QObject class PassKeyModel : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -43,12 +76,21 @@ class PassKeyModel : public QObject
Q_PROPERTY(bool isSecret READ isSecret CONSTANT) Q_PROPERTY(bool isSecret READ isSecret CONSTANT)
Q_PROPERTY(bool isExpired READ isExpired CONSTANT) Q_PROPERTY(bool isExpired READ isExpired CONSTANT)
Key m_key; private:
public: Key m_key; /**< The GPG key associated with the model. */
PassKeyModel(Key key):
m_key(key)
{};
public:
/**
* @brief Constructs a PassKeyModel for the given GPG key.
* @param key The GPG key to model.
*/
PassKeyModel(Key key) : m_key(key) {}
/**
* @brief Converts a vector of GPG keys into a list of PassKeyModel objects.
* @param keys The vector of GPG keys to convert.
* @return A QList of PassKeyModel objects representing the keys.
*/
static QList<QObject *> keysToPassKey(std::vector<Key> keys) static QList<QObject *> keysToPassKey(std::vector<Key> keys)
{ {
QList<QObject *> ret; QList<QObject *> ret;
@ -58,16 +100,28 @@ public:
return ret; return ret;
}; };
/**
* @brief Gets the GPG key associated with this model.
* @return The GPG key.
*/
Key key() const Key key() const
{ {
return m_key; return m_key;
}; };
/**
* @brief Gets the unique identifier (UID) for this GPG key.
* @return The UID as a QString.
*/
QString uid() const QString uid() const
{ {
return QString::fromUtf8(m_key.keyID()); return QString::fromUtf8(m_key.keyID());
}; };
/**
* @brief Gets the list of user IDs associated with this GPG key.
* @return A list of UserIdModel objects representing the user IDs.
*/
QList<QObject *> userIds() const QList<QObject *> userIds() const
{ {
auto user_ids = m_key.userIDs(); auto user_ids = m_key.userIDs();
@ -78,17 +132,23 @@ public:
return ret; return ret;
}; };
/**
* @brief Checks if the GPG key is a secret key.
* @return True if the key is a secret key, false otherwise.
*/
bool isSecret() const bool isSecret() const
{ {
return m_key.hasSecret(); return m_key.hasSecret();
}; };
/**
* @brief Checks if the GPG key is expired.
* @return True if the key is expired, false otherwise.
*/
bool isExpired() const bool isExpired() const
{ {
return m_key.hasSecret(); return m_key.isExpired();
}; };
}; };
#endif #endif

View File

@ -10,49 +10,91 @@
#include <gpgme++/interfaces/passphraseprovider.h> #include <gpgme++/interfaces/passphraseprovider.h>
#include "gpg.h" #include "gpg.h"
/**
* @class UTPassphraseProvider
* @brief A passphrase provider for GPG operations that interacts with a QML dialog.
*
* This class implements the `PassphraseProvider` interface from GPGME and is responsible for
* obtaining passphrases for GPG operations. It does so by triggering a QML dialog to prompt the user
* for their passphrase. The response is then handled asynchronously, and the passphrase is returned to
* the calling GPGME function.
*/
class UTPassphraseProvider : public QObject, public PassphraseProvider class UTPassphraseProvider : public QObject, public PassphraseProvider
{ {
Q_OBJECT Q_OBJECT
public slots: public slots:
void handleResponse(bool canceled, QString p) /**
{ * @brief Slot to handle the user's response from the passphrase dialog.
qDebug() << "call handleResponse"; *
if (!canceled) * This method processes the response from the passphrase dialog. If the user provides a passphrase,
gpgrt_asprintf(&m_passphrase, "%s", p.toUtf8().constData()); * it is stored; if the operation is canceled, a flag is set.
else *
m_canceled = true; * @param canceled Whether the user canceled the passphrase entry.
emit unlockEventLoop(); * @param passphrase The passphrase entered by the user.
}; */
void handleResponse(bool canceled, QString passphrase)
{
qDebug() << "call handleResponse";
if (!canceled)
gpgrt_asprintf(&m_passphrase, "%s", passphrase.toUtf8().constData());
else
m_canceled = true;
emit unlockEventLoop();
};
signals: signals:
/**
* @brief Signal to unlock the event loop.
*
* This signal is emitted when the passphrase has been entered or the operation has been canceled,
* unlocking the event loop waiting for the response.
*/
void unlockEventLoop(); void unlockEventLoop();
private: private:
std::unique_ptr<QSemaphore> m_sem; std::unique_ptr<QSemaphore> m_sem; /**< Semaphore for managing access. */
char *m_passphrase; char *m_passphrase; /**< The passphrase provided by the user. */
bool m_canceled; bool m_canceled; /**< Flag indicating whether the passphrase operation was canceled. */
QObject* m_window; QObject *m_window; /**< The window object that triggers the QML dialog. */
public: public:
UTPassphraseProvider(QObject* window): /**
m_sem(std::unique_ptr<QSemaphore>(new QSemaphore(1))), * @brief Constructs a UTPassphraseProvider.
m_passphrase(nullptr), *
m_canceled(false), * Initializes the semaphore, passphrase, and canceled flag. Sets the window object that will
m_window(window) * trigger the passphrase dialog.
*
* @param window The QObject representing the window that interacts with QML.
*/
UTPassphraseProvider(QObject* window)
: m_sem(std::make_unique<QSemaphore>(1)),
m_passphrase(nullptr),
m_canceled(false),
m_window(window)
{ {
qDebug() << "Initialize UTPassphraseProviderr"; qDebug() << "Initialize UTPassphraseProvider";
} }
char *getPassphrase( const char *useridHint, /**
const char *description, * @brief Implements the PassphraseProvider's `getPassphrase` method.
bool previousWasBad, *
bool &canceled ) Q_DECL_OVERRIDE { * This method is called by GPGME to retrieve the passphrase needed for GPG operations. It triggers
qDebug() << "Call the getPassphrase"; * a QML dialog for the user to input their passphrase. The method waits for the response and returns
* the passphrase if successful, or null if canceled.
*
* @param useridHint A hint for the user ID to which the passphrase corresponds.
* @param description A description of the passphrase request.
* @param previousWasBad Flag indicating whether the previous passphrase attempt was incorrect.
* @param canceled Reference to a boolean flag that will be set if the operation is canceled.
*
* @return The passphrase as a `char *` or `nullptr` if canceled.
*/
char *getPassphrase(const char *useridHint,
const char *description,
bool previousWasBad,
bool &canceled) Q_DECL_OVERRIDE {
qDebug() << "Call the getPassphrase";
if (!this->m_sem->tryAcquire(1, 500)) if (!this->m_sem->tryAcquire(1, 500))
{ {
qWarning() << "Cannot acquire UTPassphraseProvider semaphore."; qWarning() << "Cannot acquire UTPassphraseProvider semaphore.";
@ -92,4 +134,5 @@ public:
return ret; return ret;
}; };
}; };
#endif #endif

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: utpass.qrouland\n" "Project-Id-Version: utpass.qrouland\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-01-15 23:14+0100\n" "POT-Creation-Date: 2025-01-15 23:39+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -85,19 +85,19 @@ msgid ""
"a zip in the settings" "a zip in the settings"
msgstr "" msgstr ""
#: ../qml/pages/PasswordList.qml:76 #: ../qml/pages/PasswordList.qml:71 ../qml/pages/settings/InfoKeys.qml:169
msgid "Decryption failed !"
msgstr ""
#: ../qml/pages/PasswordList.qml:85
msgid "Back" msgid "Back"
msgstr "" msgstr ""
#: ../qml/pages/PasswordList.qml:83 ../qml/pages/headers/MainHeader.qml:9 #: ../qml/pages/PasswordList.qml:92 ../qml/pages/headers/MainHeader.qml:9
#: ../qml/pages/headers/StackHeader.qml:9 UTPass.desktop.in.h:1 #: ../qml/pages/headers/StackHeader.qml:9 UTPass.desktop.in.h:1
msgid "UTPass" msgid "UTPass"
msgstr "" msgstr ""
#: ../qml/pages/PasswordList.qml:96
msgid "Decryption failed !"
msgstr ""
#: ../qml/pages/headers/MainHeader.qml:26 ../qml/pages/settings/Settings.qml:70 #: ../qml/pages/headers/MainHeader.qml:26 ../qml/pages/settings/Settings.qml:70
msgid "Settings" msgid "Settings"
msgstr "" msgstr ""
@ -126,7 +126,7 @@ msgstr ""
#: ../qml/pages/settings/ImportGitClone.qml:91 #: ../qml/pages/settings/ImportGitClone.qml:91
#: ../qml/pages/settings/ImportZip.qml:62 #: ../qml/pages/settings/ImportZip.qml:62
#: ../qml/pages/settings/InfoKeys.qml:122 #: ../qml/pages/settings/InfoKeys.qml:131
msgid "Yes" msgid "Yes"
msgstr "" msgstr ""
@ -168,31 +168,31 @@ msgstr ""
msgid "Zip Password Store Import" msgid "Zip Password Store Import"
msgstr "" msgstr ""
#: ../qml/pages/settings/InfoKeys.qml:39 #: ../qml/pages/settings/InfoKeys.qml:48
msgid "Key ID :" msgid "Key ID :"
msgstr "" msgstr ""
#: ../qml/pages/settings/InfoKeys.qml:73 #: ../qml/pages/settings/InfoKeys.qml:82
msgid "Users IDs : " msgid "Users IDs : "
msgstr "" msgstr ""
#: ../qml/pages/settings/InfoKeys.qml:99 #: ../qml/pages/settings/InfoKeys.qml:108
msgid "Delete this key" msgid "Delete this key"
msgstr "" msgstr ""
#: ../qml/pages/settings/InfoKeys.qml:121 #: ../qml/pages/settings/InfoKeys.qml:130
msgid "You're are about to delete<br>%1<br>Continue ?" msgid "You're are about to delete<br>%1<br>Continue ?"
msgstr "" msgstr ""
#: ../qml/pages/settings/InfoKeys.qml:139 #: ../qml/pages/settings/InfoKeys.qml:148
msgid "Key removal failed !" msgid "Key removal failed !"
msgstr "" msgstr ""
#: ../qml/pages/settings/InfoKeys.qml:148 #: ../qml/pages/settings/InfoKeys.qml:157
msgid "Key successfully deleted !" msgid "Key successfully deleted !"
msgstr "" msgstr ""
#: ../qml/pages/settings/InfoKeys.qml:159 #: ../qml/pages/settings/InfoKeys.qml:177
msgid "Info Keys" msgid "Info Keys"
msgstr "" msgstr ""

View File

@ -24,7 +24,6 @@ MainView {
objectName: "mainView" objectName: "mainView"
applicationName: "utpass.qrouland" applicationName: "utpass.qrouland"
automaticOrientation: true automaticOrientation: true
width: units.gu(45) width: units.gu(45)
height: units.gu(75) height: units.gu(75)
@ -49,4 +48,5 @@ MainView {
} }
} }
} }

View File

@ -34,12 +34,12 @@ Component {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
var path = folderModel.folder + "/" + fileName; var path = folderModel.folder + "/" + fileName;
if (fileIsDir) { if (fileIsDir) {
folderModel.folder = path; folderModel.folder = path;
backAction.visible = true; backAction.visible = true;
passwordListHeader.title = fileName; passwordListHeader.title = fileName;
} else { } else {
console.debug("pass show %1".arg(path)) console.debug("pass show %1".arg(path));
Pass.show(path); Pass.show(path);
} }
} }

View File

@ -1,11 +1,11 @@
import "headers"
import "../components" import "../components"
import "../dialogs" import "../dialogs"
import Lomiri.Components 1.3 import Lomiri.Components 1.3
import Lomiri.Components.Popups 1.3
import Pass 1.0 import Pass 1.0
import Qt.labs.folderlistmodel 2.1 import Qt.labs.folderlistmodel 2.1
import QtQuick 2.4 import QtQuick 2.4
import Lomiri.Components.Popups 1.3 import "headers"
Page { Page {
id: passwordListPage id: passwordListPage
@ -64,6 +64,15 @@ Page {
} }
Component {
id: passwordPageDecryptError
ErrorDialog {
textError: i18n.tr("Decryption failed !")
}
}
header: MainHeader { header: MainHeader {
id: passwordListHeader id: passwordListHeader
@ -89,13 +98,4 @@ Page {
] ]
} }
Component {
id: passwordPageDecryptError
ErrorDialog {
textError: i18n.tr("Decryption failed !")
}
}
} }

View File

@ -11,6 +11,16 @@ Page {
property string currentKey property string currentKey
Component.onCompleted: {
Pass.onGetAllGPGKeysSucceed.connect(function(keys_info) {
infoKeysListView.model = keys_info;
});
Pass.getAllGPGKeysFailed.connect(function(message) {
PopupUtils.open(infoKeysPageGetAllError);
});
Pass.getAllGPGKeys();
}
ListView { ListView {
id: infoKeysListView id: infoKeysListView
@ -18,7 +28,6 @@ Page {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.right: parent.right anchors.right: parent.right
anchors.left: parent.left anchors.left: parent.left
model: Pass.getAllGPGKeys()
delegate: Grid { delegate: Grid {
columns: 1 columns: 1
@ -153,6 +162,15 @@ Page {
} }
Component {
id: infoKeysPageGetAllError
ErrorDialog {
textError: i18n.tr("Decryption failed !")
}
}
header: StackHeader { header: StackHeader {
id: infoKeysHeader id: infoKeysHeader