]> Untitled Git - lemmy.git/blob - src/api_routes_http.rs
Revert "feat: re-added captcha checks (#3249)" (#3288)
[lemmy.git] / src / api_routes_http.rs
1 use actix_web::{guard, web, Error, HttpResponse, Result};
2 use lemmy_api::Perform;
3 use lemmy_api_common::{
4   comment::{
5     CreateComment,
6     CreateCommentLike,
7     CreateCommentReport,
8     DeleteComment,
9     DistinguishComment,
10     EditComment,
11     GetComment,
12     GetComments,
13     ListCommentReports,
14     RemoveComment,
15     ResolveCommentReport,
16     SaveComment,
17   },
18   community::{
19     AddModToCommunity,
20     BanFromCommunity,
21     BlockCommunity,
22     CreateCommunity,
23     DeleteCommunity,
24     EditCommunity,
25     FollowCommunity,
26     GetCommunity,
27     HideCommunity,
28     ListCommunities,
29     RemoveCommunity,
30     TransferCommunity,
31   },
32   context::LemmyContext,
33   custom_emoji::{CreateCustomEmoji, DeleteCustomEmoji, EditCustomEmoji},
34   person::{
35     AddAdmin,
36     BanPerson,
37     BlockPerson,
38     ChangePassword,
39     DeleteAccount,
40     GetBannedPersons,
41     GetPersonDetails,
42     GetPersonMentions,
43     GetReplies,
44     GetReportCount,
45     GetUnreadCount,
46     Login,
47     MarkAllAsRead,
48     MarkCommentReplyAsRead,
49     MarkPersonMentionAsRead,
50     PasswordChangeAfterReset,
51     PasswordReset,
52     Register,
53     SaveUserSettings,
54     VerifyEmail,
55   },
56   post::{
57     CreatePost,
58     CreatePostLike,
59     CreatePostReport,
60     DeletePost,
61     EditPost,
62     FeaturePost,
63     GetPost,
64     GetPosts,
65     GetSiteMetadata,
66     ListPostReports,
67     LockPost,
68     MarkPostAsRead,
69     RemovePost,
70     ResolvePostReport,
71     SavePost,
72   },
73   private_message::{
74     CreatePrivateMessage,
75     CreatePrivateMessageReport,
76     DeletePrivateMessage,
77     EditPrivateMessage,
78     GetPrivateMessages,
79     ListPrivateMessageReports,
80     MarkPrivateMessageAsRead,
81     ResolvePrivateMessageReport,
82   },
83   site::{
84     ApproveRegistrationApplication,
85     CreateSite,
86     EditSite,
87     GetFederatedInstances,
88     GetModlog,
89     GetSite,
90     GetUnreadRegistrationApplicationCount,
91     LeaveAdmin,
92     ListRegistrationApplications,
93     PurgeComment,
94     PurgeCommunity,
95     PurgePerson,
96     PurgePost,
97     ResolveObject,
98     Search,
99   },
100 };
101 use lemmy_api_crud::PerformCrud;
102 use lemmy_apub::{api::PerformApub, SendActivity};
103 use lemmy_utils::rate_limit::RateLimitCell;
104 use serde::Deserialize;
105
106 pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
107   cfg.service(
108     web::scope("/api/v3")
109       // Site
110       .service(
111         web::scope("/site")
112           .wrap(rate_limit.message())
113           .route("", web::get().to(route_get_crud::<GetSite>))
114           // Admin Actions
115           .route("", web::post().to(route_post_crud::<CreateSite>))
116           .route("", web::put().to(route_post_crud::<EditSite>)),
117       )
118       .service(
119         web::resource("/modlog")
120           .wrap(rate_limit.message())
121           .route(web::get().to(route_get::<GetModlog>)),
122       )
123       .service(
124         web::resource("/search")
125           .wrap(rate_limit.search())
126           .route(web::get().to(route_get_apub::<Search>)),
127       )
128       .service(
129         web::resource("/resolve_object")
130           .wrap(rate_limit.message())
131           .route(web::get().to(route_get_apub::<ResolveObject>)),
132       )
133       // Community
134       .service(
135         web::resource("/community")
136           .guard(guard::Post())
137           .wrap(rate_limit.register())
138           .route(web::post().to(route_post_crud::<CreateCommunity>)),
139       )
140       .service(
141         web::scope("/community")
142           .wrap(rate_limit.message())
143           .route("", web::get().to(route_get_apub::<GetCommunity>))
144           .route("", web::put().to(route_post_crud::<EditCommunity>))
145           .route("/hide", web::put().to(route_post::<HideCommunity>))
146           .route("/list", web::get().to(route_get_crud::<ListCommunities>))
147           .route("/follow", web::post().to(route_post::<FollowCommunity>))
148           .route("/block", web::post().to(route_post::<BlockCommunity>))
149           .route(
150             "/delete",
151             web::post().to(route_post_crud::<DeleteCommunity>),
152           )
153           // Mod Actions
154           .route(
155             "/remove",
156             web::post().to(route_post_crud::<RemoveCommunity>),
157           )
158           .route("/transfer", web::post().to(route_post::<TransferCommunity>))
159           .route("/ban_user", web::post().to(route_post::<BanFromCommunity>))
160           .route("/mod", web::post().to(route_post::<AddModToCommunity>)),
161       )
162       .service(
163         web::scope("/federated_instances")
164           .wrap(rate_limit.message())
165           .route("", web::get().to(route_get::<GetFederatedInstances>)),
166       )
167       // Post
168       .service(
169         // Handle POST to /post separately to add the post() rate limitter
170         web::resource("/post")
171           .guard(guard::Post())
172           .wrap(rate_limit.post())
173           .route(web::post().to(route_post_crud::<CreatePost>)),
174       )
175       .service(
176         web::scope("/post")
177           .wrap(rate_limit.message())
178           .route("", web::get().to(route_get_crud::<GetPost>))
179           .route("", web::put().to(route_post_crud::<EditPost>))
180           .route("/delete", web::post().to(route_post_crud::<DeletePost>))
181           .route("/remove", web::post().to(route_post_crud::<RemovePost>))
182           .route(
183             "/mark_as_read",
184             web::post().to(route_post::<MarkPostAsRead>),
185           )
186           .route("/lock", web::post().to(route_post::<LockPost>))
187           .route("/feature", web::post().to(route_post::<FeaturePost>))
188           .route("/list", web::get().to(route_get_apub::<GetPosts>))
189           .route("/like", web::post().to(route_post::<CreatePostLike>))
190           .route("/save", web::put().to(route_post::<SavePost>))
191           .route("/report", web::post().to(route_post::<CreatePostReport>))
192           .route(
193             "/report/resolve",
194             web::put().to(route_post::<ResolvePostReport>),
195           )
196           .route("/report/list", web::get().to(route_get::<ListPostReports>))
197           .route(
198             "/site_metadata",
199             web::get().to(route_get::<GetSiteMetadata>),
200           ),
201       )
202       // Comment
203       .service(
204         // Handle POST to /comment separately to add the comment() rate limitter
205         web::resource("/comment")
206           .guard(guard::Post())
207           .wrap(rate_limit.comment())
208           .route(web::post().to(route_post_crud::<CreateComment>)),
209       )
210       .service(
211         web::scope("/comment")
212           .wrap(rate_limit.message())
213           .route("", web::get().to(route_get_crud::<GetComment>))
214           .route("", web::put().to(route_post_crud::<EditComment>))
215           .route("/delete", web::post().to(route_post_crud::<DeleteComment>))
216           .route("/remove", web::post().to(route_post_crud::<RemoveComment>))
217           .route(
218             "/mark_as_read",
219             web::post().to(route_post::<MarkCommentReplyAsRead>),
220           )
221           .route(
222             "/distinguish",
223             web::post().to(route_post::<DistinguishComment>),
224           )
225           .route("/like", web::post().to(route_post::<CreateCommentLike>))
226           .route("/save", web::put().to(route_post::<SaveComment>))
227           .route("/list", web::get().to(route_get_apub::<GetComments>))
228           .route("/report", web::post().to(route_post::<CreateCommentReport>))
229           .route(
230             "/report/resolve",
231             web::put().to(route_post::<ResolveCommentReport>),
232           )
233           .route(
234             "/report/list",
235             web::get().to(route_get::<ListCommentReports>),
236           ),
237       )
238       // Private Message
239       .service(
240         web::scope("/private_message")
241           .wrap(rate_limit.message())
242           .route("/list", web::get().to(route_get_crud::<GetPrivateMessages>))
243           .route("", web::post().to(route_post_crud::<CreatePrivateMessage>))
244           .route("", web::put().to(route_post_crud::<EditPrivateMessage>))
245           .route(
246             "/delete",
247             web::post().to(route_post_crud::<DeletePrivateMessage>),
248           )
249           .route(
250             "/mark_as_read",
251             web::post().to(route_post::<MarkPrivateMessageAsRead>),
252           )
253           .route(
254             "/report",
255             web::post().to(route_post::<CreatePrivateMessageReport>),
256           )
257           .route(
258             "/report/resolve",
259             web::put().to(route_post::<ResolvePrivateMessageReport>),
260           )
261           .route(
262             "/report/list",
263             web::get().to(route_get::<ListPrivateMessageReports>),
264           ),
265       )
266       // User
267       .service(
268         // Account action, I don't like that it's in /user maybe /accounts
269         // Handle /user/register separately to add the register() rate limitter
270         web::resource("/user/register")
271           .guard(guard::Post())
272           .wrap(rate_limit.register())
273           .route(web::post().to(route_post_crud::<Register>)),
274       )
275       // User actions
276       .service(
277         web::scope("/user")
278           .wrap(rate_limit.message())
279           .route("", web::get().to(route_get_apub::<GetPersonDetails>))
280           .route("/mention", web::get().to(route_get::<GetPersonMentions>))
281           .route(
282             "/mention/mark_as_read",
283             web::post().to(route_post::<MarkPersonMentionAsRead>),
284           )
285           .route("/replies", web::get().to(route_get::<GetReplies>))
286           // Admin action. I don't like that it's in /user
287           .route("/ban", web::post().to(route_post::<BanPerson>))
288           .route("/banned", web::get().to(route_get::<GetBannedPersons>))
289           .route("/block", web::post().to(route_post::<BlockPerson>))
290           // Account actions. I don't like that they're in /user maybe /accounts
291           .route("/login", web::post().to(route_post::<Login>))
292           .route(
293             "/delete_account",
294             web::post().to(route_post_crud::<DeleteAccount>),
295           )
296           .route(
297             "/password_reset",
298             web::post().to(route_post::<PasswordReset>),
299           )
300           .route(
301             "/password_change",
302             web::post().to(route_post::<PasswordChangeAfterReset>),
303           )
304           // mark_all_as_read feels off being in this section as well
305           .route(
306             "/mark_all_as_read",
307             web::post().to(route_post::<MarkAllAsRead>),
308           )
309           .route(
310             "/save_user_settings",
311             web::put().to(route_post::<SaveUserSettings>),
312           )
313           .route(
314             "/change_password",
315             web::put().to(route_post::<ChangePassword>),
316           )
317           .route("/report_count", web::get().to(route_get::<GetReportCount>))
318           .route("/unread_count", web::get().to(route_get::<GetUnreadCount>))
319           .route("/verify_email", web::post().to(route_post::<VerifyEmail>))
320           .route("/leave_admin", web::post().to(route_post::<LeaveAdmin>)),
321       )
322       // Admin Actions
323       .service(
324         web::scope("/admin")
325           .wrap(rate_limit.message())
326           .route("/add", web::post().to(route_post::<AddAdmin>))
327           .route(
328             "/registration_application/count",
329             web::get().to(route_get::<GetUnreadRegistrationApplicationCount>),
330           )
331           .route(
332             "/registration_application/list",
333             web::get().to(route_get::<ListRegistrationApplications>),
334           )
335           .route(
336             "/registration_application/approve",
337             web::put().to(route_post::<ApproveRegistrationApplication>),
338           )
339           .service(
340             web::scope("/purge")
341               .route("/person", web::post().to(route_post::<PurgePerson>))
342               .route("/community", web::post().to(route_post::<PurgeCommunity>))
343               .route("/post", web::post().to(route_post::<PurgePost>))
344               .route("/comment", web::post().to(route_post::<PurgeComment>)),
345           ),
346       )
347       .service(
348         web::scope("/custom_emoji")
349           .wrap(rate_limit.message())
350           .route("", web::post().to(route_post_crud::<CreateCustomEmoji>))
351           .route("", web::put().to(route_post_crud::<EditCustomEmoji>))
352           .route(
353             "/delete",
354             web::post().to(route_post_crud::<DeleteCustomEmoji>),
355           ),
356       ),
357   );
358 }
359
360 async fn perform<'a, Data>(
361   data: Data,
362   context: web::Data<LemmyContext>,
363   apub_data: activitypub_federation::config::Data<LemmyContext>,
364 ) -> Result<HttpResponse, Error>
365 where
366   Data: Perform
367     + SendActivity<Response = <Data as Perform>::Response>
368     + Clone
369     + Deserialize<'a>
370     + Send
371     + 'static,
372 {
373   let res = data.perform(&context).await?;
374   SendActivity::send_activity(&data, &res, &apub_data).await?;
375   Ok(HttpResponse::Ok().json(res))
376 }
377
378 async fn route_get<'a, Data>(
379   data: web::Query<Data>,
380   context: web::Data<LemmyContext>,
381   apub_data: activitypub_federation::config::Data<LemmyContext>,
382 ) -> Result<HttpResponse, Error>
383 where
384   Data: Perform
385     + SendActivity<Response = <Data as Perform>::Response>
386     + Clone
387     + Deserialize<'a>
388     + Send
389     + 'static,
390 {
391   perform::<Data>(data.0, context, apub_data).await
392 }
393
394 async fn route_get_apub<'a, Data>(
395   data: web::Query<Data>,
396   context: activitypub_federation::config::Data<LemmyContext>,
397 ) -> Result<HttpResponse, Error>
398 where
399   Data: PerformApub
400     + SendActivity<Response = <Data as PerformApub>::Response>
401     + Clone
402     + Deserialize<'a>
403     + Send
404     + 'static,
405 {
406   let res = data.perform(&context).await?;
407   SendActivity::send_activity(&data.0, &res, &context).await?;
408   Ok(HttpResponse::Ok().json(res))
409 }
410
411 async fn route_post<'a, Data>(
412   data: web::Json<Data>,
413   context: web::Data<LemmyContext>,
414   apub_data: activitypub_federation::config::Data<LemmyContext>,
415 ) -> Result<HttpResponse, Error>
416 where
417   Data: Perform
418     + SendActivity<Response = <Data as Perform>::Response>
419     + Clone
420     + Deserialize<'a>
421     + Send
422     + 'static,
423 {
424   perform::<Data>(data.0, context, apub_data).await
425 }
426
427 async fn perform_crud<'a, Data>(
428   data: Data,
429   context: web::Data<LemmyContext>,
430   apub_data: activitypub_federation::config::Data<LemmyContext>,
431 ) -> Result<HttpResponse, Error>
432 where
433   Data: PerformCrud
434     + SendActivity<Response = <Data as PerformCrud>::Response>
435     + Clone
436     + Deserialize<'a>
437     + Send
438     + 'static,
439 {
440   let res = data.perform(&context).await?;
441   SendActivity::send_activity(&data, &res, &apub_data).await?;
442   Ok(HttpResponse::Ok().json(res))
443 }
444
445 async fn route_get_crud<'a, Data>(
446   data: web::Query<Data>,
447   context: web::Data<LemmyContext>,
448   apub_data: activitypub_federation::config::Data<LemmyContext>,
449 ) -> Result<HttpResponse, Error>
450 where
451   Data: PerformCrud
452     + SendActivity<Response = <Data as PerformCrud>::Response>
453     + Clone
454     + Deserialize<'a>
455     + Send
456     + 'static,
457 {
458   perform_crud::<Data>(data.0, context, apub_data).await
459 }
460
461 async fn route_post_crud<'a, Data>(
462   data: web::Json<Data>,
463   context: web::Data<LemmyContext>,
464   apub_data: activitypub_federation::config::Data<LemmyContext>,
465 ) -> Result<HttpResponse, Error>
466 where
467   Data: PerformCrud
468     + SendActivity<Response = <Data as PerformCrud>::Response>
469     + Clone
470     + Deserialize<'a>
471     + Send
472     + 'static,
473 {
474   perform_crud::<Data>(data.0, context, apub_data).await
475 }