Can export data as ZIP file
This commit is contained in:
		
							
								
								
									
										210
									
								
								moneymgr_backend/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										210
									
								
								moneymgr_backend/Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -34,6 +34,29 @@ dependencies = [
 | 
			
		||||
 "smallvec",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "actix-files"
 | 
			
		||||
version = "0.6.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "0773d59061dedb49a8aed04c67291b9d8cf2fe0b60130a381aab53c6dd86e9be"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "actix-http",
 | 
			
		||||
 "actix-service",
 | 
			
		||||
 "actix-utils",
 | 
			
		||||
 "actix-web",
 | 
			
		||||
 "bitflags",
 | 
			
		||||
 "bytes",
 | 
			
		||||
 "derive_more 0.99.19",
 | 
			
		||||
 "futures-core",
 | 
			
		||||
 "http-range",
 | 
			
		||||
 "log",
 | 
			
		||||
 "mime",
 | 
			
		||||
 "mime_guess",
 | 
			
		||||
 "percent-encoding",
 | 
			
		||||
 "pin-project-lite",
 | 
			
		||||
 "v_htmlescape",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "actix-http"
 | 
			
		||||
version = "3.10.0"
 | 
			
		||||
@@ -412,6 +435,15 @@ version = "1.0.97"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "arbitrary"
 | 
			
		||||
version = "1.4.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "derive_arbitrary",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "arc-swap"
 | 
			
		||||
version = "1.7.1"
 | 
			
		||||
@@ -612,6 +644,25 @@ dependencies = [
 | 
			
		||||
 "bytes",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "bzip2"
 | 
			
		||||
version = "0.5.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bzip2-sys",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "bzip2-sys"
 | 
			
		||||
version = "0.1.13+1.0.8"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cc",
 | 
			
		||||
 "pkg-config",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "castaway"
 | 
			
		||||
version = "0.2.3"
 | 
			
		||||
@@ -827,6 +878,21 @@ dependencies = [
 | 
			
		||||
 "libc",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "crc"
 | 
			
		||||
version = "3.2.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "crc-catalog",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "crc-catalog"
 | 
			
		||||
version = "2.4.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "crc32fast"
 | 
			
		||||
version = "1.4.2"
 | 
			
		||||
@@ -836,6 +902,12 @@ dependencies = [
 | 
			
		||||
 "cfg-if",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "crossbeam-utils"
 | 
			
		||||
version = "0.8.21"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "crunchy"
 | 
			
		||||
version = "0.2.3"
 | 
			
		||||
@@ -915,6 +987,12 @@ dependencies = [
 | 
			
		||||
 "syn",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "deflate64"
 | 
			
		||||
version = "0.1.9"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "der"
 | 
			
		||||
version = "0.7.9"
 | 
			
		||||
@@ -936,6 +1014,17 @@ dependencies = [
 | 
			
		||||
 "serde",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "derive_arbitrary"
 | 
			
		||||
version = "1.4.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "derive_more"
 | 
			
		||||
version = "0.99.19"
 | 
			
		||||
@@ -1365,8 +1454,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cfg-if",
 | 
			
		||||
 "js-sys",
 | 
			
		||||
 "libc",
 | 
			
		||||
 "wasi 0.13.3+wasi-0.2.2",
 | 
			
		||||
 "wasm-bindgen",
 | 
			
		||||
 "windows-targets 0.52.6",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
@@ -1555,6 +1646,12 @@ dependencies = [
 | 
			
		||||
 "pin-project-lite",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "http-range"
 | 
			
		||||
version = "0.1.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "httparse"
 | 
			
		||||
version = "1.10.1"
 | 
			
		||||
@@ -2046,6 +2143,27 @@ version = "0.4.27"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "lzma-rs"
 | 
			
		||||
version = "0.3.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "byteorder",
 | 
			
		||||
 "crc",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "lzma-sys"
 | 
			
		||||
version = "0.1.20"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cc",
 | 
			
		||||
 "libc",
 | 
			
		||||
 "pkg-config",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "maybe-async"
 | 
			
		||||
version = "0.2.10"
 | 
			
		||||
@@ -2141,6 +2259,7 @@ name = "moneymgr_backend"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "actix-cors",
 | 
			
		||||
 "actix-files",
 | 
			
		||||
 "actix-multipart",
 | 
			
		||||
 "actix-remote-ip",
 | 
			
		||||
 "actix-session",
 | 
			
		||||
@@ -2166,8 +2285,10 @@ dependencies = [
 | 
			
		||||
 "serde",
 | 
			
		||||
 "serde_json",
 | 
			
		||||
 "sha2",
 | 
			
		||||
 "tempfile",
 | 
			
		||||
 "thiserror 2.0.12",
 | 
			
		||||
 "tokio",
 | 
			
		||||
 "zip",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
@@ -2378,6 +2499,16 @@ version = "1.1.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "487f2ccd1e17ce8c1bfab3a65c89525af41cfad4c8659021a1e9a2aacd73b89b"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "pbkdf2"
 | 
			
		||||
version = "0.12.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "digest",
 | 
			
		||||
 "hmac",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "pem-rfc7468"
 | 
			
		||||
version = "0.7.0"
 | 
			
		||||
@@ -3142,6 +3273,12 @@ dependencies = [
 | 
			
		||||
 "rand_core 0.6.4",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "simd-adler32"
 | 
			
		||||
version = "0.3.7"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "slab"
 | 
			
		||||
version = "0.4.9"
 | 
			
		||||
@@ -3274,9 +3411,9 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "tempfile"
 | 
			
		||||
version = "3.19.0"
 | 
			
		||||
version = "3.19.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "488960f40a3fd53d72c2a29a58722561dee8afdd175bd88e3db4677d7b2ba600"
 | 
			
		||||
checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "fastrand",
 | 
			
		||||
 "getrandom 0.3.1",
 | 
			
		||||
@@ -3627,6 +3764,12 @@ version = "0.2.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "v_htmlescape"
 | 
			
		||||
version = "0.15.8"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "vcpkg"
 | 
			
		||||
version = "0.2.15"
 | 
			
		||||
@@ -4031,6 +4174,15 @@ version = "0.5.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "xz2"
 | 
			
		||||
version = "0.1.7"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "lzma-sys",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "yoke"
 | 
			
		||||
version = "0.7.5"
 | 
			
		||||
@@ -4101,6 +4253,20 @@ name = "zeroize"
 | 
			
		||||
version = "1.8.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "zeroize_derive",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "zeroize_derive"
 | 
			
		||||
version = "1.4.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "zerovec"
 | 
			
		||||
@@ -4124,6 +4290,46 @@ dependencies = [
 | 
			
		||||
 "syn",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "zip"
 | 
			
		||||
version = "2.6.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1dcb24d0152526ae49b9b96c1dcf71850ca1e0b882e4e28ed898a93c41334744"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "aes",
 | 
			
		||||
 "arbitrary",
 | 
			
		||||
 "bzip2",
 | 
			
		||||
 "constant_time_eq",
 | 
			
		||||
 "crc32fast",
 | 
			
		||||
 "crossbeam-utils",
 | 
			
		||||
 "deflate64",
 | 
			
		||||
 "flate2",
 | 
			
		||||
 "getrandom 0.3.1",
 | 
			
		||||
 "hmac",
 | 
			
		||||
 "indexmap",
 | 
			
		||||
 "lzma-rs",
 | 
			
		||||
 "memchr",
 | 
			
		||||
 "pbkdf2",
 | 
			
		||||
 "sha1",
 | 
			
		||||
 "time",
 | 
			
		||||
 "xz2",
 | 
			
		||||
 "zeroize",
 | 
			
		||||
 "zopfli",
 | 
			
		||||
 "zstd",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "zopfli"
 | 
			
		||||
version = "0.8.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bumpalo",
 | 
			
		||||
 "crc32fast",
 | 
			
		||||
 "log",
 | 
			
		||||
 "simd-adler32",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "zstd"
 | 
			
		||||
version = "0.13.3"
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ actix-cors = "0.7.0"
 | 
			
		||||
actix-multipart = "0.7.0"
 | 
			
		||||
actix-remote-ip = "0.1.0"
 | 
			
		||||
actix-session = { version = "0.10.0", features = ["redis-session"] }
 | 
			
		||||
actix-files = "0.6.6"
 | 
			
		||||
lazy_static = "1.5.0"
 | 
			
		||||
anyhow = "1.0.97"
 | 
			
		||||
serde = { version = "1.0.219", features = ["derive"] }
 | 
			
		||||
@@ -32,3 +33,5 @@ rust-embed = { version = "8.6.0" }
 | 
			
		||||
sha2 = "0.10.8"
 | 
			
		||||
httpdate = "1.0.3"
 | 
			
		||||
chrono = "0.4.41"
 | 
			
		||||
tempfile = "3.19.1"
 | 
			
		||||
zip = "2.6.1"
 | 
			
		||||
@@ -53,3 +53,21 @@ pub const ACCOUNT_TYPES: [AccountTypeDesc; 3] = [
 | 
			
		||||
        icon: include_str!("../assets/saving.svg"),
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
/// ZIP export paths
 | 
			
		||||
pub mod zip_export {
 | 
			
		||||
    /// Accounts file path inside archive
 | 
			
		||||
    pub const ACCOUNTS_FILE: &str = "accounts.json";
 | 
			
		||||
 | 
			
		||||
    /// Movements file path inside archive
 | 
			
		||||
    pub const MOVEMENTS_FILE: &str = "movements.json";
 | 
			
		||||
 | 
			
		||||
    /// Files list file path inside archive
 | 
			
		||||
    pub const FILES_FILE: &str = "files.json";
 | 
			
		||||
 | 
			
		||||
    /// Files directory inside archive
 | 
			
		||||
    pub const FILES_DIR: &str = "files/";
 | 
			
		||||
 | 
			
		||||
    /// Inbox file path inside archive
 | 
			
		||||
    pub const INBOX_FILE: &str = "inbox.json";
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
use crate::app_config::AppConfig;
 | 
			
		||||
use crate::constants;
 | 
			
		||||
use crate::controllers::HttpResult;
 | 
			
		||||
use crate::converters::finances_manager_converter::{
 | 
			
		||||
    FinancesManagerAccount, FinancesManagerFile, FinancesManagerMovement,
 | 
			
		||||
@@ -7,9 +9,23 @@ use crate::extractors::file_extractor::FileExtractor;
 | 
			
		||||
use crate::models::accounts::AccountType;
 | 
			
		||||
use crate::services::accounts_service::UpdateAccountQuery;
 | 
			
		||||
use crate::services::movements_service::UpdateMovementQuery;
 | 
			
		||||
use crate::services::{accounts_service, movements_service};
 | 
			
		||||
use crate::services::{accounts_service, files_service, movements_service};
 | 
			
		||||
use crate::utils::time_utils::{format_date, time};
 | 
			
		||||
use actix_web::HttpResponse;
 | 
			
		||||
use actix_files::NamedFile;
 | 
			
		||||
use actix_web::{HttpRequest, HttpResponse};
 | 
			
		||||
use serde::Serialize;
 | 
			
		||||
use std::fs::File;
 | 
			
		||||
use std::io::Write;
 | 
			
		||||
use zip::ZipWriter;
 | 
			
		||||
use zip::write::SimpleFileOptions;
 | 
			
		||||
 | 
			
		||||
/// Generate export filename
 | 
			
		||||
fn export_filename(ext: &str) -> String {
 | 
			
		||||
    format!(
 | 
			
		||||
        "export_{}.{ext}",
 | 
			
		||||
        format_date(time() as i64).unwrap().replace('/', "-")
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Import data from a [FinancesManager](https://gitlab.com/pierre42100/cpp-financesmanager) file
 | 
			
		||||
pub async fn finances_manager_import(auth: AuthExtractor, file: FileExtractor) -> HttpResult {
 | 
			
		||||
@@ -69,10 +85,71 @@ pub async fn finances_manager_export(auth: AuthExtractor) -> HttpResult {
 | 
			
		||||
    Ok(HttpResponse::Ok()
 | 
			
		||||
        .insert_header((
 | 
			
		||||
            "Content-Disposition",
 | 
			
		||||
            format!(
 | 
			
		||||
                "attachment; filename=export_{}.finance",
 | 
			
		||||
                format_date(time() as i64)?.replace('/', "-")
 | 
			
		||||
            ),
 | 
			
		||||
            format!("attachment; filename={}", export_filename("finance")),
 | 
			
		||||
        ))
 | 
			
		||||
        .body(out.encode()))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Add JSON file to ZIP
 | 
			
		||||
fn zip_json<E: Serialize>(
 | 
			
		||||
    zip: &mut ZipWriter<File>,
 | 
			
		||||
    path: &str,
 | 
			
		||||
    content: &E,
 | 
			
		||||
) -> anyhow::Result<()> {
 | 
			
		||||
    let file_encoded = serde_json::to_string(&content)?;
 | 
			
		||||
 | 
			
		||||
    let options = SimpleFileOptions::default()
 | 
			
		||||
        .compression_method(zip::CompressionMethod::Deflated)
 | 
			
		||||
        .unix_permissions(0o750);
 | 
			
		||||
 | 
			
		||||
    zip.start_file(path, options)?;
 | 
			
		||||
    zip.write_all(file_encoded.as_bytes())?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Export all user data as ZIP
 | 
			
		||||
pub async fn zip_export(req: HttpRequest, auth: AuthExtractor) -> HttpResult {
 | 
			
		||||
    let dest_dir = tempfile::tempdir_in(&AppConfig::get().temp_dir)?;
 | 
			
		||||
    let zip_path = dest_dir.path().join("export.zip");
 | 
			
		||||
 | 
			
		||||
    let file = File::create(&zip_path)?;
 | 
			
		||||
    let mut zip = ZipWriter::new(file);
 | 
			
		||||
 | 
			
		||||
    // Process all JSON documents
 | 
			
		||||
    zip_json(
 | 
			
		||||
        &mut zip,
 | 
			
		||||
        constants::zip_export::ACCOUNTS_FILE,
 | 
			
		||||
        &accounts_service::get_list_user(auth.user_id()).await?,
 | 
			
		||||
    )?;
 | 
			
		||||
    zip_json(
 | 
			
		||||
        &mut zip,
 | 
			
		||||
        constants::zip_export::MOVEMENTS_FILE,
 | 
			
		||||
        &movements_service::get_all_movements_user(auth.user_id()).await?,
 | 
			
		||||
    )?;
 | 
			
		||||
    let files_list = files_service::get_all_files_user(auth.user_id()).await?;
 | 
			
		||||
    zip_json(&mut zip, constants::zip_export::FILES_FILE, &files_list)?;
 | 
			
		||||
    // TODO : inbox
 | 
			
		||||
 | 
			
		||||
    // Process all files
 | 
			
		||||
    for file in files_list {
 | 
			
		||||
        let buff = files_service::get_file_content(&file).await?;
 | 
			
		||||
 | 
			
		||||
        let options = SimpleFileOptions::default()
 | 
			
		||||
            .compression_method(zip::CompressionMethod::Deflated)
 | 
			
		||||
            .unix_permissions(0o750);
 | 
			
		||||
 | 
			
		||||
        zip.start_file(
 | 
			
		||||
            format!("{}{}", constants::zip_export::FILES_DIR, file.sha512),
 | 
			
		||||
            options,
 | 
			
		||||
        )?;
 | 
			
		||||
        zip.write_all(&buff)?;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Finalize ZIP and return response
 | 
			
		||||
    zip.finish()?;
 | 
			
		||||
    let file = File::open(zip_path)?;
 | 
			
		||||
 | 
			
		||||
    let file = NamedFile::from_file(file, export_filename("zip"))?;
 | 
			
		||||
 | 
			
		||||
    Ok(file.into_response(&req))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
use actix_web::http::StatusCode;
 | 
			
		||||
use actix_web::{HttpResponse, ResponseError};
 | 
			
		||||
use std::error::Error;
 | 
			
		||||
use zip::result::ZipError;
 | 
			
		||||
 | 
			
		||||
pub mod accounts_controller;
 | 
			
		||||
pub mod auth_controller;
 | 
			
		||||
@@ -30,6 +31,10 @@ pub enum HttpFailure {
 | 
			
		||||
    InternalError(#[from] anyhow::Error),
 | 
			
		||||
    #[error("a serde_json error occurred: {0}")]
 | 
			
		||||
    SerdeJsonError(#[from] serde_json::error::Error),
 | 
			
		||||
    #[error("a zip manipulation error occurred: {0}")]
 | 
			
		||||
    ZipError(#[from] ZipError),
 | 
			
		||||
    #[error("a standard I/O manipulation error occurred: {0}")]
 | 
			
		||||
    StdIoError(#[from] std::io::Error),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ResponseError for HttpFailure {
 | 
			
		||||
 
 | 
			
		||||
@@ -170,6 +170,10 @@ async fn main() -> std::io::Result<()> {
 | 
			
		||||
                "/api/backup/finances_manager/export",
 | 
			
		||||
                web::get().to(backup_controller::finances_manager_export),
 | 
			
		||||
            )
 | 
			
		||||
            .route(
 | 
			
		||||
                "/api/backup/zip/export",
 | 
			
		||||
                web::get().to(backup_controller::zip_export),
 | 
			
		||||
            )
 | 
			
		||||
            // Static assets
 | 
			
		||||
            .route("/", web::get().to(static_controller::root_index))
 | 
			
		||||
            .route(
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user