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