+167 -13 +/-6 browse
1 | diff --git a/mailpot-tests/for_testing.db b/mailpot-tests/for_testing.db |
2 | index 64f74ee..fa043ad 100644 |
3 | Binary files a/mailpot-tests/for_testing.db and b/mailpot-tests/for_testing.db differ |
4 | diff --git a/rest-http/src/routes/list.rs b/rest-http/src/routes/list.rs |
5 | index 1897ce2..ebe9910 100644 |
6 | --- a/rest-http/src/routes/list.rs |
7 | +++ b/rest-http/src/routes/list.rs |
8 | @@ -384,7 +384,15 @@ mod tests { |
9 | assert_eq!(response.status(), StatusCode::OK); |
10 | let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); |
11 | let r: Vec<ListOwner> = serde_json::from_slice(&body).unwrap(); |
12 | - assert_eq!(&r, &[]); |
13 | + assert_eq!( |
14 | + &r, |
15 | + &[ListOwner { |
16 | + pk: 1, |
17 | + list: 1, |
18 | + address: "user@example.com".into(), |
19 | + name: None |
20 | + }] |
21 | + ); |
22 | |
23 | // ------------------------------------------------------------ |
24 | // new_list_owner() |
25 | diff --git a/web/src/auth.rs b/web/src/auth.rs |
26 | index af17e30..cc852b2 100644 |
27 | --- a/web/src/auth.rs |
28 | +++ b/web/src/auth.rs |
29 | @@ -158,7 +158,8 @@ pub async fn ssh_signin( |
30 | .into_response() |
31 | } |
32 | |
33 | - pub async fn ssh_signin_post( |
34 | + #[allow(non_snake_case)] |
35 | + pub async fn ssh_signin_POST( |
36 | _: LoginPath, |
37 | mut session: WritableSession, |
38 | Query(next): Query<Next>, |
39 | diff --git a/web/src/lists.rs b/web/src/lists.rs |
40 | index bc25716..c0197af 100644 |
41 | --- a/web/src/lists.rs |
42 | +++ b/web/src/lists.rs |
43 | @@ -320,7 +320,8 @@ pub async fn list_edit( |
44 | )) |
45 | } |
46 | |
47 | - pub async fn list_edit_post( |
48 | + #[allow(non_snake_case)] |
49 | + pub async fn list_edit_POST( |
50 | ListEditPath(id): ListEditPath, |
51 | mut session: WritableSession, |
52 | Extension(user): Extension<User>, |
53 | @@ -514,7 +515,7 @@ pub enum SubscriptionPolicySettings { |
54 | } |
55 | |
56 | /// Raw post page. |
57 | - pub async fn post_raw( |
58 | + pub async fn list_post_raw( |
59 | ListPostRawPath(id, msg_id): ListPostRawPath, |
60 | State(state): State<Arc<AppState>>, |
61 | ) -> Result<String, ResponseError> { |
62 | @@ -541,7 +542,7 @@ pub async fn post_raw( |
63 | } |
64 | |
65 | /// .eml post page. |
66 | - pub async fn post_eml( |
67 | + pub async fn list_post_eml( |
68 | ListPostEmlPath(id, msg_id): ListPostEmlPath, |
69 | State(state): State<Arc<AppState>>, |
70 | ) -> Result<impl IntoResponse, ResponseError> { |
71 | diff --git a/web/src/main.rs b/web/src/main.rs |
72 | index 000d58e..231ac2c 100644 |
73 | --- a/web/src/main.rs |
74 | +++ b/web/src/main.rs |
75 | @@ -54,8 +54,8 @@ fn create_app(shared_state: Arc<AppState>) -> Router { |
76 | .route("/", get(root)) |
77 | .typed_get(list) |
78 | .typed_get(list_post) |
79 | - .typed_get(post_raw) |
80 | - .typed_get(post_eml) |
81 | + .typed_get(list_post_raw) |
82 | + .typed_get(list_post_eml) |
83 | .typed_get(list_edit.layer(RequireAuth::login_with_role_or_redirect( |
84 | Role::User.., |
85 | Arc::clone(&login_url), |
86 | @@ -65,7 +65,7 @@ fn create_app(shared_state: Arc<AppState>) -> Router { |
87 | { |
88 | let shared_state = Arc::clone(&shared_state); |
89 | move |path, session, user, payload| { |
90 | - list_edit_post(path, session, user, payload, State(shared_state)) |
91 | + list_edit_POST(path, session, user, payload, State(shared_state)) |
92 | } |
93 | } |
94 | .layer(RequireAuth::login_with_role_or_redirect( |
95 | @@ -93,7 +93,7 @@ fn create_app(shared_state: Arc<AppState>) -> Router { |
96 | .typed_post({ |
97 | let shared_state = Arc::clone(&shared_state); |
98 | move |path, session, query, auth, body| { |
99 | - auth::ssh_signin_post(path, session, query, auth, body, shared_state) |
100 | + auth::ssh_signin_POST(path, session, query, auth, body, shared_state) |
101 | } |
102 | }) |
103 | .typed_get(logout_handler) |
104 | @@ -112,7 +112,7 @@ fn create_app(shared_state: Arc<AppState>) -> Router { |
105 | { |
106 | let shared_state = Arc::clone(&shared_state); |
107 | move |path, session, auth, body| { |
108 | - settings_post(path, session, auth, body, shared_state) |
109 | + settings_POST(path, session, auth, body, shared_state) |
110 | } |
111 | } |
112 | .layer(RequireAuth::login_or_redirect( |
113 | @@ -131,7 +131,7 @@ fn create_app(shared_state: Arc<AppState>) -> Router { |
114 | { |
115 | let shared_state = Arc::clone(&shared_state); |
116 | move |session, path, user, body| { |
117 | - user_list_subscription_post(session, path, user, body, shared_state) |
118 | + user_list_subscription_POST(session, path, user, body, shared_state) |
119 | } |
120 | } |
121 | .layer(RequireAuth::login_with_role_or_redirect( |
122 | @@ -225,6 +225,7 @@ mod tests { |
123 | }; |
124 | use mailpot::{Configuration, Connection, SendMail}; |
125 | use mailpot_tests::init_stderr_logging; |
126 | + use percent_encoding::utf8_percent_encode; |
127 | use tempfile::TempDir; |
128 | use tower::ServiceExt; |
129 | |
130 | @@ -258,6 +259,11 @@ mod tests { |
131 | |
132 | let db_path = tmp_dir.path().join("mpot.db"); |
133 | std::fs::copy("../mailpot-tests/for_testing.db", &db_path).unwrap(); |
134 | + let mut perms = std::fs::metadata(&db_path).unwrap().permissions(); |
135 | + #[allow(clippy::permissions_set_readonly_false)] |
136 | + perms.set_readonly(false); |
137 | + std::fs::set_permissions(&db_path, perms).unwrap(); |
138 | + |
139 | let config = Configuration { |
140 | send_mail: SendMail::ShellCommand("/usr/bin/false".to_string()), |
141 | db_path, |
142 | @@ -285,6 +291,66 @@ mod tests { |
143 | ); |
144 | |
145 | // ------------------------------------------------------------ |
146 | + // list_post(), list_post_eml(), list_post_raw() |
147 | + |
148 | + { |
149 | + let msg_id = "<abcdefgh@sator.example.com>"; |
150 | + let res = create_app(state.clone()) |
151 | + .oneshot(req!( |
152 | + get & format!( |
153 | + "/list/{id}/posts/{msgid}/", |
154 | + id = list.id, |
155 | + msgid = utf8_percent_encode(msg_id, PATH_SEGMENT) |
156 | + ) |
157 | + )) |
158 | + .await |
159 | + .unwrap(); |
160 | + |
161 | + assert_eq!(res.status(), StatusCode::OK); |
162 | + assert_eq!( |
163 | + res.headers().get(http::header::CONTENT_TYPE), |
164 | + Some(&http::HeaderValue::from_static("text/html; charset=utf-8")) |
165 | + ); |
166 | + let res = create_app(state.clone()) |
167 | + .oneshot(req!( |
168 | + get & format!( |
169 | + "/list/{id}/posts/{msgid}/raw/", |
170 | + id = list.id, |
171 | + msgid = utf8_percent_encode(msg_id, PATH_SEGMENT) |
172 | + ) |
173 | + )) |
174 | + .await |
175 | + .unwrap(); |
176 | + |
177 | + assert_eq!(res.status(), StatusCode::OK); |
178 | + assert_eq!( |
179 | + res.headers().get(http::header::CONTENT_TYPE), |
180 | + Some(&http::HeaderValue::from_static("text/plain; charset=utf-8")) |
181 | + ); |
182 | + let res = create_app(state.clone()) |
183 | + .oneshot(req!( |
184 | + get & format!( |
185 | + "/list/{id}/posts/{msgid}/eml/", |
186 | + id = list.id, |
187 | + msgid = utf8_percent_encode(msg_id, PATH_SEGMENT) |
188 | + ) |
189 | + )) |
190 | + .await |
191 | + .unwrap(); |
192 | + |
193 | + assert_eq!(res.status(), StatusCode::OK); |
194 | + assert_eq!( |
195 | + res.headers().get(http::header::CONTENT_TYPE), |
196 | + Some(&http::HeaderValue::from_static("application/octet-stream")) |
197 | + ); |
198 | + assert_eq!( |
199 | + res.headers().get(http::header::CONTENT_DISPOSITION), |
200 | + Some(&http::HeaderValue::from_static( |
201 | + "attachment; filename=\"<abcdefgh@sator.example.com>.eml\"" |
202 | + )), |
203 | + ); |
204 | + } |
205 | + // ------------------------------------------------------------ |
206 | // help(), ssh_signin(), root() |
207 | |
208 | for path in ["/help/", "/"] { |
209 | @@ -391,5 +457,81 @@ mod tests { |
210 | |
211 | // ------------------------------------------------------------ |
212 | // user_list_subscription_post() TODO |
213 | + |
214 | + // ------------------------------------------------------------ |
215 | + // list_edit() |
216 | + |
217 | + { |
218 | + let mut request = req!(get & format!("/list/{id}/edit/", id = list.id,)); |
219 | + request |
220 | + .headers_mut() |
221 | + .insert(COOKIE, session_cookie.to_owned()); |
222 | + let response = login_app.clone().oneshot(request).await.unwrap(); |
223 | + |
224 | + assert_eq!(response.status(), StatusCode::OK); |
225 | + } |
226 | + |
227 | + // ------------------------------------------------------------ |
228 | + // list_edit_POST() |
229 | + |
230 | + { |
231 | + let mut request = req!( |
232 | + post & format!("/list/{id}/edit/", id = list.id,), |
233 | + crate::lists::ChangeSetting::Metadata { |
234 | + name: "new name".to_string(), |
235 | + id: "new-name".to_string(), |
236 | + address: list.address.clone(), |
237 | + description: list.description.clone(), |
238 | + owner_local_part: None, |
239 | + request_local_part: None, |
240 | + archive_url: None, |
241 | + } |
242 | + ); |
243 | + request |
244 | + .headers_mut() |
245 | + .insert(COOKIE, session_cookie.to_owned()); |
246 | + let response = login_app.clone().oneshot(request).await.unwrap(); |
247 | + |
248 | + assert_eq!(response.status(), StatusCode::SEE_OTHER); |
249 | + let list_mod = db.lists().unwrap().remove(0); |
250 | + assert_eq!(&list_mod.name, "new name"); |
251 | + assert_eq!(&list_mod.id, "new-name"); |
252 | + assert_eq!(&list_mod.address, &list.address); |
253 | + assert_eq!(&list_mod.description, &list.description); |
254 | + } |
255 | + |
256 | + { |
257 | + let mut request = req!(post "/list/new-name/edit/", |
258 | + crate::lists::ChangeSetting::SubscriptionPolicy { |
259 | + send_confirmation: BoolPOST(false), |
260 | + subscription_policy: crate::lists::SubscriptionPolicySettings::Custom, |
261 | + } |
262 | + ); |
263 | + request |
264 | + .headers_mut() |
265 | + .insert(COOKIE, session_cookie.to_owned()); |
266 | + let response = login_app.clone().oneshot(request).await.unwrap(); |
267 | + |
268 | + assert_eq!(response.status(), StatusCode::SEE_OTHER); |
269 | + let policy = db.list_subscription_policy(list.pk()).unwrap().unwrap(); |
270 | + assert!(!policy.send_confirmation); |
271 | + assert!(policy.custom); |
272 | + } |
273 | + { |
274 | + let mut request = req!(post "/list/new-name/edit/", |
275 | + crate::lists::ChangeSetting::PostPolicy { |
276 | + delete_post_policy: None, |
277 | + post_policy: crate::lists::PostPolicySettings::Custom, |
278 | + } |
279 | + ); |
280 | + request |
281 | + .headers_mut() |
282 | + .insert(COOKIE, session_cookie.to_owned()); |
283 | + let response = login_app.clone().oneshot(request).await.unwrap(); |
284 | + |
285 | + assert_eq!(response.status(), StatusCode::SEE_OTHER); |
286 | + let policy = db.list_post_policy(list.pk()).unwrap().unwrap(); |
287 | + assert!(policy.custom); |
288 | + } |
289 | } |
290 | } |
291 | diff --git a/web/src/settings.rs b/web/src/settings.rs |
292 | index 7a29830..033614b 100644 |
293 | --- a/web/src/settings.rs |
294 | +++ b/web/src/settings.rs |
295 | @@ -89,7 +89,8 @@ pub enum ChangeSetting { |
296 | ChangeName { new: String }, |
297 | } |
298 | |
299 | - pub async fn settings_post( |
300 | + #[allow(non_snake_case)] |
301 | + pub async fn settings_POST( |
302 | _: SettingsPath, |
303 | mut session: WritableSession, |
304 | Extension(user): Extension<User>, |
305 | @@ -331,7 +332,8 @@ pub struct SubscriptionFormPayload { |
306 | pub receive_confirmation: bool, |
307 | } |
308 | |
309 | - pub async fn user_list_subscription_post( |
310 | + #[allow(non_snake_case)] |
311 | + pub async fn user_list_subscription_POST( |
312 | ListSettingsPath(id): ListSettingsPath, |
313 | mut session: WritableSession, |
314 | Extension(user): Extension<User>, |