Skip to content

Commit

Permalink
Add fuzzy select
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike Lloyd committed Jun 4, 2024
1 parent 732e4e5 commit 65eaa0d
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 10 deletions.
51 changes: 50 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ sqlx = { version = "0.7.4", features = [
tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"] }
orion = { version = "0.17.6", features = ["serde"] }
xdg = "2.5.2"
dialoguer = "0.11.0"
dialoguer = { version = "0.11.0", features = ["fuzzy-select"] }
serde = "1.0.200"
colored_json = "4.1.0"
uuid = { version = "1.8.0", features = ["v4"] }
Expand All @@ -35,6 +35,7 @@ time = "0.3.36"
clap_complete = "4.5.2"
duration-str = "0.10.0"
toml = "0.8.12"
ctrlc = "3.4.4"

[dev-dependencies]
assert_cmd = "2.0.14"
Expand Down
40 changes: 37 additions & 3 deletions src/command/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use std::{
use anyhow::{bail, Context, Result};
use clap::CommandFactory;
use clap_complete::{generate, shells};
use dialoguer::theme::ColorfulTheme;
use sqlx::SqlitePool;
use tabled::{
settings::{style::BorderColor, Color, Style},
Table, Tabled,
Expand Down Expand Up @@ -100,7 +102,7 @@ pub async fn handle_create(
pub async fn handle_get(config_dir: &Path, name: String, json: bool) -> Result<()> {
let app = App::new(config_dir, true).await?;

let sec = Secret::get(&app.db, &name).await?;
let sec = select_secret(&app.db, &name).await?;
let cleartext = sec.to_cleartext(&app.master_key)?;

if json {
Expand All @@ -115,7 +117,7 @@ pub async fn handle_get(config_dir: &Path, name: String, json: bool) -> Result<(
pub async fn handle_edit(config_dir: &Path, name: String, description: bool) -> Result<()> {
let app = App::new(config_dir, true).await?;

let mut sec = Secret::get(&app.db, &name).await?;
let mut sec = select_secret(&app.db, &name).await?;

if description {
let old_desc = sec.description.unwrap_or_default();
Expand Down Expand Up @@ -157,7 +159,7 @@ pub async fn handle_edit(config_dir: &Path, name: String, description: bool) ->
pub async fn handle_delete(config_dir: &Path, name: String) -> Result<()> {
let app = App::new(config_dir, true).await?;

let sec = Secret::get(&app.db, &name).await?;
let sec = select_secret(&app.db, &name).await?;

let prompt_msg = format!("Delete secret '{}'?", sec.name);
let confirm = prompt::confirm(&prompt_msg, false)?;
Expand Down Expand Up @@ -312,3 +314,35 @@ pub fn handle_generate_completions(shell: ShellType) -> Result<()> {

Ok(())
}

/// Prompts the user to select a secret if multiple secrets match the inputted name
pub async fn select_secret(db: &SqlitePool, search_str: &str) -> Result<Secret> {
let mut secrets = vec![];
for secret in Secret::get_all(db).await? {
if secret.name == search_str {
return Ok(secret);
}
if secret
.name
.to_lowercase()
.contains(&search_str.to_lowercase())
{
secrets.push(secret)
}
}

if secrets.len() == 1 {
Ok(secrets.pop().unwrap())
} else {
let items: Vec<&str> = secrets.iter().map(|s| s.name.as_str()).collect();
let selection = dialoguer::FuzzySelect::with_theme(&ColorfulTheme::default())
.items(&items)
.with_prompt("Select secret")
.vim_mode(true)
.interact()?;
Ok(secrets
.get(selection)
.expect("Selected option should be in bounds")
.clone())
}
}
8 changes: 8 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::path::PathBuf;
use anyhow::{bail, Result};
use clap::Parser;

use dialoguer::console::Term;
use rudric::{
command::{
cli::{Cli, Command},
Expand All @@ -13,6 +14,9 @@ use rudric::{

#[tokio::main]
async fn main() -> Result<()> {
// Ignore SIGINT so we can handle it ourselves
ctrlc::set_handler(move || {}).expect("Error setting Ctrl-C handler");

let cli = Cli::parse();

let config_dir = match cli.config_dir {
Expand Down Expand Up @@ -44,4 +48,8 @@ async fn main() -> Result<()> {
Command::ChangePassword => handle_change_password(&config_dir).await,
Command::GenerateCompletions { shell } => handle_generate_completions(shell),
}
.map_err(|e| {
let _ = Term::stdout().show_cursor();
e
})
}
2 changes: 1 addition & 1 deletion src/types/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::crypto;

pub const SECRET_NOT_FOUND: &str = "Secret not found";

#[derive(Debug, FromRow)]
#[derive(Debug, FromRow, Clone)]
pub struct Secret {
pub id: Option<i64>,
pub name: String,
Expand Down
5 changes: 1 addition & 4 deletions src/types/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{env, fmt::Display};
use anyhow::{bail, Context, Result};
use base64::{engine::general_purpose::STANDARD_NO_PAD as b64, Engine};
use orion::aead::SecretKey;
use sqlx::{sqlite::SqliteRow, Execute, FromRow, Row, SqlitePool};
use sqlx::{sqlite::SqliteRow, FromRow, Row, SqlitePool};
use time::OffsetDateTime;
use uuid::Uuid;

Expand Down Expand Up @@ -98,9 +98,6 @@ impl SessionKey {
.await
.context("Failed to delete expired session key")?;

println!("{}",sqlx::query!("delete from session_keys where expire_time < ?", now).sql());


Ok(())
}
}
Expand Down

0 comments on commit 65eaa0d

Please sign in to comment.