From dc977891deba39ac5dadd93b61ef2e08c792834d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Wo=C5=BAniak?= Date: Thu, 14 Oct 2021 17:03:36 +0200 Subject: [PATCH] Broken start of issue cleanup --- Cargo.lock | 341 ++++++++++++++++++--------- actors/amazon-actor/Cargo.toml | 2 +- actors/database-actor/Cargo.toml | 4 +- actors/database-actor/src/models.rs | 10 - actors/mail-actor/Cargo.toml | 4 +- actors/mail-actor/src/invite.rs | 32 +-- actors/mail-actor/src/lib.rs | 45 +++- actors/mail-actor/src/welcome.rs | 32 +-- actors/web-actor/Cargo.toml | 2 +- actors/websocket-actor/Cargo.toml | 2 +- docs/Deploy.md | 4 +- jirs-cli/Cargo.toml | 6 +- jirs-server/Cargo.toml | 6 +- shared/jirs-data/Cargo.toml | 2 +- web/Cargo.toml | 2 +- web/src/lib.rs | 2 + web/src/model.rs | 14 +- web/src/pages/project_page/model.rs | 11 +- web/src/pages/sign_in_page/model.rs | 6 + web/src/pages/sign_in_page/update.rs | 4 + web/src/ws/issue.rs | 30 ++- web/src/ws/mod.rs | 41 ++-- 22 files changed, 374 insertions(+), 228 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a526d883..482ae5d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -410,6 +410,18 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "ascii_utils" version = "0.9.3" @@ -531,6 +543,29 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitvec" +version = "0.19.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2b_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + [[package]] name = "block-buffer" version = "0.7.3" @@ -590,12 +625,6 @@ dependencies = [ "bytes 0.5.6", ] -[[package]] -name = "bufstream" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" - [[package]] name = "bumpalo" version = "3.7.1" @@ -741,11 +770,11 @@ dependencies = [ [[package]] name = "console_error_panic_hook" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "wasm-bindgen", ] @@ -755,6 +784,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f92cfa0fd5690b3cf8c1ef2cabbd9b7ef22fa53cf5e1f92b05103f6d5d1cf6e7" +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "convert_case" version = "0.4.0" @@ -780,9 +815,9 @@ checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" [[package]] name = "core-foundation" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" +checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" dependencies = [ "core-foundation-sys", "libc", @@ -790,9 +825,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cpufeatures" @@ -818,7 +853,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" dependencies = [ - "crossbeam-utils", + "crossbeam-utils 0.7.2", "maybe-uninit", ] @@ -833,6 +868,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +dependencies = [ + "cfg-if 1.0.0", + "lazy_static", +] + [[package]] name = "crypto-mac" version = "0.11.1" @@ -858,7 +903,7 @@ dependencies = [ "diesel", "dotenv", "futures", - "ipnetwork 0.16.0", + "ipnetwork", "jirs-config", "jirs-data", "libc", @@ -925,16 +970,11 @@ dependencies = [ "byteorder", "chrono", "diesel_derives", - "ipnetwork 0.18.0", - "libc", "num-bigint", "num-integer", "num-traits", "pq-sys", "r2d2", - "serde_json", - "time 0.1.43", - "uuid 0.6.5", "uuid 0.8.2", ] @@ -967,6 +1007,17 @@ dependencies = [ "generic-array 0.14.4", ] +[[package]] +name = "dirs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +dependencies = [ + "libc", + "redox_users 0.3.5", + "winapi 0.3.9", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -984,7 +1035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", - "redox_users", + "redox_users 0.4.0", "winapi 0.3.9", ] @@ -1146,6 +1197,15 @@ dependencies = [ "ascii_utils", ] +[[package]] +name = "fastrand" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b394ed3d285a429378d3b384b9eb1285267e7df4b166df24b7a6939a04dc392e" +dependencies = [ + "instant", +] + [[package]] name = "filesystem-actor" version = "0.1.0" @@ -1223,6 +1283,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + [[package]] name = "futures" version = "0.3.17" @@ -1512,16 +1578,6 @@ dependencies = [ "digest 0.9.0", ] -[[package]] -name = "hostname" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" -dependencies = [ - "libc", - "winutil", -] - [[package]] name = "hostname" version = "0.3.1" @@ -1673,15 +1729,6 @@ dependencies = [ "serde", ] -[[package]] -name = "ipnetwork" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4088d739b183546b239688ddbc79891831df421773df95e236daf7867866d355" -dependencies = [ - "serde", -] - [[package]] name = "itertools" version = "0.9.0" @@ -1698,14 +1745,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] -name = "jirs-cli" +name = "jirs" version = "0.1.0" dependencies = [ "actix", - "clap", + "amazon-actor", "common", - "termion", - "tui", + "database-actor", + "dotenv", + "filesystem-actor", + "futures", + "highlight-actor", + "jirs-config", + "jirs-data", + "libc", + "mail-actor", + "openssl-sys", + "serde", + "serde_json", + "tokio 0.2.25", + "toml", + "web-actor", + "websocket-actor", ] [[package]] @@ -1734,31 +1795,6 @@ dependencies = [ "uuid 0.8.2", ] -[[package]] -name = "jirs-server" -version = "0.1.0" -dependencies = [ - "actix", - "amazon-actor", - "common", - "database-actor", - "dotenv", - "filesystem-actor", - "futures", - "highlight-actor", - "jirs-config", - "jirs-data", - "libc", - "mail-actor", - "openssl-sys", - "serde", - "serde_json", - "tokio 0.2.25", - "toml", - "web-actor", - "websocket-actor", -] - [[package]] name = "jirs_client" version = "0.1.0" @@ -1785,6 +1821,17 @@ dependencies = [ "wee_alloc", ] +[[package]] +name = "jirsc" +version = "0.1.0" +dependencies = [ + "actix", + "clap", + "common", + "termion", + "tui", +] + [[package]] name = "js-sys" version = "0.3.55" @@ -1828,16 +1875,28 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86ed8677138975b573ab4949c35613931a4addeadd0a8a6aa0327e2a979660de" dependencies = [ - "base64 0.10.1", - "bufstream", "fast_chemail", - "hostname 0.1.5", "log", +] + +[[package]] +name = "lettre" +version = "0.10.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8697ded52353bdd6fec234b3135972433397e86d0493d9fc38fbf407b7c106a" +dependencies = [ + "base64 0.13.0", + "fastrand", + "hostname", + "httpdate", + "idna", + "mime", "native-tls", - "nom", - "serde", - "serde_derive", - "serde_json", + "nom 6.1.2", + "once_cell", + "quoted_printable", + "r2d2", + "regex", ] [[package]] @@ -1848,7 +1907,7 @@ checksum = "fd02480f8dcf48798e62113974d6ccca2129a51d241fa20f1ea349c8a42559d5" dependencies = [ "base64 0.10.1", "email", - "lettre", + "lettre 0.9.6", "mime", "time 0.1.43", "uuid 0.7.4", @@ -1911,7 +1970,7 @@ dependencies = [ "dotenv", "futures", "jirs-config", - "lettre", + "lettre 0.10.0-rc.3", "lettre_email", "libc", "log", @@ -2097,6 +2156,18 @@ dependencies = [ "version_check 0.1.5", ] +[[package]] +name = "nom" +version = "6.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" +dependencies = [ + "bitvec", + "funty", + "memchr", + "version_check 0.9.3", +] + [[package]] name = "ntapi" version = "0.3.6" @@ -2255,7 +2326,7 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall", + "redox_syscall 0.2.10", "smallvec", "winapi 0.3.9", ] @@ -2389,9 +2460,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741" [[package]] name = "pq-sys" @@ -2426,9 +2497,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" -version = "1.0.29" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" +checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70" dependencies = [ "unicode-xid", ] @@ -2460,6 +2531,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "quoted_printable" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1238256b09923649ec89b08104c4dfe9f6cb2fea734a5db5384e44916d59e9c5" + [[package]] name = "r2d2" version = "0.8.9" @@ -2471,6 +2548,12 @@ dependencies = [ "scheduled-thread-pool", ] +[[package]] +name = "radium" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" + [[package]] name = "rand" version = "0.4.6" @@ -2690,6 +2773,12 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + [[package]] name = "redox_syscall" version = "0.2.10" @@ -2705,7 +2794,18 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" dependencies = [ - "redox_syscall", + "redox_syscall 0.2.10", +] + +[[package]] +name = "redox_users" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" +dependencies = [ + "getrandom 0.1.16", + "redox_syscall 0.1.57", + "rust-argon2", ] [[package]] @@ -2715,7 +2815,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ "getrandom 0.2.3", - "redox_syscall", + "redox_syscall 0.2.10", ] [[package]] @@ -2756,7 +2856,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" dependencies = [ - "hostname 0.3.1", + "hostname", "quick-error", ] @@ -2842,6 +2942,18 @@ dependencies = [ "tokio 1.12.0", ] +[[package]] +name = "rust-argon2" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" +dependencies = [ + "base64 0.13.0", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils 0.8.5", +] + [[package]] name = "rustc_version" version = "0.2.3" @@ -3129,9 +3241,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "smallvec" @@ -3275,6 +3387,12 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.2.0" @@ -3284,7 +3402,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "rand 0.8.4", - "redox_syscall", + "redox_syscall 0.2.10", "remove_dir_all", "winapi 0.3.9", ] @@ -3306,7 +3424,7 @@ checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e" dependencies = [ "libc", "numtoa", - "redox_syscall", + "redox_syscall 0.2.10", "redox_termios", ] @@ -3453,9 +3571,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "154794c8f499c2619acd19e839294703e9e32e7630ef5f46ea80d4ef0fbee5eb" +checksum = "b2dd85aeaba7b68df939bd357c6afb36c87951be9e80bf9c859f2fc3e9fca0fd" dependencies = [ "proc-macro2", "quote", @@ -3707,15 +3825,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "uuid" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363" -dependencies = [ - "cfg-if 0.1.10", -] - [[package]] name = "uuid" version = "0.7.4" @@ -3748,11 +3857,11 @@ dependencies = [ [[package]] name = "v_escape_derive" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c860ad1273f4eee7006cee05db20c9e60e5d24cba024a32e1094aa8e574f3668" +checksum = "f29769400af8b264944b851c961a4a6930e76604f59b1fcd51246bab6a296c8c" dependencies = [ - "nom", + "nom 4.2.3", "proc-macro2", "quote", "syn", @@ -4058,15 +4167,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "winutil" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -4078,10 +4178,19 @@ dependencies = [ ] [[package]] -name = "xdg" -version = "2.2.0" +name = "wyz" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + +[[package]] +name = "xdg" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de4cfc7dc9727713f386aadce9496f1ed64ea368d9f1f813a54d0f98f8741286" +dependencies = [ + "dirs", +] [[package]] name = "xml-rs" diff --git a/actors/amazon-actor/Cargo.toml b/actors/amazon-actor/Cargo.toml index fd6d6f48..c8ed9ccf 100644 --- a/actors/amazon-actor/Cargo.toml +++ b/actors/amazon-actor/Cargo.toml @@ -23,7 +23,7 @@ futures = { version = "0.3.8" } openssl-sys = { version = "*", features = ["vendored"] } libc = { version = "0.2.0", default-features = false } -uuid = { version = "0.8.1", features = ["serde", "v4", "v5"] } +uuid = { version = "0.8.2", features = ["serde", "v4", "v5"] } [dependencies.jirs-config] path = "../../shared/jirs-config" diff --git a/actors/database-actor/Cargo.toml b/actors/database-actor/Cargo.toml index c9e8a574..12adc40e 100644 --- a/actors/database-actor/Cargo.toml +++ b/actors/database-actor/Cargo.toml @@ -54,5 +54,5 @@ features = ["backend"] path = "../../derive/derive_db_execute" [dependencies.diesel] -version = "1.4.7" -features = [ "postgres", "numeric", "uuidv07", "r2d2", "extras" ] +version = "1.4.8" +features = [ "postgres", "numeric", "uuidv07", "r2d2", "chrono" ] diff --git a/actors/database-actor/src/models.rs b/actors/database-actor/src/models.rs index 18333a17..edd8a09f 100644 --- a/actors/database-actor/src/models.rs +++ b/actors/database-actor/src/models.rs @@ -4,7 +4,6 @@ use jirs_data::{ TimeTracking, UserId, }; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::schema::*; @@ -105,15 +104,6 @@ pub struct UserForm { pub avatar_url: Option, } -#[derive(Debug, Serialize, Deserialize, Insertable)] -#[table_name = "tokens"] -pub struct TokenForm { - pub user_id: i32, - pub access_token: Uuid, - pub refresh_token: Uuid, - pub bind_token: Option, -} - #[derive(Debug, Serialize, Deserialize, Insertable)] #[table_name = "invitations"] pub struct InvitationForm { diff --git a/actors/mail-actor/Cargo.toml b/actors/mail-actor/Cargo.toml index f35126ff..b572aa6b 100644 --- a/actors/mail-actor/Cargo.toml +++ b/actors/mail-actor/Cargo.toml @@ -21,13 +21,13 @@ toml = { version = "*" } dotenv = { version = "*" } -uuid = { version = "0.8.1", features = ["serde", "v4", "v5"] } +uuid = { version = "0.8.2", features = ["serde", "v4", "v5"] } futures = { version = "*" } openssl-sys = { version = "*", features = ["vendored"] } libc = { version = "0.2.0", default-features = false } -lettre = { version = "*" } +lettre = { version = "0.10.0-rc.3" } lettre_email = { version = "*" } log = { version = "*" } diff --git a/actors/mail-actor/src/invite.rs b/actors/mail-actor/src/invite.rs index 4fb043ba..cce38b8a 100644 --- a/actors/mail-actor/src/invite.rs +++ b/actors/mail-actor/src/invite.rs @@ -1,7 +1,8 @@ use actix::{Handler, Message}; +use lettre::message::Mailbox; use uuid::Uuid; -use crate::MailExecutor; +use crate::{email_address, MailError, MailExecutor}; #[derive(Debug)] pub struct Invite { @@ -11,17 +12,18 @@ pub struct Invite { } impl Message for Invite { - type Result = Result<(), String>; + type Result = Result<(), MailError>; } impl Handler for MailExecutor { - type Result = Result<(), String>; + type Result = Result<(), MailError>; fn handle(&mut self, msg: Invite, _ctx: &mut Self::Context) -> Self::Result { use lettre::Transport; let transport = &mut self.transport; - let from = self.config.from.as_str(); let addr = jirs_config::web::Configuration::read().full_addr(); + let from = email_address(self.config.from.as_str())?; + let to = email_address(&msg.email)?; let html = format!( r#" @@ -43,17 +45,19 @@ impl Handler for MailExecutor { addr = addr, ); - let email = lettre_email::Email::builder() - .from(from) - .to(msg.email.as_str()) - .html(html.as_str()) + let mail = lettre::Message::builder() + .to(Mailbox::new(None, to)) + .from(Mailbox::new(None, from)) .subject("Invitation to JIRS project") - .build() - .map_err(|_| "Email is not valid".to_string())?; + .body(html) + .map_err(|e| { + log::error!("{:?}", e); + MailError::MailformedBody + })?; - transport - .send(email.into()) - .map(|_| ()) - .map_err(|e| format!("Mailer: {}", e)) + transport.send(&mail).map(|_| ()).map_err(|e| { + log::error!("Mailer: {}", e); + MailError::FailedToSendEmail + }) } } diff --git a/actors/mail-actor/src/lib.rs b/actors/mail-actor/src/lib.rs index 03a08442..d40a9e7d 100644 --- a/actors/mail-actor/src/lib.rs +++ b/actors/mail-actor/src/lib.rs @@ -1,10 +1,23 @@ +use std::convert::TryFrom; + use actix::{Actor, SyncContext}; +use lettre::transport::smtp::authentication::Credentials; +use lettre::transport::smtp::PoolConfig; pub mod invite; pub mod welcome; pub type MailTransport = lettre::SmtpTransport; +#[derive(Debug)] +pub enum MailError { + EmailWithoutUser, + EmailWithoutDomain, + InvalidEmailAddress, + FailedToSendEmail, + MailformedBody, +} + pub struct MailExecutor { pub transport: MailTransport, pub config: jirs_config::mail::Configuration, @@ -24,7 +37,7 @@ impl Default for MailExecutor { } } -fn mail_client(config: &jirs_config::mail::Configuration) -> lettre::SmtpClient { +fn mail_client(config: &jirs_config::mail::Configuration) -> lettre::SmtpTransport { let jirs_config::mail::Configuration { user: mail_user, pass: mail_pass, @@ -32,16 +45,30 @@ fn mail_client(config: &jirs_config::mail::Configuration) -> lettre::SmtpClient .. } = &config; - lettre::SmtpClient::new_simple(mail_host) + lettre::SmtpTransport::relay(mail_host) .expect("Failed to init SMTP client") - .credentials(lettre::smtp::authentication::Credentials::new( - mail_user.clone(), - mail_pass.clone(), - )) - .connection_reuse(lettre::smtp::ConnectionReuseParameters::ReuseUnlimited) - .smtp_utf8(true) + .credentials(Credentials::new(mail_user.clone(), mail_pass.clone())) + .pool_config(PoolConfig::default()) + .build() } fn mail_transport(config: &jirs_config::mail::Configuration) -> MailTransport { - mail_client(config).transport() + mail_client(config) +} + +pub fn email_address(email: &str) -> Result { + let (user, domain) = { + let mut parts = email.split("@"); + ( + match parts.next() { + Some(s) => s, + None => return Err(MailError::EmailWithoutUser), + }, + match parts.next() { + Some(s) => s, + None => return Err(MailError::EmailWithoutDomain), + }, + ) + }; + lettre::Address::try_from((user, domain)).map_err(|_| MailError::InvalidEmailAddress) } diff --git a/actors/mail-actor/src/welcome.rs b/actors/mail-actor/src/welcome.rs index 67539fee..34b20b32 100644 --- a/actors/mail-actor/src/welcome.rs +++ b/actors/mail-actor/src/welcome.rs @@ -1,7 +1,8 @@ use actix::{Handler, Message}; +use lettre::message::Mailbox; use uuid::Uuid; -use crate::MailExecutor; +use crate::{email_address, MailError, MailExecutor}; #[derive(Debug)] pub struct Welcome { @@ -10,16 +11,17 @@ pub struct Welcome { } impl Message for Welcome { - type Result = Result<(), String>; + type Result = Result<(), MailError>; } impl Handler for MailExecutor { - type Result = Result<(), String>; + type Result = Result<(), MailError>; fn handle(&mut self, msg: Welcome, _ctx: &mut Self::Context) -> Self::Result { use lettre::Transport; let transport = &mut self.transport; - let from = self.config.from.as_str(); + let from = email_address(self.config.from.as_str())?; + let to = email_address(&msg.email)?; let html = format!( r#" @@ -45,17 +47,19 @@ impl Handler for MailExecutor { log::info!("Sending email:\n{}", html); } - let email = lettre_email::Email::builder() - .from(from) - .to(msg.email.as_str()) - .html(html.as_str()) + let mail = lettre::Message::builder() + .to(Mailbox::new(None, to)) + .from(Mailbox::new(None, from)) .subject("Welcome to JIRS") - .build() - .map_err(|_| "Email is not valid".to_string())?; + .body(html) + .map_err(|e| { + log::error!("{:?}", e); + MailError::MailformedBody + })?; - transport - .send(email.into()) - .map(|_| ()) - .map_err(|e| format!("Mailer: {}", e)) + transport.send(&mail).map(|_| ()).map_err(|e| { + log::error!("{:?}", e); + MailError::FailedToSendEmail + }) } } diff --git a/actors/web-actor/Cargo.toml b/actors/web-actor/Cargo.toml index 33055cd9..f968d51d 100644 --- a/actors/web-actor/Cargo.toml +++ b/actors/web-actor/Cargo.toml @@ -31,7 +31,7 @@ futures = { version = "0.3.8" } openssl-sys = { version = "*", features = ["vendored"] } libc = { version = "0.2.0", default-features = false } -uuid = { version = "0.8.1", features = ["serde", "v4", "v5"] } +uuid = { version = "0.8.2", features = ["serde", "v4", "v5"] } [dependencies.jirs-config] path = "../../shared/jirs-config" diff --git a/actors/websocket-actor/Cargo.toml b/actors/websocket-actor/Cargo.toml index ccb51ec5..f981e667 100644 --- a/actors/websocket-actor/Cargo.toml +++ b/actors/websocket-actor/Cargo.toml @@ -28,7 +28,7 @@ flate2 = { version = "*" } syntect = { version = "*" } lazy_static = { version = "*" } -uuid = { version = "0.8.1", features = ["serde", "v4", "v5"] } +uuid = { version = "0.8.2", features = ["serde", "v4", "v5"] } comrak = { version = "*" } diff --git a/docs/Deploy.md b/docs/Deploy.md index ceb23652..f1addd10 100644 --- a/docs/Deploy.md +++ b/docs/Deploy.md @@ -109,8 +109,8 @@ Ensure `$HOME/.cargo/bin` is in `$PATH` * Compile server ```bash -cargo build --bin jirs_server --release --no-default-features --features local-storage -cp ./target/release/jirs_server /usr/bin/jirs_server +cargo build --bin jirs --release --no-default-features --features local-storage +cp ./target/release/jirs /usr/bin/jirs ``` * Compile web client diff --git a/jirs-cli/Cargo.toml b/jirs-cli/Cargo.toml index 56dce607..f7568d7a 100644 --- a/jirs-cli/Cargo.toml +++ b/jirs-cli/Cargo.toml @@ -1,13 +1,9 @@ [package] -name = "jirs-cli" +name = "jirsc" version = "0.1.0" authors = ["Adrian Wozniak "] edition = "2018" -[[bin]] -name = "jirs" -path = "./src/main.rs" - [dependencies] common = { path = "../shared/common" } diff --git a/jirs-server/Cargo.toml b/jirs-server/Cargo.toml index b28bc342..ec06c100 100644 --- a/jirs-server/Cargo.toml +++ b/jirs-server/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "jirs-server" +name = "jirs" version = "0.1.0" authors = ["Adrian Wozniak "] edition = "2018" @@ -8,10 +8,6 @@ repository = "https://gitlab.com/adrian.wozniak/jirs" license = "MPL-2.0" #license-file = "../LICENSE" -[[bin]] -name = "jirs_server" -path = "./src/main.rs" - [features] aws-s3 = ["amazon-actor"] local-storage = ["filesystem-actor"] diff --git a/shared/jirs-data/Cargo.toml b/shared/jirs-data/Cargo.toml index 58c160aa..15145fc5 100644 --- a/shared/jirs-data/Cargo.toml +++ b/shared/jirs-data/Cargo.toml @@ -27,7 +27,7 @@ version = "0.10.0" optional = true [dependencies.diesel] -version = "1.4.7" +version = "1.4.8" features = [ "postgres", "numeric", "uuidv07", "r2d2" ] optional = true diff --git a/web/Cargo.toml b/web/Cargo.toml index 0a7a421c..34b24b4b 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -27,7 +27,7 @@ serde_json = { version = "*" } bincode = { version = "*" } chrono = { version = "0.4", default-features = false, features = ["serde", "wasmbind"] } -uuid = { version = "0.8.1", features = ["serde"] } +uuid = { version = "0.8.2", features = ["serde"] } futures = "0.3.6" dotenv = { version = "*" } diff --git a/web/src/lib.rs b/web/src/lib.rs index 33e9a8b9..2477927f 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -17,6 +17,7 @@ use crate::components::styled_tooltip::{TooltipVariant as StyledTooltip, Tooltip use crate::modals::DebugMsg; use crate::model::{ModalType, Model, Page}; use crate::pages::issues_and_filters::IssuesAndFiltersMsg; +use crate::pages::sign_in_page::SignInMsg; use crate::shared::go_to_login; use crate::ws::{flush_queue, open_socket, read_incoming, send_ws_msg}; @@ -89,6 +90,7 @@ pub enum Msg { SignInRequest, BindClientRequest, InvalidPair, + SignIn(SignInMsg), // users InviteRequest, diff --git a/web/src/model.rs b/web/src/model.rs index 89144cea..ccb58023 100644 --- a/web/src/model.rs +++ b/web/src/model.rs @@ -230,8 +230,8 @@ pub struct Model { pub current_user_project: Option, // issues - issues: Vec, - pub issues_by_id: HashMap, + pub issue_ids: Vec, + pub issues_by_id: HashMap, // users pub user: Option, @@ -311,16 +311,6 @@ impl Model { } } - #[inline(always)] - pub fn issues(&self) -> &[Issue] { - &self.issues - } - - #[inline(always)] - pub fn issues_mut(&mut self) -> &mut Vec { - &mut self.issues - } - #[inline(always)] pub fn issue_statuses(&self) -> &[IssueStatus] { &self.issue_statuses diff --git a/web/src/pages/project_page/model.rs b/web/src/pages/project_page/model.rs index a6dc8f13..e4294706 100644 --- a/web/src/pages/project_page/model.rs +++ b/web/src/pages/project_page/model.rs @@ -29,13 +29,16 @@ pub struct ProjectPage { } impl ProjectPage { - pub fn visible_issues( + pub fn visible_issues<'issue, IssueStream>( page: &ProjectPage, epics: &[Epic], statuses: &[IssueStatus], - issues: &[Issue], + issues: IssueStream, user: &Option, - ) -> Vec { + ) -> Vec + where + IssueStream: std::iter::Iterator, + { let epics = vec![None].into_iter().chain( epics .iter() @@ -43,7 +46,7 @@ impl ProjectPage { ); let statuses = statuses.iter().map(|s| (s.id, s.name.as_str())); - let issues = issues.iter().filter(|issue| { + let issues = issues.filter(|issue| { issue_filter_with_avatars(issue, &page.active_avatar_filters) && issue_filter_with_text(issue, page.text_filter.as_str()) && issue_filter_with_only_my(issue, page.only_my_filter, user) diff --git a/web/src/pages/sign_in_page/model.rs b/web/src/pages/sign_in_page/model.rs index bb968c10..4647caef 100644 --- a/web/src/pages/sign_in_page/model.rs +++ b/web/src/pages/sign_in_page/model.rs @@ -9,6 +9,12 @@ pub type UsernameValidator = Touched>; pub type EmailValidator = Touched>, Changed>>; pub type TokenValidator = Touched, Changed>>; +#[derive(Debug)] +pub enum SignInMsg { + AuthenticateSuccess, + InvalidPair, +} + #[derive(Debug, PartialOrd, PartialEq)] pub enum SignInState { Initial, diff --git a/web/src/pages/sign_in_page/update.rs b/web/src/pages/sign_in_page/update.rs index fec5d0ce..b6d84696 100644 --- a/web/src/pages/sign_in_page/update.rs +++ b/web/src/pages/sign_in_page/update.rs @@ -68,6 +68,10 @@ pub fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders) Msg::InvalidPair => { page.state = SignInState::InvalidPair; } + Msg::SignIn(crate::pages::sign_in_page::SignInMsg::AuthenticateSuccess) => { + let page = crate::match_page_mut!(model, SignIn); + page.state = SignInState::EmailSend; + } Msg::WebSocketChange(change) => match change { WebSocketChanged::WsMsg(WsMsg::Session(WsMsgSession::AuthenticateSuccess)) => { page.state = SignInState::EmailSend; diff --git a/web/src/ws/issue.rs b/web/src/ws/issue.rs index 8ac5cb45..660d2cd2 100644 --- a/web/src/ws/issue.rs +++ b/web/src/ws/issue.rs @@ -131,15 +131,19 @@ pub fn change_status(status_id: IssueStatusId, model: &mut Model) { return; } - let mut issues: Vec = model - .issues_mut() - .drain_filter(|issue| { - if issue.id == dragged_id { - issue.issue_status_id = status_id; - } - issue.issue_status_id == status_id && issue.epic_id == epic_id - }) - .collect(); + let mut issues = { + let mut h = std::mem::take(&mut model.issues_by_id); + h.keys() + .filter_map(|id| h.remove(id)) + .collect::>() + } + .drain_filter(|issue| { + if issue.id == dragged_id { + issue.issue_status_id = status_id; + } + issue.issue_status_id == status_id && issue.epic_id == epic_id + }) + .collect::>(); issues.sort_by(|a, b| a.list_position.cmp(&b.list_position)); @@ -153,7 +157,8 @@ pub fn change_status(status_id: IssueStatusId, model: &mut Model) { } dirty.push(issue.id); - model.issues_mut().push(issue); + model.issue_ids.push(issue.id); + model.issues_by_id.insert(issue.id, issue); } { let project_page = crate::match_page_mut!(model, Project); @@ -166,7 +171,10 @@ pub fn change_status(status_id: IssueStatusId, model: &mut Model) { crate::match_page!(model, Project), model.epics(), model.issue_statuses(), - model.issues(), + model + .issue_ids + .iter() + .filter_map(|id| model.issues_by_id.get(id)), model.user(), ); diff --git a/web/src/ws/mod.rs b/web/src/ws/mod.rs index 18e37948..6c4972ea 100644 --- a/web/src/ws/mod.rs +++ b/web/src/ws/mod.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + pub use init_load_sets::*; use jirs_data::msg::{ WsError, WsMsgComment, WsMsgEpic, WsMsgIssue, WsMsgIssueStatus, WsMsgMessage, WsMsgProject, @@ -7,7 +9,7 @@ use jirs_data::*; use seed::prelude::*; use crate::model::*; -use crate::pages::sign_in_page::SignInState; +use crate::pages::sign_in_page::SignInMsg; use crate::shared::{go_to_board, write_auth_token}; use crate::{Msg, OperationKind, ResourceKind, WebSocketChanged}; @@ -252,7 +254,15 @@ pub fn update(msg: &mut WsMsg, model: &mut Model, orders: &mut impl Orders) WsMsg::Project(WsMsgProject::ProjectIssuesLoaded(v)) => { v.sort_by(|a, b| (a.list_position as i64).cmp(&(b.list_position as i64))); { - let _ = std::mem::replace(model.issues_mut(), v.clone()); + model.issue_ids = Vec::with_capacity(v.len()); + model.issues_by_id = + std::mem::take(v) + .into_iter() + .fold(HashMap::with_capacity(v.len()), |h, o| { + model.issue_ids.push(o.id); + h.insert(o.id, o); + h + }); }; model.issues_by_id.clear(); for issue in v { @@ -267,10 +277,8 @@ pub fn update(msg: &mut WsMsg, model: &mut Model, orders: &mut impl Orders) } WsMsg::Issue(WsMsgIssue::IssueCreated(issue)) => { let id = issue.id; + model.issue_ids.push(issue.id); model.issues_by_id.insert(id, issue.clone()); - if let Some(idx) = model.issues().iter().position(|i| i.id == issue.id) { - let _ = std::mem::replace(&mut model.issues_mut()[idx], issue.clone()); - } orders.send_msg(Msg::ResourceChanged( ResourceKind::Issue, OperationKind::SingleCreated, @@ -280,10 +288,11 @@ pub fn update(msg: &mut WsMsg, model: &mut Model, orders: &mut impl Orders) WsMsg::Issue(WsMsgIssue::IssueUpdated(issue)) => { let id = issue.id; model.issues_by_id.remove(&id); + model.issue_ids = std::mem::take(&mut model.issue_ids) + .into_iter() + .filter(|id| *id != issue.id) + .collect(); model.issues_by_id.insert(id, issue.clone()); - if let Some(idx) = model.issues().iter().position(|i| i.id == issue.id) { - let _ = std::mem::replace(&mut model.issues_mut()[idx], issue.clone()); - } orders.send_msg(Msg::ResourceChanged( ResourceKind::Issue, OperationKind::SingleModified, @@ -291,13 +300,12 @@ pub fn update(msg: &mut WsMsg, model: &mut Model, orders: &mut impl Orders) )); } WsMsg::Issue(WsMsgIssue::IssueDeleted(id, _count)) => { - let old = std::mem::take(model.issues_mut()); - for is in old { - if is.id == *id { - continue; - } - model.issues_mut().push(is); - } + model.issue_ids = std::mem::take(&mut model.issue_ids) + .into_iter() + .filter(|old| *old != *id) + .collect(); + model.issues_by_id.remove(id); + orders.send_msg(Msg::ResourceChanged( ResourceKind::Issue, OperationKind::SingleRemoved, @@ -442,8 +450,7 @@ pub fn update(msg: &mut WsMsg, model: &mut Model, orders: &mut impl Orders) )); } WsMsg::Session(WsMsgSession::AuthenticateSuccess) => { - let page = crate::match_page_mut!(model, SignIn); - page.state = SignInState::EmailSend; + orders.send_msg(Msg::SignIn(SignInMsg::AuthenticateSuccess)); } WsMsg::Error(WsError::InvalidLoginPair) => { orders.send_msg(Msg::InvalidPair);