Start DB integration

This commit is contained in:
Lol3rrr
2024-09-07 17:44:57 +02:00
parent 324eaf7d3d
commit ae6c1b590f
18 changed files with 680 additions and 53 deletions

363
Cargo.lock generated
View File

@@ -152,8 +152,12 @@ version = "0.1.0"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"axum", "axum",
"diesel",
"diesel-async",
"diesel_async_migrations",
"futures-util", "futures-util",
"serde", "serde",
"serde_json",
"steam-openid", "steam-openid",
"time", "time",
"tokio", "tokio",
@@ -202,6 +206,15 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.16.0" version = "3.16.0"
@@ -344,12 +357,66 @@ version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "cpufeatures"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "crunchy" name = "crunchy"
version = "0.2.2" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "darling"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]] [[package]]
name = "dashmap" name = "dashmap"
version = "5.5.3" version = "5.5.3"
@@ -384,12 +451,109 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "diesel"
version = "2.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "158fe8e2e68695bd615d7e4f3227c0727b151330d3e253b525086c348d055d5e"
dependencies = [
"bitflags 2.6.0",
"byteorder",
"diesel_derives",
"itoa",
"serde_json",
]
[[package]]
name = "diesel-async"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb799bb6f8ca6a794462125d7b8983b0c86e6c93a33a9c55934a4a5de4409d3"
dependencies = [
"async-trait",
"diesel",
"futures-util",
"scoped-futures",
"tokio",
"tokio-postgres",
]
[[package]]
name = "diesel_async_migrations"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b99915cbb9455e8fd56f12edc58f92bbdf8161e4363cb2000cf4308aa6358ff4"
dependencies = [
"diesel",
"diesel-async",
"diesel_async_migrations_macros",
"scoped-futures",
"tracing",
]
[[package]]
name = "diesel_async_migrations_macros"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05de210f31e6ac18162501b03c37f839af9f9fd6dd6de2bb4031ae6691c47679"
dependencies = [
"proc-macro2",
"quote",
]
[[package]]
name = "diesel_derives"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7f2c3de51e2ba6bf2a648285696137aaf0f5f487bcbea93972fe8a364e131a4"
dependencies = [
"diesel_table_macro_syntax",
"dsl_auto_type",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "diesel_table_macro_syntax"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25"
dependencies = [
"syn",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]] [[package]]
name = "drain_filter_polyfill" name = "drain_filter_polyfill"
version = "0.1.3" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "669a445ee724c5c69b1b06fe0b63e70a1c84bc9bb7d9696cd4f4e3ec45050408" checksum = "669a445ee724c5c69b1b06fe0b63e70a1c84bc9bb7d9696cd4f4e3ec45050408"
[[package]]
name = "dsl_auto_type"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5d9abe6314103864cc2d8901b7ae224e0ab1a103a0a416661b4097b0779b607"
dependencies = [
"darling",
"either",
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "either" name = "either"
version = "1.13.0" version = "1.13.0"
@@ -421,6 +585,12 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "fallible-iterator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "2.1.1" version = "2.1.1"
@@ -554,6 +724,16 @@ dependencies = [
"slab", "slab",
] ]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.15" version = "0.2.15"
@@ -675,12 +855,27 @@ version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.3.9" version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]] [[package]]
name = "html-escape" name = "html-escape"
version = "0.2.13" version = "0.2.13"
@@ -835,6 +1030,12 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "idna" name = "idna"
version = "0.5.0" version = "0.5.0"
@@ -1108,6 +1309,16 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]]
name = "md-5"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
dependencies = [
"cfg-if",
"digest",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.4" version = "2.7.4"
@@ -1339,6 +1550,24 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "phf"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_shared"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
dependencies = [
"siphasher",
]
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "1.1.5" version = "1.1.5"
@@ -1377,6 +1606,35 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "postgres-protocol"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acda0ebdebc28befa84bee35e651e4c5f09073d668c7aed4cf7e23c3cda84b23"
dependencies = [
"base64 0.22.1",
"byteorder",
"bytes",
"fallible-iterator",
"hmac",
"md-5",
"memchr",
"rand",
"sha2",
"stringprep",
]
[[package]]
name = "postgres-types"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02048d9e032fb3cc3413bbf7b83a15d84a5d419778e2628751896d856498eee9"
dependencies = [
"bytes",
"fallible-iterator",
"postgres-protocol",
]
[[package]] [[package]]
name = "powerfmt" name = "powerfmt"
version = "0.2.0" version = "0.2.0"
@@ -1695,6 +1953,16 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "scoped-futures"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1473e24c637950c9bd38763220bea91ec3e095a89f672bbd7a10d03e77ba467"
dependencies = [
"cfg-if",
"pin-utils",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
@@ -1877,6 +2145,17 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]] [[package]]
name = "sharded-slab" name = "sharded-slab"
version = "0.1.7" version = "0.1.7"
@@ -1892,6 +2171,12 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "siphasher"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.9" version = "0.4.9"
@@ -1947,6 +2232,29 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "stringprep"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1"
dependencies = [
"unicode-bidi",
"unicode-normalization",
"unicode-properties",
]
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.77" version = "2.0.77"
@@ -2129,6 +2437,32 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "tokio-postgres"
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03adcf0147e203b6032c0b2d30be1415ba03bc348901f3ff1cc0df6a733e60c3"
dependencies = [
"async-trait",
"byteorder",
"bytes",
"fallible-iterator",
"futures-channel",
"futures-util",
"log",
"parking_lot",
"percent-encoding",
"phf",
"pin-project-lite",
"postgres-protocol",
"postgres-types",
"rand",
"socket2",
"tokio",
"tokio-util",
"whoami",
]
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.12" version = "0.7.12"
@@ -2381,6 +2715,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]] [[package]]
name = "unicase" name = "unicase"
version = "2.7.0" version = "2.7.0"
@@ -2411,6 +2751,12 @@ dependencies = [
"tinyvec", "tinyvec",
] ]
[[package]]
name = "unicode-properties"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524"
[[package]] [[package]]
name = "unicode-segmentation" name = "unicode-segmentation"
version = "1.11.0" version = "1.11.0"
@@ -2492,6 +2838,12 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasite"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.93" version = "0.2.93"
@@ -2584,6 +2936,17 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "whoami"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d"
dependencies = [
"redox_syscall",
"wasite",
"web-sys",
]
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"

View File

@@ -9,3 +9,6 @@ A self-hosted demo analysis tool
### Backend ### Backend
1. Navigate to the root folder 1. Navigate to the root folder
2. Run `cargo run --bin backend` 2. Run `cargo run --bin backend`
### DB Stuff
We use [diesel]() as the ORM and using the cli for all the migrations

View File

@@ -8,10 +8,15 @@ async-trait = "0.1.82"
axum = { version = "0.7.5", features = ["multipart"] } axum = { version = "0.7.5", features = ["multipart"] }
serde = { version = "1.0.210", features = ["derive"] } serde = { version = "1.0.210", features = ["derive"] }
steam-openid = "0.2.0" steam-openid = "0.2.0"
time = "0.3.36" time = { version = "0.3.36", features = ["formatting", "parsing"] }
tokio = { version = "1.40.0", features = ["rt", "macros", "net", "mio"] } tokio = { version = "1.40.0", features = ["rt", "macros", "net", "mio"] }
tower-sessions = "0.13.0" tower-sessions = "0.13.0"
tower-http = { version = "0.5", features = ["fs"] } tower-http = { version = "0.5", features = ["fs"] }
tracing = { version = "0.1.40", features = ["async-await"] } tracing = { version = "0.1.40", features = ["async-await"] }
tracing-subscriber = "0.3.18" tracing-subscriber = "0.3.18"
futures-util = "0.3" futures-util = "0.3"
diesel = { version = "2.2", features = ["serde_json"] }
diesel-async = { version = "0.5", features = ["postgres"] }
serde_json = "1.0.128"
diesel_async_migrations = { version = "0.15" }

View File

@@ -0,0 +1,98 @@
use diesel::prelude::*;
use diesel_async::RunQueryDsl;
#[derive(Debug, Clone)]
pub struct DieselStore {}
static EXPIRY_FORMAT: std::sync::LazyLock<&[time::format_description::BorrowedFormatItem<'static>]> = std::sync::LazyLock::new(|| {
time::macros::format_description!(
"[year]-[month]-[day] [hour]:[minute]:[second] [offset_hour sign:mandatory]:[offset_minute]:[offset_second]"
)
});
impl DieselStore {
pub fn new() -> Self {
Self {}
}
fn id_to_bytes(&self, val: i128) -> Vec<i64> {
let id_bytes = val.to_be_bytes();
vec![i64::from_be_bytes((id_bytes[0..8]).try_into().unwrap()), i64::from_be_bytes((id_bytes[8..16]).try_into().unwrap())]
}
fn bytes_to_id(&self, val: Vec<i64>) -> i128 {
assert_eq!(2, val.len());
let fb = val[0].to_be_bytes();
let sb = val[1].to_be_bytes();
i128::from_be_bytes([fb[0], fb[1], fb[2], fb[3], fb[4], fb[5], fb[6], fb[7], sb[0], sb[1], sb[2], sb[3], sb[4], sb[5], sb[6], sb[7]])
}
fn expiry_to_string(&self, expiry_date: &time::OffsetDateTime) -> String {
expiry_date.format(&EXPIRY_FORMAT).unwrap()
}
fn string_to_expiry(&self, input: &str) -> time::OffsetDateTime {
time::OffsetDateTime::parse(input, &EXPIRY_FORMAT).unwrap()
}
}
#[async_trait::async_trait]
impl tower_sessions::SessionStore for DieselStore {
async fn save(&self,session_record: &tower_sessions::session::Record) -> tower_sessions::session_store::Result<()> {
let db_id = self.id_to_bytes(session_record.id.0);
let data = serde_json::to_value(&session_record.data).unwrap();
let expiry_date = self.expiry_to_string(&session_record.expiry_date);
let query = diesel::dsl::insert_into(crate::schema::sessions::dsl::sessions)
.values(crate::models::Session {
id: db_id,
data: data.clone(),
expiry_date: expiry_date.clone(),
})
.on_conflict(crate::schema::sessions::dsl::id)
.do_update()
.set((crate::schema::sessions::dsl::data.eq(data), crate::schema::sessions::dsl::expiry_date.eq(expiry_date)));
let mut connection = crate::db_connection().await;
query.execute(&mut connection).await.unwrap();
Ok(())
}
async fn load(&self,session_id: &tower_sessions::session::Id) -> tower_sessions::session_store::Result<Option<tower_sessions::session::Record>> {
let db_id = self.id_to_bytes(session_id.0);
let query = crate::schema::sessions::dsl::sessions.filter(crate::schema::sessions::dsl::id.eq(db_id));
let mut connection = crate::db_connection().await;
let mut result: Vec<crate::models::Session> = query.load(&mut connection).await.unwrap();
if result.len() > 1 {
tracing::error!("Found more than 1 result");
return Err(tower_sessions::session_store::Error::Backend("Found more than 1 result".to_string()));
}
let result = result.pop().unwrap();
Ok(Some(tower_sessions::session::Record {
id: tower_sessions::session::Id(self.bytes_to_id(result.id)),
data: serde_json::from_value(result.data).unwrap(),
expiry_date: self.string_to_expiry(&result.expiry_date),
}))
}
async fn delete(&self,session_id: &tower_sessions::session::Id) -> tower_sessions::session_store::Result<()> {
let db_id = self.id_to_bytes(session_id.0);
let query = crate::schema::sessions::dsl::sessions.filter(crate::schema::sessions::dsl::id.eq(db_id));
let mut connection = crate::db_connection().await;
diesel::dsl::delete(query).execute(&mut connection).await.unwrap();
Ok(())
}
}

View File

@@ -1,59 +1,19 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize)] pub mod models;
pub struct UserSessionData { pub mod schema;
pub steam_id: Option<u64>,
}
impl Default for UserSessionData { mod usersession;
fn default() -> Self { pub use usersession::{UserSessionData, UserSession};
Self { steam_id: None }
}
}
pub struct UserSession { pub mod diesel_sessionstore;
pub session: tower_sessions::Session,
data: UserSessionData,
}
impl UserSession { pub async fn db_connection() -> diesel_async::AsyncPgConnection {
const KEY: &'static str = "user.data"; use diesel_async::AsyncConnection;
pub fn data(&self) -> &UserSessionData { let database_url = std::env::var("DATABASE_URL").expect("'DATABASE_URL' must be set");
&self.data
}
pub async fn modify_data<F>(&mut self, func: F) diesel_async::AsyncPgConnection::establish(&database_url).await.unwrap_or_else(|e| panic!("Error connecting to {} - {:?}", database_url, e))
where
F: FnOnce(&mut UserSessionData),
{
let mut entry = &mut self.data;
func(&mut entry);
self.session.insert(Self::KEY, entry).await.unwrap();
}
}
#[async_trait::async_trait]
impl<S> axum::extract::FromRequestParts<S> for UserSession
where
S: Send + Sync,
{
type Rejection = (axum::http::StatusCode, &'static str);
async fn from_request_parts(
req: &mut axum::http::request::Parts,
state: &S,
) -> Result<Self, Self::Rejection> {
let session = tower_sessions::Session::from_request_parts(req, state).await?;
let guest_data: UserSessionData = session.get(Self::KEY).await.unwrap().unwrap_or_default();
Ok(Self {
session,
data: guest_data,
})
}
} }
pub async fn get_demo_from_upload(name: &str, mut form: axum::extract::Multipart) -> Option<axum::body::Bytes> { pub async fn get_demo_from_upload(name: &str, mut form: axum::extract::Multipart) -> Option<axum::body::Bytes> {

View File

@@ -1,10 +1,19 @@
use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt; use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt;
use diesel::prelude::*;
use diesel_async::{RunQueryDsl, AsyncConnection, AsyncPgConnection};
static OPENID: std::sync::LazyLock<steam_openid::SteamOpenId> = std::sync::LazyLock::new(|| { static OPENID: std::sync::LazyLock<steam_openid::SteamOpenId> = std::sync::LazyLock::new(|| {
steam_openid::SteamOpenId::new("http://192.168.0.156:3000", "/api/steam/callback").unwrap() steam_openid::SteamOpenId::new("http://192.168.0.156:3000", "/api/steam/callback").unwrap()
}); });
static UPLOAD_FOLDER: &str = "uploads/"; static UPLOAD_FOLDER: &str = "uploads/";
const MIGRATIONS: diesel_async_migrations::EmbeddedMigrations = diesel_async_migrations::embed_migrations!("../migrations/");
async fn run_migrations(connection: &mut diesel_async::AsyncPgConnection) {
MIGRATIONS.run_pending_migrations(connection).await.unwrap();
}
#[tokio::main(flavor = "current_thread")] #[tokio::main(flavor = "current_thread")]
async fn main() { async fn main() {
let registry = tracing_subscriber::Registry::default() let registry = tracing_subscriber::Registry::default()
@@ -16,7 +25,11 @@ async fn main() {
tracing::info!("Starting..."); tracing::info!("Starting...");
let session_store = tower_sessions::MemoryStore::default(); tracing::info!("Applying Migrations");
run_migrations(&mut backend::db_connection().await).await;
tracing::info!("Completed Migrations");
let session_store = backend::diesel_sessionstore::DieselStore::new();
let session_layer = tower_sessions::SessionManagerLayer::new(session_store) let session_layer = tower_sessions::SessionManagerLayer::new(session_store)
.with_secure(false) .with_secure(false)
.with_expiry(tower_sessions::Expiry::OnInactivity( .with_expiry(tower_sessions::Expiry::OnInactivity(
@@ -60,8 +73,11 @@ async fn upload(session: backend::UserSession, form: axum::extract::Multipart) -
tokio::fs::write(demo_file_path, file_content).await.unwrap(); tokio::fs::write(demo_file_path, file_content).await.unwrap();
// TODO let query = diesel::dsl::insert_into(backend::schema::demos::dsl::demos).values(backend::models::Demo {
// Insert Demo into users list of demos and possibly queue demo for analysis? demo_id: timestamp_secs as i64,
steam_id: steam_id as i64,
});
query.execute(&mut backend::db_connection().await).await.unwrap();
Ok(axum::response::Redirect::to("/")) Ok(axum::response::Redirect::to("/"))
} }
@@ -101,5 +117,10 @@ async fn demos_list(session: backend::UserSession) -> Result<(), axum::http::Sta
let steam_id = session.data().steam_id.ok_or_else(|| axum::http::StatusCode::UNAUTHORIZED)?; let steam_id = session.data().steam_id.ok_or_else(|| axum::http::StatusCode::UNAUTHORIZED)?;
tracing::info!("SteamID: {:?}", steam_id); tracing::info!("SteamID: {:?}", steam_id);
let query = backend::schema::demos::dsl::demos.filter(backend::schema::demos::dsl::steam_id.eq(steam_id as i64));
let results: Vec<backend::models::Demo> = query.load(&mut backend::db_connection().await).await.unwrap();
dbg!(&results);
Ok(()) Ok(())
} }

18
backend/src/models.rs Normal file
View File

@@ -0,0 +1,18 @@
use diesel::prelude::*;
#[derive(Queryable, Selectable, Insertable, Debug)]
#[diesel(table_name = crate::schema::sessions)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct Session {
pub id: Vec<i64>,
pub data: serde_json::Value,
pub expiry_date: String,
}
#[derive(Queryable, Selectable, Insertable, Debug)]
#[diesel(table_name = crate::schema::demos)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct Demo {
pub steam_id: i64,
pub demo_id: i64,
}

14
backend/src/schema.rs Normal file
View File

@@ -0,0 +1,14 @@
diesel::table! {
sessions (id) {
id -> Array<BigInt>,
data -> Jsonb,
expiry_date -> Text,
}
}
diesel::table! {
demos (steam_id) {
steam_id -> BigInt,
demo_id -> BigInt
}
}

View File

@@ -0,0 +1,58 @@
use diesel::prelude::*;
use diesel_async::RunQueryDsl;
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct UserSessionData {
pub steam_id: Option<u64>,
}
impl Default for UserSessionData {
fn default() -> Self {
Self { steam_id: None }
}
}
pub struct UserSession {
pub session: tower_sessions::Session,
data: UserSessionData,
}
impl UserSession {
const KEY: &'static str = "user.data";
pub fn data(&self) -> &UserSessionData {
&self.data
}
pub async fn modify_data<F>(&mut self, func: F)
where
F: FnOnce(&mut UserSessionData),
{
let mut entry = &mut self.data;
func(&mut entry);
self.session.insert(Self::KEY, entry).await.unwrap();
}
}
#[async_trait::async_trait]
impl<S> axum::extract::FromRequestParts<S> for UserSession
where
S: Send + Sync,
{
type Rejection = (axum::http::StatusCode, &'static str);
async fn from_request_parts(
req: &mut axum::http::request::Parts,
state: &S,
) -> Result<Self, Self::Rejection> {
let session = tower_sessions::Session::from_request_parts(req, state).await?;
let guest_data: UserSessionData = session.get(Self::KEY).await.unwrap().unwrap_or_default();
Ok(Self {
session,
data: guest_data,
})
}
}

9
diesel.toml Normal file
View 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/schema.rs"
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
[migrations_directory]
dir = "/Users/leon/Documents/coding/rust/knifer/migrations"

0
migrations/.keep Normal file
View File

View 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();

View 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;

View File

@@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
DROP TABLE sessions

View File

@@ -0,0 +1,6 @@
-- Your SQL goes here
CREATE TABLE IF NOT EXISTS sessions (
id bigint[2] PRIMARY KEY,
data jsonb,
expiry_date TEXT
)

View File

@@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
DROP TABLE demos

View File

@@ -0,0 +1,5 @@
-- Your SQL goes here
CREATE TABLE IF NOT EXISTS demos (
steam_id bigint PRIMARY KEY,
demo_id bigint
)

21
src/schema.rs Normal file
View File

@@ -0,0 +1,21 @@
// @generated automatically by Diesel CLI.
diesel::table! {
demos (steam_id) {
steam_id -> Int8,
demo_id -> Nullable<Int8>,
}
}
diesel::table! {
sessions (id) {
id -> Array<Nullable<Int8>>,
data -> Nullable<Jsonb>,
expiry_date -> Nullable<Text>,
}
}
diesel::allow_tables_to_appear_in_same_query!(
demos,
sessions,
);