wip
This commit is contained in:
parent
66b3a99814
commit
98be8dd574
13 changed files with 329 additions and 46 deletions
24
src/cli.rs
24
src/cli.rs
|
|
@ -1,10 +1,12 @@
|
|||
use argh::FromArgs;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use log::info;
|
||||
|
||||
|
||||
use crate::{get_app_context, server::{start_http_server, ServerConfig}};
|
||||
|
||||
#[derive(Debug, FromArgs)]
|
||||
/// Autotasker daemon
|
||||
struct CliFlags {
|
||||
struct ServerCliFlags {
|
||||
/// path to YAML config file to use to configure autotasker
|
||||
#[argh(option)]
|
||||
config: Option<String>,
|
||||
|
|
@ -25,4 +27,22 @@ struct CliFlags {
|
|||
listen_port: u32
|
||||
}
|
||||
|
||||
const DEFAULT_ASSETS_PATH: &'static str = &"/usr/local/lib/autotasker/assets";
|
||||
|
||||
pub async fn start_server_cli() -> Result<()> {
|
||||
info!("Starting minauth");
|
||||
let flags: ServerCliFlags = argh::from_env();
|
||||
let (config, db_pool) = get_app_context(crate::StartAppConfig {
|
||||
config_path: flags.config,
|
||||
database_path: flags.database
|
||||
}).await.context("Getting app context")?;
|
||||
start_http_server(
|
||||
ServerConfig {
|
||||
assets_path: flags.static_assets.unwrap_or(DEFAULT_ASSETS_PATH.to_string()),
|
||||
listen_host: flags.listen_host,
|
||||
listen_port: flags.listen_port
|
||||
},
|
||||
config,
|
||||
db_pool
|
||||
).await
|
||||
}
|
||||
|
|
|
|||
17
src/controllers/ui/home.rs
Normal file
17
src/controllers/ui/home.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
use axum::{extract::State, response::{Html, IntoResponse}};
|
||||
use axum_macros::debug_handler;
|
||||
use minijinja::context;
|
||||
|
||||
use crate::server::AppState;
|
||||
|
||||
#[debug_handler]
|
||||
pub async fn home(
|
||||
State(app_state): State<AppState>
|
||||
) -> impl IntoResponse {
|
||||
Html(
|
||||
app_state.templating_env.get_template("pages/home.html").unwrap()
|
||||
.render(context!())
|
||||
.unwrap()
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
use axum::{extract::State, response::{Html, IntoResponse}};
|
||||
use minijinja::context;
|
||||
|
||||
use crate::server::AppState;
|
||||
|
||||
pub async fn login_form(
|
||||
State(app_state): State<AppState>
|
||||
) -> impl IntoResponse {
|
||||
Html(
|
||||
app_state.templating_env.get_template("pages/home.html").unwrap()
|
||||
.render(context!())
|
||||
.unwrap()
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn perform_login(
|
||||
State(app_state): State<AppState>
|
||||
) -> impl IntoResponse {
|
||||
Html(
|
||||
app_state.templating_env.get_template("pages/home.html").unwrap()
|
||||
.render(context!())
|
||||
.unwrap()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
pub mod home;
|
||||
pub mod authorize;
|
||||
pub mod login;
|
||||
pub mod register;
|
||||
|
|
|
|||
19
src/database.rs
Normal file
19
src/database.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
use anyhow::{anyhow, Context, Result};
|
||||
use sqlx::{sqlite::{SqliteConnectOptions, SqlitePoolOptions}, Pool, Sqlite, ConnectOptions};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub async fn prepare_database(sqlite_db_path: &str) -> Result<Pool<Sqlite>> {
|
||||
let conn_str = format!("sqlite:{}", sqlite_db_path);
|
||||
|
||||
let pool = SqlitePoolOptions::new()
|
||||
.max_connections(50)
|
||||
.connect_with(
|
||||
SqliteConnectOptions::from_str(&conn_str)?
|
||||
.log_statements(log::LevelFilter::Trace)
|
||||
)
|
||||
.await
|
||||
.context("could not connect to database_url")?;
|
||||
|
||||
Ok(pool)
|
||||
}
|
||||
|
||||
47
src/main.rs
47
src/main.rs
|
|
@ -1,20 +1,51 @@
|
|||
pub mod models;
|
||||
pub mod controllers;
|
||||
pub mod router;
|
||||
pub mod server;
|
||||
pub mod database;
|
||||
pub mod cli;
|
||||
|
||||
use std::fs;
|
||||
use anyhow::{Result, Context, anyhow};
|
||||
|
||||
use database::prepare_database;
|
||||
use log::info;
|
||||
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
|
||||
use sqlx::{ConnectOptions, Pool, Sqlite};
|
||||
use models::config::Config;
|
||||
use minijinja::{context, Environment};
|
||||
|
||||
const DEFAULT_DB_PATH: &'static str = &"/var/lib/autotasker/autotasker.db";
|
||||
const DEFAULT_ASSETS_PATH: &'static str = &"/usr/local/lib/autotasker/assets";
|
||||
const DEFAULT_CONFIG_PATH: &'static str = &"/etc/autotasker/config.yaml";
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AppState {
|
||||
config: Config,
|
||||
db: Pool<Sqlite>,
|
||||
templating_env: Environment<'static>
|
||||
fn get_config(path: String) -> Result<Config> {
|
||||
let inp_def_yaml = fs::read_to_string(path)
|
||||
.expect("Should have been able to read the the config file");
|
||||
|
||||
toml::from_str(&inp_def_yaml)
|
||||
.map_err(|e| anyhow!("Failed to parse config, {:?}", e))
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
struct StartAppConfig {
|
||||
config_path: Option<String>,
|
||||
database_path: Option<String>,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
cli::start_server_cli().await
|
||||
}
|
||||
|
||||
async fn get_app_context(start_app_config: StartAppConfig) -> Result<(Config, Pool<Sqlite>)> {
|
||||
env_logger::init();
|
||||
let pool = prepare_database(
|
||||
&start_app_config.database_path.unwrap_or(DEFAULT_DB_PATH.to_string())
|
||||
).await.context("Could not prepare db")?;
|
||||
|
||||
let config_path = start_app_config.config_path.unwrap_or(DEFAULT_CONFIG_PATH.to_string());
|
||||
info!("Using config file at {}", &config_path);
|
||||
let config: Config = get_config(config_path).expect("Cannot get config");
|
||||
|
||||
Ok((config, pool))
|
||||
}
|
||||
|
|
|
|||
10
src/router.rs
Normal file
10
src/router.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
use axum::{routing::{get, post}, Router};
|
||||
|
||||
use crate::{controllers::ui, server::AppState};
|
||||
|
||||
pub fn build_router() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/", get(ui::home::home))
|
||||
.route("/login", get(ui::login::login_form))
|
||||
.route("/login", post(ui::login::perform_login))
|
||||
}
|
||||
|
|
@ -1,27 +1,18 @@
|
|||
use fully_pub::fully_pub;
|
||||
use tower_http::services::ServeDir;
|
||||
use anyhow::{Result, Context, anyhow};
|
||||
use log::info;
|
||||
use minijinja::{context, Environment};
|
||||
use sqlx::{Pool, Sqlite};
|
||||
use crate::{models::config::Config, router::build_router};
|
||||
|
||||
fn get_config(path: String) -> Result<Config> {
|
||||
let inp_def_yaml = fs::read_to_string(path)
|
||||
.expect("Should have been able to read the the config file");
|
||||
|
||||
serde_yaml::from_str(&inp_def_yaml)
|
||||
.map_err(|e| anyhow!("Failed to parse config, {:?}", e))
|
||||
}
|
||||
|
||||
fn build_templating_env() -> Environment<'static> {
|
||||
fn build_templating_env(config: &Config) -> Environment<'static> {
|
||||
let mut templating_env = Environment::new();
|
||||
|
||||
let _ = templating_env
|
||||
.add_template("layouts/base.html", include_str!("./templates/layouts/base.html"));
|
||||
let _ = templating_env
|
||||
.add_template("pages/home.html", include_str!("./templates/pages/home.html"));
|
||||
let _ = templating_env
|
||||
.add_template("pages/list_tasks.html", include_str!("./templates/pages/list_tasks.html"));
|
||||
let _ = templating_env
|
||||
.add_template("pages/list_task_runs.html", include_str!("./templates/pages/list_task_runs.html"));
|
||||
let _ = templating_env
|
||||
.add_template("pages/task_run_details.html", include_str!("./templates/pages/task_run_details.html"));
|
||||
let _ = templating_env
|
||||
.add_template("pages/run_task.html", include_str!("./templates/pages/run_task.html"));
|
||||
|
||||
// TODO: better loading with embed https://docs.rs/minijinja-embed/latest/minijinja_embed/
|
||||
templating_env.add_global("gl", context! {
|
||||
|
|
@ -32,3 +23,44 @@ fn build_templating_env() -> Environment<'static> {
|
|||
templating_env
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[fully_pub]
|
||||
/// HTTP server arguments
|
||||
pub struct ServerConfig {
|
||||
listen_host: String,
|
||||
listen_port: u32,
|
||||
assets_path: String
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[fully_pub]
|
||||
pub struct AppState {
|
||||
config: Config,
|
||||
db: Pool<Sqlite>,
|
||||
templating_env: Environment<'static>
|
||||
}
|
||||
|
||||
pub async fn start_http_server(server_config: ServerConfig, config: Config, db_pool: Pool<Sqlite>) -> Result<()> {
|
||||
// build state
|
||||
let state = AppState {
|
||||
templating_env: build_templating_env(&config),
|
||||
config,
|
||||
db: db_pool
|
||||
};
|
||||
|
||||
// build routes
|
||||
let services = build_router()
|
||||
.nest_service(
|
||||
"/assets",
|
||||
ServeDir::new(server_config.assets_path)
|
||||
)
|
||||
.with_state(state);
|
||||
|
||||
let listen_addr = format!("{}:{}", server_config.listen_host, server_config.listen_port);
|
||||
info!("Starting web server on http://{}", &listen_addr);
|
||||
let listener = tokio::net::TcpListener::bind(listen_addr).await.unwrap();
|
||||
|
||||
axum::serve(listener, services).await.context("Axum serve")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
22
src/templates/layouts/base.html
Normal file
22
src/templates/layouts/base.html
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Minauth</title>
|
||||
<link href="/assets/styles/simple.css" rel="stylesheet">
|
||||
<link href="/assets/styles/app.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
Minauth
|
||||
</header>
|
||||
<main class="container">
|
||||
{% block body %}{% endblock %}
|
||||
</main>
|
||||
<footer>
|
||||
Minauth {{ gl.instance.version }}
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
11
src/templates/pages/home.html
Normal file
11
src/templates/pages/home.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{% extends "layouts/base.html" %}
|
||||
{% block body %}
|
||||
<h1>Bienvenue sur Minauth</h1>
|
||||
|
||||
<p>
|
||||
Minauth is free software under <a href="https://www.gnu.org/licenses/gpl-3.0.txt">GPLv3</a> licence.
|
||||
|
||||
You can find source code on a <a href="https://forge.lefuturiste.fr/mbess/minauth">self-hosted forge repository</a>.
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
||||
0
src/templates/pages/login.html
Normal file
0
src/templates/pages/login.html
Normal file
Loading…
Add table
Add a link
Reference in a new issue