From a6f5b850c7d794f53695d62cdca914b7a691ef83 Mon Sep 17 00:00:00 2001 From: peterrabbit <pierre.jarriges@tutanota.com> Date: Sun, 18 Sep 2022 17:53:47 +0200 Subject: [PATCH] wip test static files services --- Cargo.lock | 187 ++++++++++++++++++-------------------- src/app/state.rs | 19 ++-- src/cookie.rs | 25 +++++ src/main.rs | 12 ++- src/service/admin.rs | 26 ++---- src/service/files.rs | 201 +++++++++++++++++++++++++++++++++++++++++ src/testing.rs | 2 +- src/website/website.rs | 6 ++ 8 files changed, 343 insertions(+), 135 deletions(-) create mode 100644 src/cookie.rs diff --git a/Cargo.lock b/Cargo.lock index 6b0eac1..ab32366 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,9 +44,9 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.2.1" +version = "3.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f9ffb6db08c1c3a1f4aef540f1a63193adc73c4fbd40b75a95fc8c5258f6e51" +checksum = "0c83abf9903e1f0ad9973cc4f7b9767fd5a03a583f51a5b7a339e07987cd2724" dependencies = [ "actix-codec", "actix-rt", @@ -191,9 +191,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.1.0" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27e8fe9ba4ae613c21f677c2cfaf0696c3744030c6f485b34634e502d6bb379" +checksum = "d48f7b6534e06c7bfc72ee91db7917d4af6afe23e7d223b51e68fffbb21e96b9" dependencies = [ "actix-codec", "actix-http", @@ -214,6 +214,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", + "http", "itoa 1.0.3", "language-tags", "log", @@ -232,9 +233,9 @@ dependencies = [ [[package]] name = "actix-web-codegen" -version = "4.0.1" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f270541caec49c15673b0af0e9a00143421ad4f118d2df7edcb68b627632f56" +checksum = "1fa9362663c8643d67b2d5eafba49e4cb2c8a053a29ed00a0bea121f17c76b13" dependencies = [ "actix-router", "proc-macro2", @@ -346,24 +347,24 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] [[package]] name = "alloc-no-stdlib" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ef4730490ad1c4eae5c4325b2a95f521d023e5c885853ff7aca0a6a1631db3" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697ed7edc0f1711de49ce108c541623a0af97c6c60b2f6e2b65229847ac843c2" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" dependencies = [ "alloc-no-stdlib", ] @@ -431,9 +432,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ "generic-array", ] @@ -473,9 +474,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "bytes" @@ -557,9 +558,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] @@ -629,9 +630,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ "block-buffer", "crypto-common", @@ -669,9 +670,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" dependencies = [ "atty", "humantime", @@ -704,11 +705,10 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] @@ -840,9 +840,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" dependencies = [ "bytes", "fnv", @@ -918,9 +918,9 @@ checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" [[package]] name = "httparse" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" @@ -936,11 +936,10 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -978,9 +977,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -1020,9 +1019,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.127" +version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "local-channel" @@ -1044,9 +1043,9 @@ checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1" [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" dependencies = [ "autocfg", "scopeguard", @@ -1061,12 +1060,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "memchr" version = "2.5.0" @@ -1091,9 +1084,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", ] @@ -1131,9 +1124,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" [[package]] name = "opaque-debug" @@ -1166,15 +1159,15 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pin-project-lite" @@ -1271,9 +1264,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] @@ -1390,9 +1383,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "serde" @@ -1429,9 +1422,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa 1.0.3", "ryu", @@ -1452,9 +1445,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77f4e7f65455545c2153c1253d25056825e77ee2533f0e41deb65a93a34852f" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if", "cpufeatures", @@ -1463,9 +1456,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", @@ -1498,9 +1491,9 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", @@ -1579,18 +1572,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.32" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" +checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.32" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" +checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783" dependencies = [ "proc-macro2", "quote", @@ -1599,12 +1592,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.12" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74b7cc93fc23ba97fde84f7eea56c55d1ba183f495c6715defdfc7b9cb8c870f" +checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b" dependencies = [ "itoa 1.0.3", - "js-sys", "libc", "num_threads", "time-macros", @@ -1633,9 +1625,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.20.1" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" +checksum = "0020c875007ad96677dcc890298f4b942882c5d4eb7cc8f439fc3bf813dc9c95" dependencies = [ "autocfg", "bytes", @@ -1675,9 +1667,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", @@ -1759,30 +1751,30 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "universal-hash" @@ -1802,13 +1794,12 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] @@ -1832,9 +1823,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1842,9 +1833,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", @@ -1857,9 +1848,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1867,9 +1858,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -1880,15 +1871,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/src/app/state.rs b/src/app/state.rs index 8b9fc0f..a6c29af 100644 --- a/src/app/state.rs +++ b/src/app/state.rs @@ -1,5 +1,6 @@ use crate::app::{AppArgs, AppConfig, AppPreferences}; -use rand::{distributions::Alphanumeric, Rng}; +use crate::cookie::SecureCookie; +use actix_web::cookie::Cookie; use structopt::StructOpt; #[derive(Clone)] @@ -42,15 +43,11 @@ impl AdminAuthToken { } } - pub fn generate(&mut self) { - // Thanks to https://stackoverflow.com/questions/54275459/how-do-i-create-a-random-string-by-sampling-from-alphanumeric-characters#54277357 - self.value = Some( - rand::thread_rng() - .sample_iter(&Alphanumeric) - .take(36) - .map(char::from) - .collect::<String>() - .to_ascii_lowercase(), - ) + pub fn update_value(&mut self) { + self.value = Some(SecureCookie::generate_token(36)) + } + + pub fn generate_cookie(&mut self) -> Cookie { + SecureCookie::new(&self.cookie_name, self.value.as_ref().unwrap()) } } diff --git a/src/cookie.rs b/src/cookie.rs new file mode 100644 index 0000000..460d47a --- /dev/null +++ b/src/cookie.rs @@ -0,0 +1,25 @@ +use actix_web::cookie::{time::Duration, Cookie, SameSite}; +use rand::{distributions::Alphanumeric, Rng}; + +pub struct SecureCookie; +impl SecureCookie { + pub fn new<'a>(name: &String, value: &String) -> Cookie<'a> { + Cookie::build(name.to_owned(), value.to_owned()) + .path("/") + .http_only(true) + .max_age(Duration::days(7)) + .same_site(SameSite::Strict) + .secure(true) + .finish() + } + + pub fn generate_token(size: usize) -> String { + // Thanks to https://stackoverflow.com/questions/54275459 + rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(size) + .map(char::from) + .collect::<String>() + .to_ascii_lowercase() + } +} diff --git a/src/main.rs b/src/main.rs index 54299c1..37f1d9e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ mod app; +mod cookie; mod middleware; mod service; mod static_files; @@ -11,6 +12,7 @@ use actix_web_lab::middleware::RedirectHttps; use app::AppState; use middleware::AuthService; use static_files::StaticFilesManager; +use std::sync::RwLock; use tls_config::tls_config; use website::WebSiteBuilder; @@ -34,17 +36,17 @@ async fn main() -> std::io::Result<()> { let srv_conf = tls_config(&app_state.config); let dir = website.static_files_manager.dir.clone(); - let mut_app_state = std::sync::RwLock::new(app_state); - let app_state = web::Data::new(mut_app_state); - let mut_website = web::Data::new(std::sync::RwLock::new(website)); + // let mut_app_state = RwLock::new(app_state); + // let app_state = web::Data::new(mut_app_state); + // let mut_website = web::Data::new(RwLock::new(website)); HttpServer::new(move || { App::new() .wrap(actix_web::middleware::Logger::default()) .wrap(actix_web::middleware::Compress::default()) .wrap(RedirectHttps::default().to_port(port_tls)) - .app_data(web::Data::clone(&app_state)) - .app_data(web::Data::clone(&mut_website)) + .app_data(web::Data::new(RwLock::new(app_state.clone()))) + .app_data(web::Data::new(RwLock::new(website.clone()))) .service( web::scope("/admin") .service(service::admin_login) diff --git a/src/service/admin.rs b/src/service/admin.rs index 6061c47..4bce663 100644 --- a/src/service/admin.rs +++ b/src/service/admin.rs @@ -1,6 +1,5 @@ use crate::AppState; use actix_web::{ - cookie::{time::Duration, Cookie, SameSite}, get, post, web::{Data, Form}, HttpRequest, HttpResponse, Responder, @@ -37,26 +36,13 @@ async fn admin_authenticate( }; if admin_username.eq(&credentials.username) && admin_pwd.eq(&credentials.password) { - let cookie_value = { - let mut app_state = app_state - .write() - .expect("Couldn't acquire write lock for RwLock<AppState>"); - app_state.admin_auth_token.generate(); - app_state - .admin_auth_token - .value - .as_ref() - .unwrap() - .to_owned() - }; + let mut app_state = app_state + .write() + .expect("Couldn't acquire write lock for RwLock<AppState>"); + + app_state.admin_auth_token.update_value(); + let cookie = app_state.admin_auth_token.generate_cookie(); - let cookie = Cookie::build(cookie_name, cookie_value) - .path("/") - .http_only(true) - .max_age(Duration::days(7)) - .same_site(SameSite::Strict) - .secure(true) - .finish(); return HttpResponse::Accepted().cookie(cookie).finish(); } else { let mut res = HttpResponse::Unauthorized().finish(); diff --git a/src/service/files.rs b/src/service/files.rs index e04a77d..f6972e3 100644 --- a/src/service/files.rs +++ b/src/service/files.rs @@ -139,3 +139,204 @@ async fn delete_static_file( Err(e) => HttpResponse::InternalServerError().body(format!("Error deleting file {:?}", e)), } } + +#[cfg(test)] +mod test_static_files_services { + use super::*; + use crate::{cookie::*, website::*, AppState}; + use actix_web::{ + http::{Method, StatusCode}, + test, + web::Bytes, + App, + }; + use std::sync::RwLock; + + fn create_simple_request() -> Bytes { + Bytes::from( + "--abbc761f78ff4d7cb7573b5a23f96ef0\r\n\ + Content-Disposition: form-data; name=\"file\"; filename=\"test.txt\"\r\n\ + Content-Type: text/plain; charset=utf-8\r\nContent-Length: 4\r\n\r\n\ + test\r\n\ + --abbc761f78ff4d7cb7573b5a23f96ef0\r\n\ + Content-Disposition: form-data; name=\"file\"; filename=\"data.txt\"\r\n\ + Content-Type: text/plain; charset=utf-8\r\nContent-Length: 4\r\n\r\n\ + data\r\n\ + --abbc761f78ff4d7cb7573b5a23f96ef0--\r\n", + ) + } + + // fn clear_testing_static(dir: &std::path::PathBuf) { + // std::fs::remove_dir_all(dir).unwrap(); + // } + + #[actix_web::test] + async fn post_files_unauthenticated_should_be_unauthorized() { + let app_state = AppState::new(); + let static_dir = std::path::PathBuf::from("./test"); + let ws = WebSiteBuilder::testing(&static_dir); + + let mut app = test::init_service( + App::new() + .app_data(web::Data::new(RwLock::new(app_state.clone()))) + .app_data(web::Data::new(RwLock::new(ws.clone()))) + .service(post_files), + ) + .await; + + let req = test::TestRequest::with_uri("/post-files") + .method(Method::POST) + .append_header(( + "Content-Type", + "multipart/form-data; boundary=\"abbc761f78ff4d7cb7573b5a23f96ef0\"", + )) + .cookie(SecureCookie::new( + &"wrong-cookie".to_string(), + &SecureCookie::generate_token(36), + )) + .set_payload(create_simple_request()) + .to_request(); + + let resp = test::call_service(&mut app, req).await; + assert_eq!(resp.status(), StatusCode::UNAUTHORIZED); + } + + // #[actix_web::test] + // async fn test_post_files() { + // let app_state = AppState::for_test().await; + + // let admin_user = Administrator::authenticated( + // &app_state, + // AdminAuthCredentials { + // username: app_state.env.default_admin_username.to_owned(), + // password: app_state.env.default_admin_password.to_owned(), + // }, + // ) + // .await + // .unwrap(); + + // let static_files_index = create_files_index(&app_state); + + // let mut app = test::init_service( + // App::new() + // .app_data(Data::new(app_state.clone())) + // .app_data(Data::clone(&static_files_index)) + // .app_data(Data::new(AuthenticatedAdminMiddleware::new( + // "kuadrado-admin-auth", + // ))) + // .service(post_files), + // ) + // .await; + + // let req = test::TestRequest::with_uri("/post-files") + // .method(Method::POST) + // .header( + // "Content-Type", + // "multipart/form-data; boundary=\"abbc761f78ff4d7cb7573b5a23f96ef0\"", + // ) + // .cookie(get_auth_cookie( + // "kuadrado-admin-auth", + // app_state + // .encryption + // .decrypt(&admin_user.auth_token.unwrap()) + // .to_owned(), + // )) + // .set_payload(create_simple_request()) + // .to_request(); + + // let resp = test::call_service(&mut app, req).await; + // let status = resp.status(); + + // assert_eq!(status, StatusCode::OK); + + // let pathes: Vec<String> = test::read_body_json(resp).await; + // let public_dir = StaticFilesIndex::get_public_dir(&app_state.env); + + // let pathes_from_public = pathes + // .iter() + // .map(|p| { + // format!( + // "/{}", + // std::path::Path::new(p) + // .strip_prefix(&public_dir) + // .unwrap() + // .to_str() + // .unwrap() + // ) + // }) + // .collect::<Vec<String>>(); + + // let index = static_files_index.lock().unwrap(); + + // assert_eq!(pathes_from_public, index.0); + + // let mut iter_pathes = pathes.iter(); + // let f = std::fs::read_to_string(iter_pathes.next().unwrap()).unwrap(); + // assert_eq!(f, "test"); + // let f = std::fs::read_to_string(iter_pathes.next().unwrap()).unwrap(); + // assert_eq!(f, "data"); + // clear_testing_static(); + // } + + // #[actix_web::test] + // async fn test_delete_file() { + // let app_state = AppState::for_test().await; + + // let admin_user = Administrator::authenticated( + // &app_state, + // AdminAuthCredentials { + // username: app_state.env.default_admin_username.to_owned(), + // password: app_state.env.default_admin_password.to_owned(), + // }, + // ) + // .await + // .unwrap(); + + // let static_files_index = create_files_index(&app_state); + + // let mut app = test::init_service( + // App::new() + // .app_data(Data::new(app_state.clone())) + // .app_data(Data::clone(&static_files_index)) + // .app_data(Data::new(AuthenticatedAdminMiddleware::new( + // "kuadrado-admin-auth", + // ))) + // .service(post_files) + // .service(delete_static_file), + // ) + // .await; + + // let auth_token = admin_user.auth_token.unwrap(); + + // let req = test::TestRequest::with_uri("/post-files") + // .method(Method::POST) + // .header( + // "Content-Type", + // "multipart/form-data; boundary=\"abbc761f78ff4d7cb7573b5a23f96ef0\"", + // ) + // .cookie(get_auth_cookie( + // "kuadrado-admin-auth", + // app_state.encryption.decrypt(&auth_token).to_owned(), + // )) + // .set_payload(create_simple_request()) + // .to_request(); + + // let resp = test::call_service(&mut app, req).await; + // let status = resp.status(); + + // assert_eq!(status, StatusCode::OK); + + // let req = test::TestRequest::with_uri("/delete-file/uploads/docs/test.txt") + // .method(Method::DELETE) + // .cookie(get_auth_cookie( + // "kuadrado-admin-auth", + // app_state.encryption.decrypt(&auth_token).to_owned(), + // )) + // .to_request(); + + // let resp = test::call_service(&mut app, req).await; + // let status = resp.status(); + // assert_eq!(status, StatusCode::ACCEPTED); + // clear_testing_static(); + // } +} diff --git a/src/testing.rs b/src/testing.rs index 0ab5f7b..4dded61 100644 --- a/src/testing.rs +++ b/src/testing.rs @@ -1,5 +1,5 @@ #[cfg(test)] -pub const _TEST_JSON_WEBSITE: &'static str = " +pub const TEST_JSON_WEBSITE: &'static str = " { \"root_page\": { \"template_name\": \"TEST TEMPLATE\", diff --git a/src/website/website.rs b/src/website/website.rs index c5ee7d8..8e2d201 100644 --- a/src/website/website.rs +++ b/src/website/website.rs @@ -39,6 +39,12 @@ impl WebSiteBuilder { } } + #[cfg(test)] + pub fn testing(test_dir: &PathBuf) -> WebSite { + Self::from_json(crate::testing::TEST_JSON_WEBSITE) + .with_static_files_manager(StaticFilesManager::testing_new(test_dir).unwrap()) + } + pub fn load(config: &AppConfig) -> WebSiteBuilder { let file_path = match &config.load { None => std::env::current_dir() -- GitLab