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