diff --git a/Cargo.lock b/Cargo.lock
index 7621423..ab5f548 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -131,9 +131,9 @@ dependencies = [
[[package]]
name = "anstyle"
-version = "1.0.13"
+version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
+checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
[[package]]
name = "anstyle-parse"
@@ -166,15 +166,15 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.100"
+version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
+checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "arc-swap"
-version = "1.9.0"
+version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a07d1f37ff60921c83bdfc7407723bdefe89b44b98a9b772f225c8f9d67141a6"
+checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207"
dependencies = [
"rustversion",
]
@@ -203,7 +203,7 @@ dependencies = [
"nom 7.1.3",
"num-traits",
"rusticata-macros",
- "thiserror 2.0.17",
+ "thiserror 2.0.18",
"time 0.3.47",
]
@@ -255,26 +255,25 @@ dependencies = [
[[package]]
name = "async-compression"
-version = "0.4.34"
+version = "0.4.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e86f6d3dc9dc4352edeea6b8e499e13e3f5dc3b964d7ca5fd411415a3498473"
+checksum = "d0f9ee0f6e02ffd7ad5816e9464499fba7b3effd01123b515c41d1697c43dad1"
dependencies = [
"compression-codecs",
"compression-core",
- "futures-core",
"pin-project-lite",
"tokio",
]
[[package]]
name = "async-executor"
-version = "1.13.3"
+version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8"
+checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a"
dependencies = [
"async-task",
"concurrent-queue",
- "fastrand 2.3.0",
+ "fastrand 2.4.1",
"futures-lite 2.6.1",
"pin-project-lite",
"slab",
@@ -338,9 +337,9 @@ dependencies = [
[[package]]
name = "async-lock"
-version = "3.4.1"
+version = "3.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc"
+checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311"
dependencies = [
"event-listener 5.4.1",
"event-listener-strategy",
@@ -420,9 +419,9 @@ dependencies = [
[[package]]
name = "aws-lc-rs"
-version = "1.15.1"
+version = "1.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b5ce75405893cd713f9ab8e297d8e438f624dde7d706108285f7e17a25a180f"
+checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f"
dependencies = [
"aws-lc-sys",
"untrusted 0.7.1",
@@ -431,9 +430,9 @@ dependencies = [
[[package]]
name = "aws-lc-sys"
-version = "0.34.0"
+version = "0.40.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "179c3777a8b5e70e90ea426114ffc565b2c1a9f82f6c4a0c5a34aa6ef5e781b6"
+checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7"
dependencies = [
"cc",
"cmake",
@@ -460,10 +459,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
-name = "bichon"
+name = "bichon-admin"
+version = "1.0.0"
+dependencies = [
+ "bichon-core",
+ "console",
+ "dialoguer",
+ "tokio",
+]
+
+[[package]]
+name = "bichon-cli"
+version = "1.0.0"
+dependencies = [
+ "base64 0.22.1",
+ "bichon-core",
+ "chrono",
+ "clap",
+ "codepage-strings",
+ "compressed-rtf",
+ "console",
+ "dialoguer",
+ "hex",
+ "mail-parser",
+ "mail-send",
+ "memmap2",
+ "outlook-pst",
+ "reqwest",
+ "serde",
+ "tokio",
+ "toml",
+]
+
+[[package]]
+name = "bichon-core"
version = "1.0.0"
dependencies = [
- "ahash",
"async-imap",
"autoconfig",
"base64 0.22.1",
@@ -471,75 +502,95 @@ dependencies = [
"bytes 1.11.1",
"chrono",
"clap",
- "codepage-strings",
- "compressed-rtf",
- "console",
"dashmap",
- "dialoguer",
"email_address",
"encoding_rs",
"fjall",
"futures",
- "gethostname",
"governor",
- "hex",
"html2text",
- "http 1.4.0",
- "imap-proto",
"itertools",
"itoa",
- "lettre",
"lru 0.17.0",
"mail-parser",
"mail-send",
- "memmap2",
- "mimalloc",
- "mime_guess",
"murmur3",
"native_db",
"native_model",
"num_cpus",
"oauth2",
- "openssl-sys",
- "outlook-pst",
- "poem",
- "poem-derive",
"poem-openapi",
"rand 0.10.1",
- "rcgen",
"regex",
"reqwest",
"ring",
- "rust-embed",
"rustls",
- "rustls-pemfile",
"rustls-pki-types",
- "semver 1.0.28",
"serde",
"serde_json",
"snafu",
"sysinfo",
"tantivy",
- "tempfile",
"time 0.3.47",
- "timeago",
"tokio",
"tokio-io-timeout",
"tokio-rustls",
"tokio-socks",
"tokio-util",
- "toml",
"tracing",
"tracing-appender",
"tracing-log",
"tracing-subscriber",
- "url",
- "urlencoding",
"utf7-imap",
"uuid",
"webpki-roots",
]
+[[package]]
+name = "bichon-server"
+version = "1.0.0"
+dependencies = [
+ "bichon-core",
+ "bichon-smtp",
+ "chrono",
+ "email_address",
+ "governor",
+ "http 1.4.0",
+ "mimalloc",
+ "poem",
+ "poem-derive",
+ "poem-openapi",
+ "rust-embed",
+ "serde",
+ "serde_json",
+ "snafu",
+ "tantivy",
+ "timeago",
+ "tokio",
+ "tracing",
+ "urlencoding",
+]
+
+[[package]]
+name = "bichon-smtp"
+version = "1.0.0"
+dependencies = [
+ "base64 0.22.1",
+ "bichon-core",
+ "lettre",
+ "rcgen",
+ "rustls",
+ "rustls-pemfile",
+ "rustls-pki-types",
+ "serde",
+ "serde_json",
+ "tempfile",
+ "tokio",
+ "tokio-rustls",
+ "tokio-util",
+ "tracing",
+]
+
[[package]]
name = "bincode"
version = "1.3.3"
@@ -551,9 +602,9 @@ dependencies = [
[[package]]
name = "bitflags"
-version = "2.10.0"
+version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
+checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
[[package]]
name = "bitpacking"
@@ -625,7 +676,7 @@ version = "3.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "519bd3116aeeb42d5372c29d982d16d0170d3d4a5ed85fc7dd91642ffff3c67c"
dependencies = [
- "darling",
+ "darling 0.23.0",
"ident_case",
"prettyplease",
"proc-macro2",
@@ -657,9 +708,9 @@ dependencies = [
[[package]]
name = "bumpalo"
-version = "3.19.0"
+version = "3.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
+checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
[[package]]
name = "bytecount"
@@ -699,9 +750,9 @@ checksum = "1c53ba0f290bfc610084c05582d9c5d421662128fc69f4bf236707af6fd321b9"
[[package]]
name = "camino"
-version = "1.2.1"
+version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609"
+checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48"
dependencies = [
"serde_core",
]
@@ -730,9 +781,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.2.47"
+version = "1.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd405d82c84ff7f35739f175f67d8b9fb7687a0e84ccdc78bd3568839827cf07"
+checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20"
dependencies = [
"find-msvc-tools",
"jobserver",
@@ -766,7 +817,7 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601"
dependencies = [
"cfg-if",
"cpufeatures 0.3.0",
- "rand_core 0.10.0",
+ "rand_core 0.10.1",
]
[[package]]
@@ -828,15 +879,15 @@ dependencies = [
[[package]]
name = "clap_lex"
-version = "1.0.0"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831"
+checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
[[package]]
name = "cmake"
-version = "0.1.54"
+version = "0.1.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0"
+checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
dependencies = [
"cc",
]
@@ -863,9 +914,9 @@ dependencies = [
[[package]]
name = "colorchoice"
-version = "1.0.4"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
+checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
[[package]]
name = "combine"
@@ -890,14 +941,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b7f2aaf6791c6517669240b82ef12c1283b39772f0cad3bc5c73f19f6e7f16"
dependencies = [
"byteorder",
- "thiserror 2.0.17",
+ "thiserror 2.0.18",
]
[[package]]
name = "compression-codecs"
-version = "0.4.33"
+version = "0.4.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "302266479cb963552d11bd042013a58ef1adc56768016c8b82b4199488f2d4ad"
+checksum = "eb7b51a7d9c967fc26773061ba86150f19c50c0d65c887cb1fbe295fd16619b7"
dependencies = [
"brotli",
"compression-core",
@@ -936,9 +987,9 @@ dependencies = [
[[package]]
name = "const_fn"
-version = "0.4.11"
+version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f8a2ca5ac02d09563609681103aada9e1777d54fc57a5acd7a41404f9c93b6e"
+checksum = "413d67b29ef1021b4d60f4aa1e925ca031751e213832b4b1d588fae623c05c60"
[[package]]
name = "constant_time_eq"
@@ -946,6 +997,15 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b"
+[[package]]
+name = "convert_case"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9"
+dependencies = [
+ "unicode-segmentation",
+]
+
[[package]]
name = "cookie"
version = "0.14.4"
@@ -957,7 +1017,7 @@ dependencies = [
"hkdf",
"hmac",
"percent-encoding",
- "rand 0.8.5",
+ "rand 0.8.6",
"sha2 0.9.9",
"time 0.2.27",
"version_check",
@@ -1108,15 +1168,15 @@ dependencies = [
"openssl-probe 0.1.6",
"openssl-sys",
"schannel",
- "socket2 0.6.3",
+ "socket2",
"windows-sys 0.59.0",
]
[[package]]
name = "curl-sys"
-version = "0.4.84+curl-8.17.0"
+version = "0.4.87+curl-8.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abc4294dc41b882eaff37973c2ec3ae203d0091341ee68fbadd1d06e0c18a73b"
+checksum = "61a460380f0ef783703dcbe909107f39c162adeac050d73c850055118b5b6327"
dependencies = [
"cc",
"libc",
@@ -1134,8 +1194,18 @@ version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
dependencies = [
- "darling_core",
- "darling_macro",
+ "darling_core 0.20.11",
+ "darling_macro 0.20.11",
+]
+
+[[package]]
+name = "darling"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
+dependencies = [
+ "darling_core 0.23.0",
+ "darling_macro 0.23.0",
]
[[package]]
@@ -1152,13 +1222,37 @@ dependencies = [
"syn 2.0.117",
]
+[[package]]
+name = "darling_core"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
+dependencies = [
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn 2.0.117",
+]
+
[[package]]
name = "darling_macro"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
- "darling_core",
+ "darling_core 0.20.11",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
+dependencies = [
+ "darling_core 0.23.0",
"quote",
"syn 2.0.117",
]
@@ -1179,9 +1273,9 @@ dependencies = [
[[package]]
name = "data-encoding"
-version = "2.9.0"
+version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
+checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea"
[[package]]
name = "datasketches"
@@ -1205,9 +1299,9 @@ dependencies = [
[[package]]
name = "deranged"
-version = "0.5.5"
+version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"
+checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
dependencies = [
"powerfmt",
"serde_core",
@@ -1215,21 +1309,23 @@ dependencies = [
[[package]]
name = "derive_more"
-version = "2.0.1"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
+checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134"
dependencies = [
"derive_more-impl",
]
[[package]]
name = "derive_more-impl"
-version = "2.0.1"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
+checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb"
dependencies = [
+ "convert_case",
"proc-macro2",
"quote",
+ "rustc_version 0.4.1",
"syn 2.0.117",
"unicode-xid",
]
@@ -1450,15 +1546,15 @@ dependencies = [
[[package]]
name = "fastrand"
-version = "2.3.0"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
[[package]]
name = "find-msvc-tools"
-version = "0.1.5"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844"
+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "fjall"
@@ -1479,9 +1575,9 @@ dependencies = [
[[package]]
name = "flate2"
-version = "1.1.5"
+version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
+checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -1634,7 +1730,7 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
dependencies = [
- "fastrand 2.3.0",
+ "fastrand 2.4.1",
"futures-core",
"futures-io",
"parking",
@@ -1720,9 +1816,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
+checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [
"cfg-if",
"js-sys",
@@ -1740,21 +1836,21 @@ dependencies = [
"cfg-if",
"js-sys",
"libc",
- "r-efi",
+ "r-efi 5.3.0",
"wasip2",
"wasm-bindgen",
]
[[package]]
name = "getrandom"
-version = "0.4.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec"
+checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
dependencies = [
"cfg-if",
"libc",
- "r-efi",
- "rand_core 0.10.0",
+ "r-efi 6.0.0",
+ "rand_core 0.10.1",
"wasip2",
"wasip3",
]
@@ -1804,7 +1900,7 @@ dependencies = [
"parking_lot",
"portable-atomic",
"quanta",
- "rand 0.9.2",
+ "rand 0.9.4",
"smallvec",
"spinning_top 0.3.0",
"web-time",
@@ -1812,9 +1908,9 @@ dependencies = [
[[package]]
name = "h2"
-version = "0.4.12"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386"
+checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54"
dependencies = [
"atomic-waker",
"bytes 1.11.1",
@@ -1868,10 +1964,11 @@ dependencies = [
[[package]]
name = "hashify"
-version = "0.2.7"
+version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "149e3ea90eb5a26ad354cfe3cb7f7401b9329032d0235f2687d03a35f30e5d4c"
+checksum = "dd1246c0e5493286aeb2dde35b1f4eb9c4ce00e628641210a5e553fc001a1f26"
dependencies = [
+ "indexmap",
"proc-macro2",
"quote",
"syn 2.0.117",
@@ -1944,11 +2041,11 @@ dependencies = [
"idna 1.1.0",
"ipnet",
"once_cell",
- "rand 0.9.2",
+ "rand 0.9.4",
"ring",
"rustls",
"rustls-pki-types",
- "thiserror 2.0.17",
+ "thiserror 2.0.18",
"time 0.3.47",
"tinyvec",
"tokio",
@@ -1970,11 +2067,11 @@ dependencies = [
"moka",
"once_cell",
"parking_lot",
- "rand 0.9.2",
+ "rand 0.9.4",
"resolv-conf",
"rustls",
"smallvec",
- "thiserror 2.0.17",
+ "thiserror 2.0.18",
"tokio",
"tokio-rustls",
"tracing",
@@ -2019,7 +2116,7 @@ checksum = "d1c97eea9d3e6524d8d2a4643ce0e3135500c4c7ca1d02393a485f871bef69d8"
dependencies = [
"html5ever",
"tendril",
- "thiserror 2.0.17",
+ "thiserror 2.0.18",
"unicode-width",
]
@@ -2133,9 +2230,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
-version = "1.8.1"
+version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11"
+checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca"
dependencies = [
"atomic-waker",
"bytes 1.11.1",
@@ -2148,7 +2245,6 @@ dependencies = [
"httpdate",
"itoa",
"pin-project-lite",
- "pin-utils",
"smallvec",
"tokio",
"want",
@@ -2156,15 +2252,14 @@ dependencies = [
[[package]]
name = "hyper-rustls"
-version = "0.27.7"
+version = "0.27.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58"
+checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f"
dependencies = [
"http 1.4.0",
"hyper",
"hyper-util",
"rustls",
- "rustls-pki-types",
"tokio",
"tokio-rustls",
"tower-service",
@@ -2173,14 +2268,13 @@ dependencies = [
[[package]]
name = "hyper-util"
-version = "0.1.18"
+version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56"
+checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
dependencies = [
"base64 0.22.1",
"bytes 1.11.1",
"futures-channel",
- "futures-core",
"futures-util",
"http 1.4.0",
"http-body",
@@ -2189,7 +2283,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
- "socket2 0.6.3",
+ "socket2",
"tokio",
"tower-service",
"tracing",
@@ -2197,9 +2291,9 @@ dependencies = [
[[package]]
name = "iana-time-zone"
-version = "0.1.64"
+version = "0.1.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
+checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
dependencies = [
"android_system_properties",
"core-foundation-sys",
@@ -2221,12 +2315,13 @@ dependencies = [
[[package]]
name = "icu_collections"
-version = "2.1.1"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
+checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c"
dependencies = [
"displaydoc",
"potential_utf",
+ "utf8_iter",
"yoke",
"zerofrom",
"zerovec",
@@ -2234,9 +2329,9 @@ dependencies = [
[[package]]
name = "icu_locale_core"
-version = "2.1.1"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
+checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29"
dependencies = [
"displaydoc",
"litemap",
@@ -2247,9 +2342,9 @@ dependencies = [
[[package]]
name = "icu_normalizer"
-version = "2.1.1"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
+checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4"
dependencies = [
"icu_collections",
"icu_normalizer_data",
@@ -2261,15 +2356,15 @@ dependencies = [
[[package]]
name = "icu_normalizer_data"
-version = "2.1.1"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
+checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38"
[[package]]
name = "icu_properties"
-version = "2.1.1"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99"
+checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de"
dependencies = [
"icu_collections",
"icu_locale_core",
@@ -2281,15 +2376,15 @@ dependencies = [
[[package]]
name = "icu_properties_data"
-version = "2.1.1"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899"
+checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14"
[[package]]
name = "icu_provider"
-version = "2.1.1"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
+checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421"
dependencies = [
"displaydoc",
"icu_locale_core",
@@ -2346,21 +2441,21 @@ dependencies = [
[[package]]
name = "imap-proto"
-version = "0.16.6"
+version = "0.16.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba1f9b30846c3d04371159ef3a0413ce7c1ae0a8c619cd255c60b3d902553f22"
+checksum = "25f6af35c6a517aea5c72314abe90134980d2ae6a763809b50c208b3e429d71f"
dependencies = [
"nom 7.1.3",
]
[[package]]
name = "indexmap"
-version = "2.12.1"
+version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
+checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
- "hashbrown 0.16.1",
+ "hashbrown 0.17.0",
"serde",
"serde_core",
]
@@ -2400,27 +2495,28 @@ dependencies = [
[[package]]
name = "ipconfig"
-version = "0.3.2"
+version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f"
+checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222"
dependencies = [
- "socket2 0.5.10",
+ "socket2",
"widestring",
- "windows-sys 0.48.0",
- "winreg",
+ "windows-registry",
+ "windows-result",
+ "windows-sys 0.61.2",
]
[[package]]
name = "ipnet"
-version = "2.11.0"
+version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
+checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
[[package]]
name = "iri-string"
-version = "0.7.9"
+version = "0.7.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397"
+checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20"
dependencies = [
"memchr",
"serde",
@@ -2491,7 +2587,7 @@ dependencies = [
"jni-sys",
"log",
"simd_cesu8",
- "thiserror 2.0.17",
+ "thiserror 2.0.18",
"walkdir",
"windows-link",
]
@@ -2540,10 +2636,12 @@ dependencies = [
[[package]]
name = "js-sys"
-version = "0.3.82"
+version = "0.3.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65"
+checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca"
dependencies = [
+ "cfg-if",
+ "futures-util",
"once_cell",
"wasm-bindgen",
]
@@ -2578,7 +2676,7 @@ dependencies = [
"base64 0.22.1",
"email-encoding",
"email_address",
- "fastrand 2.3.0",
+ "fastrand 2.4.1",
"futures-util",
"hostname",
"httpdate",
@@ -2588,7 +2686,7 @@ dependencies = [
"nom 8.0.0",
"percent-encoding",
"quoted_printable",
- "socket2 0.6.3",
+ "socket2",
"tokio",
"url",
]
@@ -2601,9 +2699,9 @@ checksum = "0c2cdeb66e45e9f36bfad5bbdb4d2384e70936afbee843c6f6543f0c551ebb25"
[[package]]
name = "libc"
-version = "0.2.184"
+version = "0.2.185"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af"
+checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
[[package]]
name = "libmimalloc-sys"
@@ -2616,9 +2714,9 @@ dependencies = [
[[package]]
name = "libnghttp2-sys"
-version = "0.1.11+1.64.0"
+version = "0.1.13+1.68.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b6c24e48a7167cffa7119da39d577fa482e66c688a4aac016bee862e1a713c4"
+checksum = "492e00167f1418c15648144f42bbfc63099806ecee9bf8d09a6353d6b4856b3c"
dependencies = [
"cc",
"libc",
@@ -2626,9 +2724,9 @@ dependencies = [
[[package]]
name = "libz-sys"
-version = "1.1.23"
+version = "1.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7"
+checksum = "fc3a226e576f50782b3305c5ccf458698f92798987f551c6a02efe8276721e22"
dependencies = [
"cc",
"libc",
@@ -2650,9 +2748,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
[[package]]
name = "litemap"
-version = "0.8.1"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
+checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0"
[[package]]
name = "lock_api"
@@ -2665,18 +2763,18 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.28"
+version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
dependencies = [
"value-bag",
]
[[package]]
name = "lru"
-version = "0.16.3"
+version = "0.16.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593"
+checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39"
dependencies = [
"hashbrown 0.16.1",
]
@@ -2787,7 +2885,7 @@ dependencies = [
"mail-auth",
"mail-builder",
"md5",
- "rand 0.9.2",
+ "rand 0.9.4",
"rustls",
"rustls-pki-types",
"rustls-platform-verifier",
@@ -2839,9 +2937,9 @@ dependencies = [
[[package]]
name = "memchr"
-version = "2.7.6"
+version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "memmap2"
@@ -2906,9 +3004,9 @@ dependencies = [
[[package]]
name = "moka"
-version = "0.12.12"
+version = "0.12.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3dec6bd31b08944e08b58fd99373893a6c17054d6f3ea5006cc894f4f4eee2a"
+checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046"
dependencies = [
"crossbeam-channel",
"crossbeam-epoch",
@@ -3066,9 +3164,9 @@ checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21"
[[package]]
name = "ntapi"
-version = "0.4.1"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
+checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae"
dependencies = [
"winapi",
]
@@ -3094,9 +3192,9 @@ dependencies = [
[[package]]
name = "num-conv"
-version = "0.2.0"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050"
+checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967"
[[package]]
name = "num-integer"
@@ -3143,9 +3241,9 @@ checksum = "51e219e79014df21a225b1860a479e2dcd7cbd9130f4defd4bd0e191ea31d67d"
dependencies = [
"base64 0.22.1",
"chrono",
- "getrandom 0.2.16",
+ "getrandom 0.2.17",
"http 1.4.0",
- "rand 0.8.5",
+ "rand 0.8.6",
"reqwest",
"serde",
"serde_json",
@@ -3195,9 +3293,9 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.21.3"
+version = "1.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
dependencies = [
"critical-section",
"portable-atomic",
@@ -3223,9 +3321,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "openssl"
-version = "0.10.75"
+version = "0.10.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328"
+checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222"
dependencies = [
"bitflags",
"cfg-if",
@@ -3259,15 +3357,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
-[[package]]
-name = "openssl-src"
-version = "300.5.4+3.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a507b3792995dae9b0df8a1c1e3771e8418b7c2d9f0baeba32e6fe8b06c7cb72"
-dependencies = [
- "cc",
-]
-
[[package]]
name = "openssl-sys"
version = "0.9.114"
@@ -3276,7 +3365,6 @@ checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6"
dependencies = [
"cc",
"libc",
- "openssl-src",
"pkg-config",
"vcpkg",
]
@@ -3296,7 +3384,7 @@ version = "1.1.0"
source = "git+https://github.com/rustmailer/outlook-pst-rs.git?branch=main#3d36200fa359161a127287f47ca031ea8b802e48"
dependencies = [
"byteorder",
- "thiserror 2.0.17",
+ "thiserror 2.0.18",
"tracing",
]
@@ -3389,7 +3477,7 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737"
dependencies = [
- "fastrand 2.3.0",
+ "fastrand 2.4.1",
"phf_shared 0.13.1",
]
@@ -3413,18 +3501,18 @@ dependencies = [
[[package]]
name = "pin-project"
-version = "1.1.10"
+version = "1.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
+checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
-version = "1.1.10"
+version = "1.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
+checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6"
dependencies = [
"proc-macro2",
"quote",
@@ -3433,9 +3521,9 @@ dependencies = [
[[package]]
name = "pin-project-lite"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
+checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "pin-utils"
@@ -3445,20 +3533,20 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "piper"
-version = "0.2.4"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066"
+checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1"
dependencies = [
"atomic-waker",
- "fastrand 2.3.0",
+ "fastrand 2.4.1",
"futures-io",
]
[[package]]
name = "pkg-config"
-version = "0.3.32"
+version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
[[package]]
name = "poem"
@@ -3495,7 +3583,7 @@ dependencies = [
"smallvec",
"sync_wrapper",
"tempfile",
- "thiserror 2.0.17",
+ "thiserror 2.0.18",
"tokio",
"tokio-rustls",
"tokio-stream",
@@ -3539,7 +3627,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"serde_yaml",
- "thiserror 2.0.17",
+ "thiserror 2.0.18",
"tokio",
]
@@ -3549,7 +3637,7 @@ version = "5.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41273b691a3d467a8c44d05506afba9f7b6bd56c9cdf80123de13fe52d7ec587"
dependencies = [
- "darling",
+ "darling 0.20.11",
"http 1.4.0",
"indexmap",
"mime",
@@ -3558,7 +3646,7 @@ dependencies = [
"quote",
"regex",
"syn 2.0.117",
- "thiserror 2.0.17",
+ "thiserror 2.0.18",
]
[[package]]
@@ -3588,15 +3676,15 @@ dependencies = [
[[package]]
name = "portable-atomic"
-version = "1.11.1"
+version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
+checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
[[package]]
name = "potential_utf"
-version = "0.1.4"
+version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
+checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564"
dependencies = [
"zerovec",
]
@@ -3634,9 +3722,9 @@ dependencies = [
[[package]]
name = "proc-macro-crate"
-version = "3.4.0"
+version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
+checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f"
dependencies = [
"toml_edit",
]
@@ -3703,9 +3791,9 @@ dependencies = [
[[package]]
name = "quick_cache"
-version = "0.6.18"
+version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ada44a88ef953a3294f6eb55d2007ba44646015e18613d2f213016379203ef3"
+checksum = "5a70b1b8b47e31d0498ecbc3c5470bb931399a8bfed1fd79d1717a61ce7f96e3"
dependencies = [
"equivalent",
"hashbrown 0.16.1",
@@ -3724,8 +3812,8 @@ dependencies = [
"quinn-udp",
"rustc-hash",
"rustls",
- "socket2 0.6.3",
- "thiserror 2.0.17",
+ "socket2",
+ "thiserror 2.0.18",
"tokio",
"tracing",
"web-time",
@@ -3733,20 +3821,20 @@ dependencies = [
[[package]]
name = "quinn-proto"
-version = "0.11.13"
+version = "0.11.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31"
+checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098"
dependencies = [
"bytes 1.11.1",
"getrandom 0.3.4",
"lru-slab",
- "rand 0.9.2",
+ "rand 0.9.4",
"ring",
"rustc-hash",
"rustls",
"rustls-pki-types",
"slab",
- "thiserror 2.0.17",
+ "thiserror 2.0.18",
"tinyvec",
"tracing",
"web-time",
@@ -3761,7 +3849,7 @@ dependencies = [
"cfg_aliases",
"libc",
"once_cell",
- "socket2 0.6.3",
+ "socket2",
"tracing",
"windows-sys 0.60.2",
]
@@ -3777,9 +3865,9 @@ dependencies = [
[[package]]
name = "quoted_printable"
-version = "0.5.1"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "640c9bd8497b02465aeef5375144c26062e0dcd5939dfcbb0f5db76cb8c17c73"
+checksum = "478e0585659a122aa407eb7e3c0e1fa51b1d8a870038bd29f0cf4a8551eea972"
[[package]]
name = "r-efi"
@@ -3787,6 +3875,12 @@ version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+[[package]]
+name = "r-efi"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
+
[[package]]
name = "rand"
version = "0.7.3"
@@ -3802,9 +3896,9 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
dependencies = [
"libc",
"rand_chacha 0.3.1",
@@ -3813,12 +3907,12 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.9.2"
+version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
+checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
dependencies = [
"rand_chacha 0.9.0",
- "rand_core 0.9.3",
+ "rand_core 0.9.5",
]
[[package]]
@@ -3828,8 +3922,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
dependencies = [
"chacha20",
- "getrandom 0.4.1",
- "rand_core 0.10.0",
+ "getrandom 0.4.2",
+ "rand_core 0.10.1",
]
[[package]]
@@ -3859,7 +3953,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
- "rand_core 0.9.3",
+ "rand_core 0.9.5",
]
[[package]]
@@ -3877,23 +3971,23 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
- "getrandom 0.2.16",
+ "getrandom 0.2.17",
]
[[package]]
name = "rand_core"
-version = "0.9.3"
+version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
+checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
dependencies = [
"getrandom 0.3.4",
]
[[package]]
name = "rand_core"
-version = "0.10.0"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba"
+checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
[[package]]
name = "rand_hc"
@@ -3915,9 +4009,9 @@ dependencies = [
[[package]]
name = "rayon"
-version = "1.11.0"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
+checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
dependencies = [
"either",
"rayon-core",
@@ -3988,9 +4082,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.13"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
+checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
dependencies = [
"aho-corasick",
"memchr",
@@ -3999,15 +4093,15 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.8.8"
+version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
+checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "reqwest"
-version = "0.12.24"
+version = "0.12.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f"
+checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
dependencies = [
"base64 0.22.1",
"bytes 1.11.1",
@@ -4068,7 +4162,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
dependencies = [
"cc",
"cfg-if",
- "getrandom 0.2.16",
+ "getrandom 0.2.17",
"libc",
"untrusted 0.9.0",
"windows-sys 0.52.0",
@@ -4087,9 +4181,9 @@ dependencies = [
[[package]]
name = "rust-embed-impl"
-version = "8.9.0"
+version = "8.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fa2c8c9e8711e10f9c4fd2d64317ef13feaab820a4c51541f1a8c8e2e851ab2"
+checksum = "da0902e4c7c8e997159ab384e6d0fc91c221375f6894346ae107f47dd0f3ccaa"
dependencies = [
"proc-macro2",
"quote",
@@ -4100,9 +4194,9 @@ dependencies = [
[[package]]
name = "rust-embed-utils"
-version = "8.9.0"
+version = "8.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60b161f275cb337fe0a44d924a5f4df0ed69c2c39519858f931ce61c779d3475"
+checksum = "5bcdef0be6fe7f6fa333b1073c949729274b05f123a0ad7efcb8efd878e5c3b1"
dependencies = [
"sha2 0.10.9",
"walkdir",
@@ -4120,9 +4214,9 @@ dependencies = [
[[package]]
name = "rustc-hash"
-version = "2.1.1"
+version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
+checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
[[package]]
name = "rustc_version"
@@ -4240,9 +4334,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
[[package]]
name = "rustls-webpki"
-version = "0.103.8"
+version = "0.103.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52"
+checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
dependencies = [
"aws-lc-rs",
"ring",
@@ -4258,9 +4352,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "ryu"
-version = "1.0.20"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
+checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
[[package]]
name = "same-file"
@@ -4273,9 +4367,9 @@ dependencies = [
[[package]]
name = "schannel"
-version = "0.1.28"
+version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1"
+checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939"
dependencies = [
"windows-sys 0.61.2",
]
@@ -4288,9 +4382,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "security-framework"
-version = "3.6.0"
+version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38"
+checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
dependencies = [
"bitflags",
"core-foundation",
@@ -4311,9 +4405,9 @@ dependencies = [
[[package]]
name = "self_cell"
-version = "1.2.1"
+version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16c2f82143577edb4921b71ede051dac62ca3c16084e918bf7b40c96ae10eb33"
+checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89"
[[package]]
name = "semver"
@@ -4419,9 +4513,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
-version = "1.0.4"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
+checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
dependencies = [
"serde_core",
]
@@ -4535,18 +4629,19 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
-version = "1.4.7"
+version = "1.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad"
+checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
dependencies = [
+ "errno",
"libc",
]
[[package]]
name = "simd-adler32"
-version = "0.3.7"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
+checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
[[package]]
name = "simd_cesu8"
@@ -4566,9 +4661,9 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "siphasher"
-version = "1.0.1"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
+checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
[[package]]
name = "skeptic"
@@ -4596,9 +4691,9 @@ dependencies = [
[[package]]
name = "slab"
-version = "0.4.11"
+version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
+checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]]
name = "sluice"
@@ -4619,9 +4714,9 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "smtp-proto"
-version = "0.2.0"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d55cc1c74d3b758d7dd1fa4dc4cf694cad2732cac14f304228477c2b0ce6233a"
+checksum = "97c9f5dd7ec5cc6d743f33fcb96de4eb91bb1cc51c5e0ba40cb285a9012043da"
[[package]]
name = "snafu"
@@ -4644,16 +4739,6 @@ dependencies = [
"syn 2.0.117",
]
-[[package]]
-name = "socket2"
-version = "0.5.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
-dependencies = [
- "libc",
- "windows-sys 0.52.0",
-]
-
[[package]]
name = "socket2"
version = "0.6.3"
@@ -4814,7 +4899,7 @@ dependencies = [
"cfg-if",
"encoding_rs",
"futures-util",
- "getrandom 0.2.16",
+ "getrandom 0.2.17",
"http-client",
"http-types",
"log",
@@ -4826,6 +4911,12 @@ dependencies = [
"web-sys",
]
+[[package]]
+name = "symlink"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a"
+
[[package]]
name = "syn"
version = "1.0.109"
@@ -4890,9 +4981,9 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
[[package]]
name = "tantivy"
-version = "0.26.0"
+version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "778da245841522199d512d19511b041425d8cff3a8f262b4e1516fceb050289a"
+checksum = "edde6a10743fff00a4e1a8c9ef020bf5f3cbad301b7d2d39f2b07f123c4eac07"
dependencies = [
"aho-corasick",
"arc-swap",
@@ -4912,7 +5003,7 @@ dependencies = [
"itertools",
"levenshtein_automata",
"log",
- "lru 0.16.3",
+ "lru 0.16.4",
"lz4_flex",
"measure_time",
"memmap2",
@@ -4934,7 +5025,7 @@ dependencies = [
"tantivy-stacker",
"tantivy-tokenizer-api",
"tempfile",
- "thiserror 2.0.17",
+ "thiserror 2.0.18",
"time 0.3.47",
"typetag",
"uuid",
@@ -5043,8 +5134,8 @@ version = "3.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [
- "fastrand 2.3.0",
- "getrandom 0.4.1",
+ "fastrand 2.4.1",
+ "getrandom 0.4.2",
"once_cell",
"rustix",
"windows-sys 0.61.2",
@@ -5071,11 +5162,11 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "2.0.17"
+version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
+checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
dependencies = [
- "thiserror-impl 2.0.17",
+ "thiserror-impl 2.0.18",
]
[[package]]
@@ -5091,9 +5182,9 @@ dependencies = [
[[package]]
name = "thiserror-impl"
-version = "2.0.17"
+version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
+checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [
"proc-macro2",
"quote",
@@ -5192,9 +5283,9 @@ dependencies = [
[[package]]
name = "tinystr"
-version = "0.8.2"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
+checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d"
dependencies = [
"displaydoc",
"zerovec",
@@ -5202,9 +5293,9 @@ dependencies = [
[[package]]
name = "tinyvec"
-version = "1.10.0"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
+checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
dependencies = [
"tinyvec_macros",
]
@@ -5227,7 +5318,7 @@ dependencies = [
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
- "socket2 0.6.3",
+ "socket2",
"tokio-macros",
"windows-sys 0.61.2",
]
@@ -5277,9 +5368,9 @@ dependencies = [
[[package]]
name = "tokio-stream"
-version = "0.1.17"
+version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
+checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70"
dependencies = [
"futures-core",
"pin-project-lite",
@@ -5301,17 +5392,17 @@ dependencies = [
[[package]]
name = "toml"
-version = "0.9.10+spec-1.1.0"
+version = "0.9.12+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48"
+checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863"
dependencies = [
"indexmap",
"serde_core",
"serde_spanned",
- "toml_datetime",
+ "toml_datetime 0.7.5+spec-1.1.0",
"toml_parser",
"toml_writer",
- "winnow",
+ "winnow 0.7.15",
]
[[package]]
@@ -5324,37 +5415,46 @@ dependencies = [
]
[[package]]
-name = "toml_edit"
-version = "0.23.7"
+name = "toml_datetime"
+version = "1.1.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d"
+checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.25.11+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b"
dependencies = [
"indexmap",
- "toml_datetime",
+ "toml_datetime 1.1.1+spec-1.1.0",
"toml_parser",
- "winnow",
+ "winnow 1.0.2",
]
[[package]]
name = "toml_parser"
-version = "1.0.6+spec-1.1.0"
+version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44"
+checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
dependencies = [
- "winnow",
+ "winnow 1.0.2",
]
[[package]]
name = "toml_writer"
-version = "1.0.6+spec-1.1.0"
+version = "1.1.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
+checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
[[package]]
name = "tower"
-version = "0.5.2"
+version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
+checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4"
dependencies = [
"futures-core",
"futures-util",
@@ -5367,9 +5467,9 @@ dependencies = [
[[package]]
name = "tower-http"
-version = "0.6.7"
+version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456"
+checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
dependencies = [
"bitflags",
"bytes 1.11.1",
@@ -5409,12 +5509,13 @@ dependencies = [
[[package]]
name = "tracing-appender"
-version = "0.2.4"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf"
+checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c"
dependencies = [
"crossbeam-channel",
- "thiserror 2.0.17",
+ "symlink",
+ "thiserror 2.0.18",
"time 0.3.47",
"tracing-subscriber",
]
@@ -5508,7 +5609,7 @@ dependencies = [
"idna 0.2.3",
"ipnet",
"lazy_static",
- "rand 0.8.5",
+ "rand 0.8.6",
"smallvec",
"thiserror 1.0.69",
"tinyvec",
@@ -5563,9 +5664,9 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
[[package]]
name = "typenum"
-version = "1.19.0"
+version = "1.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
+checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de"
[[package]]
name = "typetag"
@@ -5602,9 +5703,9 @@ dependencies = [
[[package]]
name = "unicase"
-version = "2.8.1"
+version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
+checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
[[package]]
name = "unicode-bidi"
@@ -5614,9 +5715,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
[[package]]
name = "unicode-ident"
-version = "1.0.22"
+version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "unicode-normalization"
@@ -5627,6 +5728,12 @@ dependencies = [
"tinyvec",
]
+[[package]]
+name = "unicode-segmentation"
+version = "1.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c"
+
[[package]]
name = "unicode-width"
version = "0.2.2"
@@ -5727,7 +5834,7 @@ version = "1.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76"
dependencies = [
- "getrandom 0.4.1",
+ "getrandom 0.4.2",
"js-sys",
"serde_core",
"wasm-bindgen",
@@ -5802,11 +5909,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasip2"
-version = "1.0.1+wasi-0.2.4"
+version = "1.0.3+wasi-0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
+checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
dependencies = [
- "wit-bindgen 0.46.0",
+ "wit-bindgen 0.57.1",
]
[[package]]
@@ -5820,9 +5927,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
-version = "0.2.105"
+version = "0.2.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60"
+checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89"
dependencies = [
"cfg-if",
"once_cell",
@@ -5833,22 +5940,19 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.55"
+version = "0.4.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0"
+checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8"
dependencies = [
- "cfg-if",
"js-sys",
- "once_cell",
"wasm-bindgen",
- "web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.105"
+version = "0.2.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2"
+checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -5856,9 +5960,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.105"
+version = "0.2.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc"
+checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904"
dependencies = [
"bumpalo",
"proc-macro2",
@@ -5869,9 +5973,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.105"
+version = "0.2.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76"
+checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129"
dependencies = [
"unicode-ident",
]
@@ -5925,9 +6029,9 @@ dependencies = [
[[package]]
name = "web-sys"
-version = "0.3.82"
+version = "0.3.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1"
+checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -5957,9 +6061,9 @@ dependencies = [
[[package]]
name = "webpki-root-certs"
-version = "1.0.6"
+version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca"
+checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c"
dependencies = [
"rustls-pki-types",
]
@@ -6099,6 +6203,17 @@ dependencies = [
"windows-link",
]
+[[package]]
+name = "windows-registry"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720"
+dependencies = [
+ "windows-link",
+ "windows-result",
+ "windows-strings",
+]
+
[[package]]
name = "windows-result"
version = "0.4.1"
@@ -6117,15 +6232,6 @@ dependencies = [
"windows-link",
]
-[[package]]
-name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets 0.48.5",
-]
-
[[package]]
name = "windows-sys"
version = "0.52.0"
@@ -6162,21 +6268,6 @@ dependencies = [
"windows-link",
]
-[[package]]
-name = "windows-targets"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
-dependencies = [
- "windows_aarch64_gnullvm 0.48.5",
- "windows_aarch64_msvc 0.48.5",
- "windows_i686_gnu 0.48.5",
- "windows_i686_msvc 0.48.5",
- "windows_x86_64_gnu 0.48.5",
- "windows_x86_64_gnullvm 0.48.5",
- "windows_x86_64_msvc 0.48.5",
-]
-
[[package]]
name = "windows-targets"
version = "0.52.6"
@@ -6219,12 +6310,6 @@ dependencies = [
"windows-link",
]
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
@@ -6237,12 +6322,6 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
-
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
@@ -6255,12 +6334,6 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
-[[package]]
-name = "windows_i686_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
-
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
@@ -6285,12 +6358,6 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
-[[package]]
-name = "windows_i686_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
-
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
@@ -6303,12 +6370,6 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
@@ -6321,12 +6382,6 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
-
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
@@ -6339,12 +6394,6 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
-
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
@@ -6359,29 +6408,19 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
name = "winnow"
-version = "0.7.13"
+version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
+checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
+
+[[package]]
+name = "winnow"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0"
dependencies = [
"memchr",
]
-[[package]]
-name = "winreg"
-version = "0.50.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
-dependencies = [
- "cfg-if",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "wit-bindgen"
-version = "0.46.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
-
[[package]]
name = "wit-bindgen"
version = "0.51.0"
@@ -6391,6 +6430,12 @@ dependencies = [
"wit-bindgen-rust-macro",
]
+[[package]]
+name = "wit-bindgen"
+version = "0.57.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
+
[[package]]
name = "wit-bindgen-core"
version = "0.51.0"
@@ -6472,9 +6517,9 @@ dependencies = [
[[package]]
name = "writeable"
-version = "0.6.2"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
+checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4"
[[package]]
name = "x509-parser"
@@ -6490,7 +6535,7 @@ dependencies = [
"oid-registry",
"ring",
"rusticata-macros",
- "thiserror 2.0.17",
+ "thiserror 2.0.18",
"time 0.3.47",
]
@@ -6517,9 +6562,9 @@ dependencies = [
[[package]]
name = "yoke"
-version = "0.8.1"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
+checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca"
dependencies = [
"stable_deref_trait",
"yoke-derive",
@@ -6528,9 +6573,9 @@ dependencies = [
[[package]]
name = "yoke-derive"
-version = "0.8.1"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
+checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e"
dependencies = [
"proc-macro2",
"quote",
@@ -6540,18 +6585,18 @@ dependencies = [
[[package]]
name = "zerocopy"
-version = "0.8.30"
+version = "0.8.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c"
+checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
-version = "0.8.30"
+version = "0.8.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5"
+checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
dependencies = [
"proc-macro2",
"quote",
@@ -6560,18 +6605,18 @@ dependencies = [
[[package]]
name = "zerofrom"
-version = "0.1.6"
+version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
+checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
-version = "0.1.6"
+version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
+checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1"
dependencies = [
"proc-macro2",
"quote",
@@ -6587,9 +6632,9 @@ checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
[[package]]
name = "zerotrie"
-version = "0.2.3"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
+checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf"
dependencies = [
"displaydoc",
"yoke",
@@ -6598,9 +6643,9 @@ dependencies = [
[[package]]
name = "zerovec"
-version = "0.11.5"
+version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
+checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239"
dependencies = [
"yoke",
"zerofrom",
@@ -6609,9 +6654,9 @@ dependencies = [
[[package]]
name = "zerovec-derive"
-version = "0.11.2"
+version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
+checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
dependencies = [
"proc-macro2",
"quote",
@@ -6633,9 +6678,9 @@ dependencies = [
[[package]]
name = "zmij"
-version = "1.0.5"
+version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3280a1b827474fcd5dbef4b35a674deb52ba5c312363aef9135317df179d81b"
+checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
[[package]]
name = "zstd"
diff --git a/Cargo.toml b/Cargo.toml
index 9175525..967fc38 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,48 +1,20 @@
-[package]
-name = "bichon"
+[workspace]
+
+members = ["crates/core", "crates/server", "crates/cli", "crates/admin"]
+
+resolver = "2"
+
+[workspace.package]
version = "1.0.0"
edition = "2021"
-[[bin]]
-name = "bichon"
-path = "src/main.rs"
-
-[[bin]]
-name = "bichonctl"
-path = "src/bin/bichonctl.rs"
-
-[[bin]]
-name = "bichon-admin"
-path = "src/bin/bichon_admin.rs"
-
-
-[features]
-default = []
-vendored-openssl = ["openssl-sys"]
-
-[profile.release]
-strip = true
-lto = true
-opt-level = 3
-codegen-units = 1
-
-[dependencies]
+[workspace.dependencies]
chrono = "0.4.44"
clap = { version = "4.6.1", features = ["derive", "env"] }
mimalloc = "0.1.49"
native_db = "0.8.2"
itertools = "0.14.0"
native_model = "0.4.20"
-poem = { version = "3.1.12", features = ["embed", "compression", "rustls"] }
-poem-derive = "3.1.12"
-poem-openapi = { version = "5.1.16", features = [
- "openapi-explorer",
- "rapidoc",
- "scalar",
- "redoc",
- "swagger-ui",
- "email",
-] }
ring = { version = "0.17.14", features = ["std"] }
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
@@ -74,7 +46,6 @@ tokio-rustls = { version = "0.26.4", default-features = false, features = [
"tls12",
] }
timeago = "0.6.0"
-ahash = "0.8.12"
oauth2 = { version = "5.0.0", features = ["reqwest-blocking"] }
url = { version = "2.5.8", features = ["serde"] }
sysinfo = "0.38.4"
@@ -104,19 +75,12 @@ murmur3 = "0.5.2"
autoconfig = "0.4.0"
urlencoding = "2.1.3"
dashmap = "6.1.0"
-# Statically links OpenSSL by compiling from source, avoiding system library dependencies
-openssl-sys = { version = "0.9.114", optional = true, features = ["vendored"] }
gethostname = "1.1.0"
itoa = "1.0.18"
html2text = "0.17.1"
bytes = "1.11.1"
dialoguer = "0.12.0"
console = "0.16.3"
-toml = "0.9.8"
-memmap2 = "0.9.10"
-outlook-pst = { git = "https://github.com/rustmailer/outlook-pst-rs.git", branch = "main" }
-compressed-rtf = "1.0.1"
-codepage-strings = "1.0.2"
mail-send = "0.6.0"
rcgen = "0.14.7"
rustls-pemfile = "2.2.0"
@@ -126,8 +90,10 @@ fjall = { version = "3.1.4", features = ["lz4", "metrics", "bytes_1"] }
tantivy = { version = "0.26.0", features = ["zstd-compression"] }
tracing-log = "0.2.0"
tokio-util = "0.7.18"
-[dev-dependencies]
-#bincode = "1.3.3"
-#secret-lib = "1.0.0"
-tempfile = "3.27.0"
-lettre = "0.11.21"
+
+
+[profile.release]
+strip = true
+lto = true
+opt-level = 3
+codegen-units = 1
diff --git a/crates/admin/Cargo.toml b/crates/admin/Cargo.toml
new file mode 100644
index 0000000..f65744d
--- /dev/null
+++ b/crates/admin/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "bichon-admin"
+version.workspace = true
+edition.workspace = true
+
+
+[dependencies]
+bichon-core = { path = "../core" }
+tokio.workspace = true
+dialoguer.workspace = true
+console.workspace = true
\ No newline at end of file
diff --git a/src/bin/bichon_admin.rs b/crates/admin/src/main.rs
similarity index 97%
rename from src/bin/bichon_admin.rs
rename to crates/admin/src/main.rs
index 9b0404c..f94146b 100644
--- a/src/bin/bichon_admin.rs
+++ b/crates/admin/src/main.rs
@@ -16,22 +16,19 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
use std::{
fs,
path::{Path, PathBuf},
- rc::Rc,
};
-use bichon::modules::{
- cli::admin::meta::{find_admin, init_meta_database, update_admin_password},
+use bichon_core::{
+ admin::meta::{find_admin, init_meta_database, update_admin_password},
error::BichonError,
utils::encrypt::internal_decrypt_string,
};
use console::{style, Emoji};
use dialoguer::Confirm;
use dialoguer::{theme::ColorfulTheme, Input, Password, Select};
-use native_db::Database;
#[tokio::main]
async fn main() {
@@ -75,7 +72,7 @@ async fn main() {
let root_path = PathBuf::from(&root_dir_str);
- let database: Rc> = match init_meta_database(&root_path.join("meta.db")) {
+ let database = match init_meta_database(&root_path.join("meta.db")) {
Ok(database) => database,
Err(e) => match e {
BichonError::Generic {
diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml
new file mode 100644
index 0000000..7d16cf4
--- /dev/null
+++ b/crates/cli/Cargo.toml
@@ -0,0 +1,24 @@
+[package]
+name = "bichon-cli"
+version.workspace = true
+edition.workspace = true
+
+
+[dependencies]
+bichon-core = { path = "../core" }
+tokio.workspace = true
+serde.workspace = true
+clap.workspace = true
+dialoguer.workspace = true
+console.workspace = true
+mail-parser.workspace = true
+reqwest.workspace = true
+toml = "0.9.8"
+memmap2 = "0.9.10"
+outlook-pst = { git = "https://github.com/rustmailer/outlook-pst-rs.git", branch = "main" }
+compressed-rtf = "1.0.1"
+chrono.workspace = true
+mail-send.workspace = true
+base64.workspace = true
+codepage-strings = "1.0.2"
+hex = "0.4.3"
\ No newline at end of file
diff --git a/src/modules/cli/auth.rs b/crates/cli/src/auth.rs
similarity index 99%
rename from src/modules/cli/auth.rs
rename to crates/cli/src/auth.rs
index 31d592d..3db1afb 100644
--- a/src/modules/cli/auth.rs
+++ b/crates/cli/src/auth.rs
@@ -16,19 +16,19 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
use std::process;
use console::style;
use dialoguer::{theme::ColorfulTheme, Select};
use reqwest::Client;
-use crate::modules::{
+use bichon_core::{
account::payload::MinimalAccount,
- cli::BichonCtlConfig,
users::{permissions::Permission, view::UserView},
};
+use crate::BichonCtlConfig;
+
pub async fn verify_user_and_get_account(config: &BichonCtlConfig, theme: &ColorfulTheme) -> u64 {
let client = Client::new();
let url = format!("{}/api/v1/current-user", config.base_url);
diff --git a/src/modules/cli/eml/mod.rs b/crates/cli/src/eml/mod.rs
similarity index 97%
rename from src/modules/cli/eml/mod.rs
rename to crates/cli/src/eml/mod.rs
index 41a2d68..78667bc 100644
--- a/src/modules/cli/eml/mod.rs
+++ b/crates/cli/src/eml/mod.rs
@@ -16,7 +16,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
use std::{
collections::HashMap,
fs,
@@ -28,10 +27,9 @@ use dialoguer::{theme::ColorfulTheme, Input};
use mail_parser::MessageParser;
use reqwest::Client;
-use crate::{
- base64_encode_url_safe,
- modules::cli::{sender::send_batch_request, BichonCtlConfig},
-};
+use bichon_core::base64_encode_url_safe;
+
+use crate::{sender::send_batch_request, BichonCtlConfig};
pub async fn handle_eml_directory_import(
config: &BichonCtlConfig,
diff --git a/src/bin/bichonctl.rs b/crates/cli/src/main.rs
similarity index 84%
rename from src/bin/bichonctl.rs
rename to crates/cli/src/main.rs
index c9379c9..a558e34 100644
--- a/src/bin/bichonctl.rs
+++ b/crates/cli/src/main.rs
@@ -16,17 +16,51 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
-use bichon::modules::cli::{
- auth::verify_user_and_get_account, eml::handle_eml_directory_import,
- mbox::handle_mbox_single_file_import, pst::handle_pst_import,
- thunderbird::handle_thunderbird_import, BichonCli, BichonCtlConfig,
-};
+use bichon_core::bichon_version;
use clap::Parser;
use console::style;
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select};
+use serde::{Deserialize, Serialize};
use std::fs;
+use crate::{
+ auth::verify_user_and_get_account, eml::handle_eml_directory_import,
+ mbox::handle_mbox_single_file_import, pst::handle_pst_import,
+ thunderbird::handle_thunderbird_import,
+};
+
+pub mod auth;
+pub mod eml;
+pub mod mbox;
+pub mod pst;
+pub mod sender;
+pub mod thunderbird;
+
+#[derive(Parser, Debug)]
+#[command(
+ name = "bichonctl",
+ author = "rustmailer",
+ version = bichon_version!(),
+ about = "A CLI tool to import email data into Bichon service"
+)]
+pub struct BichonCli {
+ /// Path to the configuration file
+ #[arg(
+ short,
+ long,
+ default_value = "config.toml",
+ value_name = "FILE",
+ help = "Sets a custom config file"
+ )]
+ pub config: std::path::PathBuf,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct BichonCtlConfig {
+ pub base_url: String,
+ pub api_token: String,
+}
+
#[tokio::main]
async fn main() {
let cli = BichonCli::parse();
diff --git a/src/modules/cli/mbox/gmail.rs b/crates/cli/src/mbox/gmail.rs
similarity index 100%
rename from src/modules/cli/mbox/gmail.rs
rename to crates/cli/src/mbox/gmail.rs
diff --git a/src/modules/cli/mbox/mod.rs b/crates/cli/src/mbox/mod.rs
similarity index 96%
rename from src/modules/cli/mbox/mod.rs
rename to crates/cli/src/mbox/mod.rs
index 7a6a401..a062a1b 100644
--- a/src/modules/cli/mbox/mod.rs
+++ b/crates/cli/src/mbox/mod.rs
@@ -19,11 +19,11 @@
use std::collections::HashMap;
use std::path::PathBuf;
-use crate::base64_encode_url_safe;
-use crate::modules::cli::mbox::gmail::determine_folder;
-use crate::modules::cli::mbox::reader::MboxFile;
-use crate::modules::cli::sender::send_batch_request;
-use crate::modules::cli::BichonCtlConfig;
+use crate::mbox::gmail::determine_folder;
+use crate::mbox::reader::MboxFile;
+use crate::sender::send_batch_request;
+use crate::BichonCtlConfig;
+use bichon_core::base64_encode_url_safe;
use console::style;
use dialoguer::{theme::ColorfulTheme, Input};
use dialoguer::{Confirm, Select};
diff --git a/src/modules/cli/mbox/reader.rs b/crates/cli/src/mbox/reader.rs
similarity index 98%
rename from src/modules/cli/mbox/reader.rs
rename to crates/cli/src/mbox/reader.rs
index 6146281..b5e2730 100644
--- a/src/modules/cli/mbox/reader.rs
+++ b/crates/cli/src/mbox/reader.rs
@@ -16,7 +16,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
use memmap2::Mmap;
use std::fs;
use std::io;
@@ -130,7 +129,7 @@ impl<'a> Iterator for MboxReader<'a> {
mod tests {
use mail_parser::MessageParser;
- use crate::modules::cli::mbox::gmail::determine_folder;
+ use crate::mbox::gmail::determine_folder;
use super::*;
@@ -221,7 +220,6 @@ mod tests {
labels,
determine_folder(labels)
)
-
}
}
}
diff --git a/src/modules/cli/pst/encoding/mod.rs b/crates/cli/src/pst/encoding/mod.rs
similarity index 100%
rename from src/modules/cli/pst/encoding/mod.rs
rename to crates/cli/src/pst/encoding/mod.rs
diff --git a/src/modules/cli/pst/mod.rs b/crates/cli/src/pst/mod.rs
similarity index 98%
rename from src/modules/cli/pst/mod.rs
rename to crates/cli/src/pst/mod.rs
index 060b596..a0b5917 100644
--- a/src/modules/cli/pst/mod.rs
+++ b/crates/cli/src/pst/mod.rs
@@ -16,7 +16,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
use chrono::{DateTime, TimeZone, Utc};
use dialoguer::theme::ColorfulTheme;
use dialoguer::Input;
@@ -24,10 +23,10 @@ use mail_send::mail_builder::headers::text::Text;
use mail_send::mail_builder::MessageBuilder;
use outlook_pst::ltp::prop_context::PropertyValue;
-use crate::base64_encode_url_safe;
-use crate::modules::cli::pst::encoding::decode_subject;
-use crate::modules::cli::sender::send_batch_request;
-use crate::modules::cli::BichonCtlConfig;
+use crate::BichonCtlConfig;
+use crate::pst::encoding::decode_subject;
+use crate::sender::send_batch_request;
+use bichon_core::base64_encode_url_safe;
use dialoguer::Confirm;
use outlook_pst::messaging::attachment::AttachmentProperties;
use outlook_pst::messaging::folder::Folder;
diff --git a/src/modules/cli/sender.rs b/crates/cli/src/sender.rs
similarity index 96%
rename from src/modules/cli/sender.rs
rename to crates/cli/src/sender.rs
index 4294bda..761631f 100644
--- a/src/modules/cli/sender.rs
+++ b/crates/cli/src/sender.rs
@@ -16,11 +16,12 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
use console::style;
use reqwest::Client;
-use crate::modules::{cli::BichonCtlConfig, import::BatchEmlRequest};
+use bichon_core::import::BatchEmlRequest;
+
+use crate::BichonCtlConfig;
pub async fn send_batch_request(
client: &Client,
diff --git a/src/modules/cli/thunderbird/mod.rs b/crates/cli/src/thunderbird/mod.rs
similarity index 98%
rename from src/modules/cli/thunderbird/mod.rs
rename to crates/cli/src/thunderbird/mod.rs
index 2cc97fd..c82d725 100644
--- a/src/modules/cli/thunderbird/mod.rs
+++ b/crates/cli/src/thunderbird/mod.rs
@@ -16,10 +16,9 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
use std::{collections::HashMap, path::PathBuf};
-use crate::modules::cli::{mbox::run_import, BichonCtlConfig};
+use crate::{mbox::run_import, BichonCtlConfig};
use console::style;
use dialoguer::{theme::ColorfulTheme, Confirm, Input};
diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml
new file mode 100644
index 0000000..64413f9
--- /dev/null
+++ b/crates/core/Cargo.toml
@@ -0,0 +1,67 @@
+[package]
+name = "bichon-core"
+version.workspace = true
+edition.workspace = true
+
+
+[features]
+default = ["web-api"]
+web-api = ["dep:poem-openapi"]
+
+[dependencies]
+poem-openapi = { version = "5.1.16", features = [
+ "openapi-explorer",
+ "rapidoc",
+ "scalar",
+ "redoc",
+ "swagger-ui",
+ "email",
+], optional = true }
+chrono.workspace = true
+clap.workspace = true
+native_db.workspace = true
+itertools.workspace = true
+native_model.workspace = true
+ring.workspace = true
+serde.workspace = true
+serde_json.workspace = true
+tokio.workspace = true
+tracing.workspace = true
+tracing-appender.workspace = true
+tracing-subscriber.workspace = true
+base64.workspace = true
+snafu.workspace = true
+reqwest.workspace = true
+tokio-socks.workspace = true
+regex.workspace = true
+email_address.workspace = true
+futures.workspace = true
+utf7-imap.workspace = true
+mail-parser.workspace = true
+tokio-rustls.workspace = true
+oauth2.workspace = true
+sysinfo.workspace = true
+num_cpus.workspace = true
+rand.workspace = true
+encoding_rs.workspace = true
+async-imap.workspace = true
+webpki-roots.workspace = true
+rustls.workspace = true
+rustls-pki-types.workspace = true
+tokio-io-timeout.workspace = true
+governor.workspace = true
+lru.workspace = true
+time.workspace = true
+murmur3.workspace = true
+autoconfig.workspace = true
+dashmap.workspace = true
+itoa.workspace = true
+html2text.workspace = true
+bytes.workspace = true
+mail-send.workspace = true
+blake3.workspace = true
+uuid.workspace = true
+fjall.workspace = true
+tantivy.workspace = true
+tracing-log.workspace = true
+tokio-util.workspace = true
diff --git a/src/modules/account/entity.rs b/crates/core/src/account/entity.rs
similarity index 82%
rename from src/modules/account/entity.rs
rename to crates/core/src/account/entity.rs
index fa206ef..f29d166 100644
--- a/src/modules/account/entity.rs
+++ b/crates/core/src/account/entity.rs
@@ -16,19 +16,19 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
+use crate::{encrypt, error::BichonResult};
-use crate::{encrypt, modules::error::BichonResult};
-
-use poem_openapi::{Enum, Object};
+//use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
-#[derive(Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct ImapConfig {
/// IMAP server hostname or IP address
- #[oai(validator(max_length = 253, pattern = r"^[a-zA-Z0-9\-\.]+$"))]
+ //#[oai(validator(max_length = 253, pattern = r"^[a-zA-Z0-9\-\.]+$"))]
pub host: String,
/// IMAP server port number
- #[oai(validator(minimum(value = "1"), maximum(value = "65535")))]
+ //#[oai(validator(minimum(value = "1"), maximum(value = "65535")))]
pub port: u16,
/// Connection encryption method
pub encryption: Encryption,
@@ -52,8 +52,8 @@ impl ImapConfig {
}
}
-
-#[derive(Enum, Default, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
+#[derive(Default, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Enum))]
pub enum AuthType {
/// Standard password authentication (PLAIN/LOGIN)
#[default]
@@ -62,7 +62,8 @@ pub enum AuthType {
OAuth2,
}
-#[derive(Object, Default, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
+#[derive(Default, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AuthConfig {
///Authentication method to use
pub auth_type: AuthType,
@@ -70,7 +71,7 @@ pub struct AuthConfig {
///
/// Users should provide a plaintext password (1 to 256 characters).
/// The server will encrypt the password using AES-256-GCM and securely store it.
- #[oai(validator(max_length = 256, min_length = 1))]
+ //#[oai(validator(max_length = 256, min_length = 1))]
pub password: Option,
}
@@ -97,7 +98,8 @@ impl AuthConfig {
}
}
-#[derive(Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize, Enum)]
+#[derive(Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Enum))]
pub enum Encryption {
/// SSL/TLS encrypted connection
#[default]
diff --git a/src/modules/account/grant.rs b/crates/core/src/account/grant.rs
similarity index 98%
rename from src/modules/account/grant.rs
rename to crates/core/src/account/grant.rs
index d0b61e3..d7ad697 100644
--- a/src/modules/account/grant.rs
+++ b/crates/core/src/account/grant.rs
@@ -16,11 +16,12 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
use crate::{
- modules::{
+ raise_error, utc_now,
+ {
account::migration::AccountModel,
common::auth::ClientContext,
database::{manager::DB_MANAGER, with_transaction},
@@ -31,10 +32,10 @@ use crate::{
UserModel,
},
},
- raise_error, utc_now,
};
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct BatchAccountRoleRequest {
pub account_ids: Vec,
pub user_ids: Vec,
diff --git a/src/modules/account/migration.rs b/crates/core/src/account/migration.rs
similarity index 93%
rename from src/modules/account/migration.rs
rename to crates/core/src/account/migration.rs
index ea0ba41..b276ea3 100644
--- a/src/modules/account/migration.rs
+++ b/crates/core/src/account/migration.rs
@@ -18,56 +18,54 @@
use native_db::*;
use native_model::{native_model, Model};
-
-use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
use std::collections::BTreeSet;
use tracing::info;
use crate::{
- encrypt,
- modules::{
- account::{
- entity::ImapConfig,
- since::{DateSince, RelativeDate},
- state::DownloadState,
- },
- cache::imap::mailbox::MailBox,
- database::{list_all_impl, secondary_find_impl, with_transaction},
- error::BichonResult,
- store::tantivy::{attachment::ATTACHMENT_MANAGER, envelope::ENVELOPE_MANAGER},
- users::{role::DEFAULT_ACCOUNT_MANAGER_ROLE_ID, UserModel, DEFAULT_ADMIN_USER_ID},
+ account::{
+ entity::ImapConfig,
+ since::{DateSince, RelativeDate},
+ state::DownloadState,
},
+ cache::imap::mailbox::MailBox,
+ common::paginated::DataPage,
+ database::{list_all_impl, secondary_find_impl, with_transaction},
+ encrypt,
+ error::BichonResult,
+ store::tantivy::{attachment::ATTACHMENT_MANAGER, envelope::ENVELOPE_MANAGER},
+ users::{role::DEFAULT_ACCOUNT_MANAGER_ROLE_ID, UserModel, DEFAULT_ADMIN_USER_ID},
utc_now,
};
-use crate::id;
-use crate::modules::account::payload::AccountCreateRequest;
-use crate::modules::account::payload::AccountUpdateRequest;
-use crate::modules::account::payload::MinimalAccount;
-use crate::modules::cache::imap::task::SYNC_TASKS;
-use crate::modules::context::controller::DOWNLOAD_CONTROLLER;
-use crate::modules::database::count_by_unique_secondary_key_impl;
-use crate::modules::database::delete_impl;
-use crate::modules::database::manager::DB_MANAGER;
-use crate::modules::database::{
+use crate::account::payload::AccountCreateRequest;
+use crate::account::payload::AccountUpdateRequest;
+use crate::account::payload::MinimalAccount;
+use crate::cache::imap::task::SYNC_TASKS;
+use crate::context::controller::DOWNLOAD_CONTROLLER;
+use crate::database::count_by_unique_secondary_key_impl;
+use crate::database::delete_impl;
+use crate::database::manager::DB_MANAGER;
+use crate::database::{
async_secondary_find_impl, paginate_query_primary_scan_all_impl, update_impl,
};
-use crate::modules::error::code::ErrorCode;
-use crate::modules::oauth2::token::OAuth2AccessToken;
-use crate::modules::rest::response::DataPage;
+use crate::error::code::ErrorCode;
+use crate::id;
+use crate::oauth2::token::OAuth2AccessToken;
use crate::raise_error;
pub type AccountModel = AccountV4;
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Enum)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Enum))]
pub enum AccountType {
#[default]
IMAP,
NoSync,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Enum)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Enum))]
pub enum QuotaWindow {
Hourly,
#[default]
@@ -76,7 +74,7 @@ pub enum QuotaWindow {
Monthly,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
#[native_model(id = 4, version = 1)]
#[native_db(primary_key(pk -> String))]
pub struct AccountV1 {
@@ -84,7 +82,7 @@ pub struct AccountV1 {
pub id: u64,
pub imap: Option,
pub enabled: bool,
- #[oai(validator(custom = "crate::modules::common::validator::EmailValidator"))]
+ //#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
pub email: String,
pub name: Option,
pub capabilities: Option>,
@@ -104,7 +102,7 @@ impl AccountV1 {
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
#[native_model(id = 4, version = 2, from = AccountV1)]
#[native_db(primary_key(pk -> String))]
pub struct AccountV2 {
@@ -112,7 +110,7 @@ pub struct AccountV2 {
pub id: u64,
pub imap: Option,
pub enabled: bool,
- #[oai(validator(custom = "crate::modules::common::validator::EmailValidator"))]
+ //#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
pub email: String,
pub name: Option,
pub capabilities: Option>,
@@ -135,7 +133,7 @@ impl AccountV2 {
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
#[native_model(id = 4, version = 3, from = AccountV2)]
#[native_db(primary_key(pk -> String))]
pub struct AccountV3 {
@@ -143,7 +141,7 @@ pub struct AccountV3 {
pub id: u64,
pub imap: Option,
pub enabled: bool,
- #[oai(validator(custom = "crate::modules::common::validator::EmailValidator"))]
+ //#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
pub email: String,
pub name: Option,
pub capabilities: Option>,
@@ -169,7 +167,8 @@ impl AccountV3 {
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
#[native_model(id = 4, version = 4, from = AccountV3)]
#[native_db(primary_key(pk -> String))]
pub struct AccountV4 {
@@ -177,7 +176,7 @@ pub struct AccountV4 {
pub id: u64,
pub imap: Option,
pub enabled: bool,
- #[oai(validator(custom = "crate::modules::common::validator::EmailValidator"))]
+ //#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
pub email: String,
pub account_name: Option,
pub login_name: Option,
diff --git a/src/modules/account/mod.rs b/crates/core/src/account/mod.rs
similarity index 100%
rename from src/modules/account/mod.rs
rename to crates/core/src/account/mod.rs
diff --git a/src/modules/account/old_state.rs b/crates/core/src/account/old_state.rs
similarity index 96%
rename from src/modules/account/old_state.rs
rename to crates/core/src/account/old_state.rs
index fa63f76..9bd5c13 100644
--- a/src/modules/account/old_state.rs
+++ b/crates/core/src/account/old_state.rs
@@ -16,26 +16,18 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-// use crate::{
-// modules::{
-// database::{async_find_impl, delete_impl, manager::DB_MANAGER, update_impl, upsert_impl},
-// error::{code::ErrorCode, BichonResult},
-// },
-// raise_error, utc_now,
-// };
use native_db::*;
use native_model::{native_model, Model};
-use poem_openapi::Object;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct MailboxBatchProgress {
pub total_batches: u32,
pub current_batch: u32,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
#[native_model(id = 2, version = 1)]
#[native_db]
pub struct AccountRunningState {
@@ -51,7 +43,7 @@ pub struct AccountRunningState {
pub initial_sync_failed_time: Option,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct AccountError {
pub error: String,
pub at: i64,
diff --git a/src/modules/account/payload.rs b/crates/core/src/account/payload.rs
similarity index 91%
rename from src/modules/account/payload.rs
rename to crates/core/src/account/payload.rs
index b4ad25c..be1c5ed 100644
--- a/src/modules/account/payload.rs
+++ b/crates/core/src/account/payload.rs
@@ -16,18 +16,18 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::account::entity::ImapConfig;
-use crate::modules::account::migration::{AccountModel, AccountType, QuotaWindow};
-use crate::modules::account::since::{DateSince, RelativeDate};
-use crate::modules::error::code::ErrorCode;
-use crate::modules::error::BichonResult;
+use crate::account::entity::ImapConfig;
+use crate::account::migration::{AccountModel, AccountType, QuotaWindow};
+use crate::account::since::{DateSince, RelativeDate};
+use crate::error::code::ErrorCode;
+use crate::error::BichonResult;
use crate::{raise_error, validate_email};
-use poem_openapi::Object;
use serde::{Deserialize, Serialize};
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AccountCreateRequest {
- #[oai(validator(custom = "crate::modules::common::validator::EmailValidator"))]
+ //#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
pub email: String,
pub login_name: Option,
pub account_name: Option,
@@ -36,11 +36,11 @@ pub struct AccountCreateRequest {
pub date_since: Option,
pub date_before: Option,
pub account_type: AccountType,
- #[oai(validator(minimum(value = "100")))]
+ //#[oai(validator(minimum(value = "100")))]
pub folder_limit: Option,
- #[oai(validator(minimum(value = "10")))]
+ //#[oai(validator(minimum(value = "10")))]
pub download_interval_min: Option,
- #[oai(validator(minimum(value = "10"), maximum(value = "200")))]
+ //#[oai(validator(minimum(value = "10"), maximum(value = "200")))]
pub download_batch_size: Option,
pub use_proxy: Option,
pub use_dangerous: bool,
@@ -107,7 +107,8 @@ impl AccountCreateRequest {
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AccountUpdateRequest {
pub email: Option,
/// Represents the account activation status.
@@ -135,7 +136,7 @@ pub struct AccountUpdateRequest {
/// Max emails to sync for this folder.
/// If not set, sync all emails.
/// otherwise sync up to `n` most recent emails (min 10).
- #[oai(validator(minimum(value = "100")))]
+ //#[oai(validator(minimum(value = "100")))]
pub folder_limit: Option,
pub clear_folder_limit: Option,
/// Configuration for selective folder (mailbox/label) synchronization
@@ -153,9 +154,9 @@ pub struct AccountUpdateRequest {
/// Modified folders will be automatically synced on the next update.
pub sync_folders: Option>,
/// Incremental sync interval (seconds)
- #[oai(validator(minimum(value = "10")))]
+ //#[oai(validator(minimum(value = "10")))]
pub download_interval_min: Option,
- #[oai(validator(minimum(value = "10"), maximum(value = "200")))]
+ //#[oai(validator(minimum(value = "10"), maximum(value = "200")))]
pub download_batch_size: Option,
/// Optional proxy ID for establishing the connection to external APIs (e.g., Gmail, Outlook).
/// - If `None` or not provided, the client will connect directly to the API server.
@@ -225,7 +226,8 @@ impl AccountUpdateRequest {
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct MinimalAccount {
pub id: u64,
diff --git a/src/modules/account/since.rs b/crates/core/src/account/since.rs
similarity index 95%
rename from src/modules/account/since.rs
rename to crates/core/src/account/since.rs
index 9ed5e81..a41366f 100644
--- a/src/modules/account/since.rs
+++ b/crates/core/src/account/since.rs
@@ -17,14 +17,14 @@
// along with this program. If not, see .
use crate::{
- modules::error::{code::ErrorCode, BichonResult},
+ error::{code::ErrorCode, BichonResult},
raise_error,
};
use chrono::{Datelike, Days, Local, Months, NaiveDate, Utc};
-use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct DateSince {
/// Absolute date boundary in ISO 8601 format (YYYY-MM-DD)
///
@@ -38,7 +38,7 @@ pub struct DateSince {
/// "fixed": "2025-05-01"
/// }
/// ```
- #[oai(validator(pattern = r"^\d{4}-\d{2}-\d{2}$"))]
+ //#[oai(validator(pattern = r"^\d{4}-\d{2}-\d{2}$"))]
pub fixed: Option,
/// Relative time period from current date
///
@@ -58,7 +58,8 @@ pub struct DateSince {
pub relative: Option,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Enum)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Enum))]
pub enum Unit {
#[default]
Days,
@@ -66,12 +67,13 @@ pub enum Unit {
Years,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct RelativeDate {
/// The time unit to use for the offset (days, months, or years)
pub unit: Unit,
/// The quantity of time units to offset (must be a positive integer)
- #[oai(validator(minimum(value = "1")))]
+ //#[oai(validator(minimum(value = "1")))]
pub value: u32,
}
@@ -255,7 +257,7 @@ impl DateSince {
#[cfg(test)]
mod test {
- use crate::modules::account::since::{DateSince, RelativeDate, Unit};
+ use crate::account::since::{DateSince, RelativeDate, Unit};
#[test]
fn test1() {
diff --git a/src/modules/account/state.rs b/crates/core/src/account/state.rs
similarity index 95%
rename from src/modules/account/state.rs
rename to crates/core/src/account/state.rs
index 0ff079d..20500ab 100644
--- a/src/modules/account/state.rs
+++ b/crates/core/src/account/state.rs
@@ -17,7 +17,7 @@
// along with this program. If not, see .
use crate::{
- modules::{
+ {
database::{async_find_impl, delete_impl, manager::DB_MANAGER, update_impl, upsert_impl},
error::{code::ErrorCode, BichonResult},
},
@@ -25,11 +25,11 @@ use crate::{
};
use native_db::*;
use native_model::{native_model, Model};
-use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Enum)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Enum))]
pub enum DownloadStatus {
Running,
Success,
@@ -38,14 +38,16 @@ pub enum DownloadStatus {
Cancelled,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Enum)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Enum))]
pub enum TriggerType {
Manual,
#[default]
Scheduled,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Enum)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Enum))]
pub enum FolderStatus {
#[default]
Pending,
@@ -55,7 +57,8 @@ pub enum FolderStatus {
Cancelled,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct FolderProgress {
pub folder_name: String,
pub planned: u64,
@@ -64,7 +67,8 @@ pub struct FolderProgress {
pub message: Option,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct DownloadSession {
pub start_time: i64,
pub end_time: Option,
@@ -76,7 +80,8 @@ pub struct DownloadSession {
pub errors: Vec,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
#[native_model(id = 3, version = 1)]
#[native_db]
pub struct DownloadState {
@@ -89,7 +94,8 @@ pub struct DownloadState {
pub global_errors: Vec,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AccountError {
pub error: String,
pub at: i64,
diff --git a/src/modules/account/view.rs b/crates/core/src/account/view.rs
similarity index 97%
rename from src/modules/account/view.rs
rename to crates/core/src/account/view.rs
index 6cbae1c..b594766 100644
--- a/src/modules/account/view.rs
+++ b/crates/core/src/account/view.rs
@@ -17,11 +17,9 @@
// along with this program. If not, see .
use std::collections::{BTreeSet, HashMap};
-
-use poem_openapi::Object;
use serde::{Deserialize, Serialize};
-use crate::modules::{
+use crate::{
account::{
entity::ImapConfig,
migration::{AccountModel, AccountType, QuotaWindow},
@@ -30,7 +28,8 @@ use crate::modules::{
users::UserModel,
};
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AccountResp {
pub id: u64,
pub imap: Option,
diff --git a/src/modules/cli/admin/meta.rs b/crates/core/src/admin/meta.rs
similarity index 99%
rename from src/modules/cli/admin/meta.rs
rename to crates/core/src/admin/meta.rs
index beea4a5..7ec75e8 100644
--- a/src/modules/cli/admin/meta.rs
+++ b/crates/core/src/admin/meta.rs
@@ -23,7 +23,7 @@ use std::{path::Path, rc::Rc};
use native_db::{Builder, Database};
use crate::{
- modules::{
+ {
database::META_MODELS,
error::{code::ErrorCode, BichonResult},
token::{AccessTokenModel, AccessTokenModelKey, TokenType},
diff --git a/src/modules/cli/admin/mod.rs b/crates/core/src/admin/mod.rs
similarity index 100%
rename from src/modules/cli/admin/mod.rs
rename to crates/core/src/admin/mod.rs
diff --git a/src/modules/autoconfig/entity.rs b/crates/core/src/autoconfig/entity.rs
similarity index 90%
rename from src/modules/autoconfig/entity.rs
rename to crates/core/src/autoconfig/entity.rs
index d4d28d4..af053e2 100644
--- a/src/modules/autoconfig/entity.rs
+++ b/crates/core/src/autoconfig/entity.rs
@@ -18,12 +18,12 @@
use autoconfig::config::OAuth2Config as XOAuth2Config;
-use poem_openapi::Object;
use serde::{Deserialize, Serialize};
-use crate::modules::account::entity::Encryption;
+use crate::account::entity::Encryption;
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct ServerConfig {
/// server hostname or IP address
pub host: String,
@@ -43,7 +43,8 @@ impl ServerConfig {
}
}
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct OAuth2Config {
/// The authorization server's issuer identifier URL
pub issuer: String,
@@ -66,7 +67,8 @@ impl From<&XOAuth2Config> for OAuth2Config {
}
}
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct MailServerConfig {
/// IMAP server configuration
pub imap: ServerConfig,
diff --git a/src/modules/autoconfig/load.rs b/crates/core/src/autoconfig/load.rs
similarity index 96%
rename from src/modules/autoconfig/load.rs
rename to crates/core/src/autoconfig/load.rs
index 24c063b..56cba84 100644
--- a/src/modules/autoconfig/load.rs
+++ b/crates/core/src/autoconfig/load.rs
@@ -17,10 +17,10 @@
// along with this program. If not, see .
-use crate::modules::autoconfig::entity::{MailServerConfig, ServerConfig};
-use crate::modules::error::code::ErrorCode;
+use crate::autoconfig::entity::{MailServerConfig, ServerConfig};
+use crate::error::code::ErrorCode;
use crate::{
- modules::{
+ {
account::entity::Encryption, autoconfig::CachedMailSettings, error::BichonResult,
},
raise_error,
diff --git a/src/modules/autoconfig/mod.rs b/crates/core/src/autoconfig/mod.rs
similarity index 90%
rename from src/modules/autoconfig/mod.rs
rename to crates/core/src/autoconfig/mod.rs
index 4fd7b13..8473f21 100644
--- a/src/modules/autoconfig/mod.rs
+++ b/crates/core/src/autoconfig/mod.rs
@@ -17,12 +17,12 @@
// along with this program. If not, see .
-use crate::modules::database::manager::DB_MANAGER;
-use crate::modules::database::{delete_impl, async_find_impl, upsert_impl};
-use crate::modules::error::code::ErrorCode;
+use crate::database::manager::DB_MANAGER;
+use crate::database::{delete_impl, async_find_impl, upsert_impl};
+use crate::error::code::ErrorCode;
use crate::raise_error;
use crate::{
- modules::autoconfig::entity::MailServerConfig, modules::error::BichonResult, utc_now,
+ autoconfig::entity::MailServerConfig, error::BichonResult, utc_now,
};
use native_db::*;
use native_model::{native_model, Model};
diff --git a/src/modules/autoconfig/tests.rs b/crates/core/src/autoconfig/tests.rs
similarity index 100%
rename from src/modules/autoconfig/tests.rs
rename to crates/core/src/autoconfig/tests.rs
diff --git a/src/modules/cache/imap/download/download_folders.rs b/crates/core/src/cache/imap/download/download_folders.rs
similarity index 99%
rename from src/modules/cache/imap/download/download_folders.rs
rename to crates/core/src/cache/imap/download/download_folders.rs
index b41f7f4..c6c1eaf 100644
--- a/src/modules/cache/imap/download/download_folders.rs
+++ b/crates/core/src/cache/imap/download/download_folders.rs
@@ -20,7 +20,7 @@ use std::collections::BTreeSet;
use crate::{
decode_mailbox_name,
- modules::{
+ {
account::migration::{AccountModel, AccountType},
cache::imap::mailbox::{AttributeEnum, MailBox},
error::{code::ErrorCode, BichonResult},
diff --git a/src/modules/cache/imap/download/download_type.rs b/crates/core/src/cache/imap/download/download_type.rs
similarity index 99%
rename from src/modules/cache/imap/download/download_type.rs
rename to crates/core/src/cache/imap/download/download_type.rs
index 83200c2..346413e 100644
--- a/src/modules/cache/imap/download/download_type.rs
+++ b/crates/core/src/cache/imap/download/download_type.rs
@@ -17,7 +17,7 @@
// along with this program. If not, see .
use crate::{
- modules::{
+ {
account::{
migration::AccountModel,
state::{DownloadState, TriggerType},
diff --git a/src/modules/cache/imap/download/flow.rs b/crates/core/src/cache/imap/download/flow.rs
similarity index 99%
rename from src/modules/cache/imap/download/flow.rs
rename to crates/core/src/cache/imap/download/flow.rs
index 8a2500f..b0f2a7d 100644
--- a/src/modules/cache/imap/download/flow.rs
+++ b/crates/core/src/cache/imap/download/flow.rs
@@ -17,7 +17,7 @@
// along with this program. If not, see .
use crate::{
- modules::{
+ {
account::{
migration::AccountModel,
state::{DownloadState, DownloadStatus, FolderStatus},
diff --git a/src/modules/cache/imap/download/mod.rs b/crates/core/src/cache/imap/download/mod.rs
similarity index 99%
rename from src/modules/cache/imap/download/mod.rs
rename to crates/core/src/cache/imap/download/mod.rs
index 5482336..0cfe354 100644
--- a/src/modules/cache/imap/download/mod.rs
+++ b/crates/core/src/cache/imap/download/mod.rs
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::{
+use crate::{
account::{
migration::{AccountModel, AccountType},
state::{DownloadState, DownloadStatus},
diff --git a/src/modules/cache/imap/download/rebuild.rs b/crates/core/src/cache/imap/download/rebuild.rs
similarity index 99%
rename from src/modules/cache/imap/download/rebuild.rs
rename to crates/core/src/cache/imap/download/rebuild.rs
index 95f39e4..c4042ae 100644
--- a/src/modules/cache/imap/download/rebuild.rs
+++ b/crates/core/src/cache/imap/download/rebuild.rs
@@ -17,7 +17,7 @@
// along with this program. If not, see .
use crate::{
- modules::{
+ {
account::{
migration::AccountModel,
state::{DownloadState, DownloadStatus, FolderStatus},
diff --git a/src/modules/cache/imap/mailbox.rs b/crates/core/src/cache/imap/mailbox.rs
similarity index 96%
rename from src/modules/cache/imap/mailbox.rs
rename to crates/core/src/cache/imap/mailbox.rs
index 4ff48d7..d8f320f 100644
--- a/src/modules/cache/imap/mailbox.rs
+++ b/crates/core/src/cache/imap/mailbox.rs
@@ -18,7 +18,7 @@
use crate::{
decode_mailbox_name, encode_mailbox_name,
- modules::{
+ {
database::{
async_filter_by_secondary_key_impl, async_find_impl, batch_delete_impl,
batch_insert_impl, batch_upsert_impl, delete_impl, filter_by_secondary_key_impl,
@@ -32,10 +32,10 @@ use async_imap::types::{Name, NameAttribute};
use itertools::Itertools;
use native_db::*;
use native_model::{native_model, Model};
-use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
#[native_model(id = 1, version = 1)]
#[native_db]
pub struct MailBox {
@@ -145,7 +145,8 @@ impl MailBox {
}
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct Attribute {
pub attr: AttributeEnum,
pub extension: Option,
@@ -157,7 +158,8 @@ impl Attribute {
}
}
-#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize, Enum)]
+#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Enum))]
pub enum AttributeEnum {
NoInferiors,
NoSelect,
diff --git a/src/modules/cache/imap/mod.rs b/crates/core/src/cache/imap/mod.rs
similarity index 86%
rename from src/modules/cache/imap/mod.rs
rename to crates/core/src/cache/imap/mod.rs
index 41624bc..8ff116c 100644
--- a/src/modules/cache/imap/mod.rs
+++ b/crates/core/src/cache/imap/mod.rs
@@ -16,18 +16,20 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use std::sync::LazyLock;
+use std::{
+ collections::{HashMap, HashSet},
+ sync::LazyLock,
+};
-use crate::modules::{
- account::{state::DownloadState, old_state::AccountRunningState},
+use crate::{
+ account::{old_state::AccountRunningState, state::DownloadState},
database::ModelsAdapter,
};
-use ahash::{AHashMap, AHashSet};
use mailbox::MailBox;
use native_db::Models;
-pub mod mailbox;
pub mod download;
+pub mod mailbox;
pub mod task;
pub static MAILBOX_MODELS: LazyLock = LazyLock::new(|| {
@@ -42,7 +44,7 @@ pub fn find_missing_mailboxes(
local_mailboxes: &[MailBox],
server_mailboxes: &[MailBox],
) -> Vec {
- let local_names: AHashSet<_> = local_mailboxes.iter().map(|m| &m.name).collect();
+ let local_names: HashSet<_> = local_mailboxes.iter().map(|m| &m.name).collect();
server_mailboxes
.iter()
.filter(|m| !local_names.contains(&m.name))
@@ -54,7 +56,7 @@ pub fn find_intersecting_mailboxes(
local_mailboxes: &[MailBox],
remote_mailboxes: &[MailBox],
) -> Vec<(MailBox, MailBox)> {
- let local_map: AHashMap<_, _> = local_mailboxes
+ let local_map: HashMap<_, _> = local_mailboxes
.iter()
.map(|m| (m.name.clone(), m.clone()))
.collect();
diff --git a/src/modules/cache/imap/task.rs b/crates/core/src/cache/imap/task.rs
similarity index 94%
rename from src/modules/cache/imap/task.rs
rename to crates/core/src/cache/imap/task.rs
index c9f450d..0c331ed 100644
--- a/src/modules/cache/imap/task.rs
+++ b/crates/core/src/cache/imap/task.rs
@@ -16,12 +16,12 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::account::entity::AuthType;
-use crate::modules::account::state::DownloadState;
-use crate::modules::cache::imap::download::process_imap_download;
-use crate::modules::common::periodic::{PeriodicTask, TaskHandle};
-use crate::modules::oauth2::token::OAuth2AccessToken;
-use crate::modules::{account::migration::AccountModel, error::BichonResult};
+use crate::account::entity::AuthType;
+use crate::account::state::DownloadState;
+use crate::cache::imap::download::process_imap_download;
+use crate::common::periodic::{PeriodicTask, TaskHandle};
+use crate::oauth2::token::OAuth2AccessToken;
+use crate::{account::migration::AccountModel, error::BichonResult};
use crate::utc_now;
use std::collections::HashMap;
use std::sync::atomic::{AtomicI64, Ordering};
diff --git a/src/modules/cache/mod.rs b/crates/core/src/cache/mod.rs
similarity index 96%
rename from src/modules/cache/mod.rs
rename to crates/core/src/cache/mod.rs
index c151ff1..599ec46 100644
--- a/src/modules/cache/mod.rs
+++ b/crates/core/src/cache/mod.rs
@@ -17,7 +17,7 @@
// along with this program. If not, see .
-use crate::modules::settings::cli::SETTINGS;
+use crate::settings::cli::SETTINGS;
use std::sync::{Arc, LazyLock};
use tokio::sync::Semaphore;
diff --git a/crates/core/src/common/auth.rs b/crates/core/src/common/auth.rs
new file mode 100644
index 0000000..61b631f
--- /dev/null
+++ b/crates/core/src/common/auth.rs
@@ -0,0 +1,143 @@
+use std::{
+ collections::{BTreeSet, HashSet},
+ net::IpAddr,
+};
+
+use crate::{
+ error::{code::ErrorCode, BichonResult},
+ raise_error,
+ users::{permissions::Permission, role::UserRole, UserModel},
+};
+
+#[derive(Clone, Debug)]
+pub struct ClientContext {
+ pub ip_addr: Option,
+ pub user: UserModel,
+}
+
+impl ClientContext {
+ pub async fn require_any_permission(
+ &self,
+ requirements: Vec<(Option, &str)>,
+ ) -> BichonResult<()> {
+ for (account_id, permission) in requirements {
+ if self.has_permission(account_id, permission).await {
+ return Ok(());
+ }
+ }
+ Err(raise_error!(
+ "Access denied: Insufficient permissions to perform this action.".into(),
+ ErrorCode::Forbidden
+ ))
+ }
+
+ pub async fn check_has_permission(
+ user: &UserModel,
+ account_id: Option,
+ permission: &str,
+ ) -> bool {
+ if user.is_admin().await {
+ return true;
+ }
+
+ let mut global_perms = HashSet::new();
+ for rid in &user.global_roles {
+ if let Some(role) = UserRole::find(*rid).await.ok().flatten() {
+ global_perms.extend(role.permissions);
+ }
+ }
+
+ if Self::check_global_logic(&global_perms, permission) {
+ return true;
+ }
+
+ if let Some(aid) = account_id {
+ if let Some(role_id) = user.account_access_map.get(&aid) {
+ if let Some(role) = UserRole::find(*role_id).await.ok().flatten() {
+ if role.permissions.contains(&permission.to_string())
+ || Self::check_account_logic(&role.permissions, permission)
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ false
+ }
+
+ pub async fn has_permission(&self, account_id: Option, permission: &str) -> bool {
+ if self.user.is_admin().await {
+ return true;
+ }
+
+ let mut global_perms = HashSet::new();
+ for rid in &self.user.global_roles {
+ if let Some(role) = UserRole::find(*rid).await.ok().flatten() {
+ global_perms.extend(role.permissions);
+ }
+ }
+
+ if Self::check_global_logic(&global_perms, permission) {
+ return true;
+ }
+
+ if let Some(aid) = account_id {
+ if let Some(role_id) = self.user.account_access_map.get(&aid) {
+ if let Some(role) = UserRole::find(*role_id).await.ok().flatten() {
+ if role.permissions.contains(&permission.to_string())
+ || Self::check_account_logic(&role.permissions, permission)
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ false
+ }
+
+ fn check_global_logic(global: &HashSet, perm: &str) -> bool {
+ if global.contains(perm) {
+ return true;
+ }
+
+ match perm {
+ Permission::DATA_READ => global.contains(Permission::DATA_READ_ALL),
+ Permission::DATA_DELETE => global.contains(Permission::DATA_DELETE_ALL),
+ Permission::DATA_RAW_DOWNLOAD => global.contains(Permission::DATA_RAW_DOWNLOAD_ALL),
+ Permission::DATA_EXPORT_BATCH => global.contains(Permission::DATA_EXPORT_BATCH_ALL),
+ Permission::ACCOUNT_MANAGE | Permission::ACCOUNT_READ_DETAILS => {
+ global.contains(Permission::ACCOUNT_MANAGE_ALL)
+ }
+ _ => false,
+ }
+ }
+
+ fn check_account_logic(scoped_perms: &BTreeSet, perm: &str) -> bool {
+ if scoped_perms.contains(perm) {
+ return true;
+ }
+ match perm {
+ Permission::DATA_READ | Permission::ACCOUNT_READ_DETAILS => {
+ scoped_perms.contains(Permission::ACCOUNT_MANAGE)
+ }
+ _ => false,
+ }
+ }
+
+ pub async fn require_permission(
+ &self,
+ account_id: Option,
+ permission: &str,
+ ) -> BichonResult<()> {
+ if self.has_permission(account_id, permission).await {
+ Ok(())
+ } else {
+ Err(raise_error!(
+ format!("Access Denied: Missing permission '{}'", permission),
+ ErrorCode::Forbidden
+ ))
+ }
+ }
+}
diff --git a/src/modules/common/mod.rs b/crates/core/src/common/mod.rs
similarity index 60%
rename from src/modules/common/mod.rs
rename to crates/core/src/common/mod.rs
index 8b8e8f8..7545de7 100644
--- a/src/modules/common/mod.rs
+++ b/crates/core/src/common/mod.rs
@@ -16,29 +16,17 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use super::error::code::ErrorCode;
-use super::error::BichonError;
-use mail_parser::{Addr as ImapAddr, Address as ImapAddress};
-use poem::error::ResponseError;
-use poem::Body;
-use poem::{http::StatusCode, Error, Response};
-use poem_openapi::Object;
-use serde::{Deserialize, Serialize};
use std::ops::Deref;
-use tracing::error;
+use mail_parser::{Addr as ImapAddr, Address as ImapAddress};
+use serde::{Deserialize, Serialize};
pub mod auth;
-pub mod error;
-pub mod log;
pub mod paginated;
pub mod periodic;
pub mod rustls;
pub mod signal;
-pub mod timeout;
-pub mod tls;
-pub mod validator;
-#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Object)]
+#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct Addr {
/// The optional display name associated with the email address (e.g., "John Doe").
/// If `None`, no display name is specified.
@@ -91,57 +79,3 @@ impl<'x> From<&ImapAddress<'x>> for AddrVec {
AddrVec(vec)
}
}
-
-#[inline]
-fn create_rust_mailer_error(message: &str, code: ErrorCode) -> BichonError {
- BichonError::Generic {
- message: message.into(),
- location: snafu::location!(),
- code,
- }
-}
-
-#[inline]
-pub fn create_api_error_response(message: &str, code: ErrorCode) -> Error {
- let rust_mailer_error = create_rust_mailer_error(message, code);
- rust_mailer_error.into()
-}
-
-impl ResponseError for BichonError {
- fn status(&self) -> StatusCode {
- match self {
- BichonError::Generic {
- message: _,
- location: _,
- code,
- } => code.status(),
- }
- }
-
- fn as_response(&self) -> Response
- where
- Self: std::error::Error + Send + Sync + 'static,
- {
- match self {
- BichonError::Generic {
- message,
- location,
- code,
- } => {
- error!(
- error_code = *code as u32,
- error_message = %message,
- error_location = ?location
- );
-
- let body = Body::from_json(serde_json::json!({
- "code": *code as u32,
- "message": message.to_string(),
- }))
- .unwrap();
-
- Response::builder().status(self.status()).body(body)
- }
- }
- }
-}
diff --git a/crates/core/src/common/paginated.rs b/crates/core/src/common/paginated.rs
new file mode 100644
index 0000000..2f67e7f
--- /dev/null
+++ b/crates/core/src/common/paginated.rs
@@ -0,0 +1,180 @@
+//
+// Copyright (c) 2025-2026 rustmailer.com (https://rustmailer.com)
+//
+// This file is part of the Bichon Email Archiving Project
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use crate::{
+ error::{code::ErrorCode, BichonResult},
+ raise_error,
+};
+use serde::{Deserialize, Serialize};
+use std::cmp::min;
+
+pub fn paginate_vec(
+ items: &Vec,
+ page: Option,
+ page_size: Option,
+) -> BichonResult> {
+ let total_items = items.len() as u64;
+
+ let (offset, total_pages) = match (page, page_size) {
+ (Some(p), Some(s)) if p > 0 && s > 0 => {
+ let offset = (p - 1) * s;
+ let total_pages = if total_items > 0 {
+ (total_items + s - 1) / s
+ } else {
+ 0
+ };
+ (Some(offset), Some(total_pages))
+ }
+ (Some(0), _) | (_, Some(0)) => {
+ return Err(raise_error!(
+ "'page' and 'page_size' must be greater than 0.".into(),
+ ErrorCode::InvalidParameter
+ ));
+ }
+ _ => (None, None),
+ };
+
+ let data = match offset {
+ Some(offset) if offset >= total_items => vec![],
+ Some(offset) => {
+ let end = min(offset + page_size.unwrap_or(total_items), total_items) as usize;
+ items[offset as usize..end].to_vec()
+ }
+ None => items.clone(),
+ };
+
+ Ok(Paginated::new(
+ page,
+ page_size,
+ total_items,
+ total_pages,
+ data,
+ ))
+}
+
+
+#[cfg(not(feature = "web-api"))]
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
+pub struct DataPage
+where
+ S: Serialize + std::fmt::Debug + std::marker::Unpin + Send + Sync,
+{
+ /// The current page number (starting from 1).
+ pub current_page: Option,
+ /// The number of items per page.
+ pub page_size: Option,
+ /// The total number of items across all pages.
+ pub total_items: u64,
+ /// The list of items returned on the current page.
+ pub items: Vec,
+ /// The total number of pages. This is optional and may not be set if not calculated.
+ pub total_pages: Option,
+}
+#[cfg(not(feature = "web-api"))]
+impl From>
+ for DataPage
+{
+ fn from(paginated: Paginated) -> Self {
+ DataPage {
+ current_page: paginated.page,
+ page_size: paginated.page_size,
+ total_items: paginated.total_items,
+ total_pages: paginated.total_pages,
+ items: paginated.items,
+ }
+ }
+}
+
+
+
+
+#[cfg(feature = "web-api")]
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, poem_openapi::Object)]
+pub struct DataPage
+where
+ S: Serialize
+ + std::fmt::Debug
+ + std::marker::Unpin
+ + Send
+ + Sync
+ + poem_openapi::types::Type
+ + poem_openapi::types::ParseFromJSON
+ + poem_openapi::types::ToJSON,
+{
+ /// The current page number (starting from 1).
+ pub current_page: Option,
+ /// The number of items per page.
+ pub page_size: Option,
+ /// The total number of items across all pages.
+ pub total_items: u64,
+ /// The list of items returned on the current page.
+ pub items: Vec,
+ /// The total number of pages. This is optional and may not be set if not calculated.
+ pub total_pages: Option,
+}
+
+#[cfg(feature = "web-api")]
+impl<
+ S: Serialize
+ + std::fmt::Debug
+ + std::marker::Unpin
+ + Send
+ + Sync
+ + poem_openapi::types::Type
+ + poem_openapi::types::ParseFromJSON
+ + poem_openapi::types::ToJSON,
+ > From> for DataPage
+{
+ fn from(paginated: Paginated) -> Self {
+ DataPage {
+ current_page: paginated.page,
+ page_size: paginated.page_size,
+ total_items: paginated.total_items,
+ total_pages: paginated.total_pages,
+ items: paginated.items,
+ }
+ }
+}
+
+
+#[derive(Debug)]
+pub struct Paginated {
+ pub page: Option,
+ pub page_size: Option,
+ pub total_items: u64,
+ pub total_pages: Option,
+ pub items: Vec,
+}
+
+impl Paginated {
+ pub fn new(
+ page: Option,
+ page_size: Option,
+ total_items: u64,
+ total_pages: Option,
+ items: Vec,
+ ) -> Self {
+ Paginated {
+ page,
+ page_size,
+ total_items,
+ total_pages,
+ items,
+ }
+ }
+}
diff --git a/src/modules/common/periodic.rs b/crates/core/src/common/periodic.rs
similarity index 98%
rename from src/modules/common/periodic.rs
rename to crates/core/src/common/periodic.rs
index 0009922..b36c2ab 100644
--- a/src/modules/common/periodic.rs
+++ b/crates/core/src/common/periodic.rs
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::{common::signal::SIGNAL_MANAGER, error::BichonResult};
+use crate::{common::signal::SIGNAL_MANAGER, error::BichonResult};
use std::{future::Future, time::Duration};
use tokio::{sync::oneshot, task::JoinHandle, time::MissedTickBehavior};
use tracing::{info, warn};
diff --git a/src/modules/common/rustls.rs b/crates/core/src/common/rustls.rs
similarity index 98%
rename from src/modules/common/rustls.rs
rename to crates/core/src/common/rustls.rs
index 7fd75a2..9ad860e 100644
--- a/src/modules/common/rustls.rs
+++ b/crates/core/src/common/rustls.rs
@@ -17,7 +17,7 @@
// along with this program. If not, see .
use crate::{
- modules::{
+ {
context::Initialize,
error::{code::ErrorCode, BichonResult},
},
diff --git a/src/modules/common/signal.rs b/crates/core/src/common/signal.rs
similarity index 94%
rename from src/modules/common/signal.rs
rename to crates/core/src/common/signal.rs
index 25abe57..2deb0ce 100644
--- a/src/modules/common/signal.rs
+++ b/crates/core/src/common/signal.rs
@@ -18,7 +18,7 @@
use std::sync::LazyLock;
-use crate::modules::{context::Initialize, error::BichonResult, utils::shutdown::shutdown_signal};
+use crate::{context::Initialize, error::BichonResult, utils::shutdown::shutdown_signal};
use tokio::sync::broadcast;
pub static SIGNAL_MANAGER: LazyLock = LazyLock::new(SignalManager::new);
diff --git a/src/modules/context/controller.rs b/crates/core/src/context/controller.rs
similarity index 97%
rename from src/modules/context/controller.rs
rename to crates/core/src/context/controller.rs
index eacd501..f63e531 100644
--- a/src/modules/context/controller.rs
+++ b/crates/core/src/context/controller.rs
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::{cache::imap::task::SYNC_TASKS, error::BichonResult};
+use crate::{cache::imap::task::SYNC_TASKS, error::BichonResult};
use std::{sync::LazyLock, time::Duration};
use tokio::sync::mpsc;
use tracing::{error, info};
diff --git a/src/modules/context/executors.rs b/crates/core/src/context/executors.rs
similarity index 95%
rename from src/modules/context/executors.rs
rename to crates/core/src/context/executors.rs
index 23624f0..aad48e2 100644
--- a/src/modules/context/executors.rs
+++ b/crates/core/src/context/executors.rs
@@ -16,10 +16,10 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::account::migration::AccountType;
-use crate::modules::context::Initialize;
+use crate::account::migration::AccountType;
+use crate::context::Initialize;
use crate::{
- modules::{
+ {
account::migration::AccountModel, context::controller::DOWNLOAD_CONTROLLER, error::BichonResult,
},
utc_now,
diff --git a/src/modules/context/mod.rs b/crates/core/src/context/mod.rs
similarity index 91%
rename from src/modules/context/mod.rs
rename to crates/core/src/context/mod.rs
index 7a81019..b053525 100644
--- a/src/modules/context/mod.rs
+++ b/crates/core/src/context/mod.rs
@@ -16,11 +16,10 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::{common::periodic::TaskHandle, error::BichonResult};
+use crate::{common::periodic::TaskHandle, error::BichonResult};
pub mod controller;
pub mod executors;
-pub mod status;
#[allow(async_fn_in_trait)]
pub trait Initialize {
diff --git a/src/modules/dashboard/mod.rs b/crates/core/src/dashboard/mod.rs
similarity index 95%
rename from src/modules/dashboard/mod.rs
rename to crates/core/src/dashboard/mod.rs
index 4903e0b..bf92970 100644
--- a/src/modules/dashboard/mod.rs
+++ b/crates/core/src/dashboard/mod.rs
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::{
+use crate::{
store::tantivy::{
attachment::ATTACHMENT_MANAGER,
envelope::ENVELOPE_MANAGER,
@@ -25,24 +25,24 @@ use crate::modules::{
},
users::permissions::Permission,
};
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use tantivy::{schema::Value, TantivyDocument};
use crate::{
- bichon_version,
- modules::{
+ bichon_version, raise_error,
+ {
account::migration::AccountModel,
common::auth::ClientContext,
error::{code::ErrorCode, BichonResult},
settings::dir::DATA_DIR_MANAGER,
utils::get_total_size,
},
- raise_error,
};
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct DashboardStats {
pub account_count: usize, // Number of accounts
pub email_count: u64, // Total number of emails
@@ -57,7 +57,6 @@ pub struct DashboardStats {
pub top_largest_emails: Vec, // Top 10 largest emails
pub top_largest_attachments: Vec, // Top 10 largest attachments
pub system_version: String, // The semantic version string of the currently running backend service
- pub commit_hash: String, // Git commit hash used to build this system version
}
impl DashboardStats {
@@ -103,25 +102,27 @@ impl DashboardStats {
}
stat.system_version = bichon_version!().to_string();
- stat.commit_hash = env!("GIT_HASH").to_string();
Ok(stat)
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct TimeBucket {
pub timestamp_ms: i64, // Timestamp in milliseconds
pub count: u64, // Number of emails in this time bucket
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct Group {
pub key: String,
pub count: u64, // Number of emails from this sender
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct LargestEmail {
pub subject: String, // Email subject
pub size_bytes: u64, // Email size in bytes
@@ -173,7 +174,8 @@ impl LargestEmail {
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct LargestAttachment {
pub name: String, // Attachment name
pub size_bytes: u64, // Attachment size in bytes
diff --git a/src/modules/database/manager.rs b/crates/core/src/database/manager.rs
similarity index 91%
rename from src/modules/database/manager.rs
rename to crates/core/src/database/manager.rs
index f4b7fc1..1925ae9 100644
--- a/src/modules/database/manager.rs
+++ b/crates/core/src/database/manager.rs
@@ -16,13 +16,13 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::account::migration::AccountModel;
-use crate::modules::cache::imap::MAILBOX_MODELS;
-use crate::modules::error::{code::ErrorCode, BichonError};
-use crate::modules::settings::cli::SETTINGS;
-use crate::modules::settings::dir::DATA_DIR_MANAGER;
-use crate::modules::users::UserModel;
-use crate::modules::{database::META_MODELS, error::BichonResult};
+use crate::account::migration::AccountModel;
+use crate::cache::imap::MAILBOX_MODELS;
+use crate::error::{code::ErrorCode, BichonError};
+use crate::settings::cli::SETTINGS;
+use crate::settings::dir::DATA_DIR_MANAGER;
+use crate::users::UserModel;
+use crate::{database::META_MODELS, error::BichonResult};
use crate::raise_error;
use native_db::{Builder, Database};
use std::sync::{Arc, LazyLock};
diff --git a/src/modules/database/mod.rs b/crates/core/src/database/mod.rs
similarity index 94%
rename from src/modules/database/mod.rs
rename to crates/core/src/database/mod.rs
index 12b3b10..12fb264 100644
--- a/src/modules/database/mod.rs
+++ b/crates/core/src/database/mod.rs
@@ -16,18 +16,19 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::account::migration::{AccountV1, AccountV2, AccountV3, AccountV4};
-use crate::modules::autoconfig::CachedMailSettings;
-use crate::modules::error::code::ErrorCode;
-use crate::modules::error::BichonResult;
-use crate::modules::oauth2::entity::OAuth2;
-use crate::modules::oauth2::pending::OAuth2PendingEntity;
-use crate::modules::oauth2::token::OAuth2AccessToken;
-use crate::modules::settings::proxy::Proxy;
-use crate::modules::settings::system::SystemSetting;
-use crate::modules::token::AccessTokenModel;
-use crate::modules::users::role::UserRole;
-use crate::modules::users::{BichonUser, BichonUserV2};
+use crate::account::migration::{AccountV1, AccountV2, AccountV3, AccountV4};
+use crate::autoconfig::CachedMailSettings;
+use crate::common::paginated::Paginated;
+use crate::error::code::ErrorCode;
+use crate::error::BichonResult;
+use crate::oauth2::entity::OAuth2;
+use crate::oauth2::pending::OAuth2PendingEntity;
+use crate::oauth2::token::OAuth2AccessToken;
+use crate::settings::proxy::Proxy;
+use crate::settings::system::SystemSetting;
+use crate::token::AccessTokenModel;
+use crate::users::role::UserRole;
+use crate::users::{BichonUser, BichonUserV2};
use crate::raise_error;
use db_type::{KeyOptions, ToKeyDefinition};
use itertools::Itertools;
@@ -503,30 +504,3 @@ pub fn secondary_find_impl(
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::InternalError))?;
Ok(entities)
}
-
-#[derive(Debug)]
-pub struct Paginated {
- pub page: Option,
- pub page_size: Option,
- pub total_items: u64,
- pub total_pages: Option,
- pub items: Vec,
-}
-
-impl Paginated {
- pub fn new(
- page: Option,
- page_size: Option,
- total_items: u64,
- total_pages: Option,
- items: Vec,
- ) -> Self {
- Paginated {
- page,
- page_size,
- total_items,
- total_pages,
- items,
- }
- }
-}
diff --git a/src/modules/envelope/extractor.rs b/crates/core/src/envelope/extractor.rs
similarity index 96%
rename from src/modules/envelope/extractor.rs
rename to crates/core/src/envelope/extractor.rs
index 3ad42ca..b28ee4c 100644
--- a/src/modules/envelope/extractor.rs
+++ b/crates/core/src/envelope/extractor.rs
@@ -16,18 +16,18 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::common::AddrVec;
-use crate::modules::envelope::utils::normalize_subject;
-use crate::modules::error::code::ErrorCode;
-use crate::modules::error::BichonResult;
-use crate::modules::message::content::AttachmentInfo;
-use crate::modules::store::storage::{DetachedEmail, BLOB_MANAGER};
-use crate::modules::store::tantivy::attachment::ATTACHMENT_MANAGER;
-use crate::modules::store::tantivy::envelope::ENVELOPE_MANAGER;
-use crate::modules::store::tantivy::model::{AttachmentModel, EnvelopeWithAttachments};
-use crate::modules::utils::html::extract_text;
-use crate::modules::utils::{compute_content_hash, hex_hash};
-use crate::{id, modules::store::envelope::Envelope};
+use crate::common::AddrVec;
+use crate::envelope::utils::normalize_subject;
+use crate::error::code::ErrorCode;
+use crate::error::BichonResult;
+use crate::message::content::AttachmentInfo;
+use crate::store::storage::{DetachedEmail, BLOB_MANAGER};
+use crate::store::tantivy::attachment::ATTACHMENT_MANAGER;
+use crate::store::tantivy::envelope::ENVELOPE_MANAGER;
+use crate::store::tantivy::model::{AttachmentModel, EnvelopeWithAttachments};
+use crate::utils::html::extract_text;
+use crate::utils::{compute_content_hash, hex_hash};
+use crate::{id, store::envelope::Envelope};
use crate::{raise_error, utc_now};
use async_imap::types::Fetch;
use bytes::Bytes;
diff --git a/src/modules/envelope/mod.rs b/crates/core/src/envelope/mod.rs
similarity index 100%
rename from src/modules/envelope/mod.rs
rename to crates/core/src/envelope/mod.rs
diff --git a/src/modules/envelope/utils.rs b/crates/core/src/envelope/utils.rs
similarity index 98%
rename from src/modules/envelope/utils.rs
rename to crates/core/src/envelope/utils.rs
index ffa0ff3..4623d14 100644
--- a/src/modules/envelope/utils.rs
+++ b/crates/core/src/envelope/utils.rs
@@ -90,7 +90,7 @@ pub fn normalize_subject(raw_subject: Option<&str>) -> String {
#[cfg(test)]
mod tests {
- use crate::modules::envelope::utils::merge_contiguous_encoded_words;
+ use crate::envelope::utils::merge_contiguous_encoded_words;
#[tokio::test]
diff --git a/crates/core/src/error/code.rs b/crates/core/src/error/code.rs
new file mode 100644
index 0000000..490c427
--- /dev/null
+++ b/crates/core/src/error/code.rs
@@ -0,0 +1,44 @@
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[repr(u32)]
+pub enum ErrorCode {
+ // Client-side errors (10000–10999)
+ InvalidParameter = 10000,
+ MissingConfiguration = 10020,
+ Incompatible = 10030,
+ PayloadTooLarge = 10070,
+ RequestTimeout = 10080,
+ MethodNotAllowed = 10090,
+
+ // Authentication and authorization errors (20000–20999)
+ PermissionDenied = 20000,
+ AccountDisabled = 20010,
+ Forbidden = 20020,
+ OAuth2ItemDisabled = 20050,
+ MissingRefreshToken = 20060,
+
+ // Resource errors (30000–30999)
+ ResourceNotFound = 30000,
+ TooManyRequest = 30020,
+ AlreadyExists = 30030,
+
+ // Network connection errors (40000–40999)
+ NetworkError = 40000,
+ ConnectionTimeout = 40010,
+ ConnectionPoolTimeout = 40020,
+ HttpResponseError = 40030,
+
+ // Mail service errors (50000–50999)
+ ImapCommandFailed = 50000,
+ ImapAuthenticationFailed = 50010,
+ ImapUnexpectedResult = 50020,
+ AutoconfigFetchFailed = 50060,
+ // Internal system errors (70000–70999)
+ InternalError = 70000,
+ UnhandledPoemError = 70010,
+}
+
+impl ErrorCode {
+ pub fn to_u32(&self) -> u32 {
+ *self as u32
+ }
+}
diff --git a/crates/core/src/error/mod.rs b/crates/core/src/error/mod.rs
new file mode 100644
index 0000000..edf360c
--- /dev/null
+++ b/crates/core/src/error/mod.rs
@@ -0,0 +1,19 @@
+use snafu::{Location, Snafu};
+
+use crate::error::code::ErrorCode;
+
+pub mod code;
+
+#[derive(Debug, Snafu)]
+#[snafu(visibility(pub))]
+pub enum BichonError {
+ #[snafu(display("{message}"))]
+ Generic {
+ message: String,
+ #[snafu(implicit)]
+ location: Location,
+ code: ErrorCode,
+ },
+}
+
+pub type BichonResult = std::result::Result;
diff --git a/src/modules/imap/capabilities.rs b/crates/core/src/imap/capabilities.rs
similarity index 91%
rename from src/modules/imap/capabilities.rs
rename to crates/core/src/imap/capabilities.rs
index a2bbbf9..e7ffc53 100644
--- a/src/modules/imap/capabilities.rs
+++ b/crates/core/src/imap/capabilities.rs
@@ -16,9 +16,9 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::error::code::ErrorCode;
-use crate::modules::imap::session::SessionStream;
-use crate::{modules::error::BichonResult, raise_error};
+use crate::error::code::ErrorCode;
+use crate::imap::session::SessionStream;
+use crate::{error::BichonResult, raise_error};
use async_imap::types::Capability;
use async_imap::{types::Capabilities, Session};
diff --git a/src/modules/imap/client.rs b/crates/core/src/imap/client.rs
similarity index 95%
rename from src/modules/imap/client.rs
rename to crates/core/src/imap/client.rs
index 157ac42..1fd70b0 100644
--- a/src/modules/imap/client.rs
+++ b/crates/core/src/imap/client.rs
@@ -16,14 +16,14 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::account::entity::Encryption;
-use crate::modules::error::code::ErrorCode;
-use crate::modules::error::BichonResult;
-use crate::modules::imap::session::SessionStream;
-use crate::modules::imap::stats::StatsWrapper;
-use crate::modules::utils::net::establish_tcp_connection_with_timeout;
-use crate::modules::utils::net::establish_tls_connection;
-use crate::modules::utils::tls::establish_tls_stream;
+use crate::account::entity::Encryption;
+use crate::error::code::ErrorCode;
+use crate::error::BichonResult;
+use crate::imap::session::SessionStream;
+use crate::imap::stats::StatsWrapper;
+use crate::utils::net::establish_tcp_connection_with_timeout;
+use crate::utils::net::establish_tls_connection;
+use crate::utils::tls::establish_tls_stream;
use crate::raise_error;
use async_imap::Client as ImapClient;
use async_imap::Session as ImapSession;
diff --git a/src/modules/imap/executor.rs b/crates/core/src/imap/executor.rs
similarity index 95%
rename from src/modules/imap/executor.rs
rename to crates/core/src/imap/executor.rs
index c7dcf11..5ad2ef0 100644
--- a/src/modules/imap/executor.rs
+++ b/crates/core/src/imap/executor.rs
@@ -16,14 +16,14 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::account::migration::AccountModel;
-use crate::modules::account::state::{DownloadState, FolderStatus};
-use crate::modules::cache::imap::mailbox::MailBox;
-use crate::modules::cache::imap::download::flow::{generate_uid_sequence_hashset, DEFAULT_BATCH_SIZE};
-use crate::modules::envelope::extractor::extract_envelope_and_store_it;
-use crate::modules::error::code::ErrorCode;
-use crate::modules::imap::session::SessionStream;
-use crate::modules::{error::BichonResult, imap::manager::ImapConnectionManager};
+use crate::account::migration::AccountModel;
+use crate::account::state::{DownloadState, FolderStatus};
+use crate::cache::imap::mailbox::MailBox;
+use crate::cache::imap::download::flow::{generate_uid_sequence_hashset, DEFAULT_BATCH_SIZE};
+use crate::envelope::extractor::extract_envelope_and_store_it;
+use crate::error::code::ErrorCode;
+use crate::imap::session::SessionStream;
+use crate::{error::BichonResult, imap::manager::ImapConnectionManager};
use crate::raise_error;
use async_imap::types::Name;
use async_imap::Session;
diff --git a/src/modules/imap/manager.rs b/crates/core/src/imap/manager.rs
similarity index 92%
rename from src/modules/imap/manager.rs
rename to crates/core/src/imap/manager.rs
index d45b929..ac2f1cb 100644
--- a/src/modules/imap/manager.rs
+++ b/crates/core/src/imap/manager.rs
@@ -16,17 +16,17 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::account::entity::AuthType;
-use crate::modules::account::migration::{AccountModel, AccountType};
-use crate::modules::error::code::ErrorCode;
-use crate::modules::error::BichonResult;
-use crate::modules::imap::capabilities::{
+use crate::account::entity::AuthType;
+use crate::account::migration::{AccountModel, AccountType};
+use crate::error::code::ErrorCode;
+use crate::error::BichonResult;
+use crate::imap::capabilities::{
capability_to_string, check_capabilities, fetch_capabilities,
};
-use crate::modules::imap::client::Client;
-use crate::modules::imap::oauth2::OAuth2;
-use crate::modules::imap::session::SessionStream;
-use crate::modules::oauth2::token::OAuth2AccessToken;
+use crate::imap::client::Client;
+use crate::imap::oauth2::OAuth2;
+use crate::imap::session::SessionStream;
+use crate::oauth2::token::OAuth2AccessToken;
use crate::{bichon_version, decrypt, raise_error};
use async_imap::Session;
use tracing::{error, warn};
diff --git a/src/modules/imap/mod.rs b/crates/core/src/imap/mod.rs
similarity index 100%
rename from src/modules/imap/mod.rs
rename to crates/core/src/imap/mod.rs
diff --git a/src/modules/imap/oauth2.rs b/crates/core/src/imap/oauth2.rs
similarity index 100%
rename from src/modules/imap/oauth2.rs
rename to crates/core/src/imap/oauth2.rs
diff --git a/src/modules/imap/session.rs b/crates/core/src/imap/session.rs
similarity index 100%
rename from src/modules/imap/session.rs
rename to crates/core/src/imap/session.rs
diff --git a/src/modules/imap/stats.rs b/crates/core/src/imap/stats.rs
similarity index 98%
rename from src/modules/imap/stats.rs
rename to crates/core/src/imap/stats.rs
index 63253f4..541852e 100644
--- a/src/modules/imap/stats.rs
+++ b/crates/core/src/imap/stats.rs
@@ -23,7 +23,7 @@ use std::task::{Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
-use crate::modules::imap::session::SessionStream;
+use crate::imap::session::SessionStream;
pub struct StatsWrapper {
inner: T,
diff --git a/src/modules/imap/tests.rs b/crates/core/src/imap/tests.rs
similarity index 99%
rename from src/modules/imap/tests.rs
rename to crates/core/src/imap/tests.rs
index f9fe96b..7b20d90 100644
--- a/src/modules/imap/tests.rs
+++ b/crates/core/src/imap/tests.rs
@@ -20,7 +20,7 @@ use mail_parser::{parsers::MessageStream, MessageParser, MimeHeaders};
use crate::{
base64_encode_url_safe,
- modules::{account::entity::Encryption, imap::client::Client},
+ {account::entity::Encryption, imap::client::Client},
};
#[tokio::test]
diff --git a/src/modules/import/mod.rs b/crates/core/src/import/mod.rs
similarity index 95%
rename from src/modules/import/mod.rs
rename to crates/core/src/import/mod.rs
index 99b5ff9..2f74a9d 100644
--- a/src/modules/import/mod.rs
+++ b/crates/core/src/import/mod.rs
@@ -17,12 +17,12 @@
// along with this program. If not, see .
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
use crate::{
base64_decode_url_safe,
- modules::{
+ {
account::migration::{AccountModel, AccountType},
cache::imap::mailbox::{Attribute, AttributeEnum, MailBox},
envelope::extractor::extract_envelope_from_eml,
@@ -32,7 +32,8 @@ use crate::{
raise_error,
};
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct BatchEmlRequest {
pub account_id: u64,
pub mail_folder: String,
@@ -40,7 +41,8 @@ pub struct BatchEmlRequest {
pub emls: Vec,
}
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct FailedEmlDetail {
/// The 0-based index of the failed EML in the request list
pub index: usize,
@@ -48,7 +50,8 @@ pub struct FailedEmlDetail {
pub error_message: String,
}
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct BatchEmlResult {
/// Total number of emails processed
pub total: usize,
diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs
new file mode 100644
index 0000000..b9b8033
--- /dev/null
+++ b/crates/core/src/lib.rs
@@ -0,0 +1,23 @@
+pub mod account;
+pub mod admin;
+pub mod autoconfig;
+pub mod cache;
+pub mod common;
+pub mod context;
+pub mod dashboard;
+pub mod database;
+pub mod envelope;
+pub mod error;
+pub mod imap;
+pub mod import;
+pub mod logger;
+pub mod mailbox;
+pub mod message;
+pub mod oauth2;
+pub mod settings;
+pub mod store;
+pub mod tasks;
+pub mod token;
+pub mod users;
+pub mod utils;
+pub mod version;
diff --git a/src/modules/logger/file.rs b/crates/core/src/logger/file.rs
similarity index 94%
rename from src/modules/logger/file.rs
rename to crates/core/src/logger/file.rs
index 001bc03..8aadaa6 100644
--- a/src/modules/logger/file.rs
+++ b/crates/core/src/logger/file.rs
@@ -16,9 +16,9 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::logger::LocalTimer;
-use crate::modules::settings::cli::SETTINGS;
-use crate::modules::settings::dir::DATA_DIR_MANAGER;
+use crate::logger::LocalTimer;
+use crate::settings::cli::SETTINGS;
+use crate::settings::dir::DATA_DIR_MANAGER;
use std::sync::OnceLock;
use tracing::level_filters::LevelFilter;
use tracing::Level;
diff --git a/src/modules/logger/mod.rs b/crates/core/src/logger/mod.rs
similarity index 96%
rename from src/modules/logger/mod.rs
rename to crates/core/src/logger/mod.rs
index e0851a3..ed3ec3e 100644
--- a/src/modules/logger/mod.rs
+++ b/crates/core/src/logger/mod.rs
@@ -16,8 +16,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::logger::file::setup_file_logger;
-use crate::modules::settings::cli::SETTINGS;
+use crate::logger::file::setup_file_logger;
+use crate::settings::cli::SETTINGS;
use chrono::Local;
use std::process;
use tracing::Level;
diff --git a/src/modules/mailbox/delete.rs b/crates/core/src/mailbox/delete.rs
similarity index 98%
rename from src/modules/mailbox/delete.rs
rename to crates/core/src/mailbox/delete.rs
index ea19f38..3bf9160 100644
--- a/src/modules/mailbox/delete.rs
+++ b/crates/core/src/mailbox/delete.rs
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::{
+use crate::{
cache::imap::mailbox::MailBox,
error::BichonResult,
store::tantivy::{attachment::ATTACHMENT_MANAGER, envelope::ENVELOPE_MANAGER},
diff --git a/src/modules/mailbox/list.rs b/crates/core/src/mailbox/list.rs
similarity index 88%
rename from src/modules/mailbox/list.rs
rename to crates/core/src/mailbox/list.rs
index 542a615..d3226c6 100644
--- a/src/modules/mailbox/list.rs
+++ b/crates/core/src/mailbox/list.rs
@@ -16,13 +16,13 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::account::migration::{AccountModel, AccountType};
-use crate::modules::cache::imap::mailbox::{Attribute, AttributeEnum, MailBox};
-use crate::modules::error::code::ErrorCode;
-use crate::modules::error::BichonResult;
-use crate::modules::imap::executor::ImapExecutor;
-use crate::modules::imap::session::SessionStream;
-use crate::modules::utils::create_hash;
+use crate::account::migration::{AccountModel, AccountType};
+use crate::cache::imap::mailbox::{Attribute, AttributeEnum, MailBox};
+use crate::error::code::ErrorCode;
+use crate::error::BichonResult;
+use crate::imap::executor::ImapExecutor;
+use crate::imap::session::SessionStream;
+use crate::utils::create_hash;
use crate::raise_error;
use async_imap::types::Name;
use async_imap::Session;
diff --git a/src/modules/mailbox/mod.rs b/crates/core/src/mailbox/mod.rs
similarity index 100%
rename from src/modules/mailbox/mod.rs
rename to crates/core/src/mailbox/mod.rs
diff --git a/src/modules/message/append.rs b/crates/core/src/message/append.rs
similarity index 95%
rename from src/modules/message/append.rs
rename to crates/core/src/message/append.rs
index 1544a1f..cd59c81 100644
--- a/src/modules/message/append.rs
+++ b/crates/core/src/message/append.rs
@@ -1,6 +1,6 @@
use crate::{
encode_mailbox_name,
- modules::{
+ {
account::migration::{AccountModel, AccountType},
envelope::extractor::reattach_eml_content,
error::{code::ErrorCode, BichonResult},
@@ -8,12 +8,13 @@ use crate::{
},
raise_error,
};
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
const MAX_RESTORE_COUNT: usize = 100;
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct RestoreMessagesRequest {
/// envelope IDs to restore (max 100)
pub envelope_ids: Vec,
diff --git a/src/modules/message/attachment.rs b/crates/core/src/message/attachment.rs
similarity index 97%
rename from src/modules/message/attachment.rs
rename to crates/core/src/message/attachment.rs
index 0ae718d..28dd206 100644
--- a/src/modules/message/attachment.rs
+++ b/crates/core/src/message/attachment.rs
@@ -1,7 +1,7 @@
use std::io::Cursor;
use crate::{
- modules::{
+ {
dashboard::Group,
envelope::extractor::reattach_eml_content,
error::{code::ErrorCode, BichonResult},
@@ -11,10 +11,11 @@ use crate::{
};
use bytes::Bytes;
use mail_parser::MessageParser;
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AttachmentMetadata {
/// Statistics of attachment file extensions (key + count).
/// Each item represents a file extension and its occurrence count.
diff --git a/src/modules/message/contacts.rs b/crates/core/src/message/contacts.rs
similarity index 81%
rename from src/modules/message/contacts.rs
rename to crates/core/src/message/contacts.rs
index ccfe081..7dace5b 100644
--- a/src/modules/message/contacts.rs
+++ b/crates/core/src/message/contacts.rs
@@ -1,7 +1,7 @@
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct Contact {
pub email: String,
pub name: Option,
diff --git a/src/modules/message/content.rs b/crates/core/src/message/content.rs
similarity index 96%
rename from src/modules/message/content.rs
rename to crates/core/src/message/content.rs
index 69a5b7f..2c65594 100644
--- a/src/modules/message/content.rs
+++ b/crates/core/src/message/content.rs
@@ -17,23 +17,24 @@
// along with this program. If not, see .
use crate::base64_encode;
-use crate::modules::account::migration::AccountModel;
-use crate::modules::envelope::extractor::{
+use crate::account::migration::AccountModel;
+use crate::envelope::extractor::{
extract_envelope_from_nested_message, reattach_eml_content,
};
-use crate::modules::error::code::ErrorCode;
-use crate::modules::store::envelope::Envelope;
-use crate::modules::utils::compute_content_hash;
-use crate::{modules::error::BichonResult, raise_error};
+use crate::error::code::ErrorCode;
+use crate::store::envelope::Envelope;
+use crate::utils::compute_content_hash;
+use crate::{error::BichonResult, raise_error};
use mail_parser::{MessageParser, MimeHeaders};
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
/// Represents metadata of an attachment in a Gmail message.
///
/// This struct stores information required to identify, download,
/// and render an attachment, including inline images embedded
/// in HTML emails.
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AttachmentInfo {
/// MIME content type of the attachment (e.g., `image/png`, `application/pdf`).
pub file_type: String,
@@ -134,7 +135,8 @@ impl AttachmentInfo {
///
/// - `plain`: The plain text version of the message, if available.
/// - `html`: The HTML version of the message, if available.
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct FullMessageContent {
/// Optional plain text version of the message.
pub text: Option,
@@ -144,7 +146,8 @@ pub struct FullMessageContent {
pub attachments: Option>,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct FullNestedMessageContent {
/// Optional plain text version of the message.
pub text: Option,
diff --git a/src/modules/message/delete.rs b/crates/core/src/message/delete.rs
similarity index 86%
rename from src/modules/message/delete.rs
rename to crates/core/src/message/delete.rs
index f998fdd..cc768f6 100644
--- a/src/modules/message/delete.rs
+++ b/crates/core/src/message/delete.rs
@@ -16,9 +16,9 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::error::BichonResult;
-use crate::modules::store::tantivy::attachment::ATTACHMENT_MANAGER;
-use crate::modules::store::tantivy::envelope::ENVELOPE_MANAGER;
+use crate::error::BichonResult;
+use crate::store::tantivy::attachment::ATTACHMENT_MANAGER;
+use crate::store::tantivy::envelope::ENVELOPE_MANAGER;
use std::collections::HashMap;
pub async fn delete_messages_impl(request: HashMap>) -> BichonResult<()> {
diff --git a/src/modules/message/list.rs b/crates/core/src/message/list.rs
similarity index 85%
rename from src/modules/message/list.rs
rename to crates/core/src/message/list.rs
index 836c1d1..47c4f04 100644
--- a/src/modules/message/list.rs
+++ b/crates/core/src/message/list.rs
@@ -16,11 +16,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::{
- account::migration::AccountModel,
- error::BichonResult,
- rest::response::DataPage,
- store::{envelope::Envelope, tantivy::envelope::ENVELOPE_MANAGER},
+use crate::{
+ account::migration::AccountModel, common::paginated::DataPage, error::BichonResult, store::{envelope::Envelope, tantivy::envelope::ENVELOPE_MANAGER}
};
pub async fn get_thread_messages(
diff --git a/src/modules/message/mod.rs b/crates/core/src/message/mod.rs
similarity index 100%
rename from src/modules/message/mod.rs
rename to crates/core/src/message/mod.rs
diff --git a/src/modules/message/search.rs b/crates/core/src/message/search.rs
similarity index 91%
rename from src/modules/message/search.rs
rename to crates/core/src/message/search.rs
index 85c82a9..07eff21 100644
--- a/src/modules/message/search.rs
+++ b/crates/core/src/message/search.rs
@@ -16,25 +16,21 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use poem_openapi::{Enum, Object};
+//use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use crate::{
- modules::{
- error::{code::ErrorCode, BichonResult},
- rest::response::DataPage,
- store::{
+ common::paginated::DataPage, error::{BichonResult, code::ErrorCode}, raise_error, store::{
envelope::Envelope,
tantivy::{
attachment::ATTACHMENT_MANAGER, envelope::ENVELOPE_MANAGER, model::AttachmentModel,
},
- },
- },
- raise_error,
+ }
};
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct EmailSearchFilter {
pub text: Option,
pub subject: Option,
@@ -59,14 +55,16 @@ pub struct EmailSearchFilter {
pub attachment_content_type: Option,
}
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Enum)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Enum))]
pub enum SortBy {
#[default]
DATE,
SIZE,
}
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct EmailSearchRequest {
filter: EmailSearchFilter,
page: u64,
@@ -110,7 +108,8 @@ pub async fn search_messages_impl(
.await
}
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AttachmentSearchFilter {
pub id: Option,
pub text: Option,
@@ -139,7 +138,8 @@ pub struct AttachmentSearchFilter {
pub max_page_count: Option,
}
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AttachmentSearchRequest {
filter: AttachmentSearchFilter,
page: u64,
diff --git a/src/modules/message/tags.rs b/crates/core/src/message/tags.rs
similarity index 80%
rename from src/modules/message/tags.rs
rename to crates/core/src/message/tags.rs
index c048567..52864d9 100644
--- a/src/modules/message/tags.rs
+++ b/crates/core/src/message/tags.rs
@@ -18,23 +18,26 @@
use std::collections::HashMap;
-use poem_openapi::{Enum, Object};
+//use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct TagsRequest {
pub updates: HashMap>,
pub tags: Vec,
pub action: TagAction,
}
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct TagCount {
pub tag: String,
pub count: u64,
}
-#[derive(Enum, Default, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
+#[derive(Default, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Enum))]
pub enum TagAction {
Add,
Remove,
diff --git a/src/modules/oauth2/entity.rs b/crates/core/src/oauth2/entity.rs
similarity index 95%
rename from src/modules/oauth2/entity.rs
rename to crates/core/src/oauth2/entity.rs
index f3cb806..2b689d5 100644
--- a/src/modules/oauth2/entity.rs
+++ b/crates/core/src/oauth2/entity.rs
@@ -17,25 +17,24 @@
// along with this program. If not, see .
use crate::{
- encrypt, id,
- modules::{
- database::{
- async_secondary_find_impl, delete_impl, insert_impl, manager::DB_MANAGER,
- paginate_query_primary_scan_all_impl, update_impl,
- },
- error::{code::ErrorCode, BichonResult},
- rest::response::DataPage,
+ common::paginated::DataPage,
+ database::{
+ async_secondary_find_impl, delete_impl, insert_impl, manager::DB_MANAGER,
+ paginate_query_primary_scan_all_impl, update_impl,
},
- raise_error, utc_now,
+ encrypt,
+ error::{code::ErrorCode, BichonResult},
+ id, raise_error, utc_now,
};
use native_db::*;
use native_model::{native_model, Model};
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
/// Represents the OAuth2 configuration for a client, including initialization and runtime values.
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
#[native_model(id = 5, version = 1)]
#[native_db(primary_key(pk -> String))]
pub struct OAuth2 {
@@ -175,7 +174,8 @@ impl OAuth2 {
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct OAuth2CreateRequest {
/// A description of what this configuration is used for.
pub description: Option,
@@ -225,7 +225,8 @@ impl OAuth2CreateRequest {
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct OAuth2UpdateRequest {
/// A description of what this configuration is used for.
pub description: Option,
diff --git a/src/modules/oauth2/flow.rs b/crates/core/src/oauth2/flow.rs
similarity index 97%
rename from src/modules/oauth2/flow.rs
rename to crates/core/src/oauth2/flow.rs
index 4aa310c..9bc92c3 100644
--- a/src/modules/oauth2/flow.rs
+++ b/crates/core/src/oauth2/flow.rs
@@ -17,18 +17,18 @@
// along with this program. If not, see .
-use crate::modules::error::code::ErrorCode;
-use crate::modules::error::BichonResult;
-use crate::modules::oauth2::{
+use crate::error::code::ErrorCode;
+use crate::error::BichonResult;
+use crate::oauth2::{
entity::OAuth2, pending::OAuth2PendingEntity, token::OAuth2AccessToken,
};
-use crate::modules::settings::proxy::Proxy;
+use crate::settings::proxy::Proxy;
use crate::{decrypt, encrypt, raise_error};
use oauth2::{
basic::BasicClient, AuthUrl, AuthorizationCode, ClientId, ClientSecret, CsrfToken,
PkceCodeChallenge, PkceCodeVerifier, RedirectUrl, RefreshToken, Scope, TokenResponse, TokenUrl,
};
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
pub type OAuth2Client = oauth2::Client<
@@ -47,7 +47,8 @@ pub type OAuth2Client = oauth2::Client<
oauth2::EndpointSet,
>;
-#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AuthorizeUrlRequest {
/// The ID of the account for which the authorization URL is generated.
pub account_id: u64,
diff --git a/src/modules/oauth2/mod.rs b/crates/core/src/oauth2/mod.rs
similarity index 100%
rename from src/modules/oauth2/mod.rs
rename to crates/core/src/oauth2/mod.rs
diff --git a/src/modules/oauth2/pending.rs b/crates/core/src/oauth2/pending.rs
similarity index 99%
rename from src/modules/oauth2/pending.rs
rename to crates/core/src/oauth2/pending.rs
index 5014cbb..2473d4b 100644
--- a/src/modules/oauth2/pending.rs
+++ b/crates/core/src/oauth2/pending.rs
@@ -18,7 +18,7 @@
use crate::{
- modules::{
+ {
database::{
batch_delete_impl, delete_impl, async_find_impl, insert_impl, manager::DB_MANAGER,
},
diff --git a/src/modules/oauth2/refresh/mod.rs b/crates/core/src/oauth2/refresh/mod.rs
similarity index 94%
rename from src/modules/oauth2/refresh/mod.rs
rename to crates/core/src/oauth2/refresh/mod.rs
index 70fa260..8051281 100644
--- a/src/modules/oauth2/refresh/mod.rs
+++ b/crates/core/src/oauth2/refresh/mod.rs
@@ -16,10 +16,10 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::common::periodic::{PeriodicTask, TaskHandle};
-use crate::modules::context::BichonTask;
-use crate::modules::oauth2::token::EXTERNAL_OAUTH_APP_ID;
-use crate::modules::oauth2::{flow::OAuth2Flow, token::OAuth2AccessToken};
+use crate::common::periodic::{PeriodicTask, TaskHandle};
+use crate::context::BichonTask;
+use crate::oauth2::token::EXTERNAL_OAUTH_APP_ID;
+use crate::oauth2::{flow::OAuth2Flow, token::OAuth2AccessToken};
use crate::utc_now;
use std::time::Duration;
use tracing::{debug, error, info};
diff --git a/src/modules/oauth2/task.rs b/crates/core/src/oauth2/task.rs
similarity index 98%
rename from src/modules/oauth2/task.rs
rename to crates/core/src/oauth2/task.rs
index 6f81f3a..1142e90 100644
--- a/src/modules/oauth2/task.rs
+++ b/crates/core/src/oauth2/task.rs
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::{
+use crate::{
common::periodic::{PeriodicTask, TaskHandle},
context::BichonTask,
oauth2::pending::OAuth2PendingEntity,
diff --git a/src/modules/oauth2/token.rs b/crates/core/src/oauth2/token.rs
similarity index 97%
rename from src/modules/oauth2/token.rs
rename to crates/core/src/oauth2/token.rs
index 44b7b0f..237657e 100644
--- a/src/modules/oauth2/token.rs
+++ b/crates/core/src/oauth2/token.rs
@@ -19,7 +19,7 @@
use crate::{
decrypt, encrypt,
- modules::{
+ {
database::{
async_find_impl, delete_impl, insert_impl, list_all_impl, manager::DB_MANAGER,
update_impl, upsert_impl,
@@ -31,12 +31,13 @@ use crate::{
};
use native_db::*;
use native_model::{native_model, Model};
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
pub const EXTERNAL_OAUTH_APP_ID: u64 = 0;
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
#[native_model(id = 7, version = 1)]
#[native_db]
pub struct OAuth2AccessToken {
@@ -195,7 +196,8 @@ impl OAuth2AccessToken {
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct ExternalOAuth2Request {
/// The id of the OAuth2 configuration associated with this access token.
pub oauth2_id: Option,
@@ -245,7 +247,7 @@ impl ExternalOAuth2Request {
#[cfg(test)]
mod tests {
- use crate::modules::oauth2::token::OAuth2AccessToken;
+ use crate::oauth2::token::OAuth2AccessToken;
#[tokio::test]
async fn test1() {
diff --git a/src/modules/settings/cli.rs b/crates/core/src/settings/cli.rs
similarity index 99%
rename from src/modules/settings/cli.rs
rename to crates/core/src/settings/cli.rs
index 2a7df79..e43c9f4 100644
--- a/src/modules/settings/cli.rs
+++ b/crates/core/src/settings/cli.rs
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::settings::io::check_dir_read_write;
+use crate::settings::io::check_dir_read_write;
use clap::{builder::ValueParser, Parser, ValueEnum};
use std::{collections::HashSet, env, fmt, path::PathBuf, sync::LazyLock};
diff --git a/src/modules/settings/dir.rs b/crates/core/src/settings/dir.rs
similarity index 96%
rename from src/modules/settings/dir.rs
rename to crates/core/src/settings/dir.rs
index eb926b0..f973154 100644
--- a/src/modules/settings/dir.rs
+++ b/crates/core/src/settings/dir.rs
@@ -16,10 +16,10 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::context::Initialize;
-use crate::modules::settings::cli::SETTINGS;
+use crate::context::Initialize;
+use crate::settings::cli::SETTINGS;
use crate::{
- modules::error::{code::ErrorCode, BichonResult},
+ error::{code::ErrorCode, BichonResult},
raise_error,
};
use std::path::PathBuf;
diff --git a/src/modules/settings/io.rs b/crates/core/src/settings/io.rs
similarity index 100%
rename from src/modules/settings/io.rs
rename to crates/core/src/settings/io.rs
diff --git a/src/modules/settings/mod.rs b/crates/core/src/settings/mod.rs
similarity index 96%
rename from src/modules/settings/mod.rs
rename to crates/core/src/settings/mod.rs
index 151234e..be7d9bb 100644
--- a/src/modules/settings/mod.rs
+++ b/crates/core/src/settings/mod.rs
@@ -16,8 +16,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::settings::cli::Settings;
-use poem_openapi::Object;
+use crate::settings::cli::Settings;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
pub mod cli;
@@ -25,7 +25,8 @@ pub mod dir;
pub mod io;
pub mod proxy;
pub mod system;
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct SystemConfigurations {
pub bichon_log_level: String,
pub bichon_http_port: i32,
diff --git a/src/modules/settings/proxy.rs b/crates/core/src/settings/proxy.rs
similarity index 97%
rename from src/modules/settings/proxy.rs
rename to crates/core/src/settings/proxy.rs
index 9fbbdeb..49ee80d 100644
--- a/src/modules/settings/proxy.rs
+++ b/crates/core/src/settings/proxy.rs
@@ -18,12 +18,12 @@
use native_db::*;
use native_model::{native_model, Model};
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
use crate::{
id,
- modules::{
+ {
database::{
async_find_impl, delete_impl, insert_impl, list_all_impl, manager::DB_MANAGER,
update_impl,
@@ -34,7 +34,8 @@ use crate::{
raise_error, utc_now,
};
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
#[native_model(id = 8, version = 1)]
#[native_db]
pub struct Proxy {
diff --git a/src/modules/settings/system.rs b/crates/core/src/settings/system.rs
similarity index 92%
rename from src/modules/settings/system.rs
rename to crates/core/src/settings/system.rs
index 025df65..115040f 100644
--- a/src/modules/settings/system.rs
+++ b/crates/core/src/settings/system.rs
@@ -16,11 +16,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
-// use crate::modules::database::manager::DB_MANAGER;
-// use crate::modules::database::{find_impl, upsert_impl};
-// use crate::modules::error::BichonResult;
-// use crate::utc_now;
use native_db::*;
use native_model::{native_model, Model};
use serde::{Deserialize, Serialize};
diff --git a/src/modules/store/envelope.rs b/crates/core/src/store/envelope.rs
similarity index 94%
rename from src/modules/store/envelope.rs
rename to crates/core/src/store/envelope.rs
index ac02919..6767f29 100644
--- a/src/modules/store/envelope.rs
+++ b/crates/core/src/store/envelope.rs
@@ -16,11 +16,12 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
use tantivy::doc;
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct Envelope {
pub id: String,
pub message_id: String,
diff --git a/src/modules/store/mod.rs b/crates/core/src/store/mod.rs
similarity index 100%
rename from src/modules/store/mod.rs
rename to crates/core/src/store/mod.rs
diff --git a/src/modules/store/storage.rs b/crates/core/src/store/storage.rs
similarity index 99%
rename from src/modules/store/storage.rs
rename to crates/core/src/store/storage.rs
index 0f0823b..e0f0a03 100644
--- a/src/modules/store/storage.rs
+++ b/crates/core/src/store/storage.rs
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::{
+use crate::{
common::signal::SIGNAL_MANAGER,
envelope::extractor::reattach_eml_content,
error::{code::ErrorCode, BichonResult},
diff --git a/src/modules/store/tantivy/attachment.rs b/crates/core/src/store/tantivy/attachment.rs
similarity index 99%
rename from src/modules/store/tantivy/attachment.rs
rename to crates/core/src/store/tantivy/attachment.rs
index e5ce6b8..0b6d967 100644
--- a/src/modules/store/tantivy/attachment.rs
+++ b/crates/core/src/store/tantivy/attachment.rs
@@ -25,28 +25,19 @@ use std::{
};
use crate::{
- modules::{
- common::signal::SIGNAL_MANAGER,
- dashboard::{Group, LargestAttachment},
- error::{code::ErrorCode, BichonResult},
- message::{
+ common::{paginated::DataPage, signal::SIGNAL_MANAGER}, dashboard::{Group, LargestAttachment}, error::{BichonResult, code::ErrorCode}, message::{
attachment::AttachmentMetadata,
search::{AttachmentSearchFilter, SortBy},
tags::{TagAction, TagCount, TagsRequest},
- },
- rest::response::DataPage,
- settings::dir::DATA_DIR_MANAGER,
- store::tantivy::{
+ }, raise_error, settings::dir::DATA_DIR_MANAGER, store::tantivy::{
fatal_commit,
fields::{
F_ATTACHMENT_CATEGORY, F_ATTACHMENT_CONTENT_TYPE, F_ATTACHMENT_EXT, F_DATE, F_SIZE,
F_TAGS,
},
- model::{extract_senders, AttachmentModel},
+ model::{AttachmentModel, extract_senders},
schema::SchemaTools,
- },
- },
- raise_error,
+ }
};
use serde_json::json;
diff --git a/src/modules/store/tantivy/envelope.rs b/crates/core/src/store/tantivy/envelope.rs
similarity index 99%
rename from src/modules/store/tantivy/envelope.rs
rename to crates/core/src/store/tantivy/envelope.rs
index fd4e24f..69ce4a9 100644
--- a/src/modules/store/tantivy/envelope.rs
+++ b/crates/core/src/store/tantivy/envelope.rs
@@ -25,18 +25,10 @@ use std::{
};
use crate::{
- modules::{
- account::migration::AccountModel,
- common::signal::SIGNAL_MANAGER,
- dashboard::{DashboardStats, Group, LargestEmail, TimeBucket},
- error::{code::ErrorCode, BichonResult},
- message::{
+ account::migration::AccountModel, common::{paginated::DataPage, signal::SIGNAL_MANAGER}, dashboard::{DashboardStats, Group, LargestEmail, TimeBucket}, error::{BichonResult, code::ErrorCode}, message::{
search::{EmailSearchFilter, SortBy},
tags::{TagAction, TagCount, TagsRequest},
- },
- rest::response::DataPage,
- settings::dir::DATA_DIR_MANAGER,
- store::{
+ }, raise_error, settings::dir::DATA_DIR_MANAGER, store::{
envelope::Envelope,
storage::BLOB_MANAGER,
tantivy::{
@@ -45,12 +37,10 @@ use crate::{
F_ACCOUNT_ID, F_DATE, F_FROM, F_REGULAR_ATTACHMENT_COUNT, F_SIZE, F_TAGS,
F_THREAD_ID, F_UID,
},
- model::{extract_contacts, EnvelopeWithAttachments},
+ model::{EnvelopeWithAttachments, extract_contacts},
schema::SchemaTools,
},
- },
- },
- raise_error, utc_now,
+ }, utc_now
};
use chrono::Utc;
diff --git a/src/modules/store/tantivy/fields.rs b/crates/core/src/store/tantivy/fields.rs
similarity index 100%
rename from src/modules/store/tantivy/fields.rs
rename to crates/core/src/store/tantivy/fields.rs
diff --git a/src/modules/store/tantivy/mod.rs b/crates/core/src/store/tantivy/mod.rs
similarity index 100%
rename from src/modules/store/tantivy/mod.rs
rename to crates/core/src/store/tantivy/mod.rs
diff --git a/src/modules/store/tantivy/model.rs b/crates/core/src/store/tantivy/model.rs
similarity index 99%
rename from src/modules/store/tantivy/model.rs
rename to crates/core/src/store/tantivy/model.rs
index f943ada..cc74e28 100644
--- a/src/modules/store/tantivy/model.rs
+++ b/crates/core/src/store/tantivy/model.rs
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use tantivy::{
@@ -25,7 +25,8 @@ use tantivy::{
};
use crate::{
- modules::{
+ raise_error,
+ {
account::migration::AccountModel,
cache::imap::mailbox::MailBox,
error::{code::ErrorCode, BichonResult},
@@ -44,7 +45,6 @@ use crate::{
},
},
},
- raise_error,
};
#[derive(Debug, Clone)]
@@ -308,7 +308,8 @@ pub async fn extract_senders(doc: &TantivyDocument) -> BichonResult.
-use crate::modules::common::periodic::TaskHandle;
-use crate::modules::context::BichonTask;
-use crate::modules::oauth2::{refresh::OAuth2RefreshTask, task::OAuth2CleanTask};
+use crate::common::periodic::TaskHandle;
+use crate::context::BichonTask;
+use crate::oauth2::{refresh::OAuth2RefreshTask, task::OAuth2CleanTask};
pub struct PeriodicTasks {
tasks: Vec,
}
diff --git a/src/modules/token/mod.rs b/crates/core/src/token/mod.rs
similarity index 94%
rename from src/modules/token/mod.rs
rename to crates/core/src/token/mod.rs
index cc02ade..36199bf 100644
--- a/src/modules/token/mod.rs
+++ b/crates/core/src/token/mod.rs
@@ -19,22 +19,21 @@
use std::collections::HashMap;
use super::error::code::ErrorCode;
-use crate::modules::database::manager::DB_MANAGER;
-use crate::modules::database::{
+use crate::database::manager::DB_MANAGER;
+use crate::database::{
async_filter_by_secondary_key_impl, async_find_impl, delete_impl, with_transaction,
};
-use crate::modules::database::{insert_impl, list_all_impl, update_impl};
-use crate::modules::settings::cli::SETTINGS;
-use crate::modules::token::view::AccessTokenResp;
-use crate::modules::users::UserModel;
+use crate::database::{insert_impl, list_all_impl, update_impl};
use crate::raise_error;
+use crate::settings::cli::SETTINGS;
+use crate::token::view::AccessTokenResp;
+use crate::users::UserModel;
use crate::{
- generate_token, modules::error::BichonResult,
- modules::token::payload::AccessTokenCreateRequest, utc_now,
+ error::BichonResult, generate_token, token::payload::AccessTokenCreateRequest, utc_now,
};
use native_db::*;
use native_model::{native_model, Model};
-use poem_openapi::{Enum, Object};
+//use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
pub mod payload;
@@ -62,13 +61,15 @@ pub mod view;
// pub acl: Option,
// }
-#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Enum)]
+#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Enum))]
pub enum TokenType {
WebUI,
Api,
}
-#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
#[native_model(id = 11, version = 1)]
#[native_db]
pub struct AccessTokenModel {
diff --git a/src/modules/token/payload.rs b/crates/core/src/token/payload.rs
similarity index 91%
rename from src/modules/token/payload.rs
rename to crates/core/src/token/payload.rs
index 1c2e3a2..fdbed4f 100644
--- a/src/modules/token/payload.rs
+++ b/crates/core/src/token/payload.rs
@@ -17,16 +17,17 @@
// along with this program. If not, see .
use crate::{
- modules::error::{code::ErrorCode, BichonResult},
+ error::{code::ErrorCode, BichonResult},
raise_error,
};
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
-#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AccessTokenCreateRequest {
/// An optional description of the token's purpose or usage.
- #[oai(validator(max_length = "32"))]
+ //#[oai(validator(max_length = "32"))]
pub name: Option,
/// The expiration interval for this token, in hours.
/// None means the token does not expire (this applies only to API tokens).
diff --git a/src/modules/token/view.rs b/crates/core/src/token/view.rs
similarity index 91%
rename from src/modules/token/view.rs
rename to crates/core/src/token/view.rs
index 9732289..6fc6abe 100644
--- a/src/modules/token/view.rs
+++ b/crates/core/src/token/view.rs
@@ -16,12 +16,11 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
-use crate::modules::token::TokenType;
-use poem_openapi::Object;
+use crate::token::TokenType;
use serde::{Deserialize, Serialize};
-#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AccessTokenResp {
pub user_id: u64,
pub token: String,
@@ -38,7 +37,7 @@ pub struct AccessTokenResp {
pub expire_at: Option,
/// The timestamp (in milliseconds since epoch) when the token was last used.
pub last_access_at: i64,
-
+
pub user_name: String,
pub user_email: String,
}
diff --git a/src/modules/users/acl.rs b/crates/core/src/users/acl.rs
similarity index 86%
rename from src/modules/users/acl.rs
rename to crates/core/src/users/acl.rs
index 46974b4..7c88fbc 100644
--- a/src/modules/users/acl.rs
+++ b/crates/core/src/users/acl.rs
@@ -18,12 +18,16 @@
use std::{collections::BTreeSet, net::IpAddr};
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
-use crate::{modules::error::{BichonResult, code::ErrorCode}, raise_error};
+use crate::{
+ error::{code::ErrorCode, BichonResult},
+ raise_error,
+};
-#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct RateLimit {
/// The time window in seconds for the rate limit.
pub interval: u64,
@@ -31,7 +35,8 @@ pub struct RateLimit {
pub quota: u32,
}
-#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AccessControl {
/// An optional set of valid IPv4 or IPv6 addresses allowed to use the access token.
pub ip_whitelist: Option>,
diff --git a/src/modules/users/manager.rs b/crates/core/src/users/manager.rs
similarity index 98%
rename from src/modules/users/manager.rs
rename to crates/core/src/users/manager.rs
index d873d7d..5df10f9 100644
--- a/src/modules/users/manager.rs
+++ b/crates/core/src/users/manager.rs
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::{
+use crate::{
context::Initialize,
error::BichonResult,
users::{role::UserRole, UserModel},
diff --git a/src/modules/users/minimal.rs b/crates/core/src/users/minimal.rs
similarity index 93%
rename from src/modules/users/minimal.rs
rename to crates/core/src/users/minimal.rs
index 76bfce7..b10508b 100644
--- a/src/modules/users/minimal.rs
+++ b/crates/core/src/users/minimal.rs
@@ -16,16 +16,17 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
-use crate::modules::{
+use crate::{
database::{list_all_impl, manager::DB_MANAGER},
error::BichonResult,
users::UserModel,
};
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct MinimalUser {
pub id: u64,
pub username: String,
diff --git a/src/modules/users/mod.rs b/crates/core/src/users/mod.rs
similarity index 99%
rename from src/modules/users/mod.rs
rename to crates/core/src/users/mod.rs
index 0b625e2..e523b35 100644
--- a/src/modules/users/mod.rs
+++ b/crates/core/src/users/mod.rs
@@ -17,8 +17,8 @@
// along with this program. If not, see .
use crate::{
- decrypt, encrypt, generate_token, id,
- modules::{
+ decrypt, encrypt, generate_token, id, raise_error, utc_now,
+ {
database::{
async_find_impl, async_secondary_find_impl, batch_delete_impl, delete_impl,
list_all_impl, manager::DB_MANAGER, update_impl, with_transaction,
@@ -33,12 +33,11 @@ use crate::{
view::UserView,
},
},
- raise_error, utc_now,
};
use itertools::Itertools;
use native_db::*;
use native_model::{native_model, Model};
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet, HashSet};
use tracing::warn;
@@ -53,7 +52,7 @@ pub mod view;
pub type UserModel = BichonUserV2;
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct LoginResult {
pub success: bool,
pub error_message: Option,
@@ -64,7 +63,7 @@ pub struct LoginResult {
pub const DEFAULT_ADMIN_USER_ID: u64 = 100000000000000;
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
#[native_model(id = 10, version = 1)]
#[native_db]
pub struct BichonUser {
@@ -96,7 +95,7 @@ pub struct BichonUser {
pub acl: Option,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
#[native_model(id = 10, version = 2, from = BichonUser)]
#[native_db]
pub struct BichonUserV2 {
diff --git a/src/modules/users/payload.rs b/crates/core/src/users/payload.rs
similarity index 96%
rename from src/modules/users/payload.rs
rename to crates/core/src/users/payload.rs
index d73ea8d..100f01f 100644
--- a/src/modules/users/payload.rs
+++ b/crates/core/src/users/payload.rs
@@ -17,7 +17,8 @@
// along with this program. If not, see .
use crate::{
- modules::{
+ raise_error,
+ {
account::migration::AccountModel,
error::{code::ErrorCode, BichonResult},
users::{
@@ -27,9 +28,8 @@ use crate::{
},
utils::decode_avatar_bytes,
},
- raise_error,
};
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
@@ -70,7 +70,8 @@ fn validate_language(language: &Option) -> BichonResult<()> {
validate_option_in_set(language, &allowed_languages(), "language")
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct RoleCreateRequest {
pub name: String,
pub role_type: RoleType,
@@ -123,7 +124,8 @@ impl RoleCreateRequest {
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct RoleUpdateRequest {
pub name: Option,
pub description: Option,
@@ -194,11 +196,12 @@ impl RoleUpdateRequest {
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct UserCreateRequest {
pub username: String,
- #[oai(validator(custom = "crate::modules::common::validator::EmailValidator"))]
+ //#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
pub email: String,
pub password: String,
@@ -331,16 +334,17 @@ impl UserCreateRequest {
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct UserUpdateRequest {
pub username: Option,
- #[oai(validator(custom = "crate::modules::common::validator::EmailValidator"))]
+ //#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
pub email: Option,
pub password: Option,
pub avatar_base64: Option,
pub global_roles: Option>,
/// Scoped Access
- pub account_access_map: Option>,
+ pub account_access_map: Option>,
pub acl: Option,
pub description: Option,
pub theme: Option,
diff --git a/src/modules/users/permissions.rs b/crates/core/src/users/permissions.rs
similarity index 99%
rename from src/modules/users/permissions.rs
rename to crates/core/src/users/permissions.rs
index 6cc71f2..2362ab3 100644
--- a/src/modules/users/permissions.rs
+++ b/crates/core/src/users/permissions.rs
@@ -22,11 +22,11 @@ use std::{
};
use crate::{
- modules::{
+ raise_error,
+ {
error::{code::ErrorCode, BichonResult},
users::role::RoleType,
},
- raise_error,
};
pub static VALID_PERMISSION_SET: LazyLock> = LazyLock::new(|| {
diff --git a/src/modules/users/role.rs b/crates/core/src/users/role.rs
similarity index 98%
rename from src/modules/users/role.rs
rename to crates/core/src/users/role.rs
index b5944df..f28e380 100644
--- a/src/modules/users/role.rs
+++ b/crates/core/src/users/role.rs
@@ -23,12 +23,12 @@ use std::{
use native_db::*;
use native_model::{native_model, Model};
-use poem_openapi::{Enum, Object};
+//use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
use crate::{
- id,
- modules::{
+ id, raise_error, utc_now,
+ {
database::{
async_find_impl, delete_impl, insert_impl, list_all_impl, manager::DB_MANAGER,
update_impl, with_transaction,
@@ -40,7 +40,6 @@ use crate::{
UserModel,
},
},
- raise_error, utc_now,
};
/// Enumerates the built-in roles in the Bichon system.
@@ -175,14 +174,16 @@ fn is_builtin(id: u64) -> bool {
)
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Enum)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Enum))]
pub enum RoleType {
#[default]
Global,
Account,
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
#[native_model(id = 9, version = 1)]
#[native_db]
pub struct UserRole {
diff --git a/src/modules/users/view.rs b/crates/core/src/users/view.rs
similarity index 93%
rename from src/modules/users/view.rs
rename to crates/core/src/users/view.rs
index 70b672f..2839635 100644
--- a/src/modules/users/view.rs
+++ b/crates/core/src/users/view.rs
@@ -18,12 +18,13 @@
use std::collections::BTreeMap;
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
-use crate::modules::users::acl::AccessControl;
+use crate::users::acl::AccessControl;
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct UserView {
pub id: u64,
pub username: String,
diff --git a/src/modules/utils/encrypt.rs b/crates/core/src/utils/encrypt.rs
similarity index 97%
rename from src/modules/utils/encrypt.rs
rename to crates/core/src/utils/encrypt.rs
index c7918c0..5eb9533 100644
--- a/src/modules/utils/encrypt.rs
+++ b/crates/core/src/utils/encrypt.rs
@@ -24,9 +24,9 @@ use std::fs;
use std::num::NonZeroU32;
use std::sync::LazyLock;
-use crate::modules::error::code::ErrorCode;
-use crate::modules::error::BichonResult;
-use crate::modules::settings::cli::SETTINGS;
+use crate::error::code::ErrorCode;
+use crate::error::BichonResult;
+use crate::settings::cli::SETTINGS;
use crate::raise_error;
static ENCRYPT_PASSWORD: LazyLock = LazyLock::new(|| {
diff --git a/src/modules/utils/html.rs b/crates/core/src/utils/html.rs
similarity index 100%
rename from src/modules/utils/html.rs
rename to crates/core/src/utils/html.rs
diff --git a/src/modules/utils/mod.rs b/crates/core/src/utils/mod.rs
similarity index 93%
rename from src/modules/utils/mod.rs
rename to crates/core/src/utils/mod.rs
index dc74d02..3399ef2 100644
--- a/src/modules/utils/mod.rs
+++ b/crates/core/src/utils/mod.rs
@@ -18,7 +18,7 @@
use std::{fs, io, path::PathBuf};
-use crate::modules::error::BichonResult;
+use crate::error::BichonResult;
use base64::engine::general_purpose::STANDARD;
use base64::{engine::general_purpose, Engine};
use rand::{rng, RngExt};
@@ -104,7 +104,7 @@ macro_rules! license_header {
#[macro_export]
macro_rules! raise_error {
($msg:expr, $code:expr) => {
- $crate::modules::error::BichonError::Generic {
+ $crate::error::BichonError::Generic {
message: $msg,
code: $code,
location: snafu::location!(),
@@ -134,7 +134,7 @@ macro_rules! free_memory {
#[macro_export]
macro_rules! generate_token {
($bit_strength:expr) => {{
- $crate::modules::utils::generate_token_impl($bit_strength)
+ $crate::utils::generate_token_impl($bit_strength)
}};
}
@@ -169,7 +169,7 @@ fn make_single_random_char() -> char {
#[macro_export]
macro_rules! ensure_access {
($dir:expr) => {{
- $crate::modules::utils::ensure_dir_and_test_access($dir)
+ $crate::utils::ensure_dir_and_test_access($dir)
}};
}
@@ -208,25 +208,25 @@ macro_rules! current_datetime {
#[macro_export]
macro_rules! validate_email {
($email:expr) => {{
- $crate::modules::utils::validate_email($email)
+ $crate::utils::validate_email($email)
}};
}
#[macro_export]
macro_rules! encrypt {
($plaintext:expr) => {{
- $crate::modules::utils::encrypt::encrypt_string($plaintext)
+ $crate::utils::encrypt::encrypt_string($plaintext)
}};
}
#[macro_export]
macro_rules! decrypt {
($plaintext:expr) => {{
- $crate::modules::utils::encrypt::decrypt_string($plaintext)
+ $crate::utils::encrypt::decrypt_string($plaintext)
}};
}
-pub fn validate_email(email: &str) -> crate::modules::error::BichonResult<()> {
+pub fn validate_email(email: &str) -> crate::error::BichonResult<()> {
use std::str::FromStr;
let email_address = email_address::EmailAddress::from_str(email).map_err(|_| {
raise_error!(
@@ -247,9 +247,9 @@ pub fn validate_email(email: &str) -> crate::modules::error::BichonResult<()> {
macro_rules! id {
($bit_strength:expr) => {{
// Generate a token with the given bit strength
- let token = $crate::modules::utils::generate_token_impl($bit_strength);
+ let token = $crate::utils::generate_token_impl($bit_strength);
// Hash the generated token
- $crate::modules::utils::hash(&token)
+ $crate::utils::hash(&token)
}};
}
diff --git a/src/modules/utils/net.rs b/crates/core/src/utils/net.rs
similarity index 96%
rename from src/modules/utils/net.rs
rename to crates/core/src/utils/net.rs
index 73914d1..31f8543 100644
--- a/src/modules/utils/net.rs
+++ b/crates/core/src/utils/net.rs
@@ -16,11 +16,11 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::error::code::ErrorCode;
-use crate::modules::settings::proxy::Proxy;
-use crate::modules::utils::tls::establish_tls_stream;
-use crate::modules::{error::BichonResult, imap::session::SessionStream};
+use crate::error::code::ErrorCode;
use crate::raise_error;
+use crate::settings::proxy::Proxy;
+use crate::utils::tls::establish_tls_stream;
+use crate::{error::BichonResult, imap::session::SessionStream};
use std::net::SocketAddr;
use std::pin::Pin;
use std::time::Duration;
diff --git a/src/modules/utils/rate_limit/mod.rs b/crates/core/src/utils/rate_limit/mod.rs
similarity index 98%
rename from src/modules/utils/rate_limit/mod.rs
rename to crates/core/src/utils/rate_limit/mod.rs
index 7768fa6..bdea0bf 100644
--- a/src/modules/utils/rate_limit/mod.rs
+++ b/crates/core/src/utils/rate_limit/mod.rs
@@ -29,7 +29,7 @@ use std::{
time::Duration,
};
-use crate::modules::users::acl::RateLimit;
+use crate::users::acl::RateLimit;
pub static RATE_LIMITER_MANAGER: LazyLock = LazyLock::new(UserRateLimiter::new);
diff --git a/src/modules/utils/shutdown.rs b/crates/core/src/utils/shutdown.rs
similarity index 100%
rename from src/modules/utils/shutdown.rs
rename to crates/core/src/utils/shutdown.rs
diff --git a/src/modules/utils/tls.rs b/crates/core/src/utils/tls.rs
similarity index 99%
rename from src/modules/utils/tls.rs
rename to crates/core/src/utils/tls.rs
index 39fd1fb..061c24b 100644
--- a/src/modules/utils/tls.rs
+++ b/crates/core/src/utils/tls.rs
@@ -17,11 +17,11 @@
// along with this program. If not, see .
use crate::{
- modules::{
+ raise_error,
+ {
error::{code::ErrorCode, BichonResult},
imap::session::SessionStream,
},
- raise_error,
};
use rustls::{
client::danger::{ServerCertVerified, ServerCertVerifier},
diff --git a/src/modules/version/mod.rs b/crates/core/src/version/mod.rs
similarity index 89%
rename from src/modules/version/mod.rs
rename to crates/core/src/version/mod.rs
index f188c90..8400107 100644
--- a/src/modules/version/mod.rs
+++ b/crates/core/src/version/mod.rs
@@ -16,13 +16,13 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
-use poem_openapi::Object;
+//use poem_openapi::Object;
use serde::{Deserialize, Serialize};
-use crate::{modules::error::BichonResult, bichon_version};
+use crate::{bichon_version, error::BichonResult};
-#[derive(Debug, Serialize, Deserialize, Object)]
+#[derive(Debug, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct ReleaseNotification {
/// Details of the latest release, if available. `None` if no release data is available.
pub latest: Option,
@@ -32,7 +32,8 @@ pub struct ReleaseNotification {
pub error_message: Option,
}
-#[derive(Debug, Serialize, Deserialize, Object)]
+#[derive(Debug, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct Release {
/// The tag name of the release (e.g., "v1.2.3").
pub tag_name: String,
@@ -44,7 +45,8 @@ pub struct Release {
pub html_url: String,
}
-#[derive(Debug, Serialize, Deserialize, Object)]
+#[derive(Debug, Serialize, Deserialize)]
+#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct Notifications {
pub release: ReleaseNotification,
}
@@ -105,7 +107,7 @@ async fn check_new_release(owner: &str, repo: &str, current_version: &str) -> Re
#[cfg(test)]
mod test {
- use crate::{modules::version::check_new_release, bichon_version};
+ use crate::{bichon_version, version::check_new_release};
#[tokio::test]
async fn test() {
diff --git a/crates/server/Cargo.toml b/crates/server/Cargo.toml
new file mode 100644
index 0000000..a2105ff
--- /dev/null
+++ b/crates/server/Cargo.toml
@@ -0,0 +1,33 @@
+[package]
+name = "bichon-server"
+version.workspace = true
+edition.workspace = true
+
+
+[dependencies]
+bichon-core = { path = "../core", features = ["web-api"] }
+bichon-smtp = { path = "../smtp" }
+poem = { version = "3.1.12", features = ["embed", "compression", "rustls"] }
+poem-derive = "3.1.12"
+poem-openapi = { version = "5.1.16", features = [
+ "openapi-explorer",
+ "rapidoc",
+ "scalar",
+ "redoc",
+ "swagger-ui",
+ "email",
+] }
+rust-embed = "8.11.0"
+email_address.workspace = true
+tantivy.workspace = true
+serde.workspace = true
+serde_json.workspace = true
+governor.workspace = true
+snafu.workspace = true
+timeago.workspace = true
+chrono.workspace = true
+tracing.workspace = true
+tokio.workspace = true
+http.workspace = true
+urlencoding.workspace = true
+mimalloc.workspace = true
diff --git a/build.rs b/crates/server/build.rs
similarity index 100%
rename from build.rs
rename to crates/server/build.rs
diff --git a/crates/server/src/common/auth.rs b/crates/server/src/common/auth.rs
new file mode 100644
index 0000000..bf74e5d
--- /dev/null
+++ b/crates/server/src/common/auth.rs
@@ -0,0 +1,155 @@
+//
+// Copyright (c) 2025-2026 rustmailer.com (https://rustmailer.com)
+//
+// This file is part of the Bichon Email Archiving Project
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use bichon_core::{
+ common::auth::ClientContext, error::code::ErrorCode, token::AccessTokenModel,
+ utils::rate_limit::RATE_LIMITER_MANAGER,
+};
+use governor::clock::{Clock, QuantaClock};
+use poem::{
+ web::{
+ headers::{authorization::Bearer, Authorization, HeaderMapExt},
+ RealIp,
+ },
+ Endpoint, FromRequest, Middleware, Request, RequestBody, Result,
+};
+use serde::Deserialize;
+use std::{ops::Deref, sync::Arc};
+
+use super::create_api_error_response;
+
+pub struct ApiGuard;
+
+pub struct ApiGuardEndpoint {
+ ep: E,
+}
+
+impl Middleware for ApiGuard {
+ type Output = ApiGuardEndpoint;
+
+ fn transform(&self, ep: E) -> Self::Output {
+ ApiGuardEndpoint { ep }
+ }
+}
+
+#[derive(Deserialize)]
+struct Param {
+ access_token: String,
+}
+
+impl Endpoint for ApiGuardEndpoint {
+ type Output = E::Output;
+
+ async fn call(&self, mut req: Request) -> Result {
+ let context = authorize_access(&req).await?;
+ req.set_data(Arc::new(context));
+ self.ep.call(req).await
+ }
+}
+
+pub struct WrappedContext(pub ClientContext);
+
+impl Deref for WrappedContext {
+ type Target = ClientContext;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<'a> FromRequest<'a> for WrappedContext {
+ async fn from_request(req: &'a Request, _body: &mut RequestBody) -> Result {
+ let ctx = extract_client_context(req).await?;
+ Ok(WrappedContext(ctx))
+ }
+}
+
+pub async fn extract_client_context(req: &Request) -> Result {
+ let ip_addr = RealIp::from_request_without_body(req)
+ .await
+ .map_err(|_| {
+ create_api_error_response(
+ "Failed to parse client IP address",
+ ErrorCode::InvalidParameter,
+ )
+ })?
+ .0
+ .ok_or_else(|| {
+ create_api_error_response(
+ "Failed to parse client IP address",
+ ErrorCode::InvalidParameter,
+ )
+ })?;
+ // Extract access token from Bearer header or query params
+ let bearer = req
+ .headers()
+ .typed_get::>()
+ .map(|auth| auth.0.token().to_string())
+ .or_else(|| req.params::().ok().map(|param| param.access_token));
+
+ let token = bearer.ok_or_else(|| {
+ create_api_error_response("Valid access token not found", ErrorCode::PermissionDenied)
+ })?;
+
+ // Validate and update access token
+ let user = AccessTokenModel::resolve_user_from_token(&token)
+ .await
+ .map_err(|e| {
+ create_api_error_response(&format!("{:#?}", e), ErrorCode::PermissionDenied)
+ })?;
+
+ return Ok(ClientContext {
+ ip_addr: Some(ip_addr),
+ user,
+ });
+}
+
+pub async fn authorize_access(req: &Request) -> Result {
+ let context = extract_client_context(&req).await?;
+ if let Some(access_control) = &context.user.acl {
+ if let Some(ip_addr) = context.ip_addr {
+ if let Some(whitelist) = &access_control.ip_whitelist {
+ if !whitelist.contains(&ip_addr.to_string()) {
+ return Err(create_api_error_response(
+ &format!("IP {} not in whitelist", ip_addr),
+ ErrorCode::Forbidden,
+ ));
+ }
+ }
+ }
+
+ if let Some(rate_limit) = &access_control.rate_limit {
+ if let Err(not_until) = RATE_LIMITER_MANAGER
+ .check(context.user.id, rate_limit.clone())
+ .await
+ {
+ let wait_duration = not_until.wait_time_from(QuantaClock::default().now());
+ return Err(create_api_error_response(
+ &format!(
+ "Rate limit: {}/{}s. Retry after {}s",
+ rate_limit.quota,
+ rate_limit.interval,
+ wait_duration.as_secs()
+ ),
+ ErrorCode::TooManyRequest,
+ ));
+ }
+ }
+ }
+
+ Ok(context)
+}
diff --git a/src/modules/common/error.rs b/crates/server/src/common/error.rs
similarity index 96%
rename from src/modules/common/error.rs
rename to crates/server/src/common/error.rs
index 2553641..5cec0b0 100644
--- a/src/modules/common/error.rs
+++ b/crates/server/src/common/error.rs
@@ -19,7 +19,7 @@
use poem::{Endpoint, IntoResponse, Middleware, Request, Response, Result};
-use crate::modules::error::handler::error_handler;
+use crate::error::handler::error_handler;
pub struct ErrorCapture;
diff --git a/src/modules/common/log.rs b/crates/server/src/common/log.rs
similarity index 100%
rename from src/modules/common/log.rs
rename to crates/server/src/common/log.rs
diff --git a/crates/server/src/common/mod.rs b/crates/server/src/common/mod.rs
new file mode 100644
index 0000000..7119cff
--- /dev/null
+++ b/crates/server/src/common/mod.rs
@@ -0,0 +1,108 @@
+//
+// Copyright (c) 2025-2026 rustmailer.com (https://rustmailer.com)
+//
+// This file is part of the Bichon Email Archiving Project
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use std::fmt;
+
+use bichon_core::error::code::ErrorCode;
+use bichon_core::error::BichonError;
+use poem::error::ResponseError;
+use poem::Body;
+use poem::{http::StatusCode, Error, Response};
+use tracing::error;
+
+use crate::error::code::IntoStatusCode;
+
+pub mod auth;
+pub mod error;
+pub mod log;
+pub mod status;
+pub mod timeout;
+pub mod tls;
+pub mod validator;
+
+#[derive(Debug)]
+pub struct BichonServerError(pub BichonError);
+
+impl fmt::Display for BichonServerError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "Internal Server Error: {:?}", self.0)
+ }
+}
+
+impl std::error::Error for BichonServerError {}
+
+impl From for BichonServerError {
+ fn from(err: BichonError) -> Self {
+ BichonServerError(err)
+ }
+}
+
+#[inline]
+fn create_rust_mailer_error(message: &str, code: ErrorCode) -> BichonServerError {
+ BichonError::Generic {
+ message: message.into(),
+ location: snafu::location!(),
+ code,
+ }
+ .into()
+}
+
+#[inline]
+pub fn create_api_error_response(message: &str, code: ErrorCode) -> Error {
+ let rust_mailer_error = create_rust_mailer_error(message, code);
+ rust_mailer_error.into()
+}
+
+impl ResponseError for BichonServerError {
+ fn status(&self) -> StatusCode {
+ match self.0 {
+ BichonError::Generic {
+ message: _,
+ location: _,
+ code,
+ } => code.status(),
+ }
+ }
+
+ fn as_response(&self) -> Response
+ where
+ Self: std::error::Error + Send + Sync + 'static,
+ {
+ match &self.0 {
+ BichonError::Generic {
+ message,
+ location,
+ code,
+ } => {
+ error!(
+ error_code = code.to_u32(),
+ error_message = %message,
+ error_location = ?location
+ );
+
+ let body = Body::from_json(serde_json::json!({
+ "code": code.to_u32(),
+ "message": message.to_string(),
+ }))
+ .unwrap();
+
+ Response::builder().status(self.status()).body(body)
+ }
+ }
+ }
+}
diff --git a/src/modules/context/status.rs b/crates/server/src/common/status.rs
similarity index 97%
rename from src/modules/context/status.rs
rename to crates/server/src/common/status.rs
index 0a7ff85..7013418 100644
--- a/src/modules/context/status.rs
+++ b/crates/server/src/common/status.rs
@@ -17,7 +17,7 @@
// along with this program. If not, see .
-use crate::modules::context::executors::BICHON_CONTEXT;
+use bichon_core::context::executors::BICHON_CONTEXT;
use chrono::Local;
use poem_openapi::Object;
use serde::Deserialize;
diff --git a/src/modules/common/timeout.rs b/crates/server/src/common/timeout.rs
similarity index 98%
rename from src/modules/common/timeout.rs
rename to crates/server/src/common/timeout.rs
index 6ff2446..5448dcd 100644
--- a/src/modules/common/timeout.rs
+++ b/crates/server/src/common/timeout.rs
@@ -16,13 +16,11 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
+use bichon_core::error::code::ErrorCode;
use poem::{Endpoint, Middleware, Request, Result};
use std::time::Duration;
use tracing::error;
-use crate::modules::error::code::ErrorCode;
-
use super::create_api_error_response;
pub const TIMEOUT_HEADER: &str = "X-Bichon-Timeout-Seconds";
diff --git a/src/modules/common/tls.rs b/crates/server/src/common/tls.rs
similarity index 98%
rename from src/modules/common/tls.rs
rename to crates/server/src/common/tls.rs
index 1577024..f3fbc17 100644
--- a/src/modules/common/tls.rs
+++ b/crates/server/src/common/tls.rs
@@ -16,15 +16,13 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
use poem::listener::{RustlsCertificate, RustlsConfig};
-
-use crate::{
- modules::{
+use bichon_core::{
+ raise_error,
+ {
error::{code::ErrorCode, BichonResult},
settings::dir::DATA_DIR_MANAGER,
},
- raise_error,
};
pub fn rustls_config() -> BichonResult {
diff --git a/src/modules/common/validator.rs b/crates/server/src/common/validator.rs
similarity index 100%
rename from src/modules/common/validator.rs
rename to crates/server/src/common/validator.rs
diff --git a/src/modules/error/code.rs b/crates/server/src/error/code.rs
similarity index 64%
rename from src/modules/error/code.rs
rename to crates/server/src/error/code.rs
index a121ca5..a153d0b 100644
--- a/src/modules/error/code.rs
+++ b/crates/server/src/error/code.rs
@@ -16,50 +16,15 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
+use bichon_core::error::code::ErrorCode;
use poem::http::StatusCode;
-use poem_openapi::Enum;
-#[derive(Copy, Clone, Debug, Enum, Eq, PartialEq)]
-#[repr(u32)]
-pub enum ErrorCode {
- // Client-side errors (10000–10999)
- InvalidParameter = 10000,
- MissingConfiguration = 10020,
- Incompatible = 10030,
- PayloadTooLarge = 10070,
- RequestTimeout = 10080,
- MethodNotAllowed = 10090,
-
- // Authentication and authorization errors (20000–20999)
- PermissionDenied = 20000,
- AccountDisabled = 20010,
- Forbidden = 20020,
- OAuth2ItemDisabled = 20050,
- MissingRefreshToken = 20060,
-
- // Resource errors (30000–30999)
- ResourceNotFound = 30000,
- TooManyRequest = 30020,
- AlreadyExists = 30030,
-
- // Network connection errors (40000–40999)
- NetworkError = 40000,
- ConnectionTimeout = 40010,
- ConnectionPoolTimeout = 40020,
- HttpResponseError = 40030,
-
- // Mail service errors (50000–50999)
- ImapCommandFailed = 50000,
- ImapAuthenticationFailed = 50010,
- ImapUnexpectedResult = 50020,
- AutoconfigFetchFailed = 50060,
- // Internal system errors (70000–70999)
- InternalError = 70000,
- UnhandledPoemError = 70010,
+pub trait IntoStatusCode {
+ fn status(&self) -> StatusCode;
}
-impl ErrorCode {
- pub fn status(&self) -> StatusCode {
+impl IntoStatusCode for ErrorCode {
+ fn status(&self) -> StatusCode {
match self {
ErrorCode::InvalidParameter
| ErrorCode::MissingConfiguration
diff --git a/src/modules/error/handler.rs b/crates/server/src/error/handler.rs
similarity index 95%
rename from src/modules/error/handler.rs
rename to crates/server/src/error/handler.rs
index ad0d412..7f65c24 100644
--- a/src/modules/error/handler.rs
+++ b/crates/server/src/error/handler.rs
@@ -16,11 +16,12 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
-use crate::modules::error::{code::ErrorCode, ApiError, ApiErrorResponse, BichonError};
+use bichon_core::error::{code::ErrorCode, BichonError};
use poem::IntoResponse;
use poem_openapi::payload::Json;
+use crate::error::{ApiError, ApiErrorResponse, code::IntoStatusCode};
+
pub async fn error_handler(error: poem::Error) -> impl poem::IntoResponse {
if error.is::() {
return error.into_response();
diff --git a/src/modules/error/mod.rs b/crates/server/src/error/mod.rs
similarity index 86%
rename from src/modules/error/mod.rs
rename to crates/server/src/error/mod.rs
index ba1da01..c035eb0 100644
--- a/src/modules/error/mod.rs
+++ b/crates/server/src/error/mod.rs
@@ -16,29 +16,15 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use code::ErrorCode;
+use crate::error::code::IntoStatusCode;
+use bichon_core::error::BichonError;
use poem::http::StatusCode;
use poem_openapi::{payload::Json, ApiResponse, Object};
-use snafu::{Location, Snafu};
use std::{fmt::Formatter, u32};
pub mod code;
pub mod handler;
-#[derive(Debug, Snafu)]
-#[snafu(visibility(pub))]
-pub enum BichonError {
- #[snafu(display("{message}"))]
- Generic {
- message: String,
- #[snafu(implicit)]
- location: Location,
- code: ErrorCode,
- },
-}
-
-pub type BichonResult = std::result::Result;
-
#[derive(Debug, Clone, Object)]
pub struct ApiError {
pub message: String,
diff --git a/src/main.rs b/crates/server/src/main.rs
similarity index 87%
rename from src/main.rs
rename to crates/server/src/main.rs
index b3ad707..0295905 100644
--- a/src/main.rs
+++ b/crates/server/src/main.rs
@@ -18,29 +18,36 @@
use std::sync::LazyLock;
-use bichon::{
- bichon_version,
- modules::{
+use bichon_core::{
+ bichon_version, raise_error,
+ {
cache::imap::task::SYNC_TASKS,
common::rustls::BichonTls,
- context::{Initialize, executors::BichonContext},
- error::{BichonResult, code::ErrorCode},
+ context::{executors::BichonContext, Initialize},
+ error::{code::ErrorCode, BichonResult},
logger,
- rest::start_http_server,
settings::cli::SETTINGS,
- smtp::{SmtpServer, start_smtp_server},
- store::{storage::BLOB_MANAGER, tantivy::{attachment::ATTACHMENT_MANAGER, envelope::ENVELOPE_MANAGER}},
+ store::{
+ storage::BLOB_MANAGER,
+ tantivy::{attachment::ATTACHMENT_MANAGER, envelope::ENVELOPE_MANAGER},
+ },
tasks::PeriodicTasks,
},
- raise_error,
};
+use bichon_smtp::server::{start_smtp_server, SmtpServer};
use mimalloc::MiMalloc;
use tracing::{error, info};
-use bichon::modules::{
+use bichon_core::{
common::signal::SignalManager, settings::dir::DataDirManager, users::manager::UserManager,
};
+use crate::rest::start_http_server;
+
+pub mod common;
+pub mod error;
+pub mod rest;
+
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;
diff --git a/src/modules/rest/api/access_token.rs b/crates/server/src/rest/api/access_token.rs
similarity index 87%
rename from src/modules/rest/api/access_token.rs
rename to crates/server/src/rest/api/access_token.rs
index ad239c7..7c3ed6f 100644
--- a/src/modules/rest/api/access_token.rs
+++ b/crates/server/src/rest/api/access_token.rs
@@ -16,12 +16,12 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::modules::common::auth::ClientContext;
-use crate::modules::rest::api::ApiTags;
-use crate::modules::rest::ApiResult;
-use crate::modules::token::view::AccessTokenResp;
-use crate::modules::users::permissions::Permission;
-use crate::modules::{token::payload::AccessTokenCreateRequest, token::AccessTokenModel};
+use crate::common::auth::WrappedContext;
+use crate::rest::api::ApiTags;
+use crate::rest::ApiResult;
+use bichon_core::token::view::AccessTokenResp;
+use bichon_core::users::permissions::Permission;
+use bichon_core::{token::payload::AccessTokenCreateRequest, token::AccessTokenModel};
use poem_openapi::payload::PlainText;
use poem_openapi::{param::Path, payload::Json, OpenApi};
@@ -36,7 +36,7 @@ impl AccessTokenApi {
)]
async fn list_access_tokens(
&self,
- context: ClientContext,
+ context: WrappedContext,
) -> ApiResult>> {
context
.require_permission(None, Permission::TOKEN_MANAGE)
@@ -55,7 +55,7 @@ impl AccessTokenApi {
&self,
/// The access token to be deleted
token: Path,
- context: ClientContext,
+ context: WrappedContext,
) -> ApiResult<()> {
let token = token.0.trim();
let token = AccessTokenModel::get_token(token).await?;
@@ -76,7 +76,7 @@ impl AccessTokenApi {
)]
async fn create_access_token(
&self,
- context: ClientContext,
+ context: WrappedContext,
/// The request payload
payload: Json,
) -> ApiResult> {
diff --git a/src/modules/rest/api/account.rs b/crates/server/src/rest/api/account.rs
similarity index 90%
rename from src/modules/rest/api/account.rs
rename to crates/server/src/rest/api/account.rs
index 033d94f..99a74df 100644
--- a/src/modules/rest/api/account.rs
+++ b/crates/server/src/rest/api/account.rs
@@ -16,25 +16,23 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use std::collections::{HashMap, HashSet};
-
-use crate::modules::account::grant::BatchAccountRoleRequest;
-use crate::modules::account::migration::AccountModel;
-use crate::modules::account::payload::{
+use crate::common::auth::WrappedContext;
+use crate::rest::api::ApiTags;
+use crate::rest::ApiResult;
+use bichon_core::account::grant::BatchAccountRoleRequest;
+use bichon_core::account::migration::AccountModel;
+use bichon_core::account::payload::{
filter_accessible_accounts, AccountCreateRequest, AccountUpdateRequest, MinimalAccount,
};
-use crate::modules::account::state::DownloadState;
-use crate::modules::account::view::AccountResp;
-use crate::modules::common::auth::ClientContext;
-use crate::modules::common::paginated::paginate_vec;
-use crate::modules::rest::api::ApiTags;
-use crate::modules::rest::response::DataPage;
-use crate::modules::rest::ApiResult;
-use crate::modules::users::permissions::Permission;
-use crate::modules::users::UserModel;
+use bichon_core::account::state::DownloadState;
+use bichon_core::account::view::AccountResp;
+use bichon_core::common::paginated::{paginate_vec, DataPage};
+use bichon_core::users::permissions::Permission;
+use bichon_core::users::UserModel;
use poem_openapi::param::{Path, Query};
use poem_openapi::payload::Json;
use poem_openapi::OpenApi;
+use std::collections::{HashMap, HashSet};
pub struct AccountApi;
@@ -50,7 +48,7 @@ impl AccountApi {
&self,
/// The account ID to retrieve
account_id: Path,
- context: ClientContext,
+ context: WrappedContext,
) -> ApiResult> {
let account_id = account_id.0;
context
@@ -69,7 +67,7 @@ impl AccountApi {
&self,
/// The account ID to delete
account_id: Path,
- context: ClientContext,
+ context: WrappedContext,
) -> ApiResult<()> {
let account_id = account_id.0;
context
@@ -84,7 +82,7 @@ impl AccountApi {
&self,
/// Account creation request payload
payload: Json,
- context: ClientContext,
+ context: WrappedContext,
) -> ApiResult> {
context
.require_permission(None, Permission::ACCOUNT_CREATE)
@@ -105,7 +103,7 @@ impl AccountApi {
account_id: Path,
/// Account update request payload
payload: Json,
- context: ClientContext,
+ context: WrappedContext,
) -> ApiResult<()> {
let account_id = account_id.0;
context
@@ -124,7 +122,7 @@ impl AccountApi {
page_size: Query