This commit is contained in:
Miguel da Mota 2024-01-01 03:18:33 +01:00
parent 8a19a733d6
commit 52ef924f12
28 changed files with 577 additions and 170 deletions

252
Cargo.lock generated
View file

@ -30,7 +30,7 @@ dependencies = [
"actix-service", "actix-service",
"actix-utils", "actix-utils",
"ahash", "ahash",
"base64 0.21.5", "base64",
"bitflags 2.4.1", "bitflags 2.4.1",
"brotli", "brotli",
"bytes", "bytes",
@ -65,7 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
dependencies = [ dependencies = [
"quote", "quote",
"syn 2.0.43", "syn 2.0.44",
] ]
[[package]] [[package]]
@ -179,7 +179,7 @@ dependencies = [
"actix-router", "actix-router",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.43", "syn 2.0.44",
] ]
[[package]] [[package]]
@ -199,9 +199,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]] [[package]]
name = "ahash" name = "ahash"
version = "0.8.6" version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"getrandom", "getrandom",
@ -251,13 +251,13 @@ dependencies = [
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.75" version = "0.1.76"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98" checksum = "531b97fb4cd3dfdce92c35dedbfdc1f0b9d8091c8ca943d6dae340ef5012d514"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.43", "syn 2.0.44",
] ]
[[package]] [[package]]
@ -281,12 +281,6 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
] ]
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.21.5" version = "0.21.5"
@ -299,7 +293,7 @@ version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d1c9c15093eb224f0baa400f38fcd713fc1391a6f1c389d886beef146d60a3" checksum = "28d1c9c15093eb224f0baa400f38fcd713fc1391a6f1c389d886beef146d60a3"
dependencies = [ dependencies = [
"base64 0.21.5", "base64",
"blowfish", "blowfish",
"getrandom", "getrandom",
"subtle", "subtle",
@ -413,7 +407,7 @@ dependencies = [
"num-traits", "num-traits",
"serde", "serde",
"wasm-bindgen", "wasm-bindgen",
"windows-targets", "windows-targets 0.48.5",
] ]
[[package]] [[package]]
@ -479,9 +473,9 @@ dependencies = [
[[package]] [[package]]
name = "deranged" name = "deranged"
version = "0.3.10" version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [ dependencies = [
"powerfmt", "powerfmt",
] ]
@ -523,7 +517,7 @@ dependencies = [
"diesel_table_macro_syntax", "diesel_table_macro_syntax",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.43", "syn 2.0.44",
] ]
[[package]] [[package]]
@ -543,7 +537,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5"
dependencies = [ dependencies = [
"syn 2.0.43", "syn 2.0.44",
] ]
[[package]] [[package]]
@ -650,8 +644,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"js-sys",
"libc", "libc",
"wasi", "wasi",
"wasm-bindgen",
] ]
[[package]] [[package]]
@ -719,9 +715,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.58" version = "0.1.59"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539"
dependencies = [ dependencies = [
"android_system_properties", "android_system_properties",
"core-foundation-sys", "core-foundation-sys",
@ -794,18 +790,18 @@ dependencies = [
] ]
[[package]] [[package]]
name = "jwt" name = "jsonwebtoken"
version = "0.16.0" version = "9.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6204285f77fe7d9784db3fdc449ecce1a0114927a51d5a41c4c7a292011c015f" checksum = "5c7ea04a7c5c055c175f189b6dc6ba036fd62306b58c66c9f6389036c503a3f4"
dependencies = [ dependencies = [
"base64 0.13.1", "base64",
"crypto-common", "js-sys",
"digest", "pem",
"hmac", "ring",
"serde", "serde",
"serde_json", "serde_json",
"sha2", "simple_asn1",
] ]
[[package]] [[package]]
@ -913,6 +909,27 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "num-bigint"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.17" version = "0.2.17"
@ -957,7 +974,7 @@ dependencies = [
"libc", "libc",
"redox_syscall", "redox_syscall",
"smallvec", "smallvec",
"windows-targets", "windows-targets 0.48.5",
] ]
[[package]] [[package]]
@ -966,6 +983,16 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "pem"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310"
dependencies = [
"base64",
"serde",
]
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -1013,18 +1040,18 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.71" version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" checksum = "2dd5e8a1f1029c43224ad5898e50140c2aebb1705f19e67c918ebf5b9e797fe1"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.33" version = "1.0.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -1108,6 +1135,20 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "ring"
version = "0.17.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74"
dependencies = [
"cc",
"getrandom",
"libc",
"spin",
"untrusted",
"windows-sys",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.23" version = "0.1.23"
@ -1167,14 +1208,14 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.43", "syn 2.0.44",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.108" version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -1233,6 +1274,18 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "simple_asn1"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085"
dependencies = [
"num-bigint",
"num-traits",
"thiserror",
"time",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.9" version = "0.4.9"
@ -1258,6 +1311,12 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.5.0" version = "2.5.0"
@ -1277,15 +1336,35 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.43" version = "2.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" checksum = "92d27c2c202598d05175a6dd3af46824b7f747f8d8e9b14c623f19fa5069735d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "thiserror"
version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.44",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.31" version = "0.3.31"
@ -1442,6 +1521,12 @@ dependencies = [
"tinyvec", "tinyvec",
] ]
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]] [[package]]
name = "url" name = "url"
version = "2.5.0" version = "2.5.0"
@ -1478,7 +1563,7 @@ dependencies = [
"diesel_migrations", "diesel_migrations",
"dotenvy", "dotenvy",
"hmac", "hmac",
"jwt", "jsonwebtoken",
"lazy_static", "lazy_static",
"serde", "serde",
"serde_json", "serde_json",
@ -1512,7 +1597,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.43", "syn 2.0.44",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1534,7 +1619,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.43", "syn 2.0.44",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1547,11 +1632,11 @@ checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
[[package]] [[package]]
name = "windows-core" name = "windows-core"
version = "0.51.1" version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [ dependencies = [
"windows-targets", "windows-targets 0.52.0",
] ]
[[package]] [[package]]
@ -1560,7 +1645,7 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [ dependencies = [
"windows-targets", "windows-targets 0.48.5",
] ]
[[package]] [[package]]
@ -1569,13 +1654,28 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm", "windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc", "windows_aarch64_msvc 0.48.5",
"windows_i686_gnu", "windows_i686_gnu 0.48.5",
"windows_i686_msvc", "windows_i686_msvc 0.48.5",
"windows_x86_64_gnu", "windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm", "windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc", "windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm 0.52.0",
"windows_aarch64_msvc 0.52.0",
"windows_i686_gnu 0.52.0",
"windows_i686_msvc 0.52.0",
"windows_x86_64_gnu 0.52.0",
"windows_x86_64_gnullvm 0.52.0",
"windows_x86_64_msvc 0.52.0",
] ]
[[package]] [[package]]
@ -1584,42 +1684,84 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.5.31" version = "0.5.31"
@ -1646,7 +1788,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.43", "syn 2.0.44",
] ]
[[package]] [[package]]

View file

@ -17,6 +17,6 @@ dotenvy = "*"
hmac = "0.12" hmac = "0.12"
sha2 = "0.10" sha2 = "0.10"
lazy_static = "1" lazy_static = "1"
jwt = "0.16" jsonwebtoken = "9"
serde = "1" serde = "1"
serde_json = "1" serde_json = "1"

View file

@ -1,2 +1,2 @@
-- This file should undo anything in `up.sql` -- This file should undo anything in `up.sql`
DROP TABLE users; drop table users;

View file

@ -1,13 +1,13 @@
-- Your SQL goes here -- Your SQL goes here
CREATE TABLE IF NOT EXISTS users create table if not exists users
( (
id VARCHAR(24) DEFAULT nanoid(24), id varchar(24) default nanoid(24),
name VARCHAR(255) NOT NULL, name varchar(255) not null,
email VARCHAR(255) NOT NULL, email varchar(255) not null,
password TEXT NOT NULL, password text not null,
updated_at TIMESTAMP, updated_at timestamp,
created_at TIMESTAMP DEFAULT now() NOT NULL, created_at timestamp default now() not null,
PRIMARY KEY (id) primary key (id)
); );

View file

@ -1,2 +1,2 @@
-- This file should undo anything in `up.sql` -- This file should undo anything in `up.sql`
DROP TABLE playlists; drop table playlists;

View file

@ -1,16 +1,16 @@
CREATE TABLE IF NOT EXISTS playlists create table if not exists playlists
( (
id VARCHAR(24) DEFAULT nanoid(24), id varchar(24) default nanoid(24),
name VARCHAR(255) NOT NULL, name varchar(255) not null,
public bool default false,
creator_id VARCHAR(24) NOT NULL, creator_id varchar(24) not null,
created_at TIMESTAMP DEFAULT now() NOT NULL, created_at timestamp default now() not null,
updated_at TIMESTAMP, updated_at timestamp,
PRIMARY KEY (id), primary key (id),
FOREIGN KEY (creator_id) foreign key (creator_id)
REFERENCES users (id) references users (id)
on delete cascade
); );
CREATE INDEX ON playlists (creator_id);

View file

@ -1,2 +1,2 @@
-- This file should undo anything in `up.sql` -- This file should undo anything in `up.sql`
DROP TABLE tracks; drop table tracks;

View file

@ -1,16 +1,16 @@
-- Your SQL goes here -- Your SQL goes here
CREATE TABLE IF NOT EXISTS tracks create table if not exists tracks
( (
id VARCHAR(24) DEFAULT nanoid(24), id varchar(24) default nanoid(24),
title VARCHAR(255) NOT NULL, title varchar(255) not null,
duration_ms INT NOT NULL DEFAULT 0, duration_ms int not null default 0,
created_at TIMESTAMP DEFAULT now() NOT NULL, created_at timestamp default now() not null,
updated_at TIMESTAMP, updated_at timestamp,
-- music services -- music services
spotify_id VARCHAR(21) UNIQUE, spotify_id varchar(21) unique,
tidal_id VARCHAR(10) UNIQUE, tidal_id varchar(10) unique,
PRIMARY KEY (id) primary key (id)
); );

View file

@ -1,2 +1,2 @@
-- This file should undo anything in `up.sql` -- This file should undo anything in `up.sql`
DROP TABLE playlists_tracks; drop table playlists_tracks;

View file

@ -1,5 +1,6 @@
CREATE TABLE IF NOT EXISTS playlists_tracks ( create table if not exists playlists_tracks
playlist_id VARCHAR(24) REFERENCES playlists(id), (
track_id VARCHAR(24) REFERENCES tracks(id), playlist_id varchar(24) references playlists (id) on delete cascade,
PRIMARY KEY (playlist_id, track_id) track_id varchar(24) references tracks (id) on delete cascade,
primary key (playlist_id, track_id)
); );

View file

@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
drop table artists;

View file

@ -0,0 +1,15 @@
-- Your SQL goes here
create table if not exists artists
(
id varchar(24) default nanoid(24),
name varchar(255) NOT NULL,
created_at TIMESTAMP DEFAULT now() NOT NULL,
updated_at TIMESTAMP,
-- music services
spotify_id VARCHAR(21) UNIQUE,
tidal_id VARCHAR(10) UNIQUE,
primary key (id)
);

View file

@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
drop table artists_tracks;

View file

@ -0,0 +1,8 @@
-- Your SQL goes here
create table if not exists artists_tracks
(
artist_id varchar(24) references artists (id) on delete cascade,
track_id varchar(24) references tracks (id) on delete cascade,
primary key (artist_id, track_id)
);

View file

@ -1,13 +1,18 @@
use crate::utils::get_jwt_secret; use crate::routes::auth::JWTClaims;
use jwt::VerifyWithKey; use jsonwebtoken::errors::Error;
use std::collections::BTreeMap; use jsonwebtoken::{decode, DecodingKey, EncodingKey, TokenData, Validation};
pub fn get_token(token: &str) -> Result<BTreeMap<String, String>, &str> { const JWT_SECRET: &str = "secret";
let secret = get_jwt_secret().unwrap();
let claims = token.verify_with_key(&secret);
match claims { pub fn get_token(token: &str) -> Result<TokenData<JWTClaims>, Error> {
Ok(claims) => Ok(claims), let token = decode::<JWTClaims>(&token, &get_decoding_key(), &Validation::default())?;
Err(_e) => return Err("Error parsing token"), Ok(token)
} }
pub fn get_encoding_key() -> EncodingKey {
EncodingKey::from_secret(JWT_SECRET.as_ref())
}
pub fn get_decoding_key() -> DecodingKey {
DecodingKey::from_secret(JWT_SECRET.as_ref())
} }

View file

@ -1,9 +1,10 @@
extern crate core;
mod helpers; mod helpers;
mod middlewares; mod middlewares;
mod models; mod models;
mod routes; mod routes;
mod schema; mod schema;
mod utils;
use crate::helpers::db; use crate::helpers::db;
use actix_web::{web, App, HttpServer}; use actix_web::{web, App, HttpServer};
@ -20,7 +21,7 @@ async fn main() -> std::io::Result<()> {
.service(web::scope("/playlists").service(routes::playlists::get_playlist)) .service(web::scope("/playlists").service(routes::playlists::get_playlist))
.service(routes::auth::login) .service(routes::auth::login)
.service(routes::me::routes()) .service(routes::me::routes())
.service(web::scope("/users").service(routes::users::get_user)) .service(routes::users::routes())
}) })
.bind(("127.0.0.1", 9000))? .bind(("127.0.0.1", 9000))?
.run() .run()

View file

@ -9,18 +9,24 @@ pub fn get_user(req: HttpRequest) -> Result<Users, ErrorResponse> {
match authorization { match authorization {
Some(header) => { Some(header) => {
let claims = get_token(header.to_str().unwrap()); let token_data = get_token(header.to_str().unwrap());
match claims { match token_data {
Ok(claims) => { Ok(token_data) => {
let user = Users::find(claims["user_id"].as_str())?; let user = Users::find(token_data.claims.user_id.as_str())?;
Ok(user) Ok(user)
} }
Err(e) => { Err(e) => {
return Err(ErrorResponse { return Err(match e.kind() {
message: e.to_string(), jsonwebtoken::errors::ErrorKind::ExpiredSignature => ErrorResponse {
status: StatusCode::INTERNAL_SERVER_ERROR, message: "Not Authorized".to_string(),
status: StatusCode::UNAUTHORIZED,
},
_ => ErrorResponse {
message: e.to_string(),
status: StatusCode::INTERNAL_SERVER_ERROR,
},
}) })
} }
} }

79
src/models/artists.rs Normal file
View file

@ -0,0 +1,79 @@
use crate::helpers::db;
use crate::schema::{artists, artists_tracks};
use chrono::NaiveDateTime;
use diesel::result::Error;
use diesel::{
AsChangeset, ExpressionMethods, Insertable, QueryDsl, Queryable, RunQueryDsl, Selectable,
};
use serde::{Deserialize, Serialize};
#[derive(AsChangeset, Insertable, Queryable, Selectable, Deserialize, Serialize)]
#[diesel(table_name = crate::schema::artists)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct Artist {
pub id: String,
pub name: String,
created_at: NaiveDateTime,
updated_at: Option<NaiveDateTime>,
pub spotify_id: Option<String>,
pub tidal_id: Option<String>,
}
#[derive(Debug, Deserialize, Queryable, Serialize)]
pub struct Artists {
pub id: String,
pub title: String,
created_at: NaiveDateTime,
updated_at: Option<NaiveDateTime>,
pub spotify_id: Option<String>,
pub tidal_id: Option<String>,
}
impl Artists {
pub fn find(id: String) -> Result<Self, Error> {
let conn = &mut db::connection()?;
let playlist = artists::table.filter(artists::id.eq(id)).first(conn)?;
Ok(playlist)
}
pub fn create(artist: Artist) -> Result<Self, Error> {
let conn = &mut db::connection()?;
let playlist = diesel::insert_into(artists::table)
.values(Artist::from(artist))
.get_result(conn)?;
Ok(playlist)
}
pub fn find_by_track(track_id: &str) -> Result<Vec<Artists>, Error> {
let conn = &mut db::connection()?;
let tracks: Vec<(String, String)> = artists_tracks::table
.filter(artists_tracks::track_id.eq(track_id))
.get_results::<(String, String)>(conn)?;
let artists = tracks
.into_iter()
.map(|(artist_id, _)| Artists::find(artist_id).unwrap())
.collect::<Vec<Artists>>();
Ok(artists)
}
}
impl Artist {
fn from(artist: Artist) -> Artist {
Artist {
id: artist.id,
name: artist.name,
created_at: artist.created_at,
updated_at: artist.updated_at,
spotify_id: artist.spotify_id,
tidal_id: artist.tidal_id,
}
}
}

View file

@ -1,3 +1,4 @@
pub mod playlist; pub mod artists;
pub mod playlists;
pub mod tracks; pub mod tracks;
pub mod user; pub mod user;

View file

@ -1,11 +1,11 @@
use crate::helpers::db; use crate::helpers::db;
use crate::models::tracks::Tracks; use crate::models::tracks::{Track, Tracks, TracksWithArtists};
use crate::models::user::Users; use crate::models::user::Users;
use crate::schema::playlists; use crate::schema::playlists;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use diesel::result::Error; use diesel::result::Error;
use diesel::{ use diesel::{
AsChangeset, EqAll, ExpressionMethods, Insertable, QueryDsl, Queryable, RunQueryDsl, Selectable, AsChangeset, ExpressionMethods, Insertable, QueryDsl, Queryable, RunQueryDsl, Selectable,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -22,6 +22,7 @@ pub struct PlaylistCreator {
pub struct Playlist { pub struct Playlist {
pub id: String, pub id: String,
pub name: String, pub name: String,
pub public: bool,
pub creator_id: String, pub creator_id: String,
pub created_at: NaiveDateTime, pub created_at: NaiveDateTime,
@ -32,6 +33,7 @@ pub struct Playlist {
pub struct Playlists { pub struct Playlists {
pub id: String, pub id: String,
pub name: String, pub name: String,
pub public: bool,
pub creator_id: String, pub creator_id: String,
pub created_at: NaiveDateTime, pub created_at: NaiveDateTime,
@ -45,24 +47,36 @@ impl Playlists {
Ok(playlist) Ok(playlist)
} }
pub fn create(playlist: Playlist) -> Result<Self, Error> { pub fn create(playlist: NewPlaylist) -> Result<Self, Error> {
let conn = &mut db::connection()?; let conn = &mut db::connection()?;
let playlist = diesel::insert_into(playlists::table) let playlist = diesel::insert_into(playlists::table)
.values(Playlist::from(playlist)) .values(playlist)
.get_result(conn)?; .get_result(conn)?;
Ok(playlist) Ok(playlist)
} }
pub fn find_for_user(user_id: &str) -> Result<Vec<Playlists>, Error> { pub fn find_for_user(user_id: &str, filter_public: bool) -> Result<Vec<Playlists>, Error> {
let conn = &mut db::connection()?; let conn = &mut db::connection()?;
let playlists = playlists::table
let mut playlists = playlists::table
.filter(playlists::creator_id.eq(user_id)) .filter(playlists::creator_id.eq(user_id))
.get_results(conn)?; .into_boxed();
if filter_public {
playlists = playlists.filter(playlists::public.eq(true));
}
let playlists = playlists.get_results(conn)?;
Ok(playlists) Ok(playlists)
} }
pub fn get_tracks(&self) -> Result<Vec<Tracks>, Error> { pub fn get_tracks(&self) -> Result<Vec<TracksWithArtists>, Error> {
let tracks = Tracks::find_by_playlist(&self.id)?; let tracks = Tracks::find_by_playlist(&self.id)?;
let tracks: Vec<TracksWithArtists> = tracks
.into_iter()
.map(Track::with_artists)
.collect::<Result<Vec<TracksWithArtists>, _>>()?;
Ok(tracks) Ok(tracks)
} }
@ -72,11 +86,28 @@ impl Playlists {
} }
} }
#[derive(Debug, Insertable, Deserialize)]
#[diesel(table_name = playlists)]
pub struct NewPlaylist {
pub name: String,
pub public: bool,
pub creator_id: Option<String>,
}
impl Playlist { impl Playlist {
pub fn create(name: &str, public: bool, creator_id: &str) -> NewPlaylist {
NewPlaylist {
name: name.to_string(),
public,
creator_id: Some(creator_id.to_string()),
}
}
fn from(playlist: Playlist) -> Playlist { fn from(playlist: Playlist) -> Playlist {
Playlist { Playlist {
id: playlist.id, id: playlist.id,
name: playlist.name, name: playlist.name,
public: playlist.public,
creator_id: playlist.creator_id, creator_id: playlist.creator_id,
created_at: playlist.created_at, created_at: playlist.created_at,

View file

@ -1,4 +1,5 @@
use crate::helpers::db; use crate::helpers::db;
use crate::models::artists::Artists;
use crate::schema::tracks; use crate::schema::tracks;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use diesel::result::Error; use diesel::result::Error;
@ -69,11 +70,10 @@ impl Tracks {
Ok(tracks) Ok(tracks)
} }
// pub fn get_artist(&self) -> Result<Artist, Error> { pub fn get_artists(&self) -> Result<Vec<Artists>, Error> {
// let conn = &mut db::connection(); let artists = Artists::find_by_track(&self.id)?;
// let artist = ; Ok(artists)
// Ok(artist) }
// }
} }
impl Track { impl Track {
@ -90,4 +90,31 @@ impl Track {
tidal_id: track.tidal_id, tidal_id: track.tidal_id,
} }
} }
pub fn with_artists(track: Tracks) -> Result<TracksWithArtists, Error> {
let artists = track.get_artists()?;
Ok(TracksWithArtists {
id: track.id,
title: track.title,
duration_ms: track.duration_ms,
artists,
spotify_id: track.spotify_id,
tidal_id: track.tidal_id,
})
}
}
#[derive(Deserialize, Serialize)]
pub struct TracksWithArtists {
pub id: String,
pub title: String,
pub duration_ms: i32,
pub artists: Vec<Artists>,
pub spotify_id: Option<String>,
pub tidal_id: Option<String>,
} }

View file

@ -1,5 +1,6 @@
use crate::helpers::db; use crate::helpers::db;
use crate::schema::users; use crate::schema::users;
use bcrypt::BcryptError;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use diesel::result::Error; use diesel::result::Error;
use diesel::{ use diesel::{
@ -54,8 +55,8 @@ impl Users {
Ok(user) Ok(user)
} }
pub fn verify_password(password: &str, user: &Users) -> bool { pub fn verify_password(password: &str, hash: &str) -> Result<bool, BcryptError> {
bcrypt::verify(password, &user.password).unwrap() bcrypt::verify(password, hash)
} }
} }

View file

@ -1,40 +1,53 @@
use crate::helpers::jwt::get_encoding_key;
use crate::middlewares::error::ErrorResponse; use crate::middlewares::error::ErrorResponse;
use crate::models::user::Users; use crate::models::user::Users;
use crate::utils::get_jwt_secret;
use actix_web::http::StatusCode; use actix_web::http::StatusCode;
use actix_web::{post, web, HttpResponse}; use actix_web::{post, web, HttpResponse};
use jwt::SignWithKey; use chrono::{Days, Utc};
use jsonwebtoken::{encode, Header};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Debug, Deserialize, Serialize)]
pub struct JWTClaims {
pub user_id: String,
pub exp: usize,
}
#[post("/auth/login")] #[post("/auth/login")]
async fn login(body: web::Json<LoginBody>) -> Result<HttpResponse, ErrorResponse> { async fn login(body: web::Json<LoginBody>) -> Result<HttpResponse, ErrorResponse> {
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
struct Response { struct Response {
access_token: String, access_token: String,
exp: usize,
} }
let user = Users::find_by_email(&body.email); let user = Users::find_by_email(&body.email);
match user { match user {
Ok(user) => { Ok(user) => match Users::verify_password(&body.password, &user.password) {
let password = Users::verify_password(&body.password, &user); Ok(_res) => {
let exp = Utc::now()
.checked_add_days(Days::new(30))
.expect("valid timestamp")
.timestamp();
if password == false { let claims = JWTClaims {
user_id: user.id.to_string(),
exp: exp as usize,
};
let token = encode(&Header::default(), &claims, &get_encoding_key()).unwrap();
Ok(HttpResponse::Ok().json(Response {
access_token: token,
exp: exp as usize,
}))
}
Err(_e) => {
return Err(ErrorResponse { return Err(ErrorResponse {
message: "Invalid credentials.".to_string(), message: "Invalid credentials.".to_string(),
status: StatusCode::BAD_REQUEST, status: StatusCode::BAD_REQUEST,
}); })
} }
},
let key = get_jwt_secret().unwrap();
let mut claims = BTreeMap::new();
claims.insert("user_id", &user.id);
let token_str = claims.sign_with_key(&key).unwrap();
Ok(HttpResponse::Ok().json(Response {
access_token: token_str,
}))
}
Err(_err) => { Err(_err) => {
return Err(ErrorResponse { return Err(ErrorResponse {
message: "Invalid credentials.".to_string(), message: "Invalid credentials.".to_string(),

View file

@ -1,11 +1,14 @@
use crate::middlewares::error::ErrorResponse; use crate::middlewares::error::ErrorResponse;
use crate::middlewares::user::get_user; use crate::middlewares::user::get_user;
use crate::models::playlist::Playlists; use crate::models::playlists::{NewPlaylist, Playlists};
use actix_web::{get, web, HttpRequest, HttpResponse, Scope}; use actix_web::{get, post, web, HttpRequest, HttpResponse, Scope};
use serde::Serialize; use serde::Serialize;
pub fn routes() -> Scope { pub fn routes() -> Scope {
web::scope("/me").service(me).service(me_playlists) web::scope("/me")
.service(me)
.service(me_playlists)
.service(create_playlist)
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -36,6 +39,20 @@ async fn me_playlists(req: HttpRequest) -> Result<HttpResponse, ErrorResponse> {
} }
Ok(HttpResponse::Ok().json(Response { Ok(HttpResponse::Ok().json(Response {
playlists: Playlists::find_for_user(&user.id)?, playlists: Playlists::find_for_user(&user.id, false)?,
})) }))
} }
#[post("/playlists")]
async fn create_playlist(
req: HttpRequest,
mut playlist: web::Json<NewPlaylist>,
) -> Result<HttpResponse, ErrorResponse> {
let user = get_user(req)?;
playlist.creator_id = Option::from(user.id);
Playlists::create(playlist.into_inner())?;
Ok(HttpResponse::Accepted().finish())
}

View file

@ -1,6 +1,6 @@
use crate::middlewares::error::ErrorResponse; use crate::middlewares::error::ErrorResponse;
use crate::models::playlist::{PlaylistCreator, Playlists}; use crate::models::playlists::{PlaylistCreator, Playlists};
use crate::models::tracks::Tracks; use crate::models::tracks::TracksWithArtists;
use actix_web::{get, web, HttpResponse}; use actix_web::{get, web, HttpResponse};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -9,7 +9,9 @@ struct GetPlaylistResponse {
pub id: String, pub id: String,
pub name: String, pub name: String,
pub creator: PlaylistCreator, pub creator: PlaylistCreator,
pub tracks: Vec<Tracks>, pub tracks: Vec<TracksWithArtists>,
pub tracks_count: usize,
pub duration: usize,
} }
#[get("/{playlist_id}")] #[get("/{playlist_id}")]
@ -19,6 +21,14 @@ pub async fn get_playlist(path: web::Path<String>) -> Result<HttpResponse, Error
let creator = playlist.get_creator()?; let creator = playlist.get_creator()?;
let tracks = playlist.get_tracks()?;
let tracks_count = tracks.len();
let duration = tracks
.iter()
.map(|track| track.duration_ms)
.reduce(|a, b| a + b)
.unwrap() as usize;
Ok(HttpResponse::Ok().json(GetPlaylistResponse { Ok(HttpResponse::Ok().json(GetPlaylistResponse {
id: playlist.id.to_string(), id: playlist.id.to_string(),
name: playlist.name.to_string(), name: playlist.name.to_string(),
@ -26,6 +36,8 @@ pub async fn get_playlist(path: web::Path<String>) -> Result<HttpResponse, Error
id: creator.id, id: creator.id,
name: creator.name, name: creator.name,
}, },
tracks: playlist.get_tracks()?, tracks,
tracks_count,
duration,
})) }))
} }

View file

@ -1,27 +1,29 @@
use crate::middlewares::error::ErrorResponse; use crate::middlewares::error::ErrorResponse;
use crate::models::playlists::Playlists;
use crate::models::user::Users; use crate::models::user::Users;
use actix_web::http::StatusCode; use actix_web::http::StatusCode;
use actix_web::{get, web, HttpResponse, Result}; use actix_web::{get, web, HttpResponse, Result, Scope};
use diesel::result::Error as DBError; use diesel::result::Error as DBError;
use serde::Serialize; use serde::Serialize;
pub fn routes() -> Scope {
web::scope("/users")
.service(get_user)
.service(get_user_playlists)
}
#[derive(Serialize)] #[derive(Serialize)]
struct GetUserResponse { struct GetUserResponse {
id: String, id: String,
name: String, name: String,
cover: String,
} }
#[get("/{user_id}")] fn get_a_user(user_id: &str) -> Result<Users, ErrorResponse> {
async fn get_user(path: web::Path<String>) -> Result<HttpResponse, ErrorResponse> { let user = Users::find(user_id);
let user_id = path.into_inner();
let user = Users::find(user_id.as_str());
match user { match user {
Ok(user) => Ok(HttpResponse::Ok().json(GetUserResponse { Ok(user) => Ok(user),
id: user.id,
name: user.name,
})),
Err(DBError::NotFound) => { Err(DBError::NotFound) => {
return Err(ErrorResponse { return Err(ErrorResponse {
message: "User not found".to_string(), message: "User not found".to_string(),
@ -36,3 +38,24 @@ async fn get_user(path: web::Path<String>) -> Result<HttpResponse, ErrorResponse
} }
} }
} }
#[get("/{user_id}")]
async fn get_user(path: web::Path<String>) -> Result<HttpResponse, ErrorResponse> {
let user = get_a_user(&path.into_inner())?;
let user_id = &user.id;
Ok(HttpResponse::Ok().json(GetUserResponse {
id: user_id.to_string(),
name: user.name,
cover: format!("https://assets.vybr.net/users/{}.png", user_id),
}))
}
#[get("/{user_id}/playlists")]
async fn get_user_playlists(path: web::Path<String>) -> Result<HttpResponse, ErrorResponse> {
let user = get_a_user(&path.into_inner())?;
let playlists = Playlists::find_for_user(&user.id, true)?;
Ok(HttpResponse::Ok().json(playlists))
}

View file

@ -1,11 +1,36 @@
// @generated automatically by Diesel CLI. // @generated automatically by Diesel CLI.
diesel::table! {
artists (id) {
#[max_length = 24]
id -> Varchar,
#[max_length = 255]
name -> Varchar,
created_at -> Timestamp,
updated_at -> Nullable<Timestamp>,
#[max_length = 21]
spotify_id -> Nullable<Varchar>,
#[max_length = 10]
tidal_id -> Nullable<Varchar>,
}
}
diesel::table! {
artists_tracks (artist_id, track_id) {
#[max_length = 24]
artist_id -> Varchar,
#[max_length = 24]
track_id -> Varchar,
}
}
diesel::table! { diesel::table! {
playlists (id) { playlists (id) {
#[max_length = 24] #[max_length = 24]
id -> Varchar, id -> Varchar,
#[max_length = 255] #[max_length = 255]
name -> Varchar, name -> Varchar,
public -> Bool,
#[max_length = 24] #[max_length = 24]
creator_id -> Varchar, creator_id -> Varchar,
created_at -> Timestamp, created_at -> Timestamp,
@ -52,11 +77,15 @@ diesel::table! {
} }
} }
diesel::joinable!(artists_tracks -> artists (artist_id));
diesel::joinable!(artists_tracks -> tracks (track_id));
diesel::joinable!(playlists -> users (creator_id)); diesel::joinable!(playlists -> users (creator_id));
diesel::joinable!(playlists_tracks -> playlists (playlist_id)); diesel::joinable!(playlists_tracks -> playlists (playlist_id));
diesel::joinable!(playlists_tracks -> tracks (track_id)); diesel::joinable!(playlists_tracks -> tracks (track_id));
diesel::allow_tables_to_appear_in_same_query!( diesel::allow_tables_to_appear_in_same_query!(
artists,
artists_tracks,
playlists, playlists,
playlists_tracks, playlists_tracks,
tracks, tracks,

View file

@ -1,8 +0,0 @@
use hmac::{Hmac, Mac};
use sha2::Sha256;
use std::error::Error;
pub fn get_jwt_secret() -> Result<Hmac<Sha256>, Box<dyn Error>> {
let key: Hmac<Sha256> = Hmac::new_from_slice(b"secret")?;
Ok(key)
}