1 use actix_web::{guard, web, Error, HttpResponse, Result};
3 comment::{distinguish::distinguish_comment, like::like_comment, save::save_comment},
5 create::create_comment_report,
6 list::list_comment_reports,
7 resolve::resolve_comment_report,
10 add_mod::add_mod_to_community,
11 ban::ban_from_community,
12 block::block_community,
13 follow::follow_community,
16 local_user::{ban_person::ban_from_site, notifications::mark_reply_read::mark_reply_as_read},
17 post::{feature::feature_post, like::like_post, lock::lock_post},
18 post_report::create::create_post_report,
21 use lemmy_api_common::{
22 community::TransferCommunity,
23 context::LemmyContext,
36 MarkPersonMentionAsRead,
37 PasswordChangeAfterReset,
42 post::{GetSiteMetadata, ListPostReports, MarkPostAsRead, ResolvePostReport, SavePost},
44 CreatePrivateMessageReport,
45 ListPrivateMessageReports,
46 MarkPrivateMessageAsRead,
47 ResolvePrivateMessageReport,
50 ApproveRegistrationApplication,
51 GetFederatedInstances,
53 GetUnreadRegistrationApplicationCount,
55 ListRegistrationApplications,
64 create::create_comment,
65 delete::delete_comment,
67 remove::remove_comment,
68 update::update_comment,
71 create::create_community,
72 delete::delete_community,
73 list::list_communities,
74 remove::remove_community,
75 update::update_community,
78 create::create_custom_emoji,
79 delete::delete_custom_emoji,
80 update::update_custom_emoji,
90 create::create_private_message,
91 delete::delete_private_message,
92 read::get_private_message,
93 update::update_private_message,
95 site::{create::create_site, read::get_site, update::update_site},
96 user::{create::register, delete::delete_account},
100 list_comments::list_comments,
101 list_posts::list_posts,
102 read_community::get_community,
103 read_person::read_person,
104 resolve_object::resolve_object,
109 use lemmy_utils::{rate_limit::RateLimitCell, spawn_try_task, SYNCHRONOUS_FEDERATION};
110 use serde::Deserialize;
112 pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
114 web::scope("/api/v3")
118 .wrap(rate_limit.message())
119 .route("", web::get().to(get_site))
121 .route("", web::post().to(create_site))
122 .route("", web::put().to(update_site)),
125 web::resource("/modlog")
126 .wrap(rate_limit.message())
127 .route(web::get().to(route_get::<GetModlog>)),
130 web::resource("/search")
131 .wrap(rate_limit.search())
132 .route(web::get().to(search)),
135 web::resource("/resolve_object")
136 .wrap(rate_limit.message())
137 .route(web::get().to(resolve_object)),
141 web::resource("/community")
142 .guard(guard::Post())
143 .wrap(rate_limit.register())
144 .route(web::post().to(create_community)),
147 web::scope("/community")
148 .wrap(rate_limit.message())
149 .route("", web::get().to(get_community))
150 .route("", web::put().to(update_community))
151 .route("/hide", web::put().to(hide_community))
152 .route("/list", web::get().to(list_communities))
153 .route("/follow", web::post().to(follow_community))
154 .route("/block", web::post().to(block_community))
155 .route("/delete", web::post().to(delete_community))
157 .route("/remove", web::post().to(remove_community))
158 .route("/transfer", web::post().to(route_post::<TransferCommunity>))
159 .route("/ban_user", web::post().to(ban_from_community))
160 .route("/mod", web::post().to(add_mod_to_community)),
163 web::scope("/federated_instances")
164 .wrap(rate_limit.message())
165 .route("", web::get().to(route_get::<GetFederatedInstances>)),
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(create_post)),
177 .wrap(rate_limit.message())
178 .route("", web::get().to(get_post))
179 .route("", web::put().to(update_post))
180 .route("/delete", web::post().to(delete_post))
181 .route("/remove", web::post().to(remove_post))
184 web::post().to(route_post::<MarkPostAsRead>),
186 .route("/lock", web::post().to(lock_post))
187 .route("/feature", web::post().to(feature_post))
188 .route("/list", web::get().to(list_posts))
189 .route("/like", web::post().to(like_post))
190 .route("/save", web::put().to(route_post::<SavePost>))
191 .route("/report", web::post().to(create_post_report))
194 web::put().to(route_post::<ResolvePostReport>),
196 .route("/report/list", web::get().to(route_get::<ListPostReports>))
199 web::get().to(route_get::<GetSiteMetadata>),
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(create_comment)),
211 web::scope("/comment")
212 .wrap(rate_limit.message())
213 .route("", web::get().to(get_comment))
214 .route("", web::put().to(update_comment))
215 .route("/delete", web::post().to(delete_comment))
216 .route("/remove", web::post().to(remove_comment))
217 .route("/mark_as_read", web::post().to(mark_reply_as_read))
218 .route("/distinguish", web::post().to(distinguish_comment))
219 .route("/like", web::post().to(like_comment))
220 .route("/save", web::put().to(save_comment))
221 .route("/list", web::get().to(list_comments))
222 .route("/report", web::post().to(create_comment_report))
223 .route("/report/resolve", web::put().to(resolve_comment_report))
224 .route("/report/list", web::get().to(list_comment_reports)),
228 web::scope("/private_message")
229 .wrap(rate_limit.message())
230 .route("/list", web::get().to(get_private_message))
231 .route("", web::post().to(create_private_message))
232 .route("", web::put().to(update_private_message))
233 .route("/delete", web::post().to(delete_private_message))
236 web::post().to(route_post::<MarkPrivateMessageAsRead>),
240 web::post().to(route_post::<CreatePrivateMessageReport>),
244 web::put().to(route_post::<ResolvePrivateMessageReport>),
248 web::get().to(route_get::<ListPrivateMessageReports>),
253 // Account action, I don't like that it's in /user maybe /accounts
254 // Handle /user/register separately to add the register() rate limitter
255 web::resource("/user/register")
256 .guard(guard::Post())
257 .wrap(rate_limit.register())
258 .route(web::post().to(register)),
261 // Handle captcha separately
262 web::resource("/user/get_captcha")
263 .wrap(rate_limit.post())
264 .route(web::get().to(route_get::<GetCaptcha>)),
269 .wrap(rate_limit.message())
270 .route("", web::get().to(read_person))
271 .route("/mention", web::get().to(route_get::<GetPersonMentions>))
273 "/mention/mark_as_read",
274 web::post().to(route_post::<MarkPersonMentionAsRead>),
276 .route("/replies", web::get().to(route_get::<GetReplies>))
277 // Admin action. I don't like that it's in /user
278 .route("/ban", web::post().to(ban_from_site))
279 .route("/banned", web::get().to(route_get::<GetBannedPersons>))
280 .route("/block", web::post().to(route_post::<BlockPerson>))
281 // Account actions. I don't like that they're in /user maybe /accounts
282 .route("/login", web::post().to(route_post::<Login>))
283 .route("/delete_account", web::post().to(delete_account))
286 web::post().to(route_post::<PasswordReset>),
290 web::post().to(route_post::<PasswordChangeAfterReset>),
292 // mark_all_as_read feels off being in this section as well
295 web::post().to(route_post::<MarkAllAsRead>),
298 "/save_user_settings",
299 web::put().to(route_post::<SaveUserSettings>),
303 web::put().to(route_post::<ChangePassword>),
305 .route("/report_count", web::get().to(route_get::<GetReportCount>))
306 .route("/unread_count", web::get().to(route_get::<GetUnreadCount>))
307 .route("/verify_email", web::post().to(route_post::<VerifyEmail>))
308 .route("/leave_admin", web::post().to(route_post::<LeaveAdmin>)),
313 .wrap(rate_limit.message())
314 .route("/add", web::post().to(route_post::<AddAdmin>))
316 "/registration_application/count",
317 web::get().to(route_get::<GetUnreadRegistrationApplicationCount>),
320 "/registration_application/list",
321 web::get().to(route_get::<ListRegistrationApplications>),
324 "/registration_application/approve",
325 web::put().to(route_post::<ApproveRegistrationApplication>),
329 .route("/person", web::post().to(route_post::<PurgePerson>))
330 .route("/community", web::post().to(route_post::<PurgeCommunity>))
331 .route("/post", web::post().to(route_post::<PurgePost>))
332 .route("/comment", web::post().to(route_post::<PurgeComment>)),
336 web::scope("/custom_emoji")
337 .wrap(rate_limit.message())
338 .route("", web::post().to(create_custom_emoji))
339 .route("", web::put().to(update_custom_emoji))
340 .route("/delete", web::post().to(delete_custom_emoji)),
345 async fn perform<'a, Data>(
347 context: web::Data<LemmyContext>,
348 apub_data: activitypub_federation::config::Data<LemmyContext>,
349 ) -> Result<HttpResponse, Error>
352 + SendActivity<Response = <Data as Perform>::Response>
358 let res = data.perform(&context).await?;
359 let res_clone = res.clone();
360 let fed_task = async move { SendActivity::send_activity(&data, &res_clone, &apub_data).await };
361 if *SYNCHRONOUS_FEDERATION {
364 spawn_try_task(fed_task);
366 Ok(HttpResponse::Ok().json(&res))
369 async fn route_get<'a, Data>(
370 data: web::Query<Data>,
371 context: web::Data<LemmyContext>,
372 apub_data: activitypub_federation::config::Data<LemmyContext>,
373 ) -> Result<HttpResponse, Error>
376 + SendActivity<Response = <Data as Perform>::Response>
382 perform::<Data>(data.0, context, apub_data).await
385 async fn route_post<'a, Data>(
386 data: web::Json<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