Add basic db structure
This commit is contained in:
parent
63376af86f
commit
bcbbef1a82
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
||||||
/target
|
/target
|
||||||
|
/config.toml
|
||||||
|
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
diff --git a/src/web/mod.rs b/src/web/mod.rs
|
|
||||||
index f919e6e..4f03aa9 100644
|
|
||||||
--- a/src/web/mod.rs
|
|
||||||
+++ b/src/web/mod.rs
|
|
||||||
@@ -11,6 +11,7 @@ pub async fn start() -> anyhow::Result<()> {
|
|
||||||
let addr = "0.0.0.0:3000";
|
|
||||||
let app = Router::new()
|
|
||||||
.route("/", get(pages::home::get_page))
|
|
||||||
+ .route("/login", get(pages::login::get_page))
|
|
||||||
.nest_service(
|
|
||||||
"/static",
|
|
||||||
ServiceBuilder::new()
|
|
||||||
diff --git a/src/web/pages/mod.rs b/src/web/pages/mod.rs
|
|
||||||
index 0c1f8ad..d4fc7a0 100644
|
|
||||||
--- a/src/web/pages/mod.rs
|
|
||||||
+++ b/src/web/pages/mod.rs
|
|
||||||
@@ -1,6 +1,8 @@
|
|
||||||
|
|
||||||
|
|
||||||
+
|
|
||||||
pub mod home;
|
|
||||||
+pub mod login;
|
|
||||||
pub mod error;
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/templates/base.html b/templates/base.html
|
|
||||||
index 6731e87..86574ca 100644
|
|
||||||
--- a/templates/base.html
|
|
||||||
+++ b/templates/base.html
|
|
||||||
@@ -3,6 +3,7 @@
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>{{ self.title() }}</title>
|
|
||||||
+ <link rel="stylesheet" href="/static/index.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{% include "header.html" %}
|
|
||||||
diff --git a/templates/header.html b/templates/header.html
|
|
||||||
index c247db4..cf4fb71 100644
|
|
||||||
--- a/templates/header.html
|
|
||||||
+++ b/templates/header.html
|
|
||||||
@@ -1,6 +1,25 @@
|
|
||||||
<header>
|
|
||||||
|
|
||||||
|
|
||||||
+ <ul class="nav">
|
|
||||||
+ <li><a href="/">Home</a></li>
|
|
||||||
+ <li><a href="/personnel">Personnel</a></li>
|
|
||||||
+ <li><a href="/clients">Clients</a></li>
|
|
||||||
+ <li><a href="/tickets">Tickets</a></li>
|
|
||||||
+ <li><a href="/inventory">Inventory</a></li>
|
|
||||||
+
|
|
||||||
+ <!- not logged in>
|
|
||||||
+ <!--
|
|
||||||
+ <li class="right"><a href="/login">Sign in</a></li>
|
|
||||||
+ !-->
|
|
||||||
+
|
|
||||||
+ <!- logged in>
|
|
||||||
+ <li class="right">
|
|
||||||
+ <img class="pfp" src="/static/usericon.png">
|
|
||||||
+ <a>John Doe</a>
|
|
||||||
+ </li>
|
|
||||||
+
|
|
||||||
+ </ul>
|
|
||||||
|
|
||||||
|
|
||||||
</header>
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
diff --git a/src/web/mod.rs b/src/web/mod.rs
|
|
||||||
index f919e6e..4f03aa9 100644
|
|
||||||
--- a/src/web/mod.rs
|
|
||||||
+++ b/src/web/mod.rs
|
|
||||||
@@ -11,6 +11,7 @@ pub async fn start() -> anyhow::Result<()> {
|
|
||||||
let addr = "0.0.0.0:3000";
|
|
||||||
let app = Router::new()
|
|
||||||
.route("/", get(pages::home::get_page))
|
|
||||||
+ .route("/login", get(pages::login::get_page))
|
|
||||||
.nest_service(
|
|
||||||
"/static",
|
|
||||||
ServiceBuilder::new()
|
|
||||||
diff --git a/src/web/pages/mod.rs b/src/web/pages/mod.rs
|
|
||||||
index 0c1f8ad..d4fc7a0 100644
|
|
||||||
--- a/src/web/pages/mod.rs
|
|
||||||
+++ b/src/web/pages/mod.rs
|
|
||||||
@@ -1,6 +1,8 @@
|
|
||||||
|
|
||||||
|
|
||||||
+
|
|
||||||
pub mod home;
|
|
||||||
+pub mod login;
|
|
||||||
pub mod error;
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/templates/base.html b/templates/base.html
|
|
||||||
index 6731e87..86574ca 100644
|
|
||||||
--- a/templates/base.html
|
|
||||||
+++ b/templates/base.html
|
|
||||||
@@ -3,6 +3,7 @@
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>{{ self.title() }}</title>
|
|
||||||
+ <link rel="stylesheet" href="/static/index.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{% include "header.html" %}
|
|
||||||
diff --git a/templates/header.html b/templates/header.html
|
|
||||||
index c247db4..cf4fb71 100644
|
|
||||||
--- a/templates/header.html
|
|
||||||
+++ b/templates/header.html
|
|
||||||
@@ -1,6 +1,25 @@
|
|
||||||
<header>
|
|
||||||
|
|
||||||
|
|
||||||
+ <ul class="nav">
|
|
||||||
+ <li><a href="/">Home</a></li>
|
|
||||||
+ <li><a href="/personnel">Personnel</a></li>
|
|
||||||
+ <li><a href="/clients">Clients</a></li>
|
|
||||||
+ <li><a href="/tickets">Tickets</a></li>
|
|
||||||
+ <li><a href="/inventory">Inventory</a></li>
|
|
||||||
+
|
|
||||||
+ <!- not logged in>
|
|
||||||
+ <!--
|
|
||||||
+ <li class="right"><a href="/login">Sign in</a></li>
|
|
||||||
+ !-->
|
|
||||||
+
|
|
||||||
+ <!- logged in>
|
|
||||||
+ <li class="right">
|
|
||||||
+ <img class="pfp" src="/static/usericon.png">
|
|
||||||
+ <a>John Doe</a>
|
|
||||||
+ </li>
|
|
||||||
+
|
|
||||||
+ </ul>
|
|
||||||
|
|
||||||
|
|
||||||
</header>
|
|
||||||
526
Cargo.lock
generated
526
Cargo.lock
generated
|
|
@ -300,6 +300,12 @@ version = "1.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
|
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "camino"
|
||||||
|
version = "1.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.52"
|
version = "1.2.52"
|
||||||
|
|
@ -325,6 +331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394"
|
checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
|
"clap_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -339,6 +346,18 @@ dependencies = [
|
||||||
"strsim",
|
"strsim",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.5.49"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_lex"
|
name = "clap_lex"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
|
|
@ -399,12 +418,107 @@ dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.21.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"darling_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.21.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"ident_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strsim",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.21.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "data-encoding"
|
name = "data-encoding"
|
||||||
version = "2.9.0"
|
version = "2.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
|
checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deranged"
|
||||||
|
version = "0.5.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"
|
||||||
|
dependencies = [
|
||||||
|
"powerfmt",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diesel"
|
||||||
|
version = "2.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e130c806dccc85428c564f2dc5a96e05b6615a27c9a28776bd7761a9af4bb552"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"byteorder",
|
||||||
|
"diesel_derives",
|
||||||
|
"downcast-rs",
|
||||||
|
"ipnet",
|
||||||
|
"itoa",
|
||||||
|
"libc",
|
||||||
|
"pq-sys",
|
||||||
|
"time",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diesel_derives"
|
||||||
|
version = "2.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c30b2969f923fa1f73744b92bb7df60b858df8832742d9a3aceb79236c0be1d2"
|
||||||
|
dependencies = [
|
||||||
|
"diesel_table_macro_syntax",
|
||||||
|
"dsl_auto_type",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diesel_migrations"
|
||||||
|
version = "2.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "745fd255645f0f1135f9ec55c7b00e0882192af9683ab4731e4bba3da82b8f9c"
|
||||||
|
dependencies = [
|
||||||
|
"diesel",
|
||||||
|
"migrations_internals",
|
||||||
|
"migrations_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diesel_table_macro_syntax"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe2444076b48641147115697648dc743c2c00b61adade0f01ce67133c7babe8c"
|
||||||
|
dependencies = [
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.10.7"
|
version = "0.10.7"
|
||||||
|
|
@ -415,6 +529,43 @@ dependencies = [
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "displaydoc"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "downcast-rs"
|
||||||
|
version = "2.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dsl_auto_type"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd122633e4bef06db27737f21d3738fb89c8f6d5360d6d9d7635dda142a7757e"
|
||||||
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"either",
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "env_filter"
|
name = "env_filter"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
|
@ -461,23 +612,18 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "fma"
|
||||||
version = "1.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
|
|
||||||
dependencies = [
|
|
||||||
"percent-encoding",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fuck_microsoft_access"
|
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"askama",
|
"askama",
|
||||||
"axum",
|
"axum",
|
||||||
|
"camino",
|
||||||
"clap",
|
"clap",
|
||||||
|
"diesel",
|
||||||
|
"diesel_migrations",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"ipnet",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
@ -485,6 +631,22 @@ dependencies = [
|
||||||
"toml",
|
"toml",
|
||||||
"tower",
|
"tower",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnv"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "form_urlencoded"
|
||||||
|
version = "1.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
|
||||||
|
dependencies = [
|
||||||
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -566,6 +728,12 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
|
@ -654,6 +822,114 @@ dependencies = [
|
||||||
"tower-service",
|
"tower-service",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_collections"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"potential_utf",
|
||||||
|
"yoke",
|
||||||
|
"zerofrom",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_locale_core"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"litemap",
|
||||||
|
"tinystr",
|
||||||
|
"writeable",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_normalizer"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
|
||||||
|
dependencies = [
|
||||||
|
"icu_collections",
|
||||||
|
"icu_normalizer_data",
|
||||||
|
"icu_properties",
|
||||||
|
"icu_provider",
|
||||||
|
"smallvec",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_normalizer_data"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_properties"
|
||||||
|
version = "2.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec"
|
||||||
|
dependencies = [
|
||||||
|
"icu_collections",
|
||||||
|
"icu_locale_core",
|
||||||
|
"icu_properties_data",
|
||||||
|
"icu_provider",
|
||||||
|
"zerotrie",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_properties_data"
|
||||||
|
version = "2.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_provider"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"icu_locale_core",
|
||||||
|
"writeable",
|
||||||
|
"yoke",
|
||||||
|
"zerofrom",
|
||||||
|
"zerotrie",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ident_case"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "idna"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
|
||||||
|
dependencies = [
|
||||||
|
"idna_adapter",
|
||||||
|
"smallvec",
|
||||||
|
"utf8_iter",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "idna_adapter"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
|
||||||
|
dependencies = [
|
||||||
|
"icu_normalizer",
|
||||||
|
"icu_properties",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.13.0"
|
version = "2.13.0"
|
||||||
|
|
@ -664,6 +940,12 @@ dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ipnet"
|
||||||
|
version = "2.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iri-string"
|
name = "iri-string"
|
||||||
version = "0.7.10"
|
version = "0.7.10"
|
||||||
|
|
@ -736,6 +1018,12 @@ version = "0.2.180"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "litemap"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.29"
|
version = "0.4.29"
|
||||||
|
|
@ -754,6 +1042,27 @@ version = "2.7.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "migrations_internals"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36c791ecdf977c99f45f23280405d7723727470f6689a5e6dbf513ac547ae10d"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"toml",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "migrations_macros"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36fc5ac76be324cfd2d3f2cf0fdf5d5d3c4f14ed8aaebadb09e304ba42282703"
|
||||||
|
dependencies = [
|
||||||
|
"migrations_internals",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mime"
|
name = "mime"
|
||||||
version = "0.3.17"
|
version = "0.3.17"
|
||||||
|
|
@ -791,6 +1100,12 @@ dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-conv"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
|
|
@ -851,6 +1166,21 @@ dependencies = [
|
||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "potential_utf"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
|
||||||
|
dependencies = [
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "powerfmt"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.21"
|
version = "0.2.21"
|
||||||
|
|
@ -860,6 +1190,17 @@ dependencies = [
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pq-sys"
|
||||||
|
version = "0.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "574ddd6a267294433f140b02a726b0640c43cf7c6f717084684aaa3b285aba61"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.105"
|
version = "1.0.105"
|
||||||
|
|
@ -1080,6 +1421,12 @@ dependencies = [
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stable_deref_trait"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
|
|
@ -1103,6 +1450,17 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
|
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "synstructure"
|
||||||
|
version = "0.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.17"
|
version = "2.0.17"
|
||||||
|
|
@ -1123,6 +1481,46 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.3.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd"
|
||||||
|
dependencies = [
|
||||||
|
"deranged",
|
||||||
|
"num-conv",
|
||||||
|
"powerfmt",
|
||||||
|
"serde_core",
|
||||||
|
"time-core",
|
||||||
|
"time-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-core"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-macros"
|
||||||
|
version = "0.2.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd"
|
||||||
|
dependencies = [
|
||||||
|
"num-conv",
|
||||||
|
"time-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinystr"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.49.0"
|
version = "1.49.0"
|
||||||
|
|
@ -1331,12 +1729,31 @@ version = "1.0.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "url"
|
||||||
|
version = "2.5.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed"
|
||||||
|
dependencies = [
|
||||||
|
"form_urlencoded",
|
||||||
|
"idna",
|
||||||
|
"percent-encoding",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf-8"
|
name = "utf-8"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8_iter"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
|
@ -1354,6 +1771,12 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vcpkg"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
|
|
@ -1524,6 +1947,35 @@ version = "0.46.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "writeable"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yoke"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
|
||||||
|
dependencies = [
|
||||||
|
"stable_deref_trait",
|
||||||
|
"yoke-derive",
|
||||||
|
"zerofrom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yoke-derive"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"synstructure",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.33"
|
version = "0.8.33"
|
||||||
|
|
@ -1544,6 +1996,60 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerofrom"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
|
||||||
|
dependencies = [
|
||||||
|
"zerofrom-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerofrom-derive"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"synstructure",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerotrie"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"yoke",
|
||||||
|
"zerofrom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerovec"
|
||||||
|
version = "0.11.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
|
||||||
|
dependencies = [
|
||||||
|
"yoke",
|
||||||
|
"zerofrom",
|
||||||
|
"zerovec-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerovec-derive"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zmij"
|
name = "zmij"
|
||||||
version = "1.0.13"
|
version = "1.0.13"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "fuck_microsoft_access"
|
name = "fma"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
|
|
@ -7,8 +7,12 @@ edition = "2024"
|
||||||
anyhow = "1.0.100"
|
anyhow = "1.0.100"
|
||||||
askama = "0.15.1"
|
askama = "0.15.1"
|
||||||
axum = { version = "0.8.8", features = ["macros", "ws"] }
|
axum = { version = "0.8.8", features = ["macros", "ws"] }
|
||||||
clap = "4.5.54"
|
camino = "1.2.2"
|
||||||
|
clap = { version = "4.5.54", features = ["derive"] }
|
||||||
|
diesel = { version = "2.3.5", features = ["uuid", "time", "postgres", "ipnet-address"] }
|
||||||
|
diesel_migrations = { version = "2.3.1", features = ["postgres"] }
|
||||||
env_logger = "0.11.8"
|
env_logger = "0.11.8"
|
||||||
|
ipnet = "2.11.0"
|
||||||
log = "0.4.29"
|
log = "0.4.29"
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
serde_json = "1.0.149"
|
serde_json = "1.0.149"
|
||||||
|
|
@ -16,3 +20,4 @@ tokio = { version = "1.49.0", features = ["io-util", "macros", "net", "rt-multi-
|
||||||
toml = "0.9.11"
|
toml = "0.9.11"
|
||||||
tower = { version = "0.5.3", features = ["full"] }
|
tower = { version = "0.5.3", features = ["full"] }
|
||||||
tower-http = { version = "0.6.8", features = ["full"] }
|
tower-http = { version = "0.6.8", features = ["full"] }
|
||||||
|
url = { version = "2.5.8", features = ["serde"] }
|
||||||
|
|
|
||||||
9
diesel.toml
Normal file
9
diesel.toml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# For documentation on how to configure this file,
|
||||||
|
# see https://diesel.rs/guides/configuring-diesel-cli
|
||||||
|
|
||||||
|
[print_schema]
|
||||||
|
file = "src/db/schema.rs"
|
||||||
|
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
|
||||||
|
|
||||||
|
[migrations_directory]
|
||||||
|
dir = "migrations"
|
||||||
0
migrations/.diesel_lock
Normal file
0
migrations/.diesel_lock
Normal file
6
migrations/00000000000000_diesel_initial_setup/down.sql
Normal file
6
migrations/00000000000000_diesel_initial_setup/down.sql
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
-- This file was automatically created by Diesel to setup helper functions
|
||||||
|
-- and other internal bookkeeping. This file is safe to edit, any future
|
||||||
|
-- changes will be added to existing projects as new migrations.
|
||||||
|
|
||||||
|
DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
|
||||||
|
DROP FUNCTION IF EXISTS diesel_set_updated_at();
|
||||||
36
migrations/00000000000000_diesel_initial_setup/up.sql
Normal file
36
migrations/00000000000000_diesel_initial_setup/up.sql
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
-- This file was automatically created by Diesel to setup helper functions
|
||||||
|
-- and other internal bookkeeping. This file is safe to edit, any future
|
||||||
|
-- changes will be added to existing projects as new migrations.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Sets up a trigger for the given table to automatically set a column called
|
||||||
|
-- `updated_at` whenever the row is modified (unless `updated_at` was included
|
||||||
|
-- in the modified columns)
|
||||||
|
--
|
||||||
|
-- # Example
|
||||||
|
--
|
||||||
|
-- ```sql
|
||||||
|
-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
|
||||||
|
--
|
||||||
|
-- SELECT diesel_manage_updated_at('users');
|
||||||
|
-- ```
|
||||||
|
CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
|
||||||
|
BEGIN
|
||||||
|
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
|
||||||
|
FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
|
||||||
|
BEGIN
|
||||||
|
IF (
|
||||||
|
NEW IS DISTINCT FROM OLD AND
|
||||||
|
NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
|
||||||
|
) THEN
|
||||||
|
NEW.updated_at := current_timestamp;
|
||||||
|
END IF;
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
1
migrations/2026-01-13-095817-0000_users/down.sql
Normal file
1
migrations/2026-01-13-095817-0000_users/down.sql
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE IF EXISTS users;
|
||||||
18
migrations/2026-01-13-095817-0000_users/up.sql
Normal file
18
migrations/2026-01-13-095817-0000_users/up.sql
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
|
username TEXT NOT NULL UNIQUE,
|
||||||
|
email TEXT NOT NULL UNIQUE,
|
||||||
|
password_hash TEXT NOT NULL,
|
||||||
|
password_salt TEXT NOT NULL,
|
||||||
|
first_name TEXT NOT NULL,
|
||||||
|
last_name TEXT NOT NULL,
|
||||||
|
display_name TEXT,
|
||||||
|
date_of_birth DATE,
|
||||||
|
phone_number TEXT,
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
last_login_at TIMESTAMPTZ,
|
||||||
|
|
||||||
|
-- u128 bitfield for permissions
|
||||||
|
permissions NUMERIC(39,0) NOT NULL DEFAULT 0
|
||||||
|
)
|
||||||
1
migrations/2026-01-13-095838-0000_clients/down.sql
Normal file
1
migrations/2026-01-13-095838-0000_clients/down.sql
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE IF EXISTS clients;
|
||||||
21
migrations/2026-01-13-095838-0000_clients/up.sql
Normal file
21
migrations/2026-01-13-095838-0000_clients/up.sql
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS clients (
|
||||||
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
|
email TEXT NOT NULL UNIQUE,
|
||||||
|
|
||||||
|
first_name TEXT NOT NULL,
|
||||||
|
last_name TEXT NOT NULL,
|
||||||
|
|
||||||
|
date_of_birth DATE,
|
||||||
|
phone_number TEXT,
|
||||||
|
gov_id_number TEXT,
|
||||||
|
house_number TEXT,
|
||||||
|
address_line TEXT,
|
||||||
|
city TEXT,
|
||||||
|
state TEXT,
|
||||||
|
postal_code TEXT,
|
||||||
|
country TEXT,
|
||||||
|
|
||||||
|
worker_user_id BIGINT,
|
||||||
|
|
||||||
|
CONSTRAINT fk_worker_user_id FOREIGN KEY (worker_user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
1
migrations/2026-01-13-095842-0000_warehouses/down.sql
Normal file
1
migrations/2026-01-13-095842-0000_warehouses/down.sql
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE IF EXISTS warehouses;
|
||||||
5
migrations/2026-01-13-095842-0000_warehouses/up.sql
Normal file
5
migrations/2026-01-13-095842-0000_warehouses/up.sql
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS warehouses (
|
||||||
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE IF EXISTS inventory_catalog;
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS inventory_catalog (
|
||||||
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
)
|
||||||
1
migrations/2026-01-13-095844-0000_inventory/down.sql
Normal file
1
migrations/2026-01-13-095844-0000_inventory/down.sql
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE IF EXISTS inventory;
|
||||||
11
migrations/2026-01-13-095844-0000_inventory/up.sql
Normal file
11
migrations/2026-01-13-095844-0000_inventory/up.sql
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS inventory (
|
||||||
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
|
warehouse_id BIGINT NOT NULL,
|
||||||
|
catalog_id BIGINT NOT NULL,
|
||||||
|
count BIGINT NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
|
UNIQUE (warehouse_id, catalog_id),
|
||||||
|
|
||||||
|
CONSTRAINT fk_warehouse_id FOREIGN KEY (warehouse_id) REFERENCES warehouses(id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_catalog_id FOREIGN KEY (catalog_id) REFERENCES inventory_catalog(id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
1
migrations/2026-01-13-095855-0000_tickets/down.sql
Normal file
1
migrations/2026-01-13-095855-0000_tickets/down.sql
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE IF EXISTS tickets;
|
||||||
3
migrations/2026-01-13-095855-0000_tickets/up.sql
Normal file
3
migrations/2026-01-13-095855-0000_tickets/up.sql
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS tickets (
|
||||||
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
|
||||||
|
)
|
||||||
2
migrations/2026-01-13-101555-0000_invoices/down.sql
Normal file
2
migrations/2026-01-13-101555-0000_invoices/down.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
DROP TABLE IF EXISTS invoices;
|
||||||
|
|
||||||
7
migrations/2026-01-13-101555-0000_invoices/up.sql
Normal file
7
migrations/2026-01-13-101555-0000_invoices/up.sql
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS invoices (
|
||||||
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
|
client_id BIGINT NOT NULL,
|
||||||
|
amount REAL NOT NULL, -- f32
|
||||||
|
|
||||||
|
CONSTRAINT fk_client_id FOREIGN KEY (client_id) REFERENCES clients(id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
2
migrations/2026-01-13-101601-0000_services/down.sql
Normal file
2
migrations/2026-01-13-101601-0000_services/down.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
DROP TABLE IF EXISTS services;
|
||||||
|
|
||||||
7
migrations/2026-01-13-101601-0000_services/up.sql
Normal file
7
migrations/2026-01-13-101601-0000_services/up.sql
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS services (
|
||||||
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
client_id BIGINT NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT fk_client_id FOREIGN KEY (client_id) REFERENCES clients(id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE IF EXISTS assigned_warehouse_managers;
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS assigned_warehouse_managers (
|
||||||
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
|
user_id BIGINT NOT NULL,
|
||||||
|
warehouse_id BIGINT NOT NULL,
|
||||||
|
assigned_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
|
||||||
|
CONSTRAINT fk_warehouse_id FOREIGN KEY (warehouse_id) REFERENCES warehouses(id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE IF EXISTS warehouse_actions;
|
||||||
11
migrations/2026-01-13-103443-0000_warehouse_actions/up.sql
Normal file
11
migrations/2026-01-13-103443-0000_warehouse_actions/up.sql
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS warehouse_actions (
|
||||||
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
|
user_id BIGINT NOT NULL,
|
||||||
|
warehouse_id BIGINT NOT NULL,
|
||||||
|
count BIGINT NOT NULL,
|
||||||
|
reason TEXT NOT NULL,
|
||||||
|
timestamp TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
|
||||||
|
CONSTRAINT fk_warehouse_id FOREIGN KEY (warehouse_id) REFERENCES warehouses(id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
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;
|
use log::LevelFilter;
|
||||||
|
|
||||||
mod web;
|
mod web;
|
||||||
|
mod db;
|
||||||
|
mod config;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
env_logger::builder()
|
env_logger::builder()
|
||||||
.filter_module("fuck_microsoft_access", LevelFilter::Debug)
|
.filter_module("fma", LevelFilter::Debug)
|
||||||
|
.filter_module("diesel_migrations", LevelFilter::Debug)
|
||||||
.init();
|
.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(())
|
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<()> {
|
pub async fn start(cfg: &crate::config::Config) -> anyhow::Result<()> {
|
||||||
let addr = "0.0.0.0:3000";
|
let addr = format!("{}:{}", cfg.web.host, cfg.web.port);
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/", get(pages::home::get_page))
|
.route("/", get(pages::home::get_page))
|
||||||
.route("/login", get(pages::login::get_page))
|
.route("/login", get(pages::login::get_page))
|
||||||
|
|
@ -18,7 +18,7 @@ pub async fn start() -> anyhow::Result<()> {
|
||||||
.service(ServeDir::new("static"))
|
.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}");
|
log::info!("Listening on http://{addr}");
|
||||||
axum::serve(listener, app).await.unwrap();
|
axum::serve(listener, app).await.unwrap();
|
||||||
Ok(())
|
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)]
|
#[derive(Template)]
|
||||||
#[template(path = "error.html")]
|
#[template(path = "error.html")]
|
||||||
pub struct ErrorTemplate {
|
pub struct PageTemplate {
|
||||||
pub ctx: BaseTemplateCtx,
|
pub ctx: BaseTemplateCtx,
|
||||||
pub error: String
|
pub error: String
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BaseTemplate for ErrorTemplate {
|
impl BaseTemplate for PageTemplate {
|
||||||
fn ctx(&self) -> &BaseTemplateCtx {
|
fn ctx(&self) -> &BaseTemplateCtx {
|
||||||
&self.ctx
|
&self.ctx
|
||||||
}
|
}
|
||||||
|
|
@ -20,7 +20,7 @@ impl BaseTemplate for ErrorTemplate {
|
||||||
|
|
||||||
#[axum::debug_handler]
|
#[axum::debug_handler]
|
||||||
pub async fn get_error_page(e: String) -> String {
|
pub async fn get_error_page(e: String) -> String {
|
||||||
let mut template = ErrorTemplate {
|
let mut template = PageTemplate {
|
||||||
ctx: Default::default(),
|
ctx: Default::default(),
|
||||||
error: e.to_string()
|
error: e.to_string()
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,12 @@ use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "home.html")]
|
#[template(path = "home.html")]
|
||||||
pub struct HomeTemplate {
|
pub struct PageTemplate {
|
||||||
pub ctx: BaseTemplateCtx,
|
pub ctx: BaseTemplateCtx,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BaseTemplate for HomeTemplate {
|
impl BaseTemplate for PageTemplate {
|
||||||
fn ctx(&self) -> &BaseTemplateCtx {
|
fn ctx(&self) -> &BaseTemplateCtx {
|
||||||
&self.ctx
|
&self.ctx
|
||||||
}
|
}
|
||||||
|
|
@ -32,7 +32,7 @@ impl BaseTemplate for HomeTemplate {
|
||||||
#[axum::debug_handler]
|
#[axum::debug_handler]
|
||||||
pub async fn get_page() -> Response {
|
pub async fn get_page() -> Response {
|
||||||
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
||||||
let mut template = HomeTemplate {
|
let mut template = PageTemplate {
|
||||||
ctx: Default::default()
|
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)]
|
#[derive(Template)]
|
||||||
#[template(path = "login.html")]
|
#[template(path = "login.html")]
|
||||||
pub struct HomeTemplate {
|
pub struct PageTemplate {
|
||||||
pub ctx: BaseTemplateCtx,
|
pub ctx: BaseTemplateCtx,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BaseTemplate for HomeTemplate {
|
impl BaseTemplate for PageTemplate {
|
||||||
fn ctx(&self) -> &BaseTemplateCtx {
|
fn ctx(&self) -> &BaseTemplateCtx {
|
||||||
&self.ctx
|
&self.ctx
|
||||||
}
|
}
|
||||||
|
|
@ -29,7 +29,7 @@ impl BaseTemplate for HomeTemplate {
|
||||||
#[axum::debug_handler]
|
#[axum::debug_handler]
|
||||||
pub async fn get_page() -> Response {
|
pub async fn get_page() -> Response {
|
||||||
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
||||||
let mut template = HomeTemplate {
|
let mut template = PageTemplate {
|
||||||
ctx: Default::default()
|
ctx: Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
pub mod clients;
|
||||||
|
pub mod inventory;
|
||||||
|
pub mod tickets;
|
||||||
pub mod home;
|
pub mod home;
|
||||||
pub mod login;
|
pub mod login;
|
||||||
pub mod error;
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user