! This merge denotes the MVP completion for the backend decentralization endpoints
More routes are to be added in the future but for now this should suffice Doc's are now required and the roadmap need to be updated as well
This commit is contained in:
commit
cfbee6d887
261
json-api/Cargo.lock
generated
261
json-api/Cargo.lock
generated
@ -14,18 +14,9 @@ checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.6.10"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@ -212,9 +203,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "const_fn"
|
||||
version = "0.4.6"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "076a6803b0dacd6a88cfe64deba628b01533ff5ef265687e6938280c1afd0a28"
|
||||
checksum = "402da840495de3f976eaefc3485b7f5eb5b0bf9761f9a47be27fe975b3b8c2ec"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
@ -233,10 +224,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
||||
|
||||
[[package]]
|
||||
name = "cpuid-bool"
|
||||
version = "0.1.2"
|
||||
name = "cpufeatures"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
|
||||
checksum = "5cd5a7748210e7ec1a9696610b1015e6e31fbf58f77a160801f124bd1c36592a"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
@ -254,7 +245,8 @@ dependencies = [
|
||||
"mysql_async",
|
||||
"rand 0.8.3",
|
||||
"serde",
|
||||
"tokio 1.4.0",
|
||||
"serde_json",
|
||||
"tokio 1.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -272,15 +264,6 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
|
||||
|
||||
[[package]]
|
||||
name = "dotenv"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "400b347fe65ccfbd8f545c9d9a75d04b0caf23fec49aaa838a9a05398f94c019"
|
||||
dependencies = [
|
||||
"regex 0.2.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.20"
|
||||
@ -327,9 +310,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1"
|
||||
checksum = "a9d5813545e459ad3ca1bff9915e9ad7f1a47dc6a91b627ce321d5863b7dd253"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@ -342,9 +325,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939"
|
||||
checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
@ -352,15 +335,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94"
|
||||
checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1"
|
||||
checksum = "10f6cb7042eda00f0049b1d2080aa4b93442997ee507eb3828e8bd7577f94c9d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
@ -369,15 +352,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59"
|
||||
checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7"
|
||||
checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
@ -387,21 +370,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3"
|
||||
checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80"
|
||||
checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1"
|
||||
checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@ -451,9 +434,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc018e188373e2777d0ef2467ebff62a08e66c3f5857b23c8fbec3018210dc00"
|
||||
checksum = "825343c4eef0b63f541f8903f395dc5beb362a979b5799a84062527ef1e37726"
|
||||
dependencies = [
|
||||
"bytes 1.0.1",
|
||||
"fnv",
|
||||
@ -463,7 +446,7 @@ dependencies = [
|
||||
"http",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio 1.4.0",
|
||||
"tokio 1.5.0",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
@ -510,21 +493,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.3.6"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc35c995b9d93ec174cf9a27d425c7892722101e14993cd227fdb51d70cf9589"
|
||||
checksum = "4a1ce40d6fc9764887c2fdc7305c3dcc429ba11ff981c1509416afd5697e4437"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
version = "0.3.2"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47"
|
||||
checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.5"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bf09f61b52cfcf4c00de50df88ae423d6c02354e385a86341133b5338630ad1"
|
||||
checksum = "1e5f105c494081baa3bf9e200b279e27ec1623895cd504c7dbef8d0b080fcf54"
|
||||
dependencies = [
|
||||
"bytes 1.0.1",
|
||||
"futures-channel",
|
||||
@ -538,7 +521,7 @@ dependencies = [
|
||||
"itoa",
|
||||
"pin-project",
|
||||
"socket2",
|
||||
"tokio 1.4.0",
|
||||
"tokio 1.5.0",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"want",
|
||||
@ -546,9 +529,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21"
|
||||
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
|
||||
dependencies = [
|
||||
"matches",
|
||||
"unicode-bidi",
|
||||
@ -606,7 +589,6 @@ dependencies = [
|
||||
"bcrypt",
|
||||
"clap",
|
||||
"db",
|
||||
"dotenv",
|
||||
"futures",
|
||||
"getrandom 0.1.16",
|
||||
"hyper",
|
||||
@ -616,7 +598,7 @@ dependencies = [
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio 1.4.0",
|
||||
"tokio 1.5.0",
|
||||
"tokio-test",
|
||||
"tokio-tungstenite",
|
||||
"url",
|
||||
@ -644,9 +626,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lexical"
|
||||
version = "5.2.1"
|
||||
version = "5.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a11b9b772d42a9cf7ff6742d4695054070432742b19cecea07e7c4eca8173d25"
|
||||
checksum = "f404a90a744e32e8be729034fc33b90cf2a56418fbf594d69aa3c0214ad414e5"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"lexical-core",
|
||||
@ -654,9 +636,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lexical-core"
|
||||
version = "0.7.5"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374"
|
||||
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
@ -667,15 +649,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.93"
|
||||
version = "0.2.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
|
||||
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.1.2"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655"
|
||||
checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
@ -684,9 +666,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.3"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176"
|
||||
checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
@ -717,9 +699,9 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.4"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
@ -774,7 +756,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio 1.4.0",
|
||||
"tokio 1.5.0",
|
||||
"tokio-native-tls",
|
||||
"tokio-util",
|
||||
"twox-hash",
|
||||
@ -800,7 +782,7 @@ dependencies = [
|
||||
"num-bigint 0.3.2",
|
||||
"num-traits",
|
||||
"rand 0.8.3",
|
||||
"regex 1.4.5",
|
||||
"regex",
|
||||
"rust_decimal",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -903,9 +885,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.33"
|
||||
version = "0.10.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577"
|
||||
checksum = "6d7830286ad6a3973c0f1d9b73738f69c76b739301d0229c4b96501695cbe4c8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if 1.0.0",
|
||||
@ -923,9 +905,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.61"
|
||||
version = "0.9.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f"
|
||||
checksum = "fa52160d45fa2e7608d504b7c3a3355afed615e6d8b627a74458634ba21b69bd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
@ -967,7 +949,7 @@ checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"once_cell",
|
||||
"regex 1.4.5",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -978,18 +960,18 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.0.6"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc174859768806e91ae575187ada95c91a29e96a98dc5d2cd9a1fed039501ba6"
|
||||
checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.0.6"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a490329918e856ed1b083f244e3bfe2d8c4f336407e4ea9e1a9f479ff09049e5"
|
||||
checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1139,51 +1121,29 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.5"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
|
||||
checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.2.11"
|
||||
version = "1.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384"
|
||||
checksum = "ce5f1ceb7f74abbce32601642fcf8e8508a8a8991e0621c7d750295b9095702b"
|
||||
dependencies = [
|
||||
"aho-corasick 0.6.10",
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax 0.5.6",
|
||||
"thread_local",
|
||||
"utf8-ranges",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
|
||||
dependencies = [
|
||||
"aho-corasick 0.7.15",
|
||||
"memchr",
|
||||
"regex-syntax 0.6.23",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.5.6"
|
||||
version = "0.6.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
|
||||
dependencies = [
|
||||
"ucd-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
@ -1211,9 +1171,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rust_decimal"
|
||||
version = "1.10.3"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc7f5b8840fb1f83869a3e1dfd06d93db79ea05311ac5b42b8337d3371caa4f1"
|
||||
checksum = "72e80c4f9a71b5949e283189c3c3ae35fedddecfe112e75c9d58751c36605b62"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"num-traits",
|
||||
@ -1322,13 +1282,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.9.4"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfebf75d25bd900fd1e7d11501efab59bc846dbc76196839663e6637bba9f25f"
|
||||
checksum = "b659df5fc3ce22274daac600ffb845300bd2125bcfaec047823075afdab81c00"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"cfg-if 1.0.0",
|
||||
"cpuid-bool",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
"opaque-debug",
|
||||
]
|
||||
@ -1341,13 +1301,13 @@ checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.9.3"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de"
|
||||
checksum = "d8f6b75b17576b792bef0db1bcc4b8b8bcdf9506744cf34b974195487af6cff2"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"cfg-if 1.0.0",
|
||||
"cpuid-bool",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
"opaque-debug",
|
||||
]
|
||||
@ -1374,9 +1334,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||
checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
@ -1472,9 +1432,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.69"
|
||||
version = "1.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
|
||||
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1524,15 +1484,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.43"
|
||||
@ -1611,9 +1562,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.4.0"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134af885d758d645f0f0505c9a8b3f9bf8a348fd822e112ab5248138348f1722"
|
||||
checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes 1.0.1",
|
||||
@ -1647,7 +1598,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
|
||||
dependencies = [
|
||||
"native-tls",
|
||||
"tokio 1.4.0",
|
||||
"tokio 1.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1670,22 +1621,22 @@ dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
"pin-project",
|
||||
"tokio 1.4.0",
|
||||
"tokio 1.5.0",
|
||||
"tungstenite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.6.5"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5143d049e85af7fbc36f5454d990e62c2df705b3589f123b71f441b6b59f443f"
|
||||
checksum = "940a12c99365c31ea8dd9ba04ec1be183ffe4920102bb7122c2f515437601e8e"
|
||||
dependencies = [
|
||||
"bytes 1.0.1",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"log",
|
||||
"pin-project-lite 0.2.6",
|
||||
"tokio 1.4.0",
|
||||
"tokio 1.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1696,9 +1647,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.25"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f"
|
||||
checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"pin-project-lite 0.2.6",
|
||||
@ -1707,9 +1658,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.17"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f"
|
||||
checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
@ -1757,12 +1708,6 @@ version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-util"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c85f514e095d348c279b1e5cd76795082cf15bd59b93207832abe0b1d8fed236"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.5"
|
||||
@ -1789,9 +1734,9 @@ checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
@ -1813,15 +1758,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "utf-8"
|
||||
version = "0.7.5"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
|
||||
|
||||
[[package]]
|
||||
name = "utf8-ranges"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
@ -1834,9 +1773,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.11"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
|
||||
checksum = "cbdbff6266a24120518560b5dc983096efb98462e51d0d68169895b237be3e5d"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
|
@ -18,8 +18,6 @@ futures = "0.3"
|
||||
url = "2.2.1"
|
||||
|
||||
|
||||
dotenv = "0.9.0"
|
||||
|
||||
# Crypto things
|
||||
getrandom = "0.1"
|
||||
bcrypt = "0.8"
|
||||
|
@ -7,5 +7,9 @@ dep:
|
||||
run:
|
||||
cargo run --features rtc --release -- -s
|
||||
|
||||
test:
|
||||
cd ../ && bash scripts/run-api-tests.sh
|
||||
rm -f *.png
|
||||
|
||||
clean:
|
||||
cargo clean
|
||||
|
@ -1,5 +1,6 @@
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
|
||||
class Server:
|
||||
@ -8,6 +9,15 @@ class Server:
|
||||
self.wsurl = meta.get('wsurl')
|
||||
self.serv_name = meta.get('name')
|
||||
|
||||
def __str__(self) -> str:
|
||||
fields = {
|
||||
'url': self.url,
|
||||
'wsurl': self.wsurl,
|
||||
'name': self.serv_name
|
||||
}
|
||||
return str(fields)
|
||||
|
||||
|
||||
class Admin:
|
||||
def __init__(self, user: dict, server: dict):
|
||||
self.id = user.get('id')
|
||||
@ -20,7 +30,15 @@ class Admin:
|
||||
self.server = Server(server)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f'{self.name}#{self.id}'
|
||||
acc = {
|
||||
'id': self.id,
|
||||
'name': self.name,
|
||||
'permissions': self.permissions,
|
||||
'secret': self.secret,
|
||||
'jwt': self.jwt,
|
||||
}
|
||||
container = {'user': acc, 'server': str(self.server)}
|
||||
return str(container)
|
||||
|
||||
def create_admin() -> Admin :
|
||||
CARGO_BIN = os.getenv('CARGO_BIN')
|
||||
@ -37,10 +55,12 @@ def create_admin() -> Admin :
|
||||
if user is None or server is None:
|
||||
print('stderr ', e)
|
||||
print('stdout ', proc.stdout)
|
||||
print(f'User/Server Data was not serializable => {raw}', file=sys.stderr)
|
||||
return None
|
||||
else:
|
||||
return Admin(user, server)
|
||||
except:
|
||||
except Exception as e:
|
||||
print(f'[create_admin] General exception caught in parsing => {e}', file=sys.stderr)
|
||||
print('stderr ', proc.stderr)
|
||||
print('stdout ', proc.stdout)
|
||||
return None
|
||||
|
@ -2,12 +2,14 @@ from time import time
|
||||
from request import Request
|
||||
from config import create_admin, Admin
|
||||
from config import Server
|
||||
from json import dumps as to_json
|
||||
|
||||
RESPONSES = []
|
||||
VOICE_CHAN = 1
|
||||
TEXT_CHAN = 2
|
||||
|
||||
def login() -> (Request, str):
|
||||
def login(admin: Admin) -> (Request, str):
|
||||
print(f'Provided admin account {admin}')
|
||||
req = Request(
|
||||
admin.server.url + '/login',
|
||||
'post',
|
||||
@ -67,9 +69,11 @@ def make_and_receive_invite(admin: Admin) -> (Request, Request):
|
||||
make_inv_req.fire()
|
||||
if make_inv_req.response is None:
|
||||
return (make_inv_req, user_inv_req)
|
||||
elif make_inv_req.response.status_code >= 400:
|
||||
print('Params used ', make_inv_req)
|
||||
return (make_inv_req, None)
|
||||
|
||||
# Setup to fire the second request, .fire() is safe to blindly use at this point
|
||||
print('Response text from /join ', make_inv_req.response.text)
|
||||
new_invite_body = make_inv_req.response.json()['invite']
|
||||
code = new_invite_body['id']
|
||||
user_inv_req = req(admin , 'get' , '/join', {'code': code}, 200, verbose=True)
|
||||
@ -89,7 +93,7 @@ if __name__ == '__main__':
|
||||
|
||||
# First a quick sanity check for login
|
||||
# add this after we fire the generic tests
|
||||
login_req, jwt = login()
|
||||
login_req, jwt = login(admin)
|
||||
if jwt is None:
|
||||
print('Unable to /login - stopping now to avoid pointless failure')
|
||||
req.show_response()
|
||||
@ -104,6 +108,19 @@ if __name__ == '__main__':
|
||||
# Invite test
|
||||
|
||||
# Container for most/all the generic requests we want to fire off
|
||||
now = time()
|
||||
tmp_neighbor = {
|
||||
'name': str(now),
|
||||
'wsurl': 'wsurl',
|
||||
'url': str(now),
|
||||
'description': 'asdf',
|
||||
'tags': ['red','blue']
|
||||
}
|
||||
# This neighbor is used to "update" the tmp one above in /neighbor tests
|
||||
updated_neighbor = tmp_neighbor.copy()
|
||||
updated_neighbor['name'] = 'new'
|
||||
print('Updated neighbor as json ', to_json(updated_neighbor))
|
||||
|
||||
requests.extend([
|
||||
req(fake_user, 'get', '/channels/list', {}, 401),
|
||||
req(admin, 'post', '/channels/list', {'kind': TEXT_CHAN}, 404),
|
||||
@ -117,8 +134,18 @@ if __name__ == '__main__':
|
||||
req(admin, 'get', '/message/recent', {'channel_id': 123, 'limit': 20}, 404),
|
||||
req(admin, 'get', '/members/me', {}, 200),
|
||||
req(admin, 'get', '/members/get_online', {}, 200),
|
||||
req(admin, 'post', '/members/me/nickname', {'nick': f'randy-{time()}'}, 200),
|
||||
req(admin , 'get', '/invite/join', {'code': 123}, 404)
|
||||
req(admin, 'post', '/members/me/nickname', {'nick': f'randy-{now}'}, 200),
|
||||
req(admin , 'get', '/invite/join', {'code': 123}, 404),
|
||||
req(admin , "get", "/meta", {}, 200),
|
||||
req(admin, 'get', '/neighbor/list', {}, 200),
|
||||
req(admin,'post', '/neighbor/add', {}, 200, body=to_json(tmp_neighbor)),
|
||||
req(admin, 'get', '/neighbor/list', {}, 200, verbose=True),
|
||||
req(admin, 'put', '/neighbor/update', {'url':str(now)}, 200, body=to_json(updated_neighbor)),
|
||||
req(admin, 'put', '/neighbor/update', {'url':'fake'}, 404, body=to_json(updated_neighbor)),
|
||||
req(admin, 'get', '/neighbor/list', {}, 200),
|
||||
req(admin, 'delete', '/neighbor/delete', {'url':'fake'}, 200),
|
||||
req(admin, 'delete', '/neighbor/delete', {'url': str(now)}, 200),
|
||||
req(admin, 'get', '/neighbor/list', {}, 200, verbose=True),
|
||||
])
|
||||
|
||||
# add this after fire the generic tests
|
||||
@ -143,6 +170,7 @@ if __name__ == '__main__':
|
||||
if r.passing:
|
||||
pass_count += 1
|
||||
|
||||
|
||||
req_count = len(requests)
|
||||
print(f'Passing {pass_count}/{req_count}')
|
||||
|
||||
|
@ -4,6 +4,7 @@ import requests
|
||||
NC = '\033[0m'
|
||||
RED = '\033[1;31m'
|
||||
GREEN = '\033[1;32m'
|
||||
YELLOW = '\033[1;33m'
|
||||
|
||||
class Request:
|
||||
|
||||
@ -21,6 +22,9 @@ class Request:
|
||||
self.verbose = verbose
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return str(self.qs)
|
||||
|
||||
@property
|
||||
def passing(self):
|
||||
if self.response is None:
|
||||
@ -36,6 +40,8 @@ class Request:
|
||||
self.response = requests.post(self.url, headers=self.headers, params=self.qs, data=self.body)
|
||||
elif self.method == 'delete':
|
||||
self.response = requests.delete(self.url, headers=self.headers, params=self.qs)
|
||||
elif self.method == 'put':
|
||||
self.response = requests.put(self.url, headers=self.headers, params=self.qs, data=self.body)
|
||||
|
||||
return self.response
|
||||
except Exception as e:
|
||||
@ -45,34 +51,36 @@ class Request:
|
||||
|
||||
|
||||
def show_response(self):
|
||||
if self.response is None:
|
||||
print('Response := None')
|
||||
return
|
||||
|
||||
real_code = None
|
||||
if self.response is not None:
|
||||
real_code = self.response.status_code
|
||||
|
||||
if self.hope != real_code:
|
||||
abstract = RED + 'Fail ' + NC + 'Expected ' + str(self.hope) + ' Got ' + str(real_code)
|
||||
if self.response is None:
|
||||
print('\tNo Response to show for')
|
||||
|
||||
print(abstract)
|
||||
print('\t', self.method, ' ', self.url)
|
||||
if len(self.headers) != 0:
|
||||
print('\tRequest-Headers ', self.headers)
|
||||
print(YELLOW + '\tRequest-Headers ' + NC, self.headers)
|
||||
|
||||
if len(self.qs) != 0:
|
||||
print('\tQuery-Dictionary ', self.qs)
|
||||
print(YELLOW + '\tQuery-Dictionary' + NC, self.qs)
|
||||
|
||||
if self.body is not None:
|
||||
print('\tRequest-Body ', str(self.body))
|
||||
print(YELLOW + '\tRequest-Body' + NC, str(self.body))
|
||||
|
||||
if self.verbose:
|
||||
print(f'\tResponse-Status {self.response.status_code}')
|
||||
print(f'\tResponse-Headers {self.response.headers}')
|
||||
print(f'\tResponse-Text {self.response.text}')
|
||||
print(f'\t{YELLOW}Response-Status{NC} {self.response.status_code}')
|
||||
print(f'\t{YELLOW}Response-Headers{NC} {self.response.headers}')
|
||||
print(f'\t{YELLOW}Response-Text{NC} {self.response.text}')
|
||||
|
||||
else:
|
||||
print(f'{GREEN}Pass{NC} {self.method} {self.url}')
|
||||
if self.verbose:
|
||||
print(f'\tResponse-Status {self.response.status_code}')
|
||||
print(f'\tResponse-Headers {self.response.headers}')
|
||||
print(f'\tResponse-Text {self.response.text}')
|
||||
print(f'\t{YELLOW}Response-Status{NC} {self.response.status_code}')
|
||||
print(f'\t{YELLOW}Response-Headers{NC} {self.response.headers}')
|
||||
print(f'\t{YELLOW}Response-Text{NC} {self.response.text}')
|
||||
|
||||
|
18
json-api/config.json
Normal file
18
json-api/config.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"#": "The fields below are required and can not be empty",
|
||||
"#": "All other fields are ignored completely",
|
||||
|
||||
"database_url": "mysql://freechat_dev:password@localhost:3306/freechat",
|
||||
"hmac_path": "hmac.secret",
|
||||
"wss_hmac_path": "wss-hmac.secret",
|
||||
"name": "Freechat Server",
|
||||
"description": "Chatting server",
|
||||
"url": "http://localhost:4536",
|
||||
"wsurl": "ws://localhost:5648",
|
||||
|
||||
"tags": [
|
||||
"Freechat",
|
||||
"Libre software",
|
||||
"Chatting"
|
||||
]
|
||||
}
|
@ -10,5 +10,6 @@ edition = "2018"
|
||||
mysql_async = "0.27"
|
||||
|
||||
serde = { version = "1.0.117", features = [ "derive" ] }
|
||||
serde_json = "1.0"
|
||||
tokio = { version = "1", features = ["fs", "io-util"] }
|
||||
rand = "0.8.3"
|
||||
|
19
json-api/db/src/jwt.rs
Normal file
19
json-api/db/src/jwt.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use mysql_async::{Pool, params, Result, prelude::Queryable};
|
||||
|
||||
pub async fn listed(p: &Pool, id: u64, given_rng_value: &str) -> Result<bool> {
|
||||
let mut conn = p.get_conn().await?;
|
||||
let q = "SELECT rng FROM jwt WHERE id = :id";
|
||||
let row: Option<String> = conn.exec_first(q, params!{"id" => id}).await?;
|
||||
if let Some(value) = row {
|
||||
Ok(value == given_rng_value)
|
||||
} else{
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn insert(p: &Pool, id: u64, given_rng_value: &str) -> Result<()> {
|
||||
let mut conn = p.get_conn().await?;
|
||||
let q = "INSERT INTO jwt (id, rng) VALUES (:id, :rng)";
|
||||
conn.exec_drop(q, params!{"id" => id, "rng" => given_rng_value}).await?;
|
||||
Ok(())
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
use serde::Serialize;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
pub mod member;
|
||||
pub mod common;
|
||||
pub mod invites;
|
||||
pub mod channels;
|
||||
pub mod messages;
|
||||
pub mod neighbors;
|
||||
pub mod jwt;
|
||||
|
||||
use std::vec::Vec;
|
||||
|
||||
@ -90,3 +92,11 @@ pub struct PublicMember {
|
||||
pub permissions: UBigInt,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct Neighbor {
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub tags: Vec<String>,
|
||||
pub url: String,
|
||||
pub wsurl: Option<String>,
|
||||
}
|
||||
|
82
json-api/db/src/neighbors.rs
Normal file
82
json-api/db/src/neighbors.rs
Normal file
@ -0,0 +1,82 @@
|
||||
use crate::Neighbor;
|
||||
use mysql_async::Result as SqlResult;
|
||||
use mysql_async::{params, Pool, prelude::Queryable};
|
||||
use serde_json;
|
||||
|
||||
pub async fn get_all(p: &Pool) -> SqlResult<Vec<Neighbor>> {
|
||||
let mut conn = p.get_conn().await?;
|
||||
let q = "SELECT name, description, tags, url, wsurl FROM neighbors";
|
||||
type Types = (String, Option<String>, String, String, Option<String>);
|
||||
let set: Vec<Neighbor> = conn.exec_map(q, (), |(name, description, tags, url, wsurl): Types| {
|
||||
let json: Vec<String> = serde_json::from_str(tags.as_str()).unwrap_or(vec![]);
|
||||
Neighbor {
|
||||
name, description, tags: json, url, wsurl
|
||||
}
|
||||
}).await?;
|
||||
Ok(set)
|
||||
}
|
||||
|
||||
pub async fn add_neighbor(p: &Pool, new: Neighbor) -> SqlResult<()> {
|
||||
// Note we assume that the tags field has been verified as proper valid json prior to
|
||||
// writing it to the db
|
||||
let mut conn = p.get_conn().await?;
|
||||
let q = "INSERT INTO neighbors(url, wsurl, name, description, tags)
|
||||
VALUES(:url, :wsurl, :name, :desc, :tags)";
|
||||
let tags = serde_json::to_string(&new.tags).unwrap_or("[]".to_string());
|
||||
let sqlparams = params!{
|
||||
"url"=> new.url,
|
||||
"wsurl"=>new.wsurl,
|
||||
"name"=>new.name,
|
||||
"desc"=>new.description,
|
||||
"tags"=>tags
|
||||
};
|
||||
conn.exec_drop(q, sqlparams).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get(p: &Pool, url: &str) -> SqlResult<Option<Neighbor>> {
|
||||
let mut conn = p.get_conn().await?;
|
||||
let q = "SELECT wsurl, name, description, tags FROM neighbors
|
||||
WHERE url = :url";
|
||||
|
||||
type Fields = (Option<String>, String, Option<String>, String);
|
||||
let row: Option<Fields> = conn.exec_first(q, params!{"url" => url}).await?;
|
||||
if let Some(fields) = row {
|
||||
let tags: Vec<String> = serde_json::from_str(fields.3.as_str()).unwrap_or(vec![]);
|
||||
let n = Neighbor {
|
||||
name: fields.1,
|
||||
wsurl: fields.0,
|
||||
description: fields.2,
|
||||
tags,
|
||||
url: url.into(),
|
||||
};
|
||||
return Ok(Some(n));
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub async fn update(p: &Pool, url: &str, new: Neighbor) -> SqlResult<()> {
|
||||
let mut conn = p.get_conn().await?;
|
||||
let q = "UPDATE neighbors
|
||||
SET name = :nm, description = :desc, tags = :tags, wsurl = :ws, url = :newurl
|
||||
WHERE url = :url";
|
||||
|
||||
let sqlparams = params!{
|
||||
"url" => url,
|
||||
"nm" => new.name,
|
||||
"desc" => new.description,
|
||||
"tags" => serde_json::to_string(&new.tags).unwrap(),
|
||||
"ws" => new.wsurl,
|
||||
"newurl" => new.url
|
||||
};
|
||||
|
||||
conn.exec_drop(q, sqlparams).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn remove(p: &Pool, url: &str) -> SqlResult<()> {
|
||||
let mut conn = p.get_conn().await?;
|
||||
let q = "DELETE FROM neighbors WHERE url = :url";
|
||||
conn.exec_drop(q, params!{"url" => url}).await?;
|
||||
Ok(())
|
||||
}
|
1
json-api/migrations/2021-05-04-200859_neighbors/down.sql
Normal file
1
json-api/migrations/2021-05-04-200859_neighbors/down.sql
Normal file
@ -0,0 +1 @@
|
||||
DROP TABLE `neighbors`;
|
10
json-api/migrations/2021-05-04-200859_neighbors/up.sql
Normal file
10
json-api/migrations/2021-05-04-200859_neighbors/up.sql
Normal file
@ -0,0 +1,10 @@
|
||||
-- everything else is nullable due to
|
||||
-- A) Flexibility
|
||||
-- B) They're part of optional features(such as the wsurl which not all servers may have)
|
||||
CREATE TABLE IF NOT EXISTS `neighbors`(
|
||||
`url` VARCHAR(512) UNIQUE NOT NULL,
|
||||
`wsurl` VARCHAR(512),
|
||||
`name` VARCHAR(512) NOT NULL,
|
||||
`description` VARCHAR(1024),
|
||||
`tags` VARCHAR(1024)
|
||||
);
|
1
json-api/migrations/2021-05-07-201858_jwt/down.sql
Normal file
1
json-api/migrations/2021-05-07-201858_jwt/down.sql
Normal file
@ -0,0 +1 @@
|
||||
DROP TABLE `jwt`;
|
5
json-api/migrations/2021-05-07-201858_jwt/up.sql
Normal file
5
json-api/migrations/2021-05-07-201858_jwt/up.sql
Normal file
@ -0,0 +1,5 @@
|
||||
CREATE TABLE IF NOT EXISTS `jwt` (
|
||||
`id` BIGINT UNSIGNED NOT NULL,
|
||||
`rng` VARCHAR(48) NOT NULL,
|
||||
PRIMARY KEY(`id`)
|
||||
);
|
@ -1,12 +1,12 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
use bcrypt::{self, BcryptResult};
|
||||
use mysql_async::Pool;
|
||||
use hyper::StatusCode;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
use crate::routes;
|
||||
use crate::qs_param;
|
||||
|
||||
use db::{Response, Member};
|
||||
|
||||
@ -26,15 +26,16 @@ lazy_static! {
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct Claim {
|
||||
sub: db::UBigInt, // user id
|
||||
exp: db::BigInt, // expiry date
|
||||
nbf: i64,
|
||||
cookie: String, // unique cookie value
|
||||
pub struct Claim {
|
||||
sub: u64,// user id
|
||||
exp: i64, // expiry date
|
||||
nbf: i64, // "valid-start" time for the claim
|
||||
prm: u64, // user permissions
|
||||
rng: String, // Cheesy way of helping reduce the amount
|
||||
}
|
||||
|
||||
impl Claim {
|
||||
pub fn new(id: db::UBigInt) -> Claim {
|
||||
pub fn new(id: db::UBigInt, prm: u64) -> Claim {
|
||||
|
||||
// JWT's expire every 48 hours
|
||||
let now = SystemTime::now();
|
||||
@ -52,20 +53,20 @@ impl Claim {
|
||||
sub: id,
|
||||
exp,
|
||||
nbf,
|
||||
cookie: generate_cookie()
|
||||
prm,
|
||||
rng: generate_cookie()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// used when we create a new users for the first time
|
||||
#[derive(Debug)]
|
||||
pub enum AuthReason {
|
||||
Good, //passed regular check
|
||||
Good(Claim), //passed regular check
|
||||
OpenAuth, // route does not require auth
|
||||
NoKey, // key missing
|
||||
BadKey, // key is bad
|
||||
LoginValid, // used only to access the login route which is also our refresh
|
||||
LoginValid(Member), // used only to access the login route which is also our refresh
|
||||
ServerIssue(String) // for well 500's
|
||||
}
|
||||
|
||||
@ -81,7 +82,7 @@ fn valid_secret(given_pass: &str, hash: &str) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn valid_perms(member: Member, path: &str) -> bool {
|
||||
fn valid_perms(member: &Member, path: &str) -> bool {
|
||||
use crate::perms;
|
||||
// if there are perms on the current path make sure the user has them
|
||||
if let Some(p) = perms::get_perm_mask(path) {
|
||||
@ -111,7 +112,7 @@ pub fn generate_secret() -> String {
|
||||
}
|
||||
|
||||
pub fn generate_cookie() -> String {
|
||||
return rng_secret(32)
|
||||
return rng_secret(16)
|
||||
}
|
||||
|
||||
pub fn encrypt_secret(raw: &str) -> BcryptResult<String> {
|
||||
@ -120,7 +121,13 @@ pub fn encrypt_secret(raw: &str) -> BcryptResult<String> {
|
||||
}
|
||||
|
||||
|
||||
async fn valid_jwt(token: &str) -> AuthReason {
|
||||
async fn valid_jwt(pool: &Pool, path: &str, token: &str) -> AuthReason {
|
||||
/*
|
||||
* This function does a database check because of the requirement of always
|
||||
* enforcing permissions
|
||||
* TODO: Not all routes actually require a permissions check so we should
|
||||
* try to only do that DB call when absolutely required
|
||||
*/
|
||||
use jsonwebtoken::{
|
||||
decode, DecodingKey,
|
||||
Validation, Algorithm
|
||||
@ -136,7 +143,18 @@ async fn valid_jwt(token: &str) -> AuthReason {
|
||||
|
||||
let active = now < decoded.claims.exp;
|
||||
if active {
|
||||
AuthReason::Good
|
||||
if routes::requires_perms(path) {
|
||||
match db::jwt::listed(pool, decoded.claims.sub, decoded.claims.rng.as_str()).await {
|
||||
Ok(listed) => if listed {
|
||||
AuthReason::Good(decoded.claims)
|
||||
} else {
|
||||
AuthReason::BadKey
|
||||
}
|
||||
_ => AuthReason::BadKey
|
||||
}
|
||||
} else {
|
||||
AuthReason::Good(decoded.claims)
|
||||
}
|
||||
} else {
|
||||
AuthReason::BadKey
|
||||
}
|
||||
@ -181,8 +199,7 @@ pub async fn wall_entry<'path, 'pool, 'params>(
|
||||
}
|
||||
|
||||
if let Some(jwt) = jwt {
|
||||
// get the headers here
|
||||
return valid_jwt(jwt).await;
|
||||
return valid_jwt(pool, path, jwt).await;
|
||||
}
|
||||
if let Some((id, secret)) = login_params_from_qs(params) {
|
||||
// Last chance we might be hitting the /login route so we have to do the heavy auth flow
|
||||
@ -194,8 +211,8 @@ pub async fn wall_entry<'path, 'pool, 'params>(
|
||||
match Member::get(pool, id).await {
|
||||
Ok(response) => match response {
|
||||
Response::Row(user) => {
|
||||
if valid_secret(secret, &user.secret) && valid_perms(user, path){
|
||||
AuthReason::LoginValid
|
||||
if valid_secret(secret, &user.secret) && valid_perms(&user, path){
|
||||
AuthReason::LoginValid(user)
|
||||
}
|
||||
else {
|
||||
AuthReason::BadKey
|
||||
@ -215,7 +232,7 @@ pub async fn wall_entry<'path, 'pool, 'params>(
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn login_get_jwt(response: &mut hyper::Response<hyper::Body>, params: HashMap<String, String>) {
|
||||
pub async fn login_get_jwt(p: &Pool, response: &mut hyper::Response<hyper::Body>, user: Member) {
|
||||
// Login data has already been validated at this point
|
||||
// Required data such as 'id' and 'secret' are there and validated
|
||||
use jsonwebtoken::{
|
||||
@ -225,10 +242,9 @@ pub async fn login_get_jwt(response: &mut hyper::Response<hyper::Body>, params:
|
||||
use hyper::header::HeaderValue;
|
||||
use crate::http;
|
||||
|
||||
let id = qs_param!(params, "id", u64).unwrap();
|
||||
let id = user.id;
|
||||
|
||||
|
||||
let claim = Claim::new(id);
|
||||
let claim = Claim::new(id, user.permissions);
|
||||
let header = Header::new(Algorithm::HS512);
|
||||
let encoded = encode(
|
||||
&header,
|
||||
@ -238,7 +254,13 @@ pub async fn login_get_jwt(response: &mut hyper::Response<hyper::Body>, params:
|
||||
response.headers_mut().insert("Content-Type",
|
||||
HeaderValue::from_static("application/json"));
|
||||
|
||||
http::set_json_body(response, serde_json::json!({"jwt": encoded}));
|
||||
match db::jwt::insert(p, id, &claim.rng).await {
|
||||
Ok(_) => http::set_json_body(response, serde_json::json!({"jwt": encoded})),
|
||||
Err(e) => {
|
||||
eprintln!("/login 500 {}", e);
|
||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -259,7 +281,7 @@ mod auth_tests {
|
||||
|
||||
#[test]
|
||||
fn verify_jwt() {
|
||||
let claim = super::Claim::new(123); // example claim that we send out
|
||||
let claim = super::Claim::new(123, 456); // example claim that we send out
|
||||
let header = Header::new(Algorithm::HS512); // header that basically all clients get
|
||||
let encoded = encode(
|
||||
&header,
|
||||
|
@ -1,6 +1,5 @@
|
||||
extern crate db;
|
||||
extern crate clap;
|
||||
extern crate dotenv;
|
||||
extern crate getrandom;
|
||||
extern crate bcrypt;
|
||||
extern crate base64;
|
||||
@ -23,8 +22,8 @@ use hyper::{
|
||||
HeaderMap
|
||||
};
|
||||
use mysql_async::Pool;
|
||||
use serde::Deserialize;
|
||||
|
||||
use dotenv::dotenv;
|
||||
use clap::{Arg, App};
|
||||
use auth::AuthReason;
|
||||
|
||||
@ -64,6 +63,7 @@ async fn route_dispatcher(
|
||||
const GET: &Method = &Method::GET;
|
||||
const POST: &Method = &Method::POST;
|
||||
const DELETE: &Method = &Method::DELETE;
|
||||
const PUT: &Method = &Method::PUT;
|
||||
println!("[HTTP] {}: {}", meth, path);
|
||||
match (meth, path) {
|
||||
/* INVITES */
|
||||
@ -88,6 +88,11 @@ async fn route_dispatcher(
|
||||
(POST, routes::SET_NEW_ADMIN) => admin::new_admin(pool, resp, params).await,
|
||||
/* META ROUTE */
|
||||
(GET, routes::META) => meta::server_meta(resp).await,
|
||||
/* Federated Routes */
|
||||
(GET, routes::GET_NEIGHBORS) => meta::server_neighbors(pool, resp).await,
|
||||
(POST, routes::ADD_NEIGHBOR) => meta::add_neighbor(pool, resp, body).await,
|
||||
(PUT, routes::UPDATE_NEIGHBOR) => meta::update_neighbor(pool, resp, params, body).await,
|
||||
(DELETE, routes::REMOVE_NEIGHBOR) => meta::remove_neighbor(pool, resp, params).await,
|
||||
_ => {
|
||||
println!("[HTTP]\tNOT FOUND: {}: {}", meth, path);
|
||||
*resp.status_mut() = StatusCode::NOT_FOUND
|
||||
@ -110,15 +115,18 @@ async fn main_responder(request: Request<Body>) -> Result<Response<Body>, hyper:
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(params) = params_opt {
|
||||
match auth::wall_entry(path, &DB_POOL, ¶ms).await {
|
||||
OpenAuth | Good => {
|
||||
// route dispatch has its own more comprehensive logging
|
||||
route_dispatcher(&DB_POOL, &mut response, &method, path, body, params, headers).await;
|
||||
if let Some(qs) = params_opt {
|
||||
match auth::wall_entry(path, &DB_POOL, &qs).await {
|
||||
OpenAuth => {
|
||||
route_dispatcher(&DB_POOL, &mut response, &method, path, body, qs, headers).await;
|
||||
},
|
||||
LoginValid => {
|
||||
// Only with typical routes do we have to inject the permissions
|
||||
Good(_claim/* TODO: start moving route handlers to use claims.id for faster access */) => {
|
||||
route_dispatcher(&DB_POOL, &mut response, &method, path, body, qs, headers).await;
|
||||
},
|
||||
LoginValid(member) => {
|
||||
println!("[HTTP] POST /login");
|
||||
auth::login_get_jwt(&mut response, params).await;
|
||||
auth::login_get_jwt(&DB_POOL, &mut response, member).await;
|
||||
},
|
||||
NoKey | BadKey => {
|
||||
*response.status_mut() = StatusCode::UNAUTHORIZED;
|
||||
@ -193,14 +201,56 @@ async fn attempt_owner_creation(name: &str) {
|
||||
let _ = p.disconnect().await;
|
||||
}
|
||||
|
||||
fn init_config() -> Result<(), Box<dyn std::error::Error>> {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct RequiredFields {
|
||||
pub database_url: String,
|
||||
pub hmac_path: String,
|
||||
pub wss_hmac_path: String,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub url: String,
|
||||
pub wsurl: String,
|
||||
pub tags: Option<Vec<String>>
|
||||
}
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
|
||||
let file = File::open("config.json")?;
|
||||
let reader = BufReader::new(file);
|
||||
let fields: RequiredFields = serde_json::from_reader(reader)?;
|
||||
|
||||
// Now we can setup each environment variable for this process from config.json
|
||||
// Note that we only have to do this once since all of these are read from
|
||||
// lazy statics so the cost is very minimal
|
||||
set_var("DATABASE_URL", fields.database_url);
|
||||
|
||||
set_var("HMAC_PATH", fields.hmac_path);
|
||||
set_var("WSS_HMAC_PATH", fields.wss_hmac_path);
|
||||
|
||||
set_var("SERVER_NAME", fields.name);
|
||||
|
||||
set_var("SERVER_DESCRIPTION", fields.description.unwrap_or("".into()));
|
||||
|
||||
set_var("PUBLIC_URL", fields.url);
|
||||
set_var("PUBLIC_WS_URL", fields.wsurl);
|
||||
|
||||
// Mega cheesy way of forcing config initialization
|
||||
if meta::get_config().tags.len() == 0 {
|
||||
eprintln!("[API] [WARN] No tags have been set", );
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), u16>{
|
||||
|
||||
let mut main_ret: u16 = 0;
|
||||
let d_result = dotenv();
|
||||
let mut main_ret: u16 = 0; let d_result = init_config();
|
||||
|
||||
// check for a database_url before the override we get from the cmd line
|
||||
if let Err(_d) = d_result {
|
||||
if let Err(d) = d_result {
|
||||
eprintln!("Config error: {}", d);
|
||||
if let Err(_e) = env::var("DATABASE_URL") {
|
||||
main_ret |= CONFIG_ERR;
|
||||
}
|
||||
@ -243,9 +293,6 @@ async fn main() -> Result<(), u16>{
|
||||
.get_matches();
|
||||
|
||||
|
||||
if let Some(db_url) = args.value_of("db-url") {
|
||||
set_var("DATABASE_URL", db_url);
|
||||
}
|
||||
|
||||
// safe because we have a default value set in code
|
||||
let port = args.value_of("port").unwrap().to_string();
|
||||
@ -255,7 +302,7 @@ async fn main() -> Result<(), u16>{
|
||||
attempt_owner_creation(owner_name).await;
|
||||
}
|
||||
|
||||
// This check overrides the value set in the .env since this
|
||||
// Here we override some of the config.json variables
|
||||
if let Some(hmac) = args.value_of("hmac") {
|
||||
std::env::set_var("HMAC_PATH", hmac);
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
use mysql_async::Pool;
|
||||
use hyper::{Response, Body, HeaderMap, StatusCode};
|
||||
use hyper::body::to_bytes;
|
||||
use hyper::body::Bytes;
|
||||
use serde_json::json;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::http::set_json_body;
|
||||
use crate::perms;
|
||||
use crate::qs_param;
|
||||
use db::Message;
|
||||
|
||||
@ -62,7 +62,6 @@ pub async fn send_message(pool: &Pool, response: &mut Response<Body>, body: Body
|
||||
* TODO: more features here because send_message is a large handler
|
||||
*/
|
||||
use db::Response::*;
|
||||
use db::Member;
|
||||
|
||||
// NOTE: auth module guarantees that id will be present so the unwrap is safe
|
||||
let uid = qs_param!(params, "id", u64).unwrap();
|
||||
@ -76,25 +75,10 @@ pub async fn send_message(pool: &Pool, response: &mut Response<Body>, body: Body
|
||||
None => None
|
||||
};
|
||||
|
||||
let permissions = match Member::get(pool, uid).await {
|
||||
Ok(dbresponse) => match dbresponse {
|
||||
Row(user) => user.permissions,
|
||||
_ => 0
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("[DB-SQL] {}",e );
|
||||
0
|
||||
}
|
||||
};
|
||||
if perms::has_perm(permissions, perms::SEND_MESSAGES) == false {
|
||||
*response.status_mut() = StatusCode::BAD_REQUEST;
|
||||
return;
|
||||
}
|
||||
|
||||
let channel_id = qs_param!(params, "channel_id", u64);
|
||||
|
||||
// Black magic
|
||||
let body_bytes: &[u8] = &to_bytes(body).await.unwrap(); // yolo
|
||||
let body_bytes: &[u8] = &to_bytes(body).await.unwrap_or(Bytes::new());
|
||||
let content = String::from_utf8_lossy(body_bytes);
|
||||
|
||||
// 400 on empty bodies or missing channel id's
|
||||
@ -164,3 +148,4 @@ pub async fn recent_messages(pool: &Pool, response: &mut Response<Body>, params:
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,28 +1,138 @@
|
||||
// Basic handler for getting meta data about the server
|
||||
use std::env::var;
|
||||
use std::collections::HashMap;
|
||||
use crate::http::set_json_body;
|
||||
use db::Neighbor;
|
||||
|
||||
use hyper::{Response, Body};
|
||||
use serde_json::to_string;
|
||||
use serde::Serialize;
|
||||
use mysql_async::Pool;
|
||||
use hyper::{Response, Body, StatusCode};
|
||||
use hyper::body::to_bytes;
|
||||
use hyper::body::Bytes;
|
||||
use serde_json::{json, to_string, Result as JsonResult};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
|
||||
#[derive( Serialize)]
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub url: String,
|
||||
pub wsurl: String,
|
||||
pub tags: Vec<String>
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
// NOTE: this object must be access by proxy through get_config()
|
||||
#[derive(Deserialize, Serialize)]
|
||||
static ref BASIC_CONFIG: Config = {
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
match File::open("config.json") {
|
||||
Ok(file) => {
|
||||
let reader = BufReader::new(file);
|
||||
let rr: JsonResult<Config> = serde_json::from_reader(reader);
|
||||
match rr {
|
||||
Ok(meta) => meta,
|
||||
Err(e) => panic!("[HTTP] [FATAL-INIT] {}", e)
|
||||
}
|
||||
|
||||
},
|
||||
Err(e) => panic!("{}", e)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get_config() -> Config {
|
||||
// We have to do this (for now) because lazy_static silently hides the actual fields
|
||||
// we care about
|
||||
Config {
|
||||
name: var("SERVER_NAME").unwrap_or("No name".into()),
|
||||
description: var("SERVER_DESCRIPTION").unwrap_or("No description".into()),
|
||||
url: var("PUBLIC_URL").unwrap(),
|
||||
wsurl: var("PUBLIC_WS_URL").unwrap()
|
||||
name: BASIC_CONFIG.name.clone(),
|
||||
description: BASIC_CONFIG.description.clone(),
|
||||
url: BASIC_CONFIG.url.clone(),
|
||||
wsurl: BASIC_CONFIG.wsurl.clone(),
|
||||
tags: BASIC_CONFIG.tags.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn server_meta(response: &mut Response<Body>) {
|
||||
// NOTE: This route _is_ open but we should do something to rate limit the
|
||||
// number of requests we service as it could be ripe for abuse
|
||||
*response.body_mut() = Body::from(to_string(&get_config()).unwrap());
|
||||
}
|
||||
|
||||
pub async fn server_neighbors(p: &Pool, response: &mut Response<Body>) {
|
||||
// This method refers to what servers have been added as **related** by the admins
|
||||
// It returns a list of servers meta objects which converted to JSON
|
||||
match db::neighbors::get_all(p).await {
|
||||
Ok(neighbors) => set_json_body(response, json!({"neighbors": neighbors})),
|
||||
Err(e) => {
|
||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
eprintln!("500 /neighbors/list {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn add_neighbor(p: &Pool, response: &mut Response<Body>, body: Body) {
|
||||
let body: Bytes = to_bytes(body).await.unwrap_or(Bytes::new());
|
||||
let json: JsonResult<Neighbor> = serde_json::from_slice(&body);
|
||||
if let Ok(neighbor) = json {
|
||||
// Before we try adding the new neighbor, make sure there isn't already
|
||||
// an entry with the same url
|
||||
if let Ok(row) = db::neighbors::get(p, &neighbor.url).await {
|
||||
match row.is_some() {
|
||||
true => *response.status_mut() = StatusCode::CONFLICT,
|
||||
false => if let Err(e) = db::neighbors::add_neighbor(p, neighbor).await {
|
||||
eprintln!("[HTTP] [DB-LIB] {}", e);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
eprintln!();
|
||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
} else {
|
||||
*response.status_mut() = StatusCode::BAD_REQUEST;
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn update_neighbor(p: &Pool, response: &mut Response<Body>, params: HashMap<String, String>, body: Body) {
|
||||
// First collect the target url from the map and try to parse the body
|
||||
let target = params.get("url");
|
||||
let body: Bytes = to_bytes(body).await.unwrap_or(Bytes::new());
|
||||
let s: String = String::from_utf8_lossy(&body).to_string();
|
||||
let json: JsonResult<Neighbor> = serde_json::from_str(&s);
|
||||
|
||||
// Verify query string parameter **and** body before attempting to reach database
|
||||
match (target, json) {
|
||||
(Some(target_url), Ok(neighbor)) => {
|
||||
match db::neighbors::get(p, target_url).await {
|
||||
Ok(row) => if row.is_some() {
|
||||
if let Err(e) = db::neighbors::update(p, target_url, neighbor).await {
|
||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
eprintln!("[HTTP] [DB-LIB] /neighbor/update [DB-LIB] {}", e);
|
||||
}
|
||||
// Nothing to do on success 200 is already set by hyper
|
||||
} else{
|
||||
*response.status_mut() = StatusCode::NOT_FOUND;
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("[HTTP] [DB-LIB] /neighbor/update {}", e);
|
||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => *response.status_mut() = StatusCode::BAD_REQUEST
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn remove_neighbor(p: &Pool, response: &mut Response<Body>, params: HashMap<String, String>) {
|
||||
match params.get("url") {
|
||||
Some(url) => {
|
||||
// As usual 500 on server errors otherwise there's nothing to do
|
||||
if let Err(e) = db::neighbors::remove(p, url).await {
|
||||
eprintln!("[HTTP] [DB-LIB] /neighbor/remove {}", e);
|
||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
},
|
||||
None => *response.status_mut() = StatusCode::BAD_REQUEST
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ pub const _ADMIN: u64 = 1 << 62; // can make other admins but can't really touch
|
||||
// ADMIN PERMS
|
||||
pub const CREATE_CHANNEL:u64 = 64;
|
||||
pub const DELETE_CHANNEL:u64 = 128;
|
||||
pub const ADD_NEIGHBOR:u64 = 256;
|
||||
|
||||
// BELOW ARE COLLECTIVE PERMISSION SETS
|
||||
pub const OWNER: u64 = std::u64::MAX;
|
||||
@ -21,16 +22,22 @@ pub const ADMIN_PERMS: u64 = !(std::u64::MAX & OWNER); // filter the only perm a
|
||||
|
||||
pub fn get_perm_mask(path: &str) -> Option<u64> {
|
||||
use crate::routes::{
|
||||
self,
|
||||
INVITE_CREATE,
|
||||
CHANNELS_LIST, CHANNELS_CREATE, CHANNELS_DELETE,
|
||||
MESSAGE_SEND,
|
||||
};
|
||||
match path {
|
||||
INVITE_CREATE => Some(CREATE_TMP_INVITES),
|
||||
|
||||
CHANNELS_LIST => None,
|
||||
CHANNELS_CREATE => Some(CREATE_CHANNEL),
|
||||
|
||||
CHANNELS_DELETE => Some(DELETE_CHANNEL),
|
||||
|
||||
MESSAGE_SEND => Some(SEND_MESSAGES),
|
||||
|
||||
routes::ADD_NEIGHBOR => Some(ADD_NEIGHBOR),
|
||||
_ => Some(0)
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,20 @@ pub const SELF_UPDATE_NICKNAME: Rstr= "/members/me/nickname";
|
||||
pub const SET_PERMS_BY_ADMIN: Rstr = "/admin/setpermisions"; // @requires perms::ADMIN
|
||||
pub const SET_NEW_ADMIN: Rstr = "/owner/newadmin"; // @requiers: owner perms
|
||||
|
||||
// Server -> Server Routes
|
||||
pub const GET_NEIGHBORS: Rstr = "/neighbor/list"; // @requires: none @note must be a member for this list
|
||||
pub const ADD_NEIGHBOR: Rstr = "/neighbor/add"; // @requires: perm::add_neighbor
|
||||
pub const UPDATE_NEIGHBOR: Rstr = "/neighbor/update"; // @requires perms::add_neighbor @url(unique)
|
||||
pub const REMOVE_NEIGHBOR: Rstr = "/neighbor/delete"; // @requires perms::add_neighbor @url(unique)
|
||||
|
||||
pub fn is_open(path: &str) -> bool {
|
||||
return path.starts_with("/join") || path.starts_with("/meta");
|
||||
}
|
||||
|
||||
pub fn requires_perms(path: &str) -> bool {
|
||||
return match path {
|
||||
/* These routes _don't_ require any permissions */
|
||||
AUTH_LOGIN | META | CHANNELS_LIST | GET_MYSELF | GET_NEIGHBORS => false,
|
||||
_ => true
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,10 @@
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn get_pool() -> mysql_async::Pool {
|
||||
use dotenv::dotenv;
|
||||
// NOTE: this assumes that DATABASE_URL has been set in the environment
|
||||
// prior to running
|
||||
use mysql_async::Pool;
|
||||
|
||||
dotenv().ok();
|
||||
return Pool::new(&std::env::var("DATABASE_URL").unwrap())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user