summaryrefslogtreecommitdiffstats
path: root/server/src
diff options
context:
space:
mode:
Diffstat (limited to 'server/src')
-rw-r--r--server/src/api/comment.rs310
-rw-r--r--server/src/api/community.rs387
-rw-r--r--server/src/api/mod.rs20
-rw-r--r--server/src/api/post.rs280
-rw-r--r--server/src/api/site.rs424
-rw-r--r--server/src/api/user.rs623
-rw-r--r--server/src/apub/activities.rs59
-rw-r--r--server/src/apub/comment.rs281
-rw-r--r--server/src/apub/community.rs204
-rw-r--r--server/src/apub/community_inbox.rs81
-rw-r--r--server/src/apub/extensions/group_extensions.rs8
-rw-r--r--server/src/apub/extensions/signatures.rs87
-rw-r--r--server/src/apub/fetcher.rs304
-rw-r--r--server/src/apub/mod.rs185
-rw-r--r--server/src/apub/post.rs233
-rw-r--r--server/src/apub/private_message.rs117
-rw-r--r--server/src/apub/shared_inbox.rs877
-rw-r--r--server/src/apub/user.rs87
-rw-r--r--server/src/apub/user_inbox.rs208
-rw-r--r--server/src/db/activity.rs24
-rw-r--r--server/src/db/code_migrations.rs15
-rw-r--r--server/src/db/comment.rs2
-rw-r--r--server/src/db/community.rs2
-rw-r--r--server/src/db/password_reset_request.rs8
-rw-r--r--server/src/db/user.rs2
-rw-r--r--server/src/lib.rs118
-rw-r--r--server/src/main.rs25
-rw-r--r--server/src/rate_limit/mod.rs19
-rw-r--r--server/src/rate_limit/rate_limiter.rs5
-rw-r--r--server/src/request.rs51
-rw-r--r--server/src/routes/api.rs14
-rw-r--r--server/src/routes/feeds.rs84
-rw-r--r--server/src/routes/nodeinfo.rs62
-rw-r--r--server/src/routes/webfinger.rs108
-rw-r--r--server/src/settings.rs6
-rw-r--r--server/src/websocket/mod.rs1
-rw-r--r--server/src/websocket/server.rs565
37 files changed, 3434 insertions, 2452 deletions
diff --git a/server/src/api/comment.rs b/server/src/api/comment.rs
index 56217458..c7406b37 100644
--- a/server/src/api/comment.rs
+++ b/server/src/api/comment.rs
@@ -1,6 +1,7 @@
use crate::{
api::{APIError, Oper, Perform},
apub::{ApubLikeableType, ApubObjectType},
+ blocking,
db::{
comment::*,
comment_view::*,
@@ -27,13 +28,10 @@ use crate::{
UserOperation,
WebsocketInfo,
},
+ DbPool,
+ LemmyError,
MentionData,
};
-use diesel::{
- r2d2::{ConnectionManager, Pool},
- PgConnection,
-};
-use failure::Error;
use log::error;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
@@ -97,14 +95,15 @@ pub struct GetCommentsResponse {
comments: Vec<CommentView>,
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<CreateComment> {
type Response = CommentResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
websocket_info: Option<WebsocketInfo>,
- ) -> Result<CommentResponse, Error> {
+ ) -> Result<CommentResponse, LemmyError> {
let data: &CreateComment = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -114,20 +113,6 @@ impl Perform for Oper<CreateComment> {
let user_id = claims.id;
- let conn = pool.get()?;
-
- // Check for a community ban
- let post = Post::read(&conn, data.post_id)?;
- if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
- return Err(APIError::err("community_ban").into());
- }
-
- // Check for a site ban
- let user = User_::read(&conn, user_id)?;
- if user.banned {
- return Err(APIError::err("site_ban").into());
- }
-
let content_slurs_removed = remove_slurs(&data.content.to_owned());
let comment_form = CommentForm {
@@ -144,21 +129,48 @@ impl Perform for Oper<CreateComment> {
local: true,
};
- let inserted_comment = match Comment::create(&conn, &comment_form) {
- Ok(comment) => comment,
- Err(_e) => return Err(APIError::err("couldnt_create_comment").into()),
- };
+ // Check for a community ban
+ let post_id = data.post_id;
+ let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
+
+ let community_id = post.community_id;
+ let is_banned =
+ move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok();
+ if blocking(pool, is_banned).await? {
+ return Err(APIError::err("community_ban").into());
+ }
- let updated_comment = match Comment::update_ap_id(&conn, inserted_comment.id) {
+ // Check for a site ban
+ let user = blocking(pool, move |conn| User_::read(&conn, user_id)).await??;
+ if user.banned {
+ return Err(APIError::err("site_ban").into());
+ }
+
+ let comment_form2 = comment_form.clone();
+ let inserted_comment =
+ match blocking(pool, move |conn| Comment::create(&conn, &comment_form2)).await? {
+ Ok(comment) => comment,
+ Err(_e) => return Err(APIError::err("couldnt_create_comment").into()),
+ };
+
+ let inserted_comment_id = inserted_comment.id;
+ let updated_comment: Comment = match blocking(pool, move |conn| {
+ Comment::update_ap_id(&conn, inserted_comment_id)
+ })
+ .await?
+ {
Ok(comment) => comment,
Err(_e) => return Err(APIError::err("couldnt_create_comment").into()),
};
- updated_comment.send_create(&user, &conn)?;
+ updated_comment
+ .send_create(&user, &self.client, pool)
+ .await?;
// Scan the comment for user mentions, add those rows
let mentions = scrape_text_for_mentions(&comment_form.content);
- let recipient_ids = send_local_notifs(&conn, &mentions, &updated_comment, &user, &post);
+ let recipient_ids =
+ send_local_notifs(mentions, updated_comment.clone(), user.clone(), post, pool).await?;
// You like your own comment by default
let like_form = CommentLikeForm {
@@ -168,14 +180,17 @@ impl Perform for Oper<CreateComment> {
score: 1,
};
- let _inserted_like = match CommentLike::like(&conn, &like_form) {
- Ok(like) => like,
- Err(_e) => return Err(APIError::err("couldnt_like_comment").into()),
- };
+ let like = move |conn: &'_ _| CommentLike::like(&conn, &like_form);
+ if blocking(pool, like).await?.is_err() {
+ return Err(APIError::err("couldnt_like_comment").into());
+ }
- updated_comment.send_like(&user, &conn)?;
+ updated_comment.send_like(&user, &self.client, pool).await?;
- let comment_view = CommentView::read(&conn, inserted_comment.id, Some(user_id))?;
+ let comment_view = blocking(pool, move |conn| {
+ CommentView::read(&conn, inserted_comment.id, Some(user_id))
+ })
+ .await??;
let mut res = CommentResponse {
comment: comment_view,
@@ -198,14 +213,15 @@ impl Perform for Oper<CreateComment> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<EditComment> {
type Response = CommentResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
websocket_info: Option<WebsocketInfo>,
- ) -> Result<CommentResponse, Error> {
+ ) -> Result<CommentResponse, LemmyError> {
let data: &EditComment = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -215,30 +231,44 @@ impl Perform for Oper<EditComment> {
let user_id = claims.id;
- let conn = pool.get()?;
+ let user = blocking(pool, move |conn| User_::read(&conn, user_id)).await??;
- let user = User_::read(&conn, user_id)?;
-
- let orig_comment = CommentView::read(&conn, data.edit_id, None)?;
+ let edit_id = data.edit_id;
+ let orig_comment =
+ blocking(pool, move |conn| CommentView::read(&conn, edit_id, None)).await??;
// You are allowed to mark the comment as read even if you're banned.
if data.read.is_none() {
// Verify its the creator or a mod, or an admin
let mut editors: Vec<i32> = vec![data.creator_id];
+ let community_id = orig_comment.community_id;
+ editors.append(
+ &mut blocking(pool, move |conn| {
+ Ok(
+ CommunityModeratorView::for_community(&conn, community_id)?
+ .into_iter()
+ .map(|m| m.user_id)
+ .collect(),
+ ) as Result<_, LemmyError>
+ })
+ .await??,
+ );
editors.append(
- &mut CommunityModeratorView::for_community(&conn, orig_comment.community_id)?
- .into_iter()
- .map(|m| m.user_id)
- .collect(),
+ &mut blocking(pool, move |conn| {
+ Ok(UserView::admins(conn)?.into_iter().map(|a| a.id).collect()) as Result<_, LemmyError>
+ })
+ .await??,
);
- editors.append(&mut UserView::admins(&conn)?.into_iter().map(|a| a.id).collect());
if !editors.contains(&user_id) {
return Err(APIError::err("no_comment_edit_allowed").into());
}
// Check for a community ban
- if CommunityUserBanView::get(&conn, user_id, orig_comment.community_id).is_ok() {
+ let community_id = orig_comment.community_id;
+ let is_banned =
+ move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok();
+ if blocking(pool, is_banned).await? {
return Err(APIError::err("community_ban").into());
}
@@ -250,7 +280,8 @@ impl Perform for Oper<EditComment> {
let content_slurs_removed = remove_slurs(&data.content.to_owned());
- let read_comment = Comment::read(&conn, data.edit_id)?;
+ let edit_id = data.edit_id;
+ let read_comment = blocking(pool, move |conn| Comment::read(conn, edit_id)).await??;
let comment_form = CommentForm {
content: content_slurs_removed,
@@ -270,31 +301,48 @@ impl Perform for Oper<EditComment> {
local: read_comment.local,
};
- let updated_comment = match Comment::update(&conn, data.edit_id, &comment_form) {
+ let edit_id = data.edit_id;
+ let comment_form2 = comment_form.clone();
+ let updated_comment = match blocking(pool, move |conn| {
+ Comment::update(conn, edit_id, &comment_form2)
+ })
+ .await?
+ {
Ok(comment) => comment,
Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
};
if let Some(deleted) = data.deleted.to_owned() {
if deleted {
- updated_comment.send_delete(&user, &conn)?;
+ updated_comment
+ .send_delete(&user, &self.client, pool)
+ .await?;
} else {
- updated_comment.send_undo_delete(&user, &conn)?;
+ updated_comment
+ .send_undo_delete(&user, &self.client, pool)
+ .await?;
}
} else if let Some(removed) = data.removed.to_owned() {
if removed {
- updated_comment.send_remove(&user, &conn)?;
+ updated_comment
+ .send_remove(&user, &self.client, pool)
+ .await?;
} else {
- updated_comment.send_undo_remove(&user, &conn)?;
+ updated_comment
+ .send_undo_remove(&user, &self.client, pool)
+ .await?;
}
} else {
- updated_comment.send_update(&user, &conn)?;
+ updated_comment
+ .send_update(&user, &self.client, pool)
+ .await?;
}
- let post = Post::read(&conn, data.post_id)?;
+ let post_id = data.post_id;
+ let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
let mentions = scrape_text_for_mentions(&comment_form.content);
- let recipient_ids = send_local_notifs(&conn, &mentions, &updated_comment, &user, &post);
+ let recipient_ids = send_local_notifs(mentions, updated_comment, user, post, pool).await?;
// Mod tables
if let Some(removed) = data.removed.to_owned() {
@@ -304,10 +352,14 @@ impl Perform for Oper<EditComment> {
removed: Some(removed),
reason: data.reason.to_owned(),
};
- ModRemoveComment::create(&conn, &form)?;
+ blocking(pool, move |conn| ModRemoveComment::create(conn, &form)).await??;
}
- let comment_view = CommentView::read(&conn, data.edit_id, Some(user_id))?;
+ let edit_id = data.edit_id;
+ let comment_view = blocking(pool, move |conn| {
+ CommentView::read(conn, edit_id, Some(user_id))
+ })
+ .await??;
let mut res = CommentResponse {
comment: comment_view,
@@ -330,14 +382,15 @@ impl Perform for Oper<EditComment> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<SaveComment> {
type Response = CommentResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
_websocket_info: Option<WebsocketInfo>,
- ) -> Result<CommentResponse, Error> {
+ ) -> Result<CommentResponse, LemmyError> {
let data: &SaveComment = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -352,21 +405,23 @@ impl Perform for Oper<SaveComment> {
user_id,
};
- let conn = pool.get()?;
-
if data.save {
- match CommentSaved::save(&conn, &comment_saved_form) {
- Ok(comment) => comment,
- Err(_e) => return Err(APIError::err("couldnt_save_comment").into()),
- };
+ let save_comment = move |conn: &'_ _| CommentSaved::save(conn, &comment_saved_form);
+ if blocking(pool, save_comment).await?.is_err() {
+ return Err(APIError::err("couldnt_save_comment").into());
+ }
} else {
- match CommentSaved::unsave(&conn, &comment_saved_form) {
- Ok(comment) => comment,
- Err(_e) => return Err(APIError::err("couldnt_save_comment").into()),
- };
+ let unsave_comment = move |conn: &'_ _| CommentSaved::unsave(conn, &comment_saved_form);
+ if blocking(pool, unsave_comment).await?.is_err() {
+ return Err(APIError::err("couldnt_save_comment").into());
+ }
}
- let comment_view = CommentView::read(&conn, data.comment_id, Some(user_id))?;
+ let comment_id = data.comment_id;
+ let comment_view = blocking(pool, move |conn| {
+ CommentView::read(conn, comment_id, Some(user_id))
+ })
+ .await??;
Ok(CommentResponse {
comment: comment_view,
@@ -375,14 +430,15 @@ impl Perform for Oper<SaveComment> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<CreateCommentLike> {
type Response = CommentResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
websocket_info: Option<WebsocketInfo>,
- ) -> Result<CommentResponse, Error> {
+ ) -> Result<CommentResponse, LemmyError> {
let data: &CreateCommentLike = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -394,36 +450,42 @@ impl Perform for Oper<CreateCommentLike> {
let mut recipient_ids = Vec::new();
- let conn = pool.get()?;
-
// Don't do a downvote if site has downvotes disabled
if data.score == -1 {
- let site = SiteView::read(&conn)?;
+ let site = blocking(pool, move |conn| SiteView::read(conn)).await??;
if !site.enable_downvotes {
return Err(APIError::err("downvotes_disabled").into());
}
}
// Check for a community ban
- let post = Post::read(&conn, data.post_id)?;
- if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
+ let post_id = data.post_id;
+ let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
+ let community_id = post.community_id;
+ let is_banned =
+ move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok();
+ if blocking(pool, is_banned).await? {
return Err(APIError::err("community_ban").into());
}
// Check for a site ban
- let user = User_::read(&conn, user_id)?;
+ let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
if user.banned {
return Err(APIError::err("site_ban").into());
}
- let comment = Comment::read(&conn, data.comment_id)?;
+ let comment_id = data.comment_id;
+ let comment = blocking(pool, move |conn| Comment::read(conn, comment_id)).await??;
// Add to recipient ids
match comment.parent_id {
Some(parent_id) => {
- let parent_comment = Comment::read(&conn, parent_id)?;
+ let parent_comment = blocking(pool, move |conn| Comment::read(conn, parent_id)).await??;
if parent_comment.creator_id != user_id {
- let parent_user = User_::read(&conn, parent_comment.creator_id)?;
+ let parent_user = blocking(pool, move |conn| {
+ User_::read(conn, parent_comment.creator_id)
+ })
+ .await??;
recipient_ids.push(parent_user.id);
}
}
@@ -440,27 +502,33 @@ impl Perform for Oper<CreateCommentLike> {
};
// Remove any likes first
- CommentLike::remove(&conn, &like_form)?;
+ let like_form2 = like_form.clone();
+ blocking(pool, move |conn| CommentLike::remove(conn, &like_form2)).await??;
// Only add the like if the score isnt 0
let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
if do_add {
- let _inserted_like = match CommentLike::like(&conn, &like_form) {
- Ok(like) => like,
- Err(_e) => return Err(APIError::err("couldnt_like_comment").into()),
- };
+ let like_form2 = like_form.clone();
+ let like = move |conn: &'_ _| CommentLike::like(conn, &like_form2);
+ if blocking(pool, like).await?.is_err() {
+ return Err(APIError::err("couldnt_like_comment").into());
+ }
if like_form.score == 1 {
- comment.send_like(&user, &conn)?;
+ comment.send_like(&user, &self.client, pool).await?;
} else if like_form.score == -1 {
- comment.send_dislike(&user, &conn)?;
+ comment.send_dislike(&user, &self.client, pool).await?;
}
} else {
- comment.send_undo_like(&user, &conn)?;
+ comment.send_undo_like(&user, &self.client, pool).await?;
}
// Have to refetch the comment to get the current state
- let liked_comment = CommentView::read(&conn, data.comment_id, Some(user_id))?;
+ let comment_id = data.comment_id;
+ let liked_comment = blocking(pool, move |conn| {
+ CommentView::read(conn, comment_id, Some(user_id))
+ })
+ .await??;
let mut res = CommentResponse {
comment: liked_comment,
@@ -483,14 +551,15 @@ impl Perform for Oper<CreateCommentLike> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<GetComments> {
type Response = GetCommentsResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
websocket_info: Option<WebsocketInfo>,
- ) -> Result<GetCommentsResponse, Error> {
+ ) -> Result<GetCommentsResponse, LemmyError> {
let data: &GetComments = &self.data;
let user_claims: Option<Claims> = match &data.auth {
@@ -509,19 +578,23 @@ impl Perform for Oper<GetComments> {
let type_ = ListingType::from_str(&data.type_)?;
let sort = SortType::from_str(&data.sort)?;
- let conn = pool.get()?;
-
- let comments = match CommentQueryBuilder::create(&conn)
- .listing_type(type_)
- .sort(&sort)
- .for_community_id(data.community_id)
- .my_user_id(user_id)
- .page(data.page)
- .limit(data.limit)
- .list()
- {
+ let community_id = data.community_id;
+ let page = data.page;
+ let limit = data.limit;
+ let comments = blocking(pool, move |conn| {
+ CommentQueryBuilder::create(conn)
+ .listing_type(type_)
+ .sort(&sort)
+ .for_community_id(community_id)
+ .my_user_id(user_id)
+ .page(page)
+ .limit(limit)
+ .list()
+ })
+ .await?;
+ let comments = match comments {
Ok(comments) => comments,
- Err(_e) => return Err(APIError::err("couldnt_get_comments").into()),
+ Err(_) => return Err(APIError::err("couldnt_get_comments").into()),
};
if let Some(ws) = websocket_info {
@@ -542,8 +615,23 @@ impl Perform for Oper<GetComments> {
}
}
-pub fn send_local_notifs(
- conn: &PgConnection,
+pub async fn send_local_notifs(
+ mentions: Vec<MentionData>,
+ comment: Comment,
+ user: User_,
+ post: Post,
+ pool: &DbPool,
+) -> Result<Vec<i32>, LemmyError> {
+ let ids = blocking(pool, move |conn| {
+ do_send_local_notifs(conn, &mentions, &comment, &user, &post)
+ })
+ .await?;
+
+ Ok(ids)
+}
+
+fn do_send_local_notifs(
+ conn: &diesel::PgConnection,
mentions: &[MentionData],
comment: &Comment,
user: &User_,
diff --git a/server/src/api/community.rs b/server/src/api/community.rs
index 3fc67eb3..02071c57 100644
--- a/server/src/api/community.rs
+++ b/server/src/api/community.rs
@@ -7,6 +7,7 @@ use crate::{
ActorType,
EndpointType,
},
+ blocking,
db::{Bannable, Crud, Followable, Joinable, SortType},
is_valid_community_name,
naive_from_unix,
@@ -18,12 +19,9 @@ use crate::{
UserOperation,
WebsocketInfo,
},
+ DbPool,
+ LemmyError,
};
-use diesel::{
- r2d2::{ConnectionManager, Pool},
- PgConnection,
-};
-use failure::Error;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
@@ -138,14 +136,15 @@ pub struct TransferCommunity {
auth: String,
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<GetCommunity> {
type Response = GetCommunityResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
websocket_info: Option<WebsocketInfo>,
- ) -> Result<GetCommunityResponse, Error> {
+ ) -> Result<GetCommunityResponse, LemmyError> {
let data: &GetCommunity = &self.data;
let user_id: Option<i32> = match &data.auth {
@@ -159,33 +158,38 @@ impl Perform for Oper<GetCommunity> {
None => None,
};
- let conn = pool.get()?;
-
+ let name = data.name.to_owned().unwrap_or_else(|| "main".to_string());
let community = match data.id {
- Some(id) => Community::read(&conn, id)?,
- None => {
- match Community::read_from_name(
- &conn,
- &data.name.to_owned().unwrap_or_else(|| "main".to_string()),
- ) {
- Ok(community) => community,
- Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
- }
- }
+ Some(id) => blocking(pool, move |conn| Community::read(conn, id)).await??,
+ None => match blocking(pool, move |conn| Community::read_from_name(conn, &name)).await? {
+ Ok(community) => community,
+ Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
+ },
};
- let community_view = match CommunityView::read(&conn, community.id, user_id) {
+ let community_id = community.id;
+ let community_view = match blocking(pool, move |conn| {
+ CommunityView::read(conn, community_id, user_id)
+ })
+ .await?
+ {
Ok(community) => community,
Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
};
- let moderators = match CommunityModeratorView::for_community(&conn, community.id) {
+ let community_id = community.id;
+ let moderators: Vec<CommunityModeratorView> = match blocking(pool, move |conn| {
+ CommunityModeratorView::for_community(conn, community_id)
+ })
+ .await?
+ {
Ok(moderators) => moderators,
Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
};
- let site_creator_id = Site::read(&conn, 1)?.creator_id;
- let mut admins = UserView::admins(&conn)?;
+ let site = blocking(pool, move |conn| Site::read(conn, 1)).await??;
+ let site_creator_id = site.creator_id;
+ let mut admins = blocking(pool, move |conn| UserView::admins(conn)).await??;
let creator_index = admins.iter().position(|r| r.id == site_creator_id).unwrap();
let creator_user = admins.remove(creator_index);
admins.insert(0, creator_user);
@@ -220,14 +224,15 @@ impl Perform for Oper<GetCommunity> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<CreateCommunity> {
type Response = CommunityResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
_websocket_info: Option<WebsocketInfo>,
- ) -> Result<CommunityResponse, Error> {
+ ) -> Result<CommunityResponse, LemmyError> {
let data: &CreateCommunity = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -255,10 +260,9 @@ impl Perform for Oper<CreateCommunity> {
let user_id = claims.id;
- let conn = pool.get()?;
-
// Check for a site ban
- if UserView::read(&conn, user_id)?.banned {
+ let user_view = blocking(pool, move |conn| UserView::read(conn, user_id)).await??;
+ if user_view.banned {
return Err(APIError::err("site_ban").into());
}
@@ -283,34 +287,36 @@ impl Perform for Oper<CreateCommunity> {
published: None,
};
- let inserted_community = match Community::create(&conn, &community_form) {
- Ok(community) => community,
- Err(_e) => return Err(APIError::err("community_already_exists").into()),
- };
+ let inserted_community =
+ match blocking(pool, move |conn| Community::create(conn, &community_form)).await? {
+ Ok(community) => community,
+ Err(_e) => return Err(APIError::err("community_already_exists").into()),
+ };
let community_moderator_form = CommunityModeratorForm {
community_id: inserted_community.id,
user_id,
};
- let _inserted_community_moderator =
- match CommunityModerator::join(&conn, &community_moderator_form) {
- Ok(user) => user,
- Err(_e) => return Err(APIError::err("community_moderator_already_exists").into()),
- };
+ let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
+ if blocking(pool, join).await?.is_err() {
+ return Err(APIError::err("community_moderator_already_exists").into());
+ }
let community_follower_form = CommunityFollowerForm {
community_id: inserted_community.id,
user_id,
};
- let _inserted_community_follower =
- match CommunityFollower::follow(&conn, &community_follower_form) {
- Ok(user) => user,
- Err(_e) => return Err(APIError::err("community_follower_already_exists").into()),
- };
+ let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form);
+ if blocking(pool, follow).await?.is_err() {
+ return Err(APIError::err("community_follower_already_exists").into());
+ }
- let community_view = CommunityView::read(&conn, inserted_community.id, Some(user_id))?;
+ let community_view = blocking(pool, move |conn| {
+ CommunityView::read(conn, inserted_community.id, Some(user_id))
+ })
+ .await??;
Ok(CommunityResponse {
community: community_view,
@@ -318,14 +324,15 @@ impl Perform for Oper<CreateCommunity> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<EditCommunity> {
type Response = CommunityResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
websocket_info: Option<WebsocketInfo>,
- ) -> Result<CommunityResponse, Error> {
+ ) -> Result<CommunityResponse, LemmyError> {
let data: &EditCommunity = &self.data;
if let Err(slurs) = slur_check(&data.name) {
@@ -353,28 +360,34 @@ impl Perform for Oper<EditCommunity> {
let user_id = claims.id;
- let conn = pool.get()?;
-
// Check for a site ban
- let user = User_::read(&conn, user_id)?;
+ let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
if user.banned {
return Err(APIError::err("site_ban").into());
}
// Verify its a mod
+ let edit_id = data.edit_id;
let mut editors: Vec<i32> = Vec::new();
editors.append(
- &mut CommunityModeratorView::for_community(&conn, data.edit_id)?
- .into_iter()
- .map(|m| m.user_id)
- .collect(),
+ &mut blocking(pool, move |conn| {
+ CommunityModeratorView::for_community(conn, edit_id)
+ .map(|v| v.into_iter().map(|m| m.user_id).collect())
+ })
+ .await??,
+ );
+ editors.append(
+ &m