diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9817a23..68581f8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,29 +1,30 @@ name: tests on: - push: - branches: - - master - - main - pull_request: + push: + branches: + - master + - main + pull_request: jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af #@v1 - with: - profile: minimal - toolchain: stable - components: clippy - override: true - - uses: erlef/setup-beam@v1 - with: - otp-version: "26.0.2" - gleam-version: "1.4.1" - rebar3-version: "3" - # elixir-version: "1.15.4" - - uses: oven-sh/setup-bun@v2 - with: - bun-version: "1.1.30" - - run: bash ./build.sh --test + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af #@v1 + with: + profile: minimal + toolchain: stable + components: clippy + override: true + - uses: erlef/setup-beam@v1 + with: + otp-version: "26.0.2" + gleam-version: "1.4.1" + rebar3-version: "3" + # elixir-version: "1.15.4" + - uses: oven-sh/setup-bun@v2 + with: + bun-version: "1.1.30" + # For now at least. + - run: bash ./build.sh --test --backend=gleam diff --git a/backend-rs/Cargo.lock b/backend-rs/Cargo.lock index 06664f5..fe4f212 100644 --- a/backend-rs/Cargo.lock +++ b/backend-rs/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "actix-codec" @@ -35,7 +35,7 @@ dependencies = [ "brotli", "bytes", "bytestring", - "derive_more", + "derive_more 0.99.18", "encoding_rs", "flate2", "futures-core", @@ -60,15 +60,15 @@ dependencies = [ [[package]] name = "actix-identity" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c99b7a5614b72a78f04aa2021e5370fc1aef2475fffeffc0c1266b99007062" +checksum = "23b8ddc6f6a8b19c4016aaa13519968da9969bc3bc1c1c883cdb0f25dd6c8cf7" dependencies = [ "actix-service", "actix-session", "actix-utils", "actix-web", - "derive_more", + "derive_more 1.0.0", "futures-core", "serde", "tracing", @@ -139,15 +139,16 @@ dependencies = [ [[package]] name = "actix-session" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b671404ec72194d8af58c2bdaf51e3c477a0595056bd5010148405870dda8df2" +checksum = "efe6976a74f34f1b6d07a6c05aadc0ed0359304a7781c367fa5b4029418db08f" dependencies = [ "actix-service", "actix-utils", "actix-web", "anyhow", - "derive_more", + "derive_more 1.0.0", + "rand", "serde", "serde_json", "tracing", @@ -183,7 +184,7 @@ dependencies = [ "bytestring", "cfg-if", "cookie", - "derive_more", + "derive_more 0.99.18", "encoding_rs", "futures-core", "futures-util", @@ -241,18 +242,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "aes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" -dependencies = [ - "cfg-if", - "cipher 0.3.0", - "cpufeatures", - "opaque-debug", -] - [[package]] name = "aes" version = "0.8.4" @@ -260,7 +249,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", - "cipher 0.4.4", + "cipher", "cpufeatures", ] @@ -271,8 +260,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" dependencies = [ "aead", - "aes 0.8.4", - "cipher 0.4.4", + "aes", + "cipher", "ctr", "ghash", "subtle", @@ -478,6 +467,17 @@ version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -511,12 +511,6 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5" -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -541,16 +535,6 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "block-padding", - "generic-array", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -561,21 +545,14 @@ dependencies = [ ] [[package]] -name = "block-modes" -version = "0.8.1" +name = "block-padding" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" dependencies = [ - "block-padding", - "cipher 0.3.0", + "generic-array", ] -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - [[package]] name = "blocking" version = "1.6.1" @@ -643,15 +620,24 @@ dependencies = [ "bytes", ] +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + [[package]] name = "cc" -version = "1.0.101" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac367972e516d45567c7eafc73d24e1c193dcf200a8d94e9db7b3d38b349572d" +checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" dependencies = [ "jobserver", "libc", - "once_cell", + "shlex", ] [[package]] @@ -674,15 +660,6 @@ dependencies = [ "windows-targets 0.52.5", ] -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array", -] - [[package]] name = "cipher" version = "0.4.4" @@ -743,7 +720,7 @@ dependencies = [ "hmac", "percent-encoding", "rand", - "sha2 0.10.8", + "sha2", "subtle", "time", "version_check", @@ -838,7 +815,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ - "cipher 0.4.4", + "cipher", ] [[package]] @@ -870,23 +847,33 @@ dependencies = [ ] [[package]] -name = "des" -version = "0.7.0" +name = "derive_more" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac41dd49fb554432020d52c875fc290e110113f864c6b1b525cd62c7e7747a5d" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "byteorder", - "cipher 0.3.0", - "opaque-debug", + "derive_more-impl", ] [[package]] -name = "digest" -version = "0.9.0" +name = "derive_more-impl" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ - "generic-array", + "proc-macro2", + "quote", + "syn 2.0.68", + "unicode-xid", +] + +[[package]] +name = "des" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" +dependencies = [ + "cipher", ] [[package]] @@ -895,11 +882,17 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "crypto-common", "subtle", ] +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "dtoa" version = "1.0.9" @@ -979,6 +972,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + [[package]] name = "fallible-iterator" version = "0.3.0" @@ -1280,11 +1279,12 @@ dependencies = [ [[package]] name = "handlebars" -version = "5.1.2" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" +checksum = "fd4ccde012831f9a071a637b0d4e31df31c0f6c525784b35ae76a9ac6bc1e315" dependencies = [ "log", + "num-order", "pest", "pest_derive", "serde", @@ -1337,7 +1337,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -1555,6 +1555,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ + "block-padding", "generic-array", ] @@ -1637,9 +1638,9 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libsqlite3-sys" -version = "0.28.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" dependencies = [ "cc", "pkg-config", @@ -1713,18 +1714,17 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" [[package]] name = "magic-crypt" -version = "3.1.13" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c42f95f9d296f2dcb50665f507ed5a68a171453142663ce44d77a4eb217b053" +checksum = "844b6169eeaae32ae8a61855964331a67f12d2afba9170303fbd3e3c2a861a52" dependencies = [ - "aes 0.7.5", - "base64 0.21.7", - "block-modes", + "aes", + "base64 0.22.1", + "cbc", "crc-any", "des", - "digest 0.9.0", "md-5", - "sha2 0.9.9", + "sha2", "tiger", ] @@ -1753,13 +1753,12 @@ dependencies = [ [[package]] name = "md-5" -version = "0.9.1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "opaque-debug", + "cfg-if", + "digest", ] [[package]] @@ -1824,6 +1823,21 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[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.19" @@ -1975,7 +1989,7 @@ version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ - "digest 0.10.7", + "digest", "hmac", ] @@ -2027,7 +2041,7 @@ checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" dependencies = [ "once_cell", "pest", - "sha2 0.10.8", + "sha2", ] [[package]] @@ -2208,6 +2222,49 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +[[package]] +name = "postgres" +version = "0.19.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95c918733159f4d55d2ceb262950f00b0aebd6af4aa97b5a47bb0655120475ed" +dependencies = [ + "bytes", + "fallible-iterator 0.2.0", + "futures-util", + "log", + "tokio", + "tokio-postgres", +] + +[[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 0.2.0", + "hmac", + "md-5", + "memchr", + "rand", + "sha2", + "stringprep", +] + +[[package]] +name = "postgres-types" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f66ea23a2d0e5734297357705193335e0a957696f34bed2f2faefacb2fec336f" +dependencies = [ + "bytes", + "fallible-iterator 0.2.0", + "postgres-protocol", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -2379,12 +2436,12 @@ dependencies = [ [[package]] name = "rusqlite" -version = "0.31.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae" +checksum = "7753b721174eb8ff87a9a0e799e2d7bc3749323e773db92e0984debb00019d6e" dependencies = [ "bitflags 2.6.0", - "fallible-iterator", + "fallible-iterator 0.3.0", "fallible-streaming-iterator", "hashlink", "libsqlite3-sys", @@ -2541,7 +2598,7 @@ checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" dependencies = [ "bitflags 2.6.0", "cssparser", - "derive_more", + "derive_more 0.99.18", "fxhash", "log", "new_debug_unreachable", @@ -2627,32 +2684,25 @@ checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] name = "sha2" -version = "0.9.9" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "digest", ] [[package]] -name = "sha2" -version = "0.10.8" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" @@ -2739,6 +2789,7 @@ dependencies = [ "chrono", "colored", "console", + "dotenv", "futures", "handlebars", "home", @@ -2749,6 +2800,7 @@ dependencies = [ "markdown", "password-hash", "pbkdf2", + "postgres", "rand", "regex", "reqwest", @@ -2787,6 +2839,17 @@ dependencies = [ "quote", ] +[[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 = "subtle" version = "2.6.1" @@ -2896,13 +2959,11 @@ dependencies = [ [[package]] name = "tiger" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443e531cbcf9de83258cfef70bcd56c91188de5819ebd4b19c85f589e0617005" +checksum = "579abbce4ad73b04386dbeb34369c9873a8f9b749c7b99cbf479a2949ff715ed" dependencies = [ - "block-buffer 0.9.0", - "byteorder", - "digest 0.9.0", + "digest", ] [[package]] @@ -2993,6 +3054,32 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-postgres" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b5d3742945bc7d7f210693b0c58ae542c6fd47b17adbbda0885f3dcb34a6bdb" +dependencies = [ + "async-trait", + "byteorder", + "bytes", + "fallible-iterator 0.2.0", + "futures-channel", + "futures-util", + "log", + "parking_lot", + "percent-encoding", + "phf 0.11.2", + "pin-project-lite", + "postgres-protocol", + "postgres-types", + "rand", + "socket2 0.5.7", + "tokio", + "tokio-util", + "whoami", +] + [[package]] name = "tokio-rustls" version = "0.26.0" @@ -3143,12 +3230,24 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + [[package]] name = "unicode-width" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "universal-hash" version = "0.5.1" @@ -3221,6 +3320,12 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -3297,6 +3402,17 @@ dependencies = [ "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]] name = "winapi" version = "0.3.9" diff --git a/backend-rs/Cargo.toml b/backend-rs/Cargo.toml index 4472813..294ad0d 100644 --- a/backend-rs/Cargo.toml +++ b/backend-rs/Cargo.toml @@ -53,7 +53,7 @@ futures = "0.3.30" async-std = "1.12.0" colored = "2.0.4" log = "0.4.21" -rusqlite = { version = "0.31.0", features = ["bundled"] } +rusqlite = { version = "0.32.1", features = ["bundled"] } time = "0.3.34" password-hash = "0.5.0" tokio = { version = "1.38.0", features = [ @@ -63,17 +63,19 @@ tokio = { version = "1.38.0", features = [ "time", ] } pbkdf2 = "0.12.2" -actix-session = { version = "0.9.0", features = ["cookie-session"] } -actix-identity = "0.7.1" +actix-session = { version = "0.10.1", features = ["cookie-session"] } +actix-identity = "0.8.0" actix-web = "4.7.0" -handlebars = "5.1.0" +handlebars = "6.2.0" +postgres = "0.19.9" home = "0.5.9" -magic-crypt = "3.1.13" +magic-crypt = "4.0.1" rand = "0.8.5" build_const = "0.2.2" markdown = "1.0.0-alpha.18" chrono = "0.4.38" simplelog = "0.12.2" +dotenv = "0.15.0" indicatif = "0.17.8" console = "0.15.8" [build-dependencies] diff --git a/backend-rs/src/api_fe.rs b/backend-rs/src/api_fe.rs index a473af2..526cfa6 100644 --- a/backend-rs/src/api_fe.rs +++ b/backend-rs/src/api_fe.rs @@ -79,7 +79,7 @@ pub(crate) fn checksessionvalidity(id: i64, session: &Session, config: &LuminaCo match id { -100 => false, _ => match session.get::("validity") { - Ok(s) => matches!(s, Some(a) if a == config.clone().run.session_valid), + Ok(s) => matches!(s, Some(a) if a == config.clone().erun.session_valid), Err(_) => false, }, } @@ -112,7 +112,7 @@ pub(crate) async fn update( instance: JSClientInstance { config: JSClientConfig { interinstance: JSClientInterinstance { - iid: config.clone().interinstance.iid, + iid: config.clone().lumina_synchronisation_iid, lastsync: 0, }, }, @@ -166,7 +166,7 @@ pub(crate) async fn auth( session.insert("userid", user.id).unwrap(); session.insert("username", username).unwrap(); session - .insert("validity", config.clone().run.session_valid) + .insert("validity", config.clone().erun.session_valid) .unwrap(); HttpResponse::build(StatusCode::OK) .content_type("text/json; charset=utf-8") @@ -209,7 +209,7 @@ pub(crate) async fn newaccount( session.insert("userid", user.id).unwrap(); session.insert("username", username).unwrap(); session - .insert("validity", config.clone().run.session_valid) + .insert("validity", config.clone().erun.session_valid) .unwrap(); server_vars.tell(format!( "User creation request: approved for {} @ {}", diff --git a/backend-rs/src/api_ii.rs b/backend-rs/src/api_ii.rs index c139b3a..b0431c2 100644 --- a/backend-rs/src/api_ii.rs +++ b/backend-rs/src/api_ii.rs @@ -8,7 +8,7 @@ use std::time::Duration; -use crate::{LuminaConfig, ServerVars, SynclistItem}; +use crate::{database, LuminaConfig, ServerVars, SynclistItem}; use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; use tokio::time::sleep; @@ -16,7 +16,7 @@ pub(crate) async fn main(vars: ServerVars) { let progressbars = MultiProgress::new(); let config: LuminaConfig = vars.config.clone(); let mut round = 0; - let mut sync_interval = config.interinstance.syncing.syncintervall; + let mut sync_interval = config.lumina_synchronisation_interval; if sync_interval < 30 { sync_interval = 120 }; @@ -44,7 +44,8 @@ pub(crate) async fn main(vars: ServerVars) { .set_message(vars.format_tell(format!("{} seconds left.", remaining_waiting_time))); sleep(Duration::from_secs(1)).await; } - let number_of_instances: u64 = config.interinstance.synclist.len() as u64; + + let number_of_instances: u64 = database::get_instance_sync_list(&config).unwrap_or(vec![]).len() as u64; if number_of_instances == 0 { waiting_counter.println(vars.format_tell("Syncer: No instances to sync from are listed. Syncer will close until further notice to preserve CPU threads.")); waiting_counter.finish_and_clear(); @@ -66,7 +67,7 @@ pub(crate) async fn main(vars: ServerVars) { .unwrap() .progress_chars("██░"), ); - for instance in config.interinstance.synclist.iter() { + for instance in database::get_instance_sync_list(&config).unwrap_or_default().into_iter() { sync_progress_through_instances.inc(1); sync_progress_through_instances .set_message(vars.format_tell(format!("Syncing: {}", instance.name))); diff --git a/backend-rs/src/config.rs b/backend-rs/src/config.rs new file mode 100644 index 0000000..143ef94 --- /dev/null +++ b/backend-rs/src/config.rs @@ -0,0 +1,238 @@ +use crate::ERun; +use std::path::PathBuf; +use colored::Colorize; + +#[derive(Clone, Debug)] +pub struct LuminaConfig { + pub(crate) lumina_server_port: u16, + pub(crate) lumina_server_addr: String, + pub(crate) lumina_server_https: bool, + pub(crate) lumina_synchronisation_iid: String, + pub(crate) lumina_synchronisation_interval: u64, + pub(crate) db_custom_salt: String, + pub(crate) db_connection_info: LuminaDBConnectionInfo, + pub(crate) logging: Option, + /// Run time information + pub(crate) erun: ERun, +} + +#[derive(Clone, Debug)] +pub enum LuminaDBConnectionInfo { + LuminaDBConnectionInfoPOSTGRES(postgres::Config), + LuminaDBConnectionInfoSQLite(PathBuf), +} + +#[derive(Default, Debug, Clone, PartialEq)] +pub struct LuminaLogConfig { + pub file_loglevel: Option, + pub term_loglevel: Option, + pub logfile: Option, +} +#[derive(Debug)] +enum DBType { + POSTGRES, + SQLITE, +} +impl LuminaConfig { + /// Loads the configuration from environment variables after reading an env file if it exists. + pub fn new(erun: ERun) -> Self { + if erun.cd.join(".env").exists() { + if dotenv::from_path(erun.cd.join(".env")).is_ok() { + info!( + "Loaded environment variables from '{}' file.", + erun.cd.join(".env").display() + ); + }; + } else { + info!( + "No '.env' file found in the directory '{}'. Using only environment variables.", + erun.cd.display() + ); + } + + let db_type: DBType = { + match std::env::var("_LUMINA_DB_TYPE_") + .unwrap_or(String::from("SQLITE")) + .to_uppercase() + .as_str() + { + "POSTGRES" => DBType::POSTGRES, + _ => { + println!("{}", "Using SQLITE database, this is not recommended for production as it is not scalable.".yellow()); + println!("{}","To use a different database, set the '_LUMINA_DB_TYPE_' environment variable to 'POSTGRES'.".purple()); + DBType::SQLITE + } + } + }; + let db_connection_info = match db_type { + DBType::SQLITE => { + let keyname = "_LUMINA_SQLITE_FILE_"; + let def_val = String::from("instance.db"); + match std::env::var(keyname) { + Ok(val) => { + LuminaDBConnectionInfo::LuminaDBConnectionInfoSQLite(erun.cd.join(val)) + } + Err(_) => { + warn!("The key '{}' was not found in the environment variables. Using default: {}", keyname, def_val); + LuminaDBConnectionInfo::LuminaDBConnectionInfoSQLite(erun.cd.join(def_val)) + } + } + } + DBType::POSTGRES => { + let mut pg_config = postgres::Config::new(); + { + match std::env::var("_LUMINA_POSTGRES_USERNAME_") { + Ok(val) => { + pg_config.user(&val); + } + Err(_) => { + error!("No Postgres database user provided under environment variable '_LUMINA_POSTGRES_USER_'. Exiting."); + std::process::exit(1); + } + } + } + match std::env::var("_LUMINA_POSTGRES_HOST_") { + Ok(val) => { + pg_config.host(&val); + } + Err(_) => { + warn!("No Postgres database host provided under environment variable '_LUMINA_POSTGRES_HOST_'. Using default value 'localhost'."); + pg_config.host("localhost"); + } + }; + match std::env::var("_LUMINA_POSTGRES_PASSWORD_") { + Ok(val) => { + pg_config.password(&val); + } + Err(_) => { + info!("No Postgres database password provided under environment variable '_LUMINA_POSTGRES_PASSWORD_'. Using passwordless connection."); + } + }; + match std::env::var("_LUMINA_POSTGRES_DATABASE_") { + Ok(val) => { + pg_config.dbname(&val); + } + Err(_) => { + error!("No Postgres database name provided under environment variable '_LUMINA_POSTGRES_DATABASE_'. Exiting."); + std::process::exit(1); + } + }; + { + match std::env::var("_LUMINA_POSTGRES_PORT_") { + Ok(val) => match val.parse::() { + Ok(v) => { + pg_config.port(v); + } + Err(_) => { + error!("The value '{}' for the key '_LUMINA_POSTGRES_PORT_' is not a valid port number. Exiting.", val); + std::process::exit(1); + } + }, + Err(_) => { + warn!("No Postgres database port provided under environment variable '_LUMINA_POSTGRES_PORT_'. Using default value '5432'."); + pg_config.port(5432); + } + } + } + + LuminaDBConnectionInfo::LuminaDBConnectionInfoPOSTGRES(pg_config) + } + }; + + + LuminaConfig { + lumina_server_port: { + let keyname = "_LUMINA_SERVER_PORT_"; + let def_val = String::from("8085"); + match std::env::var(keyname) { + Ok(val) => match val.parse::() { + Ok(v) => v, + Err(_) => { + error!("The value '{}' for the key '{}' is not a valid port number. Exiting.", val, keyname); + std::process::exit(1); + } + }, + Err(_) => { + warn!("The key '{}' was not found in the environment variables. Using default value.", keyname); + def_val.parse::().unwrap() + } + } + }, + lumina_server_addr: { + let keyname = "_LUMINA_SERVER_ADDR_"; + let def_val = String::from("localhost"); + match std::env::var(keyname) { + Ok(val) => val, + Err(_) => { + warn!("The key '{}' was not found in the environment variables. Using default value.", keyname); + def_val + } + } + }, + lumina_server_https: { + let keyname = "_LUMINA_SERVER_HTTPS_"; + let def_val = String::from("true"); + match std::env::var(keyname) { + Ok(val) => { + match val.parse::() { + Ok(v) => v, + Err(_) => { + error!("The value '{}' for the key '{}' is not a valid boolean. Exiting.", val, keyname); + std::process::exit(1); + } + } + } + Err(_) => { + warn!("The key '{}' was not found in the environment variables. Using default value.", keyname); + def_val.parse::().unwrap() + } + } + }, + lumina_synchronisation_iid: { + let keyname = "_LUMINA_SYNCHRONISATION_IID_"; + let def_val = String::from("localhost"); + match std::env::var(keyname) { + Ok(val) => val, + Err(_) => { + warn!("The key '{}' was not found in the environment variables. Using default value.", keyname); + def_val + } + } + }, + lumina_synchronisation_interval: { + let keyname = "_LUMINA_SYNCHRONISATION_INTERVAL_"; + let def_val = String::from("30"); + match std::env::var(keyname) { + Ok(val) => { + match val.parse::() { + Ok(v) => v, + Err(_) => { + error!("The value '{}' for the key '{}' is not a valid number. Exiting.", val, keyname); + std::process::exit(1); + } + } + } + Err(_) => { + warn!("The key '{}' was not found in the environment variables. Using default value.", keyname); + def_val.parse::().unwrap() + } + } + }, + db_custom_salt: { + let keyname = "_LUMINA_DB_SALT_"; + let def_val = String::from("sally_sal"); + match std::env::var(keyname) { + Ok(val) => val, + Err(_) => { + warn!("The key '{}' was not found in the environment variables. Using default value.", keyname); + def_val + } + } + }, + db_connection_info, + // Uses the default value of Logging::default() fer now. + logging: None, + erun, + } + } +} diff --git a/backend-rs/src/database.rs b/backend-rs/src/database.rs index 31f4faf..d0b2444 100644 --- a/backend-rs/src/database.rs +++ b/backend-rs/src/database.rs @@ -5,15 +5,16 @@ */ #![allow(dead_code)] +use crate::config::LuminaDBConnectionInfo; +use crate::post::PostInfo; +use crate::{LuminaConfig, SynclistItem}; +use colored::Colorize; +use rusqlite::{params, Connection}; +use serde::{Deserialize, Serialize}; use std::any::type_name; use std::io::Error; use std::process; - -use rusqlite::{params, Connection}; -use serde::{Deserialize, Serialize}; - -use crate::post::PostInfo; -use crate::LuminaConfig; +use LuminaDBConnectionInfo::{LuminaDBConnectionInfoPOSTGRES, LuminaDBConnectionInfoSQLite}; /// Basic exchangable user information. #[derive(Debug, Serialize, Deserialize, Clone)] @@ -43,25 +44,471 @@ impl BasicUserInfo { IIExchangedUserInfo { id: self.id, username: self.username.clone(), - instance: config.interinstance.iid.clone(), + instance: config.lumina_synchronisation_iid.clone(), + } + } +} + +impl LuminaConfig { + /// Create a database connection to either SQLite or POSTGRES. + pub(crate) fn db_connect(&self) -> LuminaDBConnection { + match self.db_connection_info.clone() { + LuminaDBConnectionInfoSQLite(file) => match Connection::open(file.clone()) { + Ok(d) => LuminaDBConnection::SQLite(d), + Err(_e) => { + error!( + "Could not create a database connection to <{}>", + file.display().to_string().yellow() + ); + process::exit(1); + } + }, + LuminaDBConnectionInfoPOSTGRES(pg_config) => { + let f = pg_config.connect(postgres::tls::NoTls).unwrap(); + LuminaDBConnection::POSTGRES(f) + } } } } -/// Create a database connection -pub(crate) fn create_con(config: &LuminaConfig) -> Connection { - match Connection::open( - config - .clone() - .run - .cd - .join(config.clone().database.sqlite.unwrap().file), - ) { - Ok(d) => d, - Err(_e) => { - error!("Could not create a database connection!"); +pub enum LuminaDBConnection { + SQLite(Connection), + POSTGRES(postgres::Client), +} + +impl LuminaDBConnection { + pub(crate) fn initial_dbconf(&mut self) { + fn emergencyabort() { + error!("Could not configure the database correctly!"); process::exit(1); } + let qs = [ + "CREATE TABLE IF NOT EXISTS external_posts( + host_id INTEGER PRIMARY KEY, + source_id INTEGER NOT NULL, + source_instance TEXT NOT NULL + );", + "CREATE TABLE IF NOT EXISTS interinstance_relations( + instance_id TEXT PRIMARY KEY, + synclevel TEXT NOT NULL, + last_contact INTEGER NOT NULL + );", + "CREATE TABLE IF NOT EXISTS local_posts( + host_id INTEGER PRIMARY KEY, + user_id INTEGER NOT NULL, + privacy INTEGER NOT NULL + );", + "CREATE TABLE IF NOT EXISTS posts_pool( + postid INTEGER PRIMARY KEY, + kind TEXT NOT NULL, + content TEXT NOT NULL, + from_local INTEGER NOT NULL + );", + "CREATE TABLE IF NOT EXISTS users( + id INTEGER PRIMARY KEY, + username TEXT NOT NULL, + password TEXT NOT NULL, + email TEXT NOT NULL + );", + ]; + + for query in qs { + match self.execute0(query) { + Ok(_) => {} + Err(_e) => emergencyabort(), + } + } + } + pub(crate) fn execute0(&mut self, query: &str) -> Result<(), ()> { + match self { + LuminaDBConnection::SQLite(conn) => { + conn.execute(query, ()).map(|_r| ()).map_err(|_e| ()) + } + LuminaDBConnection::POSTGRES(client) => { + client.execute(query, &[]).map(|_r| ()).map_err(|_e| ()) + } + } + } + pub(crate) fn execute1(&mut self, query: &str, param: impl AsRef) -> Result<(), ()> { + match self { + LuminaDBConnection::SQLite(conn) => conn + .execute(query, &[¶m.as_ref()]) + .map(|_r| ()) + .map_err(|_e| ()), + LuminaDBConnection::POSTGRES(client) => client + .execute(query, &[¶m.as_ref()]) + .map(|_r| ()) + .map_err(|_e| ()), + } + } + pub(crate) fn execute2( + &mut self, + query: &str, + params: (impl AsRef, impl AsRef), + ) -> Result<(), ()> { + match self { + LuminaDBConnection::SQLite(conn) => conn + .execute(query, &[¶ms.0.as_ref(), ¶ms.1.as_ref()]) + .map(|_r| ()) + .map_err(|_e| ()), + LuminaDBConnection::POSTGRES(client) => client + .execute(query, &[¶ms.0.as_ref(), ¶ms.1.as_ref()]) + .map(|_r| ()) + .map_err(|_e| ()), + } + } + pub(crate) fn execute3( + &mut self, + query: &str, + params: (impl AsRef, impl AsRef, impl AsRef), + ) -> Result<(), ()> { + match self { + LuminaDBConnection::SQLite(conn) => conn + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + LuminaDBConnection::POSTGRES(client) => client + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + } + } + pub(crate) fn execute4( + &mut self, + query: &str, + params: ( + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + ), + ) -> Result<(), ()> { + match self { + LuminaDBConnection::SQLite(conn) => conn + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + LuminaDBConnection::POSTGRES(client) => client + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + } + } + pub(crate) fn execute5( + &mut self, + query: &str, + params: ( + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + ), + ) -> Result<(), ()> { + match self { + LuminaDBConnection::SQLite(conn) => conn + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + &(params.4.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + LuminaDBConnection::POSTGRES(client) => client + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + &(params.4.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + } + } + pub fn execute6( + &mut self, + query: &str, + params: ( + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + ), + ) -> Result<(), ()> { + match self { + LuminaDBConnection::SQLite(conn) => conn + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + &(params.4.as_ref()), + &(params.5.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + LuminaDBConnection::POSTGRES(client) => client + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + &(params.4.as_ref()), + &(params.5.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + } + } + + pub fn execute7( + &mut self, + query: &str, + params: ( + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + ), + ) -> Result<(), ()> { + match self { + LuminaDBConnection::SQLite(conn) => conn + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + &(params.4.as_ref()), + &(params.5.as_ref()), + &(params.6.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + LuminaDBConnection::POSTGRES(client) => client + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + &(params.4.as_ref()), + &(params.5.as_ref()), + &(params.6.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + } + } + pub fn execute8( + &mut self, + query: &str, + params: ( + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + ), + ) -> Result<(), ()> { + match self { + LuminaDBConnection::SQLite(conn) => conn + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + &(params.4.as_ref()), + &(params.5.as_ref()), + &(params.6.as_ref()), + &(params.7.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + LuminaDBConnection::POSTGRES(client) => client + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + &(params.4.as_ref()), + &(params.5.as_ref()), + &(params.6.as_ref()), + &(params.7.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + } + } + pub fn execute9( + &mut self, + query: &str, + params: ( + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + ), + ) -> Result<(), ()> { + match self { + LuminaDBConnection::SQLite(conn) => conn + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + &(params.4.as_ref()), + &(params.5.as_ref()), + &(params.6.as_ref()), + &(params.7.as_ref()), + &(params.8.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + LuminaDBConnection::POSTGRES(client) => client + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + &(params.4.as_ref()), + &(params.5.as_ref()), + &(params.6.as_ref()), + &(params.7.as_ref()), + &(params.8.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + } + } + pub fn execute10( + &mut self, + query: &str, + params: ( + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + impl AsRef, + ), + ) -> Result<(), ()> { + match self { + LuminaDBConnection::SQLite(conn) => conn + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + &(params.4.as_ref()), + &(params.5.as_ref()), + &(params.6.as_ref()), + &(params.7.as_ref()), + &(params.8.as_ref()), + &(params.9.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + LuminaDBConnection::POSTGRES(client) => client + .execute( + query, + &[ + &(params.0.as_ref()), + &(params.1.as_ref()), + &(params.2.as_ref()), + &(params.3.as_ref()), + &(params.4.as_ref()), + &(params.5.as_ref()), + &(params.6.as_ref()), + &(params.7.as_ref()), + &(params.8.as_ref()), + &(params.9.as_ref()), + ], + ) + .map(|_r| ()) + .map_err(|_e| ()), + } } } @@ -78,7 +525,7 @@ pub enum UniversalFetchAnswer { impl UniversalFetchAnswer { /// Unwraps a post from a fetch answer. /// # Panics - /// Panics if the fetch answer is not a post. + /// Will panic if the fetch answer is not a post. /// # Returns /// * `PostInfo` - The post metadata. pub fn unwrap_post(self) -> PostInfo { @@ -162,73 +609,33 @@ pub fn unifetch( process::exit(1); } } -fn dbconf(conn: &Connection) { - fn emergencyabort() { - error!("Could not configure the database correctly!"); - process::exit(1); - } - - match conn.execute( - " -CREATE TABLE if not exists Users ( - id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, - username TEXT NOT NULL, - password TEXT NOT NULL, - email TEXT NOT NULL -) -", - (), - ) { - Ok(_) => {} - Err(_e) => emergencyabort(), - }; - match conn.execute( - " -CREATE TABLE if not exists PostsStore ( - lpid INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, - pid INTEGER, - instance TEXT, - author_id INTEGER NOT NULL, - timestamp INTEGER NOT NULL, - content_type INTEGER NOT NULL, - content TEXT NOT NULL, - tags TEXT NOT NULL -) -", - (), - ) { - Ok(_) => {} - Err(_e) => emergencyabort(), - } -} pub fn fetch_posts_in_range( config: &LuminaConfig, start: i64, end: i64, ) -> Result, Error> { - if config.database.method.as_str() != "sqlite" { - error!("Unknown or unsupported database type! Only SQLITE is supported as of now."); - process::exit(1); - } + match config.db_connect() { + LuminaDBConnection::SQLite(conn) => { + let mut stmt = conn + .prepare("SELECT * FROM PostsStore WHERE timestamp BETWEEN ?1 AND ?2") + .unwrap(); - let conn = create_con(config); - dbconf(&conn); + let post_rows = stmt + .query_map(params![start, end], |row| Ok(row_to_post_info(row))) + .unwrap(); - let mut stmt = conn - .prepare("SELECT * FROM PostsStore WHERE timestamp BETWEEN ?1 AND ?2") - .unwrap(); - - let post_rows = stmt - .query_map(params![start, end], |row| Ok(row_to_post_info(row))) - .unwrap(); + let mut posts = Vec::new(); + for post_row in post_rows { + posts.push(post_row.unwrap()); + } - let mut posts = Vec::new(); - for post_row in post_rows { - posts.push(post_row.unwrap()); + Ok(posts) + } + LuminaDBConnection::POSTGRES(_) => { + todo!("Postgres not implemented yet."); + } } - - Ok(posts) } fn row_to_post_info(row: &rusqlite::Row) -> PostInfo { @@ -246,3 +653,46 @@ fn row_to_post_info(row: &rusqlite::Row) -> PostInfo { pub(crate) mod fetch; pub(crate) mod users; + +pub fn get_instance_sync_list(config: &LuminaConfig) -> Result, Error> { + match config.db_connect() { + LuminaDBConnection::SQLite(conn) => { + let mut stmt = conn + .prepare("SELECT * FROM interinstance_relations") + .unwrap(); + + let sync_list_rows = stmt + .query_map((), |row| { + Ok(SynclistItem { + name: row.get(0).unwrap(), + level: row.get(1).unwrap(), + last_contact: row.get(2).unwrap(), + }) + }) + .unwrap(); + + let mut sync_list = Vec::new(); + for sync_list_row in sync_list_rows { + sync_list.push(sync_list_row.unwrap()); + } + + Ok(sync_list) + } + LuminaDBConnection::POSTGRES(mut client) => { + let rows = client + .query("SELECT * FROM interinstance_relations", &[]) + .unwrap(); + + let mut sync_list = Vec::new(); + for row in rows { + sync_list.push(SynclistItem { + name: row.get(0), + level: row.get(1), + last_contact: row.get(2), + }); + } + + Ok(sync_list) + } + } +} \ No newline at end of file diff --git a/backend-rs/src/database/fetch.rs b/backend-rs/src/database/fetch.rs index 4cb2f80..41db7ad 100644 --- a/backend-rs/src/database/fetch.rs +++ b/backend-rs/src/database/fetch.rs @@ -4,62 +4,60 @@ * Licensed under the BSD 3-Clause License. See the LICENSE file for more info. */ -use crate::database::BasicUserInfo; +use crate::database::{BasicUserInfo, LuminaDBConnection}; use crate::post::PostInfo; use crate::{database, LuminaConfig}; use std::io::{Error, ErrorKind}; -use std::process; /// Fetches user from database pub fn user( config: &LuminaConfig, discriminator: (impl AsRef, impl AsRef), ) -> Result, Error> { - if config.database.method.as_str() == "sqlite" { - let conn = database::create_con(config); - database::dbconf(&conn); - - let mut stmt = conn - .prepare( - format!( - r#"select * from Users where {0} = '{1}'"#, - discriminator.0.as_ref(), - discriminator.1.as_ref() + match config.db_connect() { + LuminaDBConnection::SQLite(conn) => { + let mut stmt = conn + .prepare( + format!( + r#"select * from Users where {0} = '{1}'"#, + discriminator.0.as_ref(), + discriminator.1.as_ref() + ) + .trim(), ) - .trim(), - ) - .unwrap(); - debug!("{:?}", stmt); - let mut res = stmt - .query_map((), |row| { - Ok({ - serde_json::to_string(&BasicUserInfo { - id: row.get(0)?, - username: row.get(1)?, - password: row.get(2)?, - email: row.get(3)?, + .unwrap(); + debug!("{:?}", stmt); + let mut res = stmt + .query_map((), |row| { + Ok({ + serde_json::to_string(&BasicUserInfo { + id: row.get(0)?, + username: row.get(1)?, + password: row.get(2)?, + email: row.get(3)?, + }) + .unwrap() }) - .unwrap() }) - }) - .unwrap(); - // println!("{:?}", res.nth(0)); - match res.next() { - None => Ok(None), - Some(r) => match r { - Ok(s) => { - let res: BasicUserInfo = serde_json::from_str(&s).unwrap(); - Ok(Some(res)) - } - Err(f) => { - eprintln!("{:?}", f); - Err(Error::new(ErrorKind::Other, "Unparseable data.")) - } - }, + .unwrap(); + // println!("{:?}", res.nth(0)); + match res.next() { + None => Ok(None), + Some(r) => match r { + Ok(s) => { + let res: BasicUserInfo = serde_json::from_str(&s).unwrap(); + Ok(Some(res)) + } + Err(f) => { + eprintln!("{:?}", f); + Err(Error::new(ErrorKind::Other, "Unparseable data.")) + } + }, + } + } + LuminaDBConnection::POSTGRES(_) => { + todo!("Postgres not implemented yet."); } - } else { - error!("Unknown or unsupported database type! Only SQLITE is supported as of now."); - process::exit(1); } } @@ -68,45 +66,46 @@ pub fn post( config: &LuminaConfig, discriminator: (impl AsRef, impl AsRef), ) -> Result, Error> { - if config.database.method.as_str() == "sqlite" { - let conn = database::create_con(config); - database::dbconf(&conn); + match config.db_connect() { + LuminaDBConnection::SQLite(conn) => { + - let mut stmt = conn - .prepare( - format!( - r#"select * from PostsStore where {0} = '{1}'"#, - discriminator.0.as_ref(), - discriminator.1.as_ref() + let mut stmt = conn + .prepare( + format!( + r#"select * from PostsStore where {0} = '{1}'"#, + discriminator.0.as_ref(), + discriminator.1.as_ref() + ) + .trim(), ) - .trim(), - ) - .unwrap(); - debug!("{:?}", stmt); - let mut res = stmt - .query_map((), |row| { - Ok({ - let s = database::row_to_post_info(row); - serde_json::to_string(&s).unwrap() + .unwrap(); + debug!("{:?}", stmt); + let mut res = stmt + .query_map((), |row| { + Ok({ + let s = database::row_to_post_info(row); + serde_json::to_string(&s).unwrap() + }) }) - }) - .unwrap(); - // println!("{:?}", res.nth(0)); - match res.next() { - None => Ok(None), - Some(r) => match r { - Ok(s) => { - let res: PostInfo = serde_json::from_str(&s).unwrap(); - Ok(Some(res)) - } - Err(f) => { - eprintln!("{:?}", f); - Err(Error::new(ErrorKind::Other, "Unparseable data.")) - } - }, + .unwrap(); + // println!("{:?}", res.nth(0)); + match res.next() { + None => Ok(None), + Some(r) => match r { + Ok(s) => { + let res: PostInfo = serde_json::from_str(&s)?; + Ok(Some(res)) + } + Err(f) => { + eprintln!("{:?}", f); + Err(Error::new(ErrorKind::Other, "Unparseable data.")) + } + }, + } + } + LuminaDBConnection::POSTGRES(_) => { + todo!("Postgres not implemented yet."); } - } else { - error!("Unknown or unsupported database type! Only SQLITE is supported as of now."); - process::exit(1); } } diff --git a/backend-rs/src/database/users.rs b/backend-rs/src/database/users.rs index 8e8a421..e170fa1 100644 --- a/backend-rs/src/database/users.rs +++ b/backend-rs/src/database/users.rs @@ -10,7 +10,7 @@ use magic_crypt::{new_magic_crypt, MagicCryptTrait}; use crate::{database, LuminaConfig}; -use super::{create_con, BasicUserInfo}; +use super::{BasicUserInfo}; /// The minimum length of a username. pub const MINIMUM_USERNAME_LENGTH: usize = 3; @@ -92,8 +92,8 @@ pub(crate) fn add( if password.len() < 8 { return Err(Error::new(ErrorKind::Other, "Password is too short.")); } - let mcrypt = new_magic_crypt!(config.clone().database.key, 256); - let conn = create_con(&config.clone()); + let mcrypt = new_magic_crypt!(config.clone().db_custom_salt, 256); + let conn = &config.clone(); let onusername = database::fetch::user(&config.clone(), ("username", username.clone()))?; let onemail = database::fetch::user(&config.clone(), ("email", email.clone()))?; let res: Option = match onusername { @@ -104,7 +104,7 @@ pub(crate) fn add( match res { Some(_) => Err(Error::new(ErrorKind::Other, "User already exists!")), None => { - match conn.execute( + match conn.db_connect().execute3( "INSERT INTO `users` (username, password, email) VALUES (?1,?2,?3)", (username.clone(), password_encrypted, email), ) { @@ -117,8 +117,8 @@ pub(crate) fn add( )), } } - Err(e) => { - error!("Unknown database write error: {}", e); + Err(_) => { + error!("Unknown database write error!"); Err(Error::new( ErrorKind::Other, "Unknown database write error.", @@ -170,7 +170,7 @@ pub(crate) mod auth { return AuthResponse::Fail(FailReason::InvalidUsername); } let config: crate::LuminaConfig = server_vars.clone().config.clone(); - let mcrypt = new_magic_crypt!(config.clone().database.key, 256); + let mcrypt = new_magic_crypt!(config.clone().db_custom_salt, 256); let errorresponse = |e| { error!("Auth: \n\t\tRan into an error:\n {}", e); AuthResponse::Fail(FailReason::Unspecified) diff --git a/backend-rs/src/post.rs b/backend-rs/src/post.rs index 8bfaed0..f0dbe9a 100644 --- a/backend-rs/src/post.rs +++ b/backend-rs/src/post.rs @@ -76,7 +76,7 @@ impl PostInfo { instance: self .instance .clone() - .unwrap_or(config.interinstance.iid.clone()), + .unwrap_or(config.lumina_synchronisation_iid.clone()), }; let content; diff --git a/backend-rs/src/serve.rs b/backend-rs/src/serve.rs index a1b3f51..c4f6d07 100644 --- a/backend-rs/src/serve.rs +++ b/backend-rs/src/serve.rs @@ -3,7 +3,6 @@ * * Licensed under the BSD 3-Clause License. See the LICENSE file for more info. */ -//noinspection ALL const SPECIALDATES: &str = r#" /*Pride month banner*/ body:has(.monthclass-6)::before { @@ -189,14 +188,18 @@ fn replaceable(string: &str, server_vars: &ServerVars) -> String { stylesheet.push_str("\n\n\n/* --- Main stylesheet --- */\n\n\n"); stylesheet.push_str(crate::assets::STR_GENERATED_MAIN_MIN_CSS); stylesheet.push_str("\n\n\n/* --- Custom instance-specific CSS content --- */\n\n\n"); - stylesheet.push_str(&server_vars.config.run.customcss.clone()); + stylesheet.push_str(&server_vars.config.clone().erun.customcss.clone()); stylesheet.push_str("\n\n\n/* --- CSS content for special events --- */\n\n\n"); stylesheet.push_str(specialdates.as_str()); stylesheet.push_str(""); let s = string .replace( "{{iid}}", - &server_vars.clone().config.interinstance.iid.clone(), + &server_vars + .clone() + .config + .lumina_synchronisation_iid + .clone(), ) .replace( "monthclass-month", diff --git a/backend-rs/src/server.rs b/backend-rs/src/server.rs index 6be9501..19ff48d 100644 --- a/backend-rs/src/server.rs +++ b/backend-rs/src/server.rs @@ -3,13 +3,10 @@ * * Licensed under the BSD 3-Clause License. See the LICENSE file for more info. */ -const CURRENT_CONFIG_VERSION: &str = "0.3-a"; -#[macro_use] -extern crate build_const; + #[macro_use] extern crate log; extern crate simplelog; -// use console::Term; use std::fmt::Debug; use std::fs::File; @@ -27,14 +24,12 @@ use actix_web::{ }; use colored::Colorize; use rand::prelude::*; -use serde::{Deserialize, Serialize}; use simplelog::*; use tokio::sync::{Mutex, MutexGuard}; +use crate::config::{LuminaConfig, LuminaLogConfig}; use crate::serve::notfound; -use assets::{ - fonts, vec_string_assets_anons_svg, STR_CLEAN_CONFIG_TOML, STR_CLEAN_CUSTOMSTYLES_CSS, -}; +use assets::{fonts, vec_string_assets_anons_svg, STR_CLEAN_CUSTOMSTYLES_CSS}; /// ## API's to the front-end. mod api_fe; @@ -52,8 +47,14 @@ mod tell; #[derive(Clone)] struct ServerVars { - config: LuminaConfig, - // console: Term, + config: crate::config::LuminaConfig, +} + +#[derive(Clone)] +pub struct SynclistItem { + pub name: String, // The name of the instance to sync with, equal to the domain name it is public on. + pub level: String, // The level of syncing to do. "full" is the only one being implemented right now. + pub last_contact: i64, // The last time the instance was contacted. } impl ServerVars { /// This function grabs the server variables from the provided mutex. @@ -92,127 +93,20 @@ impl ServerVars { vars.clone() } } -#[derive(Default, Debug, Clone, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -struct JSClientData { - config: JSClientConfig, -} -#[derive(Default, Debug, Clone, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -struct JSClientConfig { - interinstance: JSClientConfigInterInstance, -} -#[derive(Default, Debug, Clone, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -struct JSClientConfigInterInstance { - iid: String, -} -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -struct PrePreConfig { - version: Option, -} -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct PreConfig { - pub version: String, - pub server: Server, - pub interinstance: InterInstance, - pub database: Database, - pub logging: Option, -} -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct LuminaConfig { - pub version: String, - pub server: Server, - pub interinstance: InterInstance, - pub database: Database, - pub logging: Option, - pub run: ERun, -} - -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] +#[derive(Default, Debug, Clone, PartialEq)] pub struct ERun { pub cd: PathBuf, pub customcss: String, pub session_valid: i64, } -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Logging { - #[serde(alias = "file-loglevel")] - #[serde(alias = "file-log-level")] - pub file_loglevel: Option, - #[serde(alias = "term-loglevel")] - #[serde(alias = "term-log-level")] - #[serde(alias = "console-loglevel")] - #[serde(alias = "console-log-level")] - pub term_loglevel: Option, - - #[serde(alias = "file")] - #[serde(alias = "filename")] - pub logfile: Option, -} pub struct LogSets { pub file_loglevel: LevelFilter, pub term_loglevel: LevelFilter, pub logfile: PathBuf, } -fn default_as_true() -> bool { - true -} - -#[derive(Default, Clone, PartialEq, Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct Server { - pub port: u16, - pub adress: String, - #[serde(alias = "cookiekey")] - pub cookie_key: String, - #[serde(default = "default_as_true")] - pub secure: bool, -} - -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct InterInstance { - pub iid: String, - pub synclist: Vec, - pub ignorelist: Vec, - pub syncing: Syncing, -} - -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct SynclistItem { - pub name: String, // The name of the instance to sync with, equal to the domain name it is public on. - pub level: String, // The level of syncing to do. "full" is the only one being implemented right now. -} - -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Syncing { - pub syncintervall: u64, -} - -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Database { - pub method: String, - pub sqlite: Option, - #[serde(alias = "cryptkey")] - pub key: String, -} - -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SQLite { - pub file: String, -} - #[tokio::main] async fn main() { let v = (|| { @@ -224,6 +118,7 @@ async fn main() { None => PathBuf::from(Path::new(".")), } })(); + let vs = v .canonicalize() .unwrap_or(v.to_path_buf()) @@ -249,33 +144,8 @@ async fn main() { ); process::exit(1); } - let config: LuminaConfig = { - println!("Loading configuration from {}", vs); - let va = v.clone().join("./config.toml"); - let confp = Path::new(&va); - if (!confp.is_file()) || (!confp.exists()) { - let mut output = match File::create(confp) { - Ok(p) => p, - Err(a) => { - eprintln!( - "Error: Could not create blank config file. The system returned: {}", - a - ); - process::exit(1); - } - }; - - match write!(output, "{}", STR_CLEAN_CONFIG_TOML) { - Ok(p) => p, - Err(a) => { - eprintln!( - "Error: Could not create blank config file. The system returned: {}", - a - ); - process::exit(1); - } - }; - } + + let erun: ERun = { let sty_f = v.clone().join("./custom-styles.css"); if (!sty_f.is_file()) || (!sty_f.exists()) { let mut output = match File::create(sty_f.clone()) { @@ -299,66 +169,23 @@ async fn main() { process::exit(1); } }; - } - let o = v.clone(); - let config_version_up_to_date: bool = match fs::read_to_string(confp) { - Ok(g) => match toml::from_str(&g) { - Ok(p) => { - let p: PrePreConfig = p; - p.version.unwrap_or(String::from("Unset")) == *CURRENT_CONFIG_VERSION - } - _ => false, - }, - _ => false, - }; - if !config_version_up_to_date { - eprintln!("ERROR! The config file Lumina tried to load, doesn't match the configuration version Lumina supports. (Expected: {})", CURRENT_CONFIG_VERSION); - process::exit(1); }; - - match fs::read_to_string(confp) { - Ok(g) => match toml::from_str(&g) { - Ok(p) => { - let mut rng = thread_rng(); - let p: PreConfig = p; - LuminaConfig { - version: p.version, - server: p.server, - interinstance: p.interinstance, - database: p.database, - logging: p.logging, - run: ERun { - cd: o, - customcss: fs::read_to_string(sty_f) - .unwrap_or(String::from(r"/* Failed loading custom css */")), - session_valid: rng.gen_range(1..=900000), - }, - } - } - Err(e) => { - eprintln!( - "ERROR: Could not interpret server configuration at `{}`!\n\n\t{}", - confp - .canonicalize() - .unwrap_or(confp.to_path_buf()) - .to_string_lossy() - .replace("\\\\?\\", ""), - e.message() - ); - process::exit(1); - } - }, - Err(_) => { + // read the styf file to a string + let styf = match fs::read_to_string(sty_f.clone()) { + Ok(p) => p, + Err(a) => { eprintln!( - "Error: Could not read server configuration at `{}`!", - confp - .canonicalize() - .unwrap_or(confp.to_path_buf()) - .to_string_lossy() - .replace("\\\\?\\", "") + "Error: Could not read custom style file. The system returned: {}", + a ); process::exit(1); } + }; + + ERun { + cd: v.clone(), + customcss: styf, + session_valid: rand::thread_rng().gen_range(0..1000000), } }; let logsets: LogSets = { @@ -380,11 +207,12 @@ async fn main() { } } } - match config.clone().logging { + let temp: Option = None; + match temp { None => LogSets { file_loglevel: LevelFilter::Info, term_loglevel: LevelFilter::Warn, - logfile: config.run.cd.join("./instance.log"), + logfile: erun.cd.join("./instance.log"), }, Some(d) => LogSets { file_loglevel: match d.file_loglevel { @@ -396,8 +224,8 @@ async fn main() { None => LevelFilter::Warn, }, logfile: match d.logfile { - Some(s) => config.run.cd.join(s.as_str()), - None => config.run.cd.join("./instance.log"), + Some(s) => erun.cd.join(s.as_str()), + None => erun.cd.join("./instance.log"), }, }, } @@ -415,10 +243,13 @@ async fn main() { File::create(&logsets.logfile).unwrap(), ), ]) - .unwrap(); + .unwrap(); + + let config: LuminaConfig = LuminaConfig::new(erun.clone()); + + let server_p: ServerVars = ServerVars { config: config.clone(), - // console: Term::stdout(), }; let server_q: Data> = Data::new(Mutex::new(server_p.clone())); server_p.tell(format!( @@ -430,12 +261,13 @@ async fn main() { .to_string_lossy() .replace("\\\\?\\", "") )); - let keydouble = config.server.cookie_key.repeat(2); + config.db_connect().initial_dbconf(); + let keydouble = config.db_custom_salt.repeat(10); let keybytes = keydouble.as_bytes(); if keybytes.len() < 32 { error!( "Error: Cookie key must be at least 32 (doubled) bytes long. \"{}\" yields only {} bytes.", - config.server.cookie_key.blue(), + config.db_custom_salt.blue(), format!("{}",keybytes.len()).blue() ); process::exit(1); @@ -484,26 +316,26 @@ async fn main() { .service(serve_fonts) .app_data(web::Data::clone(&server_q)) }) - .bind((config.server.adress.clone(), config.server.port)) + .bind((config.lumina_server_addr.clone(), config.lumina_server_port)) { Ok(o) => { server_p.tell(format!( "Running on {0}:{1}, which should be bound to {2}://{3}", - config.server.adress, - config.server.port, - if config.server.secure { + config.lumina_server_addr, + config.lumina_server_port, + if config.lumina_server_https { "https" } else { "http" }, - config.interinstance.iid + config.lumina_synchronisation_iid )); o } Err(s) => { error!( "Could not bind to {}:{}, error message: {}", - config.server.adress, config.server.port, s + config.lumina_server_addr, config.lumina_server_port, s ); process::exit(1); } @@ -584,6 +416,7 @@ async fn close() { // } } +mod config; mod serve; #[doc = r"Font file server"] diff --git a/backend-rs/src/tell.rs b/backend-rs/src/tell.rs index d789b50..7348632 100644 --- a/backend-rs/src/tell.rs +++ b/backend-rs/src/tell.rs @@ -12,7 +12,7 @@ use std::time::SystemTime; use colored::Colorize; use time::{format_description, OffsetDateTime}; -use crate::{Logging, ServerVars}; +use crate::{config::LuminaLogConfig, ServerVars}; const DATE_FORMAT_STR: &str = "[hour]:[minute]:[second]"; @@ -42,7 +42,7 @@ impl ServerVars { format!("{} {} {}", times, "[LOG] ".magenta(), msg) } } -impl Logging { +impl LuminaLogConfig { fn tell(self, rmsg: impl AsRef) { let msg = rmsg.as_ref(); let a = self; diff --git a/build.sh b/build.sh index 711a82d..9b9b551 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash + LOCA=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) GEN_ASSETS="$LOCA/backend/priv/generated" SECONDS=0 @@ -8,6 +9,7 @@ TESTS=false PACK=false BUNFLAGS="" CARGOFLAGS="" +BCARGOFLAGS="" TEST_FE_TS=false TEST_FE_GLEAM=false # --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -25,9 +27,11 @@ if [[ "$*" == *"--test"* ]]; then fi if [[ "$*" == *"--pack"* ]]; then PACK=true + BCARGOFLAGS="--release" fi if [[ "$*" == *"--run-packed"* ]]; then PACK=true + BCARGOFLAGS="--release" fi if [ "$QUIET" = true ]; then echo "[quiet mode]" >&2 @@ -182,7 +186,7 @@ bun x cleancss -O1 specialComments:all --inline none "$GEN_ASSETS/css/main.css" if [[ "$*" == *"--backend=rust"* ]]; then noti "Building Rust backend..." cd "$LOCA/backend-rs/" || exit 1 - if cargo build --release; then + if cargo build $BCARGOFLAGS; then success "\t--> Rust backend build success." else errnoti "\t--> Rust backend compilation ran into an error." @@ -225,7 +229,11 @@ res_noti 1 "Build completed, took $((build_duration / 60)) minutes and $((build_ if [[ "$*" == *"--run"* ]]; then noti "'--run' detected. Running Lumina directly!" if [[ "$*" == *"--backend=rust"* ]]; then + if [ "$PACK" = true ]; then "$LOCA/backend-rs/target/release/lumina-server" || exit 1 + else + "$LOCA/backend-rs/target/debug/lumina-server" || exit 1 + fi else cd "$LOCA/backend/" || exit 1 gleam run -- start