8#ifndef SRC_IMITATEPASS_H_
9#define SRC_IMITATEPASS_H_
16#include <QTemporaryDir>
22class QRegularExpression;
43 friend class tst_util;
44 friend class tst_imitatepass;
71 QString *why =
nullptr) -> bool;
84 auto writeGpgIdFile(
const QString &gpgIdFile,
const QList<UserInfo> &users,
85 QByteArray *written =
nullptr) -> bool;
94 auto signGpgIdFile(
const QString &gpgIdFile,
const QByteArray &contents)
120 auto copyDestination(
const QString &src,
const QString &dest,
bool force)
134 QByteArray *contents) -> bool;
146 auto settleSignature(
const QString &gpgIdFile,
const QByteArray &written,
148 QString *sigToCommit) -> bool;
161 auto gitAddGpgId(
const QString &gpgIdFile,
const QString &gpgIdSigFile,
162 QString *out, QString *err) -> int;
168 auto gitTracks(
const QString &file) -> bool;
186 QHash<QString, QStringList> &verified,
187 QStringList &gpgId) -> bool;
209 const QStringList &recipients, QString *why) -> bool;
216 auto decryptEntry(
const QString &fileName, QString *plaintext) -> bool;
224 auto encryptFor(
const QString &output,
const QStringList &recipients,
225 const QString &plaintext) -> bool;
233 auto ciphertextHolds(
const QString &ciphertext,
const QString &plaintext)
251 bool force) -> QString;
260 void executeMoveGit(
const QString &src,
const QString &destFile,
bool force);
267 void gitCommit(
const QString &file,
const QString &msg);
278 QString input = QString(),
bool readStdout =
true,
279 bool readStderr =
true);
300 QString input = QString(),
bool readStdout =
true,
301 bool readStderr =
true);
351 [[nodiscard]]
auto execBlocking(
const QString &app,
const QStringList &args,
352 const QString &input = QString(),
353 QString *process_out =
nullptr,
354 QString *process_err =
nullptr) -> int;
363 [[nodiscard]]
auto execBlocking(
const QString &app,
const QStringList &args,
364 QString *process_out,
365 QString *process_err =
nullptr) -> int;
372 auto storeGit(
const QStringList &args, QString *out) ->
bool override;
380 void finished(
int id,
int exitCode,
const QString &out,
381 const QString &err)
override;
389 [[nodiscard]]
auto insertWritten(
const QString &err)
const ->
bool override {
437 void Show(QString file)
override;
444 void Insert(QString file, QString newValue,
bool overwrite)
override;
450 void Remove(QString file,
bool isDir)
override;
462 void Init(QString path,
const QList<UserInfo> &users)
override;
538 void Move(
const QString src,
const QString dest,
const bool force)
override;
545 void Copy(
const QString src,
const QString dest,
const bool force)
override;
555 void Grep(QString pattern,
bool caseInsensitive)
override;
607 bool overwrite, QString *error) -> bool;
661 QHash<QString, QStringList> &verified,
756 auto
pgit(const QString &path) const -> QString;
763 auto
pgpg(const QString &path) const -> QString;
The detached signature on a store's .gpg-id: whether the configured signing key is usable,...
TransactionHelper(SimpleTransaction *trans, PROCESS result)
Start transaction.
~TransactionHelper()
End transaction on destruction.
SimpleTransaction * m_transaction
The transaction being bracketed; not owned.
PROCESS m_result
What the transaction reports as once its last step ends.
Implementation that imitates 'pass' when the real tool is unavailable.
auto commitReencrypted(const QString &fileName) -> bool
Stage and commit a re-encrypted entry, when the store is a Git repository QtPass manages.
auto encryptFor(const QString &output, const QStringList &recipients, const QString &plaintext) -> bool
Encrypt plaintext to recipients, into output.
auto createBackupCommit() -> bool
Create git backup commit before re-encryption.
void finishReencrypt(const ReencryptResult &result)
Report the outcome of a run and emit endReencryptPath().
void Remove(QString file, bool isDir) override
Remove password.
QString m_transactionOutput
stdout of the steps of the transaction in flight, collected by finished() and handed on,...
auto execBlocking(const QString &app, const QStringList &args, const QString &input=QString(), QString *process_out=nullptr, QString *process_err=nullptr) -> int
Executor::executeBlocking() for the re-encryption helpers.
void GitInit() override
Initialize Git repository.
auto recipientsForEntry(const QString &file, QStringList *recipients) -> bool
The recipients to encrypt file to: its folder's .gpg-id, verified when a signing key is set.
void executeGpg(PROCESS id, const QStringList &args, QString input=QString(), bool readStdout=true, bool readStderr=true)
Execute GPG command.
auto ciphertextHolds(const QString &ciphertext, const QString &plaintext) -> bool
Decrypt ciphertext again and compare it with plaintext, so nothing replaces an entry until it is know...
auto reencryptSingleFile(const QString &fileName, const QStringList &recipients, QString *why) -> bool
Re-encrypt single file with new recipients.
void reportUncommittedGpgId(const QString &dir, const QString &gitError, bool reencrypted)
Tell the user that the recipients of dir changed on disk but the change is not committed,...
auto copyDestination(const QString &src, const QString &dest, bool force) -> QString
The file a copy of src to dest writes: like pass cp, into an existing folder with ....
bool m_reencryptActive
Set while a re-encryption run is pending or on the worker thread.
void startReencryptWorker(const QString &dir)
Start the worker thread once the Executor queue is idle.
auto entriesToReencrypt(const QString &dir) -> QStringList
The entries under dir a run considers, telling the user about anything skipped for not being a regula...
auto writeGpgIdFile(const QString &gpgIdFile, const QList< UserInfo > &users, QByteArray *written=nullptr) -> bool
Write the enabled recipients to a .gpg-id, atomically: a write that fails halfway (full disk,...
auto commitArgs() -> QStringList
The start of a git commit for the store: "commit", and "-S" when git config pass.signcommits is true ...
auto verifyGpgIdForDir(const QString &file, QHash< QString, QStringList > &verified, QStringList &gpgId) -> bool
Recipients for the directory of file, from its verified .gpg-id.
void Grep(QString pattern, bool caseInsensitive) override
Search all password content by GPG-decrypting each .gpg file.
void Insert(QString file, QString newValue, bool overwrite) override
Insert new password.
auto insertWritten(const QString &err) const -> bool override
Whether the failed insert had placed its entry (see placeEncryptedFile()) before a later git step fai...
auto recipientsForDir(const QString &fileName, QHash< QString, QStringList > &verified, QStringList &gpgId, ReencryptResult &result) -> bool
The verified recipients for the folder fileName sits in.
auto gitTracks(const QString &file) -> bool
Check whether git already tracks a file in the store.
void GitPull_b() override
Pull with rebase.
void cancelReencryptPath()
Ask a running reencryptPath() to stop.
ImitatePass()
Construct the backend and connect its content search.
auto gitReady() -> bool
gitConfigured() plus a status message when git is enabled but no executable is configured.
void executeGit(PROCESS id, const QStringList &args, QString input=QString(), bool readStdout=true, bool readStderr=true)
Execute git command.
void Init(QString path, const QList< UserInfo > &users) override
Initialize store.
auto loadVerifiedRecipients(const QString &gpgIdFile, QStringList *recipients, QString *why=nullptr) -> bool
Read a .gpg-id, verify its detached signature and parse the recipients from the bytes that were verif...
void Copy(const QString src, const QString dest, const bool force) override
Copy password file.
QThread * m_reencryptThread
The re-encryption worker while it runs, null otherwise. The destructor sets m_reencryptCancel and joi...
auto reencryptFiles(const QString &dir) -> ReencryptResult
Worker-thread body: scan dir and re-encrypt stale files.
auto placeEncryptedFile(const QString &output, const QString &file, bool overwrite, QString *error) -> bool
Bring the ciphertext gpg wrote to output into the store as file (Util::copyFileReplacing): through a ...
auto settleSignature(const QString &gpgIdFile, const QByteArray &written, const GpgIdSigner &signer, bool useGit, QString *sigToCommit) -> bool
Bring the signature in line with the list just written: a new one when signing is on,...
SimpleTransaction m_transaction
auto signGpgIdFile(const QString &gpgIdFile, const QByteArray &contents) -> bool
Sign a .gpg-id with the configured key and verify the result; failures are reported through critical(...
QProcessEnvironment m_reencryptEnv
void reencryptProgress(int current, int total)
Re-encryption progress: current of total files checked.
void executeMoveGit(const QString &src, const QString &destFile, bool force)
Execute git move operation.
void endReencryptPath()
A reencryptPath() run is over, whether it finished, failed, was cancelled or was refused; the main wi...
auto translatePathForWsl(const QString &path, const QString &exe) const -> QString
Translate path for the given exe when WSL-routed: wraps in wslpath substitution, otherwise returns pa...
void finished(int id, int exitCode, const QString &out, const QString &err) override
Handle process completion.
void reencryptWithoutGit(const QString &dir, const QString &gitError)
Re-encrypt dir to the .gpg-id Init() wrote although its commit failed, without any Git step (they wou...
auto addGenerationHeader(const QString &gpgIdFile, const GpgIdSigner &signer, QByteArray *contents) -> bool
Put the generation header on a list that is about to be signed: reserve a generation above what this ...
auto gitAddGpgId(const QString &gpgIdFile, const QString &gpgIdSigFile, QString *out, QString *err) -> int
Stage a .gpg-id and, when given, its .sig, and commit both in one commit, so no commit in the history...
std::optional< UncommittedGpgId > m_uncommittedGpgId
std::atomic< bool > m_reencryptCancel
void GitPull() override
Pull from remote.
auto refuseLinkedGpgIdFolder(const QString &path) -> bool
Refuse a folder, or a .gpg-id/.gpg-id.sig in it, that is a link: writing there would reach outside th...
void Show(QString file) override
Show decrypted password.
auto pgpg(const QString &path) const -> QString
Translate path for gpg when WSL-routed: wraps in wslpath substitution, otherwise returns path unchang...
auto storeGit(const QStringList &args, QString *out) -> bool override
Run git with -C <store> in the store, blocking.
QQueue< PendingInsert > m_pendingInserts
The inserts whose gpg step has not ended yet, oldest first.
NativeGrep m_grep
Background search over the decrypted store; relays to finishedGrep.
auto resolveMoveDestination(const QString &src, const QString &dest, bool force) -> QString
Resolve destination for move operation.
auto recoverReencryptLeftovers(const QString &dir) -> bool
Deal with what a crashed or failed earlier run left under dir before touching anything: stale tempora...
void GitPush() override
Push to remote.
void Move(const QString src, const QString dest, const bool force) override
Move password file.
auto restoreBackup(const QString &path) -> bool
Put a 1.8.x backup back in its entry's place when the entry is missing; report it when both exist (bo...
void dropStaleTemporary(const QString &path)
Remove a stale temporary a crashed run left, unless it was modified within the hour: on a shared stor...
void startReencryptPath()
A reencryptPath() run is about to start its worker thread.
auto decryptEntry(const QString &fileName, QString *plaintext) -> bool
Decrypt fileName for re-encryption.
auto getKeysFromFile(const QString &fileName) -> QStringList
Read recipients from file.
auto reencryptUsesGit() const -> bool
gitConfigured(), unless the current run is one reencryptWithoutGit() started.
auto gitConfigured() const -> bool
Git is enabled and an executable is configured.
void reencryptPath(const QString &dir)
Re-encrypt entire directory.
auto pgit(const QString &path) const -> QString
Translate path for git when WSL-routed: wraps in wslpath substitution, otherwise returns path unchang...
void reportUnrestorable(const QString &path)
Tell the user a leftover is not a regular file and was left.
auto pullBeforeReencrypt() -> bool
Pull before a run, when the store is a Git repository and automatic pulling is on.
void gitCommit(const QString &file, const QString &msg)
Commit changes to git.
void beforeExecute(PROCESS id) override
Open a transaction for every execution.
auto gpgIdSigner() -> GpgIdSigner
The signer for this store's .gpg-id, bound to the configured gpg and signing keys and to execBlocking...
Full-text search over a password store without pass grep: every .gpg file is decrypted with gpg on a ...
Enums::PROCESS PROCESS
Alias for Enums::PROCESS used throughout this class.
Pass()
Construct a Pass instance.
Tracks a sequence of processes that should be treated as one atomic operation.
void transactionStart()
Open a transaction: the processes added until the matching transactionEnd() are reported as one opera...
void transactionEnd(Enums::PROCESS process)
Close the transaction opened by the matching transactionStart().
GpgIdSigner, which signs a store's .gpg-id and verifies an existing .gpg-id.sig against the configure...
NativeGrep, the content search that decrypts every entry on a worker thread instead of running pass g...
Pass, the abstract password-store backend that RealPass and ImitatePass implement,...
PROCESS
Identifies different subprocess operations used in QtPass.
SimpleTransaction, the bookkeeping that lets ImitatePass report several queued processes as one finis...
Plain value-object holding all flat QtPass configuration.
QString file
The entry's path in the store, where output goes.
std::shared_ptr< QTemporaryDir > scratch
The private directory gpg writes into; removed with this.
bool overwrite
Whether an entry already at file may be replaced.
QString output
The ciphertext file gpg writes, inside scratch.
Outcome of one reencryptPath() run; filled on the worker thread and consumed by finishReencrypt() on ...
A .gpg-id Init() wrote but could not commit.
QString folder
The folder whose recipients changed.
QString gitError
What Git said when the commit failed.