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