Compare commits
36 Commits
Author | SHA1 | Date | |
---|---|---|---|
d844f1de04 | |||
96f7a83e1e | |||
34e297592a | |||
375feac8a0 | |||
101c833db2 | |||
bf053eda24 | |||
522436fdfb | |||
72fe6f3007 | |||
|
6789843eeb | ||
|
3406972e21 | ||
|
005a161bb1 | ||
|
973ad49c33 | ||
|
8a973038ab | ||
|
2ced9fe955 | ||
|
6dc332843d | ||
|
102b7e044a | ||
|
92270735c5 | ||
|
e98543973a | ||
|
62b63dc3e1 | ||
|
d302782073 | ||
|
ff2d5600eb | ||
|
42508b271f | ||
|
2acdad58c0 | ||
|
7fb89aebd2 | ||
|
627959e416 | ||
|
1f7a548e87 | ||
|
4f7c68a636 | ||
|
f6e42e660c | ||
|
7b89f59a53 | ||
|
92fac7865a | ||
|
72af8bf43b | ||
|
54a85ff9d4 | ||
|
1d936552ce | ||
|
3e31a8b74f | ||
|
07306747c5 | ||
|
f0b065bbd7 |
4
.coafile
4
.coafile
@ -1,4 +0,0 @@
|
||||
[python]
|
||||
bears = PyUnusedCodeBear,PySafetyBear,PyFlakesBear,PEP8Bear,BanditBear,PyCommentedCodeBear,VultureBear,InvalidLinkBear,PyImportSortBear
|
||||
files = *.py
|
||||
use_spaces = true
|
23
.pre-commit-config.yaml
Normal file
23
.pre-commit-config.yaml
Normal file
@ -0,0 +1,23 @@
|
||||
---
|
||||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.3.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-added-large-files
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 20.8b1
|
||||
hooks:
|
||||
- id: black
|
||||
- repo: https://gitlab.com/pycqa/flake8
|
||||
rev: 3.8.4
|
||||
hooks:
|
||||
- id: flake8
|
||||
args: ['--ignore=E501,E203']
|
||||
- repo: https://github.com/asottile/reorder_python_imports
|
||||
rev: v2.3.6
|
||||
hooks:
|
||||
- id: reorder-python-imports
|
3
.tito/packages/.readme
Normal file
3
.tito/packages/.readme
Normal file
@ -0,0 +1,3 @@
|
||||
the .tito/packages directory contains metadata files
|
||||
named after their packages. Each file has the latest tagged
|
||||
version and the project's relative directory.
|
1
.tito/packages/gnome-pass-search-provider
Normal file
1
.tito/packages/gnome-pass-search-provider
Normal file
@ -0,0 +1 @@
|
||||
1.3.2-1 ./
|
5
.tito/tito.props
Normal file
5
.tito/tito.props
Normal file
@ -0,0 +1,5 @@
|
||||
[buildconfig]
|
||||
builder = tito.builder.Builder
|
||||
tagger = tito.tagger.VersionTagger
|
||||
changelog_do_not_remove_cherrypick = 0
|
||||
changelog_format = %s (%ae)
|
110
README.md
110
README.md
@ -1,8 +1,16 @@
|
||||
A search provider for GNOME Shell that adds support for searching in zx2c4/[pass](https://www.passwordstore.org/).
|
||||
A search provider for GNOME Shell that adds support for searching in:
|
||||
|
||||
Names of passwords will show up in GNOME Shell searches, choosing one will copy the corresponding content to the clipboard.
|
||||
* zx2c4/[pass](https://www.passwordstore.org/)
|
||||
* compatible alternatives such as [gopass](https://www.gopass.pw/)
|
||||
* or the [rbw](https://github.com/doy/rbw) Bitwarden/Vaultwarden client
|
||||
|
||||
Supports OTP, fields and can use GPaste.
|
||||
Names of entries will show up in GNOME Shell searches, choosing one will copy the corresponding content to the clipboard.
|
||||
|
||||
Supports:
|
||||
|
||||
* using the [GPaste](https://github.com/Keruspe/GPaste) clipboard manager
|
||||
* OTP with the [pass-otp](https://github.com/tadfisher/pass-otp) extension
|
||||
* fields (cf below for syntax)
|
||||
|
||||

|
||||
|
||||
@ -13,23 +21,31 @@ Supports OTP, fields and can use GPaste.
|
||||
Install `gnome-pass-search-provider-git` from the AUR.
|
||||
|
||||
## Debian, Ubuntu and derivatives
|
||||
If a package is available for your distribution version (see above for packaging status), just install `gnome-pass-search-provider` through APT.
|
||||
If a package is available for your distribution version (see above for packaging status), just install `gnome-pass-search-provider` through APT:
|
||||
|
||||
```
|
||||
apt install gnome-pass-search-provider
|
||||
```
|
||||
|
||||
## Fedora
|
||||
|
||||
[](https://copr.fedorainfracloud.org/coprs/jle64/gnome-pass-search-provider/package/gnome-pass-search-provider/)
|
||||
|
||||
Enable the copr repo and install the package with DNF:
|
||||
|
||||
```shell
|
||||
```
|
||||
dnf copr enable jle64/gnome-pass-search-provider
|
||||
dnf install gnome-pass-search-provider
|
||||
```
|
||||
|
||||
## Manual
|
||||
|
||||
Ensure that python>=3.5 as well as the dbus, gobject, fuzzywuzzy 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, 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.
|
||||
|
||||
Clone this repository and run the installation script as root:
|
||||
```shell
|
||||
git clone git@github.com:jle64/gnome-shell-pass-search-provider.git
|
||||
```
|
||||
git clone https://github.com/jle64/gnome-pass-search-provider.git
|
||||
cd gnome-pass-search-provider
|
||||
sudo ./install.sh
|
||||
```
|
||||
|
||||
@ -37,13 +53,17 @@ sudo ./install.sh
|
||||
|
||||
Log out and reopen your GNOME session.
|
||||
|
||||
The search provider will be loaded automatically when doing a search. You should see it enabled in GNOME Settings Search pane.
|
||||
The search provider will be loaded automatically when doing a search.
|
||||
|
||||
# OTP
|
||||
You should see it enabled in GNOME Settings, in the Search pane. This is also where you can move it up or down in the list of results relatively to other search providers.
|
||||
|
||||
# Advanced usage
|
||||
|
||||
## OTP
|
||||
|
||||
The [pass-otp](https://github.com/tadfisher/pass-otp) extension is supported. Searches starting with `otp` will copy the otp token to the clipboard.
|
||||
|
||||
# Fields
|
||||
## Fields
|
||||
|
||||
To copy other values than the password in the first line from a pass file, start the search with `:NAME search...`. The field name must be a full but case insensitive match. This requires `GPaste`.
|
||||
|
||||
@ -54,32 +74,78 @@ user: username
|
||||
pin: 123456
|
||||
```
|
||||
|
||||
To copy the pin start the search with `:pin` and for the username `:user`.
|
||||
To copy the pin start the search with `:pin` and for the username with `:user`.
|
||||
|
||||
# Environment variables
|
||||
## Disabling notifications
|
||||
|
||||
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.
|
||||
Set the `DISABLE_NOTIFICATIONS` environment variable to `True`.
|
||||
|
||||
Setting them in `~/.profile` or `~/.pam_environment` should be sufficient, but stuff in shell-specific files such as `~/.bashrc` will not be picked up by gnome-shell.
|
||||
# Alternative password providers
|
||||
|
||||
## Gopass and other pass-compatible tools
|
||||
|
||||
If you want to use [gopass](https://www.gopass.pw/) or another `pass` compatible tool instead of `pass`, you need to set the proper environment variables to point to the executable and password store directory to use.
|
||||
|
||||
For example, on a systemd-based OS, you can run `systemctl --user edit org.gnome.Pass.SearchProvider.service` and add in the file:
|
||||
|
||||
If your values have no effect, make sure they propagate to the script environment:
|
||||
```shell
|
||||
ps auxeww | grep [g]nome-pass-search-provider.py
|
||||
```
|
||||
[Service]
|
||||
Environment=PASSWORD_EXECUTABLE=gopass
|
||||
Environment=PASSWORD_STORE_DIR=/home/jonathan/.local/share/gopass/stores/root
|
||||
```
|
||||
(be careful not leave a trailing "/" at the end of the `PASSWORD_STORE_DIR` path)
|
||||
|
||||
Then save and restart the service with `systemctl --user restart org.gnome.Pass.SearchProvider.service`.
|
||||
|
||||
On other systems, you might want to use `~/.profile` or another mechanism to set these environment variables.
|
||||
|
||||
## Bitwarden/Vaultwarden
|
||||
|
||||
To search in Bitwarden/Vaultwarden instead of `pass`, you will need to setup [rbw](https://github.com/doy/rbw). You'll also need to install `wl-clipboard` or another clipboard utility (such as `xclip`), unless you use GPaste.
|
||||
|
||||
You need to set the proper environment variables to point to the executables and specify to operate in Bitwarden mode.
|
||||
|
||||
For example, on a systemd-based OS, you can run `systemctl --user edit org.gnome.Pass.SearchProvider.service` and add in the file:
|
||||
|
||||
```
|
||||
[Service]
|
||||
Environment=PASSWORD_EXECUTABLE=rbw
|
||||
Environment=PASSWORD_MODE=bw
|
||||
Environment=CLIPBOARD_EXECUTABLE=wl-copy
|
||||
```
|
||||
Then save and restart the service with `systemctl --user restart org.gnome.Pass.SearchProvider.service`.
|
||||
|
||||
On other systems, you might want to use `~/.profile` or another mechanism to set these environment variables.
|
||||
|
||||
# Clipboard managers
|
||||
|
||||
If you are using GPaste, passwords will be sent to it marked as passwords, thus ensuring they are not visible.
|
||||
Otherwise they are sent to the clipboard using `pass -c` which defaults to expiration after 45 seconds.
|
||||
By default, passwords are sent to the clipboard using `pass -c`, which defaults to expiration after 45 seconds.
|
||||
|
||||
If [GPaste](https://github.com/Keruspe/GPaste) is installed, passwords be sent to it marked as passwords through its API, thus ensuring they are not visible in the UI.
|
||||
|
||||
# Compatibility
|
||||
|
||||
This implements the `org.gnome.Shell.SearchProvider2` D-Bus API and has been tested with GNOME Shell 3.22-3.38. This uses the `org.gnome.GPaste1` or `org.gnome.GPaste2` versions of the GPaste D-Bus API to add passwords to GPaste.
|
||||
This implements the `org.gnome.Shell.SearchProvider2` D-Bus API and has been tested with GNOME Shell 3.22 to 42. This uses the `org.gnome.GPaste1` or `org.gnome.GPaste2` versions of the GPaste D-Bus API to add passwords to GPaste.
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
## Environment variables have no effect
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
```
|
||||
ps auxeww | grep [g]nome-pass-search-provider.py
|
||||
```
|
||||
|
||||
## Passphrase is not requested to unlock store
|
||||
|
||||
If you don't see passphrase prompts when your key is locked, it might be because GPG is not using the right pinentry program. You can force gpg-agent to use pinentry-gnome3 by adding `pinentry-program /usr/bin/pinentry-gnome3` to `~/.gnupg/gpg-agent.conf`.
|
||||
|
||||
If you encounter problems, make sure to look to wherever GNOME and D-Bus are logging for error messages. You can do this using `journalctl --user` on systemd-using systems.
|
||||
## Other problems
|
||||
|
||||
If you encounter problems, make sure to look in the logs of GNOME and D-Bus. On systems that use systemd, you can do this using `journalctl --user`.
|
||||
|
||||
Don't hesitate to open an issue.
|
||||
|
@ -3,7 +3,7 @@ Version=1.0
|
||||
Categories=GNOME;Security;
|
||||
Icon=dialog-password
|
||||
Name=Pass
|
||||
Comment=GNOME Shell search provider for pass
|
||||
Comment=GNOME Shell search provider for pass and Bitwarden
|
||||
Terminal=false
|
||||
Type=Application
|
||||
OnlyShowIn=GNOME;
|
||||
|
@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
Description=Pass search provider for GNOME Shell daemon
|
||||
Description=Pass and Bitwarden search provider for GNOME Shell daemon
|
||||
Wants=org.gnome.GPaste.service
|
||||
|
||||
[Service]
|
||||
|
@ -14,27 +14,31 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with gnome-pass-search-provider. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Copyright (C) 2017 Jonathan Lestrelin
|
||||
# Author: Jonathan Lestrelin <jonathan.lestrelin@gmail.com>
|
||||
|
||||
# This project was based on gnome-shell-search-github-repositories
|
||||
# Copyright (C) 2012 Red Hat, Inc.
|
||||
# Author: Ralph Bean <rbean@redhat.com>
|
||||
# which itself was based on fedmsg-notify
|
||||
# Copyright (C) 2012 Red Hat, Inc.
|
||||
# Author: Luke Macken <lmacken@redhat.com>
|
||||
|
||||
import dbus
|
||||
import dbus.service
|
||||
import re
|
||||
import subprocess
|
||||
from os import getenv
|
||||
from os import walk
|
||||
from os.path import expanduser
|
||||
from os.path import join as path_join
|
||||
|
||||
import dbus.service
|
||||
from dbus.mainloop.glib import DBusGMainLoop
|
||||
from fuzzywuzzy import process, fuzz
|
||||
|
||||
try:
|
||||
from thefuzz import fuzz
|
||||
from thefuzz import process
|
||||
except ModuleNotFoundError:
|
||||
from fuzzywuzzy import fuzz
|
||||
from fuzzywuzzy import process
|
||||
from gi.repository import GLib
|
||||
from os import getenv, walk
|
||||
from os.path import expanduser, join as path_join
|
||||
|
||||
# Convenience shorthand for declaring dbus interface methods.
|
||||
# s.b.n. -> search_bus_name
|
||||
@ -60,6 +64,12 @@ class SearchPassService(dbus.service.Object):
|
||||
self.password_store = getenv("PASSWORD_STORE_DIR") or expanduser(
|
||||
"~/.password-store"
|
||||
)
|
||||
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):
|
||||
@ -67,7 +77,10 @@ class SearchPassService(dbus.service.Object):
|
||||
|
||||
@dbus.service.method(in_signature="as", out_signature="as", **sbn)
|
||||
def GetInitialResultSet(self, terms):
|
||||
return self.get_result_set(terms)
|
||||
if self.password_mode == "bw":
|
||||
return self.get_bw_result_set(terms)
|
||||
else:
|
||||
return self.get_pass_result_set(terms)
|
||||
|
||||
@dbus.service.method(in_signature="as", out_signature="aa{sv}", **sbn)
|
||||
def GetResultMetas(self, ids):
|
||||
@ -82,13 +95,46 @@ class SearchPassService(dbus.service.Object):
|
||||
|
||||
@dbus.service.method(in_signature="asas", out_signature="as", **sbn)
|
||||
def GetSubsearchResultSet(self, previous_results, new_terms):
|
||||
return self.get_result_set(new_terms)
|
||||
if self.password_mode == "bw":
|
||||
return self.get_bw_result_set(new_terms)
|
||||
else:
|
||||
return self.get_pass_result_set(new_terms)
|
||||
|
||||
@dbus.service.method(in_signature="asu", terms="as", timestamp="u", **sbn)
|
||||
def LaunchSearch(self, terms, timestamp):
|
||||
pass
|
||||
|
||||
def get_result_set(self, terms):
|
||||
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 = list(filter(lambda p: p.startswith(name), password_list))[:5]
|
||||
|
||||
remaining = 5 - len(results)
|
||||
|
||||
if remaining > 0:
|
||||
fuzzy_results = [
|
||||
e[0]
|
||||
for e in process.extract(
|
||||
name, password_list, limit=remaining, scorer=fuzz.token_sort_ratio
|
||||
)
|
||||
]
|
||||
|
||||
results.extend(fuzzy_results)
|
||||
|
||||
if field is not None:
|
||||
results = [f":{field} {r}" for r in results]
|
||||
return results
|
||||
|
||||
def get_pass_result_set(self, terms):
|
||||
if terms[0] == "otp":
|
||||
field = terms[0]
|
||||
elif terms[0].startswith(":"):
|
||||
@ -111,44 +157,104 @@ 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(sorted(filter(lambda p: p.startswith(name), password_list)))[:5]
|
||||
|
||||
remaining = 5 - len(results)
|
||||
|
||||
if remaining > 0:
|
||||
containing_results = list(
|
||||
sorted(filter(lambda p: name in p, password_list))
|
||||
)[:remaining]
|
||||
|
||||
results.extend(containing_results)
|
||||
|
||||
remaining = 5 - len(results)
|
||||
|
||||
if remaining > 0:
|
||||
fuzzy_results = [
|
||||
e[0]
|
||||
for e in process.extract(
|
||||
name, password_list, limit=remaining, scorer=fuzz.token_sort_ratio
|
||||
)
|
||||
]
|
||||
|
||||
results.extend(fuzzy_results)
|
||||
|
||||
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 send_password_to_gpaste(self, base_args, name, field=None):
|
||||
try:
|
||||
gpaste = self.session_bus.get_object(
|
||||
"org.gnome.GPaste.Daemon", "/org/gnome/GPaste"
|
||||
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
|
||||
)
|
||||
|
||||
output = subprocess.check_output(
|
||||
base_args + [name], stderr=subprocess.STDOUT, universal_newlines=True
|
||||
)
|
||||
if field is not None:
|
||||
match = re.search(
|
||||
fr"^{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."
|
||||
)
|
||||
if match:
|
||||
value = match.group("value")
|
||||
else:
|
||||
password = output.split("\n", 1)[0]
|
||||
try:
|
||||
gpaste.AddPassword(name, password, dbus_interface="org.gnome.GPaste1")
|
||||
except dbus.DBusException:
|
||||
gpaste.AddPassword(name, password, dbus_interface="org.gnome.GPaste2")
|
||||
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)
|
||||
value = self.get_value_from_output(output, field)
|
||||
try:
|
||||
gpaste.AddPassword(name, value, dbus_interface="org.gnome.GPaste1")
|
||||
except dbus.DBusException:
|
||||
gpaste.AddPassword(name, value, dbus_interface="org.gnome.GPaste2")
|
||||
|
||||
def send_password_to_native_clipboard(self, base_args, name, field=None):
|
||||
if self.password_mode == "bw":
|
||||
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 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(
|
||||
f"Error while running pass: got return code: {result.returncode}."
|
||||
)
|
||||
|
||||
def send_password_to_clipboard(self, name):
|
||||
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", "--full"]
|
||||
elif name.startswith("otp "):
|
||||
base_args = [self.password_executable, "otp", "code"]
|
||||
name = name[4:]
|
||||
field = None
|
||||
else:
|
||||
base_args = [self.password_executable, "show"]
|
||||
|
||||
try:
|
||||
try:
|
||||
self.send_password_to_gpaste(base_args, name, field)
|
||||
except dbus.DBusException:
|
||||
# We couldn't join GPaste over D-Bus, use native clipboard
|
||||
self.send_password_to_native_clipboard(base_args, name, field)
|
||||
if "otp" in base_args:
|
||||
self.notify("Copied OTP password to clipboard:", body=f"<b>{name}</b>")
|
||||
elif field is not None:
|
||||
@ -157,47 +263,12 @@ class SearchPassService(dbus.service.Object):
|
||||
)
|
||||
else:
|
||||
self.notify("Copied password to clipboard:", body=f"<b>{name}</b>")
|
||||
except subprocess.CalledProcessError as e:
|
||||
self.notify("Failed to copy password!", body=e.output, error=True)
|
||||
except RuntimeError as e:
|
||||
self.notify("Failed to copy field!", body=e.output, error=True)
|
||||
|
||||
def send_password_to_native_clipboard(self, base_args, name, field=None):
|
||||
if field is not None:
|
||||
self.notify(
|
||||
f"Cannot copy field values.",
|
||||
body="This feature requires GPaste.",
|
||||
error=True,
|
||||
)
|
||||
return
|
||||
|
||||
pass_cmd = subprocess.run(base_args + ["-c", name])
|
||||
if pass_cmd.returncode:
|
||||
self.notify("Failed to copy password!", error=True)
|
||||
elif "otp" in base_args:
|
||||
self.notify("Copied OTP password to clipboard:", body=f"<b>{name}</b>")
|
||||
else:
|
||||
self.notify("Copied password to clipboard:", body=f"<b>{name}</b>")
|
||||
|
||||
def send_password_to_clipboard(self, name):
|
||||
field = None
|
||||
if name.startswith("otp "):
|
||||
base_args = ["pass", "otp", "code"]
|
||||
name = name[4:]
|
||||
else:
|
||||
base_args = ["pass", "show"]
|
||||
if name.startswith(":"):
|
||||
field, name = name.split(" ", 1)
|
||||
field = field[1:]
|
||||
|
||||
try:
|
||||
self.send_password_to_gpaste(base_args, name, field)
|
||||
except dbus.DBusException:
|
||||
# We couldn't join GPaste over D-Bus,
|
||||
# use pass native clipboard copy
|
||||
self.send_password_to_native_clipboard(base_args, name, field)
|
||||
except (subprocess.CalledProcessError, FileNotFoundError, RuntimeError) as e:
|
||||
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"
|
||||
|
@ -1,25 +1,23 @@
|
||||
Name: gnome-pass-search-provider
|
||||
Version: master
|
||||
Release: 0
|
||||
License: GPL-3.0+
|
||||
Summary: Gnome Shell search provider for zx2c4/pass
|
||||
Url: https://github.com/jle64/gnome-pass-search-provider
|
||||
Source: https://github.com/jle64/%{name}/archive/master.tar.gz
|
||||
Name: gnome-pass-search-provider
|
||||
Version: 1.3.3
|
||||
Release: %autorelease
|
||||
Summary: Gnome Shell search provider for zx2c4/pass
|
||||
License: GPL-3.0+
|
||||
Url: https://git.dm1sh.ru/dm1sh/%{name}
|
||||
Source0: https://git.dm1sh.ru/dm1sh/%{name}/archive/%{version}.tar.gz
|
||||
Requires: gnome-shell
|
||||
Requires: pass
|
||||
Requires: (pass or gopass)
|
||||
Requires: python3-gobject
|
||||
Requires: python3-dbus
|
||||
Requires: python3-fuzzywuzzy
|
||||
Requires: python3-Levenshtein
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
|
||||
%global debug_package %{nil}
|
||||
|
||||
%description
|
||||
A Gnome Shell search provider for zx2c4/pass (passwordstore.org) that sends passwords to clipboard (or GPaste).
|
||||
A Gnome Shell passwords search provider for zx2c4/pass (passwordstore.org) or compatibles and Bitwarden/Vaultwarden that sends passwords to clipboard (or GPaste).
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}
|
||||
%autosetup -n %{name}
|
||||
|
||||
%define debug_package %{nil}
|
||||
|
||||
%build
|
||||
|
||||
@ -29,10 +27,13 @@ sed -i -e 's|LIBDIR=|LIBDIR=$RPM_BUILD_ROOT|' install.sh
|
||||
./install.sh
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc README.md
|
||||
%license LICENSE
|
||||
%{_prefix}/lib/gnome-pass-search-provider/gnome-pass-search-provider.py
|
||||
%{_prefix}/lib/systemd/user/org.gnome.Pass.SearchProvider.service
|
||||
%{_prefix}/share/dbus-1/services/org.gnome.Pass.SearchProvider.service
|
||||
%{_prefix}/share/applications/org.gnome.Pass.SearchProvider.desktop
|
||||
%{_prefix}/share/gnome-shell/search-providers/org.gnome.Pass.SearchProvider.ini
|
||||
|
||||
%changelog
|
||||
%autochangelog
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 2.8 MiB |
Loading…
x
Reference in New Issue
Block a user