Compare commits

..

1 Commits

Author SHA1 Message Date
houseme
9aebef31ff refactor(admin/event): optimize notification target routing and logic handling (#463)
* add

* fix

* add target arns list

* improve code for arns

* upgrade crates version

* fix

* improve import code mod.rs

* fix

* improve

* improve code

* improve code

* fix

* fmt
2025-08-27 09:39:25 +08:00
8 changed files with 448 additions and 201 deletions

254
Cargo.lock generated
View File

@@ -420,7 +420,7 @@ dependencies = [
"memchr",
"num",
"regex",
"regex-syntax 0.8.5",
"regex-syntax 0.8.6",
]
[[package]]
@@ -707,9 +707,9 @@ dependencies = [
[[package]]
name = "aws-sdk-sts"
version = "1.83.0"
version = "1.84.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5468593c47efc31fdbe6c902d1a5fde8d9c82f78a3f8ccfe907b1e9434748cb"
checksum = "91abcdbfb48c38a0419eb75e0eac772a4783a96750392680e4f3c25a8a0535b9"
dependencies = [
"aws-credential-types",
"aws-runtime",
@@ -1089,7 +1089,7 @@ version = "0.69.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"cexpr",
"clang-sys",
"itertools 0.12.1",
@@ -1114,9 +1114,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.9.2"
version = "2.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29"
checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
[[package]]
name = "blake2"
@@ -1299,7 +1299,7 @@ dependencies = [
"serde",
"serde-untagged",
"serde-value",
"thiserror 2.0.15",
"thiserror 2.0.16",
"toml",
"unicode-xid",
"url",
@@ -1317,7 +1317,7 @@ dependencies = [
"semver",
"serde",
"serde_json",
"thiserror 2.0.15",
"thiserror 2.0.16",
]
[[package]]
@@ -1328,9 +1328,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.2.33"
version = "1.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f"
checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc"
dependencies = [
"jobserver",
"libc",
@@ -1348,9 +1348,9 @@ dependencies = [
[[package]]
name = "cfg-if"
version = "1.0.1"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "cfg_aliases"
@@ -1865,12 +1865,12 @@ dependencies = [
[[package]]
name = "darling"
version = "0.21.2"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08440b3dd222c3d0433e63e097463969485f112baff337dfdaca043a0d760570"
checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0"
dependencies = [
"darling_core 0.21.2",
"darling_macro 0.21.2",
"darling_core 0.21.3",
"darling_macro 0.21.3",
]
[[package]]
@@ -1889,9 +1889,9 @@ dependencies = [
[[package]]
name = "darling_core"
version = "0.21.2"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d25b7912bc28a04ab1b7715a68ea03aaa15662b43a1a4b2c480531fd19f8bf7e"
checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4"
dependencies = [
"fnv",
"ident_case",
@@ -1914,11 +1914,11 @@ dependencies = [
[[package]]
name = "darling_macro"
version = "0.21.2"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce154b9bea7fb0c8e8326e62d00354000c36e79770ff21b8c84e3aa267d9d531"
checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
dependencies = [
"darling_core 0.21.2",
"darling_core 0.21.3",
"quote",
"syn 2.0.106",
]
@@ -2311,7 +2311,7 @@ dependencies = [
"log",
"recursive",
"regex",
"regex-syntax 0.8.5",
"regex-syntax 0.8.6",
]
[[package]]
@@ -2654,20 +2654,20 @@ dependencies = [
[[package]]
name = "enumset"
version = "1.1.9"
version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f50acec76c668b4621fe3694e5ddee53c8fae2a03410026f50947d195eb44dc1"
checksum = "25b07a8dfbbbfc0064c0a6bdf9edcf966de6b1c33ce344bdeca3b41615452634"
dependencies = [
"enumset_derive",
]
[[package]]
name = "enumset_derive"
version = "0.13.1"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "588eaef9dbc5d72c5fa4edf162527e67dab5d14ba61519ef7c8e233d5bdc092c"
checksum = "f43e744e4ea338060faee68ed933e46e722fb7f3617e722a5772d7e856d8b3ce"
dependencies = [
"darling 0.21.2",
"darling 0.21.3",
"proc-macro2",
"quote",
"syn 2.0.106",
@@ -2752,14 +2752,14 @@ dependencies = [
[[package]]
name = "filetime"
version = "0.2.25"
version = "0.2.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586"
checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed"
dependencies = [
"cfg-if",
"libc",
"libredox",
"windows-sys 0.59.0",
"windows-sys 0.60.2",
]
[[package]]
@@ -2790,7 +2790,7 @@ version = "25.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1045398c1bfd89168b5fd3f1fc11f6e70b34f6f66300c87d44d3de849463abf1"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"rustc_version",
]
@@ -2819,7 +2819,7 @@ dependencies = [
"regex",
"serde",
"serde_derive",
"thiserror 2.0.15",
"thiserror 2.0.16",
"toml",
"tracing",
"tracing-subscriber",
@@ -2850,9 +2850,9 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "form_urlencoded"
version = "1.2.1"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
dependencies = [
"percent-encoding",
]
@@ -3484,9 +3484,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "1.0.3"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
dependencies = [
"idna_adapter",
"smallvec",
@@ -3505,9 +3505,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.10.0"
version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9"
dependencies = [
"equivalent",
"hashbrown 0.15.5",
@@ -3525,7 +3525,7 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"inotify-sys",
"libc",
]
@@ -3556,11 +3556,11 @@ checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02"
[[package]]
name = "io-uring"
version = "0.7.9"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"cfg-if",
"libc",
]
@@ -3637,9 +3637,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jobserver"
version = "0.1.33"
version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
dependencies = [
"getrandom 0.3.3",
"libc",
@@ -3797,7 +3797,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"libc",
"redox_syscall 0.5.17",
]
@@ -3816,7 +3816,7 @@ dependencies = [
"once_cell",
"serde",
"sha2 0.10.9",
"thiserror 2.0.15",
"thiserror 2.0.16",
"uuid",
]
@@ -3858,7 +3858,7 @@ checksum = "656b3b27f8893f7bbf9485148ff9a65f019e3f33bd5cdc87c83cab16b3fd9ec8"
dependencies = [
"libc",
"neli",
"thiserror 2.0.15",
"thiserror 2.0.16",
"windows-sys 0.59.0",
]
@@ -4082,7 +4082,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"cfg-if",
"cfg_aliases",
"libc",
@@ -4095,7 +4095,7 @@ version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"cfg-if",
"cfg_aliases",
"libc",
@@ -4126,7 +4126,7 @@ version = "8.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"fsevent-sys",
"inotify",
"kqueue",
@@ -4343,7 +4343,7 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d5c6c0ef9702176a570f06ad94f3198bc29c524c8b498f1b9346e1b1bdcbb3a"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"libloading",
"nvml-wrapper-sys",
"static_assertions",
@@ -4366,7 +4366,7 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
]
[[package]]
@@ -4449,7 +4449,7 @@ dependencies = [
"futures-sink",
"js-sys",
"pin-project-lite",
"thiserror 2.0.15",
"thiserror 2.0.16",
"tracing",
]
@@ -4478,7 +4478,7 @@ dependencies = [
"opentelemetry-proto",
"opentelemetry_sdk",
"prost 0.13.5",
"thiserror 2.0.15",
"thiserror 2.0.16",
"tokio",
"tonic 0.13.1",
"tracing",
@@ -4526,7 +4526,7 @@ dependencies = [
"percent-encoding",
"rand 0.9.2",
"serde_json",
"thiserror 2.0.15",
"thiserror 2.0.16",
"tokio",
"tokio-stream",
]
@@ -4729,9 +4729,9 @@ dependencies = [
[[package]]
name = "percent-encoding"
version = "2.3.1"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "petgraph"
@@ -5048,7 +5048,7 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"memchr",
"unicase",
]
@@ -5074,9 +5074,9 @@ dependencies = [
[[package]]
name = "quick-xml"
version = "0.38.1"
version = "0.38.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9845d9dccf565065824e69f9f235fafba1587031eda353c1f1561cd6a6be78f4"
checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89"
dependencies = [
"memchr",
"serde",
@@ -5097,7 +5097,7 @@ dependencies = [
"rustc-hash 2.1.1",
"rustls 0.23.31",
"socket2 0.5.10",
"thiserror 2.0.15",
"thiserror 2.0.16",
"tokio",
"tracing",
"web-time",
@@ -5118,7 +5118,7 @@ dependencies = [
"rustls 0.23.31",
"rustls-pki-types",
"slab",
"thiserror 2.0.15",
"thiserror 2.0.16",
"tinyvec",
"tracing",
"web-time",
@@ -5303,7 +5303,7 @@ version = "0.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
]
[[package]]
@@ -5314,7 +5314,7 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
dependencies = [
"getrandom 0.2.16",
"libredox",
"thiserror 2.0.15",
"thiserror 2.0.16",
]
[[package]]
@@ -5349,14 +5349,14 @@ dependencies = [
[[package]]
name = "regex"
version = "1.11.1"
version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata 0.4.9",
"regex-syntax 0.8.5",
"regex-automata 0.4.10",
"regex-syntax 0.8.6",
]
[[package]]
@@ -5370,20 +5370,20 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.4.9"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax 0.8.5",
"regex-syntax 0.8.6",
]
[[package]]
name = "regex-lite"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
checksum = "943f41321c63ef1c92fd763bfe054d2668f7f225a5c29f0105903dc2fc04ba30"
[[package]]
name = "regex-syntax"
@@ -5393,9 +5393,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.8.5"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
[[package]]
name = "reqwest"
@@ -5469,9 +5469,9 @@ dependencies = [
[[package]]
name = "rmcp"
version = "0.5.0"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2faf35b7d3c4b7f8c21c45bb014011b32a0ce6444bf6094da04daab01a8c3c34"
checksum = "bb21cd3555f1059f27e4813827338dec44429a08ecd0011acc41d9907b160c00"
dependencies = [
"base64 0.22.1",
"chrono",
@@ -5482,7 +5482,7 @@ dependencies = [
"schemars",
"serde",
"serde_json",
"thiserror 2.0.15",
"thiserror 2.0.16",
"tokio",
"tokio-util",
"tracing",
@@ -5490,11 +5490,11 @@ dependencies = [
[[package]]
name = "rmcp-macros"
version = "0.5.0"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad9720d9d2a943779f1dc3d47fa9072c7eeffaff4e1a82f67eb9f7ea52696091"
checksum = "ab5d16ae1ff3ce2c5fd86c37047b2869b75bec795d53a4b1d8257b15415a2354"
dependencies = [
"darling 0.21.2",
"darling 0.21.3",
"proc-macro2",
"quote",
"serde_json",
@@ -5676,7 +5676,7 @@ dependencies = [
"shadow-rs",
"socket2 0.6.0",
"sysctl",
"thiserror 2.0.15",
"thiserror 2.0.16",
"tikv-jemallocator",
"time",
"tokio",
@@ -5688,6 +5688,7 @@ dependencies = [
"tower",
"tower-http",
"tracing",
"url",
"urlencoding",
"uuid",
"zip",
@@ -5713,7 +5714,7 @@ dependencies = [
"serde_json",
"serial_test",
"tempfile",
"thiserror 2.0.15",
"thiserror 2.0.16",
"tokio",
"tokio-util",
"tracing",
@@ -5744,7 +5745,7 @@ dependencies = [
"rustfs-targets",
"serde",
"serde_json",
"thiserror 2.0.15",
"thiserror 2.0.16",
"tokio",
"tracing",
"tracing-core",
@@ -5805,7 +5806,7 @@ dependencies = [
"serde_json",
"sha2 0.10.9",
"test-case",
"thiserror 2.0.15",
"thiserror 2.0.16",
"time",
]
@@ -5841,7 +5842,7 @@ dependencies = [
"once_cell",
"path-absolutize",
"pin-project-lite",
"quick-xml 0.38.1",
"quick-xml 0.38.3",
"rand 0.9.2",
"reed-solomon-simd",
"regex",
@@ -5871,7 +5872,7 @@ dependencies = [
"smallvec",
"temp-env",
"tempfile",
"thiserror 2.0.15",
"thiserror 2.0.16",
"time",
"tokio",
"tokio-stream",
@@ -5899,7 +5900,7 @@ dependencies = [
"rustfs-utils",
"s3s",
"serde",
"thiserror 2.0.15",
"thiserror 2.0.16",
"time",
"tokio",
"tracing",
@@ -5924,7 +5925,7 @@ dependencies = [
"rustfs-utils",
"serde",
"serde_json",
"thiserror 2.0.15",
"thiserror 2.0.16",
"time",
"tokio",
"tracing",
@@ -5941,7 +5942,7 @@ dependencies = [
"rustfs-protos",
"serde",
"serde_json",
"thiserror 2.0.15",
"thiserror 2.0.16",
"tokio",
"tonic 0.14.1",
"tracing",
@@ -5989,7 +5990,7 @@ dependencies = [
"form_urlencoded",
"futures",
"once_cell",
"quick-xml 0.38.1",
"quick-xml 0.38.3",
"rumqttc",
"rustfs-config",
"rustfs-ecstore",
@@ -5997,7 +5998,7 @@ dependencies = [
"rustfs-utils",
"serde",
"serde_json",
"thiserror 2.0.15",
"thiserror 2.0.16",
"tokio",
"tracing",
"tracing-subscriber",
@@ -6028,7 +6029,7 @@ dependencies = [
"serde_json",
"smallvec",
"sysinfo",
"thiserror 2.0.15",
"thiserror 2.0.16",
"tokio",
"tracing",
"tracing-core",
@@ -6051,7 +6052,7 @@ dependencies = [
"serde_json",
"strum",
"test-case",
"thiserror 2.0.15",
"thiserror 2.0.16",
"time",
"tokio",
]
@@ -6183,7 +6184,7 @@ dependencies = [
"serde",
"serde_json",
"snap",
"thiserror 2.0.15",
"thiserror 2.0.16",
"tokio",
"tracing",
"url",
@@ -6258,7 +6259,7 @@ version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"errno",
"libc",
"linux-raw-sys 0.4.15",
@@ -6271,7 +6272,7 @@ version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"errno",
"libc",
"linux-raw-sys 0.9.4",
@@ -6471,7 +6472,7 @@ dependencies = [
"smallvec",
"std-next",
"sync_wrapper",
"thiserror 2.0.15",
"thiserror 2.0.16",
"time",
"tokio",
"tower",
@@ -6576,7 +6577,7 @@ version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"core-foundation 0.9.4",
"core-foundation-sys",
"libc",
@@ -6589,7 +6590,7 @@ version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"core-foundation 0.10.1",
"core-foundation-sys",
"libc",
@@ -6893,7 +6894,7 @@ checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb"
dependencies = [
"num-bigint",
"num-traits",
"thiserror 2.0.15",
"thiserror 2.0.16",
"time",
]
@@ -6920,9 +6921,9 @@ dependencies = [
[[package]]
name = "snafu"
version = "0.8.6"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320b01e011bf8d5d7a4a4a4be966d9160968935849c83b918827f6a435e7f627"
checksum = "0062a372b26c4a6e9155d099a3416d732514fd47ae2f235b3695b820afcee74a"
dependencies = [
"backtrace",
"snafu-derive",
@@ -6930,9 +6931,9 @@ dependencies = [
[[package]]
name = "snafu-derive"
version = "0.8.6"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1961e2ef424c1424204d3a5d6975f934f56b6d50ff5732382d84ebf460e147f7"
checksum = "7e5fd9e3263fc19d73abd5107dbd4d43e37949212d2b15d4d334ee5db53022b8"
dependencies = [
"heck",
"proc-macro2",
@@ -7049,7 +7050,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04082e93ed1a06debd9148c928234b46d2cf260bc65f44e1d1d3fa594c5beebc"
dependencies = [
"simdutf8",
"thiserror 2.0.15",
"thiserror 2.0.16",
]
[[package]]
@@ -7211,7 +7212,7 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01198a2debb237c62b6826ec7081082d951f46dbb64b0e8c7649a452230d1dfc"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"byteorder",
"enum-as-inner",
"libc",
@@ -7239,7 +7240,7 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
"core-foundation 0.9.4",
"system-configuration-sys",
]
@@ -7265,15 +7266,15 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.20.0"
version = "3.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e"
dependencies = [
"fastrand",
"getrandom 0.3.3",
"once_cell",
"rustix 1.0.8",
"windows-sys 0.59.0",
"windows-sys 0.60.2",
]
[[package]]
@@ -7320,11 +7321,11 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.15"
version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850"
checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
dependencies = [
"thiserror-impl 2.0.15",
"thiserror-impl 2.0.16",
]
[[package]]
@@ -7340,9 +7341,9 @@ dependencies = [
[[package]]
name = "thiserror-impl"
version = "2.0.15"
version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0"
checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
dependencies = [
"proc-macro2",
"quote",
@@ -7744,7 +7745,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
dependencies = [
"async-compression",
"bitflags 2.9.2",
"bitflags 2.9.3",
"bytes",
"futures-core",
"futures-util",
@@ -8003,13 +8004,14 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "url"
version = "2.5.4"
version = "2.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
"serde",
]
[[package]]
@@ -8301,11 +8303,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.9"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22"
dependencies = [
"windows-sys 0.59.0",
"windows-sys 0.60.2",
]
[[package]]
@@ -8594,9 +8596,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "winnow"
version = "0.7.12"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
dependencies = [
"memchr",
]
@@ -8607,7 +8609,7 @@ version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
dependencies = [
"bitflags 2.9.2",
"bitflags 2.9.3",
]
[[package]]
@@ -8811,7 +8813,7 @@ dependencies = [
"memchr",
"pbkdf2",
"sha1 0.10.6",
"thiserror 2.0.15",
"thiserror 2.0.16",
"time",
"xz2",
"zeroize",

View File

@@ -106,7 +106,7 @@ brotli = "8.0.2"
bytes = { version = "1.10.1", features = ["serde"] }
bytesize = "2.0.1"
byteorder = "1.5.0"
cfg-if = "1.0.1"
cfg-if = "1.0.3"
crc-fast = "1.4.0"
chacha20poly1305 = { version = "0.10.1" }
chrono = { version = "0.4.41", features = ["serde"] }
@@ -117,11 +117,11 @@ criterion = { version = "0.7", features = ["html_reports"] }
dashmap = "6.1.0"
datafusion = "46.0.1"
derive_builder = "0.20.2"
enumset = "1.1.9"
enumset = "1.1.10"
flatbuffers = "25.2.10"
flate2 = "1.1.2"
flexi_logger = { version = "0.31.2", features = ["trc", "dont_minimize_extra_stacks"] }
form_urlencoded = "1.2.1"
form_urlencoded = "1.2.2"
futures = "0.3.31"
futures-core = "0.3.31"
futures-util = "0.3.31"
@@ -175,15 +175,15 @@ path-absolutize = "3.1.1"
path-clean = "1.0.1"
blake3 = { version = "1.8.2" }
pbkdf2 = "0.12.2"
percent-encoding = "2.3.1"
percent-encoding = "2.3.2"
pin-project-lite = "0.2.16"
prost = "0.14.1"
pretty_assertions = "1.4.1"
quick-xml = "0.38.1"
quick-xml = "0.38.3"
rand = "0.9.2"
rdkafka = { version = "0.38.0", features = ["tokio"] }
reed-solomon-simd = { version = "3.0.1" }
regex = { version = "1.11.1" }
regex = { version = "1.11.2" }
reqwest = { version = "0.12.23", default-features = false, features = [
"rustls-tls",
"charset",
@@ -193,7 +193,7 @@ reqwest = { version = "0.12.23", default-features = false, features = [
"json",
"blocking",
] }
rmcp = { version = "0.5.0" }
rmcp = { version = "0.6.0" }
rmp = "0.8.14"
rmp-serde = "1.3.0"
rsa = "0.9.8"
@@ -214,16 +214,16 @@ sha2 = "0.10.9"
shadow-rs = { version = "1.2.1", default-features = false }
siphasher = "1.0.1"
smallvec = { version = "1.15.1", features = ["serde"] }
snafu = "0.8.6"
snafu = "0.8.7"
snap = "1.1.1"
socket2 = "0.6.0"
strum = { version = "0.27.2", features = ["derive"] }
sysinfo = "0.37.0"
sysctl = "0.6.0"
tempfile = "3.20.0"
tempfile = "3.21.0"
temp-env = "0.3.6"
test-case = "3.3.1"
thiserror = "2.0.15"
thiserror = "2.0.16"
time = { version = "0.3.41", features = [
"std",
"parsing",
@@ -248,7 +248,7 @@ tracing-error = "0.2.1"
tracing-opentelemetry = "0.31.0"
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "time"] }
transform-stream = "0.3.1"
url = "2.5.4"
url = "2.5.7"
urlencoding = "2.1.3"
uuid = { version = "1.18.0", features = [
"v4",

View File

@@ -27,7 +27,7 @@ pub const MQTT_QUEUE_LIMIT: &str = "queue_limit";
/// A list of all valid configuration keys for an MQTT target.
pub const NOTIFY_MQTT_KEYS: &[&str] = &[
ENABLE_KEY, // "enable" is a common key
ENABLE_KEY,
MQTT_BROKER,
MQTT_TOPIC,
MQTT_QOS,

View File

@@ -24,7 +24,7 @@ pub const WEBHOOK_CLIENT_KEY: &str = "client_key";
/// A list of all valid configuration keys for a webhook target.
pub const NOTIFY_WEBHOOK_KEYS: &[&str] = &[
ENABLE_KEY, // "enable" is a common key
ENABLE_KEY,
WEBHOOK_ENDPOINT,
WEBHOOK_AUTH_TOKEN,
WEBHOOK_QUEUE_LIMIT,

View File

@@ -103,6 +103,7 @@ tower-http = { workspace = true, features = [
"cors",
"catch-panic",
] }
url = { workspace = true }
urlencoding = { workspace = true }
uuid = { workspace = true }
zip = { workspace = true }

View File

@@ -27,15 +27,14 @@ use s3s::{Body, S3Error, S3ErrorCode, S3Request, S3Response, S3Result, header::C
use serde::{Deserialize, Serialize};
use serde_urlencoded::from_bytes;
use std::collections::HashMap;
use std::future::Future;
use std::io::{Error, ErrorKind};
use std::net::SocketAddr;
use std::path::Path;
use tokio::net::lookup_host;
use tokio::time::{Duration, sleep};
use tracing::{debug, error, info, warn};
#[derive(Debug, Deserialize)]
struct TargetQuery {
#[serde(rename = "targetType")]
target_type: String,
#[serde(rename = "targetName")]
target_name: String,
}
use url::Url;
#[derive(Debug, Deserialize)]
struct BucketQuery {
@@ -43,19 +42,104 @@ struct BucketQuery {
bucket_name: String,
}
/// Set (create or update) a notification target
pub struct SetNotificationTarget {}
#[async_trait::async_trait]
impl Operation for SetNotificationTarget {
async fn call(&self, req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
// 1. Analyze query parameters
let query: TargetQuery = from_bytes(req.uri.query().unwrap_or("").as_bytes())
.map_err(|e| s3_error!(InvalidArgument, "invalid query parameters: {}", e))?;
#[derive(Debug, Deserialize)]
pub struct KeyValue {
pub key: String,
pub value: String,
}
let target_type = query.target_type.to_lowercase();
if target_type != *NOTIFY_WEBHOOK_SUB_SYS && target_type != *NOTIFY_MQTT_SUB_SYS {
return Err(s3_error!(InvalidArgument, "unsupported target type: {}", query.target_type));
#[derive(Debug, Deserialize)]
pub struct NotificationTargetBody {
pub key_values: Vec<KeyValue>,
}
#[derive(Serialize, Debug)]
struct NotificationEndpoint {
account_id: String,
service: String,
status: String,
}
#[derive(Serialize, Debug)]
struct NotificationEndpointsResponse {
notification_endpoints: Vec<NotificationEndpoint>,
}
async fn retry_with_backoff<F, Fut, T>(mut operation: F, max_attempts: usize, base_delay: Duration) -> Result<T, Error>
where
F: FnMut() -> Fut,
Fut: Future<Output = Result<T, Error>>,
{
assert!(max_attempts > 0, "max_attempts must be greater than 0");
let mut attempts = 0;
let mut delay = base_delay;
let mut last_err = None;
while attempts < max_attempts {
match operation().await {
Ok(result) => return Ok(result),
Err(e) => {
last_err = Some(e);
attempts += 1;
if attempts < max_attempts {
warn!(
"Retry attempt {}/{} failed: {}. Retrying in {:?}",
attempts,
max_attempts,
last_err.as_ref().unwrap(),
delay
);
sleep(delay).await;
delay = delay.saturating_mul(2);
}
}
}
}
Err(last_err.unwrap_or_else(|| Error::other("retry_with_backoff: unknown error")))
}
async fn retry_metadata(path: &str) -> Result<(), Error> {
retry_with_backoff(|| async { tokio::fs::metadata(path).await.map(|_| ()) }, 3, Duration::from_millis(100)).await
}
async fn validate_queue_dir(queue_dir: &str) -> S3Result<()> {
if !queue_dir.is_empty() {
if !Path::new(queue_dir).is_absolute() {
return Err(s3_error!(InvalidArgument, "queue_dir must be absolute path"));
}
if let Err(e) = retry_metadata(queue_dir).await {
match e.kind() {
ErrorKind::NotFound => {
return Err(s3_error!(InvalidArgument, "queue_dir does not exist"));
}
ErrorKind::PermissionDenied => {
return Err(s3_error!(InvalidArgument, "queue_dir exists but permission denied"));
}
_ => {
return Err(s3_error!(InvalidArgument, "failed to access queue_dir: {}", e));
}
}
}
}
Ok(())
}
fn validate_cert_key_pair(cert: &Option<String>, key: &Option<String>) -> S3Result<()> {
if cert.is_some() != key.is_some() {
return Err(s3_error!(InvalidArgument, "client_cert and client_key must be specified as a pair"));
}
Ok(())
}
/// Set (create or update) a notification target
pub struct NotificationTarget {}
#[async_trait::async_trait]
impl Operation for NotificationTarget {
async fn call(&self, req: S3Request<Body>, params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
// 1. Analyze query parameters
let (target_type, target_name) = extract_target_params(&params)?;
// 2. Permission verification
let Some(input_cred) = &req.credentials else {
@@ -82,25 +166,119 @@ impl Operation for SetNotificationTarget {
kvs_map.insert(ENABLE_KEY.to_string(), EnableState::On.to_string());
}
let kvs = rustfs_ecstore::config::KVS(
kvs_map
.into_iter()
.map(|(key, value)| rustfs_ecstore::config::KV {
key,
value,
hidden_if_empty: false, // Set a default value
})
.collect(),
);
// 1. Get the allowed key range
let allowed_keys: std::collections::HashSet<&str> = match target_type {
NOTIFY_WEBHOOK_SUB_SYS => rustfs_config::notify::NOTIFY_WEBHOOK_KEYS.iter().cloned().collect(),
NOTIFY_MQTT_SUB_SYS => rustfs_config::notify::NOTIFY_MQTT_KEYS.iter().cloned().collect(),
_ => unreachable!(),
};
let notification_body: NotificationTargetBody = serde_json::from_slice(&body)
.map_err(|e| s3_error!(InvalidArgument, "invalid json body for target config: {}", e))?;
// 2. Filter and verify keys, and splice target_name
let mut kvs_vec = Vec::new();
let mut endpoint_val = None;
let mut queue_dir_val = None;
let mut client_cert_val = None;
let mut client_key_val = None;
let mut qos_val = None;
for kv in notification_body.key_values.iter() {
if !allowed_keys.contains(kv.key.as_str()) {
return Err(s3_error!(
InvalidArgument,
"key '{}' not allowed for target type '{}'",
kv.key,
target_type
));
}
if kv.key == "endpoint" {
endpoint_val = Some(kv.value.clone());
}
if kv.key == "queue_dir" {
queue_dir_val = Some(kv.value.clone());
}
if kv.key == "client_cert" {
client_cert_val = Some(kv.value.clone());
}
if kv.key == "client_key" {
client_key_val = Some(kv.value.clone());
}
if kv.key == "qos" {
qos_val = Some(kv.value.clone());
}
kvs_vec.push(rustfs_ecstore::config::KV {
key: kv.key.clone(),
value: kv.value.clone(),
hidden_if_empty: false,
});
}
if target_type == NOTIFY_WEBHOOK_SUB_SYS {
let endpoint = endpoint_val
.clone()
.ok_or_else(|| s3_error!(InvalidArgument, "endpoint is required"))?;
let url = Url::parse(&endpoint).map_err(|e| s3_error!(InvalidArgument, "invalid endpoint url: {}", e))?;
let host = url
.host_str()
.ok_or_else(|| s3_error!(InvalidArgument, "endpoint missing host"))?;
let port = url
.port_or_known_default()
.ok_or_else(|| s3_error!(InvalidArgument, "endpoint missing port"))?;
let addr = format!("{}:{}", host, port);
// First, try to parse as SocketAddr (IP:port)
if addr.parse::<SocketAddr>().is_err() {
// If not an IP:port, try DNS resolution
if lookup_host(&addr).await.is_err() {
return Err(s3_error!(InvalidArgument, "invalid or unresolvable endpoint address"));
}
}
if let Some(queue_dir) = queue_dir_val.clone() {
validate_queue_dir(&queue_dir).await?;
}
validate_cert_key_pair(&client_cert_val, &client_key_val)?;
}
if target_type == NOTIFY_MQTT_SUB_SYS {
let endpoint = endpoint_val.ok_or_else(|| s3_error!(InvalidArgument, "endpoint is required"))?;
let url = Url::parse(&endpoint).map_err(|e| s3_error!(InvalidArgument, "invalid endpoint url: {}", e))?;
match url.scheme() {
"tcp" | "ssl" | "ws" | "wss" | "mqtt" | "mqtts" => {}
_ => return Err(s3_error!(InvalidArgument, "unsupported broker url scheme")),
}
if let Some(queue_dir) = queue_dir_val {
validate_queue_dir(&queue_dir).await?;
if let Some(qos) = qos_val {
match qos.parse::<u8>() {
Ok(qos_int) if qos_int == 1 || qos_int == 2 => {}
Ok(0) => {
return Err(s3_error!(InvalidArgument, "qos should be 1 or 2 if queue_dir is set"));
}
_ => {
return Err(s3_error!(InvalidArgument, "qos must be an integer 0, 1, or 2"));
}
}
}
}
}
// 3. Add ENABLE_KEY
kvs_vec.push(rustfs_ecstore::config::KV {
key: ENABLE_KEY.to_string(),
value: EnableState::On.to_string(),
hidden_if_empty: false,
});
let kvs = rustfs_ecstore::config::KVS(kvs_vec);
// 5. Call notification system to set target configuration
info!("Setting target config for type '{}', name '{}'", &query.target_type, &query.target_name);
ns.set_target_config(&query.target_type, &query.target_name, kvs)
.await
.map_err(|e| {
error!("failed to set target config: {}", e);
S3Error::with_message(S3ErrorCode::InternalError, format!("failed to set target config: {e}"))
})?;
info!("Setting target config for type '{}', name '{}'", target_type, target_name);
ns.set_target_config(target_type, target_name, kvs).await.map_err(|e| {
error!("failed to set target config: {}", e);
S3Error::with_message(S3ErrorCode::InternalError, format!("failed to set target config: {e}"))
})?;
let mut header = HeaderMap::new();
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
@@ -131,20 +309,68 @@ impl Operation for ListNotificationTargets {
// 3. Get the list of activity targets
let active_targets = ns.get_active_targets().await;
debug!("ListNotificationTargets call found {} active targets", active_targets.len());
let mut notification_endpoints = Vec::new();
for target_id in active_targets.iter() {
notification_endpoints.push(NotificationEndpoint {
account_id: target_id.id.clone(),
service: target_id.name.to_string(),
status: "online".to_string(),
});
}
let response = NotificationEndpointsResponse { notification_endpoints };
// 4. Serialize and return the result
let data = serde_json::to_vec(&response).map_err(|e| {
error!("Failed to serialize notification targets response: {:?}", response);
S3Error::with_message(S3ErrorCode::InternalError, format!("failed to serialize targets: {e}"))
})?;
debug!("ListNotificationTargets call end, response data length: {}", data.len(),);
let mut header = HeaderMap::new();
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
Ok(S3Response::with_headers((StatusCode::OK, Body::from(data)), header))
}
}
/// Get a list of notification targets for all activities
pub struct ListTargetsArns {}
#[async_trait::async_trait]
impl Operation for ListTargetsArns {
async fn call(&self, req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
debug!("ListTargetsArns call start request params: {:?}", req.uri.query());
// 1. Permission verification
let Some(input_cred) = &req.credentials else {
return Err(s3_error!(InvalidRequest, "credentials not found"));
};
let (_cred, _owner) =
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
// 2. Get notification system instance
let Some(ns) = rustfs_notify::global::notification_system() else {
return Err(s3_error!(InternalError, "notification system not initialized"));
};
// 3. Get the list of activity targets
let active_targets = ns.get_active_targets().await;
debug!("ListTargetsArns call found {} active targets", active_targets.len());
let region = match req.region.clone() {
Some(region) => region,
None => return Err(s3_error!(InvalidRequest, "region not found")),
};
let mut data_target_arn_list = Vec::new();
for target_id in active_targets.iter() {
let target_arn = target_id.to_arn(&region);
data_target_arn_list.push(target_arn.to_string());
data_target_arn_list.push(target_id.to_arn(&region).to_string());
}
// 4. Serialize and return the result
let data = serde_json::to_vec(&data_target_arn_list)
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("failed to serialize targets: {e}")))?;
debug!("ListNotificationTargets call end, response data length: {}", data.len(),);
debug!("ListTargetsArns call end, response data length: {}", data.len(),);
let mut header = HeaderMap::new();
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
Ok(S3Response::with_headers((StatusCode::OK, Body::from(data)), header))
@@ -155,10 +381,9 @@ impl Operation for ListNotificationTargets {
pub struct RemoveNotificationTarget {}
#[async_trait::async_trait]
impl Operation for RemoveNotificationTarget {
async fn call(&self, req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
async fn call(&self, req: S3Request<Body>, params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
// 1. Analyze query parameters
let query: TargetQuery = from_bytes(req.uri.query().unwrap_or("").as_bytes())
.map_err(|e| s3_error!(InvalidArgument, "invalid query parameters: {}", e))?;
let (target_type, target_name) = extract_target_params(&params)?;
// 2. Permission verification
let Some(input_cred) = &req.credentials else {
@@ -173,13 +398,11 @@ impl Operation for RemoveNotificationTarget {
};
// 4. Call notification system to remove target configuration
info!("Removing target config for type '{}', name '{}'", &query.target_type, &query.target_name);
ns.remove_target_config(&query.target_type, &query.target_name)
.await
.map_err(|e| {
error!("failed to remove target config: {}", e);
S3Error::with_message(S3ErrorCode::InternalError, format!("failed to remove target config: {e}"))
})?;
info!("Removing target config for type '{}', name '{}'", target_type, target_name);
ns.remove_target_config(target_type, target_name).await.map_err(|e| {
error!("failed to remove target config: {}", e);
S3Error::with_message(S3ErrorCode::InternalError, format!("failed to remove target config: {e}"))
})?;
let mut header = HeaderMap::new();
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
@@ -188,6 +411,22 @@ impl Operation for RemoveNotificationTarget {
}
}
fn extract_param<'a>(params: &'a Params<'_, '_>, key: &str) -> S3Result<&'a str> {
params
.get(key)
.ok_or_else(|| s3_error!(InvalidArgument, "missing required parameter: '{}'", key))
}
fn extract_target_params<'a>(params: &'a Params<'_, '_>) -> S3Result<(&'a str, &'a str)> {
let target_type = extract_param(params, "target_type")?;
if target_type != NOTIFY_WEBHOOK_SUB_SYS && target_type != NOTIFY_MQTT_SUB_SYS {
return Err(s3_error!(InvalidArgument, "unsupported target type: '{}'", target_type));
}
let target_name = extract_param(params, "target_name")?;
Ok((target_type, target_name))
}
/// Set notification rules for buckets
pub struct SetBucketNotification {}
#[async_trait::async_trait]

View File

@@ -20,16 +20,15 @@ pub mod utils;
// use ecstore::global::{is_dist_erasure, is_erasure};
use handlers::{
bucket_meta, group, policies, pools, rebalance,
GetReplicationMetricsHandler, ListRemoteTargetHandler, RemoveRemoteTargetHandler, SetRemoteTargetHandler, bucket_meta,
event::{
GetBucketNotification, ListNotificationTargets, NotificationTarget, RemoveBucketNotification, RemoveNotificationTarget,
SetBucketNotification,
},
group, policies, pools, rebalance,
service_account::{AddServiceAccount, DeleteServiceAccount, InfoServiceAccount, ListServiceAccount, UpdateServiceAccount},
sts, tier, user,
};
use crate::admin::handlers::event::{
GetBucketNotification, ListNotificationTargets, RemoveBucketNotification, RemoveNotificationTarget, SetBucketNotification,
SetNotificationTarget,
};
use handlers::{GetReplicationMetricsHandler, ListRemoteTargetHandler, RemoveRemoteTargetHandler, SetRemoteTargetHandler};
use hyper::Method;
use router::{AdminOperation, S3Router};
use rpc::register_rpc_route;
@@ -371,14 +370,14 @@ fn register_user_route(r: &mut S3Router<AdminOperation>) -> std::io::Result<()>
r.insert(
Method::GET,
format!("{}{}", ADMIN_PREFIX, "/v3/target-list").as_str(),
format!("{}{}", ADMIN_PREFIX, "/v3/target/list").as_str(),
AdminOperation(&ListNotificationTargets {}),
)?;
r.insert(
Method::POST,
format!("{}{}", ADMIN_PREFIX, "/v3/target-set").as_str(),
AdminOperation(&SetNotificationTarget {}),
Method::PUT,
format!("{}{}", ADMIN_PREFIX, "/v3/target/{target_type}/{target_name}").as_str(),
AdminOperation(&NotificationTarget {}),
)?;
// Remove notification target
@@ -388,9 +387,15 @@ fn register_user_route(r: &mut S3Router<AdminOperation>) -> std::io::Result<()>
// * `target_name` - A unique name for a Target, such as "1".
r.insert(
Method::DELETE,
format!("{}{}", ADMIN_PREFIX, "/v3/target-remove").as_str(),
format!("{}{}", ADMIN_PREFIX, "/v3/target/{target_type}/{target_name}/reset").as_str(),
AdminOperation(&RemoveNotificationTarget {}),
)?;
// arns
r.insert(
Method::GET,
format!("{}{}", ADMIN_PREFIX, "/v3/target/arns").as_str(),
AdminOperation(&ListNotificationTargets {}),
)?;
r.insert(
Method::POST,

View File

@@ -45,7 +45,7 @@ export RUSTFS_VOLUMES="./target/volume/test{1...4}"
# export RUSTFS_VOLUMES="./target/volume/test"
export RUSTFS_ADDRESS=":9000"
export RUSTFS_CONSOLE_ENABLE=true
export RUSTFS_CONSOLE_ADDRESS=":9001"
# export RUSTFS_CONSOLE_ADDRESS=":9001"
# export RUSTFS_SERVER_DOMAINS="localhost:9000"
# HTTPS certificate directory
# export RUSTFS_TLS_PATH="./deploy/certs"