Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions share/translations/keepassxc_en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4557,6 +4557,25 @@ This will leave your passwords and sensitive information vulnerable!
</translation>
</message>
</context>
<context>
<name>FdoSecrets::SettingsAliasesModel</name>
<message>
<source>No database selected.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>The database with this UUID is not currently opened.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Collection Alias</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Database</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FdoSecrets::SettingsClientModel</name>
<message>
Expand Down Expand Up @@ -10069,6 +10088,23 @@ This option is deprecated, use --set-key-file instead.</source>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This improves compatibility with certain applications which search for password without unlocking the database first.&lt;/p&gt;&lt;p&gt;But enabling this may also crash the client if the database can not be unlocked within a certain timeout. (Usually 25s, but may be a different value set in applications.) &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Collection Aliases</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Add</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Expose a database&apos;s exposed group under a specific alias. If the “default”-alias has not been configured here, it will point to the currently active database tab.
A database needs to be unlocked and have an exposed group configured to be selectable here.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsWidgetKeeShare</name>
Expand Down
1 change: 1 addition & 0 deletions src/core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
{Config::FdoSecrets_ConfirmDeleteItem, {QS("FdoSecrets/ConfirmDeleteItem"), Roaming, true}},
{Config::FdoSecrets_ConfirmAccessItem, {QS("FdoSecrets/ConfirmAccessItem"), Roaming, true}},
{Config::FdoSecrets_UnlockBeforeSearch, {QS("FdoSecrets/UnlockBeforeSearch"), Roaming, true}},
{Config::FdoSecrets_CollectionAliasDatabaseUUIDs, {QS("FdoSecrets/CollectionAliasDatabaseUUIDs"), Roaming, QVariantMap()}},

// KeeShare
{Config::KeeShare_QuietSuccess, {QS("KeeShare/QuietSuccess"), Roaming, false}},
Expand Down
1 change: 1 addition & 0 deletions src/core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ class Config : public QObject
FdoSecrets_ConfirmDeleteItem,
FdoSecrets_ConfirmAccessItem,
FdoSecrets_UnlockBeforeSearch,
FdoSecrets_CollectionAliasDatabaseUUIDs,

KeeShare_QuietSuccess,
KeeShare_Own,
Expand Down
32 changes: 32 additions & 0 deletions src/fdosecrets/FdoSecretsSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,36 @@ namespace FdoSecrets
db->metadata()->customData()->set(CustomData::FdoSecretsExposedGroup, group.toString());
}

QVariantMap FdoSecretsSettings::collectionAliases() const
{
return config()->get(Config::FdoSecrets_CollectionAliasDatabaseUUIDs).toMap();
}

void FdoSecretsSettings::setCollectionAliases(const QVariantMap& aliases)
{
config()->set(Config::FdoSecrets_CollectionAliasDatabaseUUIDs, aliases);
}

void FdoSecretsSettings::setCollectionAlias(QString alias, QUuid publicUuid)
{
auto aliases = collectionAliases();
auto it = std::as_const(aliases).lowerBound(alias);
if (it != aliases.cend() && *it == publicUuid)
return;
aliases.insert(std::move(it), std::move(alias), std::move(publicUuid));
// always signals collectionAliasesChanged(), so return above if nothing changed
setCollectionAliases(std::move(aliases));
}

void FdoSecretsSettings::removeCollectionAlias(const QString& alias, const QUuid& publicUuid)
{
auto aliases = collectionAliases();
auto it = aliases.find(alias);
if (it == aliases.end() || it->toUuid() != publicUuid)
return;
aliases.erase(std::move(it));
// always signals collectionAliasesChanged(), so return above if nothing changed
setCollectionAliases(std::move(aliases));
}

} // namespace FdoSecrets
6 changes: 6 additions & 0 deletions src/fdosecrets/FdoSecretsSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include <QSharedPointer>
#include <QUuid>
#include <QVariantMap>

class Database;

Expand Down Expand Up @@ -47,6 +48,11 @@ namespace FdoSecrets
bool unlockBeforeSearch() const;
void setUnlockBeforeSearch(bool unlockBeforeSearch);

QVariantMap collectionAliases() const;
void setCollectionAliases(const QVariantMap& aliases);
void setCollectionAlias(QString alias, QUuid publicUuuid);
void removeCollectionAlias(const QString& alias, const QUuid& publicUuid);

// Per db settings

QUuid exposedGroup(const QSharedPointer<Database>& db) const;
Expand Down
66 changes: 64 additions & 2 deletions src/fdosecrets/objects/Service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ namespace FdoSecrets
onDatabaseTabOpened(dbWidget, true);
});

// when a new database is opened, apply it's aliases
connect(m_databases.data(), &DatabaseTabWidget::databaseOpened, this, &Service::applyCollectionAliasSettings);
// apply aliases from settings, when they change
connect(config(), &Config::changed, this, &Service::handleSettingsChanged);

// make default alias track current activated database
connect(m_databases.data(), &DatabaseTabWidget::activeDatabaseChanged, this, &Service::ensureDefaultAlias);

Expand Down Expand Up @@ -163,7 +168,7 @@ namespace FdoSecrets

void Service::ensureDefaultAlias()
{
if (m_insideEnsureDefaultAlias) {
if (m_insideEnsureDefaultAlias || m_explicitlyDefinedDefaultAlias) {
return;
}

Expand Down Expand Up @@ -463,6 +468,51 @@ namespace FdoSecrets
return collection->addAlias(name);
}

void Service::handleSettingsChanged(Config::ConfigKey key)
{
if (key == Config::FdoSecrets_CollectionAliasDatabaseUUIDs) {
applyCollectionAliasSettings();
}
}

void Service::applyCollectionAliasSettings()
{
auto aliases = settings()->collectionAliases();
// add missing aliases
m_explicitlyDefinedDefaultAlias = false; // is there still an explicit default alias?
for (auto it = aliases.cbegin(); it != aliases.cend(); ++it) {
auto& alias = it.key();
if (alias == DEFAULT_ALIAS) {
m_explicitlyDefinedDefaultAlias = true; // will disable this->ensureDefaultAlias()
}

auto database = m_databases->databaseWidgetFromPublicUuid(it->toUuid());
if (!database)
continue; // cannot add alias to database not currently opened
auto collection = m_dbToCollection.value(database, nullptr);
if (!collection)
continue;

collection->addAlias(alias).okOrDie(); // is idempotent
}
// remove unexpected aliases
QList<std::pair<QString, Collection*>> aliasesToRemove = {};
for (auto it = m_aliases.cbegin(); it != m_aliases.cend(); ++it) {
auto& alias = it.key();
Collection* const isCollection = *it; // the collection this alias currently points to
auto shouldUuid = aliases.value(alias, {}).toUuid(); // the UUID this alias should point to
if (shouldUuid.isNull() || isCollection->backend()->database()->publicUuid() != shouldUuid) {
// don't call isCollection->removeAlias, to avoid invalidating the iterator it
aliasesToRemove.append(std::make_pair(alias, isCollection));
}
}
for (auto toRemove : aliasesToRemove) {
toRemove.second->removeAlias(toRemove.first).okOrDie();
}
// select default alias, if not explicitly defined
ensureDefaultAlias();
}

Collection* Service::findCollection(const QString& alias) const
{
if (alias.isEmpty()) {
Expand Down Expand Up @@ -495,11 +545,23 @@ namespace FdoSecrets
{
auto coll = qobject_cast<Collection*>(sender());
m_aliases[alias] = coll;
if (!(m_insideEnsureDefaultAlias && alias == DEFAULT_ALIAS)) {
// store dynamically created aliases to settings
settings()->setCollectionAlias(alias, coll->backend()->database()->publicUuid());
}
}

void Service::onCollectionAliasRemoved(const QString& alias)
{
m_aliases.remove(alias);
auto coll = m_aliases.take(alias);
if (coll
&& !(m_insideEnsureDefaultAlias && alias == DEFAULT_ALIAS)
// don't persistently remove alias after collectionAboutToDelete() was emitted
&& m_dbToCollection.contains(coll->backend())) {
// pass publicUuid, to avoid removing alias x to database A, when
// applyCollectionAliasSettings() removes x->B while applying this very x->A
settings()->removeCollectionAlias(alias, coll->backend()->database()->publicUuid());
}
ensureDefaultAlias();
}

Expand Down
5 changes: 5 additions & 0 deletions src/fdosecrets/objects/Service.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#ifndef KEEPASSXC_FDOSECRETS_SERVICE_H
#define KEEPASSXC_FDOSECRETS_SERVICE_H

#include "core/Config.h"
#include "fdosecrets/dbus/DBusClient.h"
#include "fdosecrets/dbus/DBusObject.h"

Expand Down Expand Up @@ -143,6 +144,9 @@ namespace FdoSecrets

void onCollectionAliasRemoved(const QString& alias);

void handleSettingsChanged(Config::ConfigKey key);
void applyCollectionAliasSettings();

private:
bool initialize();

Expand Down Expand Up @@ -173,6 +177,7 @@ namespace FdoSecrets
QList<Session*> m_sessions{};

bool m_insideEnsureDefaultAlias{false};
bool m_explicitlyDefinedDefaultAlias{false};
bool m_unlockingAnyDatabase{false};
// list of db currently has unlock dialog shown
QHash<const DatabaseWidget*, QMetaObject::Connection> m_unlockingDb{};
Expand Down
Loading