name = "lemmy_api"
version = "0.18.1"
dependencies = [
+ "activitypub_federation",
"actix-web",
"anyhow",
"async-trait",
lemmy_db_views_moderator = { workspace = true, features = ["full"] }
lemmy_db_views_actor = { workspace = true, features = ["full"] }
lemmy_api_common = { workspace = true, features = ["full"] }
+activitypub_federation = { workspace = true }
bcrypt = { workspace = true }
serde = { workspace = true }
actix-web = { workspace = true }
-use crate::Perform;
-use actix_web::web::Data;
+use actix_web::web::{Data, Json};
use lemmy_api_common::{
comment::{CommentResponse, DistinguishComment},
context::LemmyContext,
use lemmy_db_views::structs::CommentView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
-#[async_trait::async_trait(?Send)]
-impl Perform for DistinguishComment {
- type Response = CommentResponse;
-
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommentResponse, LemmyError> {
- let data: &DistinguishComment = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
-
- let comment_id = data.comment_id;
- let orig_comment = CommentView::read(&mut context.pool(), comment_id, None).await?;
-
- check_community_ban(
- local_user_view.person.id,
- orig_comment.community.id,
- &mut context.pool(),
- )
- .await?;
-
- // Verify that only a mod or admin can distinguish a comment
- is_mod_or_admin(
- &mut context.pool(),
- local_user_view.person.id,
- orig_comment.community.id,
- )
- .await?;
-
- // Update the Comment
- let comment_id = data.comment_id;
- let form = CommentUpdateForm::builder()
- .distinguished(Some(data.distinguished))
- .build();
- Comment::update(&mut context.pool(), comment_id, &form)
- .await
- .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?;
-
- let comment_id = data.comment_id;
- let person_id = local_user_view.person.id;
- let comment_view = CommentView::read(&mut context.pool(), comment_id, Some(person_id)).await?;
-
- Ok(CommentResponse {
- comment_view,
- recipient_ids: Vec::new(),
- form_id: None,
- })
- }
+#[tracing::instrument(skip(context))]
+pub async fn distinguish_comment(
+ data: Json<DistinguishComment>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CommentResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
+
+ let comment_id = data.comment_id;
+ let orig_comment = CommentView::read(&mut context.pool(), comment_id, None).await?;
+
+ check_community_ban(
+ local_user_view.person.id,
+ orig_comment.community.id,
+ &mut context.pool(),
+ )
+ .await?;
+
+ // Verify that only a mod or admin can distinguish a comment
+ is_mod_or_admin(
+ &mut context.pool(),
+ local_user_view.person.id,
+ orig_comment.community.id,
+ )
+ .await?;
+
+ // Update the Comment
+ let comment_id = data.comment_id;
+ let form = CommentUpdateForm::builder()
+ .distinguished(Some(data.distinguished))
+ .build();
+ Comment::update(&mut context.pool(), comment_id, &form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?;
+
+ let comment_id = data.comment_id;
+ let person_id = local_user_view.person.id;
+ let comment_view = CommentView::read(&mut context.pool(), comment_id, Some(person_id)).await?;
+
+ Ok(Json(CommentResponse {
+ comment_view,
+ recipient_ids: Vec::new(),
+ form_id: None,
+ }))
}
-mod distinguish;
-mod like;
-mod save;
+pub mod distinguish;
+pub mod like;
+pub mod save;
-use crate::Perform;
-use actix_web::web::Data;
+use actix_web::web::{Data, Json};
use lemmy_api_common::{
comment::{CommentResponse, SaveComment},
context::LemmyContext,
use lemmy_db_views::structs::CommentView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
-#[async_trait::async_trait(?Send)]
-impl Perform for SaveComment {
- type Response = CommentResponse;
+#[tracing::instrument(skip(context))]
+pub async fn save_comment(
+ data: Json<SaveComment>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CommentResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommentResponse, LemmyError> {
- let data: &SaveComment = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ let comment_saved_form = CommentSavedForm {
+ comment_id: data.comment_id,
+ person_id: local_user_view.person.id,
+ };
- let comment_saved_form = CommentSavedForm {
- comment_id: data.comment_id,
- person_id: local_user_view.person.id,
- };
-
- if data.save {
- CommentSaved::save(&mut context.pool(), &comment_saved_form)
- .await
- .with_lemmy_type(LemmyErrorType::CouldntSaveComment)?;
- } else {
- CommentSaved::unsave(&mut context.pool(), &comment_saved_form)
- .await
- .with_lemmy_type(LemmyErrorType::CouldntSaveComment)?;
- }
+ if data.save {
+ CommentSaved::save(&mut context.pool(), &comment_saved_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntSaveComment)?;
+ } else {
+ CommentSaved::unsave(&mut context.pool(), &comment_saved_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntSaveComment)?;
+ }
- let comment_id = data.comment_id;
- let person_id = local_user_view.person.id;
- let comment_view = CommentView::read(&mut context.pool(), comment_id, Some(person_id)).await?;
+ let comment_id = data.comment_id;
+ let person_id = local_user_view.person.id;
+ let comment_view = CommentView::read(&mut context.pool(), comment_id, Some(person_id)).await?;
- Ok(CommentResponse {
- comment_view,
- recipient_ids: Vec::new(),
- form_id: None,
- })
- }
+ Ok(Json(CommentResponse {
+ comment_view,
+ recipient_ids: Vec::new(),
+ form_id: None,
+ }))
}
-use crate::Perform;
-use actix_web::web::Data;
+use actix_web::web::{Data, Json, Query};
use lemmy_api_common::{
comment::{ListCommentReports, ListCommentReportsResponse},
context::LemmyContext,
/// Lists comment reports for a community if an id is supplied
/// or returns all comment reports for communities a user moderates
-#[async_trait::async_trait(?Send)]
-impl Perform for ListCommentReports {
- type Response = ListCommentReportsResponse;
+#[tracing::instrument(skip(context))]
+pub async fn list_comment_reports(
+ data: Query<ListCommentReports>,
+ context: Data<LemmyContext>,
+) -> Result<Json<ListCommentReportsResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- ) -> Result<ListCommentReportsResponse, LemmyError> {
- let data: &ListCommentReports = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ let community_id = data.community_id;
+ let unresolved_only = data.unresolved_only;
- let community_id = data.community_id;
- let unresolved_only = data.unresolved_only;
-
- let page = data.page;
- let limit = data.limit;
- let comment_reports = CommentReportQuery {
- community_id,
- unresolved_only,
- page,
- limit,
- }
- .list(&mut context.pool(), &local_user_view.person)
- .await?;
-
- Ok(ListCommentReportsResponse { comment_reports })
+ let page = data.page;
+ let limit = data.limit;
+ let comment_reports = CommentReportQuery {
+ community_id,
+ unresolved_only,
+ page,
+ limit,
}
+ .list(&mut context.pool(), &local_user_view.person)
+ .await?;
+
+ Ok(Json(ListCommentReportsResponse { comment_reports }))
}
-mod create;
-mod list;
-mod resolve;
+pub mod create;
+pub mod list;
+pub mod resolve;
-use crate::Perform;
-use actix_web::web::Data;
+use actix_web::web::{Data, Json};
use lemmy_api_common::{
comment::{CommentReportResponse, ResolveCommentReport},
context::LemmyContext,
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
/// Resolves or unresolves a comment report and notifies the moderators of the community
-#[async_trait::async_trait(?Send)]
-impl Perform for ResolveCommentReport {
- type Response = CommentReportResponse;
+#[tracing::instrument(skip(context))]
+pub async fn resolve_comment_report(
+ data: Json<ResolveCommentReport>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CommentReportResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- ) -> Result<CommentReportResponse, LemmyError> {
- let data: &ResolveCommentReport = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ let report_id = data.report_id;
+ let person_id = local_user_view.person.id;
+ let report = CommentReportView::read(&mut context.pool(), report_id, person_id).await?;
- let report_id = data.report_id;
- let person_id = local_user_view.person.id;
- let report = CommentReportView::read(&mut context.pool(), report_id, person_id).await?;
+ let person_id = local_user_view.person.id;
+ is_mod_or_admin(&mut context.pool(), person_id, report.community.id).await?;
- let person_id = local_user_view.person.id;
- is_mod_or_admin(&mut context.pool(), person_id, report.community.id).await?;
-
- if data.resolved {
- CommentReport::resolve(&mut context.pool(), report_id, person_id)
- .await
- .with_lemmy_type(LemmyErrorType::CouldntResolveReport)?;
- } else {
- CommentReport::unresolve(&mut context.pool(), report_id, person_id)
- .await
- .with_lemmy_type(LemmyErrorType::CouldntResolveReport)?;
- }
+ if data.resolved {
+ CommentReport::resolve(&mut context.pool(), report_id, person_id)
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntResolveReport)?;
+ } else {
+ CommentReport::unresolve(&mut context.pool(), report_id, person_id)
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntResolveReport)?;
+ }
- let report_id = data.report_id;
- let comment_report_view =
- CommentReportView::read(&mut context.pool(), report_id, person_id).await?;
+ let report_id = data.report_id;
+ let comment_report_view =
+ CommentReportView::read(&mut context.pool(), report_id, person_id).await?;
- Ok(CommentReportResponse {
- comment_report_view,
- })
- }
+ Ok(Json(CommentReportResponse {
+ comment_report_view,
+ }))
}
};
use std::io::Cursor;
-mod comment;
-mod comment_report;
-mod community;
-mod local_user;
-mod post;
-mod post_report;
-mod private_message;
-mod private_message_report;
-mod site;
+pub mod comment;
+pub mod comment_report;
+pub mod community;
+pub mod local_user;
+pub mod post;
+pub mod post_report;
+pub mod private_message;
+pub mod private_message_report;
+pub mod site;
#[async_trait::async_trait(?Send)]
pub trait Perform {
-mod add_admin;
-mod ban_person;
-mod block;
-mod change_password;
-mod change_password_after_reset;
-mod get_captcha;
-mod list_banned;
-mod login;
-mod notifications;
-mod report_count;
-mod reset_password;
-mod save_settings;
-mod verify_email;
+pub mod add_admin;
+pub mod ban_person;
+pub mod block;
+pub mod change_password;
+pub mod change_password_after_reset;
+pub mod get_captcha;
+pub mod list_banned;
+pub mod login;
+pub mod notifications;
+pub mod report_count;
+pub mod reset_password;
+pub mod save_settings;
+pub mod verify_email;
-use crate::Perform;
-use actix_web::web::Data;
+use actix_web::web::{Data, Json};
use lemmy_api_common::{
context::LemmyContext,
person::{CommentReplyResponse, MarkCommentReplyAsRead},
use lemmy_db_views_actor::structs::CommentReplyView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
-#[async_trait::async_trait(?Send)]
-impl Perform for MarkCommentReplyAsRead {
- type Response = CommentReplyResponse;
+#[tracing::instrument(skip(context))]
+pub async fn mark_reply_as_read(
+ data: Json<MarkCommentReplyAsRead>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CommentReplyResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- ) -> Result<CommentReplyResponse, LemmyError> {
- let data = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ let comment_reply_id = data.comment_reply_id;
+ let read_comment_reply = CommentReply::read(&mut context.pool(), comment_reply_id).await?;
- let comment_reply_id = data.comment_reply_id;
- let read_comment_reply = CommentReply::read(&mut context.pool(), comment_reply_id).await?;
-
- if local_user_view.person.id != read_comment_reply.recipient_id {
- return Err(LemmyErrorType::CouldntUpdateComment)?;
- }
+ if local_user_view.person.id != read_comment_reply.recipient_id {
+ return Err(LemmyErrorType::CouldntUpdateComment)?;
+ }
- let comment_reply_id = read_comment_reply.id;
- let read = Some(data.read);
+ let comment_reply_id = read_comment_reply.id;
+ let read = Some(data.read);
- CommentReply::update(
- &mut context.pool(),
- comment_reply_id,
- &CommentReplyUpdateForm { read },
- )
- .await
- .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?;
+ CommentReply::update(
+ &mut context.pool(),
+ comment_reply_id,
+ &CommentReplyUpdateForm { read },
+ )
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?;
- let comment_reply_id = read_comment_reply.id;
- let person_id = local_user_view.person.id;
- let comment_reply_view =
- CommentReplyView::read(&mut context.pool(), comment_reply_id, Some(person_id)).await?;
+ let comment_reply_id = read_comment_reply.id;
+ let person_id = local_user_view.person.id;
+ let comment_reply_view =
+ CommentReplyView::read(&mut context.pool(), comment_reply_id, Some(person_id)).await?;
- Ok(CommentReplyResponse { comment_reply_view })
- }
+ Ok(Json(CommentReplyResponse { comment_reply_view }))
}
-mod list_mentions;
-mod list_replies;
-mod mark_all_read;
-mod mark_mention_read;
-mod mark_reply_read;
-mod unread_count;
+pub mod list_mentions;
+pub mod list_replies;
+pub mod mark_all_read;
+pub mod mark_mention_read;
+pub mod mark_reply_read;
+pub mod unread_count;
use lemmy_utils::{error::LemmyError, utils::mention::MentionData};
pub async fn build_comment_response(
- context: &Data<LemmyContext>,
+ context: &LemmyContext,
comment_id: CommentId,
local_user_view: Option<LocalUserView>,
form_id: Option<String>,
use crate::context::LemmyContext;
use activitypub_federation::config::Data;
use futures::future::BoxFuture;
-use lemmy_db_schema::source::post::Post;
+use lemmy_db_schema::source::{comment::Comment, post::Post};
use lemmy_utils::{error::LemmyResult, SYNCHRONOUS_FEDERATION};
use once_cell::sync::{Lazy, OnceCell};
use tokio::{
#[derive(Debug)]
pub enum SendActivityData {
CreatePost(Post),
+ CreateComment(Comment),
}
// TODO: instead of static, move this into LemmyContext. make sure that stopping the process with
-use crate::PerformCrud;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
build_response::{build_comment_response, send_local_notifs},
comment::{CommentResponse, CreateComment},
context::LemmyContext,
+ send_activity::{ActivityChannel, SendActivityData},
utils::{
check_community_ban,
check_community_deleted_or_removed,
validation::is_valid_body_field,
},
};
+use std::ops::Deref;
const MAX_COMMENT_DEPTH_LIMIT: usize = 100;
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for CreateComment {
- type Response = CommentResponse;
-
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommentResponse, LemmyError> {
- let data: &CreateComment = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
- let local_site = LocalSite::read(&mut context.pool()).await?;
-
- let content = remove_slurs(
- &data.content.clone(),
- &local_site_to_slur_regex(&local_site),
- );
- is_valid_body_field(&Some(content.clone()), false)?;
- let content = sanitize_html(&content);
-
- // Check for a community ban
- let post_id = data.post_id;
- let post = get_post(post_id, &mut context.pool()).await?;
- let community_id = post.community_id;
-
- check_community_ban(local_user_view.person.id, community_id, &mut context.pool()).await?;
- check_community_deleted_or_removed(community_id, &mut context.pool()).await?;
- check_post_deleted_or_removed(&post)?;
-
- // Check if post is locked, no new comments
- if post.locked {
- return Err(LemmyErrorType::Locked)?;
- }
+#[tracing::instrument(skip(context))]
+pub async fn create_comment(
+ data: Json<CreateComment>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CommentResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
+ let local_site = LocalSite::read(&mut context.pool()).await?;
+
+ let content = remove_slurs(
+ &data.content.clone(),
+ &local_site_to_slur_regex(&local_site),
+ );
+ is_valid_body_field(&Some(content.clone()), false)?;
+ let content = sanitize_html(&content);
+
+ // Check for a community ban
+ let post_id = data.post_id;
+ let post = get_post(post_id, &mut context.pool()).await?;
+ let community_id = post.community_id;
+
+ check_community_ban(local_user_view.person.id, community_id, &mut context.pool()).await?;
+ check_community_deleted_or_removed(community_id, &mut context.pool()).await?;
+ check_post_deleted_or_removed(&post)?;
+
+ // Check if post is locked, no new comments
+ if post.locked {
+ return Err(LemmyErrorType::Locked)?;
+ }
- // Fetch the parent, if it exists
- let parent_opt = if let Some(parent_id) = data.parent_id {
- Comment::read(&mut context.pool(), parent_id).await.ok()
- } else {
- None
- };
-
- // If there's a parent_id, check to make sure that comment is in that post
- // Strange issue where sometimes the post ID of the parent comment is incorrect
- if let Some(parent) = parent_opt.as_ref() {
- if parent.post_id != post_id {
- return Err(LemmyErrorType::CouldntCreateComment)?;
- }
- check_comment_depth(parent)?;
+ // Fetch the parent, if it exists
+ let parent_opt = if let Some(parent_id) = data.parent_id {
+ Comment::read(&mut context.pool(), parent_id).await.ok()
+ } else {
+ None
+ };
+
+ // If there's a parent_id, check to make sure that comment is in that post
+ // Strange issue where sometimes the post ID of the parent comment is incorrect
+ if let Some(parent) = parent_opt.as_ref() {
+ if parent.post_id != post_id {
+ return Err(LemmyErrorType::CouldntCreateComment)?;
}
+ check_comment_depth(parent)?;
+ }
- CommunityLanguage::is_allowed_community_language(
- &mut context.pool(),
- data.language_id,
- community_id,
- )
- .await?;
-
- // attempt to set default language if none was provided
- let language_id = match data.language_id {
- Some(lid) => Some(lid),
- None => {
- default_post_language(
- &mut context.pool(),
- community_id,
- local_user_view.local_user.id,
- )
- .await?
- }
- };
-
- let comment_form = CommentInsertForm::builder()
- .content(content.clone())
- .post_id(data.post_id)
- .creator_id(local_user_view.person.id)
- .language_id(language_id)
- .build();
-
- // Create the comment
- let parent_path = parent_opt.clone().map(|t| t.path);
- let inserted_comment =
- Comment::create(&mut context.pool(), &comment_form, parent_path.as_ref())
- .await
- .with_lemmy_type(LemmyErrorType::CouldntCreateComment)?;
-
- // Necessary to update the ap_id
- let inserted_comment_id = inserted_comment.id;
- let protocol_and_hostname = context.settings().get_protocol_and_hostname();
-
- let apub_id = generate_local_apub_endpoint(
- EndpointType::Comment,
- &inserted_comment_id.to_string(),
- &protocol_and_hostname,
- )?;
- let updated_comment = Comment::update(
- &mut context.pool(),
- inserted_comment_id,
- &CommentUpdateForm::builder().ap_id(Some(apub_id)).build(),
- )
+ CommunityLanguage::is_allowed_community_language(
+ &mut context.pool(),
+ data.language_id,
+ community_id,
+ )
+ .await?;
+
+ // attempt to set default language if none was provided
+ let language_id = match data.language_id {
+ Some(lid) => Some(lid),
+ None => {
+ default_post_language(
+ &mut context.pool(),
+ community_id,
+ local_user_view.local_user.id,
+ )
+ .await?
+ }
+ };
+
+ let comment_form = CommentInsertForm::builder()
+ .content(content.clone())
+ .post_id(data.post_id)
+ .creator_id(local_user_view.person.id)
+ .language_id(language_id)
+ .build();
+
+ // Create the comment
+ let parent_path = parent_opt.clone().map(|t| t.path);
+ let inserted_comment = Comment::create(&mut context.pool(), &comment_form, parent_path.as_ref())
.await
.with_lemmy_type(LemmyErrorType::CouldntCreateComment)?;
- // Scan the comment for user mentions, add those rows
- let mentions = scrape_text_for_mentions(&content);
- let recipient_ids = send_local_notifs(
- mentions,
- &updated_comment,
- &local_user_view.person,
- &post,
- true,
- context,
- )
- .await?;
-
- // You like your own comment by default
- let like_form = CommentLikeForm {
- comment_id: inserted_comment.id,
- post_id: post.id,
- person_id: local_user_view.person.id,
- score: 1,
- };
+ // Necessary to update the ap_id
+ let inserted_comment_id = inserted_comment.id;
+ let protocol_and_hostname = context.settings().get_protocol_and_hostname();
+
+ let apub_id = generate_local_apub_endpoint(
+ EndpointType::Comment,
+ &inserted_comment_id.to_string(),
+ &protocol_and_hostname,
+ )?;
+ let updated_comment = Comment::update(
+ &mut context.pool(),
+ inserted_comment_id,
+ &CommentUpdateForm::builder().ap_id(Some(apub_id)).build(),
+ )
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntCreateComment)?;
+
+ // Scan the comment for user mentions, add those rows
+ let mentions = scrape_text_for_mentions(&content);
+ let recipient_ids = send_local_notifs(
+ mentions,
+ &updated_comment,
+ &local_user_view.person,
+ &post,
+ true,
+ &context,
+ )
+ .await?;
+
+ // You like your own comment by default
+ let like_form = CommentLikeForm {
+ comment_id: inserted_comment.id,
+ post_id: post.id,
+ person_id: local_user_view.person.id,
+ score: 1,
+ };
+
+ CommentLike::like(&mut context.pool(), &like_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntLikeComment)?;
+
+ ActivityChannel::submit_activity(
+ SendActivityData::CreateComment(updated_comment.clone()),
+ &context,
+ )
+ .await?;
+
+ // If its a reply, mark the parent as read
+ if let Some(parent) = parent_opt {
+ let parent_id = parent.id;
+ let comment_reply = CommentReply::read_by_comment(&mut context.pool(), parent_id).await;
+ if let Ok(reply) = comment_reply {
+ CommentReply::update(
+ &mut context.pool(),
+ reply.id,
+ &CommentReplyUpdateForm { read: Some(true) },
+ )
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntUpdateReplies)?;
+ }
- CommentLike::like(&mut context.pool(), &like_form)
+ // If the parent has PersonMentions mark them as read too
+ let person_id = local_user_view.person.id;
+ let person_mention =
+ PersonMention::read_by_comment_and_person(&mut context.pool(), parent_id, person_id).await;
+ if let Ok(mention) = person_mention {
+ PersonMention::update(
+ &mut context.pool(),
+ mention.id,
+ &PersonMentionUpdateForm { read: Some(true) },
+ )
.await
- .with_lemmy_type(LemmyErrorType::CouldntLikeComment)?;
-
- // If its a reply, mark the parent as read
- if let Some(parent) = parent_opt {
- let parent_id = parent.id;
- let comment_reply = CommentReply::read_by_comment(&mut context.pool(), parent_id).await;
- if let Ok(reply) = comment_reply {
- CommentReply::update(
- &mut context.pool(),
- reply.id,
- &CommentReplyUpdateForm { read: Some(true) },
- )
- .await
- .with_lemmy_type(LemmyErrorType::CouldntUpdateReplies)?;
- }
-
- // If the parent has PersonMentions mark them as read too
- let person_id = local_user_view.person.id;
- let person_mention =
- PersonMention::read_by_comment_and_person(&mut context.pool(), parent_id, person_id).await;
- if let Ok(mention) = person_mention {
- PersonMention::update(
- &mut context.pool(),
- mention.id,
- &PersonMentionUpdateForm { read: Some(true) },
- )
- .await
- .with_lemmy_type(LemmyErrorType::CouldntUpdatePersonMentions)?;
- }
+ .with_lemmy_type(LemmyErrorType::CouldntUpdatePersonMentions)?;
}
+ }
+ Ok(Json(
build_comment_response(
- context,
+ context.deref(),
inserted_comment.id,
Some(local_user_view),
- self.form_id.clone(),
+ data.form_id.clone(),
recipient_ids,
)
- .await
- }
+ .await?,
+ ))
}
pub fn check_comment_depth(comment: &Comment) -> Result<(), LemmyError> {
};
use lemmy_db_views::structs::CommentView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
+use std::ops::Deref;
#[async_trait::async_trait(?Send)]
impl PerformCrud for DeleteComment {
.await?;
build_comment_response(
- context,
+ context.deref(),
updated_comment.id,
Some(local_user_view),
None,
-mod create;
-mod delete;
-mod read;
-mod remove;
-mod update;
+pub mod create;
+pub mod delete;
+pub mod read;
+pub mod remove;
+pub mod update;
-use crate::PerformCrud;
-use actix_web::web::Data;
+use actix_web::web::{Data, Json, Query};
use lemmy_api_common::{
build_response::build_comment_response,
comment::{CommentResponse, GetComment},
};
use lemmy_db_schema::source::local_site::LocalSite;
use lemmy_utils::error::LemmyError;
+use std::ops::Deref;
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for GetComment {
- type Response = CommentResponse;
+#[tracing::instrument(skip(context))]
+pub async fn get_comment(
+ data: Query<GetComment>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CommentResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), &context).await;
+ let local_site = LocalSite::read(&mut context.pool()).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
- let data = self;
- let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), context).await;
- let local_site = LocalSite::read(&mut context.pool()).await?;
+ check_private_instance(&local_user_view, &local_site)?;
- check_private_instance(&local_user_view, &local_site)?;
-
- build_comment_response(context, data.id, local_user_view, None, vec![]).await
- }
+ Ok(Json(
+ build_comment_response(context.deref(), data.id, local_user_view, None, vec![]).await?,
+ ))
}
};
use lemmy_db_views::structs::CommentView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
+use std::ops::Deref;
#[async_trait::async_trait(?Send)]
impl PerformCrud for RemoveComment {
.await?;
build_comment_response(
- context,
+ context.deref(),
updated_comment.id,
Some(local_user_view),
None,
validation::is_valid_body_field,
},
};
+use std::ops::Deref;
#[async_trait::async_trait(?Send)]
impl PerformCrud for EditComment {
.await?;
build_comment_response(
- context,
+ context.deref(),
updated_comment.id,
Some(local_user_view),
self.form_id.clone(),
-use crate::PerformCrud;
-use actix_web::web::Data;
+use actix_web::web::{Data, Json, Query};
use lemmy_api_common::{
community::{ListCommunities, ListCommunitiesResponse},
context::LemmyContext,
use lemmy_db_views_actor::community_view::CommunityQuery;
use lemmy_utils::error::LemmyError;
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for ListCommunities {
- type Response = ListCommunitiesResponse;
+#[tracing::instrument(skip(context))]
+pub async fn list_communities(
+ data: Query<ListCommunities>,
+ context: Data<LemmyContext>,
+) -> Result<Json<ListCommunitiesResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), &context).await;
+ let local_site = LocalSite::read(&mut context.pool()).await?;
+ let is_admin = local_user_view.as_ref().map(|luv| is_admin(luv).is_ok());
- #[tracing::instrument(skip(context))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- ) -> Result<ListCommunitiesResponse, LemmyError> {
- let data: &ListCommunities = self;
- let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), context).await;
- let local_site = LocalSite::read(&mut context.pool()).await?;
- let is_admin = local_user_view.as_ref().map(|luv| is_admin(luv).is_ok());
+ check_private_instance(&local_user_view, &local_site)?;
- check_private_instance(&local_user_view, &local_site)?;
-
- let sort = data.sort;
- let listing_type = data.type_;
- let show_nsfw = data.show_nsfw;
- let page = data.page;
- let limit = data.limit;
- let local_user = local_user_view.map(|l| l.local_user);
- let communities = CommunityQuery {
- listing_type,
- show_nsfw,
- sort,
- local_user: local_user.as_ref(),
- page,
- limit,
- is_mod_or_admin: is_admin,
- ..Default::default()
- }
- .list(&mut context.pool())
- .await?;
-
- // Return the jwt
- Ok(ListCommunitiesResponse { communities })
+ let sort = data.sort;
+ let listing_type = data.type_;
+ let show_nsfw = data.show_nsfw;
+ let page = data.page;
+ let limit = data.limit;
+ let local_user = local_user_view.map(|l| l.local_user);
+ let communities = CommunityQuery {
+ listing_type,
+ show_nsfw,
+ sort,
+ local_user: local_user.as_ref(),
+ page,
+ limit,
+ is_mod_or_admin: is_admin,
+ ..Default::default()
}
+ .list(&mut context.pool())
+ .await?;
+
+ // Return the jwt
+ Ok(Json(ListCommunitiesResponse { communities }))
}
-mod create;
-mod delete;
-mod list;
-mod remove;
-mod update;
+pub mod create;
+pub mod delete;
+pub mod list;
+pub mod remove;
+pub mod update;
use lemmy_api_common::context::LemmyContext;
use lemmy_utils::error::LemmyError;
-mod comment;
-mod community;
-mod custom_emoji;
+pub mod comment;
+pub mod community;
+pub mod custom_emoji;
pub mod post;
-mod private_message;
-mod site;
-mod user;
+pub mod private_message;
+pub mod site;
+pub mod user;
#[async_trait::async_trait(?Send)]
pub trait PerformCrud {
pub mod create;
-mod delete;
-mod read;
-mod remove;
-mod update;
+pub mod delete;
+pub mod read;
+pub mod remove;
+pub mod update;
-use crate::PerformCrud;
-use actix_web::web::Data;
+use actix_web::web::{Data, Json, Query};
use lemmy_api_common::{
context::LemmyContext,
post::{GetPost, GetPostResponse},
use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView};
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for GetPost {
- type Response = GetPostResponse;
+#[tracing::instrument(skip(context))]
+pub async fn get_post(
+ data: Query<GetPost>,
+ context: Data<LemmyContext>,
+) -> Result<Json<GetPostResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), &context).await;
+ let local_site = LocalSite::read(&mut context.pool()).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetPostResponse, LemmyError> {
- let data: &GetPost = self;
- let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), context).await;
- let local_site = LocalSite::read(&mut context.pool()).await?;
+ check_private_instance(&local_user_view, &local_site)?;
- check_private_instance(&local_user_view, &local_site)?;
+ let person_id = local_user_view.as_ref().map(|u| u.person.id);
- let person_id = local_user_view.as_ref().map(|u| u.person.id);
+ // I'd prefer fetching the post_view by a comment join, but it adds a lot of boilerplate
+ let post_id = if let Some(id) = data.id {
+ id
+ } else if let Some(comment_id) = data.comment_id {
+ Comment::read(&mut context.pool(), comment_id)
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntFindPost)?
+ .post_id
+ } else {
+ Err(LemmyErrorType::CouldntFindPost)?
+ };
- // I'd prefer fetching the post_view by a comment join, but it adds a lot of boilerplate
- let post_id = if let Some(id) = data.id {
- id
- } else if let Some(comment_id) = data.comment_id {
- Comment::read(&mut context.pool(), comment_id)
- .await
- .with_lemmy_type(LemmyErrorType::CouldntFindPost)?
- .post_id
- } else {
- Err(LemmyErrorType::CouldntFindPost)?
- };
+ // Check to see if the person is a mod or admin, to show deleted / removed
+ let community_id = Post::read(&mut context.pool(), post_id).await?.community_id;
+ let is_mod_or_admin = is_mod_or_admin_opt(
+ &mut context.pool(),
+ local_user_view.as_ref(),
+ Some(community_id),
+ )
+ .await
+ .is_ok();
- // Check to see if the person is a mod or admin, to show deleted / removed
- let community_id = Post::read(&mut context.pool(), post_id).await?.community_id;
- let is_mod_or_admin = is_mod_or_admin_opt(
- &mut context.pool(),
- local_user_view.as_ref(),
- Some(community_id),
- )
- .await
- .is_ok();
+ let post_view = PostView::read(
+ &mut context.pool(),
+ post_id,
+ person_id,
+ Some(is_mod_or_admin),
+ )
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntFindPost)?;
- let post_view = PostView::read(
- &mut context.pool(),
- post_id,
- person_id,
- Some(is_mod_or_admin),
- )
- .await
- .with_lemmy_type(LemmyErrorType::CouldntFindPost)?;
+ // Mark the post as read
+ let post_id = post_view.post.id;
+ if let Some(person_id) = person_id {
+ mark_post_as_read(person_id, post_id, &mut context.pool()).await?;
+ }
- // Mark the post as read
- let post_id = post_view.post.id;
- if let Some(person_id) = person_id {
- mark_post_as_read(person_id, post_id, &mut context.pool()).await?;
- }
+ // Necessary for the sidebar subscribed
+ let community_view = CommunityView::read(
+ &mut context.pool(),
+ community_id,
+ person_id,
+ Some(is_mod_or_admin),
+ )
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntFindCommunity)?;
- // Necessary for the sidebar subscribed
- let community_view = CommunityView::read(
- &mut context.pool(),
- community_id,
+ // Insert into PersonPostAggregates
+ // to update the read_comments count
+ if let Some(person_id) = person_id {
+ let read_comments = post_view.counts.comments;
+ let person_post_agg_form = PersonPostAggregatesForm {
person_id,
- Some(is_mod_or_admin),
- )
- .await
- .with_lemmy_type(LemmyErrorType::CouldntFindCommunity)?;
-
- // Insert into PersonPostAggregates
- // to update the read_comments count
- if let Some(person_id) = person_id {
- let read_comments = post_view.counts.comments;
- let person_post_agg_form = PersonPostAggregatesForm {
- person_id,
- post_id,
- read_comments,
- ..PersonPostAggregatesForm::default()
- };
- PersonPostAggregates::upsert(&mut context.pool(), &person_post_agg_form)
- .await
- .with_lemmy_type(LemmyErrorType::CouldntFindPost)?;
- }
+ post_id,
+ read_comments,
+ ..PersonPostAggregatesForm::default()
+ };
+ PersonPostAggregates::upsert(&mut context.pool(), &person_post_agg_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntFindPost)?;
+ }
- let moderators =
- CommunityModeratorView::for_community(&mut context.pool(), community_id).await?;
+ let moderators = CommunityModeratorView::for_community(&mut context.pool(), community_id).await?;
- // Fetch the cross_posts
- let cross_posts = if let Some(url) = &post_view.post.url {
- let mut x_posts = PostQuery {
- url_search: Some(url.inner().as_str().into()),
- ..Default::default()
- }
- .list(&mut context.pool())
- .await?;
+ // Fetch the cross_posts
+ let cross_posts = if let Some(url) = &post_view.post.url {
+ let mut x_posts = PostQuery {
+ url_search: Some(url.inner().as_str().into()),
+ ..Default::default()
+ }
+ .list(&mut context.pool())
+ .await?;
- // Don't return this post as one of the cross_posts
- x_posts.retain(|x| x.post.id != post_id);
- x_posts
- } else {
- Vec::new()
- };
+ // Don't return this post as one of the cross_posts
+ x_posts.retain(|x| x.post.id != post_id);
+ x_posts
+ } else {
+ Vec::new()
+ };
- // Return the jwt
- Ok(GetPostResponse {
- post_view,
- community_view,
- moderators,
- cross_posts,
- })
- }
+ // Return the jwt
+ Ok(Json(GetPostResponse {
+ post_view,
+ community_view,
+ moderators,
+ cross_posts,
+ }))
}
-mod create;
-mod delete;
-mod read;
-mod update;
+pub mod create;
+pub mod delete;
+pub mod read;
+pub mod update;
-use crate::PerformCrud;
-use actix_web::web::Data;
+use actix_web::web::{Data, Json, Query};
use lemmy_api_common::{
context::LemmyContext,
private_message::{GetPrivateMessages, PrivateMessagesResponse},
use lemmy_db_views::private_message_view::PrivateMessageQuery;
use lemmy_utils::error::LemmyError;
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for GetPrivateMessages {
- type Response = PrivateMessagesResponse;
+#[tracing::instrument(skip(context))]
+pub async fn get_private_message(
+ data: Query<GetPrivateMessages>,
+ context: Data<LemmyContext>,
+) -> Result<Json<PrivateMessagesResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(data.auth.as_ref(), &context).await?;
+ let person_id = local_user_view.person.id;
- #[tracing::instrument(skip(self, context))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- ) -> Result<PrivateMessagesResponse, LemmyError> {
- let data: &GetPrivateMessages = self;
- let local_user_view = local_user_view_from_jwt(data.auth.as_ref(), context).await?;
- let person_id = local_user_view.person.id;
+ let page = data.page;
+ let limit = data.limit;
+ let unread_only = data.unread_only;
+ let mut messages = PrivateMessageQuery {
+ page,
+ limit,
+ unread_only,
+ }
+ .list(&mut context.pool(), person_id)
+ .await?;
- let page = data.page;
- let limit = data.limit;
- let unread_only = data.unread_only;
- let mut messages = PrivateMessageQuery {
- page,
- limit,
- unread_only,
+ // Messages sent by ourselves should be marked as read. The `read` column in database is only
+ // for the recipient, and shouldnt be exposed to sender.
+ messages.iter_mut().for_each(|pmv| {
+ if pmv.creator.id == person_id {
+ pmv.private_message.read = true
}
- .list(&mut context.pool(), person_id)
- .await?;
-
- // Messages sent by ourselves should be marked as read. The `read` column in database is only
- // for the recipient, and shouldnt be exposed to sender.
- messages.iter_mut().for_each(|pmv| {
- if pmv.creator.id == person_id {
- pmv.private_message.read = true
- }
- });
+ });
- Ok(PrivateMessagesResponse {
- private_messages: messages,
- })
- }
+ Ok(Json(PrivateMessagesResponse {
+ private_messages: messages,
+ }))
}
-use crate::{
- site::{application_question_check, site_default_post_listing_type_check},
- PerformCrud,
-};
+use crate::site::{application_question_check, site_default_post_listing_type_check};
use activitypub_federation::http_signatures::generate_actor_keypair;
-use actix_web::web::Data;
+use actix_web::web::{Data, Json};
use lemmy_api_common::{
context::LemmyContext,
site::{CreateSite, SiteResponse},
};
use url::Url;
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for CreateSite {
- type Response = SiteResponse;
-
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<SiteResponse, LemmyError> {
- let data: &CreateSite = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
- let local_site = LocalSite::read(&mut context.pool()).await?;
-
- // Make sure user is an admin; other types of users should not create site data...
- is_admin(&local_user_view)?;
-
- validate_create_payload(&local_site, data)?;
-
- let actor_id: DbUrl = Url::parse(&context.settings().get_protocol_and_hostname())?.into();
- let inbox_url = Some(generate_site_inbox_url(&actor_id)?);
- let keypair = generate_actor_keypair()?;
- let name = sanitize_html(&data.name);
- let sidebar = sanitize_html_opt(&data.sidebar);
- let description = sanitize_html_opt(&data.description);
-
- let site_form = SiteUpdateForm::builder()
- .name(Some(name))
- .sidebar(diesel_option_overwrite(sidebar))
- .description(diesel_option_overwrite(description))
- .icon(diesel_option_overwrite_to_url(&data.icon)?)
- .banner(diesel_option_overwrite_to_url(&data.banner)?)
- .actor_id(Some(actor_id))
- .last_refreshed_at(Some(naive_now()))
- .inbox_url(inbox_url)
- .private_key(Some(Some(keypair.private_key)))
- .public_key(Some(keypair.public_key))
- .build();
-
- let site_id = local_site.site_id;
-
- Site::update(&mut context.pool(), site_id, &site_form).await?;
-
- let application_question = sanitize_html_opt(&data.application_question);
- let default_theme = sanitize_html_opt(&data.default_theme);
- let legal_information = sanitize_html_opt(&data.legal_information);
-
- let local_site_form = LocalSiteUpdateForm::builder()
- // Set the site setup to true
- .site_setup(Some(true))
- .enable_downvotes(data.enable_downvotes)
- .registration_mode(data.registration_mode)
- .enable_nsfw(data.enable_nsfw)
- .community_creation_admin_only(data.community_creation_admin_only)
- .require_email_verification(data.require_email_verification)
- .application_question(diesel_option_overwrite(application_question))
- .private_instance(data.private_instance)
- .default_theme(default_theme)
- .default_post_listing_type(data.default_post_listing_type)
- .legal_information(diesel_option_overwrite(legal_information))
- .application_email_admins(data.application_email_admins)
- .hide_modlog_mod_names(data.hide_modlog_mod_names)
- .updated(Some(Some(naive_now())))
- .slur_filter_regex(diesel_option_overwrite(data.slur_filter_regex.clone()))
- .actor_name_max_length(data.actor_name_max_length)
- .federation_enabled(data.federation_enabled)
- .captcha_enabled(data.captcha_enabled)
- .captcha_difficulty(data.captcha_difficulty.clone())
- .build();
-
- LocalSite::update(&mut context.pool(), &local_site_form).await?;
-
- let local_site_rate_limit_form = LocalSiteRateLimitUpdateForm::builder()
- .message(data.rate_limit_message)
- .message_per_second(data.rate_limit_message_per_second)
- .post(data.rate_limit_post)
- .post_per_second(data.rate_limit_post_per_second)
- .register(data.rate_limit_register)
- .register_per_second(data.rate_limit_register_per_second)
- .image(data.rate_limit_image)
- .image_per_second(data.rate_limit_image_per_second)
- .comment(data.rate_limit_comment)
- .comment_per_second(data.rate_limit_comment_per_second)
- .search(data.rate_limit_search)
- .search_per_second(data.rate_limit_search_per_second)
- .build();
-
- LocalSiteRateLimit::update(&mut context.pool(), &local_site_rate_limit_form).await?;
-
- let site_view = SiteView::read_local(&mut context.pool()).await?;
-
- let new_taglines = data.taglines.clone();
- let taglines = Tagline::replace(&mut context.pool(), local_site.id, new_taglines).await?;
-
- let rate_limit_config =
- local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit);
- context
- .settings_updated_channel()
- .send(rate_limit_config)
- .await?;
-
- Ok(SiteResponse {
- site_view,
- taglines,
- })
- }
+#[tracing::instrument(skip(context))]
+pub async fn create_site(
+ data: Json<CreateSite>,
+ context: Data<LemmyContext>,
+) -> Result<Json<SiteResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
+ let local_site = LocalSite::read(&mut context.pool()).await?;
+
+ // Make sure user is an admin; other types of users should not create site data...
+ is_admin(&local_user_view)?;
+
+ validate_create_payload(&local_site, &data)?;
+
+ let actor_id: DbUrl = Url::parse(&context.settings().get_protocol_and_hostname())?.into();
+ let inbox_url = Some(generate_site_inbox_url(&actor_id)?);
+ let keypair = generate_actor_keypair()?;
+ let name = sanitize_html(&data.name);
+ let sidebar = sanitize_html_opt(&data.sidebar);
+ let description = sanitize_html_opt(&data.description);
+
+ let site_form = SiteUpdateForm::builder()
+ .name(Some(name))
+ .sidebar(diesel_option_overwrite(sidebar))
+ .description(diesel_option_overwrite(description))
+ .icon(diesel_option_overwrite_to_url(&data.icon)?)
+ .banner(diesel_option_overwrite_to_url(&data.banner)?)
+ .actor_id(Some(actor_id))
+ .last_refreshed_at(Some(naive_now()))
+ .inbox_url(inbox_url)
+ .private_key(Some(Some(keypair.private_key)))
+ .public_key(Some(keypair.public_key))
+ .build();
+
+ let site_id = local_site.site_id;
+
+ Site::update(&mut context.pool(), site_id, &site_form).await?;
+
+ let application_question = sanitize_html_opt(&data.application_question);
+ let default_theme = sanitize_html_opt(&data.default_theme);
+ let legal_information = sanitize_html_opt(&data.legal_information);
+
+ let local_site_form = LocalSiteUpdateForm::builder()
+ // Set the site setup to true
+ .site_setup(Some(true))
+ .enable_downvotes(data.enable_downvotes)
+ .registration_mode(data.registration_mode)
+ .enable_nsfw(data.enable_nsfw)
+ .community_creation_admin_only(data.community_creation_admin_only)
+ .require_email_verification(data.require_email_verification)
+ .application_question(diesel_option_overwrite(application_question))
+ .private_instance(data.private_instance)
+ .default_theme(default_theme)
+ .default_post_listing_type(data.default_post_listing_type)
+ .legal_information(diesel_option_overwrite(legal_information))
+ .application_email_admins(data.application_email_admins)
+ .hide_modlog_mod_names(data.hide_modlog_mod_names)
+ .updated(Some(Some(naive_now())))
+ .slur_filter_regex(diesel_option_overwrite(data.slur_filter_regex.clone()))
+ .actor_name_max_length(data.actor_name_max_length)
+ .federation_enabled(data.federation_enabled)
+ .captcha_enabled(data.captcha_enabled)
+ .captcha_difficulty(data.captcha_difficulty.clone())
+ .build();
+
+ LocalSite::update(&mut context.pool(), &local_site_form).await?;
+
+ let local_site_rate_limit_form = LocalSiteRateLimitUpdateForm::builder()
+ .message(data.rate_limit_message)
+ .message_per_second(data.rate_limit_message_per_second)
+ .post(data.rate_limit_post)
+ .post_per_second(data.rate_limit_post_per_second)
+ .register(data.rate_limit_register)
+ .register_per_second(data.rate_limit_register_per_second)
+ .image(data.rate_limit_image)
+ .image_per_second(data.rate_limit_image_per_second)
+ .comment(data.rate_limit_comment)
+ .comment_per_second(data.rate_limit_comment_per_second)
+ .search(data.rate_limit_search)
+ .search_per_second(data.rate_limit_search_per_second)
+ .build();
+
+ LocalSiteRateLimit::update(&mut context.pool(), &local_site_rate_limit_form).await?;
+
+ let site_view = SiteView::read_local(&mut context.pool()).await?;
+
+ let new_taglines = data.taglines.clone();
+ let taglines = Tagline::replace(&mut context.pool(), local_site.id, new_taglines).await?;
+
+ let rate_limit_config =
+ local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit);
+ context
+ .settings_updated_channel()
+ .send(rate_limit_config)
+ .await?;
+
+ Ok(Json(SiteResponse {
+ site_view,
+ taglines,
+ }))
}
fn validate_create_payload(local_site: &LocalSite, create_site: &CreateSite) -> LemmyResult<()> {
use lemmy_db_schema::{ListingType, RegistrationMode};
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
-mod create;
-mod read;
-mod update;
+pub mod create;
+pub mod read;
+pub mod update;
/// Checks whether the default post listing type is valid for a site.
pub fn site_default_post_listing_type_check(
-use crate::PerformCrud;
-use actix_web::web::Data;
+use actix_web::web::{Data, Json, Query};
use lemmy_api_common::{
context::LemmyContext,
sensitive::Sensitive,
version,
};
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for GetSite {
- type Response = GetSiteResponse;
-
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetSiteResponse, LemmyError> {
- let data: &GetSite = self;
-
- let site_view = SiteView::read_local(&mut context.pool()).await?;
-
- let admins = PersonView::admins(&mut context.pool()).await?;
-
- // Build the local user
- let my_user = if let Some(local_user_view) =
- local_user_settings_view_from_jwt_opt(data.auth.as_ref(), context).await
- {
- let person_id = local_user_view.person.id;
- let local_user_id = local_user_view.local_user.id;
-
- let follows = CommunityFollowerView::for_person(&mut context.pool(), person_id)
- .await
- .with_lemmy_type(LemmyErrorType::SystemErrLogin)?;
-
- let person_id = local_user_view.person.id;
- let community_blocks = CommunityBlockView::for_person(&mut context.pool(), person_id)
- .await
- .with_lemmy_type(LemmyErrorType::SystemErrLogin)?;
-
- let person_id = local_user_view.person.id;
- let person_blocks = PersonBlockView::for_person(&mut context.pool(), person_id)
- .await
- .with_lemmy_type(LemmyErrorType::SystemErrLogin)?;
-
- let moderates = CommunityModeratorView::for_person(&mut context.pool(), person_id)
- .await
- .with_lemmy_type(LemmyErrorType::SystemErrLogin)?;
-
- let discussion_languages = LocalUserLanguage::read(&mut context.pool(), local_user_id)
- .await
- .with_lemmy_type(LemmyErrorType::SystemErrLogin)?;
-
- Some(MyUserInfo {
- local_user_view,
- follows,
- moderates,
- community_blocks,
- person_blocks,
- discussion_languages,
- })
- } else {
- None
- };
-
- let all_languages = Language::read_all(&mut context.pool()).await?;
- let discussion_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?;
- let taglines = Tagline::get_all(&mut context.pool(), site_view.local_site.id).await?;
- let custom_emojis =
- CustomEmojiView::get_all(&mut context.pool(), site_view.local_site.id).await?;
-
- Ok(GetSiteResponse {
- site_view,
- admins,
- version: version::VERSION.to_string(),
- my_user,
- all_languages,
+#[tracing::instrument(skip(context))]
+pub async fn get_site(
+ data: Query<GetSite>,
+ context: Data<LemmyContext>,
+) -> Result<Json<GetSiteResponse>, LemmyError> {
+ let site_view = SiteView::read_local(&mut context.pool()).await?;
+
+ let admins = PersonView::admins(&mut context.pool()).await?;
+
+ // Build the local user
+ let my_user = if let Some(local_user_view) =
+ local_user_settings_view_from_jwt_opt(data.auth.as_ref(), &context).await
+ {
+ let person_id = local_user_view.person.id;
+ let local_user_id = local_user_view.local_user.id;
+
+ let follows = CommunityFollowerView::for_person(&mut context.pool(), person_id)
+ .await
+ .with_lemmy_type(LemmyErrorType::SystemErrLogin)?;
+
+ let person_id = local_user_view.person.id;
+ let community_blocks = CommunityBlockView::for_person(&mut context.pool(), person_id)
+ .await
+ .with_lemmy_type(LemmyErrorType::SystemErrLogin)?;
+
+ let person_id = local_user_view.person.id;
+ let person_blocks = PersonBlockView::for_person(&mut context.pool(), person_id)
+ .await
+ .with_lemmy_type(LemmyErrorType::SystemErrLogin)?;
+
+ let moderates = CommunityModeratorView::for_person(&mut context.pool(), person_id)
+ .await
+ .with_lemmy_type(LemmyErrorType::SystemErrLogin)?;
+
+ let discussion_languages = LocalUserLanguage::read(&mut context.pool(), local_user_id)
+ .await
+ .with_lemmy_type(LemmyErrorType::SystemErrLogin)?;
+
+ Some(MyUserInfo {
+ local_user_view,
+ follows,
+ moderates,
+ community_blocks,
+ person_blocks,
discussion_languages,
- taglines,
- custom_emojis,
})
- }
+ } else {
+ None
+ };
+
+ let all_languages = Language::read_all(&mut context.pool()).await?;
+ let discussion_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?;
+ let taglines = Tagline::get_all(&mut context.pool(), site_view.local_site.id).await?;
+ let custom_emojis =
+ CustomEmojiView::get_all(&mut context.pool(), site_view.local_site.id).await?;
+
+ Ok(Json(GetSiteResponse {
+ site_view,
+ admins,
+ version: version::VERSION.to_string(),
+ my_user,
+ all_languages,
+ discussion_languages,
+ taglines,
+ custom_emojis,
+ }))
}
#[tracing::instrument(skip_all)]
-use crate::{
- site::{application_question_check, site_default_post_listing_type_check},
- PerformCrud,
-};
-use actix_web::web::Data;
+use crate::site::{application_question_check, site_default_post_listing_type_check};
+use actix_web::web::{Data, Json};
use lemmy_api_common::{
context::LemmyContext,
site::{EditSite, SiteResponse},
},
};
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for EditSite {
- type Response = SiteResponse;
-
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<SiteResponse, LemmyError> {
- let data: &EditSite = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
- let site_view = SiteView::read_local(&mut context.pool()).await?;
- let local_site = site_view.local_site;
- let site = site_view.site;
-
- // Make sure user is an admin; other types of users should not update site data...
- is_admin(&local_user_view)?;
-
- validate_update_payload(&local_site, data)?;
+#[tracing::instrument(skip(context))]
+pub async fn update_site(
+ data: Json<EditSite>,
+ context: Data<LemmyContext>,
+) -> Result<Json<SiteResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
+ let site_view = SiteView::read_local(&mut context.pool()).await?;
+ let local_site = site_view.local_site;
+ let site = site_view.site;
- if let Some(discussion_languages) = data.discussion_languages.clone() {
- SiteLanguage::update(&mut context.pool(), discussion_languages.clone(), &site).await?;
- }
+ // Make sure user is an admin; other types of users should not update site data...
+ is_admin(&local_user_view)?;
- let name = sanitize_html_opt(&data.name);
- let sidebar = sanitize_html_opt(&data.sidebar);
- let description = sanitize_html_opt(&data.description);
+ validate_update_payload(&local_site, &data)?;
- let site_form = SiteUpdateForm::builder()
- .name(name)
- .sidebar(diesel_option_overwrite(sidebar))
- .description(diesel_option_overwrite(description))
- .icon(diesel_option_overwrite_to_url(&data.icon)?)
- .banner(diesel_option_overwrite_to_url(&data.banner)?)
- .updated(Some(Some(naive_now())))
- .build();
+ if let Some(discussion_languages) = data.discussion_languages.clone() {
+ SiteLanguage::update(&mut context.pool(), discussion_languages.clone(), &site).await?;
+ }
- Site::update(&mut context.pool(), site.id, &site_form)
- .await
- // Ignore errors for all these, so as to not throw errors if no update occurs
- // Diesel will throw an error for empty update forms
- .ok();
-
- let application_question = sanitize_html_opt(&data.application_question);
- let default_theme = sanitize_html_opt(&data.default_theme);
- let legal_information = sanitize_html_opt(&data.legal_information);
-
- let local_site_form = LocalSiteUpdateForm::builder()
- .enable_downvotes(data.enable_downvotes)
- .registration_mode(data.registration_mode)
- .enable_nsfw(data.enable_nsfw)
- .community_creation_admin_only(data.community_creation_admin_only)
- .require_email_verification(data.require_email_verification)
- .application_question(diesel_option_overwrite(application_question))
- .private_instance(data.private_instance)
- .default_theme(default_theme)
- .default_post_listing_type(data.default_post_listing_type)
- .legal_information(diesel_option_overwrite(legal_information))
- .application_email_admins(data.application_email_admins)
- .hide_modlog_mod_names(data.hide_modlog_mod_names)
- .updated(Some(Some(naive_now())))
- .slur_filter_regex(diesel_option_overwrite(data.slur_filter_regex.clone()))
- .actor_name_max_length(data.actor_name_max_length)
- .federation_enabled(data.federation_enabled)
- .captcha_enabled(data.captcha_enabled)
- .captcha_difficulty(data.captcha_difficulty.clone())
- .reports_email_admins(data.reports_email_admins)
- .build();
-
- let update_local_site = LocalSite::update(&mut context.pool(), &local_site_form)
- .await
- .ok();
-
- let local_site_rate_limit_form = LocalSiteRateLimitUpdateForm::builder()
- .message(data.rate_limit_message)
- .message_per_second(data.rate_limit_message_per_second)
- .post(data.rate_limit_post)
- .post_per_second(data.rate_limit_post_per_second)
- .register(data.rate_limit_register)
- .register_per_second(data.rate_limit_register_per_second)
- .image(data.rate_limit_image)
- .image_per_second(data.rate_limit_image_per_second)
- .comment(data.rate_limit_comment)
- .comment_per_second(data.rate_limit_comment_per_second)
- .search(data.rate_limit_search)
- .search_per_second(data.rate_limit_search_per_second)
- .build();
-
- LocalSiteRateLimit::update(&mut context.pool(), &local_site_rate_limit_form)
+ let name = sanitize_html_opt(&data.name);
+ let sidebar = sanitize_html_opt(&data.sidebar);
+ let description = sanitize_html_opt(&data.description);
+
+ let site_form = SiteUpdateForm::builder()
+ .name(name)
+ .sidebar(diesel_option_overwrite(sidebar))
+ .description(diesel_option_overwrite(description))
+ .icon(diesel_option_overwrite_to_url(&data.icon)?)
+ .banner(diesel_option_overwrite_to_url(&data.banner)?)
+ .updated(Some(Some(naive_now())))
+ .build();
+
+ Site::update(&mut context.pool(), site.id, &site_form)
+ .await
+ // Ignore errors for all these, so as to not throw errors if no update occurs
+ // Diesel will throw an error for empty update forms
+ .ok();
+
+ let application_question = sanitize_html_opt(&data.application_question);
+ let default_theme = sanitize_html_opt(&data.default_theme);
+ let legal_information = sanitize_html_opt(&data.legal_information);
+
+ let local_site_form = LocalSiteUpdateForm::builder()
+ .enable_downvotes(data.enable_downvotes)
+ .registration_mode(data.registration_mode)
+ .enable_nsfw(data.enable_nsfw)
+ .community_creation_admin_only(data.community_creation_admin_only)
+ .require_email_verification(data.require_email_verification)
+ .application_question(diesel_option_overwrite(application_question))
+ .private_instance(data.private_instance)
+ .default_theme(default_theme)
+ .default_post_listing_type(data.default_post_listing_type)
+ .legal_information(diesel_option_overwrite(legal_information))
+ .application_email_admins(data.application_email_admins)
+ .hide_modlog_mod_names(data.hide_modlog_mod_names)
+ .updated(Some(Some(naive_now())))
+ .slur_filter_regex(diesel_option_overwrite(data.slur_filter_regex.clone()))
+ .actor_name_max_length(data.actor_name_max_length)
+ .federation_enabled(data.federation_enabled)
+ .captcha_enabled(data.captcha_enabled)
+ .captcha_difficulty(data.captcha_difficulty.clone())
+ .reports_email_admins(data.reports_email_admins)
+ .build();
+
+ let update_local_site = LocalSite::update(&mut context.pool(), &local_site_form)
+ .await
+ .ok();
+
+ let local_site_rate_limit_form = LocalSiteRateLimitUpdateForm::builder()
+ .message(data.rate_limit_message)
+ .message_per_second(data.rate_limit_message_per_second)
+ .post(data.rate_limit_post)
+ .post_per_second(data.rate_limit_post_per_second)
+ .register(data.rate_limit_register)
+ .register_per_second(data.rate_limit_register_per_second)
+ .image(data.rate_limit_image)
+ .image_per_second(data.rate_limit_image_per_second)
+ .comment(data.rate_limit_comment)
+ .comment_per_second(data.rate_limit_comment_per_second)
+ .search(data.rate_limit_search)
+ .search_per_second(data.rate_limit_search_per_second)
+ .build();
+
+ LocalSiteRateLimit::update(&mut context.pool(), &local_site_rate_limit_form)
+ .await
+ .ok();
+
+ // Replace the blocked and allowed instances
+ let allowed = data.allowed_instances.clone();
+ FederationAllowList::replace(&mut context.pool(), allowed).await?;
+ let blocked = data.blocked_instances.clone();
+ FederationBlockList::replace(&mut context.pool(), blocked).await?;
+
+ // TODO can't think of a better way to do this.
+ // If the server suddenly requires email verification, or required applications, no old users
+ // will be able to log in. It really only wants this to be a requirement for NEW signups.
+ // So if it was set from false, to true, you need to update all current users columns to be verified.
+
+ let old_require_application =
+ local_site.registration_mode == RegistrationMode::RequireApplication;
+ let new_require_application = update_local_site
+ .as_ref()
+ .map(|ols| ols.registration_mode == RegistrationMode::RequireApplication)
+ .unwrap_or(false);
+ if !old_require_application && new_require_application {
+ LocalUser::set_all_users_registration_applications_accepted(&mut context.pool())
.await
- .ok();
-
- // Replace the blocked and allowed instances
- let allowed = data.allowed_instances.clone();
- FederationAllowList::replace(&mut context.pool(), allowed).await?;
- let blocked = data.blocked_instances.clone();
- FederationBlockList::replace(&mut context.pool(), blocked).await?;
-
- // TODO can't think of a better way to do this.
- // If the server suddenly requires email verification, or required applications, no old users
- // will be able to log in. It really only wants this to be a requirement for NEW signups.
- // So if it was set from false, to true, you need to update all current users columns to be verified.
-
- let old_require_application =
- local_site.registration_mode == RegistrationMode::RequireApplication;
- let new_require_application = update_local_site
- .as_ref()
- .map(|ols| ols.registration_mode == RegistrationMode::RequireApplication)
- .unwrap_or(false);
- if !old_require_application && new_require_application {
- LocalUser::set_all_users_registration_applications_accepted(&mut context.pool())
- .await
- .with_lemmy_type(LemmyErrorType::CouldntSetAllRegistrationsAccepted)?;
- }
-
- let new_require_email_verification = update_local_site
- .as_ref()
- .map(|ols| ols.require_email_verification)
- .unwrap_or(false);
- if !local_site.require_email_verification && new_require_email_verification {
- LocalUser::set_all_users_email_verified(&mut context.pool())
- .await
- .with_lemmy_type(LemmyErrorType::CouldntSetAllEmailVerified)?;
- }
+ .with_lemmy_type(LemmyErrorType::CouldntSetAllRegistrationsAccepted)?;
+ }
- let new_taglines = data.taglines.clone();
- let taglines = Tagline::replace(&mut context.pool(), local_site.id, new_taglines).await?;
+ let new_require_email_verification = update_local_site
+ .as_ref()
+ .map(|ols| ols.require_email_verification)
+ .unwrap_or(false);
+ if !local_site.require_email_verification && new_require_email_verification {
+ LocalUser::set_all_users_email_verified(&mut context.pool())
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntSetAllEmailVerified)?;
+ }
- let site_view = SiteView::read_local(&mut context.pool()).await?;
+ let new_taglines = data.taglines.clone();
+ let taglines = Tagline::replace(&mut context.pool(), local_site.id, new_taglines).await?;
- let rate_limit_config =
- local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit);
- context
- .settings_updated_channel()
- .send(rate_limit_config)
- .await?;
+ let site_view = SiteView::read_local(&mut context.pool()).await?;
- let res = SiteResponse {
- site_view,
- taglines,
- };
+ let rate_limit_config =
+ local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit);
+ context
+ .settings_updated_channel()
+ .send(rate_limit_config)
+ .await?;
- Ok(res)
- }
+ Ok(Json(SiteResponse {
+ site_view,
+ taglines,
+ }))
}
fn validate_update_payload(local_site: &LocalSite, edit_site: &EditSite) -> LemmyResult<()> {
};
use lemmy_api_common::{
build_response::send_local_notifs,
- comment::{CommentResponse, CreateComment, EditComment},
+ comment::{CommentResponse, EditComment},
context::LemmyContext,
utils::{check_post_deleted_or_removed, is_mod_or_admin},
};
use lemmy_utils::{error::LemmyError, utils::mention::scrape_text_for_mentions};
use url::Url;
-#[async_trait::async_trait]
-impl SendActivity for CreateComment {
- type Response = CommentResponse;
-
- async fn send_activity(
- _request: &Self,
- response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- CreateOrUpdateNote::send(
- &response.comment_view.comment,
- response.comment_view.creator.id,
- CreateOrUpdateType::Create,
- context,
- )
- .await
- }
-}
-
#[async_trait::async_trait]
impl SendActivity for EditComment {
type Response = CommentResponse;
context: &Data<LemmyContext>,
) -> Result<(), LemmyError> {
CreateOrUpdateNote::send(
- &response.comment_view.comment,
+ response.comment_view.comment.clone(),
response.comment_view.creator.id,
CreateOrUpdateType::Update,
- context,
+ context.reset_request_count(),
)
.await
}
impl CreateOrUpdateNote {
#[tracing::instrument(skip(comment, person_id, kind, context))]
- async fn send(
- comment: &Comment,
+ pub(crate) async fn send(
+ comment: Comment,
person_id: PersonId,
kind: CreateOrUpdateType,
- context: &Data<LemmyContext>,
+ context: Data<LemmyContext>,
) -> Result<(), LemmyError> {
// TODO: might be helpful to add a comment method to retrieve community directly
let post_id = comment.post_id;
kind.clone(),
&context.settings().get_protocol_and_hostname(),
)?;
- let note = ApubComment(comment.clone()).into_json(context).await?;
+ let note = ApubComment(comment).into_json(&context).await?;
let create_or_update = CreateOrUpdateNote {
actor: person.id().into(),
.collect();
let mut inboxes = vec![];
for t in tagged_users {
- let person = t.dereference(context).await?;
+ let person = t.dereference(&context).await?;
inboxes.push(person.shared_inbox_or_inbox());
}
let activity = AnnouncableActivities::CreateOrUpdateComment(create_or_update);
- send_activity_in_community(activity, &person, &community, inboxes, false, context).await
+ send_activity_in_community(activity, &person, &community, inboxes, false, &context).await
}
}
use crate::{
objects::{community::ApubCommunity, person::ApubPerson},
- protocol::activities::{create_or_update::page::CreateOrUpdatePage, CreateOrUpdateType},
+ protocol::activities::{
+ create_or_update::{note::CreateOrUpdateNote, page::CreateOrUpdatePage},
+ CreateOrUpdateType,
+ },
CONTEXT,
};
use activitypub_federation::{
data: SendActivityData,
context: &Data<LemmyContext>,
) -> LemmyResult<()> {
- let fed_task = match data {
- SendActivityData::CreatePost(post) => {
- let creator_id = post.creator_id;
- CreateOrUpdatePage::send(
- post,
- creator_id,
- CreateOrUpdateType::Create,
- context.reset_request_count(),
- )
+ let context = context.reset_request_count();
+ let fed_task = async {
+ match data {
+ SendActivityData::CreatePost(post) => {
+ let creator_id = post.creator_id;
+ CreateOrUpdatePage::send(post, creator_id, CreateOrUpdateType::Create, context).await
+ }
+ SendActivityData::CreateComment(comment) => {
+ let creator_id = comment.creator_id;
+ CreateOrUpdateNote::send(comment, creator_id, CreateOrUpdateType::Create, context).await
+ }
}
};
if *SYNCHRONOUS_FEDERATION {
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorExt2, LemmyErrorType};
#[tracing::instrument(skip(context))]
-pub async fn read_community(
+pub async fn get_community(
data: Query<GetCommunity>,
context: Data<LemmyContext>,
) -> Result<Json<GetCommunityResponse>, LemmyError> {
-Subproject commit 713ceed9c7ef84deaa222e68361e670e0763cd83
+Subproject commit 1c42c579460871de7b4ea18e58dc25543b80d289
use actix_web::{guard, web, Error, HttpResponse, Result};
-use lemmy_api::Perform;
+use lemmy_api::{
+ comment::{distinguish::distinguish_comment, save::save_comment},
+ comment_report::{list::list_comment_reports, resolve::resolve_comment_report},
+ local_user::notifications::mark_reply_read::mark_reply_as_read,
+ Perform,
+};
use lemmy_api_common::{
- comment::{
- CreateComment,
- CreateCommentLike,
- CreateCommentReport,
- DeleteComment,
- DistinguishComment,
- EditComment,
- GetComment,
- ListCommentReports,
- RemoveComment,
- ResolveCommentReport,
- SaveComment,
- },
+ comment::{CreateCommentLike, CreateCommentReport, DeleteComment, EditComment, RemoveComment},
community::{
AddModToCommunity,
BanFromCommunity,
EditCommunity,
FollowCommunity,
HideCommunity,
- ListCommunities,
RemoveCommunity,
TransferCommunity,
},
GetUnreadCount,
Login,
MarkAllAsRead,
- MarkCommentReplyAsRead,
MarkPersonMentionAsRead,
PasswordChangeAfterReset,
PasswordReset,
DeletePost,
EditPost,
FeaturePost,
- GetPost,
GetSiteMetadata,
ListPostReports,
LockPost,
CreatePrivateMessageReport,
DeletePrivateMessage,
EditPrivateMessage,
- GetPrivateMessages,
ListPrivateMessageReports,
MarkPrivateMessageAsRead,
ResolvePrivateMessageReport,
},
site::{
ApproveRegistrationApplication,
- CreateSite,
- EditSite,
GetFederatedInstances,
GetModlog,
- GetSite,
GetUnreadRegistrationApplicationCount,
LeaveAdmin,
ListRegistrationApplications,
PurgePost,
},
};
-use lemmy_api_crud::{post::create::create_post, PerformCrud};
+use lemmy_api_crud::{
+ comment::{create::create_comment, read::get_comment},
+ community::list::list_communities,
+ post::{create::create_post, read::get_post},
+ private_message::read::get_private_message,
+ site::{create::create_site, read::get_site, update::update_site},
+ PerformCrud,
+};
use lemmy_apub::{
api::{
list_comments::list_comments,
list_posts::list_posts,
- read_community::read_community,
+ read_community::get_community,
read_person::read_person,
resolve_object::resolve_object,
search::search,
.service(
web::scope("/site")
.wrap(rate_limit.message())
- .route("", web::get().to(route_get_crud::<GetSite>))
+ .route("", web::get().to(get_site))
// Admin Actions
- .route("", web::post().to(route_post_crud::<CreateSite>))
- .route("", web::put().to(route_post_crud::<EditSite>)),
+ .route("", web::post().to(create_site))
+ .route("", web::put().to(update_site)),
)
.service(
web::resource("/modlog")
.service(
web::scope("/community")
.wrap(rate_limit.message())
- .route("", web::get().to(read_community))
+ .route("", web::get().to(get_community))
.route("", web::put().to(route_post_crud::<EditCommunity>))
.route("/hide", web::put().to(route_post::<HideCommunity>))
- .route("/list", web::get().to(route_get_crud::<ListCommunities>))
+ .route("/list", web::get().to(list_communities))
.route("/follow", web::post().to(route_post::<FollowCommunity>))
.route("/block", web::post().to(route_post::<BlockCommunity>))
.route(
.service(
web::scope("/post")
.wrap(rate_limit.message())
- .route("", web::get().to(route_get_crud::<GetPost>))
+ .route("", web::get().to(get_post))
.route("", web::put().to(route_post_crud::<EditPost>))
.route("/delete", web::post().to(route_post_crud::<DeletePost>))
.route("/remove", web::post().to(route_post_crud::<RemovePost>))
web::resource("/comment")
.guard(guard::Post())
.wrap(rate_limit.comment())
- .route(web::post().to(route_post_crud::<CreateComment>)),
+ .route(web::post().to(create_comment)),
)
.service(
web::scope("/comment")
.wrap(rate_limit.message())
- .route("", web::get().to(route_get_crud::<GetComment>))
+ .route("", web::get().to(get_comment))
.route("", web::put().to(route_post_crud::<EditComment>))
.route("/delete", web::post().to(route_post_crud::<DeleteComment>))
.route("/remove", web::post().to(route_post_crud::<RemoveComment>))
- .route(
- "/mark_as_read",
- web::post().to(route_post::<MarkCommentReplyAsRead>),
- )
- .route(
- "/distinguish",
- web::post().to(route_post::<DistinguishComment>),
- )
+ .route("/mark_as_read", web::post().to(mark_reply_as_read))
+ .route("/distinguish", web::post().to(distinguish_comment))
.route("/like", web::post().to(route_post::<CreateCommentLike>))
- .route("/save", web::put().to(route_post::<SaveComment>))
+ .route("/save", web::put().to(save_comment))
.route("/list", web::get().to(list_comments))
.route("/report", web::post().to(route_post::<CreateCommentReport>))
- .route(
- "/report/resolve",
- web::put().to(route_post::<ResolveCommentReport>),
- )
- .route(
- "/report/list",
- web::get().to(route_get::<ListCommentReports>),
- ),
+ .route("/report/resolve", web::put().to(resolve_comment_report))
+ .route("/report/list", web::get().to(list_comment_reports)),
)
// Private Message
.service(
web::scope("/private_message")
.wrap(rate_limit.message())
- .route("/list", web::get().to(route_get_crud::<GetPrivateMessages>))
+ .route("/list", web::get().to(get_private_message))
.route("", web::post().to(route_post_crud::<CreatePrivateMessage>))
.route("", web::put().to(route_post_crud::<EditPrivateMessage>))
.route(
Ok(HttpResponse::Ok().json(&res))
}
-async fn route_get_crud<'a, Data>(
- data: web::Query<Data>,
- context: web::Data<LemmyContext>,
- apub_data: activitypub_federation::config::Data<LemmyContext>,
-) -> Result<HttpResponse, Error>
-where
- Data: PerformCrud
- + SendActivity<Response = <Data as PerformCrud>::Response>
- + Clone
- + Deserialize<'a>
- + Send
- + 'static,
-{
- perform_crud::<Data>(data.0, context, apub_data).await
-}
-
async fn route_post_crud<'a, Data>(
data: web::Json<Data>,
context: web::Data<LemmyContext>,