add command line arguments
This commit is contained in:
@@ -26,6 +26,7 @@ itertools = "0.10.0"
|
||||
json_dotpath = "1.0.3"
|
||||
anyhow = "1.0.38"
|
||||
thiserror = "1.0.24"
|
||||
clap = "2"
|
||||
|
||||
tokio = { version="0.2.6", features=["full"] }
|
||||
|
||||
|
||||
+68
-16
@@ -7,18 +7,19 @@ extern crate thiserror;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use actix_session::CookieSession;
|
||||
use actix_web::{web, App, HttpResponse, HttpServer};
|
||||
use actix_web::{App, HttpResponse, HttpServer, web};
|
||||
use actix_web_static_files;
|
||||
use actix_web_static_files::ResourceFiles as StaticFiles;
|
||||
use clap::Arg;
|
||||
use log::LevelFilter;
|
||||
use once_cell::sync::Lazy;
|
||||
use rand::Rng;
|
||||
use tera::Tera;
|
||||
|
||||
use yopa::insert::{InsertObj, InsertRel, InsertValue};
|
||||
use yopa::{Storage, TypedValue};
|
||||
use yopa::{Storage};
|
||||
|
||||
use crate::tera_ext::TeraExt;
|
||||
|
||||
@@ -101,25 +102,83 @@ pub(crate) static TERA: Lazy<Tera> = Lazy::new(|| {
|
||||
|
||||
type YopaStoreWrapper = web::Data<tokio::sync::RwLock<yopa::Storage>>;
|
||||
|
||||
const DEF_ADDRESS : &str = "127.0.0.1:8080";
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
simple_logging::log_to_stderr(LevelFilter::Debug);
|
||||
let def_addr_help = format!("Set custom server address, default {}", DEF_ADDRESS);
|
||||
let app = clap::App::new("yopa")
|
||||
.arg(Arg::with_name("version")
|
||||
.long("version")
|
||||
.short("V")
|
||||
.help("Show version and exit"))
|
||||
.arg(Arg::with_name("verbose")
|
||||
.short("v")
|
||||
.multiple(true)
|
||||
.help("Increase verbosity of logging"))
|
||||
.arg(Arg::with_name("address")
|
||||
.short("a")
|
||||
.takes_value(true)
|
||||
.help(&def_addr_help))
|
||||
.arg(Arg::with_name("json")
|
||||
.long("json")
|
||||
.short("j")
|
||||
.help("Use JSON storage format instead of binary"))
|
||||
.arg(Arg::with_name("file")
|
||||
.help("Database file to use"));
|
||||
|
||||
let matches = app.get_matches();
|
||||
|
||||
if matches.is_present("version") {
|
||||
println!("yopa-web {}, using yopa {}", env!("CARGO_PKG_VERSION"), yopa::VERSION);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
simple_logging::log_to_stderr(match matches.occurrences_of("verbose") {
|
||||
0 => LevelFilter::Warn,
|
||||
1 => LevelFilter::Info,
|
||||
2 => LevelFilter::Debug,
|
||||
_ => LevelFilter::Trace,
|
||||
});
|
||||
|
||||
debug!("Load Tera templates");
|
||||
// Ensure the lazy ref is initialized early (to catch template bugs ASAP)
|
||||
let _ = TERA.deref();
|
||||
|
||||
let yopa_store: YopaStoreWrapper = init_yopa()
|
||||
let file = matches.value_of("file").unwrap_or("yopa-store.dat");
|
||||
|
||||
let file_path = if file.starts_with('/') {
|
||||
std::env::current_dir()?.join(file)
|
||||
} else {
|
||||
PathBuf::from(file)
|
||||
};
|
||||
|
||||
debug!("Using database file: {}", file_path.display());
|
||||
|
||||
let mut store = if matches.is_present("json") {
|
||||
Storage::new_json(file_path)
|
||||
} else {
|
||||
Storage::new_bincode(file_path)
|
||||
};
|
||||
|
||||
store.load()
|
||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
||||
|
||||
let yopa_store: YopaStoreWrapper = web::Data::new(tokio::sync::RwLock::new(store));
|
||||
|
||||
let mut session_key = [0u8; 32];
|
||||
rand::thread_rng().fill(&mut session_key);
|
||||
trace!("Cookie session key: {:?}", session_key);
|
||||
|
||||
debug!("Session key: {:?}", session_key);
|
||||
let server_address = matches.value_of("address").unwrap_or(DEF_ADDRESS);
|
||||
|
||||
println!("Starting web interface at http://{}", server_address);
|
||||
|
||||
HttpServer::new(move || {
|
||||
let static_files =
|
||||
StaticFiles::new("/static", included_static_files()).do_not_resolve_defaults();
|
||||
|
||||
debug!("Starting server thread");
|
||||
App::new()
|
||||
/* Middlewares */
|
||||
.wrap(CookieSession::signed(&session_key).secure(false))
|
||||
@@ -162,14 +221,7 @@ async fn main() -> std::io::Result<()> {
|
||||
HttpResponse::NotFound().body("File or endpoint not found")
|
||||
}))
|
||||
})
|
||||
.bind("127.0.0.1:8080")?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
|
||||
fn init_yopa() -> anyhow::Result<YopaStoreWrapper> {
|
||||
let mut store = Storage::new_bincode(std::env::current_dir()?.join("yopa-store.dat"));
|
||||
store.load()?;
|
||||
|
||||
Ok(web::Data::new(tokio::sync::RwLock::new(store)))
|
||||
.bind(server_address)?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -125,15 +125,12 @@ pub(crate) async fn update(
|
||||
|
||||
#[get("/model/object/delete/{id}")]
|
||||
pub(crate) async fn delete(
|
||||
id: web::Path<String>,
|
||||
id: web::Path<ID>,
|
||||
store: crate::YopaStoreWrapper,
|
||||
session: Session,
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let mut wg = store.write().await;
|
||||
match wg.undefine_object(
|
||||
id.parse()
|
||||
.map_err(|e| actix_web::error::ErrorBadRequest(e))?,
|
||||
) {
|
||||
match wg.undefine_object(*id) {
|
||||
Ok(om) => {
|
||||
wg.persist().err_to_500()?;
|
||||
debug!("Object model deleted, redirecting to root");
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::TERA;
|
||||
|
||||
#[get("/model/property/create/{object_id}")]
|
||||
pub(crate) async fn create_form(
|
||||
object_id: web::Path<String>,
|
||||
id: web::Path<ID>,
|
||||
store: crate::YopaStoreWrapper,
|
||||
session: Session,
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
@@ -39,17 +39,16 @@ pub(crate) async fn create_form(
|
||||
);
|
||||
}
|
||||
|
||||
debug!("ID = {}", object_id);
|
||||
debug!("ID = {}", id);
|
||||
|
||||
let object = {
|
||||
let id = object_id.parse_or_bad_request()?;
|
||||
debug!("Create property for ID={}", id);
|
||||
if let Some(om) = rg.get_object_model(id) {
|
||||
if let Some(om) = rg.get_object_model(*id) {
|
||||
ObjectOrRelationModelDisplay {
|
||||
id: om.id,
|
||||
describe: format!("object model \"{}\"", om.name),
|
||||
}
|
||||
} else if let Some(rm) = rg.get_relation_model(id) {
|
||||
} else if let Some(rm) = rg.get_relation_model(*id) {
|
||||
ObjectOrRelationModelDisplay {
|
||||
id: rm.id,
|
||||
describe: format!("relation model \"{}\"", rm.name),
|
||||
@@ -164,12 +163,12 @@ pub(crate) async fn create(
|
||||
|
||||
#[get("/model/property/delete/{id}")]
|
||||
pub(crate) async fn delete(
|
||||
id: web::Path<String>,
|
||||
id: web::Path<ID>,
|
||||
store: crate::YopaStoreWrapper,
|
||||
session: Session,
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let mut wg = store.write().await;
|
||||
match wg.undefine_property(id.parse_or_bad_request()?) {
|
||||
match wg.undefine_property(*id) {
|
||||
Ok(rm) => {
|
||||
wg.persist().err_to_500()?;
|
||||
debug!("Property deleted, redirecting to root");
|
||||
|
||||
@@ -19,7 +19,7 @@ pub(crate) struct RelationModelDisplay<'a> {
|
||||
|
||||
#[get("/model/relation/create/{object_id}")]
|
||||
pub(crate) async fn create_form(
|
||||
object_id: web::Path<String>,
|
||||
object_id: web::Path<ID>,
|
||||
store: crate::YopaStoreWrapper,
|
||||
session: Session,
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
@@ -47,7 +47,7 @@ pub(crate) async fn create_form(
|
||||
}
|
||||
|
||||
let object = rg
|
||||
.get_object_model(object_id.parse_or_bad_request()?)
|
||||
.get_object_model(*object_id)
|
||||
.ok_or_else(|| actix_web::error::ErrorNotFound("No such source object"))?;
|
||||
|
||||
let mut models: Vec<_> = rg.get_object_models().collect();
|
||||
@@ -112,12 +112,12 @@ pub(crate) struct ObjectOrRelationModelDisplay {
|
||||
|
||||
#[get("/model/relation/delete/{id}")]
|
||||
pub(crate) async fn delete(
|
||||
id: web::Path<String>,
|
||||
id: web::Path<ID>,
|
||||
store: crate::YopaStoreWrapper,
|
||||
session: Session,
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let mut wg = store.write().await;
|
||||
match wg.undefine_relation(id.parse_or_bad_request()?) {
|
||||
match wg.undefine_relation(*id) {
|
||||
Ok(rm) => {
|
||||
wg.persist().err_to_500()?;
|
||||
debug!("Relation deleted, redirecting to root");
|
||||
|
||||
@@ -499,8 +499,6 @@ pub(crate) async fn update(
|
||||
store: crate::YopaStoreWrapper,
|
||||
session: Session,
|
||||
) -> actix_web::Result<HttpResponse> {
|
||||
warn!("{:?}", form);
|
||||
|
||||
let mut wg = store.write().await;
|
||||
let form = form.into_inner();
|
||||
let name = form.name.clone();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use actix_web::http::header::IntoHeaderValue;
|
||||
use actix_web::{HttpResponse, ResponseError, Error};
|
||||
use actix_web::{HttpResponse, ResponseError};
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::str::FromStr;
|
||||
use yopa::StorageError;
|
||||
|
||||
Reference in New Issue
Block a user