1 use actix_web::{guard, web, Error, HttpResponse, Result};
2 use lemmy_api::Perform;
3 use lemmy_api_common::{
32 context::LemmyContext,
33 custom_emoji::{CreateCustomEmoji, DeleteCustomEmoji, EditCustomEmoji},
49 MarkCommentReplyAsRead,
50 MarkPersonMentionAsRead,
51 PasswordChangeAfterReset,
76 CreatePrivateMessageReport,
80 ListPrivateMessageReports,
81 MarkPrivateMessageAsRead,
82 ResolvePrivateMessageReport,
85 ApproveRegistrationApplication,
88 GetFederatedInstances,
91 GetUnreadRegistrationApplicationCount,
93 ListRegistrationApplications,
102 use lemmy_api_crud::PerformCrud;
103 use lemmy_apub::{api::PerformApub, SendActivity};
104 use lemmy_utils::rate_limit::RateLimitCell;
105 use serde::Deserialize;
107 pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
109 web::scope("/api/v3")
113 .wrap(rate_limit.message())
114 .route("", web::get().to(route_get_crud::<GetSite>))
116 .route("", web::post().to(route_post_crud::<CreateSite>))
117 .route("", web::put().to(route_post_crud::<EditSite>)),
120 web::resource("/modlog")
121 .wrap(rate_limit.message())
122 .route(web::get().to(route_get::<GetModlog>)),
125 web::resource("/search")
126 .wrap(rate_limit.search())
127 .route(web::get().to(route_get_apub::<Search>)),
130 web::resource("/resolve_object")
131 .wrap(rate_limit.message())
132 .route(web::get().to(route_get_apub::<ResolveObject>)),
136 web::resource("/community")
137 .guard(guard::Post())
138 .wrap(rate_limit.register())
139 .route(web::post().to(route_post_crud::<CreateCommunity>)),
142 web::scope("/community")
143 .wrap(rate_limit.message())
144 .route("", web::get().to(route_get_apub::<GetCommunity>))
145 .route("", web::put().to(route_post_crud::<EditCommunity>))
146 .route("/hide", web::put().to(route_post::<HideCommunity>))
147 .route("/list", web::get().to(route_get_crud::<ListCommunities>))
148 .route("/follow", web::post().to(route_post::<FollowCommunity>))
149 .route("/block", web::post().to(route_post::<BlockCommunity>))
152 web::post().to(route_post_crud::<DeleteCommunity>),
157 web::post().to(route_post_crud::<RemoveCommunity>),
159 .route("/transfer", web::post().to(route_post::<TransferCommunity>))
160 .route("/ban_user", web::post().to(route_post::<BanFromCommunity>))
161 .route("/mod", web::post().to(route_post::<AddModToCommunity>)),
164 web::scope("/federated_instances")
165 .wrap(rate_limit.message())
166 .route("", web::get().to(route_get::<GetFederatedInstances>)),
170 // Handle POST to /post separately to add the post() rate limitter
171 web::resource("/post")
172 .guard(guard::Post())
173 .wrap(rate_limit.post())
174 .route(web::post().to(route_post_crud::<CreatePost>)),
178 .wrap(rate_limit.message())
179 .route("", web::get().to(route_get_crud::<GetPost>))
180 .route("", web::put().to(route_post_crud::<EditPost>))
181 .route("/delete", web::post().to(route_post_crud::<DeletePost>))
182 .route("/remove", web::post().to(route_post_crud::<RemovePost>))
185 web::post().to(route_post::<MarkPostAsRead>),
187 .route("/lock", web::post().to(route_post::<LockPost>))
188 .route("/feature", web::post().to(route_post::<FeaturePost>))
189 .route("/list", web::get().to(route_get_apub::<GetPosts>))
190 .route("/like", web::post().to(route_post::<CreatePostLike>))
191 .route("/save", web::put().to(route_post::<SavePost>))
192 .route("/report", web::post().to(route_post::<CreatePostReport>))
195 web::put().to(route_post::<ResolvePostReport>),
197 .route("/report/list", web::get().to(route_get::<ListPostReports>))
200 web::get().to(route_get::<GetSiteMetadata>),
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>)),
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>))
220 web::post().to(route_post::<MarkCommentReplyAsRead>),
224 web::post().to(route_post::<DistinguishComment>),
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>))
232 web::put().to(route_post::<ResolveCommentReport>),
236 web::get().to(route_get::<ListCommentReports>),
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>))
248 web::post().to(route_post_crud::<DeletePrivateMessage>),
252 web::post().to(route_post::<MarkPrivateMessageAsRead>),
256 web::post().to(route_post::<CreatePrivateMessageReport>),
260 web::put().to(route_post::<ResolvePrivateMessageReport>),
264 web::get().to(route_get::<ListPrivateMessageReports>),
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>)),
277 // Handle captcha separately
278 web::resource("/user/get_captcha")
279 .wrap(rate_limit.post())
280 .route(web::get().to(route_get::<GetCaptcha>)),
285 .wrap(rate_limit.message())
286 .route("", web::get().to(route_get_apub::<GetPersonDetails>))
287 .route("/mention", web::get().to(route_get::<GetPersonMentions>))
289 "/mention/mark_as_read",
290 web::post().to(route_post::<MarkPersonMentionAsRead>),
292 .route("/replies", web::get().to(route_get::<GetReplies>))
293 // Admin action. I don't like that it's in /user
294 .route("/ban", web::post().to(route_post::<BanPerson>))
295 .route("/banned", web::get().to(route_get::<GetBannedPersons>))
296 .route("/block", web::post().to(route_post::<BlockPerson>))
297 // Account actions. I don't like that they're in /user maybe /accounts
298 .route("/login", web::post().to(route_post::<Login>))
301 web::post().to(route_post_crud::<DeleteAccount>),
305 web::post().to(route_post::<PasswordReset>),
309 web::post().to(route_post::<PasswordChangeAfterReset>),
311 // mark_all_as_read feels off being in this section as well
314 web::post().to(route_post::<MarkAllAsRead>),
317 "/save_user_settings",
318 web::put().to(route_post::<SaveUserSettings>),
322 web::put().to(route_post::<ChangePassword>),
324 .route("/report_count", web::get().to(route_get::<GetReportCount>))
325 .route("/unread_count", web::get().to(route_get::<GetUnreadCount>))
326 .route("/verify_email", web::post().to(route_post::<VerifyEmail>))
327 .route("/leave_admin", web::post().to(route_post::<LeaveAdmin>)),
332 .wrap(rate_limit.message())
333 .route("/add", web::post().to(route_post::<AddAdmin>))
335 "/registration_application/count",
336 web::get().to(route_get::<GetUnreadRegistrationApplicationCount>),
339 "/registration_application/list",
340 web::get().to(route_get::<ListRegistrationApplications>),
343 "/registration_application/approve",
344 web::put().to(route_post::<ApproveRegistrationApplication>),
348 .route("/person", web::post().to(route_post::<PurgePerson>))
349 .route("/community", web::post().to(route_post::<PurgeCommunity>))
350 .route("/post", web::post().to(route_post::<PurgePost>))
351 .route("/comment", web::post().to(route_post::<PurgeComment>)),
355 web::scope("/custom_emoji")
356 .wrap(rate_limit.message())
357 .route("", web::post().to(route_post_crud::<CreateCustomEmoji>))
358 .route("", web::put().to(route_post_crud::<EditCustomEmoji>))
361 web::post().to(route_post_crud::<DeleteCustomEmoji>),
367 async fn perform<'a, Data>(
369 context: web::Data<LemmyContext>,
370 apub_data: activitypub_federation::config::Data<LemmyContext>,
371 ) -> Result<HttpResponse, Error>
374 + SendActivity<Response = <Data as Perform>::Response>
380 let res = data.perform(&context).await?;
381 SendActivity::send_activity(&data, &res, &apub_data).await?;
382 Ok(HttpResponse::Ok().json(res))
385 async fn route_get<'a, Data>(
386 data: web::Query<Data>,
387 context: web::Data<LemmyContext>,
388 apub_data: activitypub_federation::config::Data<LemmyContext>,
389 ) -> Result<HttpResponse, Error>
392 + SendActivity<Response = <Data as Perform>::Response>
398 perform::<Data>(data.0, context, apub_data).await
401 async fn route_get_apub<'a, Data>(
402 data: web::Query<Data>,
403 context: activitypub_federation::config::Data<LemmyContext>,
404 ) -> Result<HttpResponse, Error>
407 + SendActivity<Response = <Data as PerformApub>::Response>
413 let res = data.perform(&context).await?;
414 SendActivity::send_activity(&data.0, &res, &context).await?;
415 Ok(HttpResponse::Ok().json(res))
418 async fn route_post<'a, Data>(
419 data: web::Json<Data>,
420 context: web::Data<LemmyContext>,
421 apub_data: activitypub_federation::config::Data<LemmyContext>,
422 ) -> Result<HttpResponse, Error>
425 + SendActivity<Response = <Data as Perform>::Response>
431 perform::<Data>(data.0, context, apub_data).await
434 async fn perform_crud<'a, Data>(
436 context: web::Data<LemmyContext>,
437 apub_data: activitypub_federation::config::Data<LemmyContext>,
438 ) -> Result<HttpResponse, Error>
441 + SendActivity<Response = <Data as PerformCrud>::Response>
447 let res = data.perform(&context).await?;
448 SendActivity::send_activity(&data, &res, &apub_data).await?;
449 Ok(HttpResponse::Ok().json(res))
452 async fn route_get_crud<'a, Data>(
453 data: web::Query<Data>,
454 context: web::Data<LemmyContext>,
455 apub_data: activitypub_federation::config::Data<LemmyContext>,
456 ) -> Result<HttpResponse, Error>
459 + SendActivity<Response = <Data as PerformCrud>::Response>
465 perform_crud::<Data>(data.0, context, apub_data).await
468 async fn route_post_crud<'a, Data>(
469 data: web::Json<Data>,
470 context: web::Data<LemmyContext>,
471 apub_data: activitypub_federation::config::Data<LemmyContext>,
472 ) -> Result<HttpResponse, Error>
475 + SendActivity<Response = <Data as PerformCrud>::Response>
481 perform_crud::<Data>(data.0, context, apub_data).await