mirror of https://github.com/JSH32/Backpack.git
Multi DB support
This commit is contained in:
parent
af3500df1c
commit
b596b4bd1b
|
@ -4,4 +4,9 @@ target
|
|||
/uploads
|
||||
test
|
||||
*_archive
|
||||
*.code-workspace
|
||||
*.code-workspace
|
||||
|
||||
# SQLite files
|
||||
*.db*
|
||||
*.sqlite*
|
||||
*.sqlite3*
|
|
@ -309,6 +309,15 @@ dependencies = [
|
|||
"alloc-no-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.57"
|
||||
|
@ -338,6 +347,113 @@ version = "0.10.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
|
||||
|
||||
[[package]]
|
||||
name = "async-attributes"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28"
|
||||
dependencies = [
|
||||
"concurrent-queue",
|
||||
"event-listener",
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-executor"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965"
|
||||
dependencies = [
|
||||
"async-task",
|
||||
"concurrent-queue",
|
||||
"fastrand",
|
||||
"futures-lite",
|
||||
"once_cell",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-global-executor"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5262ed948da60dd8956c6c5aca4d4163593dddb7b32d73267c93dab7b2e98940"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-executor",
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"blocking",
|
||||
"futures-lite",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-io"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07"
|
||||
dependencies = [
|
||||
"concurrent-queue",
|
||||
"futures-lite",
|
||||
"libc",
|
||||
"log",
|
||||
"once_cell",
|
||||
"parking",
|
||||
"polling",
|
||||
"slab",
|
||||
"socket2",
|
||||
"waker-fn",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-std"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d"
|
||||
dependencies = [
|
||||
"async-attributes",
|
||||
"async-channel",
|
||||
"async-global-executor",
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"crossbeam-utils",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-lite",
|
||||
"gloo-timers",
|
||||
"kv-log-macro",
|
||||
"log",
|
||||
"memchr",
|
||||
"once_cell",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
"wasm-bindgen-futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stream"
|
||||
version = "0.3.3"
|
||||
|
@ -359,6 +475,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-task"
|
||||
version = "4.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.53"
|
||||
|
@ -379,6 +501,12 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
|
@ -425,6 +553,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"lettre",
|
||||
"log",
|
||||
"migration",
|
||||
"nanoid",
|
||||
"num_cpus",
|
||||
"paste",
|
||||
|
@ -508,6 +637,20 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blocking"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-task",
|
||||
"atomic-waker",
|
||||
"fastrand",
|
||||
"futures-lite",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brotli"
|
||||
version = "3.3.4"
|
||||
|
@ -562,6 +705,12 @@ dependencies = [
|
|||
"bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cache-padded"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
|
@ -604,16 +753,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.1.18"
|
||||
version = "3.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b"
|
||||
checksum = "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
|
@ -621,9 +770,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.1.18"
|
||||
version = "3.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c"
|
||||
checksum = "9ba52acd3b0a5c33aeada5cdaa3267cdc7c594a98731d4268cdc1532f4264cb4"
|
||||
dependencies = [
|
||||
"heck 0.4.0",
|
||||
"proc-macro-error",
|
||||
|
@ -634,9 +783,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.0"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213"
|
||||
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
@ -658,6 +807,15 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "1.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c"
|
||||
dependencies = [
|
||||
"cache-padded",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.0"
|
||||
|
@ -814,6 +972,16 @@ dependencies = [
|
|||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deflate"
|
||||
version = "1.0.0"
|
||||
|
@ -1110,6 +1278,21 @@ version = "0.3.21"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
|
||||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"memchr",
|
||||
"parking",
|
||||
"pin-project-lite",
|
||||
"waker-fn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.21"
|
||||
|
@ -1206,6 +1389,18 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gloo-timers"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.13"
|
||||
|
@ -1545,6 +1740,15 @@ dependencies = [
|
|||
"simple_asn1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kv-log-macro"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "language-tags"
|
||||
version = "0.3.2"
|
||||
|
@ -1594,6 +1798,17 @@ version = "0.2.126"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "local-channel"
|
||||
version = "0.1.3"
|
||||
|
@ -1629,6 +1844,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"value-bag",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1637,6 +1853,15 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||
dependencies = [
|
||||
"regex-automata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matches"
|
||||
version = "0.1.9"
|
||||
|
@ -1678,6 +1903,14 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "migration"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"sea-orm-migration",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.16"
|
||||
|
@ -1846,9 +2079,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
|||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.10.0"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
||||
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
|
@ -1931,6 +2164,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.2"
|
||||
|
@ -2067,6 +2306,19 @@ dependencies = [
|
|||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"log",
|
||||
"wepoll-ffi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "postgres-protocol"
|
||||
version = "0.6.4"
|
||||
|
@ -2246,6 +2498,15 @@ dependencies = [
|
|||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||
dependencies = [
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.25"
|
||||
|
@ -2470,6 +2731,23 @@ dependencies = [
|
|||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sea-orm-cli"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f527a5c69fc9b9cd8d243fa45f5bcf14e5e2a3e94b003267be1b075221c5b04b"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"chrono",
|
||||
"clap",
|
||||
"dotenv",
|
||||
"regex",
|
||||
"sea-schema",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sea-orm-macros"
|
||||
version = "0.9.1"
|
||||
|
@ -2483,6 +2761,22 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sea-orm-migration"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "697d983cc6fd0ec497934cbfd16b3872b7e95be369e8851bdc65770c3b5ec57d"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"clap",
|
||||
"dotenv",
|
||||
"sea-orm",
|
||||
"sea-orm-cli",
|
||||
"sea-schema",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sea-query"
|
||||
version = "0.26.2"
|
||||
|
@ -2523,6 +2817,29 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sea-schema"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94d070aba647637b533bd669a8e430bdc8f7d5249c9b53402da34347563bbfca"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"sea-query",
|
||||
"sea-schema-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sea-schema-derive"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56821b7076f5096b8f726e2791ad255a99c82498e08ec477a65a96c461ff1927"
|
||||
dependencies = [
|
||||
"heck 0.3.3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sea-strum"
|
||||
version = "0.23.0"
|
||||
|
@ -2664,6 +2981,15 @@ dependencies = [
|
|||
"digest 0.10.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.1.0"
|
||||
|
@ -2767,8 +3093,10 @@ dependencies = [
|
|||
"dirs",
|
||||
"either",
|
||||
"event-listener",
|
||||
"flume",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-intrusive",
|
||||
"futures-util",
|
||||
"hashlink",
|
||||
|
@ -2778,6 +3106,7 @@ dependencies = [
|
|||
"indexmap",
|
||||
"itoa",
|
||||
"libc",
|
||||
"libsqlite3-sys",
|
||||
"log",
|
||||
"md-5 0.10.1",
|
||||
"memchr",
|
||||
|
@ -2832,7 +3161,6 @@ version = "0.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "874e93a365a598dc3dadb197565952cb143ae4aa716f7bcc933a8d836f6bf89f"
|
||||
dependencies = [
|
||||
"actix-rt",
|
||||
"once_cell",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
|
@ -2936,6 +3264,15 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "threadpool"
|
||||
version = "1.8.1"
|
||||
|
@ -3113,6 +3450,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"valuable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"lazy_static",
|
||||
"matchers",
|
||||
"regex",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3244,6 +3611,22 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "value-bag"
|
||||
version = "1.0.0-alpha.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55"
|
||||
dependencies = [
|
||||
"ctor",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
|
@ -3256,6 +3639,12 @@ version = "0.9.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "waker-fn"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.0"
|
||||
|
@ -3303,6 +3692,18 @@ dependencies = [
|
|||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.80"
|
||||
|
@ -3367,6 +3768,15 @@ version = "0.1.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c97e489d8f836838d497091de568cf16b117486d529ec5579233521065bd5e4"
|
||||
|
||||
[[package]]
|
||||
name = "wepoll-ffi"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "whoami"
|
||||
version = "1.2.1"
|
||||
|
|
11
Cargo.toml
11
Cargo.toml
|
@ -1,3 +1,6 @@
|
|||
[workspace]
|
||||
members = [".", "migration"]
|
||||
|
||||
[package]
|
||||
name = "backpack"
|
||||
version = "0.1.0"
|
||||
|
@ -7,16 +10,18 @@ edition = "2018"
|
|||
[dependencies.sea-orm]
|
||||
version = "0.9"
|
||||
features = [
|
||||
"sqlx-sqlite",
|
||||
"sqlx-postgres",
|
||||
"runtime-actix-rustls",
|
||||
"runtime-tokio-rustls",
|
||||
"macros"
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
migration = { path = "migration" }
|
||||
tokio = { version = "1.10.0", features = ["full"] }
|
||||
sqlx = { version = "0.6.0", features = [ "runtime-actix-rustls", "postgres", "chrono" ] }
|
||||
clap = { version = "3.1.0", features = ["derive"] }
|
||||
clap = { version = "3.2.16", features = ["derive"] }
|
||||
serde = "1.0.126"
|
||||
sqlx = { version = "0.6.0", features = [ "runtime-tokio-rustls", "postgres", "chrono", "sqlite" ] }
|
||||
serde_json = { version = "1.0.64", features = [ "preserve_order" ] }
|
||||
jsonwebtoken = "8"
|
||||
dotenv = "0.15.0"
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
[package]
|
||||
name = "migration"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
name = "migration"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
async-std = { version = "^1", features = ["attributes", "tokio1"] }
|
||||
|
||||
[dependencies.sea-orm-migration]
|
||||
version = "^0.9.0"
|
||||
features = [
|
||||
# Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI.
|
||||
# View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime.
|
||||
# e.g.
|
||||
"runtime-tokio-rustls",
|
||||
"sqlx-postgres",
|
||||
"sqlx-sqlite"
|
||||
]
|
|
@ -0,0 +1,41 @@
|
|||
# Running Migrator CLI
|
||||
|
||||
- Generate a new migration file
|
||||
```sh
|
||||
cargo run -- migrate generate MIGRATION_NAME
|
||||
```
|
||||
- Apply all pending migrations
|
||||
```sh
|
||||
cargo run
|
||||
```
|
||||
```sh
|
||||
cargo run -- up
|
||||
```
|
||||
- Apply first 10 pending migrations
|
||||
```sh
|
||||
cargo run -- up -n 10
|
||||
```
|
||||
- Rollback last applied migrations
|
||||
```sh
|
||||
cargo run -- down
|
||||
```
|
||||
- Rollback last 10 applied migrations
|
||||
```sh
|
||||
cargo run -- down -n 10
|
||||
```
|
||||
- Drop all tables from the database, then reapply all migrations
|
||||
```sh
|
||||
cargo run -- fresh
|
||||
```
|
||||
- Rollback all applied migrations, then reapply all migrations
|
||||
```sh
|
||||
cargo run -- refresh
|
||||
```
|
||||
- Rollback all applied migrations
|
||||
```sh
|
||||
cargo run -- reset
|
||||
```
|
||||
- Check the status of all migrations
|
||||
```sh
|
||||
cargo run -- status
|
||||
```
|
|
@ -0,0 +1,13 @@
|
|||
use sea_orm_migration::sea_query::ColumnDef;
|
||||
|
||||
/// Adds extra implementation utilities for migrations.
|
||||
pub trait ColumnExtension {
|
||||
fn sonyflake(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl ColumnExtension for ColumnDef {
|
||||
/// Alias for `string_len(20)`, a sonyflake is 20 chars long.
|
||||
fn sonyflake(&mut self) -> &mut Self {
|
||||
self.string_len(20)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
pub use sea_orm_migration::prelude::*;
|
||||
|
||||
mod extensions;
|
||||
mod m20220101_000001_initial_structure;
|
||||
mod m20220810_114915_settings_table;
|
||||
|
||||
pub struct Migrator;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigratorTrait for Migrator {
|
||||
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
|
||||
vec![
|
||||
Box::new(m20220101_000001_initial_structure::Migration),
|
||||
Box::new(m20220810_114915_settings_table::Migration),
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,313 @@
|
|||
use crate::extensions::*;
|
||||
use sea_orm_migration::{prelude::*, sea_orm::DbBackend, sea_query::extension::postgres::Type};
|
||||
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
// Create the actual enum types if using postgres.
|
||||
if manager.get_database_backend() == DbBackend::Postgres {
|
||||
manager
|
||||
.create_type(
|
||||
Type::create()
|
||||
.as_enum(Role::Type)
|
||||
.values(vec![Role::User, Role::Admin])
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// User table
|
||||
manager
|
||||
.create_table(
|
||||
Table::create()
|
||||
.table(Users::Table)
|
||||
.col(
|
||||
ColumnDef::new(Users::Id)
|
||||
.sonyflake()
|
||||
.primary_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Users::Email)
|
||||
.string_len(320)
|
||||
.unique_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Users::Username)
|
||||
.string_len(32)
|
||||
.unique_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(Users::Password).string_len(128).not_null())
|
||||
.col(
|
||||
ColumnDef::new(Users::Verified)
|
||||
.boolean()
|
||||
.default(false)
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Users::Role)
|
||||
.enumeration("role", ["user", "admin"])
|
||||
.default("user")
|
||||
.not_null(),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Applications table
|
||||
manager
|
||||
.create_table(
|
||||
Table::create()
|
||||
.table(Applications::Table)
|
||||
.col(
|
||||
ColumnDef::new(Applications::Id)
|
||||
.sonyflake()
|
||||
.primary_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(Applications::UserId).string().not_null())
|
||||
.col(ColumnDef::new(Applications::Name).string_len(16).not_null())
|
||||
.col(
|
||||
ColumnDef::new(Applications::LastAccessed)
|
||||
.timestamp_with_time_zone()
|
||||
.not_null()
|
||||
.extra("DEFAULT CURRENT_TIMESTAMP".into()),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.from(Applications::Table, Applications::UserId)
|
||||
.to(Users::Table, Users::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// A user may not have two duplicate application names
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.unique()
|
||||
.name("applications_name_uindex")
|
||||
.table(Applications::Table)
|
||||
.col(Applications::UserId)
|
||||
.col(Applications::Name)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// User verification
|
||||
// Only one verification may exist per user
|
||||
manager
|
||||
.create_table(
|
||||
Table::create()
|
||||
.table(Verifications::Table)
|
||||
.col(
|
||||
ColumnDef::new(Verifications::Id)
|
||||
.sonyflake()
|
||||
.primary_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Verifications::Code)
|
||||
.string_len(72)
|
||||
.not_null()
|
||||
.unique_key(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Verifications::UserId)
|
||||
.sonyflake()
|
||||
.not_null()
|
||||
.unique_key(),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.from(Verifications::Table, Verifications::UserId)
|
||||
.to(Users::Table, Users::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// File table
|
||||
manager
|
||||
.create_table(
|
||||
Table::create()
|
||||
.table(Files::Table)
|
||||
.col(
|
||||
ColumnDef::new(Files::Id)
|
||||
.sonyflake()
|
||||
.primary_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Files::Name)
|
||||
.string_len(32)
|
||||
.not_null()
|
||||
.unique_key(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Files::OriginalName)
|
||||
.string_len(256)
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(Files::Uploader).sonyflake().not_null())
|
||||
.col(ColumnDef::new(Files::Hash).string_len(64).not_null())
|
||||
.col(
|
||||
ColumnDef::new(Files::Uploaded)
|
||||
.timestamp_with_time_zone()
|
||||
.not_null()
|
||||
.extra("DEFAULT CURRENT_TIMESTAMP".into()),
|
||||
)
|
||||
.col(ColumnDef::new(Files::Size).big_integer().not_null())
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.from(Files::Table, Files::Uploader)
|
||||
.to(Users::Table, Users::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Two identical files by hash can not exist if owned by the same user
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.unique()
|
||||
.name("files_user_hash_uindex")
|
||||
.table(Files::Table)
|
||||
.col(Files::Uploader)
|
||||
.col(Files::Hash)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// User registration keys
|
||||
manager
|
||||
.create_table(
|
||||
Table::create()
|
||||
.table(RegistrationKeys::Table)
|
||||
.col(
|
||||
ColumnDef::new(RegistrationKeys::Id)
|
||||
.sonyflake()
|
||||
.primary_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(RegistrationKeys::Issuer)
|
||||
.sonyflake()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(RegistrationKeys::Code)
|
||||
.uuid()
|
||||
.not_null()
|
||||
.unique_key(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(RegistrationKeys::UsesLeft)
|
||||
.integer()
|
||||
.not_null()
|
||||
.default(1),
|
||||
)
|
||||
.col(ColumnDef::new(RegistrationKeys::ExpiryDate).timestamp_with_time_zone())
|
||||
.to_owned(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_table(Table::drop().table(Applications::Table).to_owned())
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.drop_table(Table::drop().table(Verifications::Table).to_owned())
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.drop_table(Table::drop().table(Files::Table).to_owned())
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.drop_table(Table::drop().table(RegistrationKeys::Table).to_owned())
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.drop_table(Table::drop().table(Users::Table).to_owned())
|
||||
.await?;
|
||||
|
||||
if manager.get_database_backend() == DbBackend::Postgres {
|
||||
manager
|
||||
.drop_type(Type::drop().name(Role::Type).to_owned())
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Iden)]
|
||||
enum Users {
|
||||
Table,
|
||||
Id,
|
||||
Email,
|
||||
Username,
|
||||
Password,
|
||||
Verified,
|
||||
Role,
|
||||
}
|
||||
|
||||
#[derive(Iden)]
|
||||
enum Applications {
|
||||
Table,
|
||||
Id,
|
||||
UserId,
|
||||
Name,
|
||||
LastAccessed,
|
||||
}
|
||||
|
||||
#[derive(Iden)]
|
||||
enum Verifications {
|
||||
Table,
|
||||
Id,
|
||||
Code,
|
||||
UserId,
|
||||
}
|
||||
|
||||
#[derive(Iden)]
|
||||
enum Files {
|
||||
Table,
|
||||
Id,
|
||||
Name,
|
||||
OriginalName,
|
||||
Uploader,
|
||||
Hash,
|
||||
Uploaded,
|
||||
Size,
|
||||
}
|
||||
|
||||
#[derive(Iden)]
|
||||
enum RegistrationKeys {
|
||||
Table,
|
||||
Id,
|
||||
Issuer,
|
||||
Code,
|
||||
UsesLeft,
|
||||
ExpiryDate,
|
||||
}
|
||||
|
||||
#[derive(Iden)]
|
||||
enum Role {
|
||||
#[iden = "role"]
|
||||
Type,
|
||||
User,
|
||||
Admin,
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
use sea_orm_migration::{prelude::*, sea_orm::DbBackend, sea_query::extension::postgres::Type};
|
||||
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
// Create the actual enum types if using postgres.
|
||||
if manager.get_database_backend() == DbBackend::Postgres {
|
||||
manager
|
||||
.create_type(
|
||||
Type::create()
|
||||
.as_enum(ThemeColor::Type)
|
||||
.values(vec![
|
||||
ThemeColor::Gray,
|
||||
ThemeColor::Red,
|
||||
ThemeColor::Orange,
|
||||
ThemeColor::Yellow,
|
||||
ThemeColor::Green,
|
||||
ThemeColor::Teal,
|
||||
ThemeColor::Blue,
|
||||
ThemeColor::Cyan,
|
||||
ThemeColor::Purple,
|
||||
ThemeColor::Pink,
|
||||
])
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
manager
|
||||
.create_table(
|
||||
Table::create()
|
||||
.table(Settings::Table)
|
||||
.col(
|
||||
ColumnDef::new(Settings::OneRowEnforce)
|
||||
.primary_key()
|
||||
.not_null()
|
||||
.boolean()
|
||||
.default(true),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Settings::AppName)
|
||||
.string_len(64)
|
||||
.not_null()
|
||||
.default("Backpack"),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Settings::AppDescription)
|
||||
.text()
|
||||
.not_null()
|
||||
.default("A file host for all your needs"),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Settings::Color)
|
||||
.enumeration(
|
||||
"theme_color",
|
||||
[
|
||||
"gray", "red", "orange", "yellow", "green", "teal", "blue",
|
||||
"cyan", "purple", "pink",
|
||||
],
|
||||
)
|
||||
.default("purple")
|
||||
.not_null(),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Insert default settings at first, configuration done through web UI
|
||||
manager
|
||||
.exec_stmt(
|
||||
Query::insert()
|
||||
.into_table(Settings::Table)
|
||||
.or_default_values()
|
||||
.to_owned(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_table(Table::drop().table(Settings::Table).to_owned())
|
||||
.await?;
|
||||
|
||||
if manager.get_database_backend() == DbBackend::Postgres {
|
||||
manager
|
||||
.drop_type(Type::drop().name(ThemeColor::Type).to_owned())
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Iden)]
|
||||
enum Settings {
|
||||
Table,
|
||||
OneRowEnforce,
|
||||
AppName,
|
||||
AppDescription,
|
||||
Color,
|
||||
}
|
||||
|
||||
#[derive(Iden)]
|
||||
enum ThemeColor {
|
||||
#[iden = "theme_color"]
|
||||
Type,
|
||||
Gray,
|
||||
Red,
|
||||
Orange,
|
||||
Yellow,
|
||||
Green,
|
||||
Teal,
|
||||
Blue,
|
||||
Cyan,
|
||||
Purple,
|
||||
Pink,
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
use sea_orm_migration::prelude::*;
|
||||
|
||||
#[async_std::main]
|
||||
async fn main() {
|
||||
cli::run_cli(migration::Migrator).await;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
DROP TABLE applications;
|
||||
DROP TABLE verifications;
|
||||
DROP TABLE files;
|
||||
DROP TABLE registration_keys;
|
||||
DROP TABLE users;
|
||||
DROP TYPE role;
|
||||
DROP DOMAIN sonyflake;
|
|
@ -1,71 +0,0 @@
|
|||
-- Role enum
|
||||
CREATE TYPE role AS ENUM ('user', 'admin');
|
||||
|
||||
-- Sonyflake type
|
||||
CREATE DOMAIN sonyflake AS VARCHAR(20) NOT NULL;
|
||||
|
||||
-- Users table
|
||||
CREATE TABLE users
|
||||
(
|
||||
id sonyflake PRIMARY KEY NOT NULL UNIQUE,
|
||||
email VARCHAR(320) NOT NULL UNIQUE,
|
||||
username VARCHAR(32) NOT NULL UNIQUE,
|
||||
password VARCHAR(128) NOT NULL,
|
||||
verified BOOLEAN DEFAULT false NOT NULL,
|
||||
role role DEFAULT 'user'::role NOT NULL
|
||||
);
|
||||
|
||||
-- API token table for applications
|
||||
CREATE TABLE applications
|
||||
(
|
||||
id sonyflake PRIMARY KEY NOT NULL UNIQUE,
|
||||
user_id sonyflake NOT NULL,
|
||||
name VARCHAR(16) NOT NULL,
|
||||
last_accessed timestamptz DEFAULT now() NOT NULL,
|
||||
|
||||
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- A user may not have two duplicate application names
|
||||
CREATE UNIQUE INDEX applications_name_uindex
|
||||
ON applications (user_id, name);
|
||||
|
||||
-- Only one verification may exist per user
|
||||
CREATE TABLE verifications
|
||||
(
|
||||
id SERIAL PRIMARY KEY NOT NULL UNIQUE,
|
||||
code VARCHAR(72) NOT NULL UNIQUE,
|
||||
user_id sonyflake NOT NULL UNIQUE,
|
||||
|
||||
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE files
|
||||
(
|
||||
id sonyflake PRIMARY KEY NOT NULL UNIQUE,
|
||||
name VARCHAR(32) NOT NULL UNIQUE,
|
||||
original_name VARCHAR(256) NOT NULL,
|
||||
uploader sonyflake NOT NULL,
|
||||
hash VARCHAR(64) NOT NULL,
|
||||
uploaded timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
size BIGINT NOT NULL,
|
||||
|
||||
-- Application needs to delete the files from the S3 container. This is precautionary for database
|
||||
FOREIGN KEY (uploader) REFERENCES users (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Two identical files can not exist if owned by the same user
|
||||
CREATE UNIQUE INDEX files_user_hash_uindex
|
||||
ON files (uploader, hash);
|
||||
|
||||
-- User registration keys
|
||||
CREATE TABLE registration_keys
|
||||
(
|
||||
id sonyflake NOT NULL PRIMARY KEY,
|
||||
iss_user sonyflake NOT NULL,
|
||||
code uuid NOT NULL UNIQUE,
|
||||
uses_left INTEGER NOT NULL DEFAULT 1,
|
||||
expiry_date timestamptz,
|
||||
|
||||
FOREIGN KEY (iss_user) REFERENCES users (id) ON DELETE CASCADE
|
||||
);
|
|
@ -1,2 +0,0 @@
|
|||
DROP TABLE settings;
|
||||
DROP TYPE theme_color;
|
|
@ -1,26 +0,0 @@
|
|||
CREATE TYPE theme_color AS ENUM (
|
||||
'gray',
|
||||
'red',
|
||||
'orange',
|
||||
'yellow',
|
||||
'green',
|
||||
'teal',
|
||||
'blue',
|
||||
'cyan',
|
||||
'purple',
|
||||
'pink'
|
||||
);
|
||||
|
||||
CREATE TABLE settings
|
||||
(
|
||||
-- Only true is allowed and this is set to unique. Prevents multiple settings rows
|
||||
one_row_enforce BOOLEAN PRIMARY KEY DEFAULT TRUE NOT NULL UNIQUE,
|
||||
app_name VARCHAR(64) DEFAULT 'Backpack' NOT NULL,
|
||||
app_description TEXT DEFAULT 'A file host for all your needs' NOT NULL,
|
||||
color theme_color DEFAULT 'purple'::theme_color NOT NULL,
|
||||
|
||||
CONSTRAINT one_row_unique CHECK (one_row_enforce)
|
||||
);
|
||||
|
||||
-- Insert default settings at first, configuration done through web UI
|
||||
INSERT INTO settings (one_row_enforce) VALUES (true);
|
|
@ -1,2 +1,10 @@
|
|||
## SeaORM Database models
|
||||
These are automatically generated with some manual edits for sonyflake. Be careful when regenerating and make sure to generate to a new directory and cross reference the changes.
|
||||
These are automatically generated with some manual edits for runtime defaults. Be careful when regenerating and make sure to generate to a new directory and cross reference the changes. Guidelines on how to do this are below and some steps can be skipped as long as you pay attention to what you are doing (eg. model has not changed at all).
|
||||
|
||||
## How to generate
|
||||
1. Set `DATABASE_URL` to a proper database URI.
|
||||
* Use postgres for this process. We support multiple databases but enum types can only be generated when using Postgres.
|
||||
2. Either run the application once to automatically run migrations or run `sea-orm-cli migrate up`.
|
||||
3. Run `sea-orm-cli generate entity -o entities`.
|
||||
4. Cross reference changes in the `entities` folder and the `database/entity` folder and make sure you keep `ActiveModelBehavior`s on each file as-is since they specify the ID generator and applied defaults on each model.
|
||||
5. Delete `entities` and make sure everything works properly (tests coming soon).
|
|
@ -1,4 +1,4 @@
|
|||
//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.1
|
||||
|
||||
use sea_orm::{entity::prelude::*, Set};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.1
|
||||
|
||||
use sea_orm::{entity::prelude::*, Set};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.1
|
||||
|
||||
use crate::database::sonyflake::Sonyflake;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.1
|
||||
|
||||
pub use super::applications::Entity as Applications;
|
||||
pub use super::files::Entity as Files;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.1
|
||||
|
||||
use sea_orm::{entity::prelude::*, Set};
|
||||
use uuid::Uuid;
|
||||
|
@ -10,7 +10,7 @@ use super::DB_SONYFLAKE;
|
|||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
pub iss_user: String,
|
||||
pub issuer: String,
|
||||
#[sea_orm(unique)]
|
||||
pub code: Uuid,
|
||||
pub uses_left: i32,
|
||||
|
@ -21,7 +21,7 @@ pub struct Model {
|
|||
pub enum Relation {
|
||||
#[sea_orm(
|
||||
belongs_to = "super::users::Entity",
|
||||
from = "Column::IssUser",
|
||||
from = "Column::Issuer",
|
||||
to = "super::users::Column::Id",
|
||||
on_update = "NoAction",
|
||||
on_delete = "Cascade"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.1
|
||||
|
||||
use sea_orm::entity::prelude::*;
|
||||
use serde::Serialize;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.1
|
||||
|
||||
use super::sea_orm_active_enums::ThemeColor;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.1
|
||||
|
||||
use super::DB_SONYFLAKE;
|
||||
|
||||
|
@ -21,14 +21,12 @@ pub struct Model {
|
|||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
pub enum Relation {
|
||||
#[sea_orm(has_many = "super::files::Entity")]
|
||||
Files,
|
||||
#[sea_orm(has_many = "super::applications::Entity")]
|
||||
Applications,
|
||||
#[sea_orm(has_one = "super::verifications::Entity")]
|
||||
Verifications,
|
||||
#[sea_orm(has_many = "super::files::Entity")]
|
||||
Files,
|
||||
#[sea_orm(has_many = "super::registration_keys::Entity")]
|
||||
RegistrationKeys,
|
||||
}
|
||||
|
||||
impl Related<super::applications::Entity> for Entity {
|
||||
|
@ -49,12 +47,6 @@ impl Related<super::files::Entity> for Entity {
|
|||
}
|
||||
}
|
||||
|
||||
impl Related<super::registration_keys::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::RegistrationKeys.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
|
||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.1
|
||||
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
|
@ -6,7 +6,7 @@ use sea_orm::entity::prelude::*;
|
|||
#[sea_orm(table_name = "verifications")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: i32,
|
||||
pub id: String,
|
||||
#[sea_orm(unique)]
|
||||
pub code: String,
|
||||
#[sea_orm(unique)]
|
||||
|
|
64
src/main.rs
64
src/main.rs
|
@ -7,8 +7,7 @@ use config::StorageConfig;
|
|||
use figlet_rs::FIGfont;
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
use models::MessageResponse;
|
||||
use sea_orm::{EntityTrait, SqlxPostgresConnector};
|
||||
use sqlx::{migrate::Migrator, postgres::PgPoolOptions, Row};
|
||||
use sea_orm::{ConnectionTrait, DatabaseConnection, DbBackend, EntityTrait, Statement};
|
||||
use state::State;
|
||||
use tokio::{
|
||||
fs,
|
||||
|
@ -19,7 +18,8 @@ use tokio::{
|
|||
use internal::file::IMAGE_EXTS;
|
||||
use utoipa::OpenApi;
|
||||
|
||||
use std::{convert::TryInto, ffi::OsStr, path::Path, time::Duration};
|
||||
use migration::{Migrator, MigratorTrait};
|
||||
use std::{convert::TryInto, ffi::OsStr, path::Path};
|
||||
|
||||
use actix_web::{
|
||||
http::StatusCode,
|
||||
|
@ -75,37 +75,20 @@ async fn main() -> std::io::Result<()> {
|
|||
let config = config::Config::new();
|
||||
let args = Args::parse();
|
||||
|
||||
// Create a SQLx pool for running migrations
|
||||
let sqlx_pool = PgPoolOptions::new()
|
||||
.max_connections(100)
|
||||
.min_connections(1)
|
||||
.acquire_timeout(Duration::from_secs(8))
|
||||
.idle_timeout(Duration::from_secs(8))
|
||||
.max_lifetime(Duration::from_secs(8))
|
||||
.connect(&config.database_url)
|
||||
let database = sea_orm::Database::connect(&config.database_url)
|
||||
.await
|
||||
.expect("Could not initialize database connection");
|
||||
.unwrap();
|
||||
|
||||
let pg_version = sqlx::query("SELECT version()")
|
||||
.fetch_one(&sqlx_pool)
|
||||
.await
|
||||
.unwrap()
|
||||
.try_get("version")
|
||||
.unwrap_or("unknown".to_string());
|
||||
|
||||
log::info!("Connected to the database ({})", pg_version);
|
||||
log::info!(
|
||||
"Connected to the database ({})",
|
||||
get_db_version(&database).await.unwrap()
|
||||
);
|
||||
|
||||
// Apply all pending migrations
|
||||
if config.run_migrations {
|
||||
let migrator = Migrator::new(Path::new("migrations")).await.unwrap();
|
||||
migrator
|
||||
.run(&sqlx_pool)
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!(e.to_string()))
|
||||
.unwrap();
|
||||
Migrator::up(&database, None).await.unwrap();
|
||||
}
|
||||
|
||||
let database = SqlxPostgresConnector::from_sqlx_postgres_pool(sqlx_pool);
|
||||
|
||||
let storage: Box<dyn StorageProvider> = match &config.storage_provider {
|
||||
StorageConfig::Local(v) => {
|
||||
if !v.path.exists() {
|
||||
|
@ -249,6 +232,31 @@ async fn main() -> std::io::Result<()> {
|
|||
.await
|
||||
}
|
||||
|
||||
/// Get database version.
|
||||
async fn get_db_version(database: &DatabaseConnection) -> Result<String, anyhow::Error> {
|
||||
let version: String = database
|
||||
.query_one(Statement::from_string(
|
||||
database.get_database_backend(),
|
||||
format!(
|
||||
"select {}() as version;",
|
||||
match database.get_database_backend() {
|
||||
DbBackend::Sqlite => "sqlite_version",
|
||||
_ => "version",
|
||||
}
|
||||
)
|
||||
.to_string(),
|
||||
))
|
||||
.await?
|
||||
.unwrap()
|
||||
.try_get("", "version")?;
|
||||
|
||||
// SQLite version function is just a version number.
|
||||
Ok(match database.get_database_backend() {
|
||||
DbBackend::Sqlite => format!("SQLite {}", version),
|
||||
_ => version,
|
||||
})
|
||||
}
|
||||
|
||||
/// Regenerate all thumbnails.
|
||||
/// This is a multithreaded blocking operation used in the CLI.
|
||||
async fn generate_thumbnails(state: &Data<State>) -> anyhow::Result<()> {
|
||||
|
|
|
@ -9,7 +9,7 @@ pub struct RegistrationKeyData {
|
|||
pub id: String,
|
||||
|
||||
/// Admin which issued this registration key.
|
||||
pub iss_user: String,
|
||||
pub issuer: String,
|
||||
|
||||
/// Registration key.
|
||||
#[component(value_type = String)]
|
||||
|
@ -30,7 +30,7 @@ impl From<registration_keys::Model> for RegistrationKeyData {
|
|||
id: model.id.to_string(),
|
||||
code: model.code,
|
||||
expiry_date: model.expiry_date,
|
||||
iss_user: model.iss_user,
|
||||
issuer: model.issuer,
|
||||
uses_left: model.uses_left,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ async fn create(
|
|||
) -> Response<impl Responder> {
|
||||
Ok(HttpResponse::Ok().json(RegistrationKeyData::from(
|
||||
registration_keys::ActiveModel {
|
||||
issueru: Set(user.id.to_owned()),
|
||||
issuer: Set(user.id.to_owned()),
|
||||
uses_left: Set(query.max_uses.unwrap_or(1)),
|
||||
..Default::default()
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ use actix_multipart_extract::Multipart;
|
|||
use actix_web::{delete, get, http::StatusCode, post, web, HttpResponse, Responder, Scope};
|
||||
use nanoid::nanoid;
|
||||
use sea_orm::{
|
||||
sea_query::SimpleExpr, ActiveModelTrait, ColumnTrait, ConnectionTrait, DbBackend, EntityTrait,
|
||||
ModelTrait, PaginatorTrait, QueryFilter, QueryOrder, Set, Statement,
|
||||
sea_query::SimpleExpr, ActiveModelTrait, ColumnTrait, ConnectionTrait, EntityTrait, ModelTrait,
|
||||
PaginatorTrait, QueryFilter, QueryOrder, QuerySelect, QueryTrait, Set,
|
||||
};
|
||||
use serde_json::json;
|
||||
use sha2::{Digest, Sha256};
|
||||
|
@ -167,19 +167,20 @@ async fn stats(
|
|||
state: web::Data<State>,
|
||||
user: Auth<auth_role::User, DenyUnverified, AllowApplication>,
|
||||
) -> Response<impl Responder> {
|
||||
// Im not using an ORM for this query
|
||||
let usage = state
|
||||
.database
|
||||
.query_one(Statement::from_sql_and_values(
|
||||
DbBackend::Postgres,
|
||||
r#"SELECT COALESCE(CAST(SUM(size) AS BIGINT), 0) FROM files WHERE uploader = $1"#,
|
||||
vec![user.id.clone().into()],
|
||||
))
|
||||
.await?;
|
||||
let expr = files::Entity::find()
|
||||
.select_only()
|
||||
.filter(files::Column::Uploader.eq(user.id.clone()))
|
||||
.column_as(files::Column::Size.sum(), "sum")
|
||||
.build(state.database.get_database_backend())
|
||||
.to_owned();
|
||||
|
||||
println!("{}", expr);
|
||||
|
||||
let usage = state.database.query_one(expr).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(FileStats {
|
||||
usage: match usage {
|
||||
Some(v) => v.try_get("", "coalesce")?,
|
||||
Some(v) => v.try_get("", "sum")?,
|
||||
None => 0,
|
||||
},
|
||||
}))
|
||||
|
|
Loading…
Reference in New Issue