reports
This commit is contained in:
258
Cargo.lock
generated
258
Cargo.lock
generated
@@ -1,6 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
@@ -96,7 +96,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -191,7 +191,7 @@ dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -384,6 +384,41 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.5.0"
|
||||
@@ -399,6 +434,37 @@ dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder"
|
||||
version = "0.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
|
||||
dependencies = [
|
||||
"derive_builder_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder_core"
|
||||
version = "0.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder_macro"
|
||||
version = "0.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
|
||||
dependencies = [
|
||||
"derive_builder_core",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "0.99.17"
|
||||
@@ -581,7 +647,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -643,6 +709,23 @@ version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
||||
|
||||
[[package]]
|
||||
name = "handlebars"
|
||||
version = "6.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "759e2d5aea3287cb1190c8ec394f42866cb5bf74fcbf213f354e3c856ea26098"
|
||||
dependencies = [
|
||||
"derive_builder",
|
||||
"log",
|
||||
"num-order",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.12",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
@@ -811,6 +894,12 @@ dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.5.0"
|
||||
@@ -1018,6 +1107,7 @@ dependencies = [
|
||||
"derive_more",
|
||||
"figment",
|
||||
"futures",
|
||||
"handlebars",
|
||||
"jsonwebtoken",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -1075,6 +1165,21 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-modular"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f"
|
||||
|
||||
[[package]]
|
||||
name = "num-order"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6"
|
||||
dependencies = [
|
||||
"num-modular",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.18"
|
||||
@@ -1200,7 +1305,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2-diagnostics",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1219,6 +1324,51 @@ version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"thiserror 2.0.12",
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"pest",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.5"
|
||||
@@ -1236,7 +1386,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1271,9 +1421,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.81"
|
||||
version = "1.0.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
|
||||
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -1286,7 +1436,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn 2.0.100",
|
||||
"version_check",
|
||||
"yansi",
|
||||
]
|
||||
@@ -1356,7 +1506,7 @@ checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libredox",
|
||||
"thiserror",
|
||||
"thiserror 1.0.59",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1481,6 +1631,15 @@ version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
@@ -1520,7 +1679,7 @@ checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1613,7 +1772,7 @@ checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
"thiserror",
|
||||
"thiserror 1.0.59",
|
||||
"time",
|
||||
]
|
||||
|
||||
@@ -1728,7 +1887,7 @@ dependencies = [
|
||||
"sqlformat",
|
||||
"sqlx-rt",
|
||||
"stringprep",
|
||||
"thiserror",
|
||||
"thiserror 1.0.59",
|
||||
"tokio-stream",
|
||||
"url",
|
||||
"webpki-roots",
|
||||
@@ -1776,6 +1935,12 @@ dependencies = [
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.5.0"
|
||||
@@ -1795,9 +1960,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.60"
|
||||
version = "2.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
|
||||
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1822,7 +1987,16 @@ version = "1.0.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
"thiserror-impl 1.0.59",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
||||
dependencies = [
|
||||
"thiserror-impl 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1833,7 +2007,18 @@ checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1919,7 +2104,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2054,7 +2239,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"thiserror",
|
||||
"thiserror 1.0.59",
|
||||
"time",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
@@ -2067,7 +2252,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2124,7 +2309,7 @@ dependencies = [
|
||||
"log",
|
||||
"rand",
|
||||
"sha1",
|
||||
"thiserror",
|
||||
"thiserror 1.0.59",
|
||||
"url",
|
||||
"utf-8",
|
||||
]
|
||||
@@ -2135,6 +2320,12 @@ version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
|
||||
|
||||
[[package]]
|
||||
name = "uncased"
|
||||
version = "0.9.10"
|
||||
@@ -2224,6 +2415,16 @@ version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
@@ -2257,7 +2458,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn 2.0.100",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -2279,7 +2480,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn 2.0.100",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@@ -2346,6 +2547,15 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
@@ -2532,5 +2742,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
@@ -11,6 +11,7 @@ axum = { version = "0.7.5", features = ["macros", "ws"] }
|
||||
derive_more = "0.99.17"
|
||||
figment = { version = "0.10.18", features = ["env", "toml"] }
|
||||
futures = "0.3.30"
|
||||
handlebars = { version = "6.3.2", features = ["dir_source"] }
|
||||
jsonwebtoken = "9.3.0"
|
||||
serde = { version = "1.0.198", features = ["derive"] }
|
||||
serde_json = "1.0.116"
|
||||
|
||||
@@ -4,4 +4,4 @@ port = 1234
|
||||
|
||||
[database]
|
||||
max_connections = 5
|
||||
url = "postgres://postgres:123456789@localhost:5432/postgres"
|
||||
url = "postgres://postgres:postgres@localhost:5432/cspbd_lab"
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
use std::ops::Deref;
|
||||
use derive_more::{Display, Error, From};
|
||||
use sqlx::migrate::{Migrate, Migrator};
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::{
|
||||
config,
|
||||
entity,
|
||||
};
|
||||
use crate::{config, entity};
|
||||
|
||||
static MIGRATOR: Migrator = sqlx::migrate!("./migrations");
|
||||
|
||||
@@ -18,8 +15,8 @@ impl Database {
|
||||
pub async fn init() -> Result<Self> {
|
||||
let config = config::config();
|
||||
|
||||
let pool = sqlx::postgres::PgPoolOptions::new()
|
||||
.max_connections(config.database.max_connections);
|
||||
let pool =
|
||||
sqlx::postgres::PgPoolOptions::new().max_connections(config.database.max_connections);
|
||||
let pool = pool
|
||||
.connect(&config.database.url)
|
||||
.await
|
||||
@@ -30,10 +27,13 @@ impl Database {
|
||||
let connection = pool.acquire().await?;
|
||||
let version = connection.deref().server_version_num();
|
||||
|
||||
tracing::info!("Connected to postgres version {}", match version {
|
||||
tracing::info!(
|
||||
"Connected to postgres version {}",
|
||||
match version {
|
||||
Some(version) => version.to_string(),
|
||||
None => "unknown".to_string(),
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
MIGRATOR.run(&pool).await?;
|
||||
@@ -104,7 +104,9 @@ impl Database {
|
||||
token: &str,
|
||||
expires_at: chrono::DateTime<chrono::Utc>,
|
||||
) -> Result<entity::Token> {
|
||||
sqlx::query(r#"INSERT INTO "tokens"("user_id", "token", "expires_at") VALUES ($1, $2, $3)"#)
|
||||
sqlx::query(
|
||||
r#"INSERT INTO "tokens"("user_id", "token", "expires_at") VALUES ($1, $2, $3)"#,
|
||||
)
|
||||
.bind(id)
|
||||
.bind(token)
|
||||
.bind(expires_at)
|
||||
@@ -166,7 +168,9 @@ impl Database {
|
||||
channel_id: entity::ShortId,
|
||||
admin: bool,
|
||||
) -> Result<()> {
|
||||
sqlx::query(r#"INSERT INTO "channel_user"("user_id", "channel_id", "admin") VALUES ($1, $2, $3)"#)
|
||||
sqlx::query(
|
||||
r#"INSERT INTO "channel_user"("user_id", "channel_id", "admin") VALUES ($1, $2, $3)"#,
|
||||
)
|
||||
.bind(user_id)
|
||||
.bind(channel_id)
|
||||
.bind(admin)
|
||||
@@ -231,8 +235,9 @@ impl Database {
|
||||
&self,
|
||||
channel_id: entity::ShortId,
|
||||
) -> Result<Vec<(entity::User, bool)>> {
|
||||
let user_ids =
|
||||
sqlx::query_as(r#"SELECT "user_id", "admin" FROM "channel_user" WHERE "channel_id" = $1"#)
|
||||
let user_ids = sqlx::query_as(
|
||||
r#"SELECT "user_id", "admin" FROM "channel_user" WHERE "channel_id" = $1"#,
|
||||
)
|
||||
.bind(channel_id)
|
||||
.fetch_all(&self.pool)
|
||||
.await?;
|
||||
@@ -274,9 +279,7 @@ impl Database {
|
||||
|
||||
// self.set_channel_last_message_id(channel_id, id).await?;
|
||||
|
||||
let id = sqlx::query_scalar(
|
||||
"SELECT create_message_and_update_channel($1, $2, $3)"
|
||||
)
|
||||
let id = sqlx::query_scalar("SELECT create_message_and_update_channel($1, $2, $3)")
|
||||
.bind(channel_id)
|
||||
.bind(user_id)
|
||||
.bind(content)
|
||||
@@ -375,8 +378,9 @@ impl Database {
|
||||
user_id: entity::ShortId,
|
||||
channel_id: entity::ShortId,
|
||||
) -> Result<entity::ChannelPermisions> {
|
||||
let permissions =
|
||||
sqlx::query_as(r#"SELECT * FROM "channel_user" WHERE "user_id" = $1 AND "channel_id" = $2"#)
|
||||
let permissions = sqlx::query_as(
|
||||
r#"SELECT * FROM "channel_user" WHERE "user_id" = $1 AND "channel_id" = $2"#,
|
||||
)
|
||||
.bind(user_id)
|
||||
.bind(channel_id)
|
||||
.fetch_one(&self.pool)
|
||||
@@ -577,7 +581,39 @@ impl Database {
|
||||
}
|
||||
|
||||
pub async fn any_fetch_all_query(&self, query: &str) -> Result<Vec<sqlx::postgres::PgRow>> {
|
||||
let result = sqlx::query(query)
|
||||
let result = sqlx::query(query).fetch_all(&self.pool).await?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub async fn get_report_user_stats(&self) -> Result<Vec<entity::ReportUserStat>> {
|
||||
let result = sqlx::query_as(
|
||||
r#"SELECT
|
||||
u."username",
|
||||
(SELECT COUNT(*) FROM "user_follow" WHERE "follow_id" = u."id") AS followers_count,
|
||||
(SELECT COUNT(*) FROM "user_follow" WHERE "user_id" = u."id") AS following_count,
|
||||
(SELECT COUNT(*) FROM "channel_user" WHERE "user_id" = u."id") AS channels_count,
|
||||
(SELECT COUNT(*) FROM "message" WHERE "author_id" = u."id") AS messages_count
|
||||
FROM
|
||||
"user" u
|
||||
"#,
|
||||
)
|
||||
.fetch_all(&self.pool)
|
||||
.await?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub async fn get_report_channel_stats(&self) -> Result<Vec<entity::ReportChannelStat>> {
|
||||
let result = sqlx::query_as(
|
||||
r#"SELECT
|
||||
c."name",
|
||||
(SELECT COUNT(*) FROM "channel_user" WHERE "channel_id" = c."id") AS members_count,
|
||||
(SELECT COUNT(*) FROM "message" WHERE "channel_id" = c."id") AS messages_count
|
||||
FROM
|
||||
"channel" c
|
||||
"#,
|
||||
)
|
||||
.fetch_all(&self.pool)
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ mod notification;
|
||||
mod secret;
|
||||
mod token;
|
||||
mod user;
|
||||
mod report;
|
||||
|
||||
pub use channel::*;
|
||||
pub use log::*;
|
||||
@@ -15,6 +16,7 @@ pub use notification::*;
|
||||
pub use secret::*;
|
||||
pub use token::*;
|
||||
pub use user::*;
|
||||
pub use report::*;
|
||||
|
||||
pub type ShortId = i32;
|
||||
pub type LongId = i64;
|
||||
|
||||
15
src/entity/report.rs
Normal file
15
src/entity/report.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
#[derive(sqlx::FromRow, serde::Serialize)]
|
||||
pub struct ReportUserStat {
|
||||
username: String,
|
||||
followers_count: i64,
|
||||
following_count: i64,
|
||||
channels_count: i64,
|
||||
messages_count: i64,
|
||||
}
|
||||
|
||||
#[derive(sqlx::FromRow, serde::Serialize)]
|
||||
pub struct ReportChannelStat {
|
||||
name: String,
|
||||
members_count: i64,
|
||||
messages_count: i64,
|
||||
}
|
||||
10
src/main.rs
10
src/main.rs
@@ -15,8 +15,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let _guard = log::initialize()?;
|
||||
|
||||
let database = Database::init().await?;
|
||||
let handlebars = create_handlebars()?;
|
||||
let context = AppState {
|
||||
database,
|
||||
handlebars,
|
||||
connected_users: Default::default(),
|
||||
};
|
||||
|
||||
@@ -24,3 +26,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_handlebars() -> Result<handlebars::Handlebars<'static>, handlebars::TemplateError> {
|
||||
let mut handlebars = handlebars::Handlebars::new();
|
||||
handlebars
|
||||
.register_templates_directory("./templates", handlebars::DirectorySourceOptions::default())?;
|
||||
|
||||
Ok(handlebars)
|
||||
}
|
||||
|
||||
@@ -13,5 +13,6 @@ pub struct WebSocketKey {
|
||||
#[derive(Clone)]
|
||||
pub struct AppState {
|
||||
pub database: Database,
|
||||
pub handlebars: handlebars::Handlebars<'static>,
|
||||
pub connected_users: Arc<RwLock<HashMap<WebSocketKey, UnboundedSender<ws::Message>>>>,
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ pub enum Error {
|
||||
#[from]
|
||||
Context(context::Error),
|
||||
#[from]
|
||||
Template(handlebars::RenderError),
|
||||
#[from]
|
||||
Database(database::Error),
|
||||
#[from]
|
||||
Jwt(jwt::Error),
|
||||
|
||||
@@ -9,9 +9,9 @@ pub mod middlware;
|
||||
pub mod routes;
|
||||
pub mod ws;
|
||||
|
||||
use crate::web::routes::{lab, report};
|
||||
pub use error::{Error, Result};
|
||||
use tower_http::cors::{AllowHeaders, AllowMethods, AllowOrigin};
|
||||
use crate::web::routes::lab;
|
||||
|
||||
pub async fn run(state: state::AppState) -> anyhow::Result<()> {
|
||||
let config = config::config();
|
||||
@@ -48,6 +48,9 @@ fn router(state: state::AppState) -> axum::Router {
|
||||
// lab
|
||||
.route("/lab/users", get(lab::get_all_users))
|
||||
.route("/lab/any-query", post(lab::any_fetch_all_query))
|
||||
.route("/report/user", get(report::get_user_report))
|
||||
.route("/report/channel", get(report::get_channel_report))
|
||||
|
||||
.layer(tower_http::trace::TraceLayer::new_for_http())
|
||||
.route_layer(axum::middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
|
||||
@@ -4,3 +4,4 @@ pub mod notification;
|
||||
pub mod secret;
|
||||
pub mod user;
|
||||
pub mod lab;
|
||||
pub mod report;
|
||||
|
||||
31
src/web/routes/report.rs
Normal file
31
src/web/routes/report.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use axum::extract::State;
|
||||
use axum::response::Html;
|
||||
use serde_json::json;
|
||||
use crate::state::AppState;
|
||||
use crate::web;
|
||||
|
||||
pub async fn get_user_report(
|
||||
State(state): State<AppState>,
|
||||
) -> web::Result<Html<String>> {
|
||||
let users = state.database.get_report_user_stats().await?;
|
||||
|
||||
let hbs = &state.handlebars;
|
||||
let html = hbs.render("user_report", &json!({
|
||||
"users": users,
|
||||
}))?;
|
||||
|
||||
Ok(Html(html))
|
||||
}
|
||||
|
||||
pub async fn get_channel_report(
|
||||
State(state): State<AppState>,
|
||||
) -> web::Result<Html<String>> {
|
||||
let channels = state.database.get_report_channel_stats().await?;
|
||||
|
||||
let hbs = &state.handlebars;
|
||||
let html = hbs.render("channel_report", &json!({
|
||||
"channels": channels,
|
||||
}))?;
|
||||
|
||||
Ok(Html(html))
|
||||
}
|
||||
77
templates/channel_report.hbs
Normal file
77
templates/channel_report.hbs
Normal file
@@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Отчет по статистике каналов</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 20px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
font-size: 24px;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 20px;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
tr:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
@media print {
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
table {
|
||||
margin-top: 0;
|
||||
}
|
||||
tr:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Статистика каналов</h1>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Название</th>
|
||||
<th>Участники</th>
|
||||
<th>Сообщения</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each channels}}
|
||||
<tr>
|
||||
<td>{{#if this.name}}{{this.name}}{{else}}(Без названия){{/if}}</td>
|
||||
<td>{{this.members_count}}</td>
|
||||
<td>{{this.messages_count}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
81
templates/user_report.hbs
Normal file
81
templates/user_report.hbs
Normal file
@@ -0,0 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Отчет по статистике пользователей</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 20px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
font-size: 24px;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 20px;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
tr:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
@media print {
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
table {
|
||||
margin-top: 0;
|
||||
}
|
||||
tr:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Статистика пользователей</h1>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Имя пользователя</th>
|
||||
<th>Подписчики</th>
|
||||
<th>Подписки</th>
|
||||
<th>Каналы</th>
|
||||
<th>Сообщения</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each users}}
|
||||
<tr>
|
||||
<td>{{this.username}}</td>
|
||||
<td>{{this.followers_count}}</td>
|
||||
<td>{{this.following_count}}</td>
|
||||
<td>{{this.channels_count}}</td>
|
||||
<td>{{this.messages_count}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user