Broken start of issue cleanup

This commit is contained in:
Adrian Woźniak 2021-10-14 17:03:36 +02:00
parent 47674c1448
commit dc977891de
No known key found for this signature in database
GPG Key ID: DE43476F72AD3F6C
22 changed files with 374 additions and 228 deletions

341
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View File

@ -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" ]

View File

@ -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<String>,
}
#[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<Uuid>,
}
#[derive(Debug, Serialize, Deserialize, Insertable)]
#[table_name = "invitations"]
pub struct InvitationForm {

View File

@ -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 = "*" }

View File

@ -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<Invite> 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<Invite> 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
})
}
}

View File

@ -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<lettre::Address, MailError> {
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)
}

View File

@ -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<Welcome> 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<Welcome> 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
})
}
}

View File

@ -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"

View File

@ -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 = "*" }

View File

@ -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

View File

@ -1,13 +1,9 @@
[package]
name = "jirs-cli"
name = "jirsc"
version = "0.1.0"
authors = ["Adrian Wozniak <adrian.wozniak@ita-prog.pl>"]
edition = "2018"
[[bin]]
name = "jirs"
path = "./src/main.rs"
[dependencies]
common = { path = "../shared/common" }

View File

@ -1,5 +1,5 @@
[package]
name = "jirs-server"
name = "jirs"
version = "0.1.0"
authors = ["Adrian Wozniak <adrian.wozniak@ita-prog.pl>"]
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"]

View File

@ -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

View File

@ -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 = "*" }

View File

@ -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,

View File

@ -230,8 +230,8 @@ pub struct Model {
pub current_user_project: Option<UserProject>,
// issues
issues: Vec<Issue>,
pub issues_by_id: HashMap<EpicId, Issue>,
pub issue_ids: Vec<IssueId>,
pub issues_by_id: HashMap<IssueId, Issue>,
// users
pub user: Option<User>,
@ -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<Issue> {
&mut self.issues
}
#[inline(always)]
pub fn issue_statuses(&self) -> &[IssueStatus] {
&self.issue_statuses

View File

@ -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<User>,
) -> Vec<EpicIssuePerStatus> {
) -> Vec<EpicIssuePerStatus>
where
IssueStream: std::iter::Iterator<Item = &'issue Issue>,
{
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)

View File

@ -9,6 +9,12 @@ pub type UsernameValidator = Touched<Between<4, 36>>;
pub type EmailValidator = Touched<Chain<Changed<AtLeast<6>>, Changed<EmailFormat>>>;
pub type TokenValidator = Touched<Chain<Between<10, 36>, Changed<UuidFormat>>>;
#[derive(Debug)]
pub enum SignInMsg {
AuthenticateSuccess,
InvalidPair,
}
#[derive(Debug, PartialOrd, PartialEq)]
pub enum SignInState {
Initial,

View File

@ -68,6 +68,10 @@ pub fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>)
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;

View File

@ -131,15 +131,19 @@ pub fn change_status(status_id: IssueStatusId, model: &mut Model) {
return;
}
let mut issues: Vec<Issue> = 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::<Vec<Issue>>()
}
.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::<Vec<Issue>>();
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(),
);

View File

@ -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<Msg>)
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<Msg>)
}
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<Msg>)
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<Msg>)
));
}
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<Msg>)
));
}
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);