Pour tout problème contactez-nous par mail : support@froggit.fr | La FAQ :grey_question: | Rejoignez-nous sur le Chat :speech_balloon:

Skip to content
Snippets Groups Projects
Commit c16417d7 authored by peterrabbit's avatar peterrabbit
Browse files

parse cli args

parent eb3cb869
No related branches found
No related tags found
No related merge requests found
......@@ -277,6 +277,26 @@ dependencies = [
"alloc-no-stdlib",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
......@@ -370,6 +390,21 @@ dependencies = [
"generic-array",
]
[[package]]
name = "clap"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "cms_rust"
version = "0.1.0"
......@@ -382,6 +417,7 @@ dependencies = [
"rustls-pemfile",
"serde",
"serde_json",
"structopt",
]
[[package]]
......@@ -622,6 +658,15 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
......@@ -723,6 +768,12 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.127"
......@@ -901,6 +952,30 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.43"
......@@ -1164,6 +1239,36 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "structopt"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
dependencies = [
"clap",
"lazy_static",
"structopt-derive",
]
[[package]]
name = "structopt-derive"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "subtle"
version = "2.4.1"
......@@ -1181,6 +1286,15 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.32"
......@@ -1327,6 +1441,18 @@ dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "universal-hash"
version = "0.4.1"
......@@ -1355,6 +1481,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.4"
......
......@@ -14,3 +14,4 @@ serde_json = "1.0.83"
regex = "1.6"
fs_extra = "1.2"
dirs = "4.0"
structopt = "0.3"
use std::path::PathBuf;
use structopt::StructOpt;
#[derive(Clone)]
pub enum AppContext {
Debug,
Production,
}
#[derive(Clone, StructOpt)]
pub struct AppArgs {
#[structopt(short = "c", long = "ctx", default_value = "debug")]
pub context: String,
#[structopt(short = "d", long = "dir")]
pub app_storage_root: Option<PathBuf>,
#[structopt(long)]
pub load: Option<PathBuf>,
#[structopt(short, long, default_value = "localhost")]
pub host: String,
#[structopt(short, long, default_value = "8080")]
pub port: u16,
#[structopt(long = "ptls", default_value = "8443")]
pub port_tls: u16,
#[structopt(long = "certs_dir", default_value = "/etc/letsencrypt/live")]
pub ssl_certs_dir: PathBuf,
}
#[derive(Clone)]
pub struct AppConfig {
pub exec_path: PathBuf,
pub exec_name: String,
pub context: AppContext,
pub storage_dir: PathBuf,
pub host: String,
pub port: u16,
pub port_tls: u16,
pub load: Option<PathBuf>,
pub ssl_certs_dir: PathBuf,
}
impl AppConfig {
pub fn new() -> Self {
let app_args = AppArgs::from_args();
let exec_path = std::env::current_exe().unwrap();
let exec_name = exec_path
.file_name()
.expect("Unable to get executable name")
.to_str()
.unwrap()
.to_string();
let context = match app_args.context.as_str() {
"prod" => AppContext::Production,
_ => AppContext::Debug,
};
let storage_dir = match &app_args.app_storage_root {
Some(dir) => dir.join(&exec_name),
None => match context {
AppContext::Production => PathBuf::from("/var").join(&exec_name),
AppContext::Debug => dirs::home_dir()
.expect("Unable to get home dir")
.join(&exec_name),
},
};
let ssl_certs_dir = app_args.ssl_certs_dir.join(&app_args.host);
AppConfig {
exec_path: std::path::PathBuf::from(exec_path),
exec_name,
context,
storage_dir,
host: app_args.host,
port: app_args.port,
port_tls: app_args.port_tls,
load: app_args.load,
ssl_certs_dir,
}
}
}
#[derive(Clone)]
pub struct AppState {
pub config: AppConfig,
pub preferences: AppPreference,
//
}
#[derive(Clone)]
pub struct AppPreference {}
impl AppState {
pub fn new() -> Self {
AppState {
config: AppConfig::new(),
preferences: AppPreference {},
}
}
}
mod app_state;
mod static_files;
mod tls_config;
mod website;
use actix_web::{get, App, HttpResponse, HttpServer, Responder};
use app_state::AppState;
use static_files::StaticFilesManager;
use std::path::PathBuf;
use tls_config::tls_config;
use website::WebSite;
fn load_website_template() -> WebSite {
let site_template_path = std::env::current_dir()
.unwrap()
.join("templates")
.join("new_website.json");
let site_template = std::fs::read_to_string(site_template_path).unwrap();
WebSite::from_json_str(&site_template)
}
#[get("/{pth:.*}")]
async fn page(
website: actix_web::web::Data<WebSite>,
......@@ -38,57 +33,35 @@ async fn admin_login() -> impl Responder {
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let website = load_website_template();
let site_name = "rust_cms".to_string(); // Get from arg
let mut static_files_manager = StaticFilesManager::new(&site_name).unwrap();
let app_state = AppState::new();
let website = WebSite::load(&app_state.config);
let mut static_files_manager = StaticFilesManager::new(&app_state).unwrap();
static_files_manager.build_index().unwrap();
// GET HOST AND CERTS DIR FROM CLI ARGUMENT
// Get port from arg, or get context from arg and define default port, or set default port to standard
// LOAD A WEBSITE SCHEMA (JSON) FROM CLI ARGUMENT PATH OR search in /var/{sitename} and load it CREATE A NEW ONE
// create pages resources with templates and the contents from the json file
// Save the resources in an appstate
// create the static dir in standard location if doesn't exist (like /var/{sitename}/static)
// create the static files index (like Arc<Mutex<StaticFilesIndex>>)
let host = "localhost";
let certs_dir = PathBuf::from("/etc/letsencrypt/live").join(host);
let cert_file =
&mut std::io::BufReader::new(std::fs::File::open(certs_dir.join("fullchain.pem")).unwrap());
let key_file =
&mut std::io::BufReader::new(std::fs::File::open(certs_dir.join("privkey.pem")).unwrap());
let cert = rustls::Certificate(rustls_pemfile::certs(cert_file).unwrap().remove(0).to_vec());
let host = app_state.config.host.clone();
let port = app_state.config.port;
let port_tls = app_state.config.port_tls;
let key = rustls::PrivateKey(
rustls_pemfile::pkcs8_private_keys(key_file)
.unwrap()
.remove(0)
.to_vec(),
);
let srv_conf = rustls::ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(vec![cert], key)
.expect("bad certificate/key");
let srv_conf = tls_config(&app_state.config);
let static_files_manager =
actix_web::web::Data::new(std::sync::Mutex::new(static_files_manager));
let app_state = actix_web::web::Data::new(std::sync::Mutex::new(app_state));
HttpServer::new(move || {
App::new()
.wrap(actix_web::middleware::Logger::default())
.wrap(actix_web::middleware::Compress::default())
.app_data(actix_web::web::Data::new(website.clone()))
.app_data(actix_web::web::Data::clone(&app_state))
.app_data(actix_web::web::Data::clone(&static_files_manager))
.app_data(actix_web::web::Data::new(website.clone()))
.service(admin_dashboard)
.service(admin_login)
.service(page)
})
.bind("127.0.0.1:8080")?
.bind_rustls("127.0.0.1:8443", srv_conf)?
.bind(format!("{}:{}", host, port))?
.bind_rustls(format!("{}:{}", host, port_tls), srv_conf)?
.run()
.await
}
use crate::app_state::AppState;
use std::path::PathBuf;
#[derive(Clone)]
pub struct StaticFilesManager {
dir: PathBuf,
index: Vec<String>,
}
impl StaticFilesManager {
fn create_dir_if_missing(app_dir: &PathBuf) -> Result<(), String> {
let static_path = app_dir.join("static");
if !static_path.exists() {
match std::fs::create_dir_all(static_path) {
Ok(_) => return Self::copy_default(&app_dir),
fn create_dir_if_missing(app_dir: &PathBuf) -> Result<PathBuf, String> {
let static_dir = app_dir.join("static");
if !static_dir.exists() {
match std::fs::create_dir_all(&static_dir) {
Ok(_) => {
if let Err(err) = Self::copy_default(&static_dir) {
return Err(format!("{}", err));
}
}
Err(err) => return Err(format!("{}", err)),
}
}
Ok(())
Ok(static_dir)
}
fn copy_default(app_dir: &PathBuf) -> Result<(), String> {
let local_default = std::env::current_dir().unwrap().join("default_static");
let standard_default = app_dir.join("static").join("default");
if let Err(err) = std::fs::create_dir_all(&standard_default) {
return Err(format!("{}", err));
fn copy_default(static_dir: &PathBuf) -> Result<(), String> {
let local_default_static = std::env::current_dir().unwrap().join("default_static");
let default_static = static_dir.join("default");
match std::fs::create_dir_all(&default_static) {
Err(err) => Err(format!("{}", err)),
Ok(_) => {
let mut copy_default_options = fs_extra::dir::CopyOptions::new();
copy_default_options.content_only = true;
match fs_extra::dir::copy(
local_default_static,
default_static,
&copy_default_options,
) {
Err(err) => Err(format!("{}", err)),
Ok(_) => Ok(()),
}
}
}
let mut copy_default_options = fs_extra::dir::CopyOptions::new();
copy_default_options.content_only = true;
if let Err(err) =
fs_extra::dir::copy(local_default, standard_default, &copy_default_options)
{
return Err(format!("{}", err));
};
Ok(())
}
pub fn new(website_name: &String) -> Result<Self, String> {
if let Err(err) = Self::create_dir_if_missing(&dirs::home_dir().unwrap().join(website_name))
{
return Err(err);
pub fn new(app_state: &AppState) -> Result<Self, String> {
match Self::create_dir_if_missing(&app_state.config.storage_dir) {
Ok(dir) => Ok(StaticFilesManager {
index: Vec::new(),
dir,
}),
Err(msg) => Err(msg),
}
Ok(StaticFilesManager { index: Vec::new() })
}
pub fn build_index(&mut self) -> Result<(), String> {
......
use crate::app_state::AppConfig;
pub fn tls_config(app_config: &AppConfig) -> rustls::ServerConfig {
let certs_dir = app_config.ssl_certs_dir.clone();
let cert_file =
&mut std::io::BufReader::new(std::fs::File::open(certs_dir.join("fullchain.pem")).unwrap());
let key_file =
&mut std::io::BufReader::new(std::fs::File::open(certs_dir.join("privkey.pem")).unwrap());
let cert = rustls::Certificate(rustls_pemfile::certs(cert_file).unwrap().remove(0).to_vec());
let key = rustls::PrivateKey(
rustls_pemfile::pkcs8_private_keys(key_file)
.unwrap()
.remove(0)
.to_vec(),
);
rustls::ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(vec![cert], key)
.expect("bad certificate/key")
}
use crate::app_state::AppConfig;
use regex::{Captures, Regex};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
......@@ -102,6 +103,18 @@ impl WebSite {
WebSite::new(serde_json::from_str(json).unwrap())
}
pub fn load(config: &AppConfig) -> WebSite {
let file_path = match &config.load {
None => std::env::current_dir()
.unwrap()
.join("templates")
.join("new_website.json"),
Some(pth) => pth.clone(),
};
WebSite::from_json_str(&std::fs::read_to_string(file_path).unwrap())
}
fn create_index_by_url(
index: &mut HashMap<PathBuf, WebPage>,
pages_tree: &PagesTree,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment