Add a -n (--notes) option to keepassxc-cli add and edit commands

This commit is contained in:
david 2020-06-22 15:46:33 +01:00 committed by Jonathan White
parent 8a4a804c8c
commit 55eb855267
5 changed files with 47 additions and 1 deletions

View File

@ -176,6 +176,9 @@ The same password generation options as documented for the generate command can
*--url* <__url__>:: *--url* <__url__>::
Specifies the URL of the entry. Specifies the URL of the entry.
*-n*, *--notes* <__notes__>::
Specifies the notes of the entry.
*-p*, *--password-prompt*:: *-p*, *--password-prompt*::
Uses a password prompt for the entry's password. Uses a password prompt for the entry's password.

View File

@ -36,6 +36,11 @@ const QCommandLineOption Add::UsernameOption = QCommandLineOption(QStringList()
const QCommandLineOption Add::UrlOption = const QCommandLineOption Add::UrlOption =
QCommandLineOption(QStringList() << "url", QObject::tr("URL for the entry."), QObject::tr("URL")); QCommandLineOption(QStringList() << "url", QObject::tr("URL for the entry."), QObject::tr("URL"));
const QCommandLineOption Add::NotesOption = QCommandLineOption(QStringList() << "n"
<< "notes",
QObject::tr("Notes for the entry."),
QObject::tr("Notes"));
const QCommandLineOption Add::PasswordPromptOption = const QCommandLineOption Add::PasswordPromptOption =
QCommandLineOption(QStringList() << "p" QCommandLineOption(QStringList() << "p"
<< "password-prompt", << "password-prompt",
@ -51,6 +56,7 @@ Add::Add()
description = QObject::tr("Add a new entry to a database."); description = QObject::tr("Add a new entry to a database.");
options.append(Add::UsernameOption); options.append(Add::UsernameOption);
options.append(Add::UrlOption); options.append(Add::UrlOption);
options.append(Add::NotesOption);
options.append(Add::PasswordPromptOption); options.append(Add::PasswordPromptOption);
positionalArguments.append({QString("entry"), QObject::tr("Path of the entry to add."), QString("")}); positionalArguments.append({QString("entry"), QObject::tr("Path of the entry to add."), QString("")});
@ -105,6 +111,10 @@ int Add::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<Q
entry->setUrl(parser->value(Add::UrlOption)); entry->setUrl(parser->value(Add::UrlOption));
} }
if (!parser->value(Add::NotesOption).isEmpty()) {
entry->setNotes(parser->value(Add::NotesOption).replace("\\n", "\n"));
}
if (parser->isSet(Add::PasswordPromptOption)) { if (parser->isSet(Add::PasswordPromptOption)) {
if (!parser->isSet(Command::QuietOption)) { if (!parser->isSet(Command::QuietOption)) {
out << QObject::tr("Enter password for new entry: ") << flush; out << QObject::tr("Enter password for new entry: ") << flush;

View File

@ -29,6 +29,7 @@ public:
static const QCommandLineOption UsernameOption; static const QCommandLineOption UsernameOption;
static const QCommandLineOption UrlOption; static const QCommandLineOption UrlOption;
static const QCommandLineOption NotesOption;
static const QCommandLineOption PasswordPromptOption; static const QCommandLineOption PasswordPromptOption;
static const QCommandLineOption GenerateOption; static const QCommandLineOption GenerateOption;
static const QCommandLineOption PasswordLengthOption; static const QCommandLineOption PasswordLengthOption;

View File

@ -41,6 +41,7 @@ Edit::Edit()
// Using some of the options from the Add command since they are the same. // Using some of the options from the Add command since they are the same.
options.append(Add::UsernameOption); options.append(Add::UsernameOption);
options.append(Add::UrlOption); options.append(Add::UrlOption);
options.append(Add::NotesOption);
options.append(Add::PasswordPromptOption); options.append(Add::PasswordPromptOption);
options.append(Edit::TitleOption); options.append(Edit::TitleOption);
positionalArguments.append({QString("entry"), QObject::tr("Path of the entry to edit."), QString("")}); positionalArguments.append({QString("entry"), QObject::tr("Path of the entry to edit."), QString("")});
@ -91,9 +92,10 @@ int Edit::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
QString username = parser->value(Add::UsernameOption); QString username = parser->value(Add::UsernameOption);
QString url = parser->value(Add::UrlOption); QString url = parser->value(Add::UrlOption);
QString notes = parser->value(Add::NotesOption);
QString title = parser->value(Edit::TitleOption); QString title = parser->value(Edit::TitleOption);
bool prompt = parser->isSet(Add::PasswordPromptOption); bool prompt = parser->isSet(Add::PasswordPromptOption);
if (username.isEmpty() && url.isEmpty() && title.isEmpty() && !prompt && !generate) { if (username.isEmpty() && url.isEmpty() && notes.isEmpty() && title.isEmpty() && !prompt && !generate) {
err << QObject::tr("Not changing any field for entry %1.").arg(entryPath) << endl; err << QObject::tr("Not changing any field for entry %1.").arg(entryPath) << endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -108,6 +110,10 @@ int Edit::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
entry->setUsername(username); entry->setUsername(username);
} }
if (!notes.isEmpty()) {
entry->setNotes(notes.replace("\\n", "\n"));
}
if (!url.isEmpty()) { if (!url.isEmpty()) {
entry->setUrl(url); entry->setUrl(url);
} }

View File

@ -282,6 +282,8 @@ void TestCli::testAdd()
"-g", "-g",
"-L", "-L",
"20", "20",
"-n",
"some notes",
m_dbFile->fileName(), m_dbFile->fileName(),
"/newuser-entry"}); "/newuser-entry"});
m_stderr->readLine(); // Skip password prompt m_stderr->readLine(); // Skip password prompt
@ -294,6 +296,7 @@ void TestCli::testAdd()
QCOMPARE(entry->username(), QString("newuser")); QCOMPARE(entry->username(), QString("newuser"));
QCOMPARE(entry->url(), QString("https://example.com/")); QCOMPARE(entry->url(), QString("https://example.com/"));
QCOMPARE(entry->password().size(), 20); QCOMPARE(entry->password().size(), 20);
QCOMPARE(entry->notes(), QString("some notes"));
// Quiet option // Quiet option
setInput("a"); setInput("a");
@ -353,6 +356,18 @@ void TestCli::testAdd()
QCOMPARE(entry->username(), QString("newuser4")); QCOMPARE(entry->username(), QString("newuser4"));
QCOMPARE(entry->password().size(), 20); QCOMPARE(entry->password().size(), 20);
QVERIFY(!defaultPasswordClassesRegex.match(entry->password()).hasMatch()); QVERIFY(!defaultPasswordClassesRegex.match(entry->password()).hasMatch());
setInput("a");
execCmd(addCmd, {"add", "-u", "newuser5", "-n", "test\\nnew line", m_dbFile->fileName(), "/newuser-entry5"});
m_stderr->readLine(); // skip password prompt
QCOMPARE(m_stderr->readAll(), QByteArray(""));
QCOMPARE(m_stdout->readAll(), QByteArray("Successfully added entry newuser-entry5.\n"));
db = readDatabase();
entry = db->rootGroup()->findEntryByPath("/newuser-entry5");
QVERIFY(entry);
QCOMPARE(entry->username(), QString("newuser5"));
QCOMPARE(entry->notes(), QString("test\nnew line"));
} }
void TestCli::testAddGroup() void TestCli::testAddGroup()
@ -734,6 +749,8 @@ void TestCli::testEdit()
"newuser", "newuser",
"--url", "--url",
"https://otherurl.example.com/", "https://otherurl.example.com/",
"-n",
"newnotes",
"-t", "-t",
"newtitle", "newtitle",
m_dbFile->fileName(), m_dbFile->fileName(),
@ -746,6 +763,7 @@ void TestCli::testEdit()
QCOMPARE(entry->username(), QString("newuser")); QCOMPARE(entry->username(), QString("newuser"));
QCOMPARE(entry->url(), QString("https://otherurl.example.com/")); QCOMPARE(entry->url(), QString("https://otherurl.example.com/"));
QCOMPARE(entry->password(), QString("Password")); QCOMPARE(entry->password(), QString("Password"));
QCOMPARE(entry->notes(), QString("newnotes"));
// Quiet option // Quiet option
setInput("a"); setInput("a");
@ -803,6 +821,14 @@ void TestCli::testEdit()
entry = db->rootGroup()->findEntryByPath("/evennewertitle"); entry = db->rootGroup()->findEntryByPath("/evennewertitle");
QVERIFY(entry); QVERIFY(entry);
QCOMPARE(entry->password(), QString("newpassword")); QCOMPARE(entry->password(), QString("newpassword"));
// with line break in notes
setInput("a");
execCmd(editCmd, {"edit", m_dbFile->fileName(), "-n", "testing\\nline breaks", "/evennewertitle"});
db = readDatabase();
entry = db->rootGroup()->findEntryByPath("/evennewertitle");
QVERIFY(entry);
QCOMPARE(entry->notes(), QString("testing\nline breaks"));
} }
void TestCli::testEstimate_data() void TestCli::testEstimate_data()