summaryrefslogtreecommitdiffstats
path: root/server/src/api/user.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/api/user.rs')
-rw-r--r--server/src/api/user.rs623
1 files changed, 368 insertions, 255 deletions
diff --git a/server/src/api/user.rs b/server/src/api/user.rs
index 0b6458e7..e7c27def 100644
--- a/server/src/api/user.rs
+++ b/server/src/api/user.rs
@@ -6,6 +6,7 @@ use crate::{
ApubObjectType,
EndpointType,
},
+ blocking,
db::{
comment::*,
comment_view::*,
@@ -43,13 +44,10 @@ use crate::{
UserOperation,
WebsocketInfo,
},
+ DbPool,
+ LemmyError,
};
use bcrypt::verify;
-use diesel::{
- r2d2::{ConnectionManager, Pool},
- PgConnection,
-};
-use failure::Error;
use log::error;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
@@ -252,20 +250,24 @@ pub struct UserJoinResponse {
pub user_id: i32,
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<Login> {
type Response = LoginResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
_websocket_info: Option<WebsocketInfo>,
- ) -> Result<LoginResponse, Error> {
+ ) -> Result<LoginResponse, LemmyError> {
let data: &Login = &self.data;
- let conn = pool.get()?;
-
// Fetch that username / email
- let user: User_ = match User_::find_by_email_or_username(&conn, &data.username_or_email) {
+ let username_or_email = data.username_or_email.clone();
+ let user = match blocking(pool, move |conn| {
+ User_::find_by_email_or_username(conn, &username_or_email)
+ })
+ .await?
+ {
Ok(user) => user,
Err(_e) => return Err(APIError::err("couldnt_find_that_username_or_email").into()),
};
@@ -281,20 +283,20 @@ impl Perform for Oper<Login> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<Register> {
type Response = LoginResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
_websocket_info: Option<WebsocketInfo>,
- ) -> Result<LoginResponse, Error> {
+ ) -> Result<LoginResponse, LemmyError> {
let data: &Register = &self.data;
- let conn = pool.get()?;
-
// Make sure site has open registration
- if let Ok(site) = SiteView::read(&conn) {
+ if let Ok(site) = blocking(pool, move |conn| SiteView::read(conn)).await? {
+ let site: SiteView = site;
if !site.open_registration {
return Err(APIError::err("registration_closed").into());
}
@@ -310,7 +312,11 @@ impl Perform for Oper<Register> {
}
// Make sure there are no admins
- if data.admin && !UserView::admins(&conn)?.is_empty() {
+ let any_admins = blocking(pool, move |conn| {
+ UserView::admins(conn).map(|a| a.is_empty())
+ })
+ .await??;
+ if data.admin && !any_admins {
return Err(APIError::err("admin_already_created").into());
}
@@ -346,7 +352,7 @@ impl Perform for Oper<Register> {
};
// Create the user
- let inserted_user = match User_::register(&conn, &user_form) {
+ let inserted_user = match blocking(pool, move |conn| User_::register(conn, &user_form)).await? {
Ok(user) => user,
Err(e) => {
let err_type = if e.to_string()
@@ -364,7 +370,7 @@ impl Perform for Oper<Register> {
let main_community_keypair = generate_actor_keypair()?;
// Create the main community if it doesn't exist
- let main_community: Community = match Community::read(&conn, 2) {
+ let main_community = match blocking(pool, move |conn| Community::read(conn, 2)).await? {
Ok(c) => c,
Err(_e) => {
let default_community_name = "main";
@@ -385,7 +391,7 @@ impl Perform for Oper<Register> {
last_refreshed_at: None,
published: None,
};
- Community::create(&conn, &community_form).unwrap()
+ blocking(pool, move |conn| Community::create(conn, &community_form)).await??
}
};
@@ -395,11 +401,10 @@ impl Perform for Oper<Register> {
user_id: inserted_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());
+ };
// If its an admin, add them as a mod and follower to main
if data.admin {
@@ -408,11 +413,10 @@ impl Perform for Oper<Register> {
user_id: inserted_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());
+ }
}
// Return the jwt
@@ -422,14 +426,15 @@ impl Perform for Oper<Register> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<SaveUserSettings> {
type Response = LoginResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
_websocket_info: Option<WebsocketInfo>,
- ) -> Result<LoginResponse, Error> {
+ ) -> Result<LoginResponse, LemmyError> {
let data: &SaveUserSettings = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -439,9 +444,7 @@ impl Perform for Oper<SaveUserSettings> {
let user_id = claims.id;
- let conn = pool.get()?;
-
- let read_user = User_::read(&conn, user_id)?;
+ let read_user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
let email = match &data.email {
Some(email) => Some(email.to_owned()),
@@ -465,7 +468,12 @@ impl Perform for Oper<SaveUserSettings> {
if !valid {
return Err(APIError::err("password_incorrect").into());
}
- User_::update_password(&conn, user_id, &new_password)?.password_encrypted
+ let new_password = new_password.to_owned();
+ let user = blocking(pool, move |conn| {
+ User_::update_password(conn, user_id, &new_password)
+ })
+ .await??;
+ user.password_encrypted
}
None => return Err(APIError::err("password_incorrect").into()),
}
@@ -501,7 +509,8 @@ impl Perform for Oper<SaveUserSettings> {
last_refreshed_at: None,
};
- let updated_user = match User_::update(&conn, user_id, &user_form) {
+ let res = blocking(pool, move |conn| User_::update(conn, user_id, &user_form)).await?;
+ let updated_user: User_ = match res {
Ok(user) => user,
Err(e) => {
let err_type = if e.to_string()
@@ -523,18 +532,17 @@ impl Perform for Oper<SaveUserSettings> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<GetUserDetails> {
type Response = GetUserDetailsResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
_websocket_info: Option<WebsocketInfo>,
- ) -> Result<GetUserDetailsResponse, Error> {
+ ) -> Result<GetUserDetailsResponse, LemmyError> {
let data: &GetUserDetails = &self.data;
- let conn = pool.get()?;
-
let user_claims: Option<Claims> = match &data.auth {
Some(auth) => match Claims::decode(&auth) {
Ok(claims) => Some(claims.claims),
@@ -555,54 +563,71 @@ impl Perform for Oper<GetUserDetails> {
let sort = SortType::from_str(&data.sort)?;
+ let username = data
+ .username
+ .to_owned()
+ .unwrap_or_else(|| "admin".to_string());
let user_details_id = match data.user_id {
Some(id) => id,
None => {
- match User_::read_from_name(
- &conn,
- &data
- .username
- .to_owned()
- .unwrap_or_else(|| "admin".to_string()),
- ) {
+ let user = blocking(pool, move |conn| User_::read_from_name(conn, &username)).await?;
+ match user {
Ok(user) => user.id,
Err(_e) => return Err(APIError::err("couldnt_find_that_username_or_email").into()),
}
}
};
- let mut user_view = UserView::read(&conn, user_details_id)?;
-
- let mut posts_query = PostQueryBuilder::create(&conn)
- .sort(&sort)
- .show_nsfw(show_nsfw)
- .saved_only(data.saved_only)
- .for_community_id(data.community_id)
- .my_user_id(user_id)
- .page(data.page)
- .limit(data.limit);
-
- let mut comments_query = CommentQueryBuilder::create(&conn)
- .sort(&sort)
- .saved_only(data.saved_only)
- .my_user_id(user_id)
- .page(data.page)
- .limit(data.limit);
-
- // If its saved only, you don't care what creator it was
- // Or, if its not saved, then you only want it for that specific creator
- if !data.saved_only {
- posts_query = posts_query.for_creator_id(user_details_id);
- comments_query = comments_query.for_creator_id(user_details_id);
- }
+ let mut user_view = blocking(pool, move |conn| UserView::read(conn, user_details_id)).await??;
+
+ let page = data.page;
+ let limit = data.limit;
+ let saved_only = data.saved_only;
+ let community_id = data.community_id;
+ let (posts, comments) = blocking(pool, move |conn| {
+ let mut posts_query = PostQueryBuilder::create(conn)
+ .sort(&sort)
+ .show_nsfw(show_nsfw)
+ .saved_only(saved_only)
+ .for_community_id(community_id)
+ .my_user_id(user_id)
+ .page(page)
+ .limit(limit);
+
+ let mut comments_query = CommentQueryBuilder::create(conn)
+ .sort(&sort)
+ .saved_only(saved_only)
+ .my_user_id(user_id)
+ .page(page)
+ .limit(limit);
+
+ // If its saved only, you don't care what creator it was
+ // Or, if its not saved, then you only want it for that specific creator
+ if !saved_only {
+ posts_query = posts_query.for_creator_id(user_details_id);
+ comments_query = comments_query.for_creator_id(user_details_id);
+ }
+
+ let posts = posts_query.list()?;
+ let comments = comments_query.list()?;
+
+ Ok((posts, comments)) as Result<_, LemmyError>
+ })
+ .await??;
+
+ let follows = blocking(pool, move |conn| {
+ CommunityFollowerView::for_user(conn, user_details_id)
+ })
+ .await??;
+ let moderates = blocking(pool, move |conn| {
+ CommunityModeratorView::for_user(conn, user_details_id)
+ })
+ .await??;
- let posts = posts_query.list()?;
- let comments = comments_query.list()?;
+ let site_creator_id =
+ blocking(pool, move |conn| Site::read(conn, 1).map(|s| s.creator_id)).await??;
- let follows = CommunityFollowerView::for_user(&conn, user_details_id)?;
- let moderates = CommunityModeratorView::for_user(&conn, user_details_id)?;
- let site_creator_id = Site::read(&conn, 1)?.creator_id;
- let mut admins = UserView::admins(&conn)?;
+ 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);
@@ -628,14 +653,15 @@ impl Perform for Oper<GetUserDetails> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<AddAdmin> {
type Response = AddAdminResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
websocket_info: Option<WebsocketInfo>,
- ) -> Result<AddAdminResponse, Error> {
+ ) -> Result<AddAdminResponse, LemmyError> {
let data: &AddAdmin = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -645,17 +671,17 @@ impl Perform for Oper<AddAdmin> {
let user_id = claims.id;
- let conn = pool.get()?;
-
// Make sure user is an admin
- if !UserView::read(&conn, user_id)?.admin {
+ let is_admin = move |conn: &'_ _| UserView::read(conn, user_id).map(|u| u.admin);
+ if !blocking(pool, is_admin).await?? {
return Err(APIError::err("not_an_admin").into());
}
- match User_::add_admin(&conn, user_id, data.added) {
- Ok(user) => user,
- Err(_e) => return Err(APIError::err("couldnt_update_user").into()),
- };
+ let added = data.added;
+ let add_admin = move |conn: &'_ _| User_::add_admin(conn, user_id, added);
+ if blocking(pool, add_admin).await?.is_err() {
+ return Err(APIError::err("couldnt_update_user").into());
+ }
// Mod tables
let form = ModAddForm {
@@ -664,10 +690,12 @@ impl Perform for Oper<AddAdmin> {
removed: Some(!data.added),
};
- ModAdd::create(&conn, &form)?;
+ blocking(pool, move |conn| ModAdd::create(conn, &form)).await??;
- let site_creator_id = Site::read(&conn, 1)?.creator_id;
- let mut admins = UserView::admins(&conn)?;
+ let site_creator_id =
+ blocking(pool, move |conn| Site::read(conn, 1).map(|s| s.creator_id)).await??;
+
+ 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);
@@ -686,14 +714,15 @@ impl Perform for Oper<AddAdmin> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<BanUser> {
type Response = BanUserResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
websocket_info: Option<WebsocketInfo>,
- ) -> Result<BanUserResponse, Error> {
+ ) -> Result<BanUserResponse, LemmyError> {
let data: &BanUser = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -703,17 +732,17 @@ impl Perform for Oper<BanUser> {
let user_id = claims.id;
- let conn = pool.get()?;
-
// Make sure user is an admin
- if !UserView::read(&conn, user_id)?.admin {
+ let is_admin = move |conn: &'_ _| UserView::read(conn, user_id).map(|u| u.admin);
+ if !blocking(pool, is_admin).await?? {
return Err(APIError::err("not_an_admin").into());
}
- match User_::ban_user(&conn, user_id, data.ban) {
- Ok(user) => user,
- Err(_e) => return Err(APIError::err("couldnt_update_user").into()),
- };
+ let ban = data.ban;
+ let ban_user = move |conn: &'_ _| User_::ban_user(conn, user_id, ban);
+ if blocking(pool, ban_user).await?.is_err() {
+ return Err(APIError::err("couldnt_update_user").into());
+ }
// Mod tables
let expires = match data.expires {
@@ -729,9 +758,10 @@ impl Perform for Oper<BanUser> {
expires,
};
- ModBan::create(&conn, &form)?;
+ blocking(pool, move |conn| ModBan::create(conn, &form)).await??;
- let user_view = UserView::read(&conn, data.user_id)?;
+ let user_id = data.user_id;
+ let user_view = blocking(pool, move |conn| UserView::read(conn, user_id)).await??;
let res = BanUserResponse {
user: user_view,
@@ -750,14 +780,15 @@ impl Perform for Oper<BanUser> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<GetReplies> {
type Response = GetRepliesResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
_websocket_info: Option<WebsocketInfo>,
- ) -> Result<GetRepliesResponse, Error> {
+ ) -> Result<GetRepliesResponse, LemmyError> {
let data: &GetReplies = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -769,27 +800,32 @@ impl Perform for Oper<GetReplies> {
let sort = SortType::from_str(&data.sort)?;
- let conn = pool.get()?;
-
- let replies = ReplyQueryBuilder::create(&conn, user_id)
- .sort(&sort)
- .unread_only(data.unread_only)
- .page(data.page)
- .limit(data.limit)
- .list()?;
+ let page = data.page;
+ let limit = data.limit;
+ let unread_only = data.unread_only;
+ let replies = blocking(pool, move |conn| {
+ ReplyQueryBuilder::create(conn, user_id)
+ .sort(&sort)
+ .unread_only(unread_only)
+ .page(page)
+ .limit(limit)
+ .list()
+ })
+ .await??;
Ok(GetRepliesResponse { replies })
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<GetUserMentions> {
type Response = GetUserMentionsResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
_websocket_info: Option<WebsocketInfo>,
- ) -> Result<GetUserMentionsResponse, Error> {
+ ) -> Result<GetUserMentionsResponse, LemmyError> {
let data: &GetUserMentions = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -801,27 +837,32 @@ impl Perform for Oper<GetUserMentions> {
let sort = SortType::from_str(&data.sort)?;
- let conn = pool.get()?;
-
- let mentions = UserMentionQueryBuilder::create(&conn, user_id)
- .sort(&sort)
- .unread_only(data.unread_only)
- .page(data.page)
- .limit(data.limit)
- .list()?;
+ let page = data.page;
+ let limit = data.limit;
+ let unread_only = data.unread_only;
+ let mentions = blocking(pool, move |conn| {
+ UserMentionQueryBuilder::create(conn, user_id)
+ .sort(&sort)
+ .unread_only(unread_only)
+ .page(page)
+ .limit(limit)
+ .list()
+ })
+ .await??;
Ok(GetUserMentionsResponse { mentions })
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<EditUserMention> {
type Response = UserMentionResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
_websocket_info: Option<WebsocketInfo>,
- ) -> Result<UserMentionResponse, Error> {
+ ) -> Result<UserMentionResponse, LemmyError> {
let data: &EditUserMention = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -831,9 +872,9 @@ impl Perform for Oper<EditUserMention> {
let user_id = claims.id;
- let conn = pool.get()?;
-
- let user_mention = UserMention::read(&conn, data.user_mention_id)?;
+ let user_mention_id = data.user_mention_id;
+ let user_mention =
+ blocking(pool, move |conn| UserMention::read(conn, user_mention_id)).await??;
let user_mention_form = UserMentionForm {
recipient_id: user_id,
@@ -841,13 +882,18 @@ impl Perform for Oper<EditUserMention> {
read: data.read.to_owned(),
};
- let _updated_user_mention =
- match UserMention::update(&conn, user_mention.id, &user_mention_form) {
- Ok(comment) => comment,
- Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
- };
+ let user_mention_id = user_mention.id;
+ let update_mention =
+ move |conn: &'_ _| UserMention::update(conn, user_mention_id, &user_mention_form);
+ if blocking(pool, update_mention).await?.is_err() {
+ return Err(APIError::err("couldnt_update_comment").into());
+ };
- let user_mention_view = UserMentionView::read(&conn, user_mention.id, user_id)?;
+ let user_mention_id = user_mention.id;
+ let user_mention_view = blocking(pool, move |conn| {
+ UserMentionView::read(conn, user_mention_id, user_id)
+ })
+ .await??;
Ok(UserMentionResponse {
mention: user_mention_view,
@@ -855,14 +901,15 @@ impl Perform for Oper<EditUserMention> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<MarkAllAsRead> {
type Response = GetRepliesResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
_websocket_info: Option<WebsocketInfo>,
- ) -> Result<GetRepliesResponse, Error> {
+ ) -> Result<GetRepliesResponse, LemmyError> {
let data: &MarkAllAsRead = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -872,28 +919,35 @@ impl Perform for Oper<MarkAllAsRead> {
let user_id = claims.id;
- let conn = pool.get()?;
-
- let replies = ReplyQueryBuilder::create(&conn, user_id)
- .unread_only(true)
- .page(1)
- .limit(999)
- .list()?;
+ let replies = blocking(pool, move |conn| {
+ ReplyQueryBuilder::create(conn, user_id)
+ .unread_only(true)
+ .page(1)
+ .limit(999)
+ .list()
+ })
+ .await??;
+ // TODO: this should probably be a bulk operation
for reply in &replies {
- match Comment::mark_as_read(&conn, reply.id) {
- Ok(comment) => comment,
- Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
- };
+ let reply_id = reply.id;
+ let mark_as_read = move |conn: &'_ _| Comment::mark_as_read(conn, reply_id);
+ if blocking(pool, mark_as_read).await?.is_err() {
+ return Err(APIError::err("couldnt_update_comment").into());
+ }
}
// Mentions
- let mentions = UserMentionQueryBuilder::create(&conn, user_id)
- .unread_only(true)
- .page(1)
- .limit(999)
- .list()?;
+ let mentions = blocking(pool, move |conn| {
+ UserMentionQueryBuilder::create(conn, user_id)
+ .unread_only(true)
+ .page(1)
+ .limit(999)
+ .list()
+ })
+ .await??;
+ // TODO: this should probably be a bulk operation
for mention in &mentions {
let mention_form = UserMentionForm {
recipient_id: mention.to_owned().recipient_id,
@@ -901,20 +955,25 @@ impl Perform for Oper<MarkAllAsRead> {
read: Some(true),
};
- let _updated_mention =
- match UserMention::update(&conn, mention.user_mention_id, &mention_form) {
- Ok(mention) => mention,
- Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
- };
+ let user_mention_id = mention.user_mention_id;
+ let update_mention =
+ move |conn: &'_ _| UserMention::update(conn, user_mention_id, &mention_form);
+ if blocking(pool, update_mention).await?.is_err() {
+ return Err(APIError::err("couldnt_update_comment").into());
+ }
}
// messages
- let messages = PrivateMessageQueryBuilder::create(&conn, user_id)
- .page(1)
- .limit(999)
- .unread_only(true)
- .list()?;
+ let messages = blocking(pool, move |conn| {
+ PrivateMessageQueryBuilder::create(conn, user_id)
+ .page(1)
+ .limit(999)
+ .unread_only(true)
+ .list()
+ })
+ .await??;
+ // TODO: this should probably be a bulk operation
for message in &messages {
let private_message_form = PrivateMessageForm {
content: message.to_owned().content,
@@ -928,25 +987,27 @@ impl Perform for Oper<MarkAllAsRead> {
published: None,
};
- let _updated_message = match PrivateMessage::update(&conn, message.id, &private_message_form)
- {
- Ok(message) => message,
- Err(_e) => return Err(APIError::err("couldnt_update_private_message").into()),
- };
+ let message_id = message.id;
+ let update_pm =
+ move |conn: &'_ _| PrivateMessage::update(conn, message_id, &private_message_form);
+ if blocking(pool, update_pm).await?.is_err() {
+ return Err(APIError::err("couldnt_update_private_message").into());
+ }
}
Ok(GetRepliesResponse { replies: vec![] })
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<DeleteAccount> {
type Response = LoginResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
_websocket_info: Option<WebsocketInfo>,
- ) -> Result<LoginResponse, Error> {
+ ) -> Result<LoginResponse, LemmyError> {
let data: &DeleteAccount = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -956,9 +1017,7 @@ impl Perform for Oper<DeleteAccount> {
let user_id = claims.id;
- let conn = pool.get()?;
-
- let user: User_ = User_::read(&conn, user_id)?;
+ let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
// Verify the password
let valid: bool = verify(&data.password, &user.password_encrypted).unwrap_or(false);
@@ -967,30 +1026,40 @@ impl Perform for Oper<DeleteAccount> {
}
// Comments
- let comments = CommentQueryBuilder::create(&conn)
- .for_creator_id(user_id)
- .limit(std::i64::MAX)
- .list()?;
+ let comments = blocking(pool, move |conn| {
+ CommentQueryBuilder::create(conn)
+ .for_creator_id(user_id)
+ .limit(std::i64::MAX)
+ .list()
+ })
+ .await??;
+ // TODO: this should probably be a bulk operation
for comment in &comments {
- let _updated_comment = match Comment::permadelete(&conn, comment.id) {
- Ok(comment) => comment,
- Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
- };
+ let comment_id = comment.id;
+ let permadelete = move |conn: &'_ _| Comment::permadelete(conn, comment_id);
+ if blocking(pool, permadelete).await?.is_err() {
+ return Err(APIError::err("couldnt_update_comment").into());
+ }
}
// Posts
- let posts = PostQueryBuilder::create(&conn)
- .sort(&SortType::New)
- .for_creator_id(user_id)
- .limit(std::i64::MAX)
- .list()?;
+ let posts = blocking(pool, move |conn| {
+ PostQueryBuilder::create(conn)
+ .sort(&SortType::New)
+ .for_creator_id(user_id)
+ .limit(std::i64::MAX)
+ .list()
+ })
+ .await??;
+ // TODO: this should probably be a bulk operation
for post in &posts {
- let _updated_post = match Post::permadelete(&conn, post.id) {
- Ok(post) => post,
- Err(_e) => return Err(APIError::err("couldnt_update_post").into()),
- };
+ let post_id = post.id;
+ let permadelete = move |conn: &'_ _| Post::permadelete(conn, post_id);
+ if blocking(pool, permadelete).await?.is_err() {
+ return Err(APIError::err("couldnt_update_post").into());
+ }
}
Ok(LoginResponse {
@@ -999,20 +1068,20 @@ impl Perform for Oper<DeleteAccount> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<PasswordReset> {
type Response = PasswordResetResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
_websocket_info: Option<WebsocketInfo>,
- ) -> Result<PasswordResetResponse, Error> {
+ ) -> Result<PasswordResetResponse, LemmyError> {
let data: &PasswordReset = &self.data;
- let conn = pool.get()?;
-
// Fetch that email
- let user: User_ = match User_::find_by_email(&conn, &data.email) {
+ let email = data.email.clone();
+ let user = match blocking(pool, move |conn| User_::find_by_email(conn, &email)).await? {
Ok(user) => user,
Err(_e) => return Err(APIError::err("couldnt_find_that_username_or_email").into()),
};
@@ -1021,7 +1090,12 @@ impl Perform for Oper<PasswordReset> {
let token = generate_random_string();
// Insert the row
- PasswordResetRequest::create_token(&conn, user.id, &token)?;
+ let token2 = token.clone();
+ let user_id = user.id;
+ blocking(pool, move |conn| {
+ PasswordResetRequest::create_token(conn, user_id, &token2)
+ })
+ .await??;
// Email the pure token to the user.
// TODO no i18n support here.
@@ -1038,20 +1112,23 @@ impl Perform for Oper<PasswordReset> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<PasswordChange> {
type Response = LoginResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
_websocket_info: Option<WebsocketInfo>,
- ) -> Result<LoginResponse, Error> {
+ ) -> Result<LoginResponse, LemmyError> {
let data: &PasswordChange = &self.data;
- let conn = pool.get()?;
-
// Fetch the user_id from the token
- let user_id = PasswordResetRequest::read_from_token(&conn, &data.token)?.user_id;
+ let token = data.token.clone();
+ let user_id = blocking(pool, move |conn| {
+ PasswordResetRequest::read_from_token(conn, &token).map(|p| p.user_id)
+ })
+ .await??;
// Make sure passwords match
if data.password != data.password_verify {
@@ -1059,7 +1136,12 @@ impl Perform for Oper<PasswordChange> {
}
// Update the user with the new password
- let updated_user = match User_::update_password(&conn, user_id, &data.password) {
+ let password = data.password.clone();
+ let updated_user = match blocking(pool, move |conn| {
+ User_::update_password(conn, user_id, &password)
+ })
+ .await?
+ {
Ok(user) => user,
Err(_e) => return Err(APIError::err("couldnt_update_user").into()),
};
@@ -1071,14 +1153,15 @@ impl Perform for Oper<PasswordChange> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<CreatePrivateMessage> {
type Response = PrivateMessageResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
websocket_info: Option<WebsocketInfo>,
- ) -> Result<PrivateMessageResponse, Error> {
+ ) -> Result<PrivateMessageResponse, LemmyError> {
let data: &CreatePrivateMessage = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -1090,10 +1173,8 @@ impl Perform for Oper<CreatePrivateMessage> {
let hostname = &format!("https://{}", Settings::get().hostname);
- 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());
}
@@ -1112,23 +1193,34 @@ impl Perform for Oper<CreatePrivateMessage> {
published: None,
};
- let inserted_private_message = match PrivateMessage::create(&conn, &private_message_form) {
+ let inserted_private_message = match blocking(pool, move |conn| {
+ PrivateMessage::create(conn, &private_message_form)
+ })
+ .await?
+ {
Ok(private_message) => private_message,
Err(_e) => {
return Err(APIError::err("couldnt_create_private_message").into());
}
};
- let updated_private_message =
- match PrivateMessage::update_ap_id(&conn, inserted_private_message.id) {
- Ok(private_message) => private_message,
- Err(_e) => return Err(APIError::err("couldnt_create_private_message").into()),
- };
+ let inserted_private_message_id = inserted_private_message.id;
+ let updated_private_message = match blocking(pool, move |conn| {
+ PrivateMessage::update_ap_id(&conn, inserted_private_message_id)
+ })
+ .await?
+ {
+ Ok(private_message) => private_message,
+ Err(_e) => return Err(APIError::err("couldnt_create_private_message").into()),
+ };
- updated_private_message.send_create(&user, &conn)?;
+ updated_private_message
+ .send_create(&user, &self.client, pool)
+ .await?;
// Send notifications to the recipient
- let recipient_user = User_::read(&conn, data.recipient_id)?;
+ let recipient_id = data.recipient_id;
+ let recipient_user = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
if recipient_user.send_notifications_to_email {
if let Some(email) = recipient_user.email {
let subject = &format!(
@@ -1147,7 +1239,10 @@ impl Perform for Oper<CreatePrivateMessage> {
}
}
- let message = PrivateMessageView::read(&conn, inserted_private_message.id)?;
+ let message = blocking(pool, move |conn| {
+ PrivateMessageView::read(conn, inserted_private_message.id)
+ })
+ .await??;
let res = PrivateMessageResponse { message };
@@ -1164,14 +1259,15 @@ impl Perform for Oper<CreatePrivateMessage> {
}
}
+#[async_trait::async_trait(?Send)]
impl Perform for Oper<EditPrivateMessage> {
type Response = PrivateMessageResponse;
- fn perform(
+ async fn perform(
&self,
- pool: Pool<ConnectionManager<PgConnection>>,
+ pool: &DbPool,
websocket_info: Option<WebsocketInfo>,
- ) -> Result<PrivateMessageResponse, Error> {
+ ) -> Result<PrivateMessageResponse, LemmyError> {
let data: &EditPrivateMessage = &self.data;
let claims = match Claims::decode(&data.auth) {
@@ -1181,12 +1277,12 @@ impl Perform for Oper<EditPrivateMessage> {
let user_id = claims.id;
- let conn = pool.get()?;
-
- let orig_private_message = PrivateMessage::read(&conn, data.edit_id)?;
+ let edit_id = data.edit_id;
+ let orig_private_message =
+ blocking(pool, move |conn| PrivateMessage::read(conn, edit_id)).await??;
// 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());
}
@@ -1219,23 +1315,34 @@ impl Perform for Oper<EditPrivateMessage> {
published: None,
};
- let updated_private_message =
- match PrivateMessage::update(&conn, data.edit_id, &private_message_form) {
- Ok(private_message) => private_message,
- Err(_e) => return Err(APIError::err("couldnt_update_private_message").into()),
- };
+ let edit_id = data.edit_id;
+ let updated_private_message = match blocking(pool, move |conn| {
+ PrivateMessage::update(conn, edit_id, &private_message_form)
+ })
+ .await?
+ {
+ Ok(private_message) => private_message,
+ Err(_e) => return Err(APIError::err("couldnt_update_private_message").into()),
+ };
if let Some(deleted) = data.deleted.to_owned() {
if deleted {
- updated_private_message.send_delete(&user, &conn)?;
+ updated_private_message
+