14 Commits
1.1.0 ... 1.3.1

Author SHA1 Message Date
72fe6f3007 Replaced fuzzy search with exact string start match 2023-03-28 21:30:03 +03:00
6789843eeb Merge pull request #36 from electrickite/rbw-clipboard-copy
Enable field searches for rbw when using native clipboard
2022-11-04 01:07:49 +00:00
3406972e21 Enable field searches for rbw when using native clipboard 2022-11-03 17:10:04 -04:00
005a161bb1 Merge pull request #35 from electrickite/rbw-fields
Support field searches for Bitwarden/rbw
2022-10-28 01:14:13 +00:00
973ad49c33 Add support for field searches to Bitwarden/rbw 2022-10-26 20:27:33 -04:00
8a973038ab Merge pull request #33 from jnphilipp/fix-notifications
Default in getenv needs to be str not bool.
2022-10-07 09:49:06 +00:00
2ced9fe955 Default in getenv needs to be str not bool. 2022-10-02 18:26:14 +02:00
6dc332843d Merge pull request #32 from jnphilipp/fix-notification
Fix NoneType error when DISABLE_NOTIFICATIONS is not set.
2022-10-01 21:43:01 +00:00
102b7e044a Fix NoneType error. 2022-10-01 18:17:24 +02:00
92270735c5 Merge branch 'Layerex-disable-notifications' 2022-09-30 11:41:25 +02:00
e98543973a Require DISABLE_NOTIFICATIONS to be set to True, update README. 2022-09-30 11:41:00 +02:00
62b63dc3e1 Don't disable error notifications with environment variable 2022-09-28 11:16:45 +03:00
d302782073 Add support for disabling notifications with enviroment variable 2022-09-28 11:09:05 +03:00
ff2d5600eb Update README.md 2022-07-01 23:39:27 +00:00
3 changed files with 55 additions and 47 deletions

View File

@ -40,7 +40,7 @@ dnf install gnome-pass-search-provider
## Manual
Ensure that python>=3.7 as well as the dbus, gobject and thefuzz (formerly fuzzywuzzy, might still be packaged under that name in your distribution) Python modules are installed. They should all be packaged under python-name or python3-name depending on your distribution.
Ensure that python>=3.7 as well as the dbus and gobject Python modules are installed. They should all be packaged under python-name or python3-name depending on your distribution.
Clone this repository and run the installation script as root:
```
@ -76,6 +76,10 @@ pin: 123456
To copy the pin start the search with `:pin` and for the username with `:user`.
## Disabling notifications
Set the `DISABLE_NOTIFICATIONS` environment variable to `True`.
# Alternative password providers
## Gopass and other pass-compatible tools
@ -127,9 +131,9 @@ This implements the `org.gnome.Shell.SearchProvider2` D-Bus API and has been tes
## Environment variables have no effect
If you are configuring `pass` through environment variables, such as `PASSWORD_STORE_DIR`, make sure to set them in a way that will propagate to the search provider executable, not just in your shell.
If you are configuring `pass` using environment variables, such as `PASSWORD_STORE_DIR`, make sure to set them in a way that will propagate to the search provider executable, not just in your shell.
Setting them in `~/.profile` should be sufficient, but keep in mind that stuff in shell-specific files such as `~/.bashrc` only affects the command-line shell and will not propagate to the script. On systemd-based OSes, you can also directly set them in `~/.config/environment.d/*.conf` (see `man environment.d`).
On systemd-based OSes, you can directly set them in `~/.config/environment.d/*.conf` (see `man environment.d`). On other systems, setting them in `~/.profile` should be sufficient, but keep in mind that some shell-specific files such as `~/.bashrc` might be only loaded in non-login interactive shells and will thus not propagate to the script.
If your values have no effect, make sure they propagate to the script environment. You can check this by displaying the process environment with `ps` and looking for your values here:
```

View File

@ -32,12 +32,6 @@ from os.path import join as path_join
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
try:
from thefuzz import fuzz
from thefuzz import process
except ModuleNotFoundError:
from fuzzywuzzy import fuzz
from fuzzywuzzy import process
from gi.repository import GLib
# Convenience shorthand for declaring dbus interface methods.
@ -67,6 +61,9 @@ class SearchPassService(dbus.service.Object):
self.password_executable = getenv("PASSWORD_EXECUTABLE") or "pass"
self.password_mode = getenv("PASSWORD_MODE") or "pass"
self.clipboard_executable = getenv("CLIPBOARD_EXECUTABLE") or "wl-copy"
self.disable_notifications = (
getenv("DISABLE_NOTIFICATIONS", "false").lower() == "true"
)
@dbus.service.method(in_signature="sasu", **sbn)
def ActivateResult(self, id, terms, timestamp):
@ -102,18 +99,21 @@ class SearchPassService(dbus.service.Object):
pass
def get_bw_result_set(self, terms):
if terms[0].startswith(":"):
field = terms[0][1:]
terms = terms[1:]
else:
field = None
name = "".join(terms)
password_list = subprocess.check_output(
[self.password_executable, "list"], universal_newlines=True
).split("\n")[:-1]
results = [
e[0]
for e in process.extract(
name, password_list, limit=5, scorer=fuzz.partial_ratio
)
]
results = list(filter(lambda x: x.startswith(name), password_list))[:5]
if field is not None:
results = [f":{field} {r}" for r in results]
return results
def get_pass_result_set(self, terms):
@ -139,51 +139,51 @@ class SearchPassService(dbus.service.Object):
path = path_join(dir_path, filename)[:-4]
password_list.append(path)
results = [
e[0]
for e in process.extract(
name, password_list, limit=5, scorer=fuzz.partial_ratio
)
]
results = list(filter(lambda x: x.startswith(name), password_list))[:5]
if field == "otp":
results = [f"otp {r}" for r in results]
elif field is not None:
results = [f":{field} {r}" for r in results]
return results
def get_value_from_output(self, output, field=None):
if field is not None:
match = re.search(
rf"^{field}:\s*(?P<value>.+?)$", output, flags=re.I | re.M
)
if match:
value = match.group("value")
else:
raise RuntimeError(f"The field {field} was not found in the password entry.")
else:
value = output.split("\n", 1)[0]
return value
def send_password_to_gpaste(self, base_args, name, field=None):
gpaste = self.session_bus.get_object(
"org.gnome.GPaste.Daemon", "/org/gnome/GPaste"
)
output = subprocess.check_output(base_args + [name], universal_newlines=True)
if field is not None:
match = re.search(
rf"^{field}:\s*(?P<value>.+?)$", output, flags=re.I | re.M
)
if match:
password = match.group("value")
else:
raise RuntimeError(f"The field {field} was not found in the pass file.")
else:
password = output.split("\n", 1)[0]
value = self.get_value_from_output(output, field)
try:
gpaste.AddPassword(name, password, dbus_interface="org.gnome.GPaste1")
gpaste.AddPassword(name, value, dbus_interface="org.gnome.GPaste1")
except dbus.DBusException:
gpaste.AddPassword(name, password, dbus_interface="org.gnome.GPaste2")
gpaste.AddPassword(name, value, dbus_interface="org.gnome.GPaste2")
def send_password_to_native_clipboard(self, base_args, name, field=None):
if field is not None:
raise RuntimeError("This feature requires GPaste.")
if self.password_mode == "bw":
p1 = subprocess.Popen(base_args + [name], stdout=subprocess.PIPE)
p2 = subprocess.run(self.clipboard_executable, stdin=p1.stdout)
if p1.returncode or p2.returncode:
output = subprocess.check_output(base_args + [name], universal_newlines=True)
value = self.get_value_from_output(output, field)
p1 = subprocess.run(self.clipboard_executable, input=value, text=True)
if p1.returncode:
raise RuntimeError(
f"Error while running rbw: got return codes: {p1.returncode} {p2.returncode}."
f"Error while running copying to clipboard: got return code: {p1.returncode}."
)
else:
if field is not None:
raise RuntimeError("This feature requires GPaste.")
result = subprocess.run(base_args + ["-c", name])
if result.returncode:
raise RuntimeError(
@ -191,17 +191,21 @@ class SearchPassService(dbus.service.Object):
)
def send_password_to_clipboard(self, name):
field = None
if name.startswith(":"):
field, name = name.split(" ", 1)
field = field[1:]
else:
field = None
if self.password_mode == "bw":
base_args = [self.password_executable, "get"]
base_args = [self.password_executable, "get", "--full"]
elif name.startswith("otp "):
base_args = [self.password_executable, "otp", "code"]
name = name[4:]
field = None
else:
base_args = [self.password_executable, "show"]
if name.startswith(":"):
field, name = name.split(" ", 1)
field = field[1:]
try:
try:
self.send_password_to_gpaste(base_args, name, field)
@ -220,6 +224,8 @@ class SearchPassService(dbus.service.Object):
self.notify("Failed to copy password or field!", body=str(e), error=True)
def notify(self, message, body="", error=False):
if not error and self.disable_notifications:
return
try:
self.session_bus.get_object(
"org.freedesktop.Notifications", "/org/freedesktop/Notifications"

View File

@ -9,8 +9,6 @@ Requires: gnome-shell
Requires: pass
Requires: python3-gobject
Requires: python3-dbus
Requires: python3-fuzzywuzzy
Requires: python3-Levenshtein
BuildRoot: %{_tmppath}/%{name}-%{version}-build
%global debug_package %{nil}