mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-11-06 00:42:56 -05:00
Improve CLI Show and Clip Commands
* Fixes #11767 * When requesting TOTP, only output that value and then exit * Add explicit requests for UUID and Tags for both show and clip commands. * When showing all values, also include UUID and Tags. * Only hide the attribute names when specifically requesting them by name
This commit is contained in:
parent
f53c7e5af5
commit
87ccc85247
9 changed files with 151 additions and 131 deletions
|
|
@ -52,11 +52,12 @@ It provides the ability to query and modify the entries of a KeePass database, d
|
|||
Removes the named attachment from an entry.
|
||||
|
||||
*clip* [_options_] <__database__> <__entry__> [_timeout_]::
|
||||
Copies an attribute or the current TOTP (if the *-t* option is specified) of a database entry to the clipboard.
|
||||
Copies an attribute, current TOTP value, UUID, or tags list of a database entry to the clipboard.
|
||||
If no attribute name is specified using the *-a* option, the password is copied.
|
||||
If multiple entries with the same name exist in different groups, only the attribute for the first one is copied.
|
||||
For copying the attribute of an entry in a specific group, the group path to the entry should be specified as well, instead of just the name.
|
||||
Optionally, a timeout in seconds can be specified to automatically clear the clipboard, the default timeout is 10 seconds, set to 0 to disable.
|
||||
Note: an error will be thrown if you specify multiple options at once (eg, *--uuid* and *-a*).
|
||||
|
||||
*close*::
|
||||
In interactive mode, closes the currently opened database (see *open*).
|
||||
|
|
@ -143,8 +144,8 @@ It provides the ability to query and modify the entries of a KeePass database, d
|
|||
Searches all entries that match a specific search term in a database.
|
||||
|
||||
*show* [_options_] <__database__> <__entry__>::
|
||||
Shows the title, username, password, URL and notes of a database entry.
|
||||
Can also show the current TOTP.
|
||||
Shows the title, username, password, URL and notes of a database entry by default.
|
||||
Can also show the current TOTP, entry UUID, and tags list.
|
||||
Regarding the occurrence of multiple entries with the same name in different groups, everything stated in the *clip* command section also applies here.
|
||||
|
||||
== OPTIONS
|
||||
|
|
@ -235,6 +236,12 @@ The same password generation options as documented for the generate command can
|
|||
Copies the current TOTP instead of the specified attribute to the clipboard.
|
||||
Will report an error if no TOTP is configured for the entry.
|
||||
|
||||
*--uuid*::
|
||||
Copies the UUID of the entry to the clipboard.
|
||||
|
||||
*--tags*::
|
||||
Copies the tags of the entry to the clipboard.
|
||||
|
||||
*-b*, *--best*::
|
||||
Try to find and copy to clipboard a unique entry matching the input
|
||||
If a unique matching entry is found it will be copied to the clipboard.
|
||||
|
|
@ -262,7 +269,6 @@ The same password generation options as documented for the generate command can
|
|||
*-a*, *--attributes* <__attribute__>...::
|
||||
Shows the named attributes.
|
||||
This option can be specified more than once, with each attribute shown one-per-line in the given order.
|
||||
If no attributes are specified and *-t* is not specified, a summary of the default attributes is given.
|
||||
Protected attributes will be displayed in clear text if specified explicitly by this option.
|
||||
|
||||
*--all*::
|
||||
|
|
@ -275,7 +281,13 @@ The same password generation options as documented for the generate command can
|
|||
Shows the attachment names along with the size of the attachments.
|
||||
|
||||
*-t*, *--totp*::
|
||||
Also shows the current TOTP, reporting an error if no TOTP is configured for the entry.
|
||||
Shows the current TOTP and then exits. An error is thrown if no TOTP is configured for the entry.
|
||||
|
||||
*--uuid*::
|
||||
Shows the UUID of the entry.
|
||||
|
||||
*--tags*::
|
||||
Shows the tag list of the entry.
|
||||
|
||||
=== Diceware options
|
||||
*-W*, *--words* <__count__>::
|
||||
|
|
|
|||
|
|
@ -7635,10 +7635,6 @@ Do you want to overwrite it?</source>
|
|||
<source>Entry %1 not found.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>ERROR: Please specify one of --attribute or --totp, not both.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Entry with path %1 has no TOTP set up.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
|
|
@ -8352,18 +8348,10 @@ Available commands:
|
|||
<source>Search term.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show the entry's current TOTP.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show the protected attributes in clear text.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show all the attributes of the entry.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show the attachments of the entry.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
|
|
@ -9248,6 +9236,34 @@ This option is deprecated, use --set-key-file instead.</source>
|
|||
<source>Tags</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy the entry's UUID to the clipboard.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy the entry's tag list to the clipboard.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>ERROR: Cannot specify multiple options at once (--attribute, --totp, --uuid, --tags).</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Only show the entry's current TOTP.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show the entry's UUID.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show the entry's tags.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show all the attributes of the entry, including UUID and Tags.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QtIOCompressor</name>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,12 @@ const QCommandLineOption Clip::TotpOption =
|
|||
QCommandLineOption(QStringList() << "t" << "totp",
|
||||
QObject::tr("Copy the current TOTP to the clipboard (equivalent to \"-a totp\")."));
|
||||
|
||||
const QCommandLineOption Clip::UuidOption =
|
||||
QCommandLineOption(QStringList() << "uuid", QObject::tr("Copy the entry's UUID to the clipboard."));
|
||||
|
||||
const QCommandLineOption Clip::TagsOption =
|
||||
QCommandLineOption(QStringList() << "tags", QObject::tr("Copy the entry's tag list to the clipboard."));
|
||||
|
||||
const QCommandLineOption Clip::BestMatchOption =
|
||||
QCommandLineOption(QStringList() << "b" << "best-match",
|
||||
QObject::tr("Must match only one entry, otherwise a list of possible matches is shown."));
|
||||
|
|
@ -47,6 +53,8 @@ Clip::Clip()
|
|||
description = QObject::tr("Copy an entry's attribute to the clipboard.");
|
||||
options.append(Clip::AttributeOption);
|
||||
options.append(Clip::TotpOption);
|
||||
options.append(Clip::UuidOption);
|
||||
options.append(Clip::TagsOption);
|
||||
options.append(Clip::BestMatchOption);
|
||||
positionalArguments.append(
|
||||
{QString("entry"), QObject::tr("Path of the entry to clip.", "clip = copy to clipboard"), QString("")});
|
||||
|
|
@ -99,8 +107,13 @@ int Clip::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (parser->isSet(AttributeOption) && parser->isSet(TotpOption)) {
|
||||
err << QObject::tr("ERROR: Please specify one of --attribute or --totp, not both.") << Qt::endl;
|
||||
auto optionCount = parser->isSet(AttributeOption) ? 1 : 0;
|
||||
optionCount += parser->isSet(TotpOption) ? 1 : 0;
|
||||
optionCount += parser->isSet(UuidOption) ? 1 : 0;
|
||||
optionCount += parser->isSet(TagsOption) ? 1 : 0;
|
||||
if (optionCount > 1) {
|
||||
err << QObject::tr("ERROR: Cannot specify multiple options at once (--attribute, --totp, --uuid, --tags).")
|
||||
<< Qt::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
|
@ -113,11 +126,16 @@ int Clip::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
selectedAttribute = "totp";
|
||||
found = true;
|
||||
value = entry->totp();
|
||||
} else if (Utils::EntryFieldNames.contains(selectedAttribute)) {
|
||||
value = Utils::getTopLevelField(entry, selectedAttribute);
|
||||
selectedAttribute = "TOTP";
|
||||
found = true;
|
||||
} else if (parser->isSet(UuidOption)) {
|
||||
value = entry->uuid().toString();
|
||||
selectedAttribute = "UUID";
|
||||
found = true;
|
||||
} else if (parser->isSet(TagsOption)) {
|
||||
value = entry->tags();
|
||||
selectedAttribute = "Tags";
|
||||
found = true;
|
||||
} else {
|
||||
QStringList attrs = Utils::findAttributes(*entry->attributes(), selectedAttribute);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ public:
|
|||
|
||||
static const QCommandLineOption AttributeOption;
|
||||
static const QCommandLineOption TotpOption;
|
||||
static const QCommandLineOption UuidOption;
|
||||
static const QCommandLineOption TagsOption;
|
||||
static const QCommandLineOption BestMatchOption;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -24,14 +24,21 @@
|
|||
#include <QCommandLineParser>
|
||||
|
||||
const QCommandLineOption Show::TotpOption =
|
||||
QCommandLineOption(QStringList() << "t" << "totp", QObject::tr("Show the entry's current TOTP."));
|
||||
QCommandLineOption(QStringList() << "t" << "totp", QObject::tr("Only show the entry's current TOTP."));
|
||||
|
||||
const QCommandLineOption Show::UuidOption =
|
||||
QCommandLineOption(QStringList() << "uuid", QObject::tr("Show the entry's UUID."));
|
||||
|
||||
const QCommandLineOption Show::TagsOption =
|
||||
QCommandLineOption(QStringList() << "tags", QObject::tr("Show the entry's tags."));
|
||||
|
||||
const QCommandLineOption Show::ProtectedAttributesOption =
|
||||
QCommandLineOption(QStringList() << "s" << "show-protected",
|
||||
QObject::tr("Show the protected attributes in clear text."));
|
||||
|
||||
const QCommandLineOption Show::AllAttributesOption =
|
||||
QCommandLineOption(QStringList() << "all", QObject::tr("Show all the attributes of the entry."));
|
||||
QCommandLineOption(QStringList() << "all",
|
||||
QObject::tr("Show all the attributes of the entry, including UUID and Tags."));
|
||||
|
||||
const QCommandLineOption Show::AttachmentsOption =
|
||||
QCommandLineOption(QStringList() << "show-attachments", QObject::tr("Show the attachments of the entry."));
|
||||
|
|
@ -49,6 +56,8 @@ Show::Show()
|
|||
name = QString("show");
|
||||
description = QObject::tr("Show an entry's information.");
|
||||
options.append(Show::TotpOption);
|
||||
options.append(Show::UuidOption);
|
||||
options.append(Show::TagsOption);
|
||||
options.append(Show::AttributesOption);
|
||||
options.append(Show::ProtectedAttributesOption);
|
||||
options.append(Show::AllAttributesOption);
|
||||
|
|
@ -63,9 +72,10 @@ int Show::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
|
|||
|
||||
const QStringList args = parser->positionalArguments();
|
||||
const QString& entryPath = args.at(1);
|
||||
bool showTotp = parser->isSet(Show::TotpOption);
|
||||
bool showProtectedAttributes = parser->isSet(Show::ProtectedAttributesOption);
|
||||
bool showAllAttributes = parser->isSet(Show::AllAttributesOption);
|
||||
bool showUuid = parser->isSet(Show::UuidOption);
|
||||
bool showTags = parser->isSet(Show::TagsOption);
|
||||
QStringList attributes = parser->values(Show::AttributesOption);
|
||||
|
||||
Entry* entry = database->rootGroup()->findEntryByPath(entryPath);
|
||||
|
|
@ -74,18 +84,23 @@ int Show::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (showTotp && !entry->hasTotp()) {
|
||||
err << QObject::tr("Entry with path %1 has no TOTP set up.").arg(entryPath) << Qt::endl;
|
||||
return EXIT_FAILURE;
|
||||
// Early exit if the user only wants to show the TOTP
|
||||
if (parser->isSet(Show::TotpOption)) {
|
||||
if (!entry->hasTotp()) {
|
||||
err << QObject::tr("Entry with path %1 has no TOTP set up.").arg(entryPath) << Qt::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
out << entry->totp() << Qt::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
bool attributesWereSpecified = true;
|
||||
bool attributesWereSpecified = !showUuid && !showTags;
|
||||
if (showAllAttributes) {
|
||||
attributesWereSpecified = false;
|
||||
showUuid = true;
|
||||
showTags = true;
|
||||
attributes = EntryAttributes::DefaultAttributes;
|
||||
for (QString fieldName : Utils::EntryFieldNames) {
|
||||
attributes.append(fieldName);
|
||||
}
|
||||
// Adding the custom attributes after the default attributes so that
|
||||
// the default attributes are always shown first.
|
||||
for (QString attributeName : entry->attributes()->keys()) {
|
||||
|
|
@ -94,26 +109,16 @@ int Show::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
|
|||
}
|
||||
attributes.append(attributeName);
|
||||
}
|
||||
} else if (attributes.isEmpty() && !showTotp) {
|
||||
} else if (attributes.isEmpty() && !showUuid && !showTags) {
|
||||
// If no attributes are specified, output the default attribute set.
|
||||
attributesWereSpecified = false;
|
||||
attributes = EntryAttributes::DefaultAttributes;
|
||||
for (QString fieldName : Utils::EntryFieldNames) {
|
||||
attributes.append(fieldName);
|
||||
}
|
||||
showTags = true;
|
||||
}
|
||||
|
||||
// Iterate over the attributes and output them line-by-line.
|
||||
bool encounteredError = false;
|
||||
for (const QString& attributeName : asConst(attributes)) {
|
||||
if (Utils::EntryFieldNames.contains(attributeName)) {
|
||||
if (!attributesWereSpecified) {
|
||||
out << attributeName << ": ";
|
||||
}
|
||||
out << Utils::getTopLevelField(entry, attributeName) << Qt::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
QStringList attrs = Utils::findAttributes(*entry->attributes(), attributeName);
|
||||
if (attrs.isEmpty()) {
|
||||
encounteredError = true;
|
||||
|
|
@ -137,6 +142,14 @@ int Show::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
|
|||
}
|
||||
}
|
||||
|
||||
// Output UUID and Tags if a certain field wasn't specified
|
||||
if (showTags) {
|
||||
out << "Tags: " << entry->tags() << Qt::endl;
|
||||
}
|
||||
if (showUuid) {
|
||||
out << "UUID: " << entry->uuid().toString() << Qt::endl;
|
||||
}
|
||||
|
||||
if (parser->isSet(Show::AttachmentsOption)) {
|
||||
// Separate attachment output from attributes output via a newline.
|
||||
out << Qt::endl;
|
||||
|
|
@ -156,9 +169,5 @@ int Show::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
|
|||
}
|
||||
}
|
||||
|
||||
if (showTotp) {
|
||||
out << entry->totp() << Qt::endl;
|
||||
}
|
||||
|
||||
return encounteredError ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ public:
|
|||
int executeWithDatabase(QSharedPointer<Database> db, QSharedPointer<QCommandLineParser> parser) override;
|
||||
|
||||
static const QCommandLineOption TotpOption;
|
||||
static const QCommandLineOption UuidOption;
|
||||
static const QCommandLineOption TagsOption;
|
||||
static const QCommandLineOption AllAttributesOption;
|
||||
static const QCommandLineOption AttributesOption;
|
||||
static const QCommandLineOption ProtectedAttributesOption;
|
||||
|
|
|
|||
|
|
@ -395,17 +395,6 @@ namespace Utils
|
|||
return result;
|
||||
}
|
||||
|
||||
QString getTopLevelField(const Entry* entry, const QString& fieldName)
|
||||
{
|
||||
if (fieldName == UuidFieldName) {
|
||||
return entry->uuid().toString();
|
||||
}
|
||||
if (fieldName == TagsFieldName) {
|
||||
return entry->tags();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
QStringList findAttributes(const EntryAttributes& attributes, const QString& name)
|
||||
{
|
||||
QStringList result;
|
||||
|
|
|
|||
|
|
@ -34,10 +34,6 @@ namespace Utils
|
|||
extern QTextStream STDIN;
|
||||
extern QTextStream DEVNULL;
|
||||
|
||||
static const QString UuidFieldName = "Uuid";
|
||||
static const QString TagsFieldName = "Tags";
|
||||
static const QStringList EntryFieldNames(QStringList() << UuidFieldName << TagsFieldName);
|
||||
|
||||
void setDefaultTextStreams();
|
||||
void resetTextStreams();
|
||||
|
||||
|
|
@ -61,10 +57,6 @@ namespace Utils
|
|||
* (case-insensitive).
|
||||
*/
|
||||
QStringList findAttributes(const EntryAttributes& attributes, const QString& name);
|
||||
/**
|
||||
* Get the value of a top-level Entry field using its name.
|
||||
*/
|
||||
QString getTopLevelField(const Entry* entry, const QString& fieldName);
|
||||
}; // namespace Utils
|
||||
|
||||
#endif // KEEPASSXC_UTILS_H
|
||||
|
|
|
|||
|
|
@ -673,14 +673,14 @@ void TestCli::testClip()
|
|||
|
||||
// Uuid (top-level field)
|
||||
setInput("a");
|
||||
execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry", "0", "-a", "Uuid"});
|
||||
execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry", "0", "--uuid"});
|
||||
QTRY_COMPARE(clipboard->text(), QString("{9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}"));
|
||||
|
||||
// TOTP
|
||||
setInput("a");
|
||||
execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry", "0", "--totp"});
|
||||
QTRY_VERIFY(isTotp(clipboard->text()));
|
||||
QCOMPARE(m_stdout->readLine(), QByteArray("Entry's \"totp\" attribute copied to the clipboard!\n"));
|
||||
QCOMPARE(m_stdout->readLine(), QByteArray("Entry's \"TOTP\" attribute copied to the clipboard!\n"));
|
||||
|
||||
// Test Unicode
|
||||
setInput("a");
|
||||
|
|
@ -725,7 +725,7 @@ void TestCli::testClip()
|
|||
|
||||
setInput("a");
|
||||
execCmd(clipCmd, {"clip", m_dbFile2->fileName(), "--attribute", "Username", "--totp", "/Sample Entry", "0"});
|
||||
QVERIFY(m_stderr->readAll().contains("ERROR: Please specify one of --attribute or --totp, not both.\n"));
|
||||
QVERIFY(m_stderr->readAll().contains("ERROR: Cannot specify multiple options at once"));
|
||||
|
||||
// Best option
|
||||
setInput("a");
|
||||
|
|
@ -2077,72 +2077,55 @@ void TestCli::testShow()
|
|||
QVERIFY(!showCmd.name.isEmpty());
|
||||
QVERIFY(showCmd.getDescriptionLine().contains(showCmd.name));
|
||||
|
||||
const QByteArray expectTitle("Title: Sample Entry");
|
||||
const QByteArray expectUserName("UserName: User Name");
|
||||
const QByteArray expectUrl("URL: http://www.somesite.com/");
|
||||
const QByteArray expectUuid("UUID: {9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}");
|
||||
const QByteArray expectNotes("Notes: Notes");
|
||||
const QByteArray expectTags("Tags: ");
|
||||
|
||||
setInput("a");
|
||||
execCmd(showCmd, {"show", m_dbFile->fileName(), "/Sample Entry"});
|
||||
m_stderr->readLine(); // Skip password prompt
|
||||
QCOMPARE(m_stderr->readAll(), QByteArray());
|
||||
QCOMPARE(m_stdout->readAll(),
|
||||
QByteArray("Title: Sample Entry\n"
|
||||
"UserName: User Name\n"
|
||||
"Password: PROTECTED\n"
|
||||
"URL: http://www.somesite.com/\n"
|
||||
"Notes: Notes\n"
|
||||
"Uuid: {9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}\n"
|
||||
"Tags: \n"));
|
||||
auto out = m_stdout->readAll();
|
||||
QVERIFY(out.contains(expectTitle));
|
||||
QVERIFY(out.contains(expectUserName));
|
||||
QVERIFY(out.contains(expectUrl));
|
||||
QVERIFY(out.contains(expectNotes));
|
||||
QVERIFY(out.contains(expectTags));
|
||||
QVERIFY(!out.contains(expectUuid));
|
||||
QVERIFY(out.contains("Password: PROTECTED"));
|
||||
|
||||
setInput("a");
|
||||
execCmd(showCmd, {"show", "-s", m_dbFile->fileName(), "/Sample Entry"});
|
||||
QCOMPARE(m_stdout->readAll(),
|
||||
QByteArray("Title: Sample Entry\n"
|
||||
"UserName: User Name\n"
|
||||
"Password: Password\n"
|
||||
"URL: http://www.somesite.com/\n"
|
||||
"Notes: Notes\n"
|
||||
"Uuid: {9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}\n"
|
||||
"Tags: \n"));
|
||||
out = m_stdout->readAll();
|
||||
QVERIFY(out.contains("Password: Password"));
|
||||
|
||||
setInput("a");
|
||||
execCmd(showCmd, {"show", m_dbFile->fileName(), "-q", "/Sample Entry"});
|
||||
QCOMPARE(m_stderr->readAll(), QByteArray());
|
||||
QCOMPARE(m_stdout->readAll(),
|
||||
QByteArray("Title: Sample Entry\n"
|
||||
"UserName: User Name\n"
|
||||
"Password: PROTECTED\n"
|
||||
"URL: http://www.somesite.com/\n"
|
||||
"Notes: Notes\n"
|
||||
"Uuid: {9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}\n"
|
||||
"Tags: \n"));
|
||||
out = m_stdout->readAll();
|
||||
QVERIFY(out.contains(expectTitle));
|
||||
QVERIFY(out.contains(expectUserName));
|
||||
QVERIFY(out.contains(expectUrl));
|
||||
QVERIFY(out.contains(expectNotes));
|
||||
QVERIFY(out.contains(expectTags));
|
||||
QVERIFY(!out.contains(expectUuid));
|
||||
|
||||
setInput("a");
|
||||
execCmd(showCmd, {"show", m_dbFile->fileName(), "--show-attachments", "/Sample Entry"});
|
||||
m_stderr->readLine(); // Skip password prompt
|
||||
QCOMPARE(m_stderr->readAll(), QByteArray());
|
||||
QCOMPARE(m_stdout->readAll(),
|
||||
QByteArray("Title: Sample Entry\n"
|
||||
"UserName: User Name\n"
|
||||
"Password: PROTECTED\n"
|
||||
"URL: http://www.somesite.com/\n"
|
||||
"Notes: Notes\n"
|
||||
"Uuid: {9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}\n"
|
||||
"Tags: \n"
|
||||
"\n"
|
||||
"Attachments:\n"
|
||||
" Sample attachment.txt (15 B)\n"));
|
||||
out = m_stdout->readAll();
|
||||
QVERIFY(out.contains("Attachments:\n Sample attachment.txt (15 B)"));
|
||||
|
||||
setInput("a");
|
||||
execCmd(showCmd, {"show", m_dbFile->fileName(), "--show-attachments", "/Homebanking/Subgroup/Subgroup Entry"});
|
||||
m_stderr->readLine(); // Skip password prompt
|
||||
QCOMPARE(m_stderr->readAll(), QByteArray());
|
||||
QCOMPARE(m_stdout->readAll(),
|
||||
QByteArray("Title: Subgroup Entry\n"
|
||||
"UserName: Bank User Name\n"
|
||||
"Password: PROTECTED\n"
|
||||
"URL: https://www.bank.com\n"
|
||||
"Notes: Important note\n"
|
||||
"Uuid: {20b183fd-6878-4506-a50b-06d30792aa10}\n"
|
||||
"Tags: \n"
|
||||
"\n"
|
||||
"No attachments present.\n"));
|
||||
out = m_stdout->readAll();
|
||||
QVERIFY(out.contains("No attachments present."));
|
||||
|
||||
setInput("a");
|
||||
execCmd(showCmd, {"show", "-a", "Title", m_dbFile->fileName(), "/Sample Entry"});
|
||||
|
|
@ -2153,8 +2136,8 @@ void TestCli::testShow()
|
|||
QCOMPARE(m_stdout->readAll(), QByteArray("Password\n"));
|
||||
|
||||
setInput("a");
|
||||
execCmd(showCmd, {"show", "-a", "Uuid", m_dbFile->fileName(), "/Sample Entry"});
|
||||
QCOMPARE(m_stdout->readAll(), QByteArray("{9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}\n"));
|
||||
execCmd(showCmd, {"show", "--uuid", m_dbFile->fileName(), "/Sample Entry"});
|
||||
QVERIFY(m_stdout->readAll().contains(expectUuid));
|
||||
|
||||
setInput("a");
|
||||
execCmd(showCmd, {"show", "-a", "Title", "-a", "URL", m_dbFile->fileName(), "/Sample Entry"});
|
||||
|
|
@ -2178,9 +2161,9 @@ void TestCli::testShow()
|
|||
execCmd(showCmd, {"show", "-t", m_dbFile->fileName(), "/Sample Entry"});
|
||||
QVERIFY(isTotp(m_stdout->readAll()));
|
||||
|
||||
// TOTP paramter short circuits any other parameter
|
||||
setInput("a");
|
||||
execCmd(showCmd, {"show", "-a", "Title", m_dbFile->fileName(), "--totp", "/Sample Entry"});
|
||||
QCOMPARE(m_stdout->readLine(), QByteArray("Sample Entry\n"));
|
||||
QVERIFY(isTotp(m_stdout->readAll()));
|
||||
|
||||
setInput("a");
|
||||
|
|
@ -2196,18 +2179,15 @@ void TestCli::testShow()
|
|||
|
||||
setInput("a");
|
||||
execCmd(showCmd, {"show", "--all", m_dbFile->fileName(), "/Sample Entry"});
|
||||
QCOMPARE(m_stdout->readAll(),
|
||||
QByteArray("Title: Sample Entry\n"
|
||||
"UserName: User Name\n"
|
||||
"Password: PROTECTED\n"
|
||||
"URL: http://www.somesite.com/\n"
|
||||
"Notes: Notes\n"
|
||||
"Uuid: {9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}\n"
|
||||
"Tags: \n"
|
||||
"TOTP Seed: PROTECTED\n"
|
||||
"TOTP Settings: 30;6\n"
|
||||
"TestAttribute1: b\n"
|
||||
"testattribute1: a\n"));
|
||||
out = m_stdout->readAll();
|
||||
QVERIFY(out.contains(expectTitle));
|
||||
QVERIFY(out.contains(expectUserName));
|
||||
QVERIFY(out.contains(expectUuid));
|
||||
QVERIFY(out.contains(expectTags));
|
||||
QVERIFY(out.contains("TOTP Seed: PROTECTED"));
|
||||
QVERIFY(out.contains("TOTP Settings: 30;6"));
|
||||
QVERIFY(out.contains("TestAttribute1: b"));
|
||||
QVERIFY(out.contains("testattribute1: a"));
|
||||
}
|
||||
|
||||
void TestCli::testInvalidDbFiles()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue