diff --git a/.circleci/config.yml b/.circleci/config.yml index 3dc3e66b3..74bf897d9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -101,7 +101,9 @@ jobs: - run: name: Prepare database command: | - sleep 10 + while true; do + if pg_isready -qh localhost; then break; fi + done diesel migration run \ --database-url postgres://username:@localhost/database - run: diff --git a/.gitignore b/.gitignore index b3cf12852..d133c17b4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ target/ .*/target/ **/*.rs.bk *.tar +.gdb_history diff --git a/.rustfmt.toml b/.rustfmt.toml index ead68ee63..132a08e01 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,6 +1,6 @@ condense_wildcard_suffixes = true format_strings = true -max_width = 120 +max_width = 100 merge_imports = true newline_style = "Unix" normalize_comments = true diff --git a/Cargo.lock b/Cargo.lock index d737c46c3..6a2178f14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [[package]] name = "actix" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix_derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -31,20 +31,20 @@ name = "actix-web" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -175,7 +175,7 @@ name = "base64" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -184,7 +184,7 @@ name = "base64" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -193,7 +193,7 @@ name = "bincode" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -232,7 +232,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.3" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -240,7 +240,7 @@ name = "bytes" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -414,7 +414,7 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "diesel_derives 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "pq-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "r2d2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -559,7 +559,7 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -619,10 +619,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "h2" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -691,7 +691,6 @@ dependencies = [ "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -699,7 +698,7 @@ dependencies = [ [[package]] name = "hyper-tls" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -812,7 +811,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -830,14 +829,6 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "log" version = "0.4.3" @@ -1098,7 +1089,7 @@ name = "phf_shared" version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1183,16 +1174,6 @@ dependencies = [ "scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand" version = "0.4.2" @@ -1290,14 +1271,14 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "libflate 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1419,7 +1400,7 @@ name = "serde_cbor" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1461,12 +1442,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "siphasher" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "slab" -version = "0.3.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1474,11 +1450,6 @@ name = "slab" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "smallvec" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "smallvec" version = "0.6.3" @@ -1601,11 +1572,6 @@ dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "take" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "tempdir" version = "0.3.7" @@ -1735,23 +1701,6 @@ dependencies = [ "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "tokio-proto" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "tokio-reactor" version = "0.1.2" @@ -1861,7 +1810,7 @@ name = "trust-dns-proto" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2022,7 +1971,7 @@ dependencies = [ name = "webapp-backend" version = "0.1.0" dependencies = [ - "actix 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "actix-web 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "diesel 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2035,12 +1984,13 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)", "r2d2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_cbor 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "webapp 0.3.0", ] @@ -2056,6 +2006,7 @@ dependencies = [ "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "stdweb 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "webapp 0.3.0", "yew 0.5.0 (git+https://github.com/DenisKolodin/yew)", ] @@ -2146,7 +2097,7 @@ dependencies = [ ] [metadata] -"checksum actix 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ce3cde6db6c8f7a3baa14614d634c06743ba64361f360919e3a9c697a1432098" +"checksum actix 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0470f5163ac229ed0329f6abbd6f775591b06ec5ecbf2f2589c16ab8bd6f76b8" "checksum actix-web 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1bf2bc88dea9c852b9e2fc1c509a422907e05e83d06bef510e8f493b3396f01a" "checksum actix_derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b9d1525ef45e5e021f0b93dace157dcab5d792acb4cc78f3213787d65e2bb92" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" @@ -2167,7 +2118,7 @@ dependencies = [ "checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" "checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" -"checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" +"checksum byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8389c509ec62b9fe8eca58c502a0acaf017737355615243496cde4994f8fa4f9" "checksum bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e178b8e0e239e844b083d5a0d4a156b2654e67f9f80144d48398fcd736a24fb8" "checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275" "checksum cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efe5c877e17a9c717a0bf3613b2709f723202c4e4675cc8f12926ded29bcb17e" @@ -2205,7 +2156,7 @@ dependencies = [ "checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" "checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" -"checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" +"checksum flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "37847f133aae7acf82bb9577ccd8bda241df836787642654286e79679826a54b" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" @@ -2214,14 +2165,14 @@ dependencies = [ "checksum futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "884dbe32a6ae4cd7da5c6db9b78114449df9953b8d490c9d7e1b51720b922c62" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" -"checksum h2 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6229ac66d3392dd83288fe04defd4b353354b15bbe07820d53dda063a736afcc" +"checksum h2 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "35754349586639c6ff629abd19a605e5a42599b0da4aff7be67d63e48ef1ba4e" "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" "checksum http 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0d7f7b919d476c052ff46833ac89aaf205726da8133dae61facad50ec4c9eaec" "checksum httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7b6288d7db100340ca12873fd4d08ad1b8f206a9457798dfb17c018a33fee540" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" "checksum hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)" = "34a590ca09d341e94cddf8e5af0bbccde205d5fbc2fa3c09dd67c7f85cea59d7" -"checksum hyper-tls 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a5aa51f6ae9842239b0fac14af5f22123b8432b4cc774a44ff059fcba0f675ca" +"checksum hyper-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffb1bd5e518d3065840ab315dbbf44e4420e5f7d80e2cb93fa6ffffc50522378" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08173ba1e906efb6538785a8844dd496f5d34f0a2d88038e95195172fc667220" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" @@ -2238,7 +2189,6 @@ dependencies = [ "checksum libflate 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "7d4b4c7aff5bac19b956f693d0ea0eade8066deb092186ae954fa6ba14daab98" "checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" "checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "61bd98ae7f7b754bc53dca7d44b604f733c6bba044ea6f41bc8d89272d8161d2" "checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" "checksum matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "835511bab37c34c47da5cb44844bea2cfde0236db0b506f90ea4224482c9774a" @@ -2279,7 +2229,6 @@ dependencies = [ "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b71f9f575d55555aa9c06188be9d4e2bfc83ed02537948ac0d520c24d0419f1a" "checksum r2d2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f9078ca6a8a5568ed142083bb2f7dc9295b69d16f867ddcc9849e51b17d8db46" -"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "12397506224b2f93e6664ffc4f664b29be8208e5157d3d90b44f09b5fae470ea" "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" @@ -2291,7 +2240,7 @@ dependencies = [ "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2abe46f8e00792693a2488e296c593d1f4ea39bb1178cfce081d6793657575e4" +"checksum reqwest 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e7e237e32c3bfa55c95e29af872c8f481471d70b8a5ec15d85f4d274ffd92dd9" "checksum resolv-conf 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c62bd95a41841efdf7fca2ae9951e64a8d8eae7e5da196d8ce489a2241491a92" "checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" @@ -2310,10 +2259,8 @@ dependencies = [ "checksum serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c6908c7b925cd6c590358a4034de93dbddb20c45e1d021931459fd419bf0e2" "checksum serde_urlencoded 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e703cef904312097cfceab9ce131ff6bbe09e8c964a0703345a5f49238757bc1" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" -"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" +"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" -"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" "checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8" "checksum socket2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "962a516af4d3a7c272cb3a1d50a8cc4e5b41802e4ad54cfb7bee8ba61d37d703" "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa" @@ -2327,7 +2274,6 @@ dependencies = [ "checksum syn 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4bad7abdf6633f07c7046b90484f1d9dc055eca39f8c991177b1046ce61dba9a" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" -"checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "722426c4a0539da2c4ffd9b419d90ad540b4cff4a053be9069c908d4d07e2836" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" @@ -2340,7 +2286,6 @@ dependencies = [ "checksum tokio-fs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "40697ecbea5660df15b15d50a077386477d2f6a35002adf01ce76ff9dd9dce48" "checksum tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a5c9635ee806f26d302b8baa1e145689a280d8f5aa8d0552e7344808da54cc21" "checksum tokio-openssl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4646ae1fd623393de3d796ea53af75acd02938dd5579544fbd6d236d041978a6" -"checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" "checksum tokio-reactor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e00ec63bbec2c97ce1178cb0587b2c438b2f6b09d3ee54a33c45a9cf0d530810" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" "checksum tokio-signal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "342d088c63623f63eada591e065778038c63b516939530db2aa09a8df9118507" diff --git a/Config.toml b/Config.toml index 47a5e0bf4..d09c19cbc 100644 --- a/Config.toml +++ b/Config.toml @@ -1,7 +1,11 @@ [server] -ip = "127.0.0.1" -port = "30080" -tls = false +url = "http://127.0.0.1:30080" +cert = "backend/tls/cert.pem" +key = "backend/tls/key.pem" +redirect-from = [ + "http://127.0.0.1:30081", + "https://127.0.0.1:30082", +] [log] actix-web = "debug" @@ -12,8 +16,3 @@ host = "127.0.0.1" username = "username" password = "" database = "database" - -[api] -login-credentials = "/login/credentials" -login-session = "/login/session" -logout = "/logout" diff --git a/Makefile b/Makefile index 9586a1a32..109b8a4ec 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ build-frontend: cargo web build $(FRONTEND_ARGS) coverage: - cd backend && cargo kcov -v + cd backend && cargo kcov deploy: # Deploy the frontend @@ -93,9 +93,7 @@ run-postgres: -p 5432:5432 \ -d postgres ;\ while true; do \ - if docker logs postgres 2>&1 | grep -q "PostgreSQL init process complete"; then \ - break ;\ - fi \ + if pg_isready -qh $(PG_HOST); then break; fi \ done ;\ sleep 1; \ diesel migration run --database-url \ diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 1ec4d84d1..b9ca1dd1c 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -20,10 +20,10 @@ path = "src/main.rs" [dev-dependencies] lazy_static = "1.0.2" -reqwest = "0.8.6" +reqwest = "0.8.7" [dependencies] -actix = "0.7.2" +actix = "0.7.3" actix-web = { version = "=0.7.1", features = ["alpn"] } bytes = "0.4.9" diesel = { version = "1.3.2", features = ["r2d2", "postgres"] } @@ -40,5 +40,6 @@ serde_cbor = "0.8.2" serde_derive = "1.0.70" time = "0.1.40" toml = "0.4.6" +url = "1.7.1" uuid = { version = "0.6.5", features = ["v4"] } webapp = { path = "..", features = ["backend"] } diff --git a/backend/src/cbor.rs b/backend/src/cbor/mod.rs similarity index 99% rename from backend/src/cbor.rs rename to backend/src/cbor/mod.rs index b0d2ae22d..5f5cf8823 100644 --- a/backend/src/cbor.rs +++ b/backend/src/cbor/mod.rs @@ -1,5 +1,7 @@ //! Cbor abstraction for HTTP message handling +mod test; + use actix_web::{ dev::HttpResponseBuilder, error::{Error as HttpError, PayloadError}, diff --git a/backend/src/cbor/test.rs b/backend/src/cbor/test.rs new file mode 100644 index 000000000..47bce2065 --- /dev/null +++ b/backend/src/cbor/test.rs @@ -0,0 +1,80 @@ +//! The cbor tests + +#![cfg(test)] + +use actix_web::{test::TestRequest, HttpRequest, HttpResponse}; +use cbor::{CborRequest, CborResponseBuilder}; +use failure::Fail; +use futures::Future; +use serde_cbor::to_vec; +use webapp::protocol::{request, response}; + +fn build_request() -> TestRequest<()> { + TestRequest::with_header("content-type", "application/cbor") +} + +#[test] +fn succeed_to_decode_request() { + let login = request::LoginCredentials { + username: "username".to_owned(), + password: "password".to_owned(), + }; + let payload = to_vec(&login).unwrap(); + let request: HttpRequest<()> = build_request().set_payload(payload).finish(); + let result: request::LoginCredentials = CborRequest::new(&request).wait().unwrap(); + assert_eq!(result, login); +} + +#[test] +fn fail_to_decode_empty_request() { + let request: HttpRequest<()> = build_request().finish(); + let result: Result<(), _> = CborRequest::new(&request).wait(); + assert!( + &result + .unwrap_err() + .cause() + .unwrap() + .to_string() + .contains("EOF") + ); +} + +#[test] +fn fail_to_decode_wrong_request() { + let payload: Vec = (1..10).collect(); + let request: HttpRequest<()> = build_request().set_payload(payload).finish(); + let result: Result<(), _> = CborRequest::new(&request).wait(); + assert!( + &result + .unwrap_err() + .cause() + .unwrap() + .to_string() + .contains("invalid type") + ); +} + +#[test] +fn fail_to_decode_wrong_typed_request() { + let login = request::LoginCredentials { + username: "username".to_owned(), + password: "password".to_owned(), + }; + let payload = to_vec(&login).unwrap(); + let request: HttpRequest<()> = build_request().set_payload(payload).finish(); + let result: Result = CborRequest::new(&request).wait(); + assert!( + &result + .unwrap_err() + .cause() + .unwrap() + .to_string() + .contains("missing field") + ); +} + +#[test] +fn succeed_to_encode_response() { + let response = HttpResponse::Ok().cbor(response::Logout); + assert!(response.is_ok()); +} diff --git a/backend/src/http/login_credentials/mod.rs b/backend/src/http/login_credentials/mod.rs index c856a9797..0bd4fcfb4 100644 --- a/backend/src/http/login_credentials/mod.rs +++ b/backend/src/http/login_credentials/mod.rs @@ -2,26 +2,24 @@ use actix::{dev::ToEnvelope, prelude::*}; use actix_web::{error::ErrorUnauthorized, AsyncResponder, HttpRequest, HttpResponse}; -use cbor::{CborRequest, CborResponseBuilder}; +use cbor::CborResponseBuilder; use database::CreateSession; use futures::Future; -use http::FutureResponse; +use http::{unpack_cbor, FutureResponse}; use server::State; use token::Token; use webapp::protocol::{request, response}; -mod tests; +mod test; pub fn login_credentials(http_request: &HttpRequest>) -> FutureResponse where T: Actor + Handler, ::Context: ToEnvelope, { - let request_clone = http_request.clone(); - CborRequest::new(http_request) - .from_err() - // Verify username and password - .and_then(|request::LoginCredentials{username, password}| { + let (request_clone, cbor) = unpack_cbor(http_request); + // Verify username and password + cbor.and_then(|request::LoginCredentials{username, password}| { debug!("User {} is trying to login", username); if username.is_empty() || password.is_empty() || username != password { return Err(ErrorUnauthorized("wrong username or password")); diff --git a/backend/src/http/login_credentials/tests.rs b/backend/src/http/login_credentials/test.rs similarity index 79% rename from backend/src/http/login_credentials/tests.rs rename to backend/src/http/login_credentials/test.rs index 993677355..1bfda815b 100644 --- a/backend/src/http/login_credentials/tests.rs +++ b/backend/src/http/login_credentials/test.rs @@ -8,7 +8,7 @@ use database::CreateSession; use failure::Error; use http::{ login_credentials::login_credentials, - tests::{execute_request, state, DatabaseExecutorMock}, + test::{execute_request, state, DatabaseExecutorMock}, }; use serde_cbor::to_vec; use token::Token; @@ -59,3 +59,18 @@ fn fail_to_login_with_wrong_credentials() { // Then assert_eq!(response.status().is_success(), false); } + +#[test] +fn fail_to_login_with_invalid_cbor() { + // Given + #[derive(Serialize)] + struct Invalid; + let mut server = create_testserver(); + let body = to_vec(&Invalid).unwrap(); + + // When + let response = execute_request(&mut server, body); + + // Then + assert_eq!(response.status().is_success(), false); +} diff --git a/backend/src/http/login_session/mod.rs b/backend/src/http/login_session/mod.rs index 73e8e3698..ce36ca7dc 100644 --- a/backend/src/http/login_session/mod.rs +++ b/backend/src/http/login_session/mod.rs @@ -2,26 +2,24 @@ use actix::{dev::ToEnvelope, prelude::*}; use actix_web::{AsyncResponder, HttpRequest, HttpResponse}; -use cbor::{CborRequest, CborResponseBuilder}; +use cbor::CborResponseBuilder; use database::UpdateSession; use futures::Future; -use http::FutureResponse; +use http::{unpack_cbor, FutureResponse}; use server::State; use token::Token; use webapp::protocol::{model::Session, request, response}; -mod tests; +mod test; pub fn login_session(http_request: &HttpRequest>) -> FutureResponse where T: Actor + Handler, ::Context: ToEnvelope, { - let request_clone = http_request.clone(); - CborRequest::new(http_request) - .from_err() - // Create a new token for the already given one - .and_then(|request::LoginSession(Session{token})| { + let (request_clone, cbor) = unpack_cbor(http_request); + // Create a new token for the already given one + cbor.and_then(|request::LoginSession(Session{token})| { debug!("Session token {} wants to be renewed", token); Ok((Token::verify(&token)?, token)) }) diff --git a/backend/src/http/login_session/tests.rs b/backend/src/http/login_session/test.rs similarity index 78% rename from backend/src/http/login_session/tests.rs rename to backend/src/http/login_session/test.rs index 02b93ca20..4e2b929b9 100644 --- a/backend/src/http/login_session/tests.rs +++ b/backend/src/http/login_session/test.rs @@ -8,7 +8,7 @@ use database::UpdateSession; use failure::Error; use http::{ login_session::login_session, - tests::{execute_request, state, DatabaseExecutorMock}, + test::{execute_request, state, DatabaseExecutorMock}, }; use serde_cbor::to_vec; use token::Token; @@ -56,3 +56,18 @@ fn fail_to_login_with_wrong_session() { // Then assert_eq!(response.status().is_success(), false); } + +#[test] +fn fail_to_login_with_invalid_cbor() { + // Given + #[derive(Serialize)] + struct Invalid; + let mut server = create_testserver(); + let body = to_vec(&Invalid).unwrap(); + + // When + let response = execute_request(&mut server, body); + + // Then + assert_eq!(response.status().is_success(), false); +} diff --git a/backend/src/http/logout/mod.rs b/backend/src/http/logout/mod.rs index ccaec0fe4..973a16625 100644 --- a/backend/src/http/logout/mod.rs +++ b/backend/src/http/logout/mod.rs @@ -2,35 +2,32 @@ use actix::{dev::ToEnvelope, prelude::*}; use actix_web::{AsyncResponder, HttpRequest, HttpResponse}; -use cbor::{CborRequest, CborResponseBuilder}; +use cbor::CborResponseBuilder; use database::DeleteSession; use futures::Future; -use http::FutureResponse; +use http::{unpack_cbor, FutureResponse}; use server::State; use webapp::protocol::{model::Session, request, response}; -mod tests; +mod test; pub fn logout(http_request: &HttpRequest>) -> FutureResponse where T: Actor + Handler, ::Context: ToEnvelope, { - let request_clone = http_request.clone(); - CborRequest::new(http_request) - .from_err() - // Remove the session from the database - .and_then(move |request::Logout(Session{token})| { - debug!("Session token {} wants to be logged out", token); - request_clone - .state() - .database - .send(DeleteSession(token)) - .from_err() - .and_then(|result| { - result?; - Ok(HttpResponse::Ok().cbor(response::Logout)?) - }) - }) - .responder() + let (request_clone, cbor) = unpack_cbor(http_request); + // Remove the session from the database + cbor.and_then(move |request::Logout(Session { token })| { + debug!("Session token {} wants to be logged out", token); + request_clone + .state() + .database + .send(DeleteSession(token)) + .from_err() + .and_then(|result| { + result?; + Ok(HttpResponse::Ok().cbor(response::Logout)?) + }) + }).responder() } diff --git a/backend/src/http/logout/tests.rs b/backend/src/http/logout/test.rs similarity index 69% rename from backend/src/http/logout/tests.rs rename to backend/src/http/logout/test.rs index 6b0328d17..dcde5f463 100644 --- a/backend/src/http/logout/tests.rs +++ b/backend/src/http/logout/test.rs @@ -8,7 +8,7 @@ use database::DeleteSession; use failure::Error; use http::{ logout::logout, - tests::{execute_request, state, DatabaseExecutorMock}, + test::{execute_request, state, DatabaseExecutorMock}, }; use serde_cbor::to_vec; use webapp::protocol::{model::Session, request}; @@ -39,3 +39,18 @@ fn succeed_to_logout() { // Then assert!(response.status().is_success()); } + +#[test] +fn fail_to_logout_with_invalid_cbor() { + // Given + #[derive(Serialize)] + struct Invalid; + let mut server = create_testserver(); + let body = to_vec(&Invalid).unwrap(); + + // When + let response = execute_request(&mut server, body); + + // Then + assert_eq!(response.status().is_success(), false); +} diff --git a/backend/src/http/mod.rs b/backend/src/http/mod.rs index 26c6d7ad1..8fddbdb91 100644 --- a/backend/src/http/mod.rs +++ b/backend/src/http/mod.rs @@ -3,11 +3,33 @@ pub mod login_credentials; pub mod login_session; pub mod logout; -mod tests; +mod test; -pub use http::{login_credentials::login_credentials, login_session::login_session, logout::logout}; - -use actix_web::{error::Error, HttpResponse}; -use futures::Future; +use actix::{dev::ToEnvelope, prelude::*}; +use actix_web::{error::Error, HttpRequest, HttpResponse}; +use cbor::CborRequest; +use futures::{future::FromErr, Future}; +pub use http::{ + login_credentials::login_credentials, login_session::login_session, logout::logout, +}; +use serde::de::DeserializeOwned; +use server::State; +/// The generic response pub type FutureResponse = Box>; + +/// Cbor unpacking helper, also returns a clone of the request reference +pub fn unpack_cbor( + http_request: &HttpRequest>, +) -> (HttpRequest>, FromErr, Error>) +where + M: Message, + D: DeserializeOwned + 'static, + A: Actor + Handler, + ::Context: ToEnvelope, +{ + ( + http_request.clone(), + CborRequest::new(http_request).from_err(), + ) +} diff --git a/backend/src/http/tests.rs b/backend/src/http/test.rs similarity index 100% rename from backend/src/http/tests.rs rename to backend/src/http/test.rs diff --git a/backend/src/lib.rs b/backend/src/lib.rs index a4c3a6dea..ec570bace 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -20,6 +20,7 @@ extern crate serde_cbor; #[macro_use] extern crate serde_derive; extern crate time; +extern crate url; extern crate uuid; extern crate webapp; diff --git a/backend/src/main.rs b/backend/src/main.rs index cd7a9e727..839738468 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -17,7 +17,10 @@ fn main() -> Result<(), Error> { // Set the logging verbosity set_var( "RUST_LOG", - format!("actix_web={},webapp={}", config.log.actix_web, config.log.webapp), + format!( + "actix_web={},webapp={}", + config.log.actix_web, config.log.webapp + ), ); // Initialize the logger diff --git a/backend/src/server/mod.rs b/backend/src/server/mod.rs index ddae3254b..3abd4ea9f 100644 --- a/backend/src/server/mod.rs +++ b/backend/src/server/mod.rs @@ -3,24 +3,32 @@ use actix::{prelude::*, SystemRunner}; use actix_web::{ fs::StaticFiles, - http::{self, header::CONTENT_TYPE}, + http::{ + self, + header::{CONTENT_TYPE, LOCATION}, + NormalizePath, + }, middleware::{self, cors::Cors}, - server, App, + server, App, HttpResponse, }; use database::DatabaseExecutor; use diesel::{prelude::*, r2d2::ConnectionManager}; use failure::Error; use http::{login_credentials, login_session, logout}; use num_cpus; -use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; +use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; use r2d2::Pool; -use webapp::config::Config; +use std::thread; +use url::Url; +use webapp::{config::Config, API_URL_LOGIN_CREDENTIALS, API_URL_LOGIN_SESSION, API_URL_LOGOUT}; -mod tests; +mod test; /// The server instance pub struct Server { + config: Config, runner: SystemRunner, + url: Url, } /// Shared mutable application state @@ -41,14 +49,16 @@ impl Server { // Start database executor actors let database_url = format!( "postgres://{}:{}@{}/{}", - config.postgres.username, config.postgres.password, config.postgres.host, config.postgres.database, + config.postgres.username, + config.postgres.password, + config.postgres.host, + config.postgres.database, ); let manager = ConnectionManager::::new(database_url); let pool = Pool::builder().build(manager)?; let db_addr = SyncArbiter::start(num_cpus::get(), move || DatabaseExecutor(pool.clone())); // Create the server - let config_clone = config.clone(); let server = server::new(move || { App::with_state(State { database: db_addr.clone(), @@ -58,33 +68,100 @@ impl Server { .allowed_methods(vec!["GET", "POST"]) .allowed_header(CONTENT_TYPE) .max_age(3600) - .resource(&config_clone.api.login_credentials, |r| { + .resource(API_URL_LOGIN_CREDENTIALS, |r| { r.method(http::Method::POST).f(login_credentials) - }).resource(&config_clone.api.login_session, |r| { + }).resource(API_URL_LOGIN_SESSION, |r| { r.method(http::Method::POST).f(login_session) - }).resource(&config_clone.api.logout, |r| r.method(http::Method::POST).f(logout)) + }).resource(API_URL_LOGOUT, |r| r.method(http::Method::POST).f(logout)) .register() - }).handler("/", StaticFiles::new(".").unwrap().index_file("index.html")) + }).default_resource(|r| r.h(NormalizePath::default())) + .handler("/", StaticFiles::new(".").unwrap().index_file("index.html")) }); // Create the server url from the given configuration - let server_url = format!("{}:{}", config.server.ip, config.server.port); - - // Load the SSL Certificate if needed - if config.server.tls { - let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls())?; - builder.set_private_key_file("tls/key.pem", SslFiletype::PEM)?; - builder.set_certificate_chain_file("tls/crt.pem")?; - server.bind_ssl(server_url, builder)?.shutdown_timeout(0).start(); + let url = Url::parse(&config.server.url)?; + + // Bind the address + if url.scheme() == "https" { + server.bind_ssl(&url, Self::build_tls(&config)?)?.start(); } else { - server.bind(server_url)?.shutdown_timeout(0).start(); + server.bind(&url)?.start(); } - Ok(Server { runner }) + Ok(Server { + config: config.to_owned(), + runner, + url, + }) } /// Start the server pub fn start(self) -> i32 { + // Start the redirecting server + self.start_redirects(); + + // Start the actual main server self.runner.run() } + + /// Build an SslAcceptorBuilder from a config + fn build_tls(config: &Config) -> Result { + let mut tls_builder = SslAcceptor::mozilla_intermediate(SslMethod::tls())?; + tls_builder.set_private_key_file(&config.server.key, SslFiletype::PEM)?; + tls_builder.set_certificate_chain_file(&config.server.cert)?; + Ok(tls_builder) + } + + fn start_redirects(&self) { + // Check if we need to create a redirecting server + if !self.config.server.redirect_from.is_empty() { + // Prepare needed variables + let server_url = self.url.clone(); + let urls = self.config.server.redirect_from.to_owned(); + let config_clone = self.config.clone(); + + // Create a separate thread for redirecting + thread::spawn(move || { + let system = actix::System::new("redirect"); + let url = server_url.clone(); + + // Create redirecting server + let mut server = server::new(move || { + let location = url.clone(); + App::new().default_resource(|r| { + r.f(move |_| { + HttpResponse::PermanentRedirect() + .header(LOCATION, location.as_str()) + .finish() + }) + }) + }); + + // Bind the URLs if possible + for url in &urls { + if let Ok(valid_url) = Url::parse(url) { + info!( + "Starting server to redirect from {} to {}", + valid_url, server_url + ); + if valid_url.scheme() == "https" { + if let Ok(tls) = Self::build_tls(&config_clone) { + server = server.bind_ssl(&valid_url, tls).unwrap(); + } else { + warn!("Unable to build TLS acceptor for server: {}", valid_url); + } + } else { + server = server.bind(&valid_url).unwrap(); + } + } else { + warn!("Skipping invalid url: {}", url); + } + } + + // Start the server and the system + server.start(); + system.run(); + }); + } + } } diff --git a/backend/src/server/test.rs b/backend/src/server/test.rs new file mode 100644 index 000000000..ae29556f8 --- /dev/null +++ b/backend/src/server/test.rs @@ -0,0 +1,43 @@ +//! The Server tests + +#![cfg(test)] + +extern crate toml; + +use server::Server; +use std::fs::read_to_string; +use webapp::{config::Config, CONFIG_FILENAME}; + +fn get_config() -> Config { + toml::from_str(&read_to_string(format!("../{}", CONFIG_FILENAME)).unwrap()).unwrap() +} + +#[test] +fn succeed_to_create_a_server() { + assert!(Server::new(&get_config()).is_ok()); +} + +#[test] +fn fail_to_create_a_server_with_wrong_url() { + let mut config = get_config(); + config.server.url = "".to_owned(); + assert!(Server::new(&config).is_err()); +} + +#[test] +fn succeed_to_create_a_server_with_tls() { + let mut config = get_config(); + config.server.url = "https://localhost:30081".to_owned(); + config.server.cert = "tls/cert.pem".to_owned(); + config.server.key = "tls/key.pem".to_owned(); + assert!(Server::new(&config).is_ok()); +} + +#[test] +fn fail_to_create_a_server_with_tls_if_not_found() { + let mut config = get_config(); + config.server.url = "https://localhost:30082".to_owned(); + config.server.cert = "".to_owned(); + config.server.key = "".to_owned(); + assert!(Server::new(&config).is_err()); +} diff --git a/backend/src/server/tests.rs b/backend/src/server/tests.rs deleted file mode 100644 index 64e7d2062..000000000 --- a/backend/src/server/tests.rs +++ /dev/null @@ -1,32 +0,0 @@ -//! The Server tests - -#![cfg(test)] - -extern crate toml; - -use server::Server; -use std::fs::read_to_string; -use webapp::{config::Config, CONFIG_FILENAME}; - -fn get_config() -> Config { - toml::from_str(&read_to_string(format!("../{}", CONFIG_FILENAME)).unwrap()).unwrap() -} - -#[test] -fn succeed_to_create_a_server() { - assert!(Server::new(&get_config()).is_ok()); -} - -#[test] -fn fail_to_create_a_server_with_wrong_addr() { - let mut config = get_config(); - config.server.ip = "".to_owned(); - assert!(Server::new(&config).is_err()); -} - -#[test] -fn fail_to_create_a_server_with_wrong_port() { - let mut config = get_config(); - config.server.port = "-1".to_owned(); - assert!(Server::new(&config).is_err()); -} diff --git a/backend/src/token/mod.rs b/backend/src/token/mod.rs index aa4ede03c..6196b8cab 100644 --- a/backend/src/token/mod.rs +++ b/backend/src/token/mod.rs @@ -5,7 +5,7 @@ use jsonwebtoken::{decode, encode, Header, Validation}; use time::get_time; use uuid::Uuid; -mod tests; +mod test; const SECRET: &[u8] = b"my_secret"; @@ -61,7 +61,8 @@ impl Token { /// Verify the validity of a token and get a new one pub fn verify(token: &str) -> Result { - let data = decode::(token, SECRET, &Validation::default()).map_err(|_| TokenError::Verify)?; + let data = decode::(token, SECRET, &Validation::default()) + .map_err(|_| TokenError::Verify)?; Self::create(&data.claims.sub) } } diff --git a/backend/src/token/tests.rs b/backend/src/token/test.rs similarity index 100% rename from backend/src/token/tests.rs rename to backend/src/token/test.rs diff --git a/backend/tests/server.rs b/backend/tests/server.rs index f63c5aeeb..9f0759e05 100644 --- a/backend/tests/server.rs +++ b/backend/tests/server.rs @@ -3,56 +3,97 @@ extern crate lazy_static; extern crate reqwest; extern crate serde_cbor; extern crate toml; +extern crate url; extern crate webapp; extern crate webapp_backend; use reqwest::{Client, StatusCode}; use serde_cbor::{from_slice, to_vec}; use std::{fs::read_to_string, sync::Mutex, thread, time::Duration}; +use url::Url; use webapp::{ config::Config, protocol::{model::Session, request, response}, - CONFIG_FILENAME, + API_URL_LOGIN_CREDENTIALS, API_URL_LOGIN_SESSION, API_URL_LOGOUT, CONFIG_FILENAME, }; use webapp_backend::Server; lazy_static! { - static ref PORT: Mutex = Mutex::new(30000); + static ref PORT: Mutex = Mutex::new(30000); } -fn create_testserver() -> (String, Config) { - // Create the server thread +fn parse_config() -> Config { let config_string = read_to_string(format!("../{}", CONFIG_FILENAME)).unwrap(); - let mut config: Config = toml::from_str(&config_string).unwrap(); + toml::from_str(&config_string).unwrap() +} + +fn get_next_port() -> u16 { let mut port = PORT.lock().unwrap(); *port += 1; - config.server.port = port.to_string(); - config.server.tls = false; + *port +} + +fn create_testserver() -> Url { + // Prepare the configuration + let mut config = parse_config(); + // Set the test configuration + let mut url = Url::parse(&config.server.url).unwrap(); + url.set_port(Some(get_next_port())).unwrap(); + config.server.url = url.as_str().to_owned(); + config.server.redirect_from = vec![]; + + // Start the server let config_clone = config.clone(); thread::spawn(move || Server::new(&config_clone).unwrap().start()); // Wait until the server is up thread::sleep(Duration::from_millis(300)); - (format!("http://{}:{}", config.server.ip, config.server.port), config) + // Return the server url + url +} + +#[test] +fn succeed_to_create_server_with_common_redirects() { + // Given + let mut config = parse_config(); + let mut url = Url::parse(&config.server.url).unwrap(); + url.set_port(Some(get_next_port())).unwrap(); + config.server.url = url.as_str().to_owned(); + config.server.cert = "tls/cert.pem".to_owned(); + config.server.key = "tls/key.pem".to_owned(); + + let redirect_url = "http://127.0.0.1:30666".to_owned(); + config.server.redirect_from = vec![ + redirect_url.clone(), + "https://localhost:30667".to_owned(), + "invalid".to_owned(), + ]; + + // When + let config_clone = config.clone(); + thread::spawn(move || Server::new(&config_clone).unwrap().start()); + thread::sleep(Duration::from_millis(300)); + let res = Client::new().get(&redirect_url).send().unwrap(); + + // Then + assert_eq!(res.url().as_str().contains(&redirect_url), false); } #[test] fn succeed_to_login_with_credentials() { // Given - let (url, config) = create_testserver(); + let mut url = create_testserver(); + url.set_path(API_URL_LOGIN_CREDENTIALS); // When let request = to_vec(&request::LoginCredentials { username: "username".to_owned(), password: "username".to_owned(), }).unwrap(); - let mut res = Client::new() - .post(&(url + &config.api.login_credentials)) - .body(request) - .send() - .unwrap(); + println!("::: url:: {}", url); + let mut res = Client::new().post(url).body(request).send().unwrap(); let mut body = vec![]; res.copy_to(&mut body).unwrap(); let response::Login(session) = from_slice(&body).unwrap(); @@ -65,18 +106,15 @@ fn succeed_to_login_with_credentials() { #[test] fn fail_to_login_with_wrong_credentials() { // Given - let (url, config) = create_testserver(); + let mut url = create_testserver(); + url.set_path(API_URL_LOGIN_CREDENTIALS); // When let request = to_vec(&request::LoginCredentials { username: "username".to_owned(), password: "password".to_owned(), }).unwrap(); - let res = Client::new() - .post(&(url + &config.api.login_credentials)) - .body(request) - .send() - .unwrap(); + let res = Client::new().post(url).body(request).send().unwrap(); // Then assert_eq!(res.status(), StatusCode::Unauthorized); @@ -85,7 +123,8 @@ fn fail_to_login_with_wrong_credentials() { #[test] fn succeed_to_login_with_session() { // Given - let (url, config) = create_testserver(); + let mut url = create_testserver(); + url.set_path(API_URL_LOGIN_CREDENTIALS); // When let mut request = to_vec(&request::LoginCredentials { @@ -93,7 +132,7 @@ fn succeed_to_login_with_session() { password: "username".to_owned(), }).unwrap(); let mut res = Client::new() - .post(&(url.clone() + &config.api.login_credentials)) + .post(url.clone()) .body(request) .send() .unwrap(); @@ -102,11 +141,8 @@ fn succeed_to_login_with_session() { let response::Login(session) = from_slice(&body).unwrap(); request = to_vec(&request::LoginSession(session)).unwrap(); - res = Client::new() - .post(&(url + &config.api.login_session)) - .body(request) - .send() - .unwrap(); + url.set_path(API_URL_LOGIN_SESSION); + res = Client::new().post(url).body(request).send().unwrap(); body.clear(); res.copy_to(&mut body).unwrap(); let response::Login(new_session) = from_slice(&body).unwrap(); @@ -119,17 +155,14 @@ fn succeed_to_login_with_session() { #[test] fn fail_to_login_with_wrong_session() { // Given - let (url, config) = create_testserver(); + let mut url = create_testserver(); + url.set_path(API_URL_LOGIN_SESSION); // When let request = to_vec(&request::LoginSession(Session { token: "wrong".to_owned(), })).unwrap(); - let res = Client::new() - .post(&(url + &config.api.login_session)) - .body(request) - .send() - .unwrap(); + let res = Client::new().post(url).body(request).send().unwrap(); // Then assert_eq!(res.status(), StatusCode::Unauthorized); @@ -138,17 +171,14 @@ fn fail_to_login_with_wrong_session() { #[test] fn succeed_to_logout() { // Given - let (url, config) = create_testserver(); + let mut url = create_testserver(); + url.set_path(API_URL_LOGOUT); // When let request = to_vec(&request::Logout(Session { token: "wrong".to_owned(), })).unwrap(); - let res = Client::new() - .post(&(url + &config.api.logout)) - .body(request) - .send() - .unwrap(); + let res = Client::new().post(url).body(request).send().unwrap(); // Then assert!(res.status().is_success()); diff --git a/backend/tls/crt.pem b/backend/tls/cert.pem similarity index 100% rename from backend/tls/crt.pem rename to backend/tls/cert.pem diff --git a/frontend/Cargo.toml b/frontend/Cargo.toml index e2fd91709..a1ff7bd98 100644 --- a/frontend/Cargo.toml +++ b/frontend/Cargo.toml @@ -22,6 +22,7 @@ path = "src/main.rs" failure = "0.1.1" sass-rs = "0.2.1" toml = "0.4.6" +url = "1.7.1" webapp = { path = ".." } [dependencies] diff --git a/frontend/build.rs b/frontend/build.rs index 30dcc66fe..7ed65f016 100644 --- a/frontend/build.rs +++ b/frontend/build.rs @@ -1,6 +1,7 @@ extern crate failure; extern crate sass_rs; extern crate toml; +extern crate url; extern crate webapp; use failure::Error; @@ -11,6 +12,7 @@ use std::{ path::{Path, PathBuf}, process::Command, }; +use url::Url; use webapp::{config::Config, CONFIG_FILENAME}; const REPOSITORY: &str = "https://github.com/uikit/uikit.git"; @@ -82,20 +84,7 @@ fn prepare_style() -> Result<(), Error> { fn prepare_api() -> Result<(), Error> { let config: Config = toml::from_str(&read_to_string(format!("../{}", CONFIG_FILENAME))?)?; - - let secure_protocol = if config.server.tls { "s" } else { "" }; - let api_url = format!("http{}://{}:{}", secure_protocol, config.server.ip, config.server.port); - - println!("cargo:rustc-env=API_URL={}", api_url); - println!( - "cargo:rustc-env=API_URL_LOGIN_CREDENTIALS={}{}", - api_url, config.api.login_credentials - ); - println!( - "cargo:rustc-env=API_URL_LOGIN_SESSION={}{}", - api_url, config.api.login_session - ); - println!("cargo:rustc-env=API_URL_LOGOUT={}{}", api_url, config.api.logout); - + let url = Url::parse(&config.server.url)?; + println!("cargo:rustc-env=API_URL={}", url); Ok(()) } diff --git a/frontend/src/component/content.rs b/frontend/src/component/content.rs index 3ca8ac56a..dc5e247db 100644 --- a/frontend/src/component/content.rs +++ b/frontend/src/component/content.rs @@ -9,7 +9,10 @@ use service::{ uikit::{NotificationStatus, UIkitService}, }; use string::{REQUEST_ERROR, RESPONSE_ERROR, TEXT_CONTENT, TEXT_LOGOUT}; -use webapp::protocol::{model::Session, request, response}; +use webapp::{ + protocol::{model::Session, request, response}, + API_URL_LOGOUT, +}; use yew::{ format::Cbor, prelude::*, @@ -18,7 +21,6 @@ use yew::{ FetchService, }, }; -use API_URL_LOGOUT; use SESSION_COOKIE; /// Data Model for the Content component @@ -48,7 +50,8 @@ impl Component for ContentComponent { // Guard the authentication let mut router_agent = RouterAgent::bridge(link.send_back(|_| Message::Ignore)); let cookie_service = CookieService::new(); - let mut session_timer_agent = SessionTimerAgent::bridge(link.send_back(|_| Message::Ignore)); + let mut session_timer_agent = + SessionTimerAgent::bridge(link.send_back(|_| Message::Ignore)); if cookie_service.get(SESSION_COOKIE).is_err() { info!("No session token found, routing back to login"); router_agent.send(router::Request::ChangeRoute(RouterTarget::Login.into())); @@ -79,21 +82,26 @@ impl Component for ContentComponent { Message::LogoutRequest => { if let Ok(token) = self.cookie_service.get(SESSION_COOKIE) { // Create the logout request - match fetch::Request::post(API_URL_LOGOUT).body(Cbor(&request::Logout(Session { - token: token.to_owned(), - }))) { + match fetch::Request::post(api!(API_URL_LOGOUT)).body(Cbor(&request::Logout( + Session { + token: token.to_owned(), + }, + ))) { Ok(body) => { // Disable user interaction self.logout_button_disabled = true; // Send the request - self.fetch_task = Some( - FetchService::new().fetch_binary(body, self.component_link.send_back(Message::Fetch)), - ); + self.fetch_task = + Some(FetchService::new().fetch_binary( + body, + self.component_link.send_back(Message::Fetch), + )); } _ => { error!("Unable to create logout request"); - self.uikit_service.notify(REQUEST_ERROR, &NotificationStatus::Danger); + self.uikit_service + .notify(REQUEST_ERROR, &NotificationStatus::Danger); } } } else { @@ -115,7 +123,8 @@ impl Component for ContentComponent { Ok(response::Logout) => info!("Got valid logout response"), _ => { warn!("Got wrong logout response"); - self.uikit_service.notify(RESPONSE_ERROR, &NotificationStatus::Danger); + self.uikit_service + .notify(RESPONSE_ERROR, &NotificationStatus::Danger); } } } else { diff --git a/frontend/src/component/login.rs b/frontend/src/component/login.rs index 2b35f0ed0..412188fa2 100644 --- a/frontend/src/component/login.rs +++ b/frontend/src/component/login.rs @@ -7,8 +7,13 @@ use service::{ router::{self, RouterAgent}, uikit::{NotificationStatus, UIkitService}, }; -use string::{AUTHENTICATION_ERROR, INPUT_PASSWORD, INPUT_USERNAME, REQUEST_ERROR, RESPONSE_ERROR, TEXT_LOGIN}; -use webapp::protocol::{model::Session, request, response}; +use string::{ + AUTHENTICATION_ERROR, INPUT_PASSWORD, INPUT_USERNAME, REQUEST_ERROR, RESPONSE_ERROR, TEXT_LOGIN, +}; +use webapp::{ + protocol::{model::Session, request, response}, + API_URL_LOGIN_CREDENTIALS, +}; use yew::{ format::Cbor, prelude::*, @@ -17,7 +22,6 @@ use yew::{ FetchService, }, }; -use API_URL_LOGIN_CREDENTIALS; use SESSION_COOKIE; /// Data Model for the Login component @@ -71,22 +75,27 @@ impl Component for LoginComponent { match msg { // Login via username and password Message::LoginRequest => { - match fetch::Request::post(API_URL_LOGIN_CREDENTIALS).body(Cbor(&request::LoginCredentials { - username: self.username.to_owned(), - password: self.password.to_owned(), - })) { + match fetch::Request::post(api!(API_URL_LOGIN_CREDENTIALS)).body(Cbor( + &request::LoginCredentials { + username: self.username.to_owned(), + password: self.password.to_owned(), + }, + )) { Ok(body) => { // Disable user interaction self.login_button_disabled = true; self.inputs_disabled = true; // Send the request - self.fetch_task = - Some(FetchService::new().fetch_binary(body, self.component_link.send_back(Message::Fetch))); + self.fetch_task = Some( + FetchService::new() + .fetch_binary(body, self.component_link.send_back(Message::Fetch)), + ); } _ => { error!("Unable to create credentials login request"); - self.uikit_service.notify(REQUEST_ERROR, &NotificationStatus::Danger); + self.uikit_service + .notify(REQUEST_ERROR, &NotificationStatus::Danger); } } } @@ -119,7 +128,8 @@ impl Component for LoginComponent { } _ => { warn!("Got wrong credentials login response"); - self.uikit_service.notify(RESPONSE_ERROR, &NotificationStatus::Danger); + self.uikit_service + .notify(RESPONSE_ERROR, &NotificationStatus::Danger); } } } else { diff --git a/frontend/src/component/root.rs b/frontend/src/component/root.rs index a1f137349..ae01aa381 100644 --- a/frontend/src/component/root.rs +++ b/frontend/src/component/root.rs @@ -9,7 +9,10 @@ use service::{ uikit::{NotificationStatus, UIkitService}, }; use string::{REQUEST_ERROR, RESPONSE_ERROR}; -use webapp::protocol::{model::Session, request, response}; +use webapp::{ + protocol::{model::Session, request, response}, + API_URL_LOGIN_SESSION, +}; use yew::{ format::Cbor, prelude::*, @@ -18,7 +21,6 @@ use yew::{ FetchService, }, }; -use API_URL_LOGIN_SESSION; use SESSION_COOKIE; /// Data Model for the Root Component @@ -49,10 +51,15 @@ impl Component for RootComponent { // Verify if a session cookie already exist and try to authenticate if so if let Ok(token) = cookie_service.get(SESSION_COOKIE) { - match fetch::Request::post(API_URL_LOGIN_SESSION).body(Cbor(&request::LoginSession(Session { - token: token.to_owned(), - }))) { - Ok(body) => fetch_task = Some(FetchService::new().fetch_binary(body, link.send_back(Message::Fetch))), + match fetch::Request::post(api!(API_URL_LOGIN_SESSION)).body(Cbor( + &request::LoginSession(Session { + token: token.to_owned(), + }), + )) { + Ok(body) => { + fetch_task = + Some(FetchService::new().fetch_binary(body, link.send_back(Message::Fetch))) + } Err(_) => { error!("Unable to create session login request"); uikit_service.notify(REQUEST_ERROR, &NotificationStatus::Danger); @@ -104,7 +111,8 @@ impl Component for RootComponent { _ => { // Send an error notification to the user on any failure warn!("Got wrong session login response"); - self.uikit_service.notify(RESPONSE_ERROR, &NotificationStatus::Danger); + self.uikit_service + .notify(RESPONSE_ERROR, &NotificationStatus::Danger); self.router_agent .send(router::Request::ChangeRoute(RouterTarget::Login.into())); } diff --git a/frontend/src/lib.rs b/frontend/src/lib.rs index b30fb61cd..124cadf38 100644 --- a/frontend/src/lib.rs +++ b/frontend/src/lib.rs @@ -16,6 +16,13 @@ extern crate webapp; #[macro_use] extern crate yew; +/// Generic API access macro +macro_rules! api { + ($url:expr) => { + env!("API_URL").to_owned() + $url + }; +} + mod component; mod route; mod service; @@ -26,8 +33,3 @@ pub use service::log::init_logger; /// The global session cookie name const SESSION_COOKIE: &str = "sessionToken"; - -/// The API URLs -const API_URL_LOGIN_CREDENTIALS: &str = env!("API_URL_LOGIN_CREDENTIALS"); -const API_URL_LOGIN_SESSION: &str = env!("API_URL_LOGIN_SESSION"); -const API_URL_LOGOUT: &str = env!("API_URL_LOGOUT"); diff --git a/frontend/src/service/router.rs b/frontend/src/service/router.rs index 007d8640b..a17618a12 100644 --- a/frontend/src/service/router.rs +++ b/frontend/src/service/router.rs @@ -27,7 +27,9 @@ where { /// Creates the route service. pub fn new() -> RouterService { - let location = window().location().expect("browser does not support location API"); + let location = window() + .location() + .expect("browser does not support location API"); Self { history: window().history(), location, @@ -187,7 +189,14 @@ impl Transferable for Request where for<'de> T: Serialize + Deserialize<'d /// access to it. pub struct RouterAgent where - for<'de> T: JsSerialize + Clone + Debug + TryFrom + Default + Serialize + Deserialize<'de> + 'static, + for<'de> T: JsSerialize + + Clone + + Debug + + TryFrom + + Default + + Serialize + + Deserialize<'de> + + 'static, { link: AgentLink>, route_service: RouterService, @@ -199,7 +208,14 @@ where impl Agent for RouterAgent where - for<'de> T: JsSerialize + Clone + Debug + TryFrom + Default + Serialize + Deserialize<'de> + 'static, + for<'de> T: JsSerialize + + Clone + + Debug + + TryFrom + + Default + + Serialize + + Deserialize<'de> + + 'static, { type Input = Request; type Message = Message; diff --git a/frontend/src/service/session_timer.rs b/frontend/src/service/session_timer.rs index d6e6fa618..6328b9a21 100644 --- a/frontend/src/service/session_timer.rs +++ b/frontend/src/service/session_timer.rs @@ -3,7 +3,10 @@ use failure::Error; use service::cookie::CookieService; use std::time::Duration; -use webapp::protocol::{model::Session, request, response}; +use webapp::{ + protocol::{model::Session, request, response}, + API_URL_LOGIN_SESSION, +}; use yew::{ format::Cbor, prelude::{worker::*, *}, @@ -12,7 +15,6 @@ use yew::{ IntervalService, Task, }, }; -use API_URL_LOGIN_SESSION; use SESSION_COOKIE; /// Possible message types @@ -67,12 +69,16 @@ impl Agent for SessionTimerAgent { Message::Update => { info!("Updating current session"); if let Ok(token) = self.cookie_service.get(SESSION_COOKIE) { - match fetch::Request::post(API_URL_LOGIN_SESSION).body(Cbor(&request::LoginSession(Session { - token: token.to_owned(), - }))) { + match fetch::Request::post(api!(API_URL_LOGIN_SESSION)).body(Cbor( + &request::LoginSession(Session { + token: token.to_owned(), + }), + )) { Ok(body) => { - self.fetch_task = - Some(FetchService::new().fetch_binary(body, self.agent_link.send_back(Message::Fetch))) + self.fetch_task = Some( + FetchService::new() + .fetch_binary(body, self.agent_link.send_back(Message::Fetch)), + ) } Err(_) => { warn!("Unable to create scheduled session login request"); @@ -96,7 +102,10 @@ impl Agent for SessionTimerAgent { } } else { // Authentication failed - info!("Scheduled session login failed with status: {}", meta.status); + info!( + "Scheduled session login failed with status: {}", + meta.status + ); } // Remove the ongoing task @@ -109,7 +118,8 @@ impl Agent for SessionTimerAgent { fn handle(&mut self, msg: Self::Input, _: HandlerId) { match msg { Request::Start => { - let handle = IntervalService::new().spawn(Duration::from_secs(10), self.callback.clone()); + let handle = + IntervalService::new().spawn(Duration::from_secs(10), self.callback.clone()); self.timer_task = Some(Box::new(handle)); } Request::Stop => { diff --git a/src/config.rs b/src/config.rs index cc3ce1a82..19b8482d6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,4 +1,4 @@ -//! Configruation related structures +//! Configuration related structures #[derive(Clone, Deserialize)] /// The global configuration @@ -11,22 +11,23 @@ pub struct Config { /// The database configuration pub postgres: PostgresConfig, - - /// The API configuration - pub api: ApiConfig, } #[derive(Clone, Deserialize)] +#[serde(rename_all = "kebab-case")] /// The server configuration pub struct ServerConfig { - /// The server IP address - pub ip: String, + /// The full server url + pub url: String, + + /// The server certificate + pub cert: String, - /// The server port - pub port: String, + /// The server key + pub key: String, - /// True if the server should use a tls connection - pub tls: bool, + /// The redirecting URLs + pub redirect_from: Vec, } #[derive(Clone, Deserialize)] @@ -55,17 +56,3 @@ pub struct PostgresConfig { /// The database to be used pub database: String, } - -#[derive(Clone, Deserialize)] -#[serde(rename_all = "kebab-case")] -/// The API configuration -pub struct ApiConfig { - /// The credentials based login API - pub login_credentials: String, - - /// The session based login API - pub login_session: String, - - /// The logout API - pub logout: String, -} diff --git a/src/lib.rs b/src/lib.rs index 71f88793e..4fa29b343 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,3 +17,12 @@ pub mod schema; /// The global config file name pub const CONFIG_FILENAME: &str = "Config.toml"; + +/// The API URL for login with credentials +pub const API_URL_LOGIN_CREDENTIALS: &str = "login/credentials"; + +/// The API URL for login with session +pub const API_URL_LOGIN_SESSION: &str = "login/session"; + +/// The API URL for logout +pub const API_URL_LOGOUT: &str = "logout"; diff --git a/src/protocol/model.rs b/src/protocol/model.rs index e7f574f4b..62b9f1d70 100644 --- a/src/protocol/model.rs +++ b/src/protocol/model.rs @@ -5,7 +5,7 @@ use schema::sessions; #[cfg_attr(feature = "backend", derive(Insertable, Queryable))] #[cfg_attr(feature = "backend", table_name = "sessions")] -#[derive(Deserialize, Serialize)] +#[derive(Debug, PartialEq, Deserialize, Serialize)] /// A session representation pub struct Session { /// The actual session token diff --git a/src/protocol/request.rs b/src/protocol/request.rs index 9afae732b..2c587a98c 100644 --- a/src/protocol/request.rs +++ b/src/protocol/request.rs @@ -2,7 +2,7 @@ use protocol::model::Session; -#[derive(Deserialize, Serialize)] +#[derive(Debug, PartialEq, Deserialize, Serialize)] /// The credentials based login request pub struct LoginCredentials { /// The username @@ -12,10 +12,10 @@ pub struct LoginCredentials { pub password: String, } -#[derive(Deserialize, Serialize)] +#[derive(Debug, PartialEq, Deserialize, Serialize)] /// The session based login request pub struct LoginSession(pub Session); -#[derive(Deserialize, Serialize)] +#[derive(Debug, PartialEq, Deserialize, Serialize)] /// The logout request pub struct Logout(pub Session); diff --git a/src/protocol/response.rs b/src/protocol/response.rs index 44a6a38d3..0318cf895 100644 --- a/src/protocol/response.rs +++ b/src/protocol/response.rs @@ -2,10 +2,10 @@ use protocol::model::Session; -#[derive(Deserialize, Serialize)] +#[derive(Debug, PartialEq, Deserialize, Serialize)] /// The login response pub struct Login(pub Session); -#[derive(Deserialize, Serialize)] +#[derive(Debug, PartialEq, Deserialize, Serialize)] /// The logout response pub struct Logout;