]> Untitled Git - lemmy.git/blob - src/api_routes_http.rs
Version 0.18.0-rc.5
[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       )
340       .service(
341         web::scope("/admin/purge")
342           .wrap(rate_limit.message())
343           .route("/person", web::post().to(route_post::<PurgePerson>))
344           .route("/community", web::post().to(route_post::<PurgeCommunity>))
345           .route("/post", web::post().to(route_post::<PurgePost>))
346           .route("/comment", web::post().to(route_post::<PurgeComment>)),
347       )
348       .service(
349         web::scope("/custom_emoji")
350           .wrap(rate_limit.message())
351           .route("", web::post().to(route_post_crud::<CreateCustomEmoji>))
352           .route("", web::put().to(route_post_crud::<EditCustomEmoji>))
353           .route(
354             "/delete",
355             web::post().to(route_post_crud::<DeleteCustomEmoji>),
356           ),
357       ),
358   );
359 }
360
361 async fn perform<'a, Data>(
362   data: Data,
363   context: web::Data<LemmyContext>,
364   apub_data: activitypub_federation::config::Data<LemmyContext>,
365 ) -> Result<HttpResponse, Error>
366 where
367   Data: Perform
368     + SendActivity<Response = <Data as Perform>::Response>
369     + Clone
370     + Deserialize<'a>
371     + Send
372     + 'static,
373 {
374   let res = data.perform(&context).await?;
375   SendActivity::send_activity(&data, &res, &apub_data).await?;
376   Ok(HttpResponse::Ok().json(res))
377 }
378
379 async fn route_get<'a, Data>(
380   data: web::Query<Data>,
381   context: web::Data<LemmyContext>,
382   apub_data: activitypub_federation::config::Data<LemmyContext>,
383 ) -> Result<HttpResponse, Error>
384 where
385   Data: Perform
386     + SendActivity<Response = <Data as Perform>::Response>
387     + Clone
388     + Deserialize<'a>
389     + Send
390     + 'static,
391 {
392   perform::<Data>(data.0, context, apub_data).await
393 }
394
395 async fn route_get_apub<'a, Data>(
396   data: web::Query<Data>,
397   context: activitypub_federation::config::Data<LemmyContext>,
398 ) -> Result<HttpResponse, Error>
399 where
400   Data: PerformApub
401     + SendActivity<Response = <Data as PerformApub>::Response>
402     + Clone
403     + Deserialize<'a>
404     + Send
405     + 'static,
406 {
407   let res = data.perform(&context).await?;
408   SendActivity::send_activity(&data.0, &res, &context).await?;
409   Ok(HttpResponse::Ok().json(res))
410 }
411
412 async fn route_post<'a, Data>(
413   data: web::Json<Data>,
414   context: web::Data<LemmyContext>,
415   apub_data: activitypub_federation::config::Data<LemmyContext>,
416 ) -> Result<HttpResponse, Error>
417 where
418   Data: Perform
419     + SendActivity<Response = <Data as Perform>::Response>
420     + Clone
421     + Deserialize<'a>
422     + Send
423     + 'static,
424 {
425   perform::<Data>(data.0, context, apub_data).await
426 }
427
428 async fn perform_crud<'a, Data>(
429   data: Data,
430   context: web::Data<LemmyContext>,
431   apub_data: activitypub_federation::config::Data<LemmyContext>,
432 ) -> Result<HttpResponse, Error>
433 where
434   Data: PerformCrud
435     + SendActivity<Response = <Data as PerformCrud>::Response>
436     + Clone
437     + Deserialize<'a>
438     + Send
439     + 'static,
440 {
441   let res = data.perform(&context).await?;
442   SendActivity::send_activity(&data, &res, &apub_data).await?;
443   Ok(HttpResponse::Ok().json(res))
444 }
445
446 async fn route_get_crud<'a, Data>(
447   data: web::Query<Data>,
448   context: web::Data<LemmyContext>,
449   apub_data: activitypub_federation::config::Data<LemmyContext>,
450 ) -> Result<HttpResponse, Error>
451 where
452   Data: PerformCrud
453     + SendActivity<Response = <Data as PerformCrud>::Response>
454     + Clone
455     + Deserialize<'a>
456     + Send
457     + 'static,
458 {
459   perform_crud::<Data>(data.0, context, apub_data).await
460 }
461
462 async fn route_post_crud<'a, Data>(
463   data: web::Json<Data>,
464   context: web::Data<LemmyContext>,
465   apub_data: activitypub_federation::config::Data<LemmyContext>,
466 ) -> Result<HttpResponse, Error>
467 where
468   Data: PerformCrud
469     + SendActivity<Response = <Data as PerformCrud>::Response>
470     + Clone
471     + Deserialize<'a>
472     + Send
473     + 'static,
474 {
475   perform_crud::<Data>(data.0, context, apub_data).await
476 }