mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-03-29 17:38:02 -04:00
Allow groups to restrict by browser integration key (#6437)
This commit is contained in:
parent
7bfe9065cf
commit
884386c924
@ -953,7 +953,7 @@ Do you want to overwrite the Passkey in %1 - %2?</source>
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>KeePassXC - New key association request</source>
|
<source>Disable</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
@ -972,6 +972,10 @@ Do you want to overwrite the Passkey in %1 - %2?</source>
|
|||||||
<source>KeePassXC - Delete entry</source>
|
<source>KeePassXC - Delete entry</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>KeePassXC - New key association request</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>BrowserSettingsWidget</name>
|
<name>BrowserSettingsWidget</name>
|
||||||
@ -3209,6 +3213,14 @@ Would you like to correct it?</source>
|
|||||||
<source>Omit WWW subdomain from matching toggle for this and sub groups</source>
|
<source>Omit WWW subdomain from matching toggle for this and sub groups</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Restrict matching to given browser key:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Restrict matching to given browser key toggle for this and sub groups</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>EditGroupWidgetKeeShare</name>
|
<name>EditGroupWidgetKeeShare</name>
|
||||||
|
@ -64,6 +64,7 @@ const QString BrowserService::OPTION_HIDE_ENTRY = QStringLiteral("BrowserHideEnt
|
|||||||
const QString BrowserService::OPTION_ONLY_HTTP_AUTH = QStringLiteral("BrowserOnlyHttpAuth");
|
const QString BrowserService::OPTION_ONLY_HTTP_AUTH = QStringLiteral("BrowserOnlyHttpAuth");
|
||||||
const QString BrowserService::OPTION_NOT_HTTP_AUTH = QStringLiteral("BrowserNotHttpAuth");
|
const QString BrowserService::OPTION_NOT_HTTP_AUTH = QStringLiteral("BrowserNotHttpAuth");
|
||||||
const QString BrowserService::OPTION_OMIT_WWW = QStringLiteral("BrowserOmitWww");
|
const QString BrowserService::OPTION_OMIT_WWW = QStringLiteral("BrowserOmitWww");
|
||||||
|
const QString BrowserService::OPTION_RESTRICT_KEY = QStringLiteral("BrowserRestrictKey");
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(BrowserService, s_browserService);
|
Q_GLOBAL_STATIC(BrowserService, s_browserService);
|
||||||
|
|
||||||
@ -947,6 +948,7 @@ bool BrowserService::deleteEntry(const QString& uuid)
|
|||||||
QList<Entry*> BrowserService::searchEntries(const QSharedPointer<Database>& db,
|
QList<Entry*> BrowserService::searchEntries(const QSharedPointer<Database>& db,
|
||||||
const QString& siteUrl,
|
const QString& siteUrl,
|
||||||
const QString& formUrl,
|
const QString& formUrl,
|
||||||
|
const QStringList& keys,
|
||||||
bool passkey)
|
bool passkey)
|
||||||
{
|
{
|
||||||
QList<Entry*> entries;
|
QList<Entry*> entries;
|
||||||
@ -961,6 +963,12 @@ QList<Entry*> BrowserService::searchEntries(const QSharedPointer<Database>& db,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a key restriction is specified and not contained in the keys list then skip this group.
|
||||||
|
auto restrictKey = group->resolveCustomDataString(BrowserService::OPTION_RESTRICT_KEY);
|
||||||
|
if (!restrictKey.isEmpty() && !keys.contains(restrictKey)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const auto omitWwwSubdomain =
|
const auto omitWwwSubdomain =
|
||||||
group->resolveCustomDataTriState(BrowserService::OPTION_OMIT_WWW) == Group::Enable;
|
group->resolveCustomDataTriState(BrowserService::OPTION_OMIT_WWW) == Group::Enable;
|
||||||
|
|
||||||
@ -997,30 +1005,35 @@ QList<Entry*> BrowserService::searchEntries(const QString& siteUrl,
|
|||||||
const StringPairList& keyList,
|
const StringPairList& keyList,
|
||||||
bool passkey)
|
bool passkey)
|
||||||
{
|
{
|
||||||
// Check if database is connected with KeePassXC-Browser
|
// Check if database is connected with KeePassXC-Browser. If so, return browser key (otherwise empty)
|
||||||
auto databaseConnected = [&](const QSharedPointer<Database>& db) {
|
auto databaseConnected = [&](const QSharedPointer<Database>& db) {
|
||||||
for (const StringPair& keyPair : keyList) {
|
for (const StringPair& keyPair : keyList) {
|
||||||
QString key = db->metadata()->customData()->value(CustomData::BrowserKeyPrefix + keyPair.first);
|
QString key = db->metadata()->customData()->value(CustomData::BrowserKeyPrefix + keyPair.first);
|
||||||
if (!key.isEmpty() && keyPair.second == key) {
|
if (!key.isEmpty() && keyPair.second == key) {
|
||||||
return true;
|
return keyPair.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return QString();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the list of databases to search
|
// Get the list of databases to search
|
||||||
QList<QSharedPointer<Database>> databases;
|
QList<QSharedPointer<Database>> databases;
|
||||||
|
QStringList keys;
|
||||||
if (browserSettings()->searchInAllDatabases()) {
|
if (browserSettings()->searchInAllDatabases()) {
|
||||||
for (auto dbWidget : getMainWindow()->getOpenDatabases()) {
|
for (auto dbWidget : getMainWindow()->getOpenDatabases()) {
|
||||||
auto db = dbWidget->database();
|
auto db = dbWidget->database();
|
||||||
if (db && databaseConnected(dbWidget->database())) {
|
auto key = databaseConnected(dbWidget->database());
|
||||||
|
if (db && !key.isEmpty()) {
|
||||||
databases << db;
|
databases << db;
|
||||||
|
keys << key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const auto& db = getDatabase();
|
const auto& db = getDatabase();
|
||||||
if (databaseConnected(db)) {
|
auto key = databaseConnected(db);
|
||||||
|
if (!key.isEmpty()) {
|
||||||
databases << db;
|
databases << db;
|
||||||
|
keys << key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1029,13 +1042,18 @@ QList<Entry*> BrowserService::searchEntries(const QString& siteUrl,
|
|||||||
QList<Entry*> entries;
|
QList<Entry*> entries;
|
||||||
do {
|
do {
|
||||||
for (const auto& db : databases) {
|
for (const auto& db : databases) {
|
||||||
entries << searchEntries(db, siteUrl, formUrl, passkey);
|
entries << searchEntries(db, siteUrl, formUrl, keys, passkey);
|
||||||
}
|
}
|
||||||
} while (entries.isEmpty() && removeFirstDomain(hostname));
|
} while (entries.isEmpty() && removeFirstDomain(hostname));
|
||||||
|
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString BrowserService::decodeCustomDataRestrictKey(const QString& key)
|
||||||
|
{
|
||||||
|
return key.isEmpty() ? tr("Disable") : key;
|
||||||
|
}
|
||||||
|
|
||||||
void BrowserService::requestGlobalAutoType(const QString& search)
|
void BrowserService::requestGlobalAutoType(const QString& search)
|
||||||
{
|
{
|
||||||
emit osUtils->globalShortcutTriggered("autotype", search);
|
emit osUtils->globalShortcutTriggered("autotype", search);
|
||||||
|
@ -119,6 +119,8 @@ public:
|
|||||||
QJsonArray findEntries(const EntryParameters& entryParameters, const StringPairList& keyList, bool* entriesFound);
|
QJsonArray findEntries(const EntryParameters& entryParameters, const StringPairList& keyList, bool* entriesFound);
|
||||||
void requestGlobalAutoType(const QString& search);
|
void requestGlobalAutoType(const QString& search);
|
||||||
|
|
||||||
|
static QString decodeCustomDataRestrictKey(const QString& key);
|
||||||
|
|
||||||
static const QString KEEPASSXCBROWSER_NAME;
|
static const QString KEEPASSXCBROWSER_NAME;
|
||||||
static const QString KEEPASSXCBROWSER_OLD_NAME;
|
static const QString KEEPASSXCBROWSER_OLD_NAME;
|
||||||
static const QString OPTION_SKIP_AUTO_SUBMIT;
|
static const QString OPTION_SKIP_AUTO_SUBMIT;
|
||||||
@ -126,6 +128,7 @@ public:
|
|||||||
static const QString OPTION_ONLY_HTTP_AUTH;
|
static const QString OPTION_ONLY_HTTP_AUTH;
|
||||||
static const QString OPTION_NOT_HTTP_AUTH;
|
static const QString OPTION_NOT_HTTP_AUTH;
|
||||||
static const QString OPTION_OMIT_WWW;
|
static const QString OPTION_OMIT_WWW;
|
||||||
|
static const QString OPTION_RESTRICT_KEY;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void requestUnlock();
|
void requestUnlock();
|
||||||
@ -157,6 +160,7 @@ private:
|
|||||||
QList<Entry*> searchEntries(const QSharedPointer<Database>& db,
|
QList<Entry*> searchEntries(const QSharedPointer<Database>& db,
|
||||||
const QString& siteUrl,
|
const QString& siteUrl,
|
||||||
const QString& formUrl,
|
const QString& formUrl,
|
||||||
|
const QStringList& keys = {},
|
||||||
bool passkey = false);
|
bool passkey = false);
|
||||||
QList<Entry*>
|
QList<Entry*>
|
||||||
searchEntries(const QString& siteUrl, const QString& formUrl, const StringPairList& keyList, bool passkey = false);
|
searchEntries(const QString& siteUrl, const QString& formUrl, const StringPairList& keyList, bool passkey = false);
|
||||||
|
@ -288,6 +288,21 @@ void Group::setCustomDataTriState(const QString& key, const Group::TriState& val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note that this returns an empty string both if the key is missing *or* if the key is present but value is empty.
|
||||||
|
QString Group::resolveCustomDataString(const QString& key, bool checkParent) const
|
||||||
|
{
|
||||||
|
// If not defined, check our parent up to the root group
|
||||||
|
if (!m_customData->contains(key)) {
|
||||||
|
if (!m_parent || !checkParent) {
|
||||||
|
return QString();
|
||||||
|
} else {
|
||||||
|
return m_parent->resolveCustomDataString(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_customData->value(key);
|
||||||
|
}
|
||||||
|
|
||||||
bool Group::equals(const Group* other, CompareItemOptions options) const
|
bool Group::equals(const Group* other, CompareItemOptions options) const
|
||||||
{
|
{
|
||||||
if (!other) {
|
if (!other) {
|
||||||
|
@ -102,6 +102,7 @@ public:
|
|||||||
const CustomData* customData() const;
|
const CustomData* customData() const;
|
||||||
Group::TriState resolveCustomDataTriState(const QString& key, bool checkParent = true) const;
|
Group::TriState resolveCustomDataTriState(const QString& key, bool checkParent = true) const;
|
||||||
void setCustomDataTriState(const QString& key, const Group::TriState& value);
|
void setCustomDataTriState(const QString& key, const Group::TriState& value);
|
||||||
|
QString resolveCustomDataString(const QString& key, bool checkParent = true) const;
|
||||||
const Group* previousParentGroup() const;
|
const Group* previousParentGroup() const;
|
||||||
QUuid previousParentGroupUuid() const;
|
QUuid previousParentGroupUuid() const;
|
||||||
|
|
||||||
|
@ -196,6 +196,7 @@ void EditGroupWidget::loadGroup(Group* group, bool create, const QSharedPointer<
|
|||||||
auto inheritOnlyHttp = false;
|
auto inheritOnlyHttp = false;
|
||||||
auto inheritNoHttp = false;
|
auto inheritNoHttp = false;
|
||||||
auto inheritOmitWww = false;
|
auto inheritOmitWww = false;
|
||||||
|
auto inheritRestrictKey = QString();
|
||||||
|
|
||||||
auto parent = group->parentGroup();
|
auto parent = group->parentGroup();
|
||||||
if (parent) {
|
if (parent) {
|
||||||
@ -204,6 +205,7 @@ void EditGroupWidget::loadGroup(Group* group, bool create, const QSharedPointer<
|
|||||||
inheritOnlyHttp = parent->resolveCustomDataTriState(BrowserService::OPTION_ONLY_HTTP_AUTH);
|
inheritOnlyHttp = parent->resolveCustomDataTriState(BrowserService::OPTION_ONLY_HTTP_AUTH);
|
||||||
inheritNoHttp = parent->resolveCustomDataTriState(BrowserService::OPTION_NOT_HTTP_AUTH);
|
inheritNoHttp = parent->resolveCustomDataTriState(BrowserService::OPTION_NOT_HTTP_AUTH);
|
||||||
inheritOmitWww = parent->resolveCustomDataTriState(BrowserService::OPTION_OMIT_WWW);
|
inheritOmitWww = parent->resolveCustomDataTriState(BrowserService::OPTION_OMIT_WWW);
|
||||||
|
inheritRestrictKey = parent->resolveCustomDataString(BrowserService::OPTION_RESTRICT_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the page has not been created at all, some of the elements are null
|
// If the page has not been created at all, some of the elements are null
|
||||||
@ -219,6 +221,7 @@ void EditGroupWidget::loadGroup(Group* group, bool create, const QSharedPointer<
|
|||||||
addTriStateItems(m_browserUi->browserIntegrationOnlyHttpAuthComboBox, inheritOnlyHttp);
|
addTriStateItems(m_browserUi->browserIntegrationOnlyHttpAuthComboBox, inheritOnlyHttp);
|
||||||
addTriStateItems(m_browserUi->browserIntegrationNotHttpAuthComboBox, inheritNoHttp);
|
addTriStateItems(m_browserUi->browserIntegrationNotHttpAuthComboBox, inheritNoHttp);
|
||||||
addTriStateItems(m_browserUi->browserIntegrationOmitWwwCombobox, inheritOmitWww);
|
addTriStateItems(m_browserUi->browserIntegrationOmitWwwCombobox, inheritOmitWww);
|
||||||
|
addRestrictKeyComboBoxItems(m_db->metadata()->customData()->keys(), inheritRestrictKey);
|
||||||
|
|
||||||
m_browserUi->browserIntegrationHideEntriesComboBox->setCurrentIndex(
|
m_browserUi->browserIntegrationHideEntriesComboBox->setCurrentIndex(
|
||||||
indexFromTriState(group->resolveCustomDataTriState(BrowserService::OPTION_HIDE_ENTRY, false)));
|
indexFromTriState(group->resolveCustomDataTriState(BrowserService::OPTION_HIDE_ENTRY, false)));
|
||||||
@ -230,6 +233,7 @@ void EditGroupWidget::loadGroup(Group* group, bool create, const QSharedPointer<
|
|||||||
indexFromTriState(group->resolveCustomDataTriState(BrowserService::OPTION_NOT_HTTP_AUTH, false)));
|
indexFromTriState(group->resolveCustomDataTriState(BrowserService::OPTION_NOT_HTTP_AUTH, false)));
|
||||||
m_browserUi->browserIntegrationOmitWwwCombobox->setCurrentIndex(
|
m_browserUi->browserIntegrationOmitWwwCombobox->setCurrentIndex(
|
||||||
indexFromTriState(group->resolveCustomDataTriState(BrowserService::OPTION_OMIT_WWW, false)));
|
indexFromTriState(group->resolveCustomDataTriState(BrowserService::OPTION_OMIT_WWW, false)));
|
||||||
|
setRestrictKeyComboBoxIndex(group);
|
||||||
} else if (hasPage(m_browserWidget)) {
|
} else if (hasPage(m_browserWidget)) {
|
||||||
setPageHidden(m_browserWidget, true);
|
setPageHidden(m_browserWidget, true);
|
||||||
}
|
}
|
||||||
@ -303,6 +307,7 @@ void EditGroupWidget::apply()
|
|||||||
m_temporaryGroup->setCustomDataTriState(
|
m_temporaryGroup->setCustomDataTriState(
|
||||||
BrowserService::OPTION_OMIT_WWW,
|
BrowserService::OPTION_OMIT_WWW,
|
||||||
triStateFromIndex(m_browserUi->browserIntegrationOmitWwwCombobox->currentIndex()));
|
triStateFromIndex(m_browserUi->browserIntegrationOmitWwwCombobox->currentIndex()));
|
||||||
|
setRestrictKeyCustomData(m_temporaryGroup->customData());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -444,3 +449,58 @@ Group::TriState EditGroupWidget::triStateFromIndex(int index)
|
|||||||
return Group::Inherit;
|
return Group::Inherit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
void EditGroupWidget::addRestrictKeyComboBoxItems(QStringList const& keyList, QString inheritValue)
|
||||||
|
{
|
||||||
|
auto comboBox = m_browserUi->browserIntegrationRestrictKeyCombobox;
|
||||||
|
|
||||||
|
comboBox->clear();
|
||||||
|
comboBox->addItem(
|
||||||
|
tr("Inherit from parent group (%1)").arg(BrowserService::decodeCustomDataRestrictKey(inheritValue)));
|
||||||
|
comboBox->addItem(tr("Disable"));
|
||||||
|
|
||||||
|
comboBox->insertSeparator(2);
|
||||||
|
|
||||||
|
// Add all the browser keys to the combobox
|
||||||
|
for (const QString& key : keyList) {
|
||||||
|
if (key.startsWith(CustomData::BrowserKeyPrefix)) {
|
||||||
|
auto strippedKey = key;
|
||||||
|
strippedKey.remove(CustomData::BrowserKeyPrefix);
|
||||||
|
comboBox->addItem(strippedKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditGroupWidget::setRestrictKeyComboBoxIndex(const Group* group)
|
||||||
|
{
|
||||||
|
auto comboBox = m_browserUi->browserIntegrationRestrictKeyCombobox;
|
||||||
|
|
||||||
|
if (!group || !group->customData()->contains(BrowserService::OPTION_RESTRICT_KEY)) {
|
||||||
|
comboBox->setCurrentIndex(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto key = group->customData()->value(BrowserService::OPTION_RESTRICT_KEY);
|
||||||
|
if (key.isEmpty()) {
|
||||||
|
comboBox->setCurrentIndex(1);
|
||||||
|
} else {
|
||||||
|
comboBox->setCurrentText(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the customData regarding OPTION_RESTRICT_KEY
|
||||||
|
void EditGroupWidget::setRestrictKeyCustomData(CustomData* customData)
|
||||||
|
{
|
||||||
|
auto comboBox = m_browserUi->browserIntegrationRestrictKeyCombobox;
|
||||||
|
auto key = BrowserService::OPTION_RESTRICT_KEY;
|
||||||
|
auto idx = comboBox->currentIndex();
|
||||||
|
if (idx == 0) {
|
||||||
|
customData->remove(key);
|
||||||
|
} else if (idx == 1) {
|
||||||
|
customData->set(key, QString());
|
||||||
|
} else {
|
||||||
|
customData->set(key, comboBox->currentText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -81,6 +81,10 @@ private:
|
|||||||
Group::TriState triStateFromIndex(int index);
|
Group::TriState triStateFromIndex(int index);
|
||||||
void setupModifiedTracking();
|
void setupModifiedTracking();
|
||||||
|
|
||||||
|
void addRestrictKeyComboBoxItems(QStringList const& keyList, QString inheritValue);
|
||||||
|
void setRestrictKeyComboBoxIndex(const Group* group);
|
||||||
|
void setRestrictKeyCustomData(CustomData* customData);
|
||||||
|
|
||||||
const QScopedPointer<Ui::EditGroupWidgetMain> m_mainUi;
|
const QScopedPointer<Ui::EditGroupWidgetMain> m_mainUi;
|
||||||
|
|
||||||
QPointer<QScrollArea> m_editGroupWidgetMain;
|
QPointer<QScrollArea> m_editGroupWidgetMain;
|
||||||
|
@ -136,6 +136,23 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="browserIntegrationRestrictKey">
|
||||||
|
<property name="text">
|
||||||
|
<string>Restrict matching to given browser key:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QComboBox" name="browserIntegrationRestrictKeyCombobox">
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>Restrict matching to given browser key toggle for this and sub groups</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
<spacer name="verticalSpacer_1">
|
<spacer name="verticalSpacer_1">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@ -158,6 +175,7 @@
|
|||||||
<tabstop>browserIntegrationOnlyHttpAuthComboBox</tabstop>
|
<tabstop>browserIntegrationOnlyHttpAuthComboBox</tabstop>
|
||||||
<tabstop>browserIntegrationNotHttpAuthComboBox</tabstop>
|
<tabstop>browserIntegrationNotHttpAuthComboBox</tabstop>
|
||||||
<tabstop>browserIntegrationOmitWwwCombobox</tabstop>
|
<tabstop>browserIntegrationOmitWwwCombobox</tabstop>
|
||||||
|
<tabstop>browserIntegrationRestrictKeyCombobox</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
@ -675,3 +675,68 @@ void TestBrowser::testBestMatchingWithAdditionalURLs()
|
|||||||
QCOMPARE(sorted.length(), 1);
|
QCOMPARE(sorted.length(), 1);
|
||||||
QCOMPARE(sorted[0]->url(), urls[0]);
|
QCOMPARE(sorted[0]->url(), urls[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestBrowser::testRestrictBrowserKey()
|
||||||
|
{
|
||||||
|
auto db = QSharedPointer<Database>::create();
|
||||||
|
auto* root = db->rootGroup();
|
||||||
|
|
||||||
|
// Group 0 (root): No browser key restriction given
|
||||||
|
QStringList urlsRoot = {"https://example.com/0"};
|
||||||
|
auto entriesRoot = createEntries(urlsRoot, root);
|
||||||
|
|
||||||
|
// Group 1: restricted to browser with 'key1'
|
||||||
|
auto* group1 = new Group();
|
||||||
|
group1->setParent(root);
|
||||||
|
group1->setName("TestGroup1");
|
||||||
|
group1->customData()->set(BrowserService::OPTION_RESTRICT_KEY, "key1");
|
||||||
|
QStringList urls1 = {"https://example.com/1"};
|
||||||
|
auto entries1 = createEntries(urls1, group1);
|
||||||
|
|
||||||
|
// Group 2: restricted to browser with 'key2'
|
||||||
|
auto* group2 = new Group();
|
||||||
|
group2->setParent(root);
|
||||||
|
group2->setName("TestGroup2");
|
||||||
|
group2->customData()->set(BrowserService::OPTION_RESTRICT_KEY, "key2");
|
||||||
|
QStringList urls2 = {"https://example.com/2"};
|
||||||
|
auto entries2 = createEntries(urls2, group2);
|
||||||
|
|
||||||
|
// Group 2b: inherits parent group (2) restriction
|
||||||
|
auto* group2b = new Group();
|
||||||
|
group2b->setParent(group2);
|
||||||
|
group2b->setName("TestGroup2b");
|
||||||
|
QStringList urls2b = {"https://example.com/2b"};
|
||||||
|
auto entries2b = createEntries(urls2b, group2b);
|
||||||
|
|
||||||
|
// Group 3: inherits parent group (root) - any browser can see
|
||||||
|
auto* group3 = new Group();
|
||||||
|
group3->setParent(root);
|
||||||
|
group3->setName("TestGroup3");
|
||||||
|
QStringList urls3 = {"https://example.com/3"};
|
||||||
|
auto entries3 = createEntries(urls3, group3);
|
||||||
|
|
||||||
|
// Browser 'key0': Groups 1 and 2 are excluded, so entries 0 and 3 will be found
|
||||||
|
auto siteUrl = QString("https://example.com");
|
||||||
|
auto result = m_browserService->searchEntries(db, siteUrl, siteUrl, {"key0"});
|
||||||
|
auto sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
|
||||||
|
QCOMPARE(sorted.size(), 2);
|
||||||
|
QCOMPARE(sorted[0]->url(), QString("https://example.com/3"));
|
||||||
|
QCOMPARE(sorted[1]->url(), QString("https://example.com/0"));
|
||||||
|
|
||||||
|
// Browser 'key1': Group 2 will be excluded, so entries 0, 1, and 3 will be found
|
||||||
|
result = m_browserService->searchEntries(db, siteUrl, siteUrl, {"key1"});
|
||||||
|
sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
|
||||||
|
QCOMPARE(sorted.size(), 3);
|
||||||
|
QCOMPARE(sorted[0]->url(), QString("https://example.com/3"));
|
||||||
|
QCOMPARE(sorted[1]->url(), QString("https://example.com/1"));
|
||||||
|
QCOMPARE(sorted[2]->url(), QString("https://example.com/0"));
|
||||||
|
|
||||||
|
// Browser 'key2': Group 1 will be excluded, so entries 0, 2, 2b, 3 will be found
|
||||||
|
result = m_browserService->searchEntries(db, siteUrl, siteUrl, {"key2"});
|
||||||
|
sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
|
||||||
|
QCOMPARE(sorted.size(), 4);
|
||||||
|
QCOMPARE(sorted[0]->url(), QString("https://example.com/3"));
|
||||||
|
QCOMPARE(sorted[1]->url(), QString("https://example.com/2b"));
|
||||||
|
QCOMPARE(sorted[2]->url(), QString("https://example.com/2"));
|
||||||
|
QCOMPARE(sorted[3]->url(), QString("https://example.com/0"));
|
||||||
|
}
|
||||||
|
@ -49,6 +49,7 @@ private slots:
|
|||||||
void testSubdomainsAndPaths();
|
void testSubdomainsAndPaths();
|
||||||
void testBestMatchingCredentials();
|
void testBestMatchingCredentials();
|
||||||
void testBestMatchingWithAdditionalURLs();
|
void testBestMatchingWithAdditionalURLs();
|
||||||
|
void testRestrictBrowserKey();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<Entry*> createEntries(QStringList& urls, Group* root) const;
|
QList<Entry*> createEntries(QStringList& urls, Group* root) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user