Compare commits

...

1 Commits

7 changed files with 166 additions and 61 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "creddy", "name": "creddy",
"version": "0.2.1", "version": "0.2.2",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",

95
src-tauri/Cargo.lock generated
View File

@ -68,36 +68,6 @@ version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]]
name = "app"
version = "0.2.1"
dependencies = [
"argon2",
"auto-launch",
"aws-config",
"aws-sdk-sts",
"aws-smithy-types",
"aws-types",
"chacha20poly1305",
"clap",
"dirs 5.0.1",
"is-terminal",
"netstat2",
"once_cell",
"serde",
"serde_json",
"sodiumoxide",
"sqlx",
"strum",
"strum_macros",
"sysinfo",
"tauri",
"tauri-build",
"tauri-plugin-single-instance",
"thiserror",
"tokio",
]
[[package]] [[package]]
name = "argon2" name = "argon2"
version = "0.5.0" version = "0.5.0"
@ -975,6 +945,37 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "creddy"
version = "0.2.2"
dependencies = [
"argon2",
"auto-launch",
"aws-config",
"aws-sdk-sts",
"aws-smithy-types",
"aws-types",
"chacha20poly1305",
"clap",
"dirs 5.0.1",
"gag",
"netstat2",
"once_cell",
"serde",
"serde_json",
"sodiumoxide",
"sqlx",
"strum",
"strum_macros",
"sysinfo",
"tauri",
"tauri-build",
"tauri-plugin-single-instance",
"thiserror",
"tokio",
"windows 0.48.0",
]
[[package]] [[package]]
name = "crossbeam-channel" name = "crossbeam-channel"
version = "0.5.8" version = "0.5.8"
@ -1347,6 +1348,17 @@ dependencies = [
"rustc_version", "rustc_version",
] ]
[[package]]
name = "filedescriptor"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7199d965852c3bac31f779ef99cbb4537f80e952e2d6aa0ffeb30cce00f4f46e"
dependencies = [
"libc",
"thiserror",
"winapi",
]
[[package]] [[package]]
name = "filetime" name = "filetime"
version = "0.2.21" version = "0.2.21"
@ -1529,6 +1541,16 @@ dependencies = [
"byteorder", "byteorder",
] ]
[[package]]
name = "gag"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a713bee13966e9fbffdf7193af71d54a6b35a0bb34997cd6c9519ebeb5005972"
dependencies = [
"filedescriptor",
"tempfile",
]
[[package]] [[package]]
name = "gdk" name = "gdk"
version = "0.15.4" version = "0.15.4"
@ -2099,18 +2121,6 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "is-terminal"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
dependencies = [
"hermit-abi 0.3.1",
"io-lifetimes",
"rustix",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.5" version = "0.10.5"
@ -4009,6 +4019,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe7e0f1d535e7cbbbab43c82be4fc992b84f9156c16c160955617e0260ebc449" checksum = "fe7e0f1d535e7cbbbab43c82be4fc992b84f9156c16c160955617e0260ebc449"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap",
"cocoa", "cocoa",
"dirs-next", "dirs-next",
"embed_plist", "embed_plist",

View File

@ -1,11 +1,11 @@
[package] [package]
name = "app" name = "creddy"
version = "0.2.1" version = "0.2.2"
description = "A Tauri App" description = "A friendly AWS credentials manager"
authors = ["you"] authors = ["Joseph Montanaro"]
license = "" license = ""
repository = "" repository = ""
default-run = "app" default-run = "creddy"
edition = "2021" edition = "2021"
rust-version = "1.57" rust-version = "1.57"
@ -17,7 +17,7 @@ tauri-build = { version = "1.0.4", features = [] }
[dependencies] [dependencies]
serde_json = "1.0" serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.2", features = ["dialog", "os-all", "system-tray"] } tauri = { version = "1.2", features = ["cli", "dialog", "os-all", "system-tray"] }
tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" } tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
sodiumoxide = "0.2.7" sodiumoxide = "0.2.7"
tokio = { version = ">=1.19", features = ["full"] } tokio = { version = ">=1.19", features = ["full"] }
@ -35,9 +35,11 @@ strum_macros = "0.24"
auto-launch = "0.4.0" auto-launch = "0.4.0"
dirs = "5.0" dirs = "5.0"
clap = { version = "3.2.23", features = ["derive"] } clap = { version = "3.2.23", features = ["derive"] }
is-terminal = "0.4.7" # is-terminal = "0.4.7"
argon2 = { version = "0.5.0", features = ["std"] } argon2 = { version = "0.5.0", features = ["std"] }
chacha20poly1305 = { version = "0.10.1", features = ["std"] } chacha20poly1305 = { version = "0.10.1", features = ["std"] }
windows = { version = "0.48", features = ["Win32_Foundation", "Win32_System_Console"] }
gag = "1.0"
[features] [features]
# by default Tauri runs in production mode # by default Tauri runs in production mode

View File

@ -13,7 +13,6 @@ use tokio::{
io::{AsyncReadExt, AsyncWriteExt}, io::{AsyncReadExt, AsyncWriteExt},
}; };
use crate::app; use crate::app;
use crate::config::AppConfig; use crate::config::AppConfig;
use crate::credentials::{BaseCredentials, SessionCredentials}; use crate::credentials::{BaseCredentials, SessionCredentials};
@ -23,6 +22,16 @@ use crate::errors::*;
pub fn parser() -> Command<'static> { pub fn parser() -> Command<'static> {
Command::new("creddy") Command::new("creddy")
.about("A friendly AWS credentials manager") .about("A friendly AWS credentials manager")
// we don't want the default help handling because it early-exits,
// and on Windows we need to setup the console before we can output
.disable_help_flag(true)
.arg(
Arg::new("help")
.short('h')
.long("help")
.action(ArgAction::SetTrue)
.help("Print this message or the help of the given subcommand(s)")
)
.subcommand( .subcommand(
Command::new("run") Command::new("run")
.about("Launch Creddy") .about("Launch Creddy")

View File

@ -2,7 +2,6 @@ use std::net::Ipv4Addr;
use std::path::PathBuf; use std::path::PathBuf;
use auto_launch::AutoLaunchBuilder; use auto_launch::AutoLaunchBuilder;
use is_terminal::IsTerminal;
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use sqlx::SqlitePool; use sqlx::SqlitePool;
@ -96,7 +95,7 @@ pub fn get_or_create_db_path() -> Result<PathBuf, DataDirError> {
path.push("Creddy"); path.push("Creddy");
std::fs::create_dir_all(&path)?; std::fs::create_dir_all(&path)?;
if cfg!(debug_assertions) && std::io::stdout().is_terminal() { if cfg!(debug_assertions) {
path.push("creddy.dev.db"); path.push("creddy.dev.db");
} }
else { else {

View File

@ -3,6 +3,20 @@
windows_subsystem = "windows" windows_subsystem = "windows"
)] )]
#[cfg(windows)]
use {
std::fs::File,
std::os::windows::io::FromRawHandle,
std::os::raw::c_void,
gag::Redirect,
windows::Win32::System::Console::{
AllocConsole,
AttachConsole,
GetStdHandle,
STD_OUTPUT_HANDLE,
STD_ERROR_HANDLE,
}
};
mod app; mod app;
mod cli; mod cli;
@ -15,18 +29,40 @@ mod state;
mod server; mod server;
mod tray; mod tray;
use crate::errors::ErrorPopup; use crate::errors::ErrorPopup;
use std::io::Write;
fn main() { fn main() {
let res = match cli::parser().get_matches().subcommand() { let args = cli::parser().get_matches();
None | Some(("run", _)) => { let help = matches!(args.get_one::<bool>("help"), Some(true));
// This is the only case that doesn't need a console
if let None | Some(("run", _)) = args.subcommand() {
if !help {
app::run().error_popup("Creddy failed to start"); app::run().error_popup("Creddy failed to start");
Ok(()) return;
}, }
}
// on Windows, need to do the whole allocate-a-console thing
#[cfg(windows)]
attach_console();
// let (out, err) = setup_console();
println!("Testing stdout");
// writeln!(&mut out, "Testing allocated file");
if help {
// if we can't print help, we can't print an error, so just panic
dbg!(args.get_one::<bool>("help"));
cli::parser().print_help().unwrap();
std::thread::sleep(std::time::Duration::from_secs(3));
return;
}
let res = match args.subcommand() {
Some(("show", m)) => cli::show(m), Some(("show", m)) => cli::show(m),
Some(("exec", m)) => cli::exec(m), Some(("exec", m)) => cli::exec(m),
// clap ensures that subcommand is either None or run/show/exec
_ => unreachable!(), _ => unreachable!(),
}; };
@ -34,3 +70,43 @@ fn main() {
eprintln!("Error: {e}"); eprintln!("Error: {e}");
} }
} }
fn attach_console() {
unsafe { AttachConsole(u32::MAX); }
}
fn setup_console() -> (Redirect<File>, Redirect<File>) {
let (mut stdout, stderr) = unsafe {
AllocConsole();
// if we can't get handles to stdout/err, we can't display these errors,
// so there's no point in doing anything other than panicking
let stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE).unwrap();
let stderr_handle = GetStdHandle(STD_ERROR_HANDLE).unwrap();
let mut f = File::create("C:\\Users\\Joe\\Downloads\\debug.txt").unwrap();
writeln!(&mut f, "{stdout_handle:?}\n{:?}", stdout_handle.0 as *mut c_void).unwrap();
(
File::from_raw_handle(stdout_handle.0 as *mut c_void),
File::from_raw_handle(stderr_handle.0 as *mut c_void),
)
};
writeln!(&mut stdout, "Testing stdout before redirect")
.map_err(|e| log_err(e))
.unwrap();
(
Redirect::stdout(stdout).unwrap(),
Redirect::stderr(stderr).unwrap()
)
}
fn log_err(e: impl std::error::Error) {
let mut f = File::create("C:\\Users\\Joe\\Downloads\\log.txt").unwrap();
writeln!(&mut f, "{e}").unwrap();
}

View File

@ -7,8 +7,8 @@
"distDir": "../dist" "distDir": "../dist"
}, },
"package": { "package": {
"productName": "creddy", "productName": "Creddy",
"version": "0.2.1" "version": "0.2.2"
}, },
"tauri": { "tauri": {
"allowlist": { "allowlist": {
@ -47,6 +47,14 @@
"timestampUrl": "" "timestampUrl": ""
} }
}, },
"cli": {
"description": "A friendly AWS credentials manager",
"subcommands": {
"run": {
"description": "Launch Creddy"
}
}
},
"security": { "security": {
"csp": { "csp": {
"default-src": ["'self'"], "default-src": ["'self'"],