-
-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implements a GNOME search provider for Ripasso. This is a very convenient way to obtain passwords from pass when using the GNOME shell. I totally understand if this isn't the kind of addition you would like to see in this repo, especially if you don't use GNOME. So I have no problem spinning it off into it's own project. It's only about 150 LoC. But since there is already a GTK project in here, I figured why not give it a shot. There will need to be some additions made for the configuration files. I know there is at least an arch linux package, and I'd be happy to contribute to that. Thanks for your work on Ripasso!
- Loading branch information
Showing
10 changed files
with
692 additions
and
5 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
name = "ripasso-gnome-search-provider" | ||
version = "0.1.0" | ||
edition = "2021" | ||
authors = ["Austin Riba <[email protected]>"] | ||
|
||
[dependencies] | ||
arboard = { version = "3.4.1", features = ["wayland-data-control"] } | ||
ripasso = { path = "../", version = "0.7.0-alpha" } | ||
search-provider = "0.10.0" | ||
tokio = { version = "1.40.0", features = ["macros"] } | ||
zbus = { version = "4.4.0", features = ["tokio"] } | ||
zeroize = "1.8.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Ripasso Gnome Search Provider | ||
|
||
WIP search provider for GNOME using ripasso. | ||
|
||
## Setting a custom PASSWORD_STORE_DIR | ||
|
||
Use `systemctl --user edit org.gnome.Ripasso.SearchProvider.service` | ||
to create an override file that contains the following: | ||
|
||
```ini | ||
[Service] | ||
Environment="PASSWORD_STORE_DIR=/path/to/password-store" | ||
``` |
9 changes: 9 additions & 0 deletions
9
gnome_search_provider/conf/org.gnome.Ripasso.SearchProvider.desktop
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[Desktop Entry] | ||
Version=1.0 | ||
Categories=GNOME;Security; | ||
Icon=dialog-password | ||
Name=Ripasso | ||
Comment=GNOME Shell search provider for Ripasso | ||
Terminal=true | ||
Type=Application | ||
OnlyShowIn=GNOME; |
4 changes: 4 additions & 0 deletions
4
gnome_search_provider/conf/org.gnome.Ripasso.SearchProvider.service.dbus
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[D-BUS Service] | ||
Name=org.gnome.Ripasso.SearchProvider | ||
Exec=/usr/lib/ripasso-search-provider/ripasso-gnome-search-provider | ||
SystemdService=org.gnome.Ripasso.SearchProvider.service |
7 changes: 7 additions & 0 deletions
7
gnome_search_provider/conf/org.gnome.Ripasso.SearchProvider.service.systemd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[Unit] | ||
Description=Ripasso Gnome Shell search provider for GNOME | ||
|
||
[Service] | ||
Type=dbus | ||
BusName=org.gnome.Ripasso.SearchProvider | ||
ExecStart=/usr/lib/ripasso-search-provider/ripasso-gnome-search-provider |
5 changes: 5 additions & 0 deletions
5
gnome_search_provider/conf/org.gnome.Ripasso.search-provider.ini
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
[Shell Search Provider] | ||
DesktopId=org.gnome.Ripasso.SearchProvider.desktop | ||
BusName=org.gnome.Ripasso.SearchProvider | ||
ObjectPath=/org/gnome/Ripasso/SearchProvider | ||
Version=2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#!/usr/bin/env bash | ||
set -eu -o pipefail | ||
cd "$(dirname "$(realpath "${0}")")" | ||
|
||
DATADIR=${DATADIR:-/usr/share} | ||
LIBDIR=${LIBDIR:-/usr/lib} | ||
|
||
install -Dm 0755 ../target/release/ripasso-gnome-search-provider "${LIBDIR}"/ripasso-search-provider/ripasso-gnome-search-provider | ||
|
||
install -Dm 0644 conf/org.gnome.Ripasso.search-provider.ini "${DATADIR}"/gnome-shell/search-providers/org.gnome.Ripasso.search-provider.ini | ||
|
||
install -Dm 0644 conf/org.gnome.Ripasso.SearchProvider.desktop "${DATADIR}"/applications/org.gnome.Ripasso.SearchProvider.desktop | ||
|
||
install -Dm 0644 conf/org.gnome.Ripasso.SearchProvider.service.dbus "${DATADIR}"/dbus-1/services/org.gnome.Ripasso.SearchProvider.service | ||
|
||
install -Dm 0644 conf/org.gnome.Ripasso.SearchProvider.service.systemd "${LIBDIR}"/systemd/user/org.gnome.Ripasso.SearchProvider.service |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
use arboard::Clipboard; | ||
use ripasso::pass::PasswordStore; | ||
use search_provider::{ResultID, ResultMeta, SearchProvider, SearchProviderImpl}; | ||
use std::{collections::HashMap, path::PathBuf, thread, time}; | ||
use zbus::{blocking::Connection, proxy, zvariant::Value}; | ||
use zeroize::Zeroize; | ||
|
||
#[proxy( | ||
default_service = "org.freedesktop.Notifications", | ||
default_path = "/org/freedesktop/Notifications" | ||
)] | ||
trait Notifications { | ||
fn notify( | ||
&self, | ||
app_name: &str, | ||
replaces_id: u32, | ||
app_icon: &str, | ||
summary: &str, | ||
body: &str, | ||
actions: &[&str], | ||
hints: HashMap<&str, &Value<'_>>, | ||
expire_timeout: i32, | ||
) -> zbus::Result<u32>; | ||
} | ||
|
||
fn copy_to_clipbard(content: &String) { | ||
let mut clipboard = Clipboard::new().unwrap(); | ||
clipboard.set_text(content).unwrap(); | ||
thread::spawn(|| { | ||
thread::sleep(time::Duration::from_secs(40)); | ||
let mut clipboard = Clipboard::new().unwrap(); | ||
clipboard.set_text(&String::new()).unwrap(); | ||
}); | ||
} | ||
|
||
fn send_notification(summary: String, body: String) { | ||
thread::spawn(move || { | ||
let connection = Connection::session().unwrap(); | ||
let proxy = NotificationsProxyBlocking::new(&connection).unwrap(); | ||
let _ = proxy.notify( | ||
"ripasso", | ||
0, | ||
"dialog-password", | ||
&summary, | ||
&body, | ||
&[], | ||
HashMap::from([("transient", &Value::Bool(true))]), | ||
4000, | ||
); | ||
}) | ||
.join() | ||
.unwrap(); | ||
} | ||
|
||
struct Application { | ||
password_store: PasswordStore, | ||
} | ||
|
||
impl SearchProviderImpl for Application { | ||
fn activate_result(&self, identifier: ResultID, terms: &[String], _timestamp: u32) { | ||
let passwords = self.password_store.all_passwords().unwrap_or_default(); | ||
if let Some(password) = passwords | ||
.iter() | ||
.find(|entry| entry.name == identifier.to_owned()) | ||
{ | ||
if terms[0] == "otp" { | ||
let mut otp = match password.mfa(&self.password_store) { | ||
Ok(otp) => otp, | ||
Err(err) => { | ||
send_notification("OTP Error".to_string(), err.to_string()); | ||
return; | ||
} | ||
}; | ||
copy_to_clipbard(&otp); | ||
otp.zeroize(); | ||
send_notification(identifier, "OTP copied to clipboard".to_string()); | ||
} else { | ||
let mut secret = match password.password(&self.password_store) { | ||
Ok(secret) => secret, | ||
Err(err) => { | ||
send_notification("Password Error".to_string(), err.to_string()); | ||
return; | ||
} | ||
}; | ||
copy_to_clipbard(&secret); | ||
secret.zeroize(); | ||
send_notification(identifier, "Password copied to clipboard".to_string()); | ||
} | ||
} else { | ||
send_notification("Error".to_string(), "Could Not Find Password".to_string()); | ||
} | ||
} | ||
|
||
fn initial_result_set(&self, terms: &[String]) -> Vec<ResultID> { | ||
let search_terms = if terms[0] == "otp" { | ||
&terms[1..] | ||
} else { | ||
terms | ||
}; | ||
|
||
self.password_store | ||
.all_passwords() | ||
.unwrap_or_default() | ||
.iter() | ||
.filter(|entry| { | ||
search_terms | ||
.iter() | ||
.any(|term| entry.name.to_lowercase().contains(&term.to_lowercase())) | ||
}) | ||
.map(|entry| entry.name.to_owned()) | ||
.collect() | ||
} | ||
|
||
fn result_metas(&self, identifiers: &[ResultID]) -> Vec<ResultMeta> { | ||
identifiers | ||
.iter() | ||
.map(|id| ResultMeta::builder(id.to_owned(), id).build()) | ||
.collect() | ||
} | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() -> zbus::Result<()> { | ||
let home = std::env::var("HOME").expect("Could not determine $HOME"); | ||
let home_path = PathBuf::from(home); | ||
let default_path = match std::env::var("PASSWORD_STORE_DIR") { | ||
Ok(val) => PathBuf::from(val), | ||
Err(_) => [home_path.to_str().unwrap(), ".password-store"] | ||
.iter() | ||
.collect(), | ||
}; | ||
let password_store = PasswordStore::new( | ||
"default", | ||
&Some(default_path), | ||
&None, | ||
&Some(home_path), | ||
&None, | ||
&ripasso::crypto::CryptoImpl::GpgMe, | ||
&None, | ||
) | ||
.unwrap(); | ||
let app = Application { password_store }; | ||
SearchProvider::new( | ||
app, | ||
"org.gnome.Ripasso.SearchProvider", | ||
"/org/gnome/Ripasso/SearchProvider", | ||
) | ||
.await?; | ||
Ok(()) | ||
} |