From e6468b012d5b33dd16992652da57f11dd5a6e82f Mon Sep 17 00:00:00 2001 From: Jokler Date: Sun, 21 Jun 2020 06:37:46 +0200 Subject: Initial commit --- .gitignore | 3 + Cargo.lock | 3163 ++++++++++++++++++++ Cargo.toml | 36 + migrations/2020-06-07-160636_create_user/down.sql | 2 + migrations/2020-06-07-160636_create_user/up.sql | 13 + .../2020-06-07-161450_create_transaction/down.sql | 1 + .../2020-06-07-161450_create_transaction/up.sql | 12 + src/admin.rs | 114 + src/admin/user_creation.rs | 87 + src/error.rs | 44 + src/error_handlers.rs | 33 + src/main.rs | 115 + src/model.rs | 54 + src/schema.rs | 34 + src/user.rs | 467 +++ src/user/login.rs | 77 + src/user/settings.rs | 36 + src/user/transactions.rs | 175 ++ src/util.rs | 37 + static/css/.gitkeep | 0 static/errors/400.htm | 21 + static/errors/404.htm | 21 + static/errors/500.htm | 22 + static/less/normalize.less | 427 +++ static/less/style.less | 137 + templates/admin.htm | 22 + templates/base.htm | 18 + templates/login.htm | 19 + templates/settings.htm | 31 + templates/transactions.htm | 40 + templates/transfer.htm | 31 + 31 files changed, 5292 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 migrations/2020-06-07-160636_create_user/down.sql create mode 100644 migrations/2020-06-07-160636_create_user/up.sql create mode 100644 migrations/2020-06-07-161450_create_transaction/down.sql create mode 100644 migrations/2020-06-07-161450_create_transaction/up.sql create mode 100644 src/admin.rs create mode 100644 src/admin/user_creation.rs create mode 100644 src/error.rs create mode 100644 src/error_handlers.rs create mode 100644 src/main.rs create mode 100644 src/model.rs create mode 100644 src/schema.rs create mode 100644 src/user.rs create mode 100644 src/user/login.rs create mode 100644 src/user/settings.rs create mode 100644 src/user/transactions.rs create mode 100644 src/util.rs create mode 100644 static/css/.gitkeep create mode 100644 static/errors/400.htm create mode 100644 static/errors/404.htm create mode 100644 static/errors/500.htm create mode 100644 static/less/normalize.less create mode 100644 static/less/style.less create mode 100644 templates/admin.htm create mode 100644 templates/base.htm create mode 100644 templates/login.htm create mode 100644 templates/settings.htm create mode 100644 templates/transactions.htm create mode 100644 templates/transfer.htm diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..343e099 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +/.env +/static/css/style.css diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..b61a7f5 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,3163 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "actix" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4af87564ff659dee8f9981540cac9418c45e910c8072fdedd643a262a38fcaf" +dependencies = [ + "actix-http 1.0.1", + "actix-rt 1.1.1", + "actix_derive", + "bitflags", + "bytes 0.5.4", + "crossbeam-channel", + "derive_more 0.99.7", + "futures 0.3.5", + "lazy_static", + "log", + "parking_lot 0.10.2", + "pin-project", + "smallvec 1.4.0", + "tokio", + "tokio-util 0.2.0", + "trust-dns-proto 0.18.0-alpha.2", + "trust-dns-resolver 0.18.0-alpha.2", +] + +[[package]] +name = "actix-codec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f2c11af4b06dc935d8e1b1491dad56bfb32febc49096a91e773f8535c176453" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.29", + "log", + "tokio-codec", + "tokio-io", +] + +[[package]] +name = "actix-codec" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e55f0a5c2ca15795035d90c46bd0e73a5123b72f68f12596d6ba5282051380" +dependencies = [ + "bitflags", + "bytes 0.5.4", + "futures-core", + "futures-sink", + "log", + "tokio", + "tokio-util 0.2.0", +] + +[[package]] +name = "actix-connect" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fade9bd4bb46bacde89f1e726c7a3dd230536092712f5d94d77ca57c087fca0" +dependencies = [ + "actix-codec 0.1.2", + "actix-rt 0.2.6", + "actix-service 0.4.2", + "actix-utils 0.4.7", + "derive_more 0.15.0", + "either", + "futures 0.1.29", + "http 0.1.21", + "log", + "tokio-current-thread", + "tokio-tcp", + "trust-dns-resolver 0.11.1", +] + +[[package]] +name = "actix-connect" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c95cc9569221e9802bf4c377f6c18b90ef10227d787611decf79fd47d2a8e76c" +dependencies = [ + "actix-codec 0.2.0", + "actix-rt 1.1.1", + "actix-service 1.0.5", + "actix-utils 1.0.6", + "derive_more 0.99.7", + "either", + "futures 0.3.5", + "http 0.2.1", + "log", + "trust-dns-proto 0.18.0-alpha.2", + "trust-dns-resolver 0.18.0-alpha.2", +] + +[[package]] +name = "actix-files" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193b22cb1f7b4ff12a4eb2415d6d19e47e44ea93e05930b30d05375ea29d3529" +dependencies = [ + "actix-http 1.0.1", + "actix-service 1.0.5", + "actix-web 2.0.0", + "bitflags", + "bytes 0.5.4", + "derive_more 0.99.7", + "futures-core", + "futures-util", + "log", + "mime", + "mime_guess", + "percent-encoding 2.1.0", + "v_htmlescape", +] + +[[package]] +name = "actix-form-data" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8828f26a4e30cad32e16daa098771681590813ca4cdf4be94df6f80d1e6eb81" +dependencies = [ + "actix-multipart", + "actix-rt 0.2.6", + "actix-threadpool 0.1.2", + "actix-web 1.0.9", + "bytes 0.4.12", + "failure", + "futures 0.1.29", + "http 0.1.21", + "log", + "mime", +] + +[[package]] +name = "actix-http" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb50f77cd28240d344fd54afd205bae8760a3b0ad448b1716a2aa31e24db139" +dependencies = [ + "actix-codec 0.1.2", + "actix-connect 0.2.5", + "actix-server-config", + "actix-service 0.4.2", + "actix-threadpool 0.1.2", + "actix-utils 0.4.7", + "base64 0.10.1", + "bitflags", + "brotli2", + "bytes 0.4.12", + "chrono", + "copyless", + "derive_more 0.15.0", + "either", + "encoding_rs", + "failure", + "flate2", + "futures 0.1.29", + "h2 0.1.26", + "hashbrown 0.6.3", + "http 0.1.21", + "httparse", + "indexmap", + "language-tags", + "lazy_static", + "log", + "mime", + "percent-encoding 2.1.0", + "rand 0.7.3", + "regex", + "serde", + "serde_json", + "serde_urlencoded", + "sha1", + "slab", + "time", + "tokio-current-thread", + "tokio-tcp", + "tokio-timer", + "trust-dns-resolver 0.11.1", +] + +[[package]] +name = "actix-http" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c16664cc4fdea8030837ad5a845eb231fb93fc3c5c171edfefb52fad92ce9019" +dependencies = [ + "actix-codec 0.2.0", + "actix-connect 1.0.2", + "actix-rt 1.1.1", + "actix-service 1.0.5", + "actix-threadpool 0.3.2", + "actix-utils 1.0.6", + "base64 0.11.0", + "bitflags", + "brotli2", + "bytes 0.5.4", + "chrono", + "copyless", + "derive_more 0.99.7", + "either", + "encoding_rs", + "failure", + "flate2", + "futures-channel", + "futures-core", + "futures-util", + "fxhash", + "h2 0.2.5", + "http 0.2.1", + "httparse", + "indexmap", + "language-tags", + "lazy_static", + "log", + "mime", + "percent-encoding 2.1.0", + "pin-project", + "rand 0.7.3", + "regex", + "ring", + "serde", + "serde_json", + "serde_urlencoded", + "sha1", + "slab", + "time", +] + +[[package]] +name = "actix-identity" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a379b0639c293292d71defb8cc1f94c87b7705c904adf044338ad392df77c7a" +dependencies = [ + "actix-service 1.0.5", + "actix-web 2.0.0", + "futures 0.3.5", + "serde", + "serde_json", + "time", +] + +[[package]] +name = "actix-macros" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a60f9ba7c4e6df97f3aacb14bb5c0cd7d98a49dcbaed0d7f292912ad9a6a3ed2" +dependencies = [ + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "actix-multipart" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91f0604a1bf3e628b4c3f516f07280f33a33cece27df514227f5ec30925bb55" +dependencies = [ + "actix-service 0.4.2", + "actix-web 1.0.9", + "bytes 0.4.12", + "derive_more 0.15.0", + "futures 0.1.29", + "httparse", + "log", + "mime", + "time", + "twoway", +] + +[[package]] +name = "actix-router" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23224bb527e204261d0291102cb9b52713084def67d94f7874923baefe04ccf7" +dependencies = [ + "bytes 0.4.12", + "http 0.1.21", + "log", + "regex", + "serde", + "string", +] + +[[package]] +name = "actix-router" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d7a10ca4d94e8c8e7a87c5173aba1b97ba9a6563ca02b0e1cd23531093d3ec8" +dependencies = [ + "bytestring", + "http 0.2.1", + "log", + "regex", + "serde", +] + +[[package]] +name = "actix-rt" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88c9da1d06603d82ec2b6690fc5b80eb626cd2d6b573f3d9a71d5252e06d098e" +dependencies = [ + "actix-threadpool 0.1.2", + "copyless", + "futures 0.1.29", + "tokio-current-thread", + "tokio-executor", + "tokio-reactor", + "tokio-timer", +] + +[[package]] +name = "actix-rt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143fcc2912e0d1de2bcf4e2f720d2a60c28652ab4179685a1ee159e0fb3db227" +dependencies = [ + "actix-macros", + "actix-threadpool 0.3.2", + "copyless", + "futures-channel", + "futures-util", + "smallvec 1.4.0", + "tokio", +] + +[[package]] +name = "actix-server" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd626534af8d0a738e5f74901fe603af0445708f91b86a7d763d80df10d562a5" +dependencies = [ + "actix-rt 0.2.6", + "actix-server-config", + "actix-service 0.4.2", + "futures 0.1.29", + "log", + "mio", + "net2", + "num_cpus", + "slab", + "tokio-io", + "tokio-reactor", + "tokio-signal", + "tokio-tcp", + "tokio-timer", +] + +[[package]] +name = "actix-server" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d74b464215a473c973a2d7d03a69cc10f4ce1f4b38a7659c5193dc5c675630" +dependencies = [ + "actix-codec 0.2.0", + "actix-rt 1.1.1", + "actix-service 1.0.5", + "actix-utils 1.0.6", + "futures-channel", + "futures-util", + "log", + "mio", + "mio-uds", + "num_cpus", + "slab", + "socket2", +] + +[[package]] +name = "actix-server-config" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "483a34989c682d93142bacad6300375bb6ad8002d2e0bb249dbad86128b9ff30" +dependencies = [ + "futures 0.1.29", + "tokio-io", + "tokio-tcp", +] + +[[package]] +name = "actix-service" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca5b48e928841ff7e7dce1fdb5b0d4582f6b1b976e08f4bac3f640643e0773f" +dependencies = [ + "futures 0.1.29", +] + +[[package]] +name = "actix-service" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e4fc95dfa7e24171b2d0bb46b85f8ab0e8499e4e3caec691fc4ea65c287564" +dependencies = [ + "futures-util", + "pin-project", +] + +[[package]] +name = "actix-testing" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af001e97ac6750994824d400a1b7087055aab14317aa012f528d0b2b363f37f1" +dependencies = [ + "actix-rt 0.2.6", + "actix-server 0.6.1", + "actix-server-config", + "actix-service 0.4.2", + "futures 0.1.29", + "log", + "net2", + "tokio-reactor", + "tokio-tcp", +] + +[[package]] +name = "actix-testing" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47239ca38799ab74ee6a8a94d1ce857014b2ac36f242f70f3f75a66f691e791c" +dependencies = [ + "actix-macros", + "actix-rt 1.1.1", + "actix-server 1.0.3", + "actix-service 1.0.5", + "log", + "socket2", +] + +[[package]] +name = "actix-threadpool" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b5ae85d13da7e6fb86b1b7bc83185e0e3bd4cc5f421c887e1803796c034d35d" +dependencies = [ + "derive_more 0.15.0", + "futures 0.1.29", + "lazy_static", + "log", + "num_cpus", + "parking_lot 0.9.0", + "threadpool", +] + +[[package]] +name = "actix-threadpool" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91164716d956745c79dcea5e66d2aa04506549958accefcede5368c70f2fd4ff" +dependencies = [ + "derive_more 0.99.7", + "futures-channel", + "lazy_static", + "log", + "num_cpus", + "parking_lot 0.10.2", + "threadpool", +] + +[[package]] +name = "actix-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e5b4faaf105e9a6d389c606c298dcdb033061b00d532af9df56ff3a54995a8" +dependencies = [ + "actix-codec 0.2.0", + "actix-rt 1.1.1", + "actix-service 1.0.5", + "actix-utils 1.0.6", + "derive_more 0.99.7", + "either", + "futures 0.3.5", + "log", +] + +[[package]] +name = "actix-utils" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "908c3109948f5c37a8b57fd343a37dcad5bb1d90bfd06300ac96b17bbe017b95" +dependencies = [ + "actix-codec 0.1.2", + "actix-service 0.4.2", + "bytes 0.4.12", + "either", + "futures 0.1.29", + "log", + "tokio-current-thread", + "tokio-timer", +] + +[[package]] +name = "actix-utils" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf8f5631bf01adec2267808f00e228b761c60c0584cc9fa0b5364f41d147f4e" +dependencies = [ + "actix-codec 0.2.0", + "actix-rt 1.1.1", + "actix-service 1.0.5", + "bitflags", + "bytes 0.5.4", + "either", + "futures 0.3.5", + "log", + "pin-project", + "slab", +] + +[[package]] +name = "actix-web" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af3a1b967cdbacb903c4b9ae71257a7f098d881b25eb483d0c468b7dac579b03" +dependencies = [ + "actix-codec 0.1.2", + "actix-http 0.2.11", + "actix-router 0.1.5", + "actix-rt 0.2.6", + "actix-server 0.6.1", + "actix-server-config", + "actix-service 0.4.2", + "actix-testing 0.1.0", + "actix-threadpool 0.1.2", + "actix-utils 0.4.7", + "actix-web-codegen 0.1.3", + "awc 0.2.8", + "bytes 0.4.12", + "derive_more 0.15.0", + "encoding_rs", + "futures 0.1.29", + "hashbrown 0.6.3", + "log", + "mime", + "net2", + "parking_lot 0.9.0", + "regex", + "serde", + "serde_json", + "serde_urlencoded", + "time", + "url 2.1.1", +] + +[[package]] +name = "actix-web" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3158e822461040822f0dbf1735b9c2ce1f95f93b651d7a7aded00b1efbb1f635" +dependencies = [ + "actix-codec 0.2.0", + "actix-http 1.0.1", + "actix-macros", + "actix-router 0.2.4", + "actix-rt 1.1.1", + "actix-server 1.0.3", + "actix-service 1.0.5", + "actix-testing 1.0.1", + "actix-threadpool 0.3.2", + "actix-tls", + "actix-utils 1.0.6", + "actix-web-codegen 0.2.2", + "awc 1.0.1", + "bytes 0.5.4", + "derive_more 0.99.7", + "encoding_rs", + "futures 0.3.5", + "fxhash", + "log", + "mime", + "net2", + "pin-project", + "regex", + "serde", + "serde_json", + "serde_urlencoded", + "time", + "url 2.1.1", +] + +[[package]] +name = "actix-web-codegen" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "068a33520e21c1eea89726be4d6b3ce2e6b81046904367e1677287695a043abb" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "actix-web-codegen" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a71bf475cbe07281d0b3696abb48212db118e7e23219f13596ce865235ff5766" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "actix_derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b95aceadaf327f18f0df5962fedc1bde2f870566a0b9f65c89508a3b1f79334c" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "addr2line" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a49806b9dadc843c61e7c97e72490ad7f7220ae249012fbda9ad0609457c0543" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler32" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" + +[[package]] +name = "ahash" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f33b5018f120946c1dcf279194f238a9f146725593ead1c08fa47ff22b0b5d3" +dependencies = [ + "const-random", +] + +[[package]] +name = "aho-corasick" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi 0.3.8", +] + +[[package]] +name = "arc-swap" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034" + +[[package]] +name = "argonautica" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b765e206f4ab068271148430e0799aa84d81b8a13680c680f29f6c1d67da5f37" +dependencies = [ + "base64 0.10.1", + "bindgen", + "bitflags", + "cc", + "cfg-if", + "failure", + "futures 0.1.29", + "futures-cpupool", + "libc", + "log", + "nom 4.2.3", + "num_cpus", + "rand 0.6.5", + "scopeguard 1.1.0", + "tempdir", +] + +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + +[[package]] +name = "askama" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a1fb9e41eb366cbcd267da2094be5b7e62fdbca9f82091e7503e80f885050d" +dependencies = [ + "askama_derive", + "askama_escape", + "askama_shared", +] + +[[package]] +name = "askama_derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1012c270085fa35ece6a48a569544fde85b6d9ee41074c7b706cc912a03f939" +dependencies = [ + "askama_shared", + "nom 5.1.1", + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "askama_escape" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a577aeba5fec1aafb9f195d98cfcc38a78b588e4ebf9b15f62ca1c7aa33795a" + +[[package]] +name = "askama_shared" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee517f4e33c27b129928e71d8a044d54c513e72e0b72ec5c4f5f1823e9de353" +dependencies = [ + "askama_escape", + "humansize", + "num-traits", + "serde", + "toml", +] + +[[package]] +name = "async-trait" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1c13101a3224fb178860ae372a031ce350bbd92d39968518f016744dde0bf7" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "autocfg" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" + +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + +[[package]] +name = "awc" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e995283278dd3bf0449e7534e77184adb1570c0de8b6a50bf7c9d01ad8db8c4" +dependencies = [ + "actix-codec 0.1.2", + "actix-http 0.2.11", + "actix-service 0.4.2", + "base64 0.10.1", + "bytes 0.4.12", + "derive_more 0.15.0", + "futures 0.1.29", + "log", + "mime", + "percent-encoding 2.1.0", + "rand 0.7.3", + "serde", + "serde_json", + "serde_urlencoded", + "tokio-timer", +] + +[[package]] +name = "awc" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7601d4d1d7ef2335d6597a41b5fe069f6ab799b85f53565ab390e7b7065aac5" +dependencies = [ + "actix-codec 0.2.0", + "actix-http 1.0.1", + "actix-rt 1.1.1", + "actix-service 1.0.5", + "base64 0.11.0", + "bytes 0.5.4", + "derive_more 0.99.7", + "futures-core", + "log", + "mime", + "percent-encoding 2.1.0", + "rand 0.7.3", + "serde", + "serde_json", + "serde_urlencoded", +] + +[[package]] +name = "backtrace" +version = "0.3.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +dependencies = [ + "byteorder", +] + +[[package]] +name = "base64" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" + +[[package]] +name = "bindgen" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d3d411fd93fd296e613bdac1d16755a6a922a4738e1c8f6a5e13542c905f3ca" +dependencies = [ + "bitflags", + "cexpr", + "cfg-if", + "clang-sys", + "clap", + "env_logger 0.6.2", + "hashbrown 0.1.8", + "lazy_static", + "log", + "peeking_take_while", + "proc-macro2 0.4.30", + "quote 0.6.13", + "regex", + "which", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "brotli-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "brotli2" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" +dependencies = [ + "brotli-sys", + "libc", +] + +[[package]] +name = "bumpalo" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + +[[package]] +name = "bytes" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" + +[[package]] +name = "bytestring" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7c05fa5172da78a62d9949d662d2ac89d4cc7355d7b49adee5163f1fb3f363" +dependencies = [ + "bytes 0.5.4", +] + +[[package]] +name = "cc" +version = "1.0.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cexpr" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d" +dependencies = [ + "nom 4.2.3", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "chrono" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" +dependencies = [ + "num-integer", + "num-traits", + "time", +] + +[[package]] +name = "clang-sys" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "2.33.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "const-random" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f1af9ac737b2dd2d577701e59fd09ba34822f6f2ebdb30a7647405d9e55e16a" +dependencies = [ + "const-random-macro", + "proc-macro-hack", +] + +[[package]] +name = "const-random-macro" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e4c606eb459dd29f7c57b2e0879f2b6f14ee130918c2b78ccb58a9624e6c7a" +dependencies = [ + "getrandom", + "proc-macro-hack", +] + +[[package]] +name = "copyless" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" + +[[package]] +name = "crc32fast" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" +dependencies = [ + "crossbeam-utils", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg 1.0.0", + "cfg-if", + "lazy_static", +] + +[[package]] +name = "derive_more" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe" +dependencies = [ + "lazy_static", + "proc-macro2 0.4.30", + "quote 0.6.13", + "regex", + "rustc_version", + "syn 0.15.44", +] + +[[package]] +name = "derive_more" +version = "0.99.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2127768764f1556535c01b5326ef94bd60ff08dcfbdc544d53e69ed155610f5d" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "diesel" +version = "1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d7ca63eb2efea87a7f56a283acc49e2ce4b2bd54adf7465dc1d81fef13d8fc" +dependencies = [ + "byteorder", + "chrono", + "diesel_derives", + "mysqlclient-sys", + "percent-encoding 2.1.0", + "url 2.1.1", +] + +[[package]] +name = "diesel_derives" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "diesel_migrations" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf3cde8413353dc7f5d72fa8ce0b99a560a359d2c5ef1e5817ca731cd9008f4c" +dependencies = [ + "migrations_internals", + "migrations_macros", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "dtoa" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" + +[[package]] +name = "either" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" + +[[package]] +name = "encoding_rs" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-as-inner" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d58266c97445680766be408285e798d3401c6d4c378ec5552e78737e681e37d" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "enum-as-inner" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc4bfcfacb61d231109d1d55202c1f33263319668b168843e02ad4652725ec9c" +dependencies = [ + "heck", + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "env_logger" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", + "synstructure", +] + +[[package]] +name = "flate2" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz-sys", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + +[[package]] +name = "futures" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" + +[[package]] +name = "futures" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" + +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +dependencies = [ + "futures 0.1.29", + "num_cpus", +] + +[[package]] +name = "futures-executor" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" + +[[package]] +name = "futures-macro" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" +dependencies = [ + "proc-macro-hack", + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "futures-sink" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc" + +[[package]] +name = "futures-task" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626" +dependencies = [ + "once_cell", +] + +[[package]] +name = "futures-util" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "getrandom" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c" + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" + +[[package]] +name = "h2" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" +dependencies = [ + "byteorder", + "bytes 0.4.12", + "fnv", + "futures 0.1.29", + "http 0.1.21", + "indexmap", + "log", + "slab", + "string", + "tokio-io", +] + +[[package]] +name = "h2" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b7246d7e4b979c03fa093da39cfb3617a96bbeee6310af63991668d7e843ff" +dependencies = [ + "bytes 0.5.4", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.1", + "indexmap", + "log", + "slab", + "tokio", + "tokio-util 0.3.1", +] + +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" +dependencies = [ + "byteorder", + "scopeguard 0.3.3", +] + +[[package]] +name = "hashbrown" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" +dependencies = [ + "ahash", + "autocfg 0.1.7", +] + +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" +dependencies = [ + "libc", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi 0.3.8", +] + +[[package]] +name = "http" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" +dependencies = [ + "bytes 0.4.12", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" +dependencies = [ + "bytes 0.5.4", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" + +[[package]] +name = "humansize" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e" + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe" +dependencies = [ + "autocfg 1.0.0", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + +[[package]] +name = "ipconfig" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" +dependencies = [ + "socket2", + "widestring", + "winapi 0.3.8", + "winreg", +] + +[[package]] +name = "itoa" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" + +[[package]] +name = "jobserver" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +dependencies = [ + "libc", +] + +[[package]] +name = "joklerpoint" +version = "0.1.0" +dependencies = [ + "actix", + "actix-files", + "actix-form-data", + "actix-http 1.0.1", + "actix-identity", + "actix-rt 1.1.1", + "actix-web 2.0.0", + "argonautica", + "askama", + "chrono", + "derive_more 0.99.7", + "diesel", + "diesel_migrations", + "dotenv", + "env_logger 0.7.1", + "log", + "num-format", + "r2d2", + "r2d2-diesel", + "serde", + "serde_urlencoded", +] + +[[package]] +name = "js-sys" +version = "0.3.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce10c23ad2ea25ceca0093bd3192229da4c5b3c0f2de499c1ecac0d98d452177" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" + +[[package]] +name = "libloading" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" +dependencies = [ + "cc", + "winapi 0.3.8", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" + +[[package]] +name = "lock_api" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +dependencies = [ + "scopeguard 1.1.0", +] + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + +[[package]] +name = "memchr" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" + +[[package]] +name = "migrations_internals" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b4fc84e4af020b837029e017966f86a1c2d5e83e64b589963d5047525995860" +dependencies = [ + "diesel", +] + +[[package]] +name = "migrations_macros" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c" +dependencies = [ + "migrations_internals", + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mime_guess" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz-sys" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9e3ae51cea1576ceba0dde3d484d30e6e5b86dee0b2d412fe3a16a15c98202" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "miniz_oxide" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" +dependencies = [ + "adler32", +] + +[[package]] +name = "mio" +version = "0.6.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" +dependencies = [ + "cfg-if", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + +[[package]] +name = "mio-uds" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" +dependencies = [ + "iovec", + "libc", + "mio", +] + +[[package]] +name = "miow" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + +[[package]] +name = "mysqlclient-sys" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9637d93448044078aaafea7419aed69d301b4a12bcc4aa0ae856eb169bef85" +dependencies = [ + "pkg-config", + "vcpkg", +] + +[[package]] +name = "net2" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" +dependencies = [ + "cfg-if", + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nom" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +dependencies = [ + "memchr", + "version_check 0.1.5", +] + +[[package]] +name = "nom" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6" +dependencies = [ + "memchr", + "version_check 0.9.2", +] + +[[package]] +name = "num-format" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" +dependencies = [ + "arrayvec", + "itoa", +] + +[[package]] +name = "num-integer" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +dependencies = [ + "autocfg 1.0.0", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +dependencies = [ + "autocfg 1.0.0", +] + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2" + +[[package]] +name = "once_cell" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d" + +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +dependencies = [ + "lock_api", + "parking_lot_core 0.6.2", + "rustc_version", +] + +[[package]] +name = "parking_lot" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" +dependencies = [ + "lock_api", + "parking_lot_core 0.7.2", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +dependencies = [ + "cfg-if", + "cloudabi", + "libc", + "redox_syscall", + "rustc_version", + "smallvec 0.6.13", + "winapi 0.3.8", +] + +[[package]] +name = "parking_lot_core" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" +dependencies = [ + "cfg-if", + "cloudabi", + "libc", + "redox_syscall", + "smallvec 1.4.0", + "winapi 0.3.8", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pin-project" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e75373ff9037d112bb19bc61333a06a159eaeb217660dcfbea7d88e1db823919" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10b4b44893d3c370407a1d6a5cfde7c41ae0478e31c516c85f67eb3adc51be6d" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "pin-project-lite" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" + +[[package]] +name = "ppv-lite86" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" + +[[package]] +name = "proc-macro-hack" +version = "0.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4" + +[[package]] +name = "proc-macro-nested" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" +dependencies = [ + "unicode-xid 0.2.0", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" +dependencies = [ + "proc-macro2 1.0.18", +] + +[[package]] +name = "r2d2" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1497e40855348e4a8a40767d8e55174bce1e445a3ac9254ad44ad468ee0485af" +dependencies = [ + "log", + "parking_lot 0.10.2", + "scheduled-thread-pool", +] + +[[package]] +name = "r2d2-diesel" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9c29bad92da76d02bc2c020452ebc3a3fe6fa74cfab91e711c43116e4fb1a3" +dependencies = [ + "diesel", + "r2d2", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi 0.3.8", +] + +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.7", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc 0.1.0", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi 0.3.8", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc 0.2.0", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.7", + "rand_core 0.3.1", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi 0.3.8", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi 0.3.8", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.7", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" + +[[package]] +name = "regex" +version = "1.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" + +[[package]] +name = "remove_dir_all" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +dependencies = [ + "winapi 0.3.8", +] + +[[package]] +name = "resolv-conf" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11834e137f3b14e309437a8276714eed3a80d1ef894869e510f2c0c0b98b9f4a" +dependencies = [ + "hostname", + "quick-error", +] + +[[package]] +name = "ring" +version = "0.16.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06b3fefa4f12272808f809a0af618501fdaba41a58963c5fb72238ab0be09603" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi 0.3.8", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "scheduled-thread-pool" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0988d7fdf88d5e5fcf5923a0f1e8ab345f3e98ab4bc6bc45a2d5ff7f7458fbf6" +dependencies = [ + "parking_lot 0.10.2", +] + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "serde_json" +version = "1.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" +dependencies = [ + "dtoa", + "itoa", + "serde", + "url 2.1.1", +] + +[[package]] +name = "sha1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" + +[[package]] +name = "signal-hook-registry" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" +dependencies = [ + "arc-swap", + "libc", +] + +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" + +[[package]] +name = "smallvec" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +dependencies = [ + "maybe-uninit", +] + +[[package]] +name = "smallvec" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" + +[[package]] +name = "socket2" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.8", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "string" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" +dependencies = [ + "bytes 0.4.12", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + +[[package]] +name = "syn" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93a56fabc59dce20fe48b6c832cc249c713e7ed88fa28b0ee0a3bfcaae5fe4e2" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.6", + "unicode-xid 0.2.0", +] + +[[package]] +name = "synstructure" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", + "unicode-xid 0.2.0", +] + +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +dependencies = [ + "rand 0.4.6", + "remove_dir_all", +] + +[[package]] +name = "termcolor" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "tokio" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d099fa27b9702bed751524694adbe393e18b36b204da91eb1cbbbbb4a5ee2d58" +dependencies = [ + "bytes 0.5.4", + "fnv", + "futures-core", + "iovec", + "lazy_static", + "libc", + "memchr", + "mio", + "mio-uds", + "pin-project-lite", + "signal-hook-registry", + "slab", + "winapi 0.3.8", +] + +[[package]] +name = "tokio-codec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.29", + "tokio-io", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" +dependencies = [ + "futures 0.1.29", + "tokio-executor", +] + +[[package]] +name = "tokio-executor" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" +dependencies = [ + "crossbeam-utils", + "futures 0.1.29", +] + +[[package]] +name = "tokio-io" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.29", + "log", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" +dependencies = [ + "crossbeam-utils", + "futures 0.1.29", + "lazy_static", + "log", + "mio", + "num_cpus", + "parking_lot 0.9.0", + "slab", + "tokio-executor", + "tokio-io", + "tokio-sync", +] + +[[package]] +name = "tokio-signal" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0c34c6e548f101053321cba3da7cbb87a610b85555884c41b07da2eb91aff12" +dependencies = [ + "futures 0.1.29", + "libc", + "mio", + "mio-uds", + "signal-hook-registry", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "winapi 0.3.8", +] + +[[package]] +name = "tokio-sync" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" +dependencies = [ + "fnv", + "futures 0.1.29", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.29", + "iovec", + "mio", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-timer" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" +dependencies = [ + "crossbeam-utils", + "futures 0.1.29", + "slab", + "tokio-executor", +] + +[[package]] +name = "tokio-udp" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.29", + "log", + "mio", + "tokio-codec", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-util" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" +dependencies = [ + "bytes 0.5.4", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" +dependencies = [ + "bytes 0.5.4", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" +dependencies = [ + "serde", +] + +[[package]] +name = "trust-dns-proto" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5559ebdf6c2368ddd11e20b11d6bbaf9e46deb803acd7815e93f5a7b4a6d2901" +dependencies = [ + "byteorder", + "enum-as-inner 0.2.1", + "failure", + "futures 0.1.29", + "idna 0.1.5", + "lazy_static", + "log", + "rand 0.6.5", + "smallvec 0.6.13", + "socket2", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-timer", + "tokio-udp", + "url 1.7.2", +] + +[[package]] +name = "trust-dns-proto" +version = "0.18.0-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a7f3a2ab8a919f5eca52a468866a67ed7d3efa265d48a652a9a3452272b413f" +dependencies = [ + "async-trait", + "enum-as-inner 0.3.2", + "failure", + "futures 0.3.5", + "idna 0.2.0", + "lazy_static", + "log", + "rand 0.7.3", + "smallvec 1.4.0", + "socket2", + "tokio", + "url 2.1.1", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c9992e58dba365798803c0b91018ff6c8d3fc77e06977c4539af2a6bfe0a039" +dependencies = [ + "cfg-if", + "failure", + "futures 0.1.29", + "ipconfig", + "lazy_static", + "log", + "lru-cache", + "resolv-conf", + "smallvec 0.6.13", + "tokio-executor", + "trust-dns-proto 0.7.4", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.18.0-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" +dependencies = [ + "cfg-if", + "failure", + "futures 0.3.5", + "ipconfig", + "lazy_static", + "log", + "lru-cache", + "resolv-conf", + "smallvec 1.4.0", + "tokio", + "trust-dns-proto 0.18.0-alpha.2", +] + +[[package]] +name = "twoway" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b40075910de3a912adbd80b5d8bad6ad10a23eeb1f5bf9d4006839e899ba5bc" +dependencies = [ + "memchr", + "unchecked-index", +] + +[[package]] +name = "unchecked-index" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c" + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check 0.9.2", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +dependencies = [ + "matches", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" +dependencies = [ + "smallvec 1.4.0", +] + +[[package]] +name = "unicode-segmentation" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" + +[[package]] +name = "unicode-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +dependencies = [ + "idna 0.1.5", + "matches", + "percent-encoding 1.0.1", +] + +[[package]] +name = "url" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" +dependencies = [ + "idna 0.2.0", + "matches", + "percent-encoding 2.1.0", +] + +[[package]] +name = "v_escape" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "660b101c07b5d0863deb9e7fb3138777e858d6d2a79f9e6049a27d1cc77c6da6" +dependencies = [ + "v_escape_derive", +] + +[[package]] +name = "v_escape_derive" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" +dependencies = [ + "nom 4.2.3", + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", +] + +[[package]] +name = "v_htmlescape" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33e939c0d8cf047514fb6ba7d5aac78bc56677a6938b2ee67000b91f2e97e41" +dependencies = [ + "cfg-if", + "v_escape", +] + +[[package]] +name = "vcpkg" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55d1e41d56121e07f1e223db0a4def204e45c85425f6a16d462fd07c8d10d74c" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + +[[package]] +name = "version_check" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasm-bindgen" +version = "0.2.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c2dc4aa152834bc334f506c1a06b866416a8b6697d5c9f75b9a689c8486def0" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded84f06e0ed21499f6184df0e0cb3494727b0c5da89534e0fcc55c51d812101" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "838e423688dac18d73e31edce74ddfac468e37b1506ad163ffaf0a46f703ffe3" +dependencies = [ + "quote 1.0.6", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.6", + "syn 1.0.30", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9ba19973a58daf4db6f352eda73dc0e289493cd29fb2632eb172085b6521acd" + +[[package]] +name = "web-sys" +version = "0.3.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b72fe77fd39e4bd3eaa4412fd299a0be6b3dfe9d2597e2f1c20beb968f41d17" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "which" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" +dependencies = [ + "failure", + "libc", +] + +[[package]] +name = "widestring" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi 0.3.8", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +dependencies = [ + "winapi 0.3.8", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..1a7529b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "joklerpoint" +version = "0.1.0" +authors = ["Jokler "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +actix = "0.9.0" +actix-web = "2.0.0" +actix-rt = "1.1.1" +actix-http = "1.0.1" +actix-identity = "0.2.1" +actix-form-data = "0.4.0" +askama = "0.9.0" +r2d2 = "0.8.8" +r2d2-diesel = "1.0.0" +env_logger = "0.7.1" +log = "0.4.8" +argonautica = "0.2.0" +dotenv = "0.15.0" +derive_more = "0.99.7" +chrono = "0.4.11" +actix-files = "0.2.2" +diesel_migrations = "1.4.0" +num-format = "0.4.0" +serde_urlencoded = "0.6.1" + +[dependencies.serde] +features = ["derive"] +version = "1.0.111" + +[dependencies.diesel] +features = ["mysql", "chrono"] +version = "1.4.4" diff --git a/migrations/2020-06-07-160636_create_user/down.sql b/migrations/2020-06-07-160636_create_user/down.sql new file mode 100644 index 0000000..5808b9c --- /dev/null +++ b/migrations/2020-06-07-160636_create_user/down.sql @@ -0,0 +1,2 @@ +DROP TABLE passwords; +DROP TABLE users; diff --git a/migrations/2020-06-07-160636_create_user/up.sql b/migrations/2020-06-07-160636_create_user/up.sql new file mode 100644 index 0000000..e0ee7f4 --- /dev/null +++ b/migrations/2020-06-07-160636_create_user/up.sql @@ -0,0 +1,13 @@ +CREATE TABLE users ( + id SERIAL NOT NULL PRIMARY KEY, + power_level INTEGER NOT NULL DEFAULT 0, + name VARCHAR(32) UNIQUE NOT NULL, + created timestamp NOT NULL DEFAULT current_timestamp(), + balance bigint UNSIGNED NOT NULL +); + +CREATE TABLE passwords ( + id SERIAL NOT NULL PRIMARY KEY, + hash CHAR(120) BINARY NOT NULL, + CONSTRAINT fk_user_id FOREIGN KEY (id) REFERENCES users (id) +); diff --git a/migrations/2020-06-07-161450_create_transaction/down.sql b/migrations/2020-06-07-161450_create_transaction/down.sql new file mode 100644 index 0000000..91345dc --- /dev/null +++ b/migrations/2020-06-07-161450_create_transaction/down.sql @@ -0,0 +1 @@ +DROP TABLE transactions; diff --git a/migrations/2020-06-07-161450_create_transaction/up.sql b/migrations/2020-06-07-161450_create_transaction/up.sql new file mode 100644 index 0000000..fb81016 --- /dev/null +++ b/migrations/2020-06-07-161450_create_transaction/up.sql @@ -0,0 +1,12 @@ +CREATE TABLE transactions ( + id SERIAL NOT NULL PRIMARY KEY, + `date` timestamp NOT NULL DEFAULT current_timestamp(), + sender bigint UNSIGNED NOT NULL, + receiver bigint UNSIGNED NOT NULL, + amount bigint UNSIGNED NOT NULL, + sender_balance bigint UNSIGNED NOT NULL, + receiver_balance bigint UNSIGNED NOT NULL, + purpose varchar(70) NOT NULL, + CONSTRAINT fk_sender_id FOREIGN KEY (sender) REFERENCES users (id), + CONSTRAINT fk_receiver_id FOREIGN KEY (receiver) REFERENCES users (id) +); diff --git a/src/admin.rs b/src/admin.rs new file mode 100644 index 0000000..2efe02f --- /dev/null +++ b/src/admin.rs @@ -0,0 +1,114 @@ +use std::str::FromStr; + +use actix::Addr; +use actix_http::error::ResponseError; +use actix_identity::Identity; +use actix_web::{http::header, web, HttpResponse}; +use askama::Template; +use serde::Deserialize; + +use crate::error::ServiceError; +use crate::model::{DbExecutor, NewUser}; +use crate::util::UserRequest; +use crate::Secret; + +pub mod user_creation; +use user_creation::{PassHashExecutor, PassHashRequest, SaveUserRequest}; + +#[derive(Template)] +#[template(path = "admin.htm")] +struct AdminTemplate; + +pub async fn index(ident: Identity, db: web::Data>) -> HttpResponse { + if let Some(name) = ident.identity() { + ident.remember(name.clone()); + let user = match db.send(UserRequest(name.clone())).await.unwrap() { + Ok(v) => v, + Err(_) => { + ident.forget(); + return HttpResponse::Found() + .header(header::LOCATION, "/login") + .finish(); + } + }; + if user.power_level != 9001 { + return ServiceError::Unauthorized.error_response(); + } + + let page = AdminTemplate.render().unwrap(); + + HttpResponse::Ok().content_type("text/html").body(page) + } else { + HttpResponse::Found() + .header(header::LOCATION, "/user/login") + .finish() + } +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "kebab-case")] +pub struct UserData { + pub user: String, + pub balance: String, + pub password: String, +} + +pub async fn create_user( + ident: Identity, + params: web::Form, + db: web::Data>, + hasher: web::Data>, + sec: web::Data, +) -> HttpResponse { + if let Some(name) = ident.identity() { + ident.remember(name.clone()); + let user = match db.send(UserRequest(name.clone())).await.unwrap() { + Ok(v) => v, + Err(_) => { + ident.forget(); + return HttpResponse::Found() + .header(header::LOCATION, "/login") + .finish(); + } + }; + if user.power_level != 9001 { + return ServiceError::Unauthorized.error_response(); + } + let new_login = params.into_inner(); + + let balance = match u64::from_str(&new_login.balance) { + Ok(v) => v, + Err(e) => { + return HttpResponse::Ok() + .content_type("text/html") + .body(e.to_string()) + } + }; + + let hash = hasher + .send(PassHashRequest::new(new_login.password, sec.0.clone())) + .await + .unwrap() + .unwrap(); + + let new_user = NewUser { + name: new_login.user, + // TODO Let the admin pick + power_level: 0, + balance: balance, + }; + + db.send(SaveUserRequest::new(new_user, hash)) + .await + .unwrap() + .unwrap(); + + HttpResponse::Found() + .header(header::LOCATION, "/admin") + .finish() + } else { + HttpResponse::Found() + .header(header::LOCATION, "/login") + .finish() + } +} diff --git a/src/admin/user_creation.rs b/src/admin/user_creation.rs new file mode 100644 index 0000000..563b660 --- /dev/null +++ b/src/admin/user_creation.rs @@ -0,0 +1,87 @@ +use actix::{Actor, Handler, Message, SyncContext}; +use argonautica::{input::SecretKey, Hasher}; +use diesel::MysqlConnection; +use diesel::{ + dsl::sql, + types::{Bigint, Unsigned}, + RunQueryDsl, +}; + +use crate::error::ServiceError; +use crate::model::{DbExecutor, NewPassword, NewUser}; +use crate::schema::passwords::dsl::passwords; +use crate::schema::users::dsl::users; + +static LAST_ID_SQL: &'static str = "SELECT LAST_INSERT_ID()"; + +pub struct PassHashExecutor(pub Hasher<'static>); + +impl Actor for PassHashExecutor { + type Context = SyncContext; +} + +pub struct PassHashRequest { + password: String, + secret: String, +} + +impl PassHashRequest { + pub fn new(password: String, secret: String) -> Self { + Self { password, secret } + } +} + +impl Message for PassHashRequest { + type Result = Result; +} + +impl Handler for PassHashExecutor { + type Result = Result; + + fn handle(&mut self, req: PassHashRequest, _: &mut Self::Context) -> Self::Result { + let secret = SecretKey::from_base64_encoded(req.secret)?; + Ok(self + .0 + .with_password(req.password) + .with_secret_key(secret) + .hash()?) + } +} + +pub struct SaveUserRequest { + user: NewUser, + pass_hash: String, +} + +impl SaveUserRequest { + pub fn new(user: NewUser, pass_hash: String) -> Self { + Self { user, pass_hash } + } +} + +impl Message for SaveUserRequest { + type Result = Result<(), ServiceError>; +} + +impl Handler for DbExecutor { + type Result = Result<(), ServiceError>; + + fn handle(&mut self, msg: SaveUserRequest, _: &mut Self::Context) -> Self::Result { + let conn: &MysqlConnection = &self.0.get().unwrap(); + + diesel::insert_into(users).values(&msg.user).execute(conn)?; + + let id = sql::>(LAST_ID_SQL).get_result(conn)?; + + let new_pass = NewPassword { + id: id, + hash: &msg.pass_hash, + }; + + diesel::insert_into(passwords) + .values(&new_pass) + .execute(conn)?; + + Ok(()) + } +} diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..062bb3d --- /dev/null +++ b/src/error.rs @@ -0,0 +1,44 @@ +use actix_web::{error::ResponseError, HttpResponse}; +use argonautica::Error as HashError; +use derive_more::Display; +use diesel::result::Error as DieselError; +use log::error; +use std::convert::From; + +#[derive(Debug, Display)] +pub enum ServiceError { + #[display(fmt = "Internal Server Error")] + InternalServerError, + + #[display(fmt = "Unauthorized")] + Unauthorized, + + #[display(fmt = "Not Found")] + NotFound, +} + +impl ResponseError for ServiceError { + fn error_response(&self) -> HttpResponse { + match *self { + ServiceError::InternalServerError => { + HttpResponse::InternalServerError().body("Internal Server Error") + } + ServiceError::Unauthorized => HttpResponse::Unauthorized().body("Unauthorized"), + ServiceError::NotFound => HttpResponse::NotFound().body("404 Not Found"), + } + } +} + +impl From for ServiceError { + fn from(e: DieselError) -> ServiceError { + error!("Database error: {}", e); + ServiceError::InternalServerError + } +} + +impl From for ServiceError { + fn from(e: HashError) -> ServiceError { + error!("Hash error: {}", e); + ServiceError::InternalServerError + } +} diff --git a/src/error_handlers.rs b/src/error_handlers.rs new file mode 100644 index 0000000..c25b1c5 --- /dev/null +++ b/src/error_handlers.rs @@ -0,0 +1,33 @@ +use actix_files::NamedFile; +use actix_web::middleware::errhandlers::ErrorHandlerResponse; +use actix_web::{dev, Responder, Result}; + +pub fn bad_request(res: dev::ServiceResponse) -> Result> { + let new_resp = NamedFile::open("static/errors/400.htm")? + .set_status_code(res.status()) + .respond_to(res.request()) + .into_inner()?; + Ok(ErrorHandlerResponse::Response( + res.into_response(new_resp.into_body()), + )) +} + +pub fn not_found(res: dev::ServiceResponse) -> Result> { + let new_resp = NamedFile::open("static/errors/404.htm")? + .set_status_code(res.status()) + .respond_to(res.request()) + .into_inner()?; + Ok(ErrorHandlerResponse::Response( + res.into_response(new_resp.into_body()), + )) +} + +pub fn internal_server_error(res: dev::ServiceResponse) -> Result> { + let new_resp = NamedFile::open("static/errors/500.htm")? + .set_status_code(res.status()) + .respond_to(res.request()) + .into_inner()?; + Ok(ErrorHandlerResponse::Response( + res.into_response(new_resp.into_body()), + )) +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..0f39622 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,115 @@ +#[macro_use] +extern crate diesel; +#[macro_use] +extern crate diesel_migrations; + +use actix::prelude::*; +use actix_web::middleware::{errhandlers::ErrorHandlers, Logger}; + +use actix_identity::{CookieIdentityPolicy, IdentityService}; +use actix_web::{http, web, App, HttpServer}; +use argonautica::{Hasher, Verifier}; + +use chrono::Duration; +use diesel::mysql::MysqlConnection; +use dotenv::dotenv; +use r2d2_diesel::ConnectionManager; + +mod admin; +mod error; +mod error_handlers; +mod model; +mod schema; +mod user; +mod util; + +use crate::admin::user_creation::PassHashExecutor; +use crate::model::DbExecutor; +use crate::user::login::HashVerifyExecutor; + +embed_migrations!(); + +pub struct Secret(String); + +#[actix_rt::main] +async fn main() -> std::io::Result<()> { + dotenv().ok(); + + std::env::set_var( + "RUST_LOG", + "joklerpoint=debug,actix_web=trace,actix_server=debug", + ); + env_logger::init(); + + let bind_host: String = + std::env::var("BIND_HOST").unwrap_or_else(|_| "127.0.0.1:8000".to_string()); + + let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set"); + let manager = ConnectionManager::::new(database_url); + let pool = r2d2::Pool::builder() + .build(manager) + .expect("Can to build connection pool"); + embedded_migrations::run(&*pool.get().expect("Can connect to mysql")) + .expect("Can run migrations"); + + let db_addr: Addr = SyncArbiter::start(4, move || DbExecutor(pool.clone())); + let verifier_addr: Addr = + SyncArbiter::start(4, move || HashVerifyExecutor(Verifier::default())); + let hasher_addr: Addr = + SyncArbiter::start(4, move || PassHashExecutor(Hasher::default())); + + HttpServer::new(move || { + let secret: String = std::env::var("SECRET_KEY").expect("SECRET_KEY env var should be set"); + let domain: String = std::env::var("DOMAIN").unwrap_or_else(|_| "localhost".to_string()); + let secure_cookies = &domain != "localhost"; + + let error_handlers = ErrorHandlers::new() + .handler( + http::StatusCode::INTERNAL_SERVER_ERROR, + error_handlers::internal_server_error, + ) + .handler(http::StatusCode::BAD_REQUEST, error_handlers::bad_request) + .handler(http::StatusCode::NOT_FOUND, error_handlers::not_found); + + App::new() + .data(db_addr.clone()) + .data(verifier_addr.clone()) + .data(hasher_addr.clone()) + .data(Secret(secret.clone())) + .wrap(error_handlers) + .wrap(IdentityService::new( + CookieIdentityPolicy::new(secret.as_bytes()) + .name("jkp-session") + .domain(domain.as_str()) + .max_age_time(Duration::days(30)) + .secure(secure_cookies), // this has to reflect the usage of https + )) + .wrap(Logger::default()) + .route("/", web::get().to(user::index)) + .service( + web::resource("/login") + .route(web::get().to(user::login)) + .route(web::post().to(user::confirm_login)), + ) + .route("/transactions", web::get().to(user::transactions)) + .service( + web::resource("/transfer") + .route(web::get().to(user::transfer)) + .route(web::post().to(user::confirm_transfer)), + ) + .route("/settings", web::get().to(user::settings)) + .route("/reset-password", web::post().to(user::reset_password)) + .route("/logout", web::get().to(user::logout)) + .service( + web::resource("/admin") + .route(web::get().to(admin::index)) + .route(web::post().to(admin::create_user)), + ) + .service(actix_files::Files::new("/static", "static/")) + }) + .bind(&bind_host)? + .run() + .await?; + + Ok(()) +} diff --git a/src/model.rs b/src/model.rs new file mode 100644 index 0000000..1d399da --- /dev/null +++ b/src/model.rs @@ -0,0 +1,54 @@ +use actix::{Actor, SyncContext}; +use chrono::NaiveDateTime; +use diesel::mysql::MysqlConnection; +use r2d2::Pool; +use r2d2_diesel::ConnectionManager; + +use crate::schema::{passwords, transactions, users}; + +pub struct DbExecutor(pub Pool>); + +impl Actor for DbExecutor { + type Context = SyncContext; +} + +#[derive(Debug, Clone, Insertable)] +#[table_name = "transactions"] +pub struct NewTransaction<'a> { + pub sender: u64, + pub receiver: u64, + pub amount: u64, + pub sender_balance: u64, + pub receiver_balance: u64, + pub purpose: &'a str, +} + +#[derive(Debug, Clone, Queryable)] +pub struct User { + pub id: u64, + pub power_level: i32, + pub name: String, + pub created: NaiveDateTime, + pub balance: u64, +} + +#[derive(Debug, Clone, Insertable)] +#[table_name = "users"] +pub struct NewUser { + pub power_level: i32, + pub name: String, + pub balance: u64, +} + +#[derive(Debug, Clone, Queryable)] +pub struct Password { + pub id: u64, + pub hash: String, +} + +#[derive(Debug, Clone, Insertable)] +#[table_name = "passwords"] +pub struct NewPassword<'a> { + pub id: u64, + pub hash: &'a str, +} diff --git a/src/schema.rs b/src/schema.rs new file mode 100644 index 0000000..2855927 --- /dev/null +++ b/src/schema.rs @@ -0,0 +1,34 @@ +table! { + transactions (id) { + id -> Unsigned, + date -> Timestamp, + sender -> Unsigned, + receiver -> Unsigned, + amount -> Unsigned, + sender_balance -> Unsigned, + receiver_balance -> Unsigned, + purpose -> Varchar, + } +} + +table! { + passwords (id) { + id -> Unsigned, + hash -> Char, + } +} + +table! { + users (id) { + id -> Unsigned, + power_level -> Integer, + name -> Varchar, + created -> Timestamp, + balance -> Unsigned, + } +} + +joinable!(passwords -> users (id)); + +allow_tables_to_appear_in_same_query!(transactions, users,); +allow_tables_to_appear_in_same_query!(passwords, users,); diff --git a/src/user.rs b/src/user.rs new file mode 100644 index 0000000..8cb2c5f --- /dev/null +++ b/src/user.rs @@ -0,0 +1,467 @@ +use serde::{Deserialize, Serialize}; + +use actix::Addr; +use actix_identity::Identity; +use actix_web::{http::header, web, HttpResponse, Responder}; +use askama::Template; + +use log::error; + +use crate::model::DbExecutor; + +use crate::util::UserRequest; +use crate::Secret; + +pub mod login; +use login::{HashVerifyExecutor, HashVerifyRequest, LoginRequest}; + +mod settings; +use settings::UpdatePasswordRequest; + +mod transactions; +use transactions::{Transaction, TransactionsRequest, TransferRequest}; + +use crate::util::filters; + +use crate::admin::user_creation::{PassHashExecutor, PassHashRequest}; + +pub async fn index(ident: Identity) -> impl Responder { + if ident.identity().is_some() { + HttpResponse::Found() + .header(header::LOCATION, "/transactions") + .finish() + } else { + HttpResponse::Found() + .header(header::LOCATION, "/login") + .finish() + } +} + +#[derive(Template)] +#[template(path = "login.htm")] +struct LoginTemplate { + failed: bool, +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "kebab-case")] +pub struct LoginError { + #[serde(default)] + pub error: bool, +} + +pub async fn login(ident: Identity, params: web::Query) -> impl Responder { + if ident.identity().is_some() { + HttpResponse::Found() + .header(header::LOCATION, "/transactions") + .finish() + } else { + let failed = params.into_inner().error; + HttpResponse::Ok() + .content_type("text/html") + .body(LoginTemplate { failed }.render().unwrap()) + } +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "kebab-case")] +pub struct LoginData { + pub user: String, + pub password: String, +} + +pub async fn confirm_login( + ident: Identity, + params: web::Form, + db: web::Data>, + verifier: web::Data>, + sec: web::Data, +) -> impl Responder { + let login = params.into_inner(); + + let (user, hash) = match db.send(LoginRequest(login.user)).await.unwrap() { + Ok(v) => v, + Err(_) => { + return HttpResponse::Found() + .header(header::LOCATION, "/login?error=true") + .finish() + } + }; + + if !verifier + .send(HashVerifyRequest::new(hash, login.password, sec.0.clone())) + .await + .unwrap() + .unwrap_or(false) + { + return HttpResponse::Found() + .header(header::LOCATION, "/login?error=true") + .finish(); + } + + ident.remember(user.name); + HttpResponse::Found() + .header(header::LOCATION, "/transactions") + .finish() +} + +#[derive(Template)] +#[template(path = "transactions.htm")] +struct TransactionsTemplate<'a> { + name: &'a str, + amount: u64, + transactions: &'a [Transaction], +} + +pub async fn transactions(ident: Identity, db: web::Data>) -> HttpResponse { + if let Some(name) = ident.identity() { + ident.remember(name.clone()); + let user = match db.send(UserRequest(name.clone())).await.unwrap() { + Ok(v) => v, + Err(_) => { + ident.forget(); + return HttpResponse::Found() + .header(header::LOCATION, "/login") + .finish(); + } + }; + + let transactions = match db.send(TransactionsRequest::new(user.id)).await.unwrap() { + Ok(transactions) => transactions, + Err(e) => { + error!("Transactions error: {}", e); + Vec::with_capacity(0) + } + }; + + let page = TransactionsTemplate { + name: &name, + amount: user.balance, + transactions: &transactions, + } + .render() + .unwrap(); + + HttpResponse::Ok().content_type("text/html").body(page) + } else { + HttpResponse::Found() + .header(header::LOCATION, "/login") + .finish() + } +} + +#[derive(Template)] +#[template(path = "transfer.htm")] +struct TransferTemplate { + balance: u64, + recipient: String, + amount: u64, + purpose: String, + error: TransferResult, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "kebab-case")] +pub struct TransferQuery { + #[serde(default)] + pub result: TransferResult, + #[serde(default)] + pub recipient: String, + #[serde(default)] + pub amount: u64, + #[serde(default)] + pub purpose: String, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "kebab-case")] +pub enum TransferResult { + ZeroPoints, + SelfSend, + TransferError, + Empty, +} + +impl Default for TransferResult { + fn default() -> Self { + TransferResult::Empty + } +} + +pub async fn transfer( + ident: Identity, + db: web::Data>, + params: web::Query, +) -> HttpResponse { + if let Some(name) = ident.identity() { + ident.remember(name.clone()); + let user = match db.send(UserRequest(name.clone())).await.unwrap() { + Ok(v) => v, + Err(_) => { + ident.forget(); + return HttpResponse::Found() + .header(header::LOCATION, "/login") + .finish(); + } + }; + + let query = params.into_inner(); + let page = TransferTemplate { + balance: user.balance, + recipient: query.recipient, + amount: query.amount, + purpose: query.purpose, + error: query.result, + } + .render() + .unwrap(); + + HttpResponse::Ok().content_type("text/html").body(page) + } else { + HttpResponse::Found() + .header(header::LOCATION, "/login") + .finish() + } +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "kebab-case")] +pub struct TransferData { + pub recipient: String, + pub amount: u64, + pub purpose: String, +} + +pub async fn confirm_transfer( + ident: Identity, + params: web::Form, + db: web::Data>, +) -> HttpResponse { + if let Some(name) = ident.identity() { + ident.remember(name.clone()); + + let form = params.into_inner(); + + if form.amount == 0 { + let query = TransferQuery { + result: TransferResult::ZeroPoints, + recipient: form.recipient, + amount: form.amount, + purpose: form.purpose, + }; + return HttpResponse::Found() + .header( + header::LOCATION, + format!( + "/transfer?{}", + serde_urlencoded::to_string(query).unwrap_or(String::with_capacity(0)) + ), + ) + .finish(); + } + + if name.to_lowercase() == form.recipient.to_lowercase() { + let query = TransferQuery { + result: TransferResult::SelfSend, + recipient: form.recipient, + amount: form.amount, + purpose: form.purpose, + }; + return HttpResponse::Found() + .header( + header::LOCATION, + format!( + "/transfer?{}", + serde_urlencoded::to_string(query).unwrap_or(String::with_capacity(0)) + ), + ) + .finish(); + } + let request = TransferRequest { + from: name, + to: form.recipient.clone(), + amount: form.amount, + purpose: form.purpose.clone(), + }; + if let Err(e) = db.send(request).await.unwrap() { + error!("Failed to transfer points: {}", e); + let query = TransferQuery { + result: TransferResult::TransferError, + recipient: form.recipient, + amount: form.amount, + purpose: form.purpose, + }; + + return HttpResponse::Found() + .header( + header::LOCATION, + format!( + "/transfer?{}", + serde_urlencoded::to_string(query).unwrap_or(String::with_capacity(0)) + ), + ) + .finish(); + } + + HttpResponse::Found() + .header(header::LOCATION, "/transactions") + .finish() + } else { + HttpResponse::Found() + .header(header::LOCATION, "/login") + .finish() + } +} + +#[derive(Template)] +#[template(path = "settings.htm")] +struct SettingsTemplate { + result: PasswordResult, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "kebab-case")] +pub struct PasswordQuery { + #[serde(default)] + pub result: PasswordResult, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "kebab-case")] +pub enum PasswordResult { + Success, + InvalidOld, + Missmatch, + Empty, +} + +impl Default for PasswordResult { + fn default() -> Self { + PasswordResult::Empty + } +} + +pub async fn settings(ident: Identity, params: web::Query) -> HttpResponse { + if let Some(name) = ident.identity() { + ident.remember(name.clone()); + + let query = params.into_inner(); + HttpResponse::Ok().content_type("text/html").body( + SettingsTemplate { + result: query.result, + } + .render() + .unwrap(), + ) + } else { + HttpResponse::Found() + .header(header::LOCATION, "/login") + .finish() + } +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "kebab-case")] +pub struct PasswordReset { + pub old_password: String, + pub new_password: String, + pub confirm_password: String, +} + +pub async fn reset_password( + ident: Identity, + params: web::Form, + db: web::Data>, + verifier: web::Data>, + hasher: web::Data>, + sec: web::Data, +) -> HttpResponse { + if let Some(name) = ident.identity() { + ident.remember(name.clone()); + let (user, hash) = match db.send(LoginRequest(name)).await.unwrap() { + Ok(v) => v, + Err(_) => { + ident.forget(); + return HttpResponse::Found() + .header(header::LOCATION, "/login") + .finish(); + } + }; + + let reset = params.into_inner(); + if reset.new_password != reset.confirm_password { + let query = PasswordQuery { + result: PasswordResult::Missmatch, + }; + return HttpResponse::Found() + .header( + header::LOCATION, + format!( + "/settings?{}", + serde_urlencoded::to_string(query).unwrap_or(String::with_capacity(0)) + ), + ) + .finish(); + } + + if !verifier + .send(HashVerifyRequest::new( + hash, + reset.old_password, + sec.0.clone(), + )) + .await + .unwrap() + .unwrap_or(false) + { + let query = PasswordQuery { + result: PasswordResult::InvalidOld, + }; + return HttpResponse::Found() + .header( + header::LOCATION, + format!( + "/settings?{}", + serde_urlencoded::to_string(query).unwrap_or(String::with_capacity(0)) + ), + ) + .finish(); + } + + let hash = hasher + .send(PassHashRequest::new(reset.new_password, sec.0.clone())) + .await + .unwrap() + .unwrap(); + + db.send(UpdatePasswordRequest::new(user.id, hash)) + .await + .unwrap() + .unwrap(); + + let query = PasswordQuery { + result: PasswordResult::Success, + }; + + HttpResponse::Found() + .header( + header::LOCATION, + format!( + "/settings?{}", + serde_urlencoded::to_string(query).unwrap_or(String::with_capacity(0)) + ), + ) + .finish() + } else { + HttpResponse::Found() + .header(header::LOCATION, "/login") + .finish() + } +} + +pub fn logout(ident: Identity) -> HttpResponse { + ident.forget(); + HttpResponse::Found() + .header(header::LOCATION, "/login") + .finish() +} diff --git a/src/user/login.rs b/src/user/login.rs new file mode 100644 index 0000000..67d4c24 --- /dev/null +++ b/src/user/login.rs @@ -0,0 +1,77 @@ +use actix::{Actor, Handler, Message, SyncContext}; +use argonautica::{input::SecretKey, Verifier}; +use diesel::MysqlConnection; +use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl}; + +use crate::error::ServiceError; +use crate::model::DbExecutor; +use crate::model::User; +use crate::schema::passwords::{columns as password_columns, dsl::passwords}; +use crate::schema::users::{columns as user_columns, dsl::users}; + +pub struct HashVerifyExecutor(pub Verifier<'static>); + +impl Actor for HashVerifyExecutor { + type Context = SyncContext; +} + +pub struct HashVerifyRequest { + hash: String, + password: String, + secret: String, +} + +impl HashVerifyRequest { + pub fn new(hash: String, password: String, secret: String) -> Self { + Self { + hash, + password, + secret, + } + } +} + +impl Message for HashVerifyRequest { + type Result = Result; +} + +impl Handler for HashVerifyExecutor { + type Result = Result; + + fn handle(&mut self, req: HashVerifyRequest, _: &mut Self::Context) -> Self::Result { + let secret = SecretKey::from_base64_encoded(req.secret)?; + Ok(self + .0 + .with_hash(req.hash) + .with_password(req.password) + .with_secret_key(secret) + .verify()?) + } +} + +pub struct LoginRequest(pub String); + +impl Message for LoginRequest { + type Result = Result<(User, String), ServiceError>; +} + +impl Handler for DbExecutor { + type Result = Result<(User, String), ServiceError>; + + fn handle(&mut self, login: LoginRequest, _: &mut Self::Context) -> Self::Result { + let conn: &MysqlConnection = &self.0.get().unwrap(); + + let user = users + .filter(user_columns::name.eq(login.0)) + .first::(conn) + .map_err(|_| ServiceError::NotFound)?; + + let hash = passwords + .filter(password_columns::id.eq(user.id)) + .select(password_columns::hash) + .first::(conn) + .map_err(|_| ServiceError::NotFound)?; + + Ok((user, hash)) + } +} diff --git a/src/user/settings.rs b/src/user/settings.rs new file mode 100644 index 0000000..55e658c --- /dev/null +++ b/src/user/settings.rs @@ -0,0 +1,36 @@ +use actix::{Handler, Message}; +use diesel::MysqlConnection; +use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl}; + +use crate::error::ServiceError; +use crate::model::DbExecutor; +use crate::schema::passwords::{columns as password_columns, dsl::passwords}; + +pub struct UpdatePasswordRequest { + pub user: u64, + pub hash: String, +} + +impl UpdatePasswordRequest { + pub fn new(user: u64, hash: String) -> Self { + Self { user, hash } + } +} + +impl Message for UpdatePasswordRequest { + type Result = Result<(), ServiceError>; +} + +impl Handler for DbExecutor { + type Result = Result<(), ServiceError>; + + fn handle(&mut self, req: UpdatePasswordRequest, _: &mut Self::Context) -> Self::Result { + let conn: &MysqlConnection = &self.0.get().unwrap(); + + diesel::update(passwords.filter(password_columns::id.eq(req.user))) + .set(password_columns::hash.eq(req.hash)) + .execute(conn)?; + + Ok(()) + } +} diff --git a/src/user/transactions.rs b/src/user/transactions.rs new file mode 100644 index 0000000..197b2ec --- /dev/null +++ b/src/user/transactions.rs @@ -0,0 +1,175 @@ +use actix::{Handler, Message}; +use chrono::NaiveDateTime; +use diesel::{BoolExpressionMethods, ExpressionMethods, JoinOnDsl, QueryDsl, RunQueryDsl}; +use diesel::{Connection, MysqlConnection}; + +use crate::error::ServiceError; +use crate::model::{DbExecutor, NewTransaction, User}; +use crate::schema::transactions::{columns as transaction_columns, dsl::transactions}; +use crate::schema::users::{columns as user_columns, dsl::users}; + +#[derive(Debug, Clone, Queryable)] +struct TempTransaction { + pub id: u64, + pub date: NaiveDateTime, + pub sender: String, + pub receiver: u64, + pub amount: u64, + pub sender_balance: u64, + pub receiver_balance: u64, + pub purpose: String, +} + +#[derive(Debug, Clone)] +pub struct Transaction { + pub id: u64, + pub date: NaiveDateTime, + pub sender: String, + pub receiver: String, + pub amount: u64, + pub sender_balance: u64, + pub receiver_balance: u64, + pub purpose: String, +} + +pub struct TransactionsRequest { + id: u64, +} + +impl TransactionsRequest { + pub fn new(id: u64) -> Self { + Self { id } + } +} + +impl Message for TransactionsRequest { + type Result = Result, ServiceError>; +} + +impl Handler for DbExecutor { + type Result = Result, ServiceError>; + + fn handle(&mut self, req: TransactionsRequest, _: &mut Self::Context) -> Self::Result { + let conn: &MysqlConnection = &self.0.get().unwrap(); + + use transaction_columns as t_cols; + let temp = transactions + .filter( + transaction_columns::sender + .eq(req.id) + .or(transaction_columns::receiver.eq(req.id)), + ) + .inner_join(users.on(transaction_columns::sender.eq(user_columns::id))) + .select(( + t_cols::id, + t_cols::date, + user_columns::name, + t_cols::receiver, + t_cols::amount, + t_cols::sender_balance, + t_cols::receiver_balance, + t_cols::purpose, + )) + .order(transaction_columns::date.desc()) + .load::(conn) + .map_err(|_| ServiceError::NotFound)?; + + let recv_ids = temp.iter().map(|t| t.receiver).collect::>(); + + let receivers = users + .select((user_columns::id, user_columns::name)) + .filter(user_columns::id.eq_any(recv_ids)) + .load::<(u64, String)>(conn)?; + + let mut output = Vec::with_capacity(temp.len()); + for t in temp { + let (_, name) = receivers + .iter() + .find(|(id, _)| id == &t.receiver) + .expect("oh no"); + + let t = Transaction { + id: t.id, + date: t.date, + sender: t.sender, + receiver: name.to_owned(), + amount: t.amount, + sender_balance: t.sender_balance, + receiver_balance: t.receiver_balance, + purpose: t.purpose, + }; + output.push(t); + } + + Ok(output) + } +} + +pub struct TransferRequest { + pub from: String, + pub to: String, + pub amount: u64, + pub purpose: String, +} + +impl Message for TransferRequest { + type Result = Result<(), ServiceError>; +} + +impl Handler for DbExecutor { + type Result = Result<(), ServiceError>; + + fn handle(&mut self, req: TransferRequest, _: &mut Self::Context) -> Self::Result { + let conn: &MysqlConnection = &self.0.get().unwrap(); + + Ok(conn.transaction::<_, diesel::result::Error, _>(|| { + // Lock the user record to avoid modification by other threads + users + .filter( + user_columns::name + .eq(&req.from) + .or(user_columns::name.eq(&req.to)), + ) + .for_update() + .execute(conn)?; + + let sender = users + .filter(user_columns::name.eq(&req.from)) + .first::(conn)?; + + let new_sender_balance = sender + .balance + .checked_sub(req.amount) + .ok_or(diesel::result::Error::RollbackTransaction)?; + + diesel::update(users.find(sender.id)) + .set(user_columns::balance.eq(new_sender_balance)) + .execute(conn)?; + + let receiver = users + .filter(user_columns::name.eq(&req.to)) + .first::(conn)?; + + let new_receiver_balance = receiver + .balance + .checked_add(req.amount) + .ok_or(diesel::result::Error::RollbackTransaction)?; + + diesel::update(users.find(receiver.id)) + .set(user_columns::balance.eq(new_receiver_balance)) + .execute(conn)?; + + let t = NewTransaction { + sender: sender.id, + receiver: receiver.id, + amount: req.amount, + sender_balance: new_sender_balance, + receiver_balance: new_receiver_balance, + purpose: &req.purpose, + }; + diesel::insert_into(transactions).values(&t).execute(conn)?; + + Ok(()) + })?) + } +} diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..944feb6 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,37 @@ +use actix::{Handler, Message}; +use diesel::{ExpressionMethods, MysqlConnection, QueryDsl, RunQueryDsl}; + +use crate::error::ServiceError; +use crate::model::{DbExecutor, User}; +use crate::schema::users::{columns as user_columns, dsl::users}; + +pub struct UserRequest(pub String); + +impl Message for UserRequest { + type Result = Result; +} + +impl Handler for DbExecutor { + type Result = Result; + + fn handle(&mut self, req: UserRequest, _: &mut Self::Context) -> Self::Result { + let conn: &MysqlConnection = &self.0.get().unwrap(); + + users + .filter(user_columns::name.eq(req.0)) + .first::(conn) + .map_err(|_| ServiceError::NotFound) + } +} + +pub mod filters { + use num_format::{CustomFormat, ToFormattedString}; + + pub fn fmt_points(amount: &u64) -> Result { + let format = CustomFormat::builder() + .separator(" ") + .build() + .expect("Format is fine"); + Ok(format!("{} JKP", (*amount).to_formatted_string(&format))) + } +} diff --git a/static/css/.gitkeep b/static/css/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/static/errors/400.htm b/static/errors/400.htm new file mode 100644 index 0000000..c4a0346 --- /dev/null +++ b/static/errors/400.htm @@ -0,0 +1,21 @@ + + + + + + + 400: Bad Request + + + + +
+

400 Bad Request

+

The Server could not understand the request.

+ +
+ + + + diff --git a/static/errors/404.htm b/static/errors/404.htm new file mode 100644 index 0000000..2825b24 --- /dev/null +++ b/static/errors/404.htm @@ -0,0 +1,21 @@ + + + + + + + 404: Not Found + + + + +
+

404 Not Found

+

The page you are looking for is either gone or never existed in the first place.

+ +
+ + + + diff --git a/static/errors/500.htm b/static/errors/500.htm new file mode 100644 index 0000000..db008ff --- /dev/null +++ b/static/errors/500.htm @@ -0,0 +1,22 @@ + + + + + + + 500: Internal Server Error + + + + +
+
+

500 Internal Server Error

+ +
+
+ + + + diff --git a/static/less/normalize.less b/static/less/normalize.less new file mode 100644 index 0000000..458eea1 --- /dev/null +++ b/static/less/normalize.less @@ -0,0 +1,427 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/** + * Address styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove border when inside `a` element in IE 8/9/10. + */ + +img { + border: 0; +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/static/less/style.less b/static/less/style.less new file mode 100644 index 0000000..558c621 --- /dev/null +++ b/static/less/style.less @@ -0,0 +1,137 @@ +@import "../less/normalize"; + +html { + font-size: 62.5%; +} + +body { + font-size: 2em; + line-height: 1.6; + font-weight: 400; + font-family: "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + background-image: url("https://jokler.xyz/f/REVI+tLt/jpg"); + background-size: cover; + background-attachment:fixed; + background-color: #151515; + color: #eee; +} + +main { + position: relative; + width: 100%; + max-width: 950px; + margin: 40px auto; + padding: 20px; + box-sizing: border-box; + background-color: #252525; + border-radius: 5px; +} + +input, button { + background-color: #141414; + border-radius: 0.1em; + border-color: #2d2d2d; + margin: 0.4em; +} + +table { + border-collapse: separate; + border-spacing: 10px; +} + +.error, .minus { + color: red; +} + +.success, .plus { + color: green; +} + +.text-right { + text-align: right; +} + +.button { + background-color: #373737; + margin: 5px; + padding: 5px; + color: #eee; + border: #444343 outset 2px; + text-decoration: none; +} + +.button:hover { + background-color: #282828; + border: #313131 inset 2px; +} + +.highlight-bg { + background-color: #222; +} + +.settings { + display: flex; + justify-content: right; +} + +.center { + display: flex; + justify-content: center; +} + +.fixed-form { + margin: 0.5em; + max-width: 15em; +} + +/* Typography + * –––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 2rem; + font-weight: 300; +} + +h1 { +font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;} +h2 { + font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; + margin-top: 0.5em; +} +h3 { + font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; +} +h4 { + font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; +} +h5 { + font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; +} +h6 { + font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; +} + +/* Larger than phablet */ +@media (min-width: 550px) { + h1 { + font-size: 5.0rem; + } + h2 { + font-size: 4.2rem; + } + h3 { + font-size: 3.6rem; + } + h4 { + font-size: 3.0rem; + } + h5 { + font-size: 2.4rem; + } + h6 { + font-size: 1.5rem; + } +} + +/* vim: expandtab sw=2 ts=2 + */ diff --git a/templates/admin.htm b/templates/admin.htm new file mode 100644 index 0000000..db4aa03 --- /dev/null +++ b/templates/admin.htm @@ -0,0 +1,22 @@ +{% extends "base.htm" %} + +{% block title %}Administration{% endblock %} + +{% block content %} +

User Creation

+
+ + + + + + + + + + +
+{% endblock %} + + diff --git a/templates/base.htm b/templates/base.htm new file mode 100644 index 0000000..b55244d --- /dev/null +++ b/templates/base.htm @@ -0,0 +1,18 @@ + + + + + + + + {% block title %}{{ title }} - xyz {% endblock %} + + +
+ {% block content %}{% endblock %} +
+ + + + diff --git a/templates/login.htm b/templates/login.htm new file mode 100644 index 0000000..e107aeb --- /dev/null +++ b/templates/login.htm @@ -0,0 +1,19 @@ +{% extends "base.htm" %} + +{% block title %}Login{% endblock %} + +{% block content %} +

Login

+{% if failed -%} +
Invalid Login Data
+{% endif -%} +
+ + + + +
+{% endblock %} + + diff --git a/templates/settings.htm b/templates/settings.htm new file mode 100644 index 0000000..5b53a64 --- /dev/null +++ b/templates/settings.htm @@ -0,0 +1,31 @@ +{% extends "base.htm" %} + +{% block title %}Settings{% endblock %} + +{% block content %} +

User Settings

+ +

Change Password

+Go Back + +{% match result %} + {% when PasswordResult::Success %} +
Password change was successful
+ {% when PasswordResult::InvalidOld -%} +
Old password was incorrect
+ {% when PasswordResult::Missmatch -%} +
New passwords were not the same
+ {% when PasswordResult::Empty -%} +{% endmatch %} + +
+ + + + + +
+{% endblock %} + + diff --git a/templates/transactions.htm b/templates/transactions.htm new file mode 100644 index 0000000..f2b93ba --- /dev/null +++ b/templates/transactions.htm @@ -0,0 +1,40 @@ +{% extends "base.htm" %} + +{% block title %}Transactions{% endblock %} + +{% block content %} +

{{ name }}'s Transactions

+

{{ amount|fmt_points }}

+ + + + + + + + + + {% for transaction in transactions %} + + + {% if name == transaction.sender -%} + + + + {% else -%} + + + + {% endif -%} + + + {% endfor %} +
TimeAmountBalanceOtherPurpose
{{ transaction.date }}-{{ transaction.amount }}{{ transaction.sender_balance }}{{ transaction.receiver }}{{ transaction.amount }}{{ transaction.receiver_balance }}{{ transaction.sender }}{{ transaction.purpose }}
+{% endblock %} + + diff --git a/templates/transfer.htm b/templates/transfer.htm new file mode 100644 index 0000000..1c484db --- /dev/null +++ b/templates/transfer.htm @@ -0,0 +1,31 @@ +{% extends "base.htm" %} + +{% block title %}Transfer Points{% endblock %} + +{% block content %} +

Transfer Points

+

{{ balance|fmt_points }}

+Go Back + +{% match error %} + {% when TransferResult::ZeroPoints %} +
You have to send at least 1 JKP
+ {% when TransferResult::SelfSend %} +
You can not send points to yourself
+ {% when TransferResult::TransferError %} +
An error occured during the transfer
+ {% when TransferResult::Empty %} +{% endmatch %} + +
+ + + + + +
+{% endblock %} + + -- cgit v1.2.3-70-g09d2