Skip to content
This repository has been archived by the owner on Dec 15, 2024. It is now read-only.

Commit

Permalink
refactor: write default config dirs relatively to exec bin
Browse files Browse the repository at this point in the history
  • Loading branch information
sripwoud committed Dec 13, 2024
1 parent f5a2517 commit bbf812c
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 63 deletions.
9 changes: 4 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
.envrc
.tool-versions

apps/server/freedit.db*
apps/server/freedit.db
apps/server/config.toml
apps/server/static/imgs
apps/server/snapshots
apps/server/tantivy
certs
freedit.db
snapshots
static/imgs
tantivy
target

bun.lockb
Expand Down
28 changes: 19 additions & 9 deletions .justfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,32 @@ build:

[working-directory: 'apps/client']
build-client:
bun tsc -b && bun vite build
@bun tsc -b
bun vite build

[working-directory: 'apps/server']
build-server:
cargo build -r
@cargo build -r

clean-server:
@rm -fr apps/server/{config.toml,freedit.db,snapshots,static/imgs,tantivy,target}

dev:
@echo "Starting freeding server and web client..."
just dev-client &
just dev-server
@just dev-client & just dev-server

[working-directory: 'apps/client']
dev-client:
bun vite dev
@bun vite dev

[working-directory: 'apps/server']
dev-server:
cargo run
@cargo run

start:
@just start-server & just start-client

start-server:
@./apps/server/target/release/freedit

preview:
vite preview
start-client:
@vite preview
2 changes: 2 additions & 0 deletions apps/server/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
target-dir = "../../apps/server/target"
118 changes: 88 additions & 30 deletions apps/server/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,72 +1,130 @@
use serde::{Deserialize, Serialize};
use std::env;
use std::fs::{self, read_to_string, File};
use std::io::Write;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::sync::LazyLock;
use tracing::{info, warn};

pub static CONFIG: LazyLock<Config> = LazyLock::new(Config::load_config);

#[derive(Serialize, Deserialize)]
pub struct Config {
pub db: String,
pub db: PathBuf,
pub snapshots_path: PathBuf,
pub addr: String,
pub rebuild_index: Option<bool>,
pub(crate) avatars_path: String,
pub(crate) inn_icons_path: String,
pub(crate) upload_path: String,
pub(crate) tantivy_path: String,
pub(crate) avatars_path: PathBuf,
pub(crate) inn_icons_path: PathBuf,
pub(crate) upload_path: PathBuf,
pub(crate) tantivy_path: PathBuf,
pub(crate) proxy: String,
}

impl Config {
fn load_config() -> Config {
let cfg_file = std::env::args()
.nth(1)
.unwrap_or_else(|| "config.toml".to_owned());
let config = if let Ok(config_toml_content) = read_to_string(cfg_file) {
let config: Config = basic_toml::from_str(&config_toml_content).unwrap();
let exe_path = env::current_exe().expect("Failed to get current executable path");
let exe_dir = exe_path
.parent()
.expect("Fialed to get executable directory")
.parent()
.expect("Failed to get target directory")
.parent()
.expect("Failed to get server directory");

let cfg_file = exe_dir.join(
env::args()
.nth(1)
.unwrap_or_else(|| "config.toml".to_owned()),
);
let config = if let Ok(config_toml_content) = read_to_string(&cfg_file) {
let mut config: Config =
basic_toml::from_str(&config_toml_content).expect("Failed to parse config.toml");
config.resolve_paths(&exe_dir);
config
} else {
warn!("Config file not found, using default config.toml");
let config = Config::default();
let toml = basic_toml::to_string(&config).unwrap();
let mut cfg_file = File::create("config.toml").unwrap();
cfg_file.write_all(toml.as_bytes()).unwrap();
let mut config = Config::default();
config.resolve_paths(&exe_dir);
let toml = basic_toml::to_string(&config).expect("Failed to serialize config.toml");
let mut file = File::create(&cfg_file).expect("Failed to create config.toml file");
file.write_all(toml.as_bytes())
.expect("Failed to write to config.toml");
info!("Wrote default config file at {}", &cfg_file.display());
config
};

check_path(&config.avatars_path);
check_path(&config.inn_icons_path);
check_path(&config.upload_path);
check_path(&config.tantivy_path);

config.ensure_dirs();
config
}

fn resolve_paths(&mut self, base_dir: &Path) {
let path_fields: &mut [&mut PathBuf] = &mut [
&mut self.db,
&mut self.snapshots_path,
&mut self.avatars_path,
&mut self.inn_icons_path,
&mut self.upload_path,
&mut self.tantivy_path,
];

for p in path_fields.iter_mut() {
**p = resolve_path(base_dir, p.as_path());
}
}

fn ensure_dirs(&self) {
let path_fields = [
&self.db,
&self.snapshots_path,
&self.avatars_path,
&self.inn_icons_path,
&self.upload_path,
&self.tantivy_path,
];

for path in &path_fields {
check_path(path);
}
}
}

impl Default for Config {
fn default() -> Self {
Config {
db: "freedit.db".into(),
db: PathBuf::from("freedit.db"),
snapshots_path: PathBuf::from("snapshots"),
addr: "127.0.0.1:3001".into(),
rebuild_index: None,
avatars_path: "static/imgs/avatars".into(),
inn_icons_path: "static/imgs/inn_icons".into(),
upload_path: "static/imgs/upload".into(),
tantivy_path: "tantivy".into(),
avatars_path: PathBuf::from("static/imgs/avatars"),
inn_icons_path: PathBuf::from("static/imgs/inn_icons"),
upload_path: PathBuf::from("static/imgs/upload"),
tantivy_path: PathBuf::from("tantivy"),
proxy: "".into(),
}
}
}

/// Resolve a PathBuf relative to base_dir if it's not absolute
fn resolve_path(base_dir: &Path, path: &Path) -> PathBuf {
if path.is_absolute() {
path.to_path_buf()
} else {
base_dir.join(path)
}
}

/// Create new dir if the path doesn't exist.
fn check_path(path_str: &str) {
let path = Path::new(path_str);
fn check_path(path: &Path) {
if !path.exists() {
fs::create_dir_all(path).unwrap();
info!("create path: {}", path_str);
fs::create_dir_all(path).unwrap_or_else(|_| {
panic!(
"Failed to created necessary dir at {:?}",
path.canonicalize().unwrap_or_else(|_| path.to_path_buf())
)
});
info!("Created dir: {:?}", path);
} else {
info!("{path_str} is ok");
info!("Dir already exists {:?}", path);
}
}
8 changes: 4 additions & 4 deletions apps/server/src/controller/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ pub(crate) async fn upload_pic_post(
return Err(AppError::Unauthorized);
}
target = format!("/mod/{iid}");
format!("{}/{}.png", &CONFIG.inn_icons_path, iid)
format!("{}/{}.png", &CONFIG.inn_icons_path.display(), iid)
} else {
return Err(AppError::NotFound);
}
}
"user" => {
target = "/user/setting".to_string();
format!("{}/{}.png", &CONFIG.avatars_path, claim.uid)
format!("{}/{}.png", &CONFIG.avatars_path.display(), claim.uid)
}
_ => unreachable!(),
};
Expand Down Expand Up @@ -177,7 +177,7 @@ pub(crate) async fn image_delete(

if count == 0 {
let img = String::from_utf8_lossy(&v1);
let path = format!("{}/{}", CONFIG.upload_path, img);
let path = format!("{}/{}", CONFIG.upload_path.display(), img);
remove_file(path).await?;
}
} else {
Expand Down Expand Up @@ -315,7 +315,7 @@ pub(crate) async fn upload_post(
let digest = context.finish();
let sha1 = HEXLOWER.encode(digest.as_ref());
let fname = format!("{}.{}", &sha1[0..20], ext);
let location = format!("{}/{}", &CONFIG.upload_path, fname);
let location = format!("{}/{}", &CONFIG.upload_path.display(), fname);

fs::write(location, &img_data).await.unwrap();
let img_id = incr_id(&DB, "imgs_count")?;
Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/controller/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -987,7 +987,7 @@ pub(crate) async fn signup_post(
let password_hash = generate_password_hash(&input.password);
let uid = incr_id(&DB, "users_count")?;

let avatar = format!("{}/{}.png", &CONFIG.avatars_path, uid);
let avatar = format!("{}/{}.png", &CONFIG.avatars_path.display(), uid);
Identicon::new(&generate_salt()).image().save(avatar)?;

let created_at = Timestamp::now().as_second();
Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ pub static DB: LazyLock<Db> = LazyLock::new(|| {
let db_url = &CONFIG.db;
let config = sled::Config::default().path(db_url);
let db = config.open().unwrap();
info!(%db_url);
info!("{}", db_url.display());
db
});
7 changes: 1 addition & 6 deletions apps/server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,7 @@ async fn main() -> Result<(), AppError> {
#[cfg(not(debug_assertions))]
tokio::spawn(async move {
loop {
let snapshot_path = PathBuf::from("snapshots");
// create snapshot dir if needed
if !snapshot_path.exists() {
fs::create_dir_all(&snapshot_path).unwrap();
}
// create a snapshot
let snapshot_path = &CONFIG.snapshots_path;
create_snapshot(&snapshot_path, &DB);
// remove snapshots older than 48 hours
if let Err(e) = prune_snapshots(&snapshot_path) {
Expand Down
7 changes: 0 additions & 7 deletions config.toml

This file was deleted.

0 comments on commit bbf812c

Please sign in to comment.