Add basic db structure
This commit is contained in:
89
src/config.rs
Normal file
89
src/config.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
use anyhow::bail;
|
||||
use clap::Parser;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, clap::Parser)]
|
||||
pub struct CliArgs {
|
||||
|
||||
/// Path to config file
|
||||
#[arg(long="config", short='C', default_value="./config.toml")]
|
||||
config_path: camino::Utf8PathBuf,
|
||||
|
||||
#[arg(long="host", short='H')]
|
||||
host: Option<String>,
|
||||
#[arg(long="port", short='p')]
|
||||
port: Option<u16>,
|
||||
#[arg(long="database", short='D')]
|
||||
database: Option<url::Url>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
pub web: ConfigWeb,
|
||||
pub database: ConfigDb
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
pub struct ConfigWeb {
|
||||
pub host: String,
|
||||
pub port: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
pub struct ConfigDb {
|
||||
host: String,
|
||||
port: u16,
|
||||
username: String,
|
||||
password: String,
|
||||
database: String,
|
||||
}
|
||||
|
||||
|
||||
impl Config {
|
||||
pub fn parse() -> anyhow::Result<Self> {
|
||||
let cli = CliArgs::parse();
|
||||
let mut cfg = Self::default();
|
||||
let mut is_new = true;
|
||||
if cli.config_path.exists() {
|
||||
log::info!("Config file exists, reading");
|
||||
let cfg_s = std::fs::read_to_string(&cli.config_path)?;
|
||||
cfg = toml::from_str(&cfg_s)?;
|
||||
is_new = false;
|
||||
}
|
||||
cfg.web.host = cli.host.unwrap_or("0.0.0.0".to_string());
|
||||
cfg.web.port = cli.port.unwrap_or(3000);
|
||||
if let Some(db) = cli.database {
|
||||
cfg.database.host = db.host_str().unwrap_or("0.0.0.0").to_string();
|
||||
cfg.database.port = db.port().unwrap_or(5432);
|
||||
cfg.database.username = db.username().to_string();
|
||||
cfg.database.password = db.password().unwrap_or("").to_string();
|
||||
cfg.database.database = {
|
||||
match db.path_segments() {
|
||||
Some(mut seg) => seg.next().unwrap_or("").to_string(),
|
||||
None => String::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if is_new {
|
||||
log::info!("Config file doesnt exist, creating new");
|
||||
let content = toml::to_string_pretty(&cfg)?;
|
||||
std::fs::write(&cli.config_path, content)?;
|
||||
}
|
||||
Ok(cfg)
|
||||
}
|
||||
|
||||
pub fn database_url(&self) -> anyhow::Result<url::Url> {
|
||||
let mut u = url::Url::parse("postgres://0.0.0.0/")?;
|
||||
u.set_host(Some(&self.database.host))?;
|
||||
let _ = u.set_port(Some(self.database.port));
|
||||
let _ = u.set_username(&self.database.username);
|
||||
if self.database.password.is_empty() {
|
||||
let _ = u.set_password(None);
|
||||
} else {
|
||||
let _ = u.set_password(Some(&self.database.password));
|
||||
}
|
||||
u.set_path(&self.database.database);
|
||||
Ok(u)
|
||||
}
|
||||
}
|
||||
19
src/db/mod.rs
Normal file
19
src/db/mod.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
use diesel::{Connection, PgConnection};
|
||||
use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations};
|
||||
|
||||
pub mod schema;
|
||||
|
||||
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations");
|
||||
|
||||
fn run_migrations(conn: &mut impl MigrationHarness<diesel::pg::Pg>) {
|
||||
conn.run_pending_migrations(MIGRATIONS).unwrap();
|
||||
log::info!("Running migrations");
|
||||
}
|
||||
|
||||
|
||||
pub fn start(cfg: &crate::config::Config) -> anyhow::Result<PgConnection> {
|
||||
let mut connection = PgConnection::establish(&cfg.database_url()?.to_string())?;
|
||||
run_migrations(&mut connection);
|
||||
Ok(connection)
|
||||
}
|
||||
|
||||
129
src/db/schema.rs
Normal file
129
src/db/schema.rs
Normal file
@@ -0,0 +1,129 @@
|
||||
// @generated automatically by Diesel CLI.
|
||||
|
||||
diesel::table! {
|
||||
assigned_warehouse_managers (id) {
|
||||
id -> Int8,
|
||||
user_id -> Int8,
|
||||
warehouse_id -> Int8,
|
||||
assigned_at -> Timestamptz,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
clients (id) {
|
||||
id -> Int8,
|
||||
email -> Text,
|
||||
first_name -> Text,
|
||||
last_name -> Text,
|
||||
date_of_birth -> Nullable<Date>,
|
||||
phone_number -> Nullable<Text>,
|
||||
gov_id_number -> Nullable<Text>,
|
||||
house_number -> Nullable<Text>,
|
||||
address_line -> Nullable<Text>,
|
||||
city -> Nullable<Text>,
|
||||
state -> Nullable<Text>,
|
||||
postal_code -> Nullable<Text>,
|
||||
country -> Nullable<Text>,
|
||||
worker_user_id -> Nullable<Int8>,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
inventory (id) {
|
||||
id -> Int8,
|
||||
warehouse_id -> Int8,
|
||||
catalog_id -> Int8,
|
||||
count -> Int8,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
inventory_catalog (id) {
|
||||
id -> Int8,
|
||||
name -> Text,
|
||||
description -> Nullable<Text>,
|
||||
created_at -> Timestamptz,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
invoices (id) {
|
||||
id -> Int8,
|
||||
client_id -> Int8,
|
||||
amount -> Float4,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
services (id) {
|
||||
id -> Int8,
|
||||
name -> Text,
|
||||
client_id -> Int8,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
tickets (id) {
|
||||
id -> Int8,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
users (id) {
|
||||
id -> Int8,
|
||||
username -> Text,
|
||||
email -> Text,
|
||||
password_hash -> Text,
|
||||
password_salt -> Text,
|
||||
first_name -> Text,
|
||||
last_name -> Text,
|
||||
display_name -> Nullable<Text>,
|
||||
date_of_birth -> Nullable<Date>,
|
||||
phone_number -> Nullable<Text>,
|
||||
created_at -> Timestamptz,
|
||||
last_login_at -> Nullable<Timestamptz>,
|
||||
permissions -> Numeric,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
warehouse_actions (id) {
|
||||
id -> Int8,
|
||||
user_id -> Int8,
|
||||
warehouse_id -> Int8,
|
||||
count -> Int8,
|
||||
reason -> Text,
|
||||
timestamp -> Timestamptz,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
warehouses (id) {
|
||||
id -> Int8,
|
||||
name -> Text,
|
||||
created_at -> Timestamptz,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::joinable!(assigned_warehouse_managers -> users (user_id));
|
||||
diesel::joinable!(assigned_warehouse_managers -> warehouses (warehouse_id));
|
||||
diesel::joinable!(clients -> users (worker_user_id));
|
||||
diesel::joinable!(inventory -> inventory_catalog (catalog_id));
|
||||
diesel::joinable!(inventory -> warehouses (warehouse_id));
|
||||
diesel::joinable!(invoices -> clients (client_id));
|
||||
diesel::joinable!(services -> clients (client_id));
|
||||
diesel::joinable!(warehouse_actions -> users (user_id));
|
||||
diesel::joinable!(warehouse_actions -> warehouses (warehouse_id));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(
|
||||
assigned_warehouse_managers,
|
||||
clients,
|
||||
inventory,
|
||||
inventory_catalog,
|
||||
invoices,
|
||||
services,
|
||||
tickets,
|
||||
users,
|
||||
warehouse_actions,
|
||||
warehouses,
|
||||
);
|
||||
16
src/main.rs
16
src/main.rs
@@ -1,14 +1,24 @@
|
||||
use log::LevelFilter;
|
||||
|
||||
mod web;
|
||||
|
||||
mod db;
|
||||
mod config;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
env_logger::builder()
|
||||
.filter_module("fuck_microsoft_access", LevelFilter::Debug)
|
||||
.filter_module("fma", LevelFilter::Debug)
|
||||
.filter_module("diesel_migrations", LevelFilter::Debug)
|
||||
.init();
|
||||
let cfg = config::Config::parse()?;
|
||||
|
||||
unsafe {
|
||||
// SAFETY: This runs while there are no other threads running, which is required for this
|
||||
// function to be safe
|
||||
std::env::set_var("DATABASE_URL", cfg.database_url()?.to_string());
|
||||
}
|
||||
|
||||
web::start().await?;
|
||||
let db = db::start(&cfg)?;
|
||||
web::start(&cfg).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
132
src/schema.rs
Normal file
132
src/schema.rs
Normal file
@@ -0,0 +1,132 @@
|
||||
// @generated automatically by Diesel CLI.
|
||||
|
||||
diesel::table! {
|
||||
assigned_warehouse_managers (id) {
|
||||
id -> Int8,
|
||||
user_id -> Int8,
|
||||
warehouse_id -> Int8,
|
||||
assigned_at -> Timestamptz,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
clients (id) {
|
||||
id -> Int8,
|
||||
email -> Text,
|
||||
first_name -> Text,
|
||||
last_name -> Text,
|
||||
date_of_birth -> Nullable<Date>,
|
||||
phone_number -> Nullable<Text>,
|
||||
gov_id_number -> Nullable<Text>,
|
||||
house_number -> Nullable<Text>,
|
||||
address_line -> Nullable<Text>,
|
||||
city -> Nullable<Text>,
|
||||
state -> Nullable<Text>,
|
||||
postal_code -> Nullable<Text>,
|
||||
country -> Nullable<Text>,
|
||||
worker_user_id -> Nullable<Int8>,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
inventory (id) {
|
||||
id -> Int8,
|
||||
warehouse_id -> Int8,
|
||||
catalog_id -> Int8,
|
||||
count -> Int8,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
inventory_catalog (id) {
|
||||
id -> Int4,
|
||||
title -> Varchar,
|
||||
body -> Text,
|
||||
published -> Bool,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
invoices (id) {
|
||||
id -> Int8,
|
||||
client_id -> Int8,
|
||||
amount -> Float4,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
services (id) {
|
||||
id -> Int8,
|
||||
name -> Text,
|
||||
client_id -> Int8,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
tickets (id) {
|
||||
id -> Int4,
|
||||
title -> Varchar,
|
||||
body -> Text,
|
||||
published -> Bool,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
users (id) {
|
||||
id -> Int8,
|
||||
username -> Text,
|
||||
email -> Text,
|
||||
password_hash -> Text,
|
||||
password_salt -> Text,
|
||||
first_name -> Text,
|
||||
last_name -> Text,
|
||||
display_name -> Nullable<Text>,
|
||||
date_of_birth -> Nullable<Date>,
|
||||
phone_number -> Nullable<Text>,
|
||||
created_at -> Timestamptz,
|
||||
last_login_at -> Nullable<Timestamptz>,
|
||||
permissions -> Numeric,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
warehouse_actions (id) {
|
||||
id -> Int8,
|
||||
user_id -> Int8,
|
||||
warehouse_id -> Int8,
|
||||
count -> Int8,
|
||||
reason -> Text,
|
||||
timestamp -> Timestamptz,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
warehouses (id) {
|
||||
id -> Int8,
|
||||
name -> Text,
|
||||
created_at -> Timestamptz,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::joinable!(assigned_warehouse_managers -> users (user_id));
|
||||
diesel::joinable!(assigned_warehouse_managers -> warehouses (warehouse_id));
|
||||
diesel::joinable!(clients -> users (worker_user_id));
|
||||
diesel::joinable!(inventory -> inventory_catalog (catalog_id));
|
||||
diesel::joinable!(inventory -> warehouses (warehouse_id));
|
||||
diesel::joinable!(invoices -> clients (client_id));
|
||||
diesel::joinable!(services -> clients (client_id));
|
||||
diesel::joinable!(warehouse_actions -> users (user_id));
|
||||
diesel::joinable!(warehouse_actions -> warehouses (warehouse_id));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(
|
||||
assigned_warehouse_managers,
|
||||
clients,
|
||||
inventory,
|
||||
inventory_catalog,
|
||||
invoices,
|
||||
services,
|
||||
tickets,
|
||||
users,
|
||||
warehouse_actions,
|
||||
warehouses,
|
||||
);
|
||||
@@ -7,8 +7,8 @@ pub mod pages;
|
||||
|
||||
|
||||
|
||||
pub async fn start() -> anyhow::Result<()> {
|
||||
let addr = "0.0.0.0:3000";
|
||||
pub async fn start(cfg: &crate::config::Config) -> anyhow::Result<()> {
|
||||
let addr = format!("{}:{}", cfg.web.host, cfg.web.port);
|
||||
let app = Router::new()
|
||||
.route("/", get(pages::home::get_page))
|
||||
.route("/login", get(pages::login::get_page))
|
||||
@@ -18,7 +18,7 @@ pub async fn start() -> anyhow::Result<()> {
|
||||
.service(ServeDir::new("static"))
|
||||
);
|
||||
|
||||
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
|
||||
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
||||
log::info!("Listening on http://{addr}");
|
||||
axum::serve(listener, app).await.unwrap();
|
||||
Ok(())
|
||||
|
||||
51
src/web/pages/clients.rs
Normal file
51
src/web/pages/clients.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
|
||||
|
||||
use askama::Template;
|
||||
use axum::response::{Html, IntoResponse, Response};
|
||||
|
||||
use axum::{
|
||||
routing::{get, post},
|
||||
http::StatusCode,
|
||||
Json, Router,
|
||||
};
|
||||
|
||||
use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "home.html")]
|
||||
pub struct PageTemplate {
|
||||
pub ctx: BaseTemplateCtx,
|
||||
|
||||
}
|
||||
|
||||
impl BaseTemplate for PageTemplate {
|
||||
fn ctx(&self) -> &BaseTemplateCtx {
|
||||
&self.ctx
|
||||
}
|
||||
fn ctx_mut(&mut self) -> &mut BaseTemplateCtx {
|
||||
&mut self.ctx
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
pub async fn get_page() -> Response {
|
||||
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
||||
let mut template = PageTemplate {
|
||||
ctx: Default::default()
|
||||
};
|
||||
|
||||
template.set_title("Home");
|
||||
|
||||
Ok((StatusCode::OK, template.render()?))
|
||||
}
|
||||
|
||||
match inner() {
|
||||
Ok((status, s)) => (status, Html(s)).into_response(),
|
||||
Err(e) => {
|
||||
let s = crate::web::pages::error::get_error_page(e.to_string()).await;
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Html(s)).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,12 @@ use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "error.html")]
|
||||
pub struct ErrorTemplate {
|
||||
pub struct PageTemplate {
|
||||
pub ctx: BaseTemplateCtx,
|
||||
pub error: String
|
||||
}
|
||||
|
||||
impl BaseTemplate for ErrorTemplate {
|
||||
impl BaseTemplate for PageTemplate {
|
||||
fn ctx(&self) -> &BaseTemplateCtx {
|
||||
&self.ctx
|
||||
}
|
||||
@@ -20,7 +20,7 @@ impl BaseTemplate for ErrorTemplate {
|
||||
|
||||
#[axum::debug_handler]
|
||||
pub async fn get_error_page(e: String) -> String {
|
||||
let mut template = ErrorTemplate {
|
||||
let mut template = PageTemplate {
|
||||
ctx: Default::default(),
|
||||
error: e.to_string()
|
||||
};
|
||||
|
||||
@@ -14,12 +14,12 @@ use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "home.html")]
|
||||
pub struct HomeTemplate {
|
||||
pub struct PageTemplate {
|
||||
pub ctx: BaseTemplateCtx,
|
||||
|
||||
}
|
||||
|
||||
impl BaseTemplate for HomeTemplate {
|
||||
impl BaseTemplate for PageTemplate {
|
||||
fn ctx(&self) -> &BaseTemplateCtx {
|
||||
&self.ctx
|
||||
}
|
||||
@@ -32,7 +32,7 @@ impl BaseTemplate for HomeTemplate {
|
||||
#[axum::debug_handler]
|
||||
pub async fn get_page() -> Response {
|
||||
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
||||
let mut template = HomeTemplate {
|
||||
let mut template = PageTemplate {
|
||||
ctx: Default::default()
|
||||
};
|
||||
|
||||
|
||||
51
src/web/pages/inventory.rs
Normal file
51
src/web/pages/inventory.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
|
||||
|
||||
use askama::Template;
|
||||
use axum::response::{Html, IntoResponse, Response};
|
||||
|
||||
use axum::{
|
||||
routing::{get, post},
|
||||
http::StatusCode,
|
||||
Json, Router,
|
||||
};
|
||||
|
||||
use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "home.html")]
|
||||
pub struct HomeTemplate {
|
||||
pub ctx: BaseTemplateCtx,
|
||||
|
||||
}
|
||||
|
||||
impl BaseTemplate for HomeTemplate {
|
||||
fn ctx(&self) -> &BaseTemplateCtx {
|
||||
&self.ctx
|
||||
}
|
||||
fn ctx_mut(&mut self) -> &mut BaseTemplateCtx {
|
||||
&mut self.ctx
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
pub async fn get_page() -> Response {
|
||||
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
||||
let mut template = HomeTemplate {
|
||||
ctx: Default::default()
|
||||
};
|
||||
|
||||
template.set_title("Home");
|
||||
|
||||
Ok((StatusCode::OK, template.render()?))
|
||||
}
|
||||
|
||||
match inner() {
|
||||
Ok((status, s)) => (status, Html(s)).into_response(),
|
||||
Err(e) => {
|
||||
let s = crate::web::pages::error::get_error_page(e.to_string()).await;
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Html(s)).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,12 +11,12 @@ use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "login.html")]
|
||||
pub struct HomeTemplate {
|
||||
pub struct PageTemplate {
|
||||
pub ctx: BaseTemplateCtx,
|
||||
|
||||
}
|
||||
|
||||
impl BaseTemplate for HomeTemplate {
|
||||
impl BaseTemplate for PageTemplate {
|
||||
fn ctx(&self) -> &BaseTemplateCtx {
|
||||
&self.ctx
|
||||
}
|
||||
@@ -29,7 +29,7 @@ impl BaseTemplate for HomeTemplate {
|
||||
#[axum::debug_handler]
|
||||
pub async fn get_page() -> Response {
|
||||
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
||||
let mut template = HomeTemplate {
|
||||
let mut template = PageTemplate {
|
||||
ctx: Default::default()
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
|
||||
|
||||
pub mod clients;
|
||||
pub mod inventory;
|
||||
pub mod tickets;
|
||||
pub mod home;
|
||||
pub mod login;
|
||||
pub mod error;
|
||||
|
||||
51
src/web/pages/tickets.rs
Normal file
51
src/web/pages/tickets.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
|
||||
|
||||
use askama::Template;
|
||||
use axum::response::{Html, IntoResponse, Response};
|
||||
|
||||
use axum::{
|
||||
routing::{get, post},
|
||||
http::StatusCode,
|
||||
Json, Router,
|
||||
};
|
||||
|
||||
use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "home.html")]
|
||||
pub struct PageTemplate {
|
||||
pub ctx: BaseTemplateCtx,
|
||||
|
||||
}
|
||||
|
||||
impl BaseTemplate for PageTemplate {
|
||||
fn ctx(&self) -> &BaseTemplateCtx {
|
||||
&self.ctx
|
||||
}
|
||||
fn ctx_mut(&mut self) -> &mut BaseTemplateCtx {
|
||||
&mut self.ctx
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
pub async fn get_page() -> Response {
|
||||
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
||||
let mut template = PageTemplate {
|
||||
ctx: Default::default()
|
||||
};
|
||||
|
||||
template.set_title("Tickets");
|
||||
|
||||
Ok((StatusCode::OK, template.render()?))
|
||||
}
|
||||
|
||||
match inner() {
|
||||
Ok((status, s)) => (status, Html(s)).into_response(),
|
||||
Err(e) => {
|
||||
let s = crate::web::pages::error::get_error_page(e.to_string()).await;
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Html(s)).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user