generated from pure_sagacity/rust-starter
added database stuff
added clap arguments added the gen_or_get_key func in lib git ignore for .env migrations
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
use diesel::prelude::*;
|
||||
use dotenvy::dotenv;
|
||||
use std::env;
|
||||
|
||||
pub mod models;
|
||||
pub mod schema;
|
||||
|
||||
pub fn establish_connection() -> SqliteConnection {
|
||||
dotenv().ok();
|
||||
|
||||
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||
SqliteConnection::establish(&database_url)
|
||||
.unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
use crate::db::schema::{projects, secrets};
|
||||
use chrono::NaiveDateTime;
|
||||
use diesel::prelude::*;
|
||||
|
||||
#[derive(Debug, Queryable, Selectable)]
|
||||
#[diesel(table_name = projects)]
|
||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
||||
pub struct Project {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub created_at: NaiveDateTime,
|
||||
}
|
||||
|
||||
#[derive(Debug, Queryable, Selectable)]
|
||||
#[diesel(table_name = secrets)]
|
||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
||||
pub struct Secret {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub project_id: String,
|
||||
pub config: String,
|
||||
pub secret: Vec<u8>,
|
||||
pub nonce: Vec<u8>,
|
||||
pub created_at: NaiveDateTime,
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// @generated automatically by Diesel CLI.
|
||||
|
||||
diesel::table! {
|
||||
projects (id) {
|
||||
id -> Text,
|
||||
name -> Text,
|
||||
created_at -> Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
secrets (id) {
|
||||
id -> Text,
|
||||
name -> Text,
|
||||
project_id -> Text,
|
||||
config -> Text,
|
||||
secret -> Binary,
|
||||
nonce -> Binary,
|
||||
created_at -> Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::joinable!(secrets -> projects (project_id));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(projects, secrets,);
|
||||
@@ -1,4 +1,7 @@
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
use keyring::Entry;
|
||||
use std::error::Error;
|
||||
mod db;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(
|
||||
@@ -54,3 +57,39 @@ pub enum ConfigCommands {
|
||||
Create { project: String, name: String },
|
||||
Delete { project: String, name: String },
|
||||
}
|
||||
|
||||
pub fn gen_or_get_key() -> Result<crypto::Key, Box<dyn Error>> {
|
||||
let entry = Entry::new("harbor", "encryption-key")?;
|
||||
|
||||
match entry.get_password() {
|
||||
Ok(hex_string) => {
|
||||
let key_bytes = hex::decode(hex_string)?;
|
||||
|
||||
if key_bytes.len() != 32 {
|
||||
return Err("Retrieved key length is invalid (must be 32 bytes)".into());
|
||||
}
|
||||
|
||||
Ok(key_bytes
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.map_err(|_| "Invalid key length")?)
|
||||
}
|
||||
|
||||
Err(err) => {
|
||||
if is_key_not_found(&err) {
|
||||
let key = crypto::helper::gen_key();
|
||||
|
||||
let hex_string = hex::encode(key.as_slice());
|
||||
entry.set_password(&hex_string)?;
|
||||
|
||||
Ok(key)
|
||||
} else {
|
||||
Err(Box::new(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_key_not_found(err: &keyring::Error) -> bool {
|
||||
matches!(err, keyring::Error::NoEntry)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user