generated from pure_sagacity/rust-starter
made adding a project work
changed the sql migration to make names unique
This commit is contained in:
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": ["chrono"]
|
||||||
|
}
|
||||||
Generated
+1
@@ -1748,6 +1748,7 @@ version = "1.23.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ea5fab0d6c3c01ae70085a09cb03d4c7a1d6314e2b3e075392783396d724ca0a"
|
checksum = "ea5fab0d6c3c01ae70085a09cb03d4c7a1d6314e2b3e075392783396d724ca0a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"getrandom 0.4.3",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"serde_core",
|
"serde_core",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
|||||||
@@ -20,5 +20,9 @@ colored = "3.1.1"
|
|||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
chrono = "0.4.45"
|
chrono = "0.4.45"
|
||||||
dotenvy = "0.15"
|
dotenvy = "0.15"
|
||||||
uuid = "1.23.5"
|
uuid = { version = "1.23.5", features = ["v4"] }
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "harbor"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|||||||
Binary file not shown.
@@ -1,11 +1,13 @@
|
|||||||
CREATE TABLE projects (
|
CREATE TABLE projects (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY NOT NULL,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
UNIQUE (name)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE secrets (
|
CREATE TABLE secrets (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY NOT NULL,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
project_id TEXT NOT NULL,
|
project_id TEXT NOT NULL,
|
||||||
config TEXT NOT NULL,
|
config TEXT NOT NULL,
|
||||||
|
|||||||
@@ -11,6 +11,13 @@ pub struct Project {
|
|||||||
pub created_at: NaiveDateTime,
|
pub created_at: NaiveDateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Insertable)]
|
||||||
|
#[diesel(table_name = projects)]
|
||||||
|
pub struct NewProject<'a> {
|
||||||
|
pub id: &'a str,
|
||||||
|
pub name: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Queryable, Selectable)]
|
#[derive(Debug, Queryable, Selectable)]
|
||||||
#[diesel(table_name = secrets)]
|
#[diesel(table_name = secrets)]
|
||||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
||||||
|
|||||||
+78
-14
@@ -1,10 +1,12 @@
|
|||||||
use base64::{Engine, engine::general_purpose::STANDARD};
|
use base64::{Engine, engine::general_purpose::STANDARD};
|
||||||
use clap::{Args, Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use crypto::helper::gen_key;
|
use crypto::helper::gen_key;
|
||||||
use keyring::Entry;
|
use keyring::Entry;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::io::{self, Write};
|
||||||
mod db;
|
mod db;
|
||||||
mod store;
|
mod store;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[clap(
|
#[clap(
|
||||||
name = "Harbor",
|
name = "Harbor",
|
||||||
@@ -22,7 +24,13 @@ pub struct Cli {
|
|||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
pub enum Commands {
|
pub enum Commands {
|
||||||
Inject(InjectArgs),
|
Inject {
|
||||||
|
#[arg(short, long)]
|
||||||
|
verbose: bool,
|
||||||
|
|
||||||
|
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
|
||||||
|
after: Vec<String>,
|
||||||
|
},
|
||||||
Shell {},
|
Shell {},
|
||||||
Add {},
|
Add {},
|
||||||
Setup {},
|
Setup {},
|
||||||
@@ -37,30 +45,72 @@ pub enum Commands {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args, Debug)]
|
|
||||||
pub struct InjectArgs {
|
|
||||||
#[arg(short, long)]
|
|
||||||
pub verbose: bool,
|
|
||||||
|
|
||||||
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
|
|
||||||
pub after: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
pub enum ProjectCommands {
|
pub enum ProjectCommands {
|
||||||
List {},
|
List {},
|
||||||
Create { name: String },
|
Create {},
|
||||||
Delete { name: String },
|
Delete { name: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
pub enum ConfigCommands {
|
pub enum ConfigCommands {
|
||||||
List {},
|
List {},
|
||||||
Create { project: String, name: String },
|
Create { project: String },
|
||||||
Delete { project: String, name: String },
|
Delete { project: String, name: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_or_get_key() -> Result<crypto::Key, Box<dyn Error>> {
|
pub mod interactions {
|
||||||
|
use super::db::models::{NewProject, Project};
|
||||||
|
use super::db::{
|
||||||
|
establish_connection,
|
||||||
|
schema::projects::dsl::{name as project_name, projects},
|
||||||
|
};
|
||||||
|
use diesel::result::{DatabaseErrorKind, Error as DieselError};
|
||||||
|
use diesel::{ExpressionMethods, OptionalExtension, QueryDsl, RunQueryDsl, SelectableHelper};
|
||||||
|
use std::error::Error;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
fn construct_error(message: &str) -> Result<(), Box<dyn Error>> {
|
||||||
|
Err(Box::new(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::AlreadyExists,
|
||||||
|
message.to_string(),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_project(proj_name: &str) -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut conn = establish_connection();
|
||||||
|
|
||||||
|
// 1. Check if the project already exists
|
||||||
|
let existing_project = projects
|
||||||
|
.filter(project_name.eq(proj_name))
|
||||||
|
.select(Project::as_select())
|
||||||
|
.first::<Project>(&mut conn)
|
||||||
|
.optional()?;
|
||||||
|
|
||||||
|
if let Some(_) = existing_project {
|
||||||
|
return construct_error("Project already exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
let project_id = Uuid::new_v4().to_string();
|
||||||
|
let new_project = NewProject {
|
||||||
|
id: &project_id,
|
||||||
|
name: proj_name,
|
||||||
|
};
|
||||||
|
|
||||||
|
match diesel::insert_into(projects)
|
||||||
|
.values(&new_project)
|
||||||
|
.execute(&mut conn)
|
||||||
|
{
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(DieselError::DatabaseError(DatabaseErrorKind::UniqueViolation, _)) => {
|
||||||
|
construct_error("Project already exists")
|
||||||
|
}
|
||||||
|
Err(err) => Err(Box::new(err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen_or_get_key() -> Result<crypto::Key, Box<dyn Error>> {
|
||||||
let entry = Entry::new("harbor", "encryption-key")?;
|
let entry = Entry::new("harbor", "encryption-key")?;
|
||||||
|
|
||||||
match entry.get_password() {
|
match entry.get_password() {
|
||||||
@@ -84,3 +134,17 @@ fn gen_or_get_key() -> Result<crypto::Key, Box<dyn Error>> {
|
|||||||
Err(err) => Err(Box::new(err)),
|
Err(err) => Err(Box::new(err)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_input(message: &str, prompt: char, new_line: bool) -> Result<String, Box<dyn Error>> {
|
||||||
|
let mut input = String::new();
|
||||||
|
|
||||||
|
if new_line {
|
||||||
|
print!("{}\n{} ", message, prompt);
|
||||||
|
} else {
|
||||||
|
print!("{}{} ", message, prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
io::stdout().flush()?;
|
||||||
|
io::stdin().read_line(&mut input)?;
|
||||||
|
Ok(input.trim().to_string())
|
||||||
|
}
|
||||||
|
|||||||
+66
-2
@@ -3,6 +3,7 @@ use std::process;
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use clap::crate_version;
|
use clap::crate_version;
|
||||||
use cli::Cli;
|
use cli::Cli;
|
||||||
|
use cli::get_input;
|
||||||
use colored::*;
|
use colored::*;
|
||||||
|
|
||||||
const GIT_VERSION: &str = env!("GIT_VERSION");
|
const GIT_VERSION: &str = env!("GIT_VERSION");
|
||||||
@@ -20,12 +21,75 @@ fn main() {
|
|||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if cli.command.is_none() {
|
match cli.command {
|
||||||
|
Some(c) => match c {
|
||||||
|
cli::Commands::Add {} => {
|
||||||
|
println!("Add command executed");
|
||||||
|
}
|
||||||
|
cli::Commands::Config { command } => match command {
|
||||||
|
cli::ConfigCommands::List {} => {
|
||||||
|
println!("Config list command executed");
|
||||||
|
}
|
||||||
|
cli::ConfigCommands::Create { project } => {
|
||||||
|
println!("Config create command executed for project: {}", project);
|
||||||
|
}
|
||||||
|
cli::ConfigCommands::Delete { project, name } => {
|
||||||
|
println!(
|
||||||
|
"Config delete command executed for project: {}, name: {}",
|
||||||
|
project, name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cli::Commands::Inject { verbose, after } => {
|
||||||
|
println!(
|
||||||
|
"Inject command executed with verbose: {}, after: {:?}",
|
||||||
|
verbose, after
|
||||||
|
);
|
||||||
|
// for harbor inject -- bun dev
|
||||||
|
// after = ["bun", "dev"]
|
||||||
|
}
|
||||||
|
cli::Commands::List {} => {
|
||||||
|
println!("List command executed");
|
||||||
|
}
|
||||||
|
cli::Commands::Project { command } => match command {
|
||||||
|
cli::ProjectCommands::List {} => {
|
||||||
|
println!("Project list command executed");
|
||||||
|
}
|
||||||
|
cli::ProjectCommands::Create {} => {
|
||||||
|
let project_name = match get_input("Project name", ':', false) {
|
||||||
|
Ok(name) => name,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error getting project name: {}", e);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match cli::interactions::create_project(&project_name) {
|
||||||
|
Ok(()) => println!("{}", "Project created successfully".blue()),
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error creating project: {}", e);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cli::ProjectCommands::Delete { name } => {
|
||||||
|
println!("Project delete command executed for name: {}", name);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cli::Commands::Shell {} => {
|
||||||
|
println!("Shell command executed");
|
||||||
|
}
|
||||||
|
cli::Commands::Setup {} => {
|
||||||
|
println!("Setup command executed");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
println!(
|
println!(
|
||||||
"{}\n{}",
|
"{}\n{}",
|
||||||
"No command was entered.".red(),
|
"No command was entered.".red(),
|
||||||
"Exiting...".dimmed()
|
"Use --help for more information.".dimmed()
|
||||||
);
|
);
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user