summaryrefslogtreecommitdiff
path: root/crates/jmap/src/api/management/reload.rs
blob: c8410fc295bdb01e153fa0ef4cf7061dc2ae1a18 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 * SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd <hello@stalw.art>
 *
 * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
 */

use directory::Permission;
use hyper::Method;
use serde_json::json;
use utils::url_params::UrlParams;

use crate::{
    api::{http::ToHttpResponse, HttpRequest, HttpResponse, JsonResponse},
    auth::AccessToken,
    services::housekeeper::Event,
    JMAP,
};

impl JMAP {
    pub async fn handle_manage_reload(
        &self,
        req: &HttpRequest,
        path: Vec<&str>,
        access_token: &AccessToken,
    ) -> trc::Result<HttpResponse> {
        // Validate the access token
        access_token.assert_has_permission(Permission::SettingsReload)?;

        match (path.get(1).copied(), req.method()) {
            (Some("lookup"), &Method::GET) => {
                let result = self.core.reload_lookups().await?;
                // Update core
                if let Some(core) = result.new_core {
                    self.shared_core.store(core.into());
                }

                Ok(JsonResponse::new(json!({
                    "data": result.config,
                }))
                .into_http_response())
            }
            (Some("certificate"), &Method::GET) => Ok(JsonResponse::new(json!({
                "data": self.core.reload_certificates().await?.config,
            }))
            .into_http_response()),
            (Some("server.blocked-ip"), &Method::GET) => {
                let result = self.core.reload_blocked_ips().await?;
                // Increment version counter
                self.core.network.blocked_ips.increment_version();

                Ok(JsonResponse::new(json!({
                    "data": result.config,
                }))
                .into_http_response())
            }
            (_, &Method::GET) => {
                let result = self.core.reload().await?;
                if !UrlParams::new(req.uri().query()).has_key("dry-run") {
                    if let Some(core) = result.new_core {
                        // Update core
                        self.shared_core.store(core.into());

                        // Increment version counter
                        self.inner.increment_config_version();
                    }

                    if let Some(tracers) = result.tracers {
                        // Update tracers
                        #[cfg(feature = "enterprise")]
                        tracers.update(self.shared_core.load().is_enterprise_edition());
                        #[cfg(not(feature = "enterprise"))]
                        tracers.update(false);
                    }

                    // Reload settings
                    self.inner
                        .housekeeper_tx
                        .send(Event::ReloadSettings)
                        .await
                        .map_err(|err| {
                            trc::EventType::Server(trc::ServerEvent::ThreadError)
                                .reason(err)
                                .details("Failed to send settings reload event to housekeeper")
                                .caused_by(trc::location!())
                        })?;
                }

                Ok(JsonResponse::new(json!({
                    "data": result.config,
                }))
                .into_http_response())
            }
            _ => Err(trc::ResourceEvent::NotFound.into_err()),
        }
    }

    pub async fn handle_manage_update(
        &self,
        req: &HttpRequest,
        path: Vec<&str>,
        access_token: &AccessToken,
    ) -> trc::Result<HttpResponse> {
        match (path.get(1).copied(), req.method()) {
            (Some("spam-filter"), &Method::GET) => {
                // Validate the access token
                access_token.assert_has_permission(Permission::UpdateSpamFilter)?;

                Ok(JsonResponse::new(json!({
                    "data":  self
                    .core
                    .storage
                    .config
                    .update_config_resource("spam-filter")
                    .await?,
                }))
                .into_http_response())
            }
            (Some("webadmin"), &Method::GET) => {
                // Validate the access token
                access_token.assert_has_permission(Permission::UpdateWebadmin)?;

                self.inner.webadmin.update_and_unpack(&self.core).await?;

                Ok(JsonResponse::new(json!({
                    "data": (),
                }))
                .into_http_response())
            }
            _ => Err(trc::ResourceEvent::NotFound.into_err()),
        }
    }
}