Remove dotenv
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
SSH_ENCRYPTION_KEY="bloop_ssh_key_32_characters_long"
|
||||
DATABASE_URL=sqlite::memory:
|
||||
ADMIN_PASSWORD=SOME_DEFAULT_PASSWORD
|
||||
JWT_SECRET="somesecret"
|
||||
@@ -21,7 +21,6 @@ tracing-subscriber = { workspace = true }
|
||||
sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "sqlite", "chrono", "uuid"] }
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
uuid = { version = "1.0", features = ["v4", "serde"] }
|
||||
dotenvy = "0.15"
|
||||
bcrypt = "0.15"
|
||||
jsonwebtoken = "9.2"
|
||||
ts-rs = { version = "9.0", features = ["uuid-impl", "chrono-impl"] }
|
||||
@@ -31,6 +30,7 @@ async-trait = "0.1"
|
||||
dissimilar = "1.0"
|
||||
rust-embed = "8.2"
|
||||
mime_guess = "2.0"
|
||||
directories = "6.0.0"
|
||||
|
||||
[build-dependencies]
|
||||
ts-rs = { version = "9.0", features = ["uuid-impl", "chrono-impl"] }
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
use axum::{
|
||||
async_trait,
|
||||
body::Body,
|
||||
extract::FromRequestParts,
|
||||
http::{request::Parts, Request, StatusCode},
|
||||
middleware::Next,
|
||||
response::Response,
|
||||
};
|
||||
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::SqlitePool;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Claims {
|
||||
pub user_id: Uuid,
|
||||
pub email: String,
|
||||
pub is_admin: bool,
|
||||
pub exp: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AuthUser {
|
||||
pub user_id: Uuid,
|
||||
pub email: String,
|
||||
pub is_admin: bool,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<S> FromRequestParts<S> for AuthUser
|
||||
where
|
||||
S: Send + Sync,
|
||||
{
|
||||
type Rejection = StatusCode;
|
||||
|
||||
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
|
||||
// Get user from request extensions (set by auth middleware)
|
||||
parts
|
||||
.extensions
|
||||
.get::<AuthUser>()
|
||||
.cloned()
|
||||
.ok_or(StatusCode::UNAUTHORIZED)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_token(
|
||||
user_id: Uuid,
|
||||
email: String,
|
||||
is_admin: bool,
|
||||
) -> Result<String, jsonwebtoken::errors::Error> {
|
||||
let jwt_secret = std::env::var("JWT_SECRET").unwrap_or_else(|_| "your-secret-key".to_string());
|
||||
|
||||
let expiration = chrono::Utc::now()
|
||||
.checked_add_signed(chrono::Duration::hours(24))
|
||||
.expect("valid timestamp")
|
||||
.timestamp() as usize;
|
||||
|
||||
let claims = Claims {
|
||||
user_id,
|
||||
email,
|
||||
is_admin,
|
||||
exp: expiration,
|
||||
};
|
||||
|
||||
encode(
|
||||
&Header::default(),
|
||||
&claims,
|
||||
&EncodingKey::from_secret(jwt_secret.as_ref()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn hash_password(password: &str) -> Result<String, bcrypt::BcryptError> {
|
||||
bcrypt::hash(password, bcrypt::DEFAULT_COST)
|
||||
}
|
||||
|
||||
pub fn verify_password(password: &str, hash: &str) -> Result<bool, bcrypt::BcryptError> {
|
||||
bcrypt::verify(password, hash)
|
||||
}
|
||||
|
||||
// Auth middleware that requires authentication for all routes
|
||||
pub async fn auth_middleware(
|
||||
mut request: Request<Body>,
|
||||
next: Next,
|
||||
) -> Result<Response, StatusCode> {
|
||||
let headers = request.headers();
|
||||
|
||||
let auth_header = headers
|
||||
.get("authorization")
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.ok_or(StatusCode::UNAUTHORIZED)?;
|
||||
|
||||
let token = auth_header
|
||||
.strip_prefix("Bearer ")
|
||||
.ok_or(StatusCode::UNAUTHORIZED)?;
|
||||
|
||||
let jwt_secret = std::env::var("JWT_SECRET").unwrap_or_else(|_| "your-secret-key".to_string());
|
||||
|
||||
let claims = decode::<Claims>(
|
||||
token,
|
||||
&DecodingKey::from_secret(jwt_secret.as_ref()),
|
||||
&Validation::default(),
|
||||
)
|
||||
.map_err(|_| StatusCode::UNAUTHORIZED)?
|
||||
.claims;
|
||||
|
||||
// Get database pool from request extensions
|
||||
let pool = request
|
||||
.extensions()
|
||||
.get::<SqlitePool>()
|
||||
.ok_or(StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
|
||||
// Note: User table removed, skipping database verification
|
||||
|
||||
// Add user info to request extensions for handlers to access
|
||||
request.extensions_mut().insert(AuthUser {
|
||||
user_id: claims.user_id,
|
||||
email: claims.email,
|
||||
is_admin: claims.is_admin,
|
||||
});
|
||||
|
||||
Ok(next.run(request).await)
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
pub mod auth;
|
||||
pub mod execution_monitor;
|
||||
pub mod executor;
|
||||
pub mod executors;
|
||||
|
||||
@@ -6,6 +6,7 @@ use axum::{
|
||||
routing::{get, post},
|
||||
Json, Router,
|
||||
};
|
||||
use directories::ProjectDirs;
|
||||
use rust_embed::RustEmbed;
|
||||
use sqlx::{sqlite::SqliteConnectOptions, SqlitePool};
|
||||
use std::str::FromStr;
|
||||
@@ -13,7 +14,6 @@ use std::{collections::HashMap, env, sync::Arc};
|
||||
use tokio::sync::Mutex;
|
||||
use tower_http::cors::CorsLayer;
|
||||
|
||||
mod auth;
|
||||
mod execution_monitor;
|
||||
mod executor;
|
||||
mod executors;
|
||||
@@ -83,11 +83,6 @@ async fn serve_file(path: &str) -> impl IntoResponse {
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
// Load environment variables from .env file
|
||||
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR")?;
|
||||
dotenvy::from_path(format!("{manifest_dir}/.env")).ok();
|
||||
// dotenvy::dotenv().ok();
|
||||
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(
|
||||
tracing_subscriber::EnvFilter::from_default_env()
|
||||
@@ -95,24 +90,16 @@ async fn main() -> anyhow::Result<()> {
|
||||
)
|
||||
.init();
|
||||
|
||||
// Create asset directory if it doesn't exist
|
||||
if !asset_dir().exists() {
|
||||
std::fs::create_dir_all(asset_dir())?;
|
||||
}
|
||||
|
||||
// Database connection
|
||||
let database_url =
|
||||
env::var("DATABASE_URL").expect("DATABASE_URL must be set in environment or .env file");
|
||||
|
||||
// if !Sqlite::database_exists(database_url).await.unwrap_or(false) {
|
||||
// println!("Creating database {}", DB_URL);
|
||||
// match Sqlite::create_database(DB_URL).await {
|
||||
// Ok(_) => println!("Create db success"),
|
||||
// Err(error) => panic!("error: {}", error),
|
||||
// }
|
||||
// } else {
|
||||
// println!("Database already exists");
|
||||
// }
|
||||
|
||||
// let pool = SqlitePoolOptions::new()
|
||||
// .max_connections(10)
|
||||
// .connect(&database_url)
|
||||
// .await?;
|
||||
let database_url = format!(
|
||||
"sqlite://{}",
|
||||
asset_dir().join("db.sqlite").to_string_lossy()
|
||||
);
|
||||
|
||||
let options = SqliteConnectOptions::from_str(&database_url)?.create_if_missing(true);
|
||||
let pool = SqlitePool::connect_with(options).await?;
|
||||
@@ -164,3 +151,14 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn asset_dir() -> std::path::PathBuf {
|
||||
// (“com”, “YourOrg”, “MyApp”) → tweak to suit your bundle ID
|
||||
let proj = ProjectDirs::from("ai", "bloop", env!("CARGO_PKG_NAME"))
|
||||
.expect("OS didn’t give us a home directory");
|
||||
|
||||
// ✔ macOS → ~/Library/Application Support/MyApp
|
||||
// ✔ Linux → ~/.local/share/myapp (respects XDG_DATA_HOME)
|
||||
// ✔ Windows → %APPDATA%\Example\MyApp
|
||||
proj.data_dir().to_path_buf()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user