mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Allow creating new groups with Browser Integration
Added a confirmation dialog
This commit is contained in:
parent
84f5adb24a
commit
14e868d2f7
@ -88,6 +88,8 @@ QJsonObject BrowserAction::handleAction(const QJsonObject& json)
|
|||||||
return handleLockDatabase(json, action);
|
return handleLockDatabase(json, action);
|
||||||
} else if (action.compare("get-database-groups", Qt::CaseSensitive) == 0) {
|
} else if (action.compare("get-database-groups", Qt::CaseSensitive) == 0) {
|
||||||
return handleGetDatabaseGroups(json, action);
|
return handleGetDatabaseGroups(json, action);
|
||||||
|
} else if (action.compare("create-new-group", Qt::CaseSensitive) == 0) {
|
||||||
|
return handleCreateNewGroup(json, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action was not recognized
|
// Action was not recognized
|
||||||
@ -407,6 +409,42 @@ QJsonObject BrowserAction::handleGetDatabaseGroups(const QJsonObject& json, cons
|
|||||||
return buildResponse(action, message, newNonce);
|
return buildResponse(action, message, newNonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QJsonObject BrowserAction::handleCreateNewGroup(const QJsonObject& json, const QString& action)
|
||||||
|
{
|
||||||
|
const QString hash = getDatabaseHash();
|
||||||
|
const QString nonce = json.value("nonce").toString();
|
||||||
|
const QString encrypted = json.value("message").toString();
|
||||||
|
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
if (!m_associated) {
|
||||||
|
return getErrorReply(action, ERROR_KEEPASS_ASSOCIATION_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QJsonObject decrypted = decryptMessage(encrypted, nonce);
|
||||||
|
if (decrypted.isEmpty()) {
|
||||||
|
return getErrorReply(action, ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString command = decrypted.value("action").toString();
|
||||||
|
if (command.isEmpty() || command.compare("create-new-group", Qt::CaseSensitive) != 0) {
|
||||||
|
return getErrorReply(action, ERROR_KEEPASS_INCORRECT_ACTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString group = decrypted.value("groupName").toString();
|
||||||
|
const QJsonObject newGroup = m_browserService.createNewGroup(group);
|
||||||
|
if (newGroup.isEmpty() || newGroup["name"].toString().isEmpty() || newGroup["uuid"].toString().isEmpty()) {
|
||||||
|
return getErrorReply(action, ERROR_KEEPASS_CANNOT_CREATE_NEW_GROUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString newNonce = incrementNonce(nonce);
|
||||||
|
|
||||||
|
QJsonObject message = buildMessage(newNonce);
|
||||||
|
message["name"] = newGroup["name"];
|
||||||
|
message["uuid"] = newGroup["uuid"];
|
||||||
|
|
||||||
|
return buildResponse(action, message, newNonce);
|
||||||
|
}
|
||||||
|
|
||||||
QJsonObject BrowserAction::getErrorReply(const QString& action, const int errorCode) const
|
QJsonObject BrowserAction::getErrorReply(const QString& action, const int errorCode) const
|
||||||
{
|
{
|
||||||
QJsonObject response;
|
QJsonObject response;
|
||||||
@ -468,6 +506,8 @@ QString BrowserAction::getErrorMessage(const int errorCode) const
|
|||||||
return QObject::tr("No logins found");
|
return QObject::tr("No logins found");
|
||||||
case ERROR_KEEPASS_NO_GROUPS_FOUND:
|
case ERROR_KEEPASS_NO_GROUPS_FOUND:
|
||||||
return QObject::tr("No groups found");
|
return QObject::tr("No groups found");
|
||||||
|
case ERROR_KEEPASS_CANNOT_CREATE_NEW_GROUP:
|
||||||
|
return QObject::tr("Cannot create new group");
|
||||||
default:
|
default:
|
||||||
return QObject::tr("Unknown error");
|
return QObject::tr("Unknown error");
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,8 @@ class BrowserAction : public QObject
|
|||||||
ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED = 13,
|
ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED = 13,
|
||||||
ERROR_KEEPASS_NO_URL_PROVIDED = 14,
|
ERROR_KEEPASS_NO_URL_PROVIDED = 14,
|
||||||
ERROR_KEEPASS_NO_LOGINS_FOUND = 15,
|
ERROR_KEEPASS_NO_LOGINS_FOUND = 15,
|
||||||
ERROR_KEEPASS_NO_GROUPS_FOUND = 16
|
ERROR_KEEPASS_NO_GROUPS_FOUND = 16,
|
||||||
|
ERROR_KEEPASS_CANNOT_CREATE_NEW_GROUP = 17
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -66,6 +67,7 @@ private:
|
|||||||
QJsonObject handleSetLogin(const QJsonObject& json, const QString& action);
|
QJsonObject handleSetLogin(const QJsonObject& json, const QString& action);
|
||||||
QJsonObject handleLockDatabase(const QJsonObject& json, const QString& action);
|
QJsonObject handleLockDatabase(const QJsonObject& json, const QString& action);
|
||||||
QJsonObject handleGetDatabaseGroups(const QJsonObject& json, const QString& action);
|
QJsonObject handleGetDatabaseGroups(const QJsonObject& json, const QString& action);
|
||||||
|
QJsonObject handleCreateNewGroup(const QJsonObject& json, const QString& action);
|
||||||
|
|
||||||
QJsonObject buildMessage(const QString& nonce) const;
|
QJsonObject buildMessage(const QString& nonce) const;
|
||||||
QJsonObject buildResponse(const QString& action, const QJsonObject& message, const QString& nonce);
|
QJsonObject buildResponse(const QString& action, const QJsonObject& message, const QString& nonce);
|
||||||
|
@ -150,7 +150,7 @@ QString BrowserService::getDatabaseRecycleBinUuid()
|
|||||||
return recycleBin->uuidToHex();
|
return recycleBin->uuidToHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonArray BrowserService::addChildrenToGroup(Group* group)
|
QJsonArray BrowserService::getChildrenFromGroup(Group* group)
|
||||||
{
|
{
|
||||||
QJsonArray groupList;
|
QJsonArray groupList;
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ QJsonArray BrowserService::addChildrenToGroup(Group* group)
|
|||||||
QJsonObject jsonGroup;
|
QJsonObject jsonGroup;
|
||||||
jsonGroup["name"] = c->name();
|
jsonGroup["name"] = c->name();
|
||||||
jsonGroup["uuid"] = Tools::uuidToHex(c->uuid());
|
jsonGroup["uuid"] = Tools::uuidToHex(c->uuid());
|
||||||
jsonGroup["children"] = addChildrenToGroup(c);
|
jsonGroup["children"] = getChildrenFromGroup(c);
|
||||||
groupList.push_back(jsonGroup);
|
groupList.push_back(jsonGroup);
|
||||||
}
|
}
|
||||||
return groupList;
|
return groupList;
|
||||||
@ -187,7 +187,7 @@ QJsonObject BrowserService::getDatabaseGroups()
|
|||||||
QJsonObject root;
|
QJsonObject root;
|
||||||
root["name"] = rootGroup->name();
|
root["name"] = rootGroup->name();
|
||||||
root["uuid"] = Tools::uuidToHex(rootGroup->uuid());
|
root["uuid"] = Tools::uuidToHex(rootGroup->uuid());
|
||||||
root["children"] = addChildrenToGroup(rootGroup);
|
root["children"] = getChildrenFromGroup(rootGroup);
|
||||||
|
|
||||||
QJsonArray groups;
|
QJsonArray groups;
|
||||||
groups.push_back(root);
|
groups.push_back(root);
|
||||||
@ -198,6 +198,80 @@ QJsonObject BrowserService::getDatabaseGroups()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QJsonObject BrowserService::createNewGroup(const QString& groupName)
|
||||||
|
{
|
||||||
|
QJsonObject result;
|
||||||
|
if (thread() != QThread::currentThread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "createNewGroup", Qt::BlockingQueuedConnection,
|
||||||
|
Q_RETURN_ARG(QJsonObject, result), Q_ARG(QString, groupName));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto db = getDatabase();
|
||||||
|
if (!db) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Group* rootGroup = db->rootGroup();
|
||||||
|
if (!rootGroup) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto group = rootGroup->findGroupByPath(groupName);
|
||||||
|
|
||||||
|
// Group already exists
|
||||||
|
if (group) {
|
||||||
|
result["name"] = group->name();
|
||||||
|
result["uuid"] = Tools::uuidToHex(group->uuid());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dialogResult = MessageBox::warning(nullptr,
|
||||||
|
tr("KeePassXC: Create a new group"),
|
||||||
|
tr("A request for creating a new group \"%1\" has been received.\n"
|
||||||
|
"Do you want to create this group?\n").arg(groupName),
|
||||||
|
MessageBox::Yes | MessageBox::No);
|
||||||
|
|
||||||
|
if (dialogResult != MessageBox::Yes) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString name, uuid;
|
||||||
|
Group* previousGroup = rootGroup;
|
||||||
|
auto groups = groupName.split("/");
|
||||||
|
|
||||||
|
// Returns the group name based on depth
|
||||||
|
auto getGroupName = [&](int depth) {
|
||||||
|
QString gName;
|
||||||
|
for (int i = 0; i < depth+1; ++i) {
|
||||||
|
gName.append((i == 0 ? "" : "/") + groups[i]);
|
||||||
|
}
|
||||||
|
return gName;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create new group(s) always when the path is not found
|
||||||
|
for (int i = 0; i < groups.length(); ++i) {
|
||||||
|
QString gName = getGroupName(i);
|
||||||
|
auto tempGroup = rootGroup->findGroupByPath(gName);
|
||||||
|
if (!tempGroup) {
|
||||||
|
Group* newGroup = new Group();
|
||||||
|
newGroup->setName(groups[i]);
|
||||||
|
newGroup->setUuid(QUuid::createUuid());
|
||||||
|
newGroup->setParent(previousGroup);
|
||||||
|
name = newGroup->name();
|
||||||
|
uuid = Tools::uuidToHex(newGroup->uuid());
|
||||||
|
previousGroup = newGroup;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
previousGroup = tempGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
result["name"] = name;
|
||||||
|
result["uuid"] = uuid;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QString BrowserService::storeKey(const QString& key)
|
QString BrowserService::storeKey(const QString& key)
|
||||||
{
|
{
|
||||||
QString id;
|
QString id;
|
||||||
|
@ -45,6 +45,7 @@ public:
|
|||||||
QString getDatabaseRootUuid();
|
QString getDatabaseRootUuid();
|
||||||
QString getDatabaseRecycleBinUuid();
|
QString getDatabaseRecycleBinUuid();
|
||||||
QJsonObject getDatabaseGroups();
|
QJsonObject getDatabaseGroups();
|
||||||
|
QJsonObject createNewGroup(const QString& groupName);
|
||||||
QString getKey(const QString& id);
|
QString getKey(const QString& id);
|
||||||
void addEntry(const QString& id,
|
void addEntry(const QString& id,
|
||||||
const QString& login,
|
const QString& login,
|
||||||
@ -121,7 +122,7 @@ private:
|
|||||||
QString baseDomain(const QString& url) const;
|
QString baseDomain(const QString& url) const;
|
||||||
QSharedPointer<Database> getDatabase();
|
QSharedPointer<Database> getDatabase();
|
||||||
QSharedPointer<Database> selectedDatabase();
|
QSharedPointer<Database> selectedDatabase();
|
||||||
QJsonArray addChildrenToGroup(Group* group);
|
QJsonArray getChildrenFromGroup(Group* group);
|
||||||
bool moveSettingsToCustomData(Entry* entry, const QString& name) const;
|
bool moveSettingsToCustomData(Entry* entry, const QString& name) const;
|
||||||
int moveKeysToCustomData(Entry* entry, const QSharedPointer<Database>& db) const;
|
int moveKeysToCustomData(Entry* entry, const QSharedPointer<Database>& db) const;
|
||||||
bool checkLegacySettings();
|
bool checkLegacySettings();
|
||||||
|
Loading…
Reference in New Issue
Block a user