1 use crate::api
::ApiError
;
2 use crate::group
::{DeleteableGroupProperty, GroupConfig, GroupConfigUpdater, GROUP_TYPENAME}
;
5 /// Get all notification groups
7 /// The caller is responsible for any needed permission checks.
8 /// Returns a list of all groups or an `ApiError` if the config is erroneous.
9 pub fn get_groups(config
: &Config
) -> Result
<Vec
<GroupConfig
>, ApiError
> {
12 .convert_to_typed_array(GROUP_TYPENAME
)
13 .map_err(|e
| ApiError
::internal_server_error("Could not fetch groups", Some(e
.into())))
16 /// Get group with given `name`
18 /// The caller is responsible for any needed permission checks.
19 /// Returns the endpoint or an `ApiError` if the group was not found.
20 pub fn get_group(config
: &Config
, name
: &str) -> Result
<GroupConfig
, ApiError
> {
23 .lookup(GROUP_TYPENAME
, name
)
24 .map_err(|_
| ApiError
::not_found(format
!("group '{name}' not found"), None
))
29 /// The caller is responsible for any needed permission checks.
30 /// The caller also responsible for locking the configuration files.
31 /// Returns an `ApiError` if a group with the same name already exists, or
32 /// if the group could not be saved
33 pub fn add_group(config
: &mut Config
, group_config
: &GroupConfig
) -> Result
<(), ApiError
> {
34 if get_group(config
, &group_config
.name
).is_ok() {
35 return Err(ApiError
::bad_request(
36 format
!("group '{}' already exists", group_config
.name
),
41 if group_config
.endpoint
.is_empty() {
42 return Err(ApiError
::bad_request(
43 "group must contain at least one endpoint",
48 if let Some(filter
) = &group_config
.filter
{
49 // Check if filter exists
50 super::filter
::get_filter(config
, filter
)?
;
53 check_if_endpoints_exist(config
, &group_config
.endpoint
)?
;
57 .set_data(&group_config
.name
, GROUP_TYPENAME
, group_config
)
59 ApiError
::internal_server_error(
60 format
!("could not save group '{}'", group_config
.name
),
68 /// Update existing group
70 /// The caller is responsible for any needed permission checks.
71 /// The caller also responsible for locking the configuration files.
72 /// Returns an `ApiError` if the config could not be saved.
76 updater
: &GroupConfigUpdater
,
77 delete
: Option
<&[DeleteableGroupProperty
]>,
78 digest
: Option
<&[u8]>,
79 ) -> Result
<(), ApiError
> {
80 super::verify_digest(config
, digest
)?
;
82 let mut group
= get_group(config
, name
)?
;
84 if let Some(delete
) = delete
{
85 for deleteable_property
in delete
{
86 match deleteable_property
{
87 DeleteableGroupProperty
::Comment
=> group
.comment
= None
,
88 DeleteableGroupProperty
::Filter
=> group
.filter
= None
,
93 if let Some(endpoints
) = &updater
.endpoint
{
94 check_if_endpoints_exist(config
, endpoints
)?
;
95 if endpoints
.is_empty() {
96 return Err(ApiError
::bad_request(
97 "group must contain at least one endpoint",
101 group
.endpoint
= endpoints
.iter().map(Into
::into
).collect()
104 if let Some(comment
) = &updater
.comment
{
105 group
.comment
= Some(comment
.into());
108 if let Some(filter
) = &updater
.filter
{
109 // Check if filter exists
110 let _
= super::filter
::get_filter(config
, filter
)?
;
111 group
.filter
= Some(filter
.into());
116 .set_data(name
, GROUP_TYPENAME
, &group
)
118 ApiError
::internal_server_error(
119 format
!("could not save group '{name}'"),
127 /// Delete existing group
129 /// The caller is responsible for any needed permission checks.
130 /// The caller also responsible for locking the configuration files.
131 /// Returns an `ApiError` if the group does not exist.
132 pub fn delete_group(config
: &mut Config
, name
: &str) -> Result
<(), ApiError
> {
133 // Check if the group exists
134 let _
= get_group(config
, name
)?
;
136 config
.config
.sections
.remove(name
);
141 fn check_if_endpoints_exist(config
: &Config
, endpoints
: &[String
]) -> Result
<(), ApiError
> {
142 for endpoint
in endpoints
{
143 if !super::endpoint_exists(config
, endpoint
) {
144 return Err(ApiError
::not_found(
145 format
!("endoint '{endpoint}' does not exist"),
154 // groups cannot be empty, so only build the tests if we have the
155 // sendmail endpoint available
156 #[cfg(all(test, feature = "sendmail"))]
159 use crate::api
::sendmail
::tests
::add_sendmail_endpoint_for_test
;
160 use crate::api
::test_helpers
::*;
162 fn add_default_group(config
: &mut Config
) -> Result
<(), ApiError
> {
163 add_sendmail_endpoint_for_test(config
, "test")?
;
168 name
: "group1".into(),
169 endpoint
: vec
!["test".to_string()],
179 fn test_add_group_fails_if_endpoint_does_not_exist() {
180 let mut config
= empty_config();
184 name
: "group1".into(),
185 endpoint
: vec
!["foo".into()],
194 fn test_add_group() -> Result
<(), ApiError
> {
195 let mut config
= empty_config();
196 assert
!(add_default_group(&mut config
).is_ok());
201 fn test_update_group_fails_if_endpoint_does_not_exist() -> Result
<(), ApiError
> {
202 let mut config
= empty_config();
203 add_default_group(&mut config
)?
;
205 assert
!(update_group(
208 &GroupConfigUpdater
{
209 endpoint
: Some(vec
!["foo".into()]),
220 fn test_update_group_fails_if_digest_invalid() -> Result
<(), ApiError
> {
221 let mut config
= empty_config();
222 add_default_group(&mut config
)?
;
224 assert
!(update_group(
236 fn test_update_group() -> Result
<(), ApiError
> {
237 let mut config
= empty_config();
238 add_default_group(&mut config
)?
;
240 assert
!(update_group(
243 &GroupConfigUpdater
{
245 comment
: Some("newcomment".into()),
252 let group
= get_group(&config
, "group1")?
;
253 assert_eq
!(group
.comment
, Some("newcomment".into()));
255 assert
!(update_group(
259 Some(&[DeleteableGroupProperty
::Comment
]),
263 let group
= get_group(&config
, "group1")?
;
264 assert_eq
!(group
.comment
, None
);
270 fn test_group_delete() -> Result
<(), ApiError
> {
271 let mut config
= empty_config();
272 add_default_group(&mut config
)?
;
274 assert
!(delete_group(&mut config
, "group1").is_ok());
275 assert
!(delete_group(&mut config
, "group1").is_err());