Generate reset password URL
This commit is contained in:
		
							
								
								
									
										270
									
								
								geneit_backend/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										270
									
								
								geneit_backend/Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -467,6 +467,22 @@ dependencies = [
 | 
			
		||||
 "version_check",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "core-foundation"
 | 
			
		||||
version = "0.9.3"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "core-foundation-sys",
 | 
			
		||||
 "libc",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "core-foundation-sys"
 | 
			
		||||
version = "0.8.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "cpufeatures"
 | 
			
		||||
version = "0.2.7"
 | 
			
		||||
@@ -543,6 +559,22 @@ dependencies = [
 | 
			
		||||
 "crypto-common",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "email-encoding"
 | 
			
		||||
version = "0.2.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "dbfb21b9878cf7a348dcb8559109aabc0ec40d69924bd706fa5149846c4fef75"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "base64",
 | 
			
		||||
 "memchr",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "email_address"
 | 
			
		||||
version = "0.2.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "encoding_rs"
 | 
			
		||||
version = "0.8.32"
 | 
			
		||||
@@ -595,6 +627,15 @@ dependencies = [
 | 
			
		||||
 "ascii_utils",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "fastrand"
 | 
			
		||||
version = "1.9.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "instant",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "flate2"
 | 
			
		||||
version = "1.0.26"
 | 
			
		||||
@@ -611,6 +652,21 @@ version = "1.0.7"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "foreign-types"
 | 
			
		||||
version = "0.3.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "foreign-types-shared",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "foreign-types-shared"
 | 
			
		||||
version = "0.1.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "form_urlencoded"
 | 
			
		||||
version = "1.1.0"
 | 
			
		||||
@@ -626,6 +682,12 @@ version = "0.3.28"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "futures-io"
 | 
			
		||||
version = "0.3.28"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "futures-macro"
 | 
			
		||||
version = "0.3.28"
 | 
			
		||||
@@ -656,8 +718,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "futures-core",
 | 
			
		||||
 "futures-io",
 | 
			
		||||
 "futures-macro",
 | 
			
		||||
 "futures-task",
 | 
			
		||||
 "memchr",
 | 
			
		||||
 "pin-project-lite",
 | 
			
		||||
 "pin-utils",
 | 
			
		||||
 "slab",
 | 
			
		||||
@@ -674,8 +738,10 @@ dependencies = [
 | 
			
		||||
 "diesel",
 | 
			
		||||
 "env_logger",
 | 
			
		||||
 "lazy_static",
 | 
			
		||||
 "lettre",
 | 
			
		||||
 "log",
 | 
			
		||||
 "mailchecker",
 | 
			
		||||
 "rand",
 | 
			
		||||
 "redis",
 | 
			
		||||
 "serde",
 | 
			
		||||
 "serde_json",
 | 
			
		||||
@@ -748,6 +814,17 @@ version = "0.3.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "hostname"
 | 
			
		||||
version = "0.3.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "libc",
 | 
			
		||||
 "match_cfg",
 | 
			
		||||
 "winapi",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "http"
 | 
			
		||||
version = "0.2.9"
 | 
			
		||||
@@ -797,6 +874,15 @@ dependencies = [
 | 
			
		||||
 "hashbrown",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "instant"
 | 
			
		||||
version = "0.1.12"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cfg-if",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "io-lifetimes"
 | 
			
		||||
version = "1.0.10"
 | 
			
		||||
@@ -847,6 +933,29 @@ version = "1.4.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "lettre"
 | 
			
		||||
version = "0.10.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "76bd09637ae3ec7bd605b8e135e757980b3968430ff2b1a4a94fb7769e50166d"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "base64",
 | 
			
		||||
 "email-encoding",
 | 
			
		||||
 "email_address",
 | 
			
		||||
 "fastrand",
 | 
			
		||||
 "futures-util",
 | 
			
		||||
 "hostname",
 | 
			
		||||
 "httpdate",
 | 
			
		||||
 "idna",
 | 
			
		||||
 "mime",
 | 
			
		||||
 "native-tls",
 | 
			
		||||
 "nom",
 | 
			
		||||
 "once_cell",
 | 
			
		||||
 "quoted_printable",
 | 
			
		||||
 "socket2",
 | 
			
		||||
 "tokio",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "libc"
 | 
			
		||||
version = "0.2.144"
 | 
			
		||||
@@ -906,6 +1015,12 @@ dependencies = [
 | 
			
		||||
 "once_cell",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "match_cfg"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "memchr"
 | 
			
		||||
version = "2.5.0"
 | 
			
		||||
@@ -918,6 +1033,12 @@ version = "0.3.17"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "minimal-lexical"
 | 
			
		||||
version = "0.2.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "miniz_oxide"
 | 
			
		||||
version = "0.7.1"
 | 
			
		||||
@@ -939,6 +1060,34 @@ dependencies = [
 | 
			
		||||
 "windows-sys 0.45.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "native-tls"
 | 
			
		||||
version = "0.2.11"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "lazy_static",
 | 
			
		||||
 "libc",
 | 
			
		||||
 "log",
 | 
			
		||||
 "openssl",
 | 
			
		||||
 "openssl-probe",
 | 
			
		||||
 "openssl-sys",
 | 
			
		||||
 "schannel",
 | 
			
		||||
 "security-framework",
 | 
			
		||||
 "security-framework-sys",
 | 
			
		||||
 "tempfile",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "nom"
 | 
			
		||||
version = "7.1.3"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "memchr",
 | 
			
		||||
 "minimal-lexical",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "num_cpus"
 | 
			
		||||
version = "1.15.0"
 | 
			
		||||
@@ -955,6 +1104,50 @@ version = "1.17.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "openssl"
 | 
			
		||||
version = "0.10.53"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "12df40a956736488b7b44fe79fe12d4f245bb5b3f5a1f6095e499760015be392"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bitflags",
 | 
			
		||||
 "cfg-if",
 | 
			
		||||
 "foreign-types",
 | 
			
		||||
 "libc",
 | 
			
		||||
 "once_cell",
 | 
			
		||||
 "openssl-macros",
 | 
			
		||||
 "openssl-sys",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "openssl-macros"
 | 
			
		||||
version = "0.1.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn 2.0.16",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "openssl-probe"
 | 
			
		||||
version = "0.1.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "openssl-sys"
 | 
			
		||||
version = "0.9.88"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "c2ce0f250f34a308dcfdbb351f511359857d4ed2134ba715a4eadd46e1ffd617"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cc",
 | 
			
		||||
 "libc",
 | 
			
		||||
 "pkg-config",
 | 
			
		||||
 "vcpkg",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "parking_lot"
 | 
			
		||||
version = "0.12.1"
 | 
			
		||||
@@ -973,7 +1166,7 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cfg-if",
 | 
			
		||||
 "libc",
 | 
			
		||||
 "redox_syscall",
 | 
			
		||||
 "redox_syscall 0.2.16",
 | 
			
		||||
 "smallvec",
 | 
			
		||||
 "windows-sys 0.45.0",
 | 
			
		||||
]
 | 
			
		||||
@@ -1065,6 +1258,12 @@ dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "quoted_printable"
 | 
			
		||||
version = "0.4.8"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5a3866219251662ec3b26fc217e3e05bf9c4f84325234dfb96bf0bf840889e49"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "rand"
 | 
			
		||||
version = "0.8.5"
 | 
			
		||||
@@ -1118,6 +1317,15 @@ dependencies = [
 | 
			
		||||
 "bitflags",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "redox_syscall"
 | 
			
		||||
version = "0.3.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bitflags",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "regex"
 | 
			
		||||
version = "1.8.2"
 | 
			
		||||
@@ -1164,12 +1372,44 @@ version = "1.0.13"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "schannel"
 | 
			
		||||
version = "0.1.21"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "windows-sys 0.42.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "scopeguard"
 | 
			
		||||
version = "1.1.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "security-framework"
 | 
			
		||||
version = "2.9.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bitflags",
 | 
			
		||||
 "core-foundation",
 | 
			
		||||
 "core-foundation-sys",
 | 
			
		||||
 "libc",
 | 
			
		||||
 "security-framework-sys",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "security-framework-sys"
 | 
			
		||||
version = "2.9.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "core-foundation-sys",
 | 
			
		||||
 "libc",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "semver"
 | 
			
		||||
version = "1.0.17"
 | 
			
		||||
@@ -1298,6 +1538,19 @@ dependencies = [
 | 
			
		||||
 "unicode-ident",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "tempfile"
 | 
			
		||||
version = "3.5.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cfg-if",
 | 
			
		||||
 "fastrand",
 | 
			
		||||
 "redox_syscall 0.3.5",
 | 
			
		||||
 "rustix",
 | 
			
		||||
 "windows-sys 0.45.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "termcolor"
 | 
			
		||||
version = "1.2.0"
 | 
			
		||||
@@ -1494,6 +1747,21 @@ version = "0.4.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-sys"
 | 
			
		||||
version = "0.42.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "windows_aarch64_gnullvm 0.42.2",
 | 
			
		||||
 "windows_aarch64_msvc 0.42.2",
 | 
			
		||||
 "windows_i686_gnu 0.42.2",
 | 
			
		||||
 "windows_i686_msvc 0.42.2",
 | 
			
		||||
 "windows_x86_64_gnu 0.42.2",
 | 
			
		||||
 "windows_x86_64_gnullvm 0.42.2",
 | 
			
		||||
 "windows_x86_64_msvc 0.42.2",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-sys"
 | 
			
		||||
version = "0.45.0"
 | 
			
		||||
 
 | 
			
		||||
@@ -17,4 +17,6 @@ serde = { version = "1.0.163", features = ["derive"] }
 | 
			
		||||
serde_json = "1.0.96"
 | 
			
		||||
actix-remote-ip = "0.1.0"
 | 
			
		||||
mailchecker = "5.0.9"
 | 
			
		||||
redis = "0.23.0"
 | 
			
		||||
redis = "0.23.0"
 | 
			
		||||
lettre = "0.10.4"
 | 
			
		||||
rand = "0.8.5"
 | 
			
		||||
@@ -55,6 +55,38 @@ pub struct AppConfig {
 | 
			
		||||
    /// Redis password
 | 
			
		||||
    #[clap(long, env, default_value = "secretredis")]
 | 
			
		||||
    redis_password: String,
 | 
			
		||||
 | 
			
		||||
    /// Mail sender
 | 
			
		||||
    #[clap(long, env, default_value = "geneit@example.com")]
 | 
			
		||||
    pub mail_sender: String,
 | 
			
		||||
 | 
			
		||||
    /// SMTP relay
 | 
			
		||||
    #[clap(long, env, default_value = "localhost")]
 | 
			
		||||
    pub smtp_relay: String,
 | 
			
		||||
 | 
			
		||||
    /// SMTP port
 | 
			
		||||
    #[clap(long, env, default_value_t = 1025)]
 | 
			
		||||
    pub smtp_port: u16,
 | 
			
		||||
 | 
			
		||||
    /// SMTP use TLS to connect to relay
 | 
			
		||||
    #[clap(long, env)]
 | 
			
		||||
    pub smtp_tls: bool,
 | 
			
		||||
 | 
			
		||||
    /// SMTP username
 | 
			
		||||
    #[clap(long, env)]
 | 
			
		||||
    pub smtp_username: Option<String>,
 | 
			
		||||
 | 
			
		||||
    /// SMTP password
 | 
			
		||||
    #[clap(long, env)]
 | 
			
		||||
    pub smtp_password: Option<String>,
 | 
			
		||||
 | 
			
		||||
    /// Password reset URL
 | 
			
		||||
    #[clap(
 | 
			
		||||
        long,
 | 
			
		||||
        env,
 | 
			
		||||
        default_value = "http://localhost:3000/reset_password#TOKEN"
 | 
			
		||||
    )]
 | 
			
		||||
    pub reset_password_url: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
lazy_static::lazy_static! {
 | 
			
		||||
@@ -88,4 +120,9 @@ impl AppConfig {
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Get password reset URL
 | 
			
		||||
    pub fn get_password_reset_url(&self, token: &str) -> String {
 | 
			
		||||
        self.reset_password_url.replace("TOKEN", token)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -39,9 +39,12 @@ pub async fn create_account(remote_ip: RemoteIP, req: web::Json<CreateAccountBod
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create the account
 | 
			
		||||
    let user_id = users_service::create_account(&req.name, &req.email).await?;
 | 
			
		||||
    let mut user = users_service::create_account(&req.name, &req.email).await?;
 | 
			
		||||
 | 
			
		||||
    // TODO : trigger reset password (send mail)
 | 
			
		||||
    // Trigger reset password (send mail)
 | 
			
		||||
    users_service::request_reset_password(&mut user).await?;
 | 
			
		||||
 | 
			
		||||
    // TODO : cleanup in a cron not validated accounts after 24 hours
 | 
			
		||||
 | 
			
		||||
    // Account successfully created
 | 
			
		||||
    Ok(HttpResponse::Created().finish())
 | 
			
		||||
 
 | 
			
		||||
@@ -3,20 +3,20 @@ use diesel::prelude::*;
 | 
			
		||||
 | 
			
		||||
/// User ID holder
 | 
			
		||||
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
 | 
			
		||||
pub struct UserID(i32);
 | 
			
		||||
pub struct UserID(pub i32);
 | 
			
		||||
 | 
			
		||||
#[derive(Queryable, Debug)]
 | 
			
		||||
pub struct User {
 | 
			
		||||
    id: i32,
 | 
			
		||||
    name: String,
 | 
			
		||||
    email: String,
 | 
			
		||||
    password: Option<String>,
 | 
			
		||||
    reset_password_token: Option<String>,
 | 
			
		||||
    time_create: i64,
 | 
			
		||||
    time_gen_reset_token: i64,
 | 
			
		||||
    time_activate: i64,
 | 
			
		||||
    active: bool,
 | 
			
		||||
    admin: bool,
 | 
			
		||||
    pub id: i32,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub email: String,
 | 
			
		||||
    pub password: Option<String>,
 | 
			
		||||
    pub reset_password_token: Option<String>,
 | 
			
		||||
    pub time_create: i64,
 | 
			
		||||
    pub time_gen_reset_token: i64,
 | 
			
		||||
    pub time_activate: i64,
 | 
			
		||||
    pub active: bool,
 | 
			
		||||
    pub admin: bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl User {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								geneit_backend/src/services/mail_service.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								geneit_backend/src/services/mail_service.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
use crate::app_config::AppConfig;
 | 
			
		||||
use lettre::message::header::ContentType;
 | 
			
		||||
use lettre::transport::smtp::authentication::Credentials;
 | 
			
		||||
use lettre::{Message, SmtpTransport, Transport};
 | 
			
		||||
use std::fmt::Display;
 | 
			
		||||
 | 
			
		||||
pub async fn send_mail<D: Display>(to: &str, subject: &str, body: D) -> anyhow::Result<()> {
 | 
			
		||||
    let conf = AppConfig::get();
 | 
			
		||||
 | 
			
		||||
    let email = Message::builder()
 | 
			
		||||
        .from(conf.mail_sender.parse()?)
 | 
			
		||||
        .to(to.parse()?)
 | 
			
		||||
        .subject(subject)
 | 
			
		||||
        .header(ContentType::TEXT_PLAIN)
 | 
			
		||||
        .body(body.to_string())?;
 | 
			
		||||
 | 
			
		||||
    let mut mailer = match conf.smtp_tls {
 | 
			
		||||
        true => SmtpTransport::relay(&conf.smtp_relay)?,
 | 
			
		||||
        false => SmtpTransport::builder_dangerous(&conf.smtp_relay),
 | 
			
		||||
    }
 | 
			
		||||
    .port(conf.smtp_port);
 | 
			
		||||
 | 
			
		||||
    if let (Some(username), Some(password)) = (&conf.smtp_username, &conf.smtp_password) {
 | 
			
		||||
        mailer = mailer.credentials(Credentials::new(username.to_string(), password.to_string()))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let mailer = mailer.build();
 | 
			
		||||
 | 
			
		||||
    mailer.send(&email)?;
 | 
			
		||||
    log::debug!("A mail was sent to {} (subject = {})", to, subject);
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
//! # Backend services
 | 
			
		||||
 | 
			
		||||
pub mod mail_service;
 | 
			
		||||
pub mod rate_limiter_service;
 | 
			
		||||
pub mod users_service;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,19 @@
 | 
			
		||||
//! # Users service
 | 
			
		||||
 | 
			
		||||
use crate::app_config::AppConfig;
 | 
			
		||||
use crate::connections::db_connection;
 | 
			
		||||
use crate::models::{NewUser, User};
 | 
			
		||||
use crate::models::{NewUser, User, UserID};
 | 
			
		||||
use crate::schema::users;
 | 
			
		||||
use crate::services::mail_service;
 | 
			
		||||
use crate::utils::string_utils::rand_str;
 | 
			
		||||
use crate::utils::time_utils::time;
 | 
			
		||||
use diesel::prelude::*;
 | 
			
		||||
 | 
			
		||||
/// Get the information of the user
 | 
			
		||||
pub async fn get_by_id(id: UserID) -> anyhow::Result<User> {
 | 
			
		||||
    db_connection::execute(|conn| Ok(users::table.filter(users::dsl::id.eq(id.0)).first(conn)?))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Create a new account
 | 
			
		||||
pub async fn create_account(name: &str, email: &str) -> anyhow::Result<User> {
 | 
			
		||||
    db_connection::execute(|conn| {
 | 
			
		||||
@@ -32,3 +40,41 @@ pub async fn exists_email(email: &str) -> anyhow::Result<bool> {
 | 
			
		||||
        Ok(count != 0)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Request password reset
 | 
			
		||||
pub async fn request_reset_password(user: &mut User) -> anyhow::Result<()> {
 | 
			
		||||
    // If required, regenerate reset token
 | 
			
		||||
    if user.reset_password_token.is_none() || user.time_gen_reset_token as u64 + 3600 * 2 < time() {
 | 
			
		||||
        user.reset_password_token = Some(rand_str(149));
 | 
			
		||||
        user.time_gen_reset_token = time() as i64;
 | 
			
		||||
 | 
			
		||||
        db_connection::execute(|conn| {
 | 
			
		||||
            Ok(
 | 
			
		||||
                diesel::update(users::dsl::users.filter(users::dsl::id.eq(user.id)))
 | 
			
		||||
                    .set((
 | 
			
		||||
                        users::dsl::time_gen_reset_token.eq(user.time_gen_reset_token),
 | 
			
		||||
                        users::dsl::reset_password_token.eq(user.reset_password_token.clone()),
 | 
			
		||||
                    ))
 | 
			
		||||
                    .execute(conn)?,
 | 
			
		||||
            )
 | 
			
		||||
        })?;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Send mail
 | 
			
		||||
    mail_service::send_mail(
 | 
			
		||||
        &user.email,
 | 
			
		||||
        "Réinitialisation de votre mot de passe",
 | 
			
		||||
        format!(
 | 
			
		||||
            "Bonjour, \n\n\
 | 
			
		||||
            Vous pouvez réinitialiser le mot de passe de votre compte à l'adresse suivante : {} \n\n\
 | 
			
		||||
            Ce lien est valide durant 24 heures.\n\n\
 | 
			
		||||
            Cordialement,\n\n\
 | 
			
		||||
            L'équipe de GeneIT",
 | 
			
		||||
            AppConfig::get()
 | 
			
		||||
                .get_password_reset_url(user.reset_password_token.as_deref().unwrap_or(""))
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
    .await?;
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
//! # App utilities
 | 
			
		||||
 | 
			
		||||
pub mod string_utils;
 | 
			
		||||
pub mod time_utils;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								geneit_backend/src/utils/string_utils.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								geneit_backend/src/utils/string_utils.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
use rand::distributions::Alphanumeric;
 | 
			
		||||
use rand::Rng;
 | 
			
		||||
 | 
			
		||||
/// Generate a random string of a given size
 | 
			
		||||
pub fn rand_str(len: usize) -> String {
 | 
			
		||||
    rand::thread_rng()
 | 
			
		||||
        .sample_iter(&Alphanumeric)
 | 
			
		||||
        .map(char::from)
 | 
			
		||||
        .take(len)
 | 
			
		||||
        .collect()
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user