diff --git a/file-service/Cargo.lock b/file-service/Cargo.lock new file mode 100644 index 0000000..2e99d09 --- /dev/null +++ b/file-service/Cargo.lock @@ -0,0 +1,1404 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "adler32" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d" + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[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 = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +dependencies = [ + "byteorder", + "safemem 0.3.3", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "bodyparser" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f023abfa58aad6f6bc4ae0630799e24d5ee0ab8bb2e49f651d9b1f9aa4f52f30" +dependencies = [ + "iron", + "persistent", + "plugin", + "serde 1.0.110", + "serde_json", +] + +[[package]] +name = "buf_redux" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9279646319ff816b05fb5897883ece50d7d854d12b59992683d4f8a71b0f949" +dependencies = [ + "memchr 1.0.2", + "safemem 0.2.0", +] + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "bytemuck" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37fa13df2292ecb479ec23aa06f4507928bef07839be9ef15281411076629431" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + +[[package]] +name = "cc" +version = "1.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "404b1fe4f65288577753b17e3b36a04596ee784493ec249bf81c7f2d2acd751c" + +[[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", + "serde 1.0.110", + "time", +] + +[[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 = "color_quant" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" + +[[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-deque" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +dependencies = [ + "autocfg 1.0.0", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "maybe-uninit", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" +dependencies = [ + "cfg-if", + "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 = "deflate" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e5d2a2273fed52a7f947ee55b092c4057025d7a3e04e5ecdbd25d6c3fb1bd7" +dependencies = [ + "adler32", + "byteorder", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "either" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "file-service" +version = "0.1.0" +dependencies = [ + "chrono", + "hex-string", + "image", + "iron", + "logger", + "mime 0.3.16", + "mime_guess 2.0.3", + "mustache", + "orizentic", + "params", + "router", + "serde 1.0.110", + "serde_json", + "sha2", + "thiserror", + "uuid 0.4.0", +] + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +dependencies = [ + "typenum", +] + +[[package]] +name = "gif" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "471d90201b3b223f3451cd4ad53e34295f16a1df17b1edf3736d47761c3981af" +dependencies = [ + "color_quant", + "lzw", +] + +[[package]] +name = "hermit-abi" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" +dependencies = [ + "libc", +] + +[[package]] +name = "hex-string" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "848ec2dd093df965a34b434580d94852197fc83feac5b2c1962399bbf2cb4f0b" + +[[package]] +name = "httparse" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" + +[[package]] +name = "hyper" +version = "0.10.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" +dependencies = [ + "base64", + "httparse", + "language-tags", + "log 0.3.9", + "mime 0.2.6", + "num_cpus", + "time", + "traitobject", + "typeable", + "unicase 1.4.2", + "url", +] + +[[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 = "image" +version = "0.23.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d534e95ad8b9d5aa614322d02352b4f1bf962254adcf02ac6f2def8be18498e8" +dependencies = [ + "bytemuck", + "byteorder", + "gif", + "jpeg-decoder", + "num-iter", + "num-rational 0.2.4", + "num-traits", + "png", + "scoped_threadpool", + "tiff", +] + +[[package]] +name = "iron" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6d308ca2d884650a8bf9ed2ff4cb13fbb2207b71f64cda11dc9b892067295e8" +dependencies = [ + "hyper", + "log 0.3.9", + "mime_guess 1.8.8", + "modifier", + "num_cpus", + "plugin", + "typemap", + "url", +] + +[[package]] +name = "itertools" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" + +[[package]] +name = "jpeg-decoder" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b47b4c4e017b01abdc5bcc126d2d1002e5a75bbe3ce73f9f4f311a916363704" +dependencies = [ + "byteorder", + "rayon", +] + +[[package]] +name = "jsonwebtoken" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d438ea707d465c230305963b67f8357a1d56fcfad9434797d7cb1c46c2e41df" +dependencies = [ + "base64", + "chrono", + "ring", + "serde 1.0.110", + "serde_derive", + "serde_json", + "untrusted", +] + +[[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.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f" + +[[package]] +name = "linked-hash-map" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" + +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +dependencies = [ + "log 0.4.8", +] + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "logger" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c9172cb4c2f6c52117e25570983edcbb322f130b1031ae5d5d6b1abe7eeb493" +dependencies = [ + "iron", + "log 0.3.9", + "time", +] + +[[package]] +name = "lzw" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" + +[[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 = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" + +[[package]] +name = "memoffset" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" +dependencies = [ + "autocfg 1.0.0", +] + +[[package]] +name = "mime" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" +dependencies = [ + "log 0.3.9", +] + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mime_guess" +version = "1.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216929a5ee4dd316b1702eedf5e74548c123d370f47841ceaac38ca154690ca3" +dependencies = [ + "mime 0.2.6", + "phf", + "phf_codegen", + "unicase 1.4.2", +] + +[[package]] +name = "mime_guess" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +dependencies = [ + "mime 0.3.16", + "unicase 2.6.0", +] + +[[package]] +name = "miniz_oxide" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" +dependencies = [ + "adler32", +] + +[[package]] +name = "modifier" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58" + +[[package]] +name = "multipart" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92f54eb45230c3aa20864ccf0c277eeaeadcf5e437e91731db498dbf7fbe0ec6" +dependencies = [ + "buf_redux", + "httparse", + "log 0.3.9", + "mime 0.2.6", + "mime_guess 1.8.8", + "rand 0.3.23", + "safemem 0.2.0", + "tempdir", + "twoway", +] + +[[package]] +name = "mustache" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51956ef1c5d20a1384524d91e616fb44dfc7d8f249bf696d49c97dd3289ecab5" +dependencies = [ + "log 0.3.9", + "serde 1.0.110", +] + +[[package]] +name = "num" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational 0.1.42", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" +dependencies = [ + "num-integer", + "num-traits", + "rand 0.4.6", + "rustc-serialize", +] + +[[package]] +name = "num-complex" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b288631d7878aaf59442cffd36910ea604ecd7745c36054328595114001c9656" +dependencies = [ + "num-traits", + "rustc-serialize", +] + +[[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-iter" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" +dependencies = [ + "autocfg 1.0.0", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", + "rustc-serialize", +] + +[[package]] +name = "num-rational" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +dependencies = [ + "autocfg 1.0.0", + "num-integer", + "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 = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "orizentic" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f4af9d9002d3b129cdad6ebdb5b745b2b7d5e8c1c85c8addd7b447695af6a3" +dependencies = [ + "chrono", + "clap", + "itertools", + "jsonwebtoken", + "serde 1.0.110", + "serde_derive", + "serde_json", + "uuid 0.6.5", + "version_check 0.1.5", + "yaml-rust", +] + +[[package]] +name = "params" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c789fdad2cfdaa551ea0e3a9eadb74c5d634968a9fb3a8c767d89be470d21589" +dependencies = [ + "bodyparser", + "iron", + "multipart", + "num", + "plugin", + "serde_json", + "tempdir", + "urlencoded", +] + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" + +[[package]] +name = "persistent" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8fa0009c4f3d350281309909c618abddf10bb7e3145f28410782f6a5ec74c5" +dependencies = [ + "iron", + "plugin", +] + +[[package]] +name = "phf" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" +dependencies = [ + "phf_shared", + "rand 0.6.5", +] + +[[package]] +name = "phf_shared" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" +dependencies = [ + "siphasher", + "unicase 1.4.2", +] + +[[package]] +name = "plugin" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0" +dependencies = [ + "typemap", +] + +[[package]] +name = "png" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ccdd66f6fe4b2433b07e4728e9a013e43233120427046e93ceb709c3a439bf" +dependencies = [ + "bitflags", + "crc32fast", + "deflate", + "miniz_oxide", +] + +[[package]] +name = "proc-macro2" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53f5ffe53a6b28e37c9c1ce74893477864d64f74778a93a4beb43c8fa167f639" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42934bc9c8ab0d3b273a16d8551c8f0fcff46be73276ca083ec2414c15c4ba5e" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +dependencies = [ + "libc", + "rand 0.4.6", +] + +[[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", +] + +[[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", + "rand_core 0.4.2", + "rand_hc", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi", +] + +[[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_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_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_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", +] + +[[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", +] + +[[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 = "rayon" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f02856753d04e03e26929f820d0a0a337ebe71f849801eea335d464b349080" +dependencies = [ + "autocfg 1.0.0", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e92e15d89083484e11353891f1af602cc661426deb9564c298b270c726973280" +dependencies = [ + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "lazy_static", + "num_cpus", +] + +[[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 = "remove_dir_all" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +dependencies = [ + "winapi", +] + +[[package]] +name = "ring" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" +dependencies = [ + "cc", + "lazy_static", + "libc", + "untrusted", +] + +[[package]] +name = "route-recognizer" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea509065eb0b3c446acdd0102f0d46567dc30902dc0be91d6552035d92b0f4f8" + +[[package]] +name = "router" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc63b6f3b8895b0d04e816b2b1aa58fdba2d5acca3cbb8f0ab8e017347d57397" +dependencies = [ + "iron", + "route-recognizer", + "url", +] + +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" + +[[package]] +name = "ryu" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" + +[[package]] +name = "safemem" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b623917345a631dc9608d5194cc206b3fe6c3554cd1c75b937e55e285254af" + +[[package]] +name = "serde" +version = "1.0.110" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.110" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" +dependencies = [ + "itoa", + "ryu", + "serde 1.0.110", +] + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", +] + +[[package]] +name = "siphasher" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" + +[[package]] +name = "smallvec" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "syn" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1425de3c33b0941002740a420b1a906a350b88d08b82b2c8a01035a3f9447bac" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[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 = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tiff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f3b8a87c4da944c3f27e5943289171ac71a6150a79ff6bacfff06d159dfff2f" +dependencies = [ + "byteorder", + "lzw", + "miniz_oxide", +] + +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "traitobject" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" + +[[package]] +name = "twoway" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" +dependencies = [ + "memchr 2.3.3", +] + +[[package]] +name = "typeable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" + +[[package]] +name = "typemap" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6" +dependencies = [ + "unsafe-any", +] + +[[package]] +name = "typenum" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" + +[[package]] +name = "unicase" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +dependencies = [ + "version_check 0.1.5", +] + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check 0.9.1", +] + +[[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", +] + +[[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.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" + +[[package]] +name = "unsafe-any" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f" +dependencies = [ + "traitobject", +] + +[[package]] +name = "untrusted" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" + +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +dependencies = [ + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "urlencoded" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a52f50139118b60ae91af08bf15ed158817d34b91b9d24c11ffbe21195d33e3" +dependencies = [ + "bodyparser", + "iron", + "plugin", + "url", +] + +[[package]] +name = "uuid" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cfec50b0842181ba6e713151b72f4ec84a6a7e2c9c8a8a3ffc37bb1cd16b231" +dependencies = [ + "rand 0.3.23", + "serde 0.9.15", +] + +[[package]] +name = "uuid" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363" +dependencies = [ + "cfg-if", + "rand 0.4.6", +] + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" + +[[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-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[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 = "yaml-rust" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" +dependencies = [ + "linked-hash-map", +] diff --git a/file-service/Cargo.toml b/file-service/Cargo.toml new file mode 100644 index 0000000..fa1be72 --- /dev/null +++ b/file-service/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "file-service" +version = "0.1.0" +authors = ["savanni@luminescent-dreams.com"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +chrono = { version = "0.4", features = ["serde"] } +hex-string = "0.1.0" +iron = "0.6.1" +logger = "*" +mime = "0.3.16" +mime_guess = "2.0.3" +mustache = "0.9.0" +orizentic = "1.0.0" +params = "*" +router = "*" +serde_json = "*" +serde = { version = "1.0", features = ["derive"] } +sha2 = "0.8.2" +uuid = { version = "0.4", features = ["serde", "v4"] } +thiserror = "1.0.20" +image = "0.23.5" \ No newline at end of file diff --git a/file-service/authdb.json b/file-service/authdb.json new file mode 100644 index 0000000..3bd3ffb --- /dev/null +++ b/file-service/authdb.json @@ -0,0 +1 @@ +[{"jti":"ac3a46c6-3fa1-4d0a-af12-e7d3fefdc878","aud":"savanni","exp":1621351436,"iss":"savanni","iat":1589729036,"sub":"https://savanni.luminescent-dreams.com/file-service/","perms":["admin"]}] \ No newline at end of file diff --git a/file-service/fixtures/.metadata/.placeholder b/file-service/fixtures/.metadata/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/file-service/fixtures/.thumbnails/.placeholder b/file-service/fixtures/.thumbnails/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/file-service/fixtures/rawr.png b/file-service/fixtures/rawr.png new file mode 100644 index 0000000..edaf323 Binary files /dev/null and b/file-service/fixtures/rawr.png differ diff --git a/file-service/src/cookies.rs b/file-service/src/cookies.rs new file mode 100644 index 0000000..3e5c45b --- /dev/null +++ b/file-service/src/cookies.rs @@ -0,0 +1,61 @@ +use iron::headers; +use std::collections::HashMap; + +#[derive(Clone, Debug)] +pub struct Cookie { + pub name: String, + pub value: String, +} + +impl From<&str> for Cookie { + fn from(s: &str) -> Cookie { + let parts: Vec<&str> = s.split("=").collect(); + Cookie { + name: String::from(parts[0]), + value: String::from(parts[1]), + } + } +} + +impl From<&String> for Cookie { + fn from(s: &String) -> Cookie { + Cookie::from(s.as_str()) + } +} + +impl From for Cookie { + fn from(s: String) -> Cookie { + Cookie::from(s.as_str()) + } +} + +#[derive(Debug)] +pub struct CookieJar(HashMap); + +impl CookieJar { + pub fn new() -> CookieJar { + CookieJar(HashMap::new()) + } + + pub fn add_cookie(&mut self, name: String, value: Cookie) { + self.0.insert(name, value); + } + + pub fn lookup(&self, name: &str) -> Option<&Cookie> { + self.0.get(name) + } +} + +// Some(Cookie(["auth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhYzNhNDZjNi0zZmExLTRkMGEtYWYxMi1lN2QzZmVmZGM4NzgiLCJhdWQiOiJzYXZhbm5pIiwiZXhwIjoxNjIxMzUxNDM2LCJpc3MiOiJzYXZhbm5pIiwiaWF0IjoxNTg5NzI5MDM2LCJzdWIiOiJodHRwczovL3NhdmFubmkubHVtaW5lc2NlbnQtZHJlYW1zLmNvbS9maWxlLXNlcnZpY2UvIiwicGVybXMiOlsiYWRtaW4iXX0.8zjAbZ7Ut0d6EcDeyik39GKhXvH4qkMDdaiQVNKWiuM"])) +impl From<&headers::Cookie> for CookieJar { + fn from(c: &headers::Cookie) -> CookieJar { + let jar = CookieJar::new(); + + let headers::Cookie(cs) = c; + cs.iter().fold(jar, |mut jar, c_| { + let cookie = Cookie::from(c_); + jar.add_cookie(cookie.name.clone(), cookie); + jar + }) + } +} diff --git a/file-service/src/lib/error.rs b/file-service/src/lib/error.rs new file mode 100644 index 0000000..53dc55f --- /dev/null +++ b/file-service/src/lib/error.rs @@ -0,0 +1,31 @@ +use std::path::PathBuf; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error("not implemented")] + NotImplemented, + + #[error("file not found: `{0}`")] + FileNotFound(PathBuf), + + #[error("file is not an image: `{0}`")] + NotAnImage(PathBuf), + + #[error("path is not a file: `{0}`")] + NotAFile(PathBuf), + + #[error("Image loading error")] + ImageError(#[from] image::ImageError), + + #[error("IO error")] + IOError(#[from] std::io::Error), + + #[error("JSON error")] + JSONError(#[from] serde_json::error::Error), + + #[error("UTF8 Error")] + UTF8Error(#[from] std::str::Utf8Error), +} + +pub type Result = std::result::Result; diff --git a/file-service/src/lib/file.rs b/file-service/src/lib/file.rs new file mode 100644 index 0000000..3a085fd --- /dev/null +++ b/file-service/src/lib/file.rs @@ -0,0 +1,151 @@ +use super::error::{Error, Result}; +use super::fileinfo::FileInfo; +use super::thumbnail::Thumbnail; +use std::fs::{copy, read_dir, remove_file}; +use std::path::{Path, PathBuf}; + +#[derive(Debug)] +pub struct File { + info: FileInfo, + tn: Thumbnail, + root: PathBuf, +} + +impl File { + pub fn new( + id: &str, + root: &Path, + temp_path: &PathBuf, + filename: &Option, + ) -> Result { + let mut dest_path = PathBuf::from(root); + dest_path.push(id); + match filename { + Some(fname) => match fname.extension() { + Some(ext) => { + dest_path.set_extension(ext); + () + } + None => (), + }, + None => (), + }; + copy(temp_path, dest_path.clone())?; + let info = FileInfo::from_path(&dest_path)?; + let tn = Thumbnail::from_path(&dest_path)?; + Ok(File { + info, + tn, + root: PathBuf::from(root), + }) + } + + pub fn open(id: &str, root: &Path) -> Result { + let mut file_path = PathBuf::from(root); + file_path.push(id.clone()); + + if !file_path.exists() { + return Err(Error::FileNotFound(file_path)); + } + if !file_path.is_file() { + return Err(Error::NotAFile(file_path)); + } + + let info = match FileInfo::open(id, root) { + Ok(i) => Ok(i), + Err(Error::FileNotFound(_)) => { + let info = FileInfo::from_path(&file_path)?; + info.save(&root)?; + Ok(info) + } + Err(err) => Err(err), + }?; + + let tn = Thumbnail::open(id, root)?; + + Ok(File { + info, + tn, + root: PathBuf::from(root), + }) + } + + pub fn list(root: &Path) -> Vec> { + let dir_iter = read_dir(&root).unwrap(); + dir_iter + .filter(|entry| { + let entry_ = entry.as_ref().unwrap(); + let filename = entry_.file_name(); + !(filename.to_string_lossy().starts_with(".")) + }) + .map(|entry| { + let entry_ = entry.unwrap(); + let id = entry_.file_name().into_string().unwrap(); + File::open(&id, root) + }) + .collect() + } + + pub fn info(&self) -> FileInfo { + self.info.clone() + } + + pub fn thumbnail(&self) -> Thumbnail { + self.tn.clone() + } + + pub fn stream(&self) -> Result { + let mut path = self.root.clone(); + path.push(self.info.id.clone()); + std::fs::File::open(path).map_err(Error::from) + } + + pub fn delete(&self) -> Result<()> { + let mut path = self.root.clone(); + path.push(self.info.id.clone()); + remove_file(path)?; + self.tn.delete()?; + self.info.delete() + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::lib::utils::FileCleanup; + use std::path::{Path, PathBuf}; + + #[test] + fn it_opens_a_file() { + let _md = FileCleanup(PathBuf::from("fixtures/.metadata/rawr.png.json")); + let _tn = FileCleanup(PathBuf::from("fixtures/.thumbnails/rawr.png")); + + File::open("rawr.png", Path::new("fixtures/")).expect("to succeed"); + } + + #[test] + fn it_can_return_a_thumbnail() { + let f = File::open("rawr.png", Path::new("fixtures/")).expect("to succeed"); + assert_eq!( + f.thumbnail(), + Thumbnail { + id: String::from("rawr.png"), + root: PathBuf::from("fixtures/"), + }, + ); + } + + #[test] + fn it_can_return_a_file_stream() { + let f = File::open("rawr.png", Path::new("fixtures/")).expect("to succeed"); + f.stream().expect("to succeed"); + } + + #[test] + fn it_raises_an_error_when_file_not_found() { + match File::open("garbage", Path::new("fixtures/")) { + Err(Error::FileNotFound(_)) => assert!(true), + _ => assert!(false), + } + } +} diff --git a/file-service/src/lib/fileinfo.rs b/file-service/src/lib/fileinfo.rs new file mode 100644 index 0000000..ee8350e --- /dev/null +++ b/file-service/src/lib/fileinfo.rs @@ -0,0 +1,160 @@ +use chrono::prelude::*; +use hex_string::HexString; +use serde::{Deserialize, Serialize}; +use serde_json; +use sha2::{Digest, Sha256}; +use std::fs::remove_file; +use std::io::{Read, Write}; +use std::path::{Path, PathBuf}; + +use super::error::{Error, Result}; +use super::utils::append_extension; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct FileInfo { + pub id: String, + pub size: u64, + pub created: DateTime, + pub file_type: String, + pub hash: String, + + #[serde(skip)] + root: PathBuf, +} + +impl FileInfo { + pub fn save(&self, root: &Path) -> Result<()> { + let ser = serde_json::to_string(self).unwrap(); + std::fs::File::create(FileInfo::metadata_path(&self.id, root)) + .and_then(|mut stream| stream.write(ser.as_bytes()).map(|_| (()))) + .map_err(Error::from) + } + + pub fn open(id: &str, root: &Path) -> Result { + let mut buf = Vec::new(); + + let md_path = FileInfo::metadata_path(id, root); + std::fs::File::open(md_path.clone()) + .and_then(|mut stream| stream.read_to_end(&mut buf)) + .map_err(move |err| match err.kind() { + std::io::ErrorKind::NotFound => Error::FileNotFound(md_path), + _ => Error::IOError(err), + })?; + + let str_repr = std::str::from_utf8(&buf)?; + + serde_json::from_str(&str_repr).map_err(Error::from) + } + + pub fn from_path(path: &Path) -> Result { + match (path.is_file(), path.is_dir()) { + (false, false) => Err(Error::FileNotFound(PathBuf::from(path))), + (false, true) => Err(Error::NotAFile(PathBuf::from(path))), + (true, _) => Ok(()), + }?; + + let metadata = path.metadata().map_err(Error::IOError)?; + let id = path + .file_name() + .map(|s| String::from(s.to_string_lossy())) + .ok_or(Error::NotAFile(PathBuf::from(path)))?; + let created = metadata + .created() + .map(|m| DateTime::from(m)) + .map_err(|err| Error::IOError(err))?; + let file_type = String::from( + mime_guess::from_path(path) + .first_or_octet_stream() + .essence_str(), + ); + let hash = FileInfo::hash_file(path)?; + Ok(FileInfo { + id, + size: metadata.len(), + created: created, + file_type, + hash: hash.as_string(), + root: PathBuf::from(path.parent().unwrap()), + }) + } + + fn hash_file(path: &Path) -> Result { + let mut buf = Vec::new(); + let mut file = std::fs::File::open(path).map_err(Error::from)?; + + file.read_to_end(&mut buf).map_err(Error::from)?; + let mut vec = Vec::new(); + vec.extend_from_slice(Sha256::digest(&buf).as_slice()); + Ok(HexString::from_bytes(&vec)) + } + + fn metadata_path(id: &str, root: &Path) -> PathBuf { + let mut path = PathBuf::from(root); + path.push(".metadata"); + path.push(id.clone()); + append_extension(&path, "json") + } + + pub fn delete(&self) -> Result<()> { + let path = FileInfo::metadata_path(&self.id, &self.root); + remove_file(path).map_err(Error::from) + } +} + +#[cfg(test)] +mod test { + use super::*; + + use crate::lib::utils::FileCleanup; + + #[test] + fn it_generates_information_from_file_path() { + let path = Path::new("fixtures/rawr.png"); + match FileInfo::from_path(&path) { + Ok(FileInfo { + id, + size, + file_type, + hash, + .. + }) => { + assert_eq!(id, "rawr.png"); + assert_eq!(size, 23777); + assert_eq!(file_type, "image/png"); + assert_eq!( + hash, + "b6cd35e113b95d62f53d9cbd27ccefef47d3e324aef01a2db6c0c6d3a43c89ee" + ); + } + Err(err) => { + println!("error loading file path: {}", err); + assert!(false); + } + } + } + + #[test] + fn it_saves_and_loads_metadata() { + let path = Path::new("fixtures/rawr.png"); + let _ = FileCleanup(append_extension(path, "json")); + let info = FileInfo::from_path(&path).unwrap(); + info.save(Path::new("fixtures")).unwrap(); + + assert!(Path::new("fixtures/.metadata/rawr.png.json").is_file()); + + let info_ = FileInfo::open("rawr.png", Path::new("fixtures")).unwrap(); + assert_eq!(info_.id, "rawr.png"); + assert_eq!(info_.size, 23777); + assert_eq!(info_.created, info.created); + assert_eq!(info_.file_type, "image/png"); + assert_eq!(info_.hash, info.hash); + } + + #[test] + fn it_extends_a_file_extension() { + assert_eq!( + append_extension(Path::new("fixtures/rawr.png"), "json"), + Path::new("fixtures/rawr.png.json") + ); + } +} diff --git a/file-service/src/lib/mod.rs b/file-service/src/lib/mod.rs new file mode 100644 index 0000000..40e80c2 --- /dev/null +++ b/file-service/src/lib/mod.rs @@ -0,0 +1,56 @@ +use std::path::{Path, PathBuf}; +use uuid::Uuid; + +mod error; +mod file; +mod fileinfo; +mod thumbnail; +mod utils; + +pub use error::{Error, Result}; +pub use file::File; +pub use fileinfo::FileInfo; +pub use thumbnail::Thumbnail; + +pub struct App { + files_root: PathBuf, +} + +impl App { + pub fn new(files_root: &Path) -> App { + App { + files_root: PathBuf::from(files_root), + } + } + + pub fn list_files(&self) -> Vec> { + File::list(&self.files_root) + } + + pub fn add_file(&mut self, temp_path: &PathBuf, filename: &Option) -> Result { + let id = Uuid::new_v4().hyphenated().to_string(); + File::new(&id, &self.files_root, temp_path, filename) + } + + pub fn delete_file(&mut self, id: String) -> Result<()> { + let f = File::open(&id, &self.files_root)?; + f.delete() + } + + pub fn get_metadata(&self, id: String) -> Result { + FileInfo::open(&id, &self.files_root) + } + + pub fn get_file(&self, id: String) -> Result<(FileInfo, std::fs::File)> { + let f = File::open(&id, &self.files_root)?; + let info = f.info(); + let stream = f.stream()?; + Ok((info, stream)) + } + + pub fn get_thumbnail(&self, id: &str) -> Result<(FileInfo, std::fs::File)> { + let f = File::open(id, &self.files_root)?; + let stream = f.thumbnail().stream()?; + Ok((f.info(), stream)) + } +} diff --git a/file-service/src/lib/thumbnail.rs b/file-service/src/lib/thumbnail.rs new file mode 100644 index 0000000..738b4aa --- /dev/null +++ b/file-service/src/lib/thumbnail.rs @@ -0,0 +1,82 @@ +use image::imageops::FilterType; +use std::fs::remove_file; +use std::path::{Path, PathBuf}; + +use super::error::{Error, Result}; + +#[derive(Clone, Debug, PartialEq)] +pub struct Thumbnail { + pub id: String, + pub root: PathBuf, +} + +impl Thumbnail { + pub fn open(id: &str, root: &Path) -> Result { + let mut source_path = PathBuf::from(root); + source_path.push(id); + + let self_ = Thumbnail { + id: String::from(id), + root: PathBuf::from(root), + }; + + let thumbnail_path = Thumbnail::thumbnail_path(id, root); + if !thumbnail_path.exists() { + let img = image::open(source_path)?; + let tn = img.resize(640, 640, FilterType::Nearest); + tn.save(thumbnail_path)?; + } + + Ok(self_) + } + + pub fn from_path(path: &Path) -> Result { + let id = path + .file_name() + .map(|s| String::from(s.to_string_lossy())) + .ok_or(Error::NotAnImage(PathBuf::from(path)))?; + + let root = path + .parent() + .ok_or(Error::FileNotFound(PathBuf::from(path)))?; + + Thumbnail::open(&id, root) + } + + fn thumbnail_path(id: &str, root: &Path) -> PathBuf { + let mut path = PathBuf::from(root); + path.push(".thumbnails"); + path.push(id.clone()); + path + } + + pub fn stream(&self) -> Result { + let thumbnail_path = Thumbnail::thumbnail_path(&self.id, &self.root); + std::fs::File::open(thumbnail_path.clone()).map_err(|err| { + if err.kind() == std::io::ErrorKind::NotFound { + Error::FileNotFound(thumbnail_path) + } else { + Error::from(err) + } + }) + } + + pub fn delete(&self) -> Result<()> { + let path = Thumbnail::thumbnail_path(&self.id, &self.root); + remove_file(path).map_err(Error::from) + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::lib::utils::FileCleanup; + + #[test] + fn it_creates_a_thumbnail_if_one_does_not_exist() { + let _ = FileCleanup(PathBuf::from("fixtures/.thumbnails/rawr.png")); + let _ = + Thumbnail::open("rawr.png", Path::new("fixtures")).expect("thumbnail open must work"); + assert!(Path::new("fixtures/.thumbnails/rawr.png").is_file()); + } +} diff --git a/file-service/src/lib/utils.rs b/file-service/src/lib/utils.rs new file mode 100644 index 0000000..9427daf --- /dev/null +++ b/file-service/src/lib/utils.rs @@ -0,0 +1,17 @@ +use std::path::{Path, PathBuf}; + +pub struct FileCleanup(pub PathBuf); + +impl Drop for FileCleanup { + fn drop(&mut self) { + let _ = std::fs::remove_file(&self.0); + } +} + +pub fn append_extension(path: &Path, extra_ext: &str) -> PathBuf { + let ext_ = match path.extension() { + None => String::from(extra_ext), + Some(ext) => [ext.to_string_lossy(), std::borrow::Cow::from(extra_ext)].join("."), + }; + path.with_extension(ext_) +} diff --git a/file-service/src/main.rs b/file-service/src/main.rs new file mode 100644 index 0000000..67f1401 --- /dev/null +++ b/file-service/src/main.rs @@ -0,0 +1,341 @@ +use iron::headers; +use iron::middleware::Handler; +use iron::modifiers::{Header, Redirect}; +use iron::prelude::*; +use iron::response::BodyReader; +use iron::status; +use mustache::{compile_path, Template}; +use orizentic::{Permissions, ResourceName, Secret}; +use params::{Params, Value}; +use router::Router; +use serde::Serialize; +use std::collections::HashMap; +use std::fs::File; +use std::io::Read; +use std::path::Path; +use std::path::PathBuf; +use std::sync::{Arc, RwLock}; + +mod cookies; +mod lib; +mod middleware; + +use lib::{App, FileInfo}; +use middleware::{Authentication, RestForm}; + +fn is_admin(resource: &ResourceName, permissions: &Permissions) -> bool { + let Permissions(perms) = permissions; + ResourceName(String::from( + "https://savanni.luminescent-dreams.com/file-service/", + )) == *resource + && perms.contains(&String::from("admin")) +} + +pub fn compare_etags(info: FileInfo, etag_list: &headers::IfNoneMatch) -> bool { + let current_etag = headers::EntityTag::new(false, info.hash); + match etag_list { + headers::IfNoneMatch::Any => false, + headers::IfNoneMatch::Items(lst) => lst.iter().any(|etag| etag.weak_eq(¤t_etag)), + } +} + +mod files { + use super::*; + + pub struct IndexHandler { + pub app: Arc>, + pub template: Template, + } + + #[derive(Serialize)] + pub enum TemplateFile { + #[serde(rename = "error")] + Error { error: String }, + #[serde(rename = "file")] + File { + id: String, + size: u64, + date: String, + type_: String, + }, + } + + #[derive(Serialize)] + pub struct IndexTemplateParams { + files: Vec, + } + + impl Handler for IndexHandler { + fn handle(&self, req: &mut Request) -> IronResult { + let app = self.app.read().unwrap(); + let m_token = req.extensions.get::(); + match m_token { + Some(token) => { + if token.check_authorizations(is_admin) { + let files: Vec = app + .list_files() + .into_iter() + .map(|entry| match entry { + Ok(file) => TemplateFile::File { + id: file.info().id, + size: file.info().size, + date: format!( + "{}", + file.info().created.format("%Y-%m-%d %H:%M:%S") + ), + type_: file.info().file_type, + }, + Err(err) => TemplateFile::Error { + error: format!("{}", err), + }, + }) + .collect(); + Ok(Response::with(( + status::Ok, + Header(headers::ContentType::html()), + Header(headers::SetCookie(vec![format!("auth={}", token.text)])), + self.template + .render_to_string(&IndexTemplateParams { files }) + .expect("the template to render"), + ))) + } else { + Ok(Response::with(status::Forbidden)) + } + } + None => Ok(Response::with(status::Forbidden)), + } + } + } + + pub struct GetHandler { + pub app: Arc>, + } + + impl Handler for GetHandler { + fn handle(&self, req: &mut Request) -> IronResult { + let app = self.app.read().unwrap(); + let capture = req.extensions.get::().unwrap().clone(); + let old_etags = req.headers.get::(); + match capture.find("id") { + Some(id) => { + let info = app.get_metadata(String::from(id)); + match (info, old_etags) { + (Ok(info_), Some(if_none_match)) => { + if compare_etags(info_, if_none_match) { + return Ok(Response::with(status::NotModified)); + } + } + _ => (), + } + match app.get_file(String::from(id)) { + Ok((info, stream)) => Ok(Response::with(( + status::Ok, + Header(headers::ContentType( + info.file_type.parse::().unwrap(), + )), + Header(headers::ETag(headers::EntityTag::new(false, info.hash))), + BodyReader(stream), + ))), + Err(_err) => Ok(Response::with(status::NotFound)), + } + } + _ => Ok(Response::with(status::BadRequest)), + } + } + } + + pub struct GetThumbnailHandler { + pub app: Arc>, + } + + impl Handler for GetThumbnailHandler { + fn handle(&self, req: &mut Request) -> IronResult { + let app = self.app.read().unwrap(); + let capture = req.extensions.get::().unwrap().clone(); + let old_etags = req.headers.get::(); + match capture.find("id") { + Some(id) => { + let info = app.get_metadata(String::from(id)); + match (info, old_etags) { + (Ok(info_), Some(if_none_match)) => { + if compare_etags(info_, if_none_match) { + return Ok(Response::with(status::NotModified)); + } + } + _ => (), + } + match app.get_thumbnail(id) { + Ok((info, stream)) => Ok(Response::with(( + status::Ok, + Header(headers::ContentType( + info.file_type.parse::().unwrap(), + )), + Header(headers::ETag(headers::EntityTag::new(false, info.hash))), + BodyReader(stream), + ))), + Err(_err) => Ok(Response::with(status::NotFound)), + } + } + _ => Ok(Response::with(status::BadRequest)), + } + } + } + pub struct PostHandler { + pub app: Arc>, + } + + impl Handler for PostHandler { + fn handle(&self, req: &mut Request) -> IronResult { + let mut app = self.app.write().unwrap(); + let m_token = req.extensions.get::(); + match m_token { + Some(token) => { + if token.check_authorizations(is_admin) { + let params = req.get_ref::().unwrap(); + if let Value::File(f_info) = params.get("file").unwrap() { + match app.add_file( + &f_info.path, + &f_info.filename.clone().map(|fname| PathBuf::from(fname)), + ) { + Ok(_) => Ok(Response::with(( + status::MovedPermanently, + Redirect(router::url_for(req, "index", HashMap::new())), + ))), + Err(_) => Ok(Response::with(status::InternalServerError)), + } + } else { + Ok(Response::with(status::BadRequest)) + } + } else { + Ok(Response::with(status::Forbidden)) + } + } + None => Ok(Response::with(status::Forbidden)), + } + } + } + + pub struct DeleteHandler { + pub app: Arc>, + } + + impl Handler for DeleteHandler { + fn handle(&self, req: &mut Request) -> IronResult { + let mut app = self.app.write().unwrap(); + let capture = req.extensions.get::().unwrap().clone(); + let m_token = req.extensions.get::(); + match m_token { + Some(token) => { + if token.check_authorizations(is_admin) { + match capture.find("id") { + Some(id) => match app.delete_file(String::from(id)) { + Ok(()) => Ok(Response::with(( + status::MovedPermanently, + Redirect(router::url_for(req, "index", HashMap::new())), + ))), + Err(_) => Ok(Response::with(status::InternalServerError)), + }, + None => Ok(Response::with(status::BadRequest)), + } + } else { + Ok(Response::with(status::Forbidden)) + } + } + None => Ok(Response::with(status::Forbidden)), + } + } + } +} + +fn css(_: &mut Request) -> IronResult { + let mut css: String = String::from(""); + File::open("templates/style.css") + .unwrap() + .read_to_string(&mut css) + .unwrap(); + Ok(Response::with(( + status::Ok, + Header(headers::ContentType(iron::mime::Mime( + iron::mime::TopLevel::Text, + iron::mime::SubLevel::Css, + vec![], + ))), + css, + ))) +} + +fn script(_: &mut Request) -> IronResult { + let mut js: String = String::from(""); + File::open("templates/script.js") + .unwrap() + .read_to_string(&mut js) + .unwrap(); + Ok(Response::with(( + status::Ok, + Header(headers::ContentType(iron::mime::Mime( + iron::mime::TopLevel::Text, + iron::mime::SubLevel::Javascript, + vec![], + ))), + js, + ))) +} + +fn main() { + let auth_db_path = std::env::var("ORIZENTIC_DB").unwrap(); + let secret = Secret(Vec::from( + std::env::var("ORIZENTIC_SECRET").unwrap().as_bytes(), + )); + let auth_middleware = Authentication::new(secret, auth_db_path); + + let app = Arc::new(RwLock::new(App::new(Path::new( + &std::env::var("FILE_SHARE_DIR").unwrap(), + )))); + + let mut router = Router::new(); + router.get( + "/", + files::IndexHandler { + app: app.clone(), + template: compile_path("templates/index.html").expect("the template to compile"), + }, + "index", + ); + + router.get( + "/:id", + files::GetFileHandler { + app: app.clone(), + template: compile_path("templates/file.html").expect("the template to compile"), + }, + "get-file-page", + ); + + router.get( + "/:id/raw", + files::GetHandler { app: app.clone() }, + "get-file", + ); + + router.get( + "/:id/tn", + files::GetThumbnailHandler { app: app.clone() }, + "get-thumbnail", + ); + + router.post("/", files::PostHandler { app: app.clone() }, "upload-file"); + + router.delete( + "/:id", + files::DeleteHandler { app: app.clone() }, + "delete-file", + ); + router.get("/css", css, "styles"); + router.get("/script", script, "script"); + + let mut chain = Chain::new(router); + chain.link_before(auth_middleware); + chain.link_before(RestForm {}); + + Iron::new(chain).http("0.0.0.0:3000").unwrap(); +} diff --git a/file-service/src/middleware/authentication.rs b/file-service/src/middleware/authentication.rs new file mode 100644 index 0000000..87c1445 --- /dev/null +++ b/file-service/src/middleware/authentication.rs @@ -0,0 +1,51 @@ +use iron::headers; +use iron::middleware::BeforeMiddleware; +use iron::prelude::*; +use iron::typemap::Key; +use orizentic::{filedb, OrizenticCtx, Secret}; +use params::{FromValue, Params}; + +use crate::cookies::{Cookie, CookieJar}; + +pub struct Authentication { + pub auth: OrizenticCtx, +} + +impl Key for Authentication { + type Value = orizentic::VerifiedToken; +} + +impl Authentication { + pub fn new(secret: Secret, auth_db_path: String) -> Authentication { + let claims = filedb::load_claims_from_file(&auth_db_path).expect("claims did not load"); + let orizentic = OrizenticCtx::new(secret, claims); + Authentication { auth: orizentic } + } + + fn authenticate_user( + &self, + token_str: String, + ) -> Result { + self.auth.decode_and_validate_text(&token_str) + } +} + +impl BeforeMiddleware for Authentication { + fn before(&self, req: &mut Request) -> IronResult<()> { + let params = req.get_ref::().unwrap(); + let token = match params.get("auth").and_then(|v| String::from_value(v)) { + Some(token_str) => self.authenticate_user(token_str).ok(), + None => { + let m_jar = req + .headers + .get::() + .map(|cookies| CookieJar::from(cookies)); + m_jar + .and_then(|jar| jar.lookup("auth").cloned()) + .and_then(|Cookie { value, .. }| self.authenticate_user(value.clone()).ok()) + } + }; + token.map(|t| req.extensions.insert::(t)); + Ok(()) + } +} diff --git a/file-service/src/middleware/logging.rs b/file-service/src/middleware/logging.rs new file mode 100644 index 0000000..2aceb1d --- /dev/null +++ b/file-service/src/middleware/logging.rs @@ -0,0 +1,16 @@ +use iron::middleware::{AfterMiddleware, BeforeMiddleware}; +use iron::prelude::*; + +pub struct Logging {} + +impl BeforeMiddleware for Logging { + fn before(&self, _: &mut Request) -> IronResult<()> { + Ok(()) + } +} + +impl AfterMiddleware for Logging { + fn after(&self, _: &mut Request, res: Response) -> IronResult { + Ok(res) + } +} diff --git a/file-service/src/middleware/mod.rs b/file-service/src/middleware/mod.rs new file mode 100644 index 0000000..1bab46b --- /dev/null +++ b/file-service/src/middleware/mod.rs @@ -0,0 +1,6 @@ +mod authentication; +mod logging; +mod restform; + +pub use authentication::Authentication; +pub use restform::RestForm; diff --git a/file-service/src/middleware/restform.rs b/file-service/src/middleware/restform.rs new file mode 100644 index 0000000..5cfadd9 --- /dev/null +++ b/file-service/src/middleware/restform.rs @@ -0,0 +1,34 @@ +use iron::method::Method; +use iron::middleware::BeforeMiddleware; +use iron::prelude::*; +use params::{Params, Value}; + +pub struct RestForm {} + +impl RestForm { + fn method(&self, v: &Value) -> Option { + match v { + Value::String(method_str) => match method_str.as_str() { + "delete" => Some(Method::Delete), + _ => None, + }, + _ => None, + } + } +} + +impl BeforeMiddleware for RestForm { + fn before(&self, req: &mut Request) -> IronResult<()> { + if req.method == Method::Post { + let method = { + let params = req.get_ref::().unwrap(); + params + .get("_method") + .and_then(|m| self.method(m)) + .unwrap_or(Method::Post) + }; + req.method = method; + } + Ok(()) + } +} diff --git a/file-service/templates/file.html b/file-service/templates/file.html new file mode 100644 index 0000000..45002cc --- /dev/null +++ b/file-service/templates/file.html @@ -0,0 +1,15 @@ + + + + {{title}} + + + + + + + + + + + \ No newline at end of file diff --git a/file-service/templates/index.html b/file-service/templates/index.html new file mode 100644 index 0000000..6c44b20 --- /dev/null +++ b/file-service/templates/index.html @@ -0,0 +1,54 @@ + + + + Admin list of files + + + + + +

Admin list of files

+ +
+
+
+ + +
+ +
+
+ +
+ {{#files}} +
+ {{#error}} +
+

{{error}}

+
+ {{/error}} + + {{#file}} +
+ +
+
+
    +
  • {{date}}
  • +
  • {{type_}}
  • +
  • {{size}}
  • +
+
+
+ + +
+
+
+ {{/file}} +
+ {{/files}} +
+ + + \ No newline at end of file diff --git a/file-service/templates/script.js b/file-service/templates/script.js new file mode 100644 index 0000000..9a820db --- /dev/null +++ b/file-service/templates/script.js @@ -0,0 +1,10 @@ +const selectFile = (selectorId) => { + console.log("wide arrow functions work: " + selectorId); + const input = document.querySelector("#" + selectorId + " input[type='file']") + const label = document.querySelector("#" + selectorId + " label") + input.addEventListener("change", (e) => { + if (input.files.length > 0) { + label.innerHTML = input.files[0].name + } + }) +} diff --git a/file-service/templates/style.css b/file-service/templates/style.css new file mode 100644 index 0000000..eeb6f8b --- /dev/null +++ b/file-service/templates/style.css @@ -0,0 +1,103 @@ +body { + font-family: 'Ariel', sans-serif; +} + +.files { + display: flex; + flex-wrap: wrap; +} + +.file { + display: flex; + margin: 1em; + border: 1px solid #449dfc; + border-radius: 5px; + padding: 1em; +} + +.thumbnail { + max-width: 320px; + margin: 1em; +} + +img { + max-width: 100%; +} + +[type="submit"] { + border-radius: 1em; + margin: 1em; + padding: 1em; +} + +.uploadform { + display: flex; + margin: 1em; + background-color: #e5f0fc; + border: 1px solid #449dfc; + border-radius: 5px; + padding: 1em; +} + +/* https://benmarshall.me/styling-file-inputs/ */ +[type="file"] { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + overflow: hidden; + padding: 0; + position: absolute !important; + white-space: nowrap; + width: 1px; +} + +[type="file"] + label { + background-color: rgb(0, 86, 112); + border-radius: 1em; + color: #fff; + cursor: pointer; + display: inline-block; + padding: 1em; + margin: 1em; + transition: background-color 0.3s; +} + +[type="file"]:focus + label, +[type="file"] + label:hover { + background-color: #67b0ff; +} + +[type="file"]:focus + label { + outline: 1px dotted #000; + outline: -webkit-focus-ring-color auto 5px; +} + +@media screen and (max-width: 980px) { /* This is the screen width of a OnePlus 5t */ + body { + font-size: xx-large; + } + + [type="submit"] { + font-size: xx-large; + width: 100%; + } + + .uploadform { + display: flex; + } + + [type="file"] + label { + width: 100%; + } + + .thumbnail { + max-width: 100%; + margin: 1em; + } + + .file { + display: flex; + flex-direction: column; + width: 100%; + } +}