Can delete member image
This commit is contained in:
		
							
								
								
									
										323
									
								
								geneit_backend/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										323
									
								
								geneit_backend/Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -482,6 +482,12 @@ dependencies = [
 | 
				
			|||||||
 "zeroize",
 | 
					 "zeroize",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "bit_field"
 | 
				
			||||||
 | 
					version = "0.10.2"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "bitflags"
 | 
					name = "bitflags"
 | 
				
			||||||
version = "1.3.2"
 | 
					version = "1.3.2"
 | 
				
			||||||
@@ -540,6 +546,12 @@ version = "3.13.0"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
 | 
					checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "bytemuck"
 | 
				
			||||||
 | 
					version = "1.13.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "byteorder"
 | 
					name = "byteorder"
 | 
				
			||||||
version = "1.4.3"
 | 
					version = "1.4.3"
 | 
				
			||||||
@@ -640,6 +652,12 @@ version = "0.5.0"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
 | 
					checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "color_quant"
 | 
				
			||||||
 | 
					version = "1.1.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "colorchoice"
 | 
					name = "colorchoice"
 | 
				
			||||||
version = "1.0.0"
 | 
					version = "1.0.0"
 | 
				
			||||||
@@ -707,6 +725,55 @@ dependencies = [
 | 
				
			|||||||
 "cfg-if",
 | 
					 "cfg-if",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "crossbeam-channel"
 | 
				
			||||||
 | 
					version = "0.5.8"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "cfg-if",
 | 
				
			||||||
 | 
					 "crossbeam-utils",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "crossbeam-deque"
 | 
				
			||||||
 | 
					version = "0.8.3"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "cfg-if",
 | 
				
			||||||
 | 
					 "crossbeam-epoch",
 | 
				
			||||||
 | 
					 "crossbeam-utils",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "crossbeam-epoch"
 | 
				
			||||||
 | 
					version = "0.9.15"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "autocfg",
 | 
				
			||||||
 | 
					 "cfg-if",
 | 
				
			||||||
 | 
					 "crossbeam-utils",
 | 
				
			||||||
 | 
					 "memoffset",
 | 
				
			||||||
 | 
					 "scopeguard",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "crossbeam-utils"
 | 
				
			||||||
 | 
					version = "0.8.16"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "cfg-if",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "crunchy"
 | 
				
			||||||
 | 
					version = "0.2.2"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "crypto-common"
 | 
					name = "crypto-common"
 | 
				
			||||||
version = "0.1.6"
 | 
					version = "0.1.6"
 | 
				
			||||||
@@ -913,6 +980,12 @@ version = "0.3.0"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
 | 
					checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "either"
 | 
				
			||||||
 | 
					version = "1.9.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "email-encoding"
 | 
					name = "email-encoding"
 | 
				
			||||||
version = "0.2.0"
 | 
					version = "0.2.0"
 | 
				
			||||||
@@ -978,6 +1051,22 @@ dependencies = [
 | 
				
			|||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "exr"
 | 
				
			||||||
 | 
					version = "1.7.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "d1e481eb11a482815d3e9d618db8c42a93207134662873809335a92327440c18"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "bit_field",
 | 
				
			||||||
 | 
					 "flume",
 | 
				
			||||||
 | 
					 "half",
 | 
				
			||||||
 | 
					 "lebe",
 | 
				
			||||||
 | 
					 "miniz_oxide",
 | 
				
			||||||
 | 
					 "rayon-core",
 | 
				
			||||||
 | 
					 "smallvec",
 | 
				
			||||||
 | 
					 "zune-inflate",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "fast_chemail"
 | 
					name = "fast_chemail"
 | 
				
			||||||
version = "0.9.6"
 | 
					version = "0.9.6"
 | 
				
			||||||
@@ -996,6 +1085,15 @@ dependencies = [
 | 
				
			|||||||
 "instant",
 | 
					 "instant",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "fdeflate"
 | 
				
			||||||
 | 
					version = "0.3.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "simd-adler32",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "flate2"
 | 
					name = "flate2"
 | 
				
			||||||
version = "1.0.26"
 | 
					version = "1.0.26"
 | 
				
			||||||
@@ -1006,6 +1104,19 @@ dependencies = [
 | 
				
			|||||||
 "miniz_oxide",
 | 
					 "miniz_oxide",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "flume"
 | 
				
			||||||
 | 
					version = "0.10.14"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "futures-core",
 | 
				
			||||||
 | 
					 "futures-sink",
 | 
				
			||||||
 | 
					 "nanorand",
 | 
				
			||||||
 | 
					 "pin-project",
 | 
				
			||||||
 | 
					 "spin",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "fnv"
 | 
					name = "fnv"
 | 
				
			||||||
version = "1.0.7"
 | 
					version = "1.0.7"
 | 
				
			||||||
@@ -1139,6 +1250,7 @@ dependencies = [
 | 
				
			|||||||
 "diesel",
 | 
					 "diesel",
 | 
				
			||||||
 "env_logger",
 | 
					 "env_logger",
 | 
				
			||||||
 "futures-util",
 | 
					 "futures-util",
 | 
				
			||||||
 | 
					 "image",
 | 
				
			||||||
 "lazy_static",
 | 
					 "lazy_static",
 | 
				
			||||||
 "lettre",
 | 
					 "lettre",
 | 
				
			||||||
 "light-openid",
 | 
					 "light-openid",
 | 
				
			||||||
@@ -1151,7 +1263,9 @@ dependencies = [
 | 
				
			|||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "serde_json",
 | 
					 "serde_json",
 | 
				
			||||||
 "serde_with",
 | 
					 "serde_with",
 | 
				
			||||||
 | 
					 "sha2",
 | 
				
			||||||
 "thiserror",
 | 
					 "thiserror",
 | 
				
			||||||
 | 
					 "uuid",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@@ -1171,8 +1285,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			|||||||
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
 | 
					checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "cfg-if",
 | 
					 "cfg-if",
 | 
				
			||||||
 | 
					 "js-sys",
 | 
				
			||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
 "wasi",
 | 
					 "wasi",
 | 
				
			||||||
 | 
					 "wasm-bindgen",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "gif"
 | 
				
			||||||
 | 
					version = "0.12.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "color_quant",
 | 
				
			||||||
 | 
					 "weezl",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@@ -1200,6 +1326,15 @@ dependencies = [
 | 
				
			|||||||
 "tracing",
 | 
					 "tracing",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "half"
 | 
				
			||||||
 | 
					version = "2.2.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "crunchy",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "hashbrown"
 | 
					name = "hashbrown"
 | 
				
			||||||
version = "0.12.3"
 | 
					version = "0.12.3"
 | 
				
			||||||
@@ -1373,6 +1508,25 @@ dependencies = [
 | 
				
			|||||||
 "unicode-normalization",
 | 
					 "unicode-normalization",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "image"
 | 
				
			||||||
 | 
					version = "0.24.6"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "bytemuck",
 | 
				
			||||||
 | 
					 "byteorder",
 | 
				
			||||||
 | 
					 "color_quant",
 | 
				
			||||||
 | 
					 "exr",
 | 
				
			||||||
 | 
					 "gif",
 | 
				
			||||||
 | 
					 "jpeg-decoder",
 | 
				
			||||||
 | 
					 "num-rational",
 | 
				
			||||||
 | 
					 "num-traits",
 | 
				
			||||||
 | 
					 "png",
 | 
				
			||||||
 | 
					 "qoi",
 | 
				
			||||||
 | 
					 "tiff",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "indexmap"
 | 
					name = "indexmap"
 | 
				
			||||||
version = "1.9.3"
 | 
					version = "1.9.3"
 | 
				
			||||||
@@ -1445,6 +1599,15 @@ dependencies = [
 | 
				
			|||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "jpeg-decoder"
 | 
				
			||||||
 | 
					version = "0.3.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "rayon",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "js-sys"
 | 
					name = "js-sys"
 | 
				
			||||||
version = "0.3.64"
 | 
					version = "0.3.64"
 | 
				
			||||||
@@ -1466,6 +1629,12 @@ version = "1.4.0"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 | 
					checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "lebe"
 | 
				
			||||||
 | 
					version = "0.5.2"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "lettre"
 | 
					name = "lettre"
 | 
				
			||||||
version = "0.10.4"
 | 
					version = "0.10.4"
 | 
				
			||||||
@@ -1594,6 +1763,15 @@ version = "2.5.0"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 | 
					checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "memoffset"
 | 
				
			||||||
 | 
					version = "0.9.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "autocfg",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "mime"
 | 
					name = "mime"
 | 
				
			||||||
version = "0.3.17"
 | 
					version = "0.3.17"
 | 
				
			||||||
@@ -1622,6 +1800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			|||||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
 | 
					checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "adler",
 | 
					 "adler",
 | 
				
			||||||
 | 
					 "simd-adler32",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@@ -1636,6 +1815,15 @@ dependencies = [
 | 
				
			|||||||
 "windows-sys",
 | 
					 "windows-sys",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "nanorand"
 | 
				
			||||||
 | 
					version = "0.7.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "getrandom",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "native-tls"
 | 
					name = "native-tls"
 | 
				
			||||||
version = "0.2.11"
 | 
					version = "0.2.11"
 | 
				
			||||||
@@ -1664,6 +1852,27 @@ dependencies = [
 | 
				
			|||||||
 "minimal-lexical",
 | 
					 "minimal-lexical",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "num-integer"
 | 
				
			||||||
 | 
					version = "0.1.45"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "autocfg",
 | 
				
			||||||
 | 
					 "num-traits",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "num-rational"
 | 
				
			||||||
 | 
					version = "0.4.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "autocfg",
 | 
				
			||||||
 | 
					 "num-integer",
 | 
				
			||||||
 | 
					 "num-traits",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "num-traits"
 | 
					name = "num-traits"
 | 
				
			||||||
version = "0.2.16"
 | 
					version = "0.2.16"
 | 
				
			||||||
@@ -1835,6 +2044,26 @@ dependencies = [
 | 
				
			|||||||
 "siphasher",
 | 
					 "siphasher",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "pin-project"
 | 
				
			||||||
 | 
					version = "1.1.3"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "pin-project-internal",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "pin-project-internal"
 | 
				
			||||||
 | 
					version = "1.1.3"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "proc-macro2",
 | 
				
			||||||
 | 
					 "quote",
 | 
				
			||||||
 | 
					 "syn 2.0.23",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "pin-project-lite"
 | 
					name = "pin-project-lite"
 | 
				
			||||||
version = "0.2.10"
 | 
					version = "0.2.10"
 | 
				
			||||||
@@ -1853,6 +2082,19 @@ version = "0.3.27"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
 | 
					checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "png"
 | 
				
			||||||
 | 
					version = "0.17.9"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "59871cc5b6cce7eaccca5a802b4173377a1c2ba90654246789a8fa2334426d11"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "bitflags 1.3.2",
 | 
				
			||||||
 | 
					 "crc32fast",
 | 
				
			||||||
 | 
					 "fdeflate",
 | 
				
			||||||
 | 
					 "flate2",
 | 
				
			||||||
 | 
					 "miniz_oxide",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "ppv-lite86"
 | 
					name = "ppv-lite86"
 | 
				
			||||||
version = "0.2.17"
 | 
					version = "0.2.17"
 | 
				
			||||||
@@ -1891,6 +2133,15 @@ dependencies = [
 | 
				
			|||||||
 "unicode-ident",
 | 
					 "unicode-ident",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "qoi"
 | 
				
			||||||
 | 
					version = "0.4.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "bytemuck",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "quick-xml"
 | 
					name = "quick-xml"
 | 
				
			||||||
version = "0.26.0"
 | 
					version = "0.26.0"
 | 
				
			||||||
@@ -1946,6 +2197,28 @@ dependencies = [
 | 
				
			|||||||
 "getrandom",
 | 
					 "getrandom",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "rayon"
 | 
				
			||||||
 | 
					version = "1.7.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "either",
 | 
				
			||||||
 | 
					 "rayon-core",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "rayon-core"
 | 
				
			||||||
 | 
					version = "1.11.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "crossbeam-channel",
 | 
				
			||||||
 | 
					 "crossbeam-deque",
 | 
				
			||||||
 | 
					 "crossbeam-utils",
 | 
				
			||||||
 | 
					 "num_cpus",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "redis"
 | 
					name = "redis"
 | 
				
			||||||
version = "0.23.0"
 | 
					version = "0.23.0"
 | 
				
			||||||
@@ -2332,6 +2605,12 @@ dependencies = [
 | 
				
			|||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "simd-adler32"
 | 
				
			||||||
 | 
					version = "0.3.7"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "siphasher"
 | 
					name = "siphasher"
 | 
				
			||||||
version = "0.3.10"
 | 
					version = "0.3.10"
 | 
				
			||||||
@@ -2374,6 +2653,15 @@ dependencies = [
 | 
				
			|||||||
 "winapi",
 | 
					 "winapi",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "spin"
 | 
				
			||||||
 | 
					version = "0.9.8"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "lock_api",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "static_assertions"
 | 
					name = "static_assertions"
 | 
				
			||||||
version = "1.1.0"
 | 
					version = "1.1.0"
 | 
				
			||||||
@@ -2468,6 +2756,17 @@ dependencies = [
 | 
				
			|||||||
 "syn 2.0.23",
 | 
					 "syn 2.0.23",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "tiff"
 | 
				
			||||||
 | 
					version = "0.8.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "7449334f9ff2baf290d55d73983a7d6fa15e01198faef72af07e2a8db851e471"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "flate2",
 | 
				
			||||||
 | 
					 "jpeg-decoder",
 | 
				
			||||||
 | 
					 "weezl",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "time"
 | 
					name = "time"
 | 
				
			||||||
version = "0.3.22"
 | 
					version = "0.3.22"
 | 
				
			||||||
@@ -2652,6 +2951,15 @@ version = "0.2.1"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
 | 
					checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "uuid"
 | 
				
			||||||
 | 
					version = "1.4.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "getrandom",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "vcpkg"
 | 
					name = "vcpkg"
 | 
				
			||||||
version = "0.2.15"
 | 
					version = "0.2.15"
 | 
				
			||||||
@@ -2768,6 +3076,12 @@ dependencies = [
 | 
				
			|||||||
 "wasm-bindgen",
 | 
					 "wasm-bindgen",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "weezl"
 | 
				
			||||||
 | 
					version = "0.1.7"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "winapi"
 | 
					name = "winapi"
 | 
				
			||||||
version = "0.3.9"
 | 
					version = "0.3.9"
 | 
				
			||||||
@@ -2918,3 +3232,12 @@ dependencies = [
 | 
				
			|||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
 "pkg-config",
 | 
					 "pkg-config",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "zune-inflate"
 | 
				
			||||||
 | 
					version = "0.2.54"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "simd-adler32",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,3 +29,6 @@ thiserror = "1.0.40"
 | 
				
			|||||||
serde_with = "3.1.0"
 | 
					serde_with = "3.1.0"
 | 
				
			||||||
rust_iso3166 = "0.1.10"
 | 
					rust_iso3166 = "0.1.10"
 | 
				
			||||||
rust-s3 = "0.33.0"
 | 
					rust-s3 = "0.33.0"
 | 
				
			||||||
 | 
					sha2 = "0.10.7"
 | 
				
			||||||
 | 
					image = "0.24.6"
 | 
				
			||||||
 | 
					uuid = { version = "1.4.1", features = ["v4"] }
 | 
				
			||||||
@@ -32,7 +32,8 @@ CREATE TABLE memberships (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
CREATE TABLE photos (
 | 
					CREATE TABLE photos (
 | 
				
			||||||
    id SERIAL PRIMARY KEY,
 | 
					    id SERIAL PRIMARY KEY,
 | 
				
			||||||
    time_create VARCHAR(130) NOT NULL,
 | 
					    file_id VARCHAR(36) NOT NULL,
 | 
				
			||||||
 | 
					    time_create BIGINT NOT NULL,
 | 
				
			||||||
    mime_type VARCHAR(150) NOT NULL,
 | 
					    mime_type VARCHAR(150) NOT NULL,
 | 
				
			||||||
    sha512 VARCHAR(130) NOT NULL,
 | 
					    sha512 VARCHAR(130) NOT NULL,
 | 
				
			||||||
    file_size INTEGER NOT NULL,
 | 
					    file_size INTEGER NOT NULL,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,3 +45,21 @@ pub async fn create_bucket_if_required() -> anyhow::Result<()> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Upload a new file to the bucket
 | 
				
			||||||
 | 
					pub async fn upload_file(path: &str, content: &[u8]) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    let bucket = AppConfig::get().s3_bucket()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bucket.put_object(path, content).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Delete a file, if it exists
 | 
				
			||||||
 | 
					pub async fn delete_file_if_exists(path: &str) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    let bucket = AppConfig::get().s3_bucket()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bucket.delete_object(path).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -128,3 +128,9 @@ pub const ALLOWED_PHOTOS_MIMETYPES: [&str; 6] = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Uploaded photos max size
 | 
					/// Uploaded photos max size
 | 
				
			||||||
pub const PHOTOS_MAX_SIZE: usize = 10 * 1000 * 1000;
 | 
					pub const PHOTOS_MAX_SIZE: usize = 10 * 1000 * 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Thumbnail width
 | 
				
			||||||
 | 
					pub const THUMB_WIDTH: u32 = 150;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Thumbnail height
 | 
				
			||||||
 | 
					pub const THUMB_HEIGHT: u32 = 150;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@ use crate::controllers::HttpResult;
 | 
				
			|||||||
use crate::extractors::family_extractor::FamilyInPath;
 | 
					use crate::extractors::family_extractor::FamilyInPath;
 | 
				
			||||||
use crate::extractors::member_extractor::FamilyAndMemberInPath;
 | 
					use crate::extractors::member_extractor::FamilyAndMemberInPath;
 | 
				
			||||||
use crate::models::{Member, MemberID, Sex};
 | 
					use crate::models::{Member, MemberID, Sex};
 | 
				
			||||||
use crate::services::members_service;
 | 
					use crate::services::{members_service, photos_service};
 | 
				
			||||||
use crate::utils::countries_utils;
 | 
					use crate::utils::countries_utils;
 | 
				
			||||||
use actix_multipart::form::tempfile::TempFile;
 | 
					use actix_multipart::form::tempfile::TempFile;
 | 
				
			||||||
use actix_multipart::form::MultipartForm;
 | 
					use actix_multipart::form::MultipartForm;
 | 
				
			||||||
@@ -237,13 +237,13 @@ pub async fn create(f: FamilyInPath, req: web::Json<MemberRequest>) -> HttpResul
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if let Err(e) = req.0.to_member(&mut member).await {
 | 
					    if let Err(e) = req.0.to_member(&mut member).await {
 | 
				
			||||||
        log::error!("Failed to apply member information! {e}");
 | 
					        log::error!("Failed to apply member information! {e}");
 | 
				
			||||||
        members_service::delete(&member).await?;
 | 
					        members_service::delete(&mut member).await?;
 | 
				
			||||||
        return Ok(HttpResponse::BadRequest().body(e.to_string()));
 | 
					        return Ok(HttpResponse::BadRequest().body(e.to_string()));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if let Err(e) = members_service::update(&mut member).await {
 | 
					    if let Err(e) = members_service::update(&mut member).await {
 | 
				
			||||||
        log::error!("Failed to update member information! {e}");
 | 
					        log::error!("Failed to update member information! {e}");
 | 
				
			||||||
        members_service::delete(&member).await?;
 | 
					        members_service::delete(&mut member).await?;
 | 
				
			||||||
        return Ok(HttpResponse::InternalServerError().finish());
 | 
					        return Ok(HttpResponse::InternalServerError().finish());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -291,7 +291,7 @@ pub async fn update(m: FamilyAndMemberInPath, req: web::Json<MemberRequest>) ->
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Delete a member
 | 
					/// Delete a member
 | 
				
			||||||
pub async fn delete(m: FamilyAndMemberInPath) -> HttpResult {
 | 
					pub async fn delete(m: FamilyAndMemberInPath) -> HttpResult {
 | 
				
			||||||
    members_service::delete(&m).await?;
 | 
					    members_service::delete(&mut m.to_member()).await?;
 | 
				
			||||||
    Ok(HttpResponse::Ok().finish())
 | 
					    Ok(HttpResponse::Ok().finish())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -303,8 +303,24 @@ pub struct UploadPhotoForm {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Upload a new photo for a user
 | 
					/// Upload a new photo for a user
 | 
				
			||||||
pub async fn set_photo(
 | 
					pub async fn set_photo(
 | 
				
			||||||
    _m: FamilyAndMemberInPath,
 | 
					    m: FamilyAndMemberInPath,
 | 
				
			||||||
    MultipartForm(_form): MultipartForm<UploadPhotoForm>,
 | 
					    MultipartForm(form): MultipartForm<UploadPhotoForm>,
 | 
				
			||||||
) -> HttpResult {
 | 
					) -> HttpResult {
 | 
				
			||||||
    todo!()
 | 
					    let photo = photos_service::finalize_upload(form.photo).await?;
 | 
				
			||||||
 | 
					    let mut member = m.to_member();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    members_service::remove_photo(&mut member).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    member.set_photo_id(Some(photo.id()));
 | 
				
			||||||
 | 
					    members_service::update(&mut member).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(HttpResponse::Ok().finish())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Remove a photo
 | 
				
			||||||
 | 
					pub async fn remove_photo(m: FamilyAndMemberInPath) -> HttpResult {
 | 
				
			||||||
 | 
					    let mut member = m.to_member();
 | 
				
			||||||
 | 
					    members_service::remove_photo(&mut member).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(HttpResponse::Ok().finish())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -157,6 +157,10 @@ async fn main() -> std::io::Result<()> {
 | 
				
			|||||||
                "/family/{id}/member/{member_id}/photo",
 | 
					                "/family/{id}/member/{member_id}/photo",
 | 
				
			||||||
                web::put().to(members_controller::set_photo),
 | 
					                web::put().to(members_controller::set_photo),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					            .route(
 | 
				
			||||||
 | 
					                "/family/{id}/member/{member_id}/photo",
 | 
				
			||||||
 | 
					                web::delete().to(members_controller::remove_photo),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    .bind(AppConfig::get().listen_address.as_str())?
 | 
					    .bind(AppConfig::get().listen_address.as_str())?
 | 
				
			||||||
    .run()
 | 
					    .run()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
use crate::schema::{families, members, memberships, users};
 | 
					use crate::schema::{families, members, memberships, photos, users};
 | 
				
			||||||
use diesel::prelude::*;
 | 
					use diesel::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// User ID holder
 | 
					/// User ID holder
 | 
				
			||||||
@@ -121,6 +121,52 @@ pub struct FamilyMembership {
 | 
				
			|||||||
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash)]
 | 
					#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash)]
 | 
				
			||||||
pub struct PhotoID(pub i32);
 | 
					pub struct PhotoID(pub i32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Queryable, Debug, serde::Serialize)]
 | 
				
			||||||
 | 
					pub struct Photo {
 | 
				
			||||||
 | 
					    id: i32,
 | 
				
			||||||
 | 
					    pub file_id: String,
 | 
				
			||||||
 | 
					    pub time_create: i64,
 | 
				
			||||||
 | 
					    pub mime_type: String,
 | 
				
			||||||
 | 
					    pub sha512: String,
 | 
				
			||||||
 | 
					    pub file_size: i32,
 | 
				
			||||||
 | 
					    pub thumb_sha512: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Photo {
 | 
				
			||||||
 | 
					    pub fn id(&self) -> PhotoID {
 | 
				
			||||||
 | 
					        PhotoID(self.id)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn photo_path(&self) -> String {
 | 
				
			||||||
 | 
					        format!("photo/{}", self.file_id)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn thumbnail_path(&self) -> String {
 | 
				
			||||||
 | 
					        format!("thumbnail/{}", self.file_id)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Insertable)]
 | 
				
			||||||
 | 
					#[diesel(table_name = photos)]
 | 
				
			||||||
 | 
					pub struct NewPhoto {
 | 
				
			||||||
 | 
					    pub file_id: String,
 | 
				
			||||||
 | 
					    pub time_create: i64,
 | 
				
			||||||
 | 
					    pub mime_type: String,
 | 
				
			||||||
 | 
					    pub sha512: String,
 | 
				
			||||||
 | 
					    pub file_size: i32,
 | 
				
			||||||
 | 
					    pub thumb_sha512: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl NewPhoto {
 | 
				
			||||||
 | 
					    pub fn photo_path(&self) -> String {
 | 
				
			||||||
 | 
					        format!("photo/{}", self.file_id)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn thumbnail_path(&self) -> String {
 | 
				
			||||||
 | 
					        format!("thumbnail/{}", self.file_id)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Member ID holder
 | 
					/// Member ID holder
 | 
				
			||||||
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash)]
 | 
					#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash)]
 | 
				
			||||||
pub struct MemberID(pub i32);
 | 
					pub struct MemberID(pub i32);
 | 
				
			||||||
@@ -187,6 +233,10 @@ impl Member {
 | 
				
			|||||||
        FamilyID(self.family_id)
 | 
					        FamilyID(self.family_id)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn set_photo_id(&mut self, p: Option<PhotoID>) {
 | 
				
			||||||
 | 
					        self.photo_id = p.map(|p| p.0)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn photo_id(&self) -> Option<PhotoID> {
 | 
					    pub fn photo_id(&self) -> Option<PhotoID> {
 | 
				
			||||||
        self.photo_id.map(PhotoID)
 | 
					        self.photo_id.map(PhotoID)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,7 +64,8 @@ diesel::table! {
 | 
				
			|||||||
diesel::table! {
 | 
					diesel::table! {
 | 
				
			||||||
    photos (id) {
 | 
					    photos (id) {
 | 
				
			||||||
        id -> Int4,
 | 
					        id -> Int4,
 | 
				
			||||||
        time_create -> Varchar,
 | 
					        file_id -> Varchar,
 | 
				
			||||||
 | 
					        time_create -> Int8,
 | 
				
			||||||
        mime_type -> Varchar,
 | 
					        mime_type -> Varchar,
 | 
				
			||||||
        sha512 -> Varchar,
 | 
					        sha512 -> Varchar,
 | 
				
			||||||
        file_size -> Int4,
 | 
					        file_size -> Int4,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
use crate::connections::db_connection;
 | 
					use crate::connections::db_connection;
 | 
				
			||||||
use crate::models::{FamilyID, Member, MemberID, NewMember};
 | 
					use crate::models::{FamilyID, Member, MemberID, NewMember};
 | 
				
			||||||
use crate::schema::members;
 | 
					use crate::schema::members;
 | 
				
			||||||
 | 
					use crate::services::photos_service;
 | 
				
			||||||
use crate::utils::time_utils::time;
 | 
					use crate::utils::time_utils::time;
 | 
				
			||||||
use diesel::prelude::*;
 | 
					use diesel::prelude::*;
 | 
				
			||||||
use diesel::RunQueryDsl;
 | 
					use diesel::RunQueryDsl;
 | 
				
			||||||
@@ -85,10 +86,25 @@ pub async fn update(member: &mut Member) -> anyhow::Result<()> {
 | 
				
			|||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Delete a member photo
 | 
				
			||||||
 | 
					pub async fn remove_photo(member: &mut Member) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    match member.photo_id() {
 | 
				
			||||||
 | 
					        None => {}
 | 
				
			||||||
 | 
					        Some(photo) => {
 | 
				
			||||||
 | 
					            photos_service::delete(photo).await?;
 | 
				
			||||||
 | 
					            member.set_photo_id(None);
 | 
				
			||||||
 | 
					            update(member).await?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Delete a member
 | 
					/// Delete a member
 | 
				
			||||||
pub async fn delete(member: &Member) -> anyhow::Result<()> {
 | 
					pub async fn delete(member: &mut Member) -> anyhow::Result<()> {
 | 
				
			||||||
    // TODO : remove associated couple
 | 
					    // TODO : remove associated couple
 | 
				
			||||||
    // TODO : remove user photo
 | 
					
 | 
				
			||||||
 | 
					    remove_photo(member).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Remove the member
 | 
					    // Remove the member
 | 
				
			||||||
    db_connection::execute(|conn| {
 | 
					    db_connection::execute(|conn| {
 | 
				
			||||||
@@ -101,8 +117,8 @@ pub async fn delete(member: &Member) -> anyhow::Result<()> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Delete all the members of a family
 | 
					/// Delete all the members of a family
 | 
				
			||||||
pub async fn delete_all_family(family_id: FamilyID) -> anyhow::Result<()> {
 | 
					pub async fn delete_all_family(family_id: FamilyID) -> anyhow::Result<()> {
 | 
				
			||||||
    for m in get_all_of_family(family_id).await? {
 | 
					    for mut m in get_all_of_family(family_id).await? {
 | 
				
			||||||
        delete(&m).await?;
 | 
					        delete(&mut m).await?;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,5 +5,6 @@ pub mod login_token_service;
 | 
				
			|||||||
pub mod mail_service;
 | 
					pub mod mail_service;
 | 
				
			||||||
pub mod members_service;
 | 
					pub mod members_service;
 | 
				
			||||||
pub mod openid_service;
 | 
					pub mod openid_service;
 | 
				
			||||||
 | 
					pub mod photos_service;
 | 
				
			||||||
pub mod rate_limiter_service;
 | 
					pub mod rate_limiter_service;
 | 
				
			||||||
pub mod users_service;
 | 
					pub mod users_service;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					use crate::connections::{db_connection, s3_connection};
 | 
				
			||||||
 | 
					use crate::constants::{ALLOWED_PHOTOS_MIMETYPES, PHOTOS_MAX_SIZE, THUMB_HEIGHT, THUMB_WIDTH};
 | 
				
			||||||
 | 
					use crate::models::{NewPhoto, Photo, PhotoID};
 | 
				
			||||||
 | 
					use crate::schema::photos;
 | 
				
			||||||
 | 
					use crate::utils::crypt_utils::sha512;
 | 
				
			||||||
 | 
					use crate::utils::time_utils::time;
 | 
				
			||||||
 | 
					use actix_multipart::form::tempfile::TempFile;
 | 
				
			||||||
 | 
					use diesel::prelude::*;
 | 
				
			||||||
 | 
					use image::imageops::FilterType;
 | 
				
			||||||
 | 
					use image::ImageOutputFormat;
 | 
				
			||||||
 | 
					use std::io::{Cursor, Read};
 | 
				
			||||||
 | 
					use uuid::Uuid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(thiserror::Error, Debug)]
 | 
				
			||||||
 | 
					enum PhotoServiceError {
 | 
				
			||||||
 | 
					    #[error("Uploaded file is too large ({0} bytes)!")]
 | 
				
			||||||
 | 
					    FileToLarge(usize),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[error("Mime type not specified in request!")]
 | 
				
			||||||
 | 
					    MissingMimeType,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[error("Mimetype forbidden ({0})!")]
 | 
				
			||||||
 | 
					    MimeTypeForbidden(String),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Finalize upload of a photo
 | 
				
			||||||
 | 
					pub async fn finalize_upload(mut file: TempFile) -> anyhow::Result<Photo> {
 | 
				
			||||||
 | 
					    // Prerequisite checks
 | 
				
			||||||
 | 
					    if file.size > PHOTOS_MAX_SIZE {
 | 
				
			||||||
 | 
					        return Err(PhotoServiceError::FileToLarge(file.size).into());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mime_type = file
 | 
				
			||||||
 | 
					        .content_type
 | 
				
			||||||
 | 
					        .ok_or(PhotoServiceError::MissingMimeType)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if !ALLOWED_PHOTOS_MIMETYPES.contains(&mime_type.as_ref()) {
 | 
				
			||||||
 | 
					        return Err(PhotoServiceError::MimeTypeForbidden(mime_type.to_string()).into());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut photo_img = Vec::with_capacity(file.size);
 | 
				
			||||||
 | 
					    file.file.read_to_end(&mut photo_img)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let thumbnail_image = image::load_from_memory(&photo_img)?.resize(
 | 
				
			||||||
 | 
					        THUMB_WIDTH,
 | 
				
			||||||
 | 
					        THUMB_HEIGHT,
 | 
				
			||||||
 | 
					        FilterType::Triangle,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut thumb_cursor = Cursor::new(vec![]);
 | 
				
			||||||
 | 
					    thumbnail_image.write_to(&mut thumb_cursor, ImageOutputFormat::Png)?;
 | 
				
			||||||
 | 
					    let thumb_img = thumb_cursor.into_inner();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let photo = NewPhoto {
 | 
				
			||||||
 | 
					        file_id: Uuid::new_v4().to_string(),
 | 
				
			||||||
 | 
					        time_create: time() as i64,
 | 
				
			||||||
 | 
					        mime_type: mime_type.to_string(),
 | 
				
			||||||
 | 
					        sha512: sha512(&photo_img),
 | 
				
			||||||
 | 
					        file_size: photo_img.len() as i32,
 | 
				
			||||||
 | 
					        thumb_sha512: sha512(&thumb_img),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s3_connection::upload_file(&photo.photo_path(), &photo_img).await?;
 | 
				
			||||||
 | 
					    s3_connection::upload_file(&photo.thumbnail_path(), &thumb_img).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    db_connection::execute(|conn| {
 | 
				
			||||||
 | 
					        let res: Photo = diesel::insert_into(photos::table)
 | 
				
			||||||
 | 
					            .values(&photo)
 | 
				
			||||||
 | 
					            .get_result(conn)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(res)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Get a photo by its ID
 | 
				
			||||||
 | 
					pub async fn get_by_id(id: PhotoID) -> anyhow::Result<Photo> {
 | 
				
			||||||
 | 
					    db_connection::execute(|conn| photos::table.filter(photos::dsl::id.eq(id.0)).first(conn))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Delete a photo
 | 
				
			||||||
 | 
					pub async fn delete(id: PhotoID) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    let photo = get_by_id(id).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s3_connection::delete_file_if_exists(&photo.photo_path()).await?;
 | 
				
			||||||
 | 
					    s3_connection::delete_file_if_exists(&photo.thumbnail_path()).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    db_connection::execute(|conn| {
 | 
				
			||||||
 | 
					        diesel::delete(photos::dsl::photos.filter(photos::dsl::id.eq(photo.id().0))).execute(conn)
 | 
				
			||||||
 | 
					    })?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					use sha2::{Digest, Sha512};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Compute hash of a slice of bytes
 | 
				
			||||||
 | 
					pub fn sha512(bytes: &[u8]) -> String {
 | 
				
			||||||
 | 
					    let mut hasher = Sha512::new();
 | 
				
			||||||
 | 
					    hasher.update(bytes);
 | 
				
			||||||
 | 
					    let h = hasher.finalize();
 | 
				
			||||||
 | 
					    format!("{:x}", h)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
//! # App utilities
 | 
					//! # App utilities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod countries_utils;
 | 
					pub mod countries_utils;
 | 
				
			||||||
 | 
					pub mod crypt_utils;
 | 
				
			||||||
pub mod string_utils;
 | 
					pub mod string_utils;
 | 
				
			||||||
pub mod time_utils;
 | 
					pub mod time_utils;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user