mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-12-23 03:11:32 +00:00
Some API cleanup, adding site_id to site aggregates.
This commit is contained in:
parent
3f36730dba
commit
2d7d9cf7d8
25 changed files with 247 additions and 236 deletions
|
@ -1,5 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
check_community_ban,
|
check_community_ban,
|
||||||
|
check_downvotes_enabled,
|
||||||
collect_moderated_communities,
|
collect_moderated_communities,
|
||||||
get_post,
|
get_post,
|
||||||
get_user_from_jwt,
|
get_user_from_jwt,
|
||||||
|
@ -11,16 +12,13 @@ use actix_web::web::Data;
|
||||||
use lemmy_apub::{ApubLikeableType, ApubObjectType};
|
use lemmy_apub::{ApubLikeableType, ApubObjectType};
|
||||||
use lemmy_db::{
|
use lemmy_db::{
|
||||||
source::{
|
source::{
|
||||||
comment::*,
|
comment::{Comment, CommentForm, CommentLike, CommentLikeForm, CommentSaved, CommentSavedForm},
|
||||||
comment_report::{CommentReport, CommentReportForm},
|
comment_report::{CommentReport, CommentReportForm},
|
||||||
moderator::*,
|
moderator::{ModRemoveComment, ModRemoveCommentForm},
|
||||||
post::*,
|
|
||||||
user::*,
|
|
||||||
},
|
},
|
||||||
views::{
|
views::{
|
||||||
comment_report_view::{CommentReportQueryBuilder, CommentReportView},
|
comment_report_view::{CommentReportQueryBuilder, CommentReportView},
|
||||||
comment_view::{CommentQueryBuilder, CommentView},
|
comment_view::{CommentQueryBuilder, CommentView},
|
||||||
site_view::SiteView,
|
|
||||||
},
|
},
|
||||||
Crud,
|
Crud,
|
||||||
Likeable,
|
Likeable,
|
||||||
|
@ -110,6 +108,7 @@ impl Perform for CreateComment {
|
||||||
updated_comment.send_create(&user, context).await?;
|
updated_comment.send_create(&user, context).await?;
|
||||||
|
|
||||||
// Scan the comment for user mentions, add those rows
|
// Scan the comment for user mentions, add those rows
|
||||||
|
let post_id = post.id;
|
||||||
let mentions = scrape_text_for_mentions(&comment_form.content);
|
let mentions = scrape_text_for_mentions(&comment_form.content);
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
mentions,
|
mentions,
|
||||||
|
@ -124,7 +123,7 @@ impl Perform for CreateComment {
|
||||||
// You like your own comment by default
|
// You like your own comment by default
|
||||||
let like_form = CommentLikeForm {
|
let like_form = CommentLikeForm {
|
||||||
comment_id: inserted_comment.id,
|
comment_id: inserted_comment.id,
|
||||||
post_id: data.post_id,
|
post_id,
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
|
@ -156,6 +155,7 @@ impl Perform for CreateComment {
|
||||||
|
|
||||||
// strip out the recipient_ids, so that
|
// strip out the recipient_ids, so that
|
||||||
// users don't get double notifs
|
// users don't get double notifs
|
||||||
|
// TODO Do this in a different way
|
||||||
res.recipient_ids = Vec::new();
|
res.recipient_ids = Vec::new();
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
|
@ -203,16 +203,13 @@ impl Perform for EditComment {
|
||||||
updated_comment.send_update(&user, context).await?;
|
updated_comment.send_update(&user, context).await?;
|
||||||
|
|
||||||
// Do the mentions / recipients
|
// Do the mentions / recipients
|
||||||
let post_id = orig_comment.post.id;
|
|
||||||
let post = get_post(post_id, context.pool()).await?;
|
|
||||||
|
|
||||||
let updated_comment_content = updated_comment.content.to_owned();
|
let updated_comment_content = updated_comment.content.to_owned();
|
||||||
let mentions = scrape_text_for_mentions(&updated_comment_content);
|
let mentions = scrape_text_for_mentions(&updated_comment_content);
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
mentions,
|
mentions,
|
||||||
updated_comment,
|
updated_comment,
|
||||||
&user,
|
&user,
|
||||||
post,
|
orig_comment.post,
|
||||||
context.pool(),
|
context.pool(),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
|
@ -239,6 +236,7 @@ impl Perform for EditComment {
|
||||||
|
|
||||||
// strip out the recipient_ids, so that
|
// strip out the recipient_ids, so that
|
||||||
// users don't get double notifs
|
// users don't get double notifs
|
||||||
|
// TODO again
|
||||||
res.recipient_ids = Vec::new();
|
res.recipient_ids = Vec::new();
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
|
@ -297,14 +295,13 @@ impl Perform for DeleteComment {
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
// Build the recipients
|
// Build the recipients
|
||||||
let post_id = comment_view.post.id;
|
let comment_view_2 = comment_view.clone();
|
||||||
let post = get_post(post_id, context.pool()).await?;
|
|
||||||
let mentions = vec![];
|
let mentions = vec![];
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
mentions,
|
mentions,
|
||||||
updated_comment,
|
updated_comment,
|
||||||
&user,
|
&user,
|
||||||
post,
|
comment_view_2.post,
|
||||||
context.pool(),
|
context.pool(),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
|
@ -313,7 +310,7 @@ impl Perform for DeleteComment {
|
||||||
let mut res = CommentResponse {
|
let mut res = CommentResponse {
|
||||||
comment_view,
|
comment_view,
|
||||||
recipient_ids,
|
recipient_ids,
|
||||||
form_id: None,
|
form_id: None, // TODO a comment delete might clear forms?
|
||||||
};
|
};
|
||||||
|
|
||||||
context.chat_server().do_send(SendComment {
|
context.chat_server().do_send(SendComment {
|
||||||
|
@ -324,6 +321,7 @@ impl Perform for DeleteComment {
|
||||||
|
|
||||||
// strip out the recipient_ids, so that
|
// strip out the recipient_ids, so that
|
||||||
// users don't get double notifs
|
// users don't get double notifs
|
||||||
|
// TODO again
|
||||||
res.recipient_ids = Vec::new();
|
res.recipient_ids = Vec::new();
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
|
@ -392,14 +390,14 @@ impl Perform for RemoveComment {
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
// Build the recipients
|
// Build the recipients
|
||||||
let post_id = comment_view.post.id;
|
let comment_view_2 = comment_view.clone();
|
||||||
let post = get_post(post_id, context.pool()).await?;
|
|
||||||
let mentions = vec![];
|
let mentions = vec![];
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
mentions,
|
mentions,
|
||||||
updated_comment,
|
updated_comment,
|
||||||
&user,
|
&user,
|
||||||
post,
|
comment_view_2.post,
|
||||||
context.pool(),
|
context.pool(),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
|
@ -408,7 +406,7 @@ impl Perform for RemoveComment {
|
||||||
let mut res = CommentResponse {
|
let mut res = CommentResponse {
|
||||||
comment_view,
|
comment_view,
|
||||||
recipient_ids,
|
recipient_ids,
|
||||||
form_id: None,
|
form_id: None, // TODO maybe this might clear other forms
|
||||||
};
|
};
|
||||||
|
|
||||||
context.chat_server().do_send(SendComment {
|
context.chat_server().do_send(SendComment {
|
||||||
|
@ -419,6 +417,7 @@ impl Perform for RemoveComment {
|
||||||
|
|
||||||
// strip out the recipient_ids, so that
|
// strip out the recipient_ids, so that
|
||||||
// users don't get double notifs
|
// users don't get double notifs
|
||||||
|
// TODO again
|
||||||
res.recipient_ids = Vec::new();
|
res.recipient_ids = Vec::new();
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
|
@ -437,41 +436,23 @@ impl Perform for MarkCommentAsRead {
|
||||||
let data: &MarkCommentAsRead = &self;
|
let data: &MarkCommentAsRead = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let edit_id = data.edit_id;
|
let comment_id = data.comment_id;
|
||||||
let orig_comment = blocking(context.pool(), move |conn| {
|
let orig_comment = blocking(context.pool(), move |conn| {
|
||||||
CommentView::read(&conn, edit_id, None)
|
CommentView::read(&conn, comment_id, None)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
check_community_ban(user.id, orig_comment.community.id, context.pool()).await?;
|
check_community_ban(user.id, orig_comment.community.id, context.pool()).await?;
|
||||||
|
|
||||||
// Verify that only the recipient can mark as read
|
// Verify that only the recipient can mark as read
|
||||||
// Needs to fetch the parent comment / post to get the recipient
|
if user.id != orig_comment.get_recipient_id() {
|
||||||
let parent_id = orig_comment.comment.parent_id;
|
return Err(APIError::err("no_comment_edit_allowed").into());
|
||||||
match parent_id {
|
|
||||||
Some(pid) => {
|
|
||||||
let parent_comment = blocking(context.pool(), move |conn| {
|
|
||||||
CommentView::read(&conn, pid, None)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
if user.id != parent_comment.creator.id {
|
|
||||||
return Err(APIError::err("no_comment_edit_allowed").into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
let parent_post_id = orig_comment.post.id;
|
|
||||||
let parent_post =
|
|
||||||
blocking(context.pool(), move |conn| Post::read(conn, parent_post_id)).await??;
|
|
||||||
if user.id != parent_post.creator_id {
|
|
||||||
return Err(APIError::err("no_comment_edit_allowed").into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the mark as read
|
// Do the mark as read
|
||||||
let read = data.read;
|
let read = data.read;
|
||||||
match blocking(context.pool(), move |conn| {
|
match blocking(context.pool(), move |conn| {
|
||||||
Comment::update_read(conn, edit_id, read)
|
Comment::update_read(conn, comment_id, read)
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
|
@ -480,7 +461,7 @@ impl Perform for MarkCommentAsRead {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Refetch it
|
// Refetch it
|
||||||
let edit_id = data.edit_id;
|
let edit_id = data.comment_id;
|
||||||
let user_id = user.id;
|
let user_id = user.id;
|
||||||
let comment_view = blocking(context.pool(), move |conn| {
|
let comment_view = blocking(context.pool(), move |conn| {
|
||||||
CommentView::read(conn, edit_id, Some(user_id))
|
CommentView::read(conn, edit_id, Some(user_id))
|
||||||
|
@ -556,12 +537,7 @@ impl Perform for CreateCommentLike {
|
||||||
let mut recipient_ids = Vec::new();
|
let mut recipient_ids = Vec::new();
|
||||||
|
|
||||||
// Don't do a downvote if site has downvotes disabled
|
// Don't do a downvote if site has downvotes disabled
|
||||||
if data.score == -1 {
|
check_downvotes_enabled(data.score, context.pool()).await?;
|
||||||
let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
|
|
||||||
if !site_view.site.enable_downvotes {
|
|
||||||
return Err(APIError::err("downvotes_disabled").into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let orig_comment = blocking(context.pool(), move |conn| {
|
let orig_comment = blocking(context.pool(), move |conn| {
|
||||||
|
@ -569,34 +545,14 @@ impl Perform for CreateCommentLike {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let post_id = orig_comment.post.id;
|
check_community_ban(user.id, orig_comment.community.id, context.pool()).await?;
|
||||||
let post = get_post(post_id, context.pool()).await?;
|
|
||||||
check_community_ban(user.id, post.community_id, context.pool()).await?;
|
|
||||||
|
|
||||||
let comment_id = data.comment_id;
|
// Add parent user to recipients
|
||||||
let comment = blocking(context.pool(), move |conn| Comment::read(conn, comment_id)).await??;
|
recipient_ids.push(orig_comment.get_recipient_id());
|
||||||
|
|
||||||
// Add to recipient ids
|
|
||||||
match comment.parent_id {
|
|
||||||
Some(parent_id) => {
|
|
||||||
let parent_comment =
|
|
||||||
blocking(context.pool(), move |conn| Comment::read(conn, parent_id)).await??;
|
|
||||||
if parent_comment.creator_id != user.id {
|
|
||||||
let parent_user = blocking(context.pool(), move |conn| {
|
|
||||||
User_::read(conn, parent_comment.creator_id)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
recipient_ids.push(parent_user.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
recipient_ids.push(post.creator_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let like_form = CommentLikeForm {
|
let like_form = CommentLikeForm {
|
||||||
comment_id: data.comment_id,
|
comment_id: data.comment_id,
|
||||||
post_id,
|
post_id: orig_comment.post.id,
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
score: data.score,
|
score: data.score,
|
||||||
};
|
};
|
||||||
|
@ -609,6 +565,7 @@ impl Perform for CreateCommentLike {
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
// Only add the like if the score isnt 0
|
// Only add the like if the score isnt 0
|
||||||
|
let comment = orig_comment.comment;
|
||||||
let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
|
let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
|
||||||
if do_add {
|
if do_add {
|
||||||
let like_form2 = like_form.clone();
|
let like_form2 = like_form.clone();
|
||||||
|
@ -649,6 +606,7 @@ impl Perform for CreateCommentLike {
|
||||||
// strip out the recipient_ids, so that
|
// strip out the recipient_ids, so that
|
||||||
// users don't get double notifs
|
// users don't get double notifs
|
||||||
res.recipient_ids = Vec::new();
|
res.recipient_ids = Vec::new();
|
||||||
|
// TODO why
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,20 +58,22 @@ impl Perform for GetCommunity {
|
||||||
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?;
|
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?;
|
||||||
let user_id = user.map(|u| u.id);
|
let user_id = user.map(|u| u.id);
|
||||||
|
|
||||||
let name = data.name.to_owned().unwrap_or_else(|| "main".to_string());
|
let community_id = match data.id {
|
||||||
let community = match data.id {
|
Some(id) => id,
|
||||||
Some(id) => blocking(context.pool(), move |conn| Community::read(conn, id)).await??,
|
None => {
|
||||||
None => match blocking(context.pool(), move |conn| {
|
let name = data.name.to_owned().unwrap_or_else(|| "main".to_string());
|
||||||
Community::read_from_name(conn, &name)
|
match blocking(context.pool(), move |conn| {
|
||||||
})
|
Community::read_from_name(conn, &name)
|
||||||
.await?
|
})
|
||||||
{
|
.await?
|
||||||
Ok(community) => community,
|
{
|
||||||
Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
|
Ok(community) => community,
|
||||||
},
|
Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
|
||||||
|
}
|
||||||
|
.id
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let community_id = community.id;
|
|
||||||
let community_view = match blocking(context.pool(), move |conn| {
|
let community_view = match blocking(context.pool(), move |conn| {
|
||||||
CommunityView::read(conn, community_id, user_id)
|
CommunityView::read(conn, community_id, user_id)
|
||||||
})
|
})
|
||||||
|
@ -81,7 +83,6 @@ impl Perform for GetCommunity {
|
||||||
Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
|
Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let community_id = community.id;
|
|
||||||
let moderators: Vec<CommunityModeratorView> = match blocking(context.pool(), move |conn| {
|
let moderators: Vec<CommunityModeratorView> = match blocking(context.pool(), move |conn| {
|
||||||
CommunityModeratorView::for_community(conn, community_id)
|
CommunityModeratorView::for_community(conn, community_id)
|
||||||
})
|
})
|
||||||
|
@ -178,6 +179,7 @@ impl Perform for CreateCommunity {
|
||||||
Err(_e) => return Err(APIError::err("community_already_exists").into()),
|
Err(_e) => return Err(APIError::err("community_already_exists").into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The community creator becomes a moderator
|
||||||
let community_moderator_form = CommunityModeratorForm {
|
let community_moderator_form = CommunityModeratorForm {
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
|
@ -188,6 +190,7 @@ impl Perform for CreateCommunity {
|
||||||
return Err(APIError::err("community_moderator_already_exists").into());
|
return Err(APIError::err("community_moderator_already_exists").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Follow your own community
|
||||||
let community_follower_form = CommunityFollowerForm {
|
let community_follower_form = CommunityFollowerForm {
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
|
@ -584,15 +587,15 @@ impl Perform for BanFromCommunity {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove/Restore their data if that's desired
|
// Remove/Restore their data if that's desired
|
||||||
if let Some(remove_data) = data.remove_data {
|
if data.remove_data {
|
||||||
// Posts
|
// Posts
|
||||||
blocking(context.pool(), move |conn: &'_ _| {
|
blocking(context.pool(), move |conn: &'_ _| {
|
||||||
Post::update_removed_for_creator(conn, banned_user_id, Some(community_id), remove_data)
|
Post::update_removed_for_creator(conn, banned_user_id, Some(community_id), true)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
// Comments
|
// Comments
|
||||||
// Diesel doesn't allow updates with joins, so this has to be a loop
|
// TODO Diesel doesn't allow updates with joins, so this has to be a loop
|
||||||
let comments = blocking(context.pool(), move |conn| {
|
let comments = blocking(context.pool(), move |conn| {
|
||||||
CommentQueryBuilder::create(conn)
|
CommentQueryBuilder::create(conn)
|
||||||
.creator_id(banned_user_id)
|
.creator_id(banned_user_id)
|
||||||
|
@ -605,7 +608,7 @@ impl Perform for BanFromCommunity {
|
||||||
for comment_view in &comments {
|
for comment_view in &comments {
|
||||||
let comment_id = comment_view.comment.id;
|
let comment_id = comment_view.comment.id;
|
||||||
blocking(context.pool(), move |conn: &'_ _| {
|
blocking(context.pool(), move |conn: &'_ _| {
|
||||||
Comment::update_removed(conn, comment_id, remove_data)
|
Comment::update_removed(conn, comment_id, true)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
}
|
}
|
||||||
|
@ -743,6 +746,7 @@ impl Perform for TransferCommunity {
|
||||||
|
|
||||||
let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??;
|
let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??;
|
||||||
|
|
||||||
|
// Making sure the creator, if an admin, is at the top
|
||||||
let creator_index = admins
|
let creator_index = admins
|
||||||
.iter()
|
.iter()
|
||||||
.position(|r| r.user.id == site_creator_id)
|
.position(|r| r.user.id == site_creator_id)
|
||||||
|
|
|
@ -4,6 +4,7 @@ use lemmy_db::{
|
||||||
source::{
|
source::{
|
||||||
community::{Community, CommunityModerator},
|
community::{Community, CommunityModerator},
|
||||||
post::Post,
|
post::Post,
|
||||||
|
site::Site,
|
||||||
user::User_,
|
user::User_,
|
||||||
},
|
},
|
||||||
views::community::community_user_ban_view::CommunityUserBanView,
|
views::community::community_user_ban_view::CommunityUserBanView,
|
||||||
|
@ -102,6 +103,16 @@ pub(crate) async fn check_community_ban(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn check_downvotes_enabled(score: i16, pool: &DbPool) -> Result<(), LemmyError> {
|
||||||
|
if score == -1 {
|
||||||
|
let site = blocking(pool, move |conn| Site::read_simple(conn)).await??;
|
||||||
|
if !site.enable_downvotes {
|
||||||
|
return Err(APIError::err("downvotes_disabled").into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a list of communities that the user moderates
|
/// Returns a list of communities that the user moderates
|
||||||
/// or if a community_id is supplied validates the user is a moderator
|
/// or if a community_id is supplied validates the user is a moderator
|
||||||
/// of that community and returns the community id in a vec
|
/// of that community and returns the community id in a vec
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
check_community_ban,
|
check_community_ban,
|
||||||
|
check_downvotes_enabled,
|
||||||
check_optional_url,
|
check_optional_url,
|
||||||
collect_moderated_communities,
|
collect_moderated_communities,
|
||||||
get_user_from_jwt,
|
get_user_from_jwt,
|
||||||
|
@ -18,10 +19,9 @@ use lemmy_db::{
|
||||||
},
|
},
|
||||||
views::{
|
views::{
|
||||||
comment_view::CommentQueryBuilder,
|
comment_view::CommentQueryBuilder,
|
||||||
community::{community_moderator_view::CommunityModeratorView, community_view::CommunityView},
|
community::community_moderator_view::CommunityModeratorView,
|
||||||
post_report_view::{PostReportQueryBuilder, PostReportView},
|
post_report_view::{PostReportQueryBuilder, PostReportView},
|
||||||
post_view::{PostQueryBuilder, PostView},
|
post_view::{PostQueryBuilder, PostView},
|
||||||
site_view::SiteView,
|
|
||||||
},
|
},
|
||||||
Crud,
|
Crud,
|
||||||
Likeable,
|
Likeable,
|
||||||
|
@ -192,12 +192,6 @@ impl Perform for GetPost {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let community_id = post_view.community.id;
|
|
||||||
let community = blocking(context.pool(), move |conn| {
|
|
||||||
CommunityView::read(conn, community_id, user_id)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
let community_id = post_view.community.id;
|
let community_id = post_view.community.id;
|
||||||
let moderators = blocking(context.pool(), move |conn| {
|
let moderators = blocking(context.pool(), move |conn| {
|
||||||
CommunityModeratorView::for_community(conn, community_id)
|
CommunityModeratorView::for_community(conn, community_id)
|
||||||
|
@ -214,7 +208,6 @@ impl Perform for GetPost {
|
||||||
Ok(GetPostResponse {
|
Ok(GetPostResponse {
|
||||||
post_view,
|
post_view,
|
||||||
comments,
|
comments,
|
||||||
community,
|
|
||||||
moderators,
|
moderators,
|
||||||
online,
|
online,
|
||||||
})
|
})
|
||||||
|
@ -285,12 +278,7 @@ impl Perform for CreatePostLike {
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
// Don't do a downvote if site has downvotes disabled
|
// Don't do a downvote if site has downvotes disabled
|
||||||
if data.score == -1 {
|
check_downvotes_enabled(data.score, context.pool()).await?;
|
||||||
let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
|
|
||||||
if !site_view.site.enable_downvotes {
|
|
||||||
return Err(APIError::err("downvotes_disabled").into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for a community ban
|
// Check for a community ban
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
|
|
|
@ -10,7 +10,6 @@ use actix_web::web::Data;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use lemmy_apub::fetcher::search_by_apub_id;
|
use lemmy_apub::fetcher::search_by_apub_id;
|
||||||
use lemmy_db::{
|
use lemmy_db::{
|
||||||
aggregates::site_aggregates::SiteAggregates,
|
|
||||||
diesel_option_overwrite,
|
diesel_option_overwrite,
|
||||||
naive_now,
|
naive_now,
|
||||||
source::{category::*, moderator::*, site::*},
|
source::{category::*, moderator::*, site::*},
|
||||||
|
@ -156,7 +155,7 @@ impl Perform for CreateSite {
|
||||||
) -> Result<SiteResponse, LemmyError> {
|
) -> Result<SiteResponse, LemmyError> {
|
||||||
let data: &CreateSite = &self;
|
let data: &CreateSite = &self;
|
||||||
|
|
||||||
let read_site = move |conn: &'_ _| Site::read(conn, 1);
|
let read_site = move |conn: &'_ _| Site::read_simple(conn);
|
||||||
if blocking(context.pool(), read_site).await?.is_ok() {
|
if blocking(context.pool(), read_site).await?.is_ok() {
|
||||||
return Err(APIError::err("site_already_exists").into());
|
return Err(APIError::err("site_already_exists").into());
|
||||||
};
|
};
|
||||||
|
@ -188,7 +187,7 @@ impl Perform for CreateSite {
|
||||||
|
|
||||||
let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
|
let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
|
||||||
|
|
||||||
Ok(SiteResponse { site: site_view })
|
Ok(SiteResponse { site_view })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +208,7 @@ impl Perform for EditSite {
|
||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
is_admin(context.pool(), user.id).await?;
|
is_admin(context.pool(), user.id).await?;
|
||||||
|
|
||||||
let found_site = blocking(context.pool(), move |conn| Site::read(conn, 1)).await??;
|
let found_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
|
||||||
|
|
||||||
let icon = diesel_option_overwrite(&data.icon);
|
let icon = diesel_option_overwrite(&data.icon);
|
||||||
let banner = diesel_option_overwrite(&data.banner);
|
let banner = diesel_option_overwrite(&data.banner);
|
||||||
|
@ -233,7 +232,7 @@ impl Perform for EditSite {
|
||||||
|
|
||||||
let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
|
let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
|
||||||
|
|
||||||
let res = SiteResponse { site: site_view };
|
let res = SiteResponse { site_view };
|
||||||
|
|
||||||
context.chat_server().do_send(SendAllMessage {
|
context.chat_server().do_send(SendAllMessage {
|
||||||
op: UserOperation::EditSite,
|
op: UserOperation::EditSite,
|
||||||
|
@ -256,39 +255,41 @@ impl Perform for GetSite {
|
||||||
) -> Result<GetSiteResponse, LemmyError> {
|
) -> Result<GetSiteResponse, LemmyError> {
|
||||||
let data: &GetSite = &self;
|
let data: &GetSite = &self;
|
||||||
|
|
||||||
// TODO refactor this a little
|
let site_view = match blocking(context.pool(), move |conn| SiteView::read(conn)).await? {
|
||||||
let res = blocking(context.pool(), move |conn| Site::read(conn, 1)).await?;
|
Ok(site_view) => Some(site_view),
|
||||||
let site_view = if res.is_ok() {
|
// If the site isn't created yet, check the setup
|
||||||
Some(blocking(context.pool(), move |conn| SiteView::read(conn)).await??)
|
Err(_) => {
|
||||||
} else if let Some(setup) = Settings::get().setup.as_ref() {
|
if let Some(setup) = Settings::get().setup.as_ref() {
|
||||||
let register = Register {
|
let register = Register {
|
||||||
username: setup.admin_username.to_owned(),
|
username: setup.admin_username.to_owned(),
|
||||||
email: setup.admin_email.to_owned(),
|
email: setup.admin_email.to_owned(),
|
||||||
password: setup.admin_password.to_owned(),
|
password: setup.admin_password.to_owned(),
|
||||||
password_verify: setup.admin_password.to_owned(),
|
password_verify: setup.admin_password.to_owned(),
|
||||||
admin: true,
|
admin: true,
|
||||||
show_nsfw: true,
|
show_nsfw: true,
|
||||||
captcha_uuid: None,
|
captcha_uuid: None,
|
||||||
captcha_answer: None,
|
captcha_answer: None,
|
||||||
};
|
};
|
||||||
let login_response = register.perform(context, websocket_id).await?;
|
let login_response = register.perform(context, websocket_id).await?;
|
||||||
info!("Admin {} created", setup.admin_username);
|
info!("Admin {} created", setup.admin_username);
|
||||||
|
|
||||||
let create_site = CreateSite {
|
let create_site = CreateSite {
|
||||||
name: setup.site_name.to_owned(),
|
name: setup.site_name.to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
icon: None,
|
icon: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
enable_downvotes: true,
|
enable_downvotes: true,
|
||||||
open_registration: true,
|
open_registration: true,
|
||||||
enable_nsfw: true,
|
enable_nsfw: true,
|
||||||
auth: login_response.jwt,
|
auth: login_response.jwt,
|
||||||
};
|
};
|
||||||
create_site.perform(context, websocket_id).await?;
|
create_site.perform(context, websocket_id).await?;
|
||||||
info!("Site {} created", setup.site_name);
|
info!("Site {} created", setup.site_name);
|
||||||
Some(blocking(context.pool(), move |conn| SiteView::read(conn)).await??)
|
Some(blocking(context.pool(), move |conn| SiteView::read(conn)).await??)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??;
|
let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??;
|
||||||
|
@ -321,17 +322,14 @@ impl Perform for GetSite {
|
||||||
u
|
u
|
||||||
});
|
});
|
||||||
|
|
||||||
let counts = blocking(context.pool(), move |conn| SiteAggregates::read(conn)).await??;
|
|
||||||
|
|
||||||
Ok(GetSiteResponse {
|
Ok(GetSiteResponse {
|
||||||
site: site_view,
|
site_view,
|
||||||
admins,
|
admins,
|
||||||
banned,
|
banned,
|
||||||
online,
|
online,
|
||||||
version: version::VERSION.to_string(),
|
version: version::VERSION.to_string(),
|
||||||
my_user,
|
my_user,
|
||||||
federated_instances: linked_instances(context.pool()).await?,
|
federated_instances: linked_instances(context.pool()).await?,
|
||||||
counts,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -521,7 +519,7 @@ impl Perform for TransferSite {
|
||||||
user.private_key = None;
|
user.private_key = None;
|
||||||
user.public_key = None;
|
user.public_key = None;
|
||||||
|
|
||||||
let read_site = blocking(context.pool(), move |conn| Site::read(conn, 1)).await??;
|
let read_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
|
||||||
|
|
||||||
// Make sure user is the creator
|
// Make sure user is the creator
|
||||||
if read_site.creator_id != user.id {
|
if read_site.creator_id != user.id {
|
||||||
|
@ -555,17 +553,14 @@ impl Perform for TransferSite {
|
||||||
|
|
||||||
let banned = blocking(context.pool(), move |conn| UserViewSafe::banned(conn)).await??;
|
let banned = blocking(context.pool(), move |conn| UserViewSafe::banned(conn)).await??;
|
||||||
|
|
||||||
let counts = blocking(context.pool(), move |conn| SiteAggregates::read(conn)).await??;
|
|
||||||
|
|
||||||
Ok(GetSiteResponse {
|
Ok(GetSiteResponse {
|
||||||
site: Some(site_view),
|
site_view: Some(site_view),
|
||||||
admins,
|
admins,
|
||||||
banned,
|
banned,
|
||||||
online: 0,
|
online: 0,
|
||||||
version: version::VERSION.to_string(),
|
version: version::VERSION.to_string(),
|
||||||
my_user: Some(user),
|
my_user: Some(user),
|
||||||
federated_instances: linked_instances(context.pool()).await?,
|
federated_instances: linked_instances(context.pool()).await?,
|
||||||
counts,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -604,12 +599,8 @@ impl Perform for SaveSiteConfig {
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
// Only let admins read this
|
// Only let admins read this
|
||||||
let admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??;
|
let user_id = user.id;
|
||||||
let admin_ids: Vec<i32> = admins.into_iter().map(|m| m.user.id).collect();
|
is_admin(context.pool(), user_id).await?;
|
||||||
|
|
||||||
if !admin_ids.contains(&user.id) {
|
|
||||||
return Err(APIError::err("not_an_admin").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure docker doesn't have :ro at the end of the volume, so its not a read-only filesystem
|
// Make sure docker doesn't have :ro at the end of the volume, so its not a read-only filesystem
|
||||||
let config_hjson = match Settings::save_config_file(&data.config_hjson) {
|
let config_hjson = match Settings::save_config_file(&data.config_hjson) {
|
||||||
|
|
|
@ -38,7 +38,6 @@ use lemmy_db::{
|
||||||
post_report_view::PostReportView,
|
post_report_view::PostReportView,
|
||||||
post_view::PostQueryBuilder,
|
post_view::PostQueryBuilder,
|
||||||
private_message_view::{PrivateMessageQueryBuilder, PrivateMessageView},
|
private_message_view::{PrivateMessageQueryBuilder, PrivateMessageView},
|
||||||
site_view::SiteView,
|
|
||||||
user_mention_view::{UserMentionQueryBuilder, UserMentionView},
|
user_mention_view::{UserMentionQueryBuilder, UserMentionView},
|
||||||
user_view::{UserViewDangerous, UserViewSafe},
|
user_view::{UserViewDangerous, UserViewSafe},
|
||||||
},
|
},
|
||||||
|
@ -120,8 +119,8 @@ impl Perform for Register {
|
||||||
let data: &Register = &self;
|
let data: &Register = &self;
|
||||||
|
|
||||||
// Make sure site has open registration
|
// Make sure site has open registration
|
||||||
if let Ok(site_view) = blocking(context.pool(), move |conn| SiteView::read(conn)).await? {
|
if let Ok(site) = blocking(context.pool(), move |conn| Site::read_simple(conn)).await? {
|
||||||
if !site_view.site.open_registration {
|
if !site.open_registration {
|
||||||
return Err(APIError::err("registration_closed").into());
|
return Err(APIError::err("registration_closed").into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,9 +346,6 @@ impl Perform for SaveUserSettings {
|
||||||
let data: &SaveUserSettings = &self;
|
let data: &SaveUserSettings = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let user_id = user.id;
|
|
||||||
let read_user = blocking(context.pool(), move |conn| User_::read(conn, user_id)).await??;
|
|
||||||
|
|
||||||
let avatar = diesel_option_overwrite(&data.avatar);
|
let avatar = diesel_option_overwrite(&data.avatar);
|
||||||
let banner = diesel_option_overwrite(&data.banner);
|
let banner = diesel_option_overwrite(&data.banner);
|
||||||
let email = diesel_option_overwrite(&data.email);
|
let email = diesel_option_overwrite(&data.email);
|
||||||
|
@ -373,6 +369,7 @@ impl Perform for SaveUserSettings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let user_id = user.id;
|
||||||
let password_encrypted = match &data.new_password {
|
let password_encrypted = match &data.new_password {
|
||||||
Some(new_password) => {
|
Some(new_password) => {
|
||||||
match &data.new_password_verify {
|
match &data.new_password_verify {
|
||||||
|
@ -385,8 +382,7 @@ impl Perform for SaveUserSettings {
|
||||||
// Check the old password
|
// Check the old password
|
||||||
match &data.old_password {
|
match &data.old_password {
|
||||||
Some(old_password) => {
|
Some(old_password) => {
|
||||||
let valid: bool =
|
let valid: bool = verify(old_password, &user.password_encrypted).unwrap_or(false);
|
||||||
verify(old_password, &read_user.password_encrypted).unwrap_or(false);
|
|
||||||
if !valid {
|
if !valid {
|
||||||
return Err(APIError::err("password_incorrect").into());
|
return Err(APIError::err("password_incorrect").into());
|
||||||
}
|
}
|
||||||
|
@ -403,33 +399,36 @@ impl Perform for SaveUserSettings {
|
||||||
None => return Err(APIError::err("passwords_dont_match").into()),
|
None => return Err(APIError::err("passwords_dont_match").into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => read_user.password_encrypted,
|
None => user.password_encrypted,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let default_listing_type = ListingType::from_str(&data.default_listing_type)? as i16;
|
||||||
|
let default_sort_type = SortType::from_str(&data.default_sort_type)? as i16;
|
||||||
|
|
||||||
let user_form = UserForm {
|
let user_form = UserForm {
|
||||||
name: read_user.name,
|
name: user.name,
|
||||||
email,
|
email,
|
||||||
matrix_user_id,
|
matrix_user_id,
|
||||||
avatar,
|
avatar,
|
||||||
banner,
|
banner,
|
||||||
password_encrypted,
|
password_encrypted,
|
||||||
preferred_username,
|
preferred_username,
|
||||||
published: Some(read_user.published),
|
published: Some(user.published),
|
||||||
updated: Some(naive_now()),
|
updated: Some(naive_now()),
|
||||||
admin: read_user.admin,
|
admin: user.admin,
|
||||||
banned: Some(read_user.banned),
|
banned: Some(user.banned),
|
||||||
show_nsfw: data.show_nsfw,
|
show_nsfw: data.show_nsfw,
|
||||||
theme: data.theme.to_owned(),
|
theme: data.theme.to_owned(),
|
||||||
default_sort_type: data.default_sort_type,
|
default_sort_type,
|
||||||
default_listing_type: data.default_listing_type,
|
default_listing_type,
|
||||||
lang: data.lang.to_owned(),
|
lang: data.lang.to_owned(),
|
||||||
show_avatars: data.show_avatars,
|
show_avatars: data.show_avatars,
|
||||||
send_notifications_to_email: data.send_notifications_to_email,
|
send_notifications_to_email: data.send_notifications_to_email,
|
||||||
actor_id: Some(read_user.actor_id),
|
actor_id: Some(user.actor_id),
|
||||||
bio,
|
bio,
|
||||||
local: read_user.local,
|
local: user.local,
|
||||||
private_key: read_user.private_key,
|
private_key: user.private_key,
|
||||||
public_key: read_user.public_key,
|
public_key: user.public_key,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -579,9 +578,8 @@ impl Perform for GetUserDetails {
|
||||||
|
|
||||||
// Return the jwt
|
// Return the jwt
|
||||||
Ok(GetUserDetailsResponse {
|
Ok(GetUserDetailsResponse {
|
||||||
// TODO need to figure out dangerous user view here
|
user_view,
|
||||||
user: user_view,
|
user_view_dangerous: user_dangerous,
|
||||||
user_dangerous,
|
|
||||||
follows,
|
follows,
|
||||||
moderates,
|
moderates,
|
||||||
comments,
|
comments,
|
||||||
|
@ -669,22 +667,22 @@ impl Perform for BanUser {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove their data if that's desired
|
// Remove their data if that's desired
|
||||||
if let Some(remove_data) = data.remove_data {
|
if data.remove_data {
|
||||||
// Posts
|
// Posts
|
||||||
blocking(context.pool(), move |conn: &'_ _| {
|
blocking(context.pool(), move |conn: &'_ _| {
|
||||||
Post::update_removed_for_creator(conn, banned_user_id, None, remove_data)
|
Post::update_removed_for_creator(conn, banned_user_id, None, true)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
// Communities
|
// Communities
|
||||||
blocking(context.pool(), move |conn: &'_ _| {
|
blocking(context.pool(), move |conn: &'_ _| {
|
||||||
Community::update_removed_for_creator(conn, banned_user_id, remove_data)
|
Community::update_removed_for_creator(conn, banned_user_id, true)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
// Comments
|
// Comments
|
||||||
blocking(context.pool(), move |conn: &'_ _| {
|
blocking(context.pool(), move |conn: &'_ _| {
|
||||||
Comment::update_removed_for_creator(conn, banned_user_id, remove_data)
|
Comment::update_removed_for_creator(conn, banned_user_id, true)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
}
|
}
|
||||||
|
@ -712,7 +710,7 @@ impl Perform for BanUser {
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let res = BanUserResponse {
|
let res = BanUserResponse {
|
||||||
user: user_view,
|
user_view,
|
||||||
banned: data.ban,
|
banned: data.ban,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1091,7 +1089,9 @@ impl Perform for CreatePrivateMessage {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let res = PrivateMessageResponse { message };
|
let res = PrivateMessageResponse {
|
||||||
|
private_message_view: message,
|
||||||
|
};
|
||||||
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::CreatePrivateMessage,
|
op: UserOperation::CreatePrivateMessage,
|
||||||
|
@ -1148,7 +1148,9 @@ impl Perform for EditPrivateMessage {
|
||||||
.await??;
|
.await??;
|
||||||
let recipient_id = message.recipient.id;
|
let recipient_id = message.recipient.id;
|
||||||
|
|
||||||
let res = PrivateMessageResponse { message };
|
let res = PrivateMessageResponse {
|
||||||
|
private_message_view: message,
|
||||||
|
};
|
||||||
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::EditPrivateMessage,
|
op: UserOperation::EditPrivateMessage,
|
||||||
|
@ -1211,7 +1213,9 @@ impl Perform for DeletePrivateMessage {
|
||||||
.await??;
|
.await??;
|
||||||
let recipient_id = message.recipient.id;
|
let recipient_id = message.recipient.id;
|
||||||
|
|
||||||
let res = PrivateMessageResponse { message };
|
let res = PrivateMessageResponse {
|
||||||
|
private_message_view: message,
|
||||||
|
};
|
||||||
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::DeletePrivateMessage,
|
op: UserOperation::DeletePrivateMessage,
|
||||||
|
@ -1267,7 +1271,9 @@ impl Perform for MarkPrivateMessageAsRead {
|
||||||
.await??;
|
.await??;
|
||||||
let recipient_id = message.recipient.id;
|
let recipient_id = message.recipient.id;
|
||||||
|
|
||||||
let res = PrivateMessageResponse { message };
|
let res = PrivateMessageResponse {
|
||||||
|
private_message_view: message,
|
||||||
|
};
|
||||||
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::MarkPrivateMessageAsRead,
|
op: UserOperation::MarkPrivateMessageAsRead,
|
||||||
|
@ -1305,7 +1311,9 @@ impl Perform for GetPrivateMessages {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
Ok(PrivateMessagesResponse { messages })
|
Ok(PrivateMessagesResponse {
|
||||||
|
private_messages: messages,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ use lemmy_db::{
|
||||||
post::Post,
|
post::Post,
|
||||||
},
|
},
|
||||||
views::comment_view::CommentView,
|
views::comment_view::CommentView,
|
||||||
|
Crud,
|
||||||
Likeable,
|
Likeable,
|
||||||
};
|
};
|
||||||
use lemmy_structs::{blocking, comment::CommentResponse, send_local_notifs};
|
use lemmy_structs::{blocking, comment::CommentResponse, send_local_notifs};
|
||||||
|
|
|
@ -47,9 +47,11 @@ pub(crate) async fn receive_create_private_message(
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let res = PrivateMessageResponse { message };
|
let res = PrivateMessageResponse {
|
||||||
|
private_message_view: message,
|
||||||
|
};
|
||||||
|
|
||||||
let recipient_id = res.message.recipient.id;
|
let recipient_id = res.private_message_view.recipient.id;
|
||||||
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::CreatePrivateMessage,
|
op: UserOperation::CreatePrivateMessage,
|
||||||
|
@ -85,9 +87,11 @@ pub(crate) async fn receive_update_private_message(
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let res = PrivateMessageResponse { message };
|
let res = PrivateMessageResponse {
|
||||||
|
private_message_view: message,
|
||||||
|
};
|
||||||
|
|
||||||
let recipient_id = res.message.recipient.id;
|
let recipient_id = res.private_message_view.recipient.id;
|
||||||
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::EditPrivateMessage,
|
op: UserOperation::EditPrivateMessage,
|
||||||
|
@ -117,8 +121,10 @@ pub(crate) async fn receive_delete_private_message(
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let res = PrivateMessageResponse { message };
|
let res = PrivateMessageResponse {
|
||||||
let recipient_id = res.message.recipient.id;
|
private_message_view: message,
|
||||||
|
};
|
||||||
|
let recipient_id = res.private_message_view.recipient.id;
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::EditPrivateMessage,
|
op: UserOperation::EditPrivateMessage,
|
||||||
response: res,
|
response: res,
|
||||||
|
@ -152,8 +158,10 @@ pub(crate) async fn receive_undo_delete_private_message(
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let res = PrivateMessageResponse { message };
|
let res = PrivateMessageResponse {
|
||||||
let recipient_id = res.message.recipient.id;
|
private_message_view: message,
|
||||||
|
};
|
||||||
|
let recipient_id = res.private_message_view.recipient.id;
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::EditPrivateMessage,
|
op: UserOperation::EditPrivateMessage,
|
||||||
response: res,
|
response: res,
|
||||||
|
|
|
@ -27,6 +27,7 @@ use lemmy_db::{
|
||||||
user_view::UserViewSafe,
|
user_view::UserViewSafe,
|
||||||
},
|
},
|
||||||
ApubObject,
|
ApubObject,
|
||||||
|
Crud,
|
||||||
Joinable,
|
Joinable,
|
||||||
SearchType,
|
SearchType,
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use actix_web::{body::Body, web, HttpResponse};
|
use actix_web::{body::Body, web, HttpResponse};
|
||||||
use diesel::result::Error::NotFound;
|
use diesel::result::Error::NotFound;
|
||||||
use lemmy_db::source::post::Post;
|
use lemmy_db::{source::post::Post, Crud};
|
||||||
use lemmy_structs::blocking;
|
use lemmy_structs::blocking;
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
|
|
@ -2,10 +2,11 @@ use crate::schema::site_aggregates;
|
||||||
use diesel::{result::Error, *};
|
use diesel::{result::Error, *};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize)]
|
#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
|
||||||
#[table_name = "site_aggregates"]
|
#[table_name = "site_aggregates"]
|
||||||
pub struct SiteAggregates {
|
pub struct SiteAggregates {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
|
pub site_id: i32,
|
||||||
pub users: i64,
|
pub users: i64,
|
||||||
pub posts: i64,
|
pub posts: i64,
|
||||||
pub comments: i64,
|
pub comments: i64,
|
||||||
|
|
|
@ -362,6 +362,7 @@ table! {
|
||||||
table! {
|
table! {
|
||||||
site_aggregates (id) {
|
site_aggregates (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
|
site_id -> Int4,
|
||||||
users -> Int8,
|
users -> Int8,
|
||||||
posts -> Int8,
|
posts -> Int8,
|
||||||
comments -> Int8,
|
comments -> Int8,
|
||||||
|
@ -560,6 +561,7 @@ joinable!(post_report -> post (post_id));
|
||||||
joinable!(post_saved -> post (post_id));
|
joinable!(post_saved -> post (post_id));
|
||||||
joinable!(post_saved -> user_ (user_id));
|
joinable!(post_saved -> user_ (user_id));
|
||||||
joinable!(site -> user_ (creator_id));
|
joinable!(site -> user_ (creator_id));
|
||||||
|
joinable!(site_aggregates -> site (site_id));
|
||||||
joinable!(user_aggregates -> user_ (user_id));
|
joinable!(user_aggregates -> user_ (user_id));
|
||||||
joinable!(user_ban -> user_ (user_id));
|
joinable!(user_ban -> user_ (user_id));
|
||||||
joinable!(user_mention -> comment (comment_id));
|
joinable!(user_mention -> comment (comment_id));
|
||||||
|
|
|
@ -106,11 +106,6 @@ impl ApubObject<PostForm> for Post {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Post {
|
impl Post {
|
||||||
pub fn read(conn: &PgConnection, post_id: i32) -> Result<Self, Error> {
|
|
||||||
use crate::schema::post::dsl::*;
|
|
||||||
post.filter(id.eq(post_id)).first::<Self>(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn list_for_community(
|
pub fn list_for_community(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
the_community_id: i32,
|
the_community_id: i32,
|
||||||
|
|
|
@ -59,4 +59,9 @@ impl Site {
|
||||||
.set((creator_id.eq(new_creator_id), updated.eq(naive_now())))
|
.set((creator_id.eq(new_creator_id), updated.eq(naive_now())))
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_simple(conn: &PgConnection) -> Result<Self, Error> {
|
||||||
|
use crate::schema::site::dsl::*;
|
||||||
|
site.first::<Self>(conn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,6 +145,15 @@ impl CommentView {
|
||||||
my_vote,
|
my_vote,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the recipient user id.
|
||||||
|
/// If there is no parent comment, its the post creator
|
||||||
|
pub fn get_recipient_id(&self) -> i32 {
|
||||||
|
match &self.recipient {
|
||||||
|
Some(parent_commenter) => parent_commenter.id,
|
||||||
|
None => self.post.creator_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CommentQueryBuilder<'a> {
|
pub struct CommentQueryBuilder<'a> {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
schema::{site, user_},
|
aggregates::site_aggregates::SiteAggregates,
|
||||||
|
schema::{site, site_aggregates, user_},
|
||||||
source::{
|
source::{
|
||||||
site::Site,
|
site::Site,
|
||||||
user::{UserSafe, User_},
|
user::{UserSafe, User_},
|
||||||
|
@ -13,15 +14,25 @@ use serde::Serialize;
|
||||||
pub struct SiteView {
|
pub struct SiteView {
|
||||||
pub site: Site,
|
pub site: Site,
|
||||||
pub creator: UserSafe,
|
pub creator: UserSafe,
|
||||||
|
pub counts: SiteAggregates,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SiteView {
|
impl SiteView {
|
||||||
pub fn read(conn: &PgConnection) -> Result<Self, Error> {
|
pub fn read(conn: &PgConnection) -> Result<Self, Error> {
|
||||||
let (site, creator) = site::table
|
let (site, creator, counts) = site::table
|
||||||
.inner_join(user_::table)
|
.inner_join(user_::table)
|
||||||
.select((site::all_columns, User_::safe_columns_tuple()))
|
.inner_join(site_aggregates::table)
|
||||||
.first::<(Site, UserSafe)>(conn)?;
|
.select((
|
||||||
|
site::all_columns,
|
||||||
|
User_::safe_columns_tuple(),
|
||||||
|
site_aggregates::all_columns,
|
||||||
|
))
|
||||||
|
.first::<(Site, UserSafe, SiteAggregates)>(conn)?;
|
||||||
|
|
||||||
Ok(SiteView { site, creator })
|
Ok(SiteView {
|
||||||
|
site,
|
||||||
|
creator,
|
||||||
|
counts,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub struct RemoveComment {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct MarkCommentAsRead {
|
pub struct MarkCommentAsRead {
|
||||||
pub edit_id: i32,
|
pub comment_id: i32,
|
||||||
pub read: bool,
|
pub read: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
@ -50,8 +50,8 @@ pub struct SaveComment {
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct CommentResponse {
|
pub struct CommentResponse {
|
||||||
pub comment_view: CommentView,
|
pub comment_view: CommentView,
|
||||||
pub recipient_ids: Vec<i32>,
|
pub recipient_ids: Vec<i32>, // TODO another way to do this? Maybe a UserMention belongs to Comment
|
||||||
pub form_id: Option<String>,
|
pub form_id: Option<String>, // An optional front end ID, to tell which is coming back
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -98,6 +98,7 @@ pub struct ResolveCommentReport {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct ResolveCommentReportResponse {
|
pub struct ResolveCommentReportResponse {
|
||||||
|
// TODO this should probably return the view
|
||||||
pub report_id: i32,
|
pub report_id: i32,
|
||||||
pub resolved: bool,
|
pub resolved: bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ pub struct BanFromCommunity {
|
||||||
pub community_id: i32,
|
pub community_id: i32,
|
||||||
pub user_id: i32,
|
pub user_id: i32,
|
||||||
pub ban: bool,
|
pub ban: bool,
|
||||||
pub remove_data: Option<bool>,
|
pub remove_data: bool,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub expires: Option<i64>,
|
pub expires: Option<i64>,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
|
|
|
@ -3,7 +3,6 @@ pub mod community;
|
||||||
pub mod post;
|
pub mod post;
|
||||||
pub mod site;
|
pub mod site;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
pub mod websocket;
|
|
||||||
|
|
||||||
use diesel::PgConnection;
|
use diesel::PgConnection;
|
||||||
use lemmy_db::{
|
use lemmy_db::{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use lemmy_db::views::{
|
use lemmy_db::views::{
|
||||||
comment_view::CommentView,
|
comment_view::CommentView,
|
||||||
community::{community_moderator_view::CommunityModeratorView, community_view::CommunityView},
|
community::community_moderator_view::CommunityModeratorView,
|
||||||
post_report_view::PostReportView,
|
post_report_view::PostReportView,
|
||||||
post_view::PostView,
|
post_view::PostView,
|
||||||
};
|
};
|
||||||
|
@ -31,7 +31,6 @@ pub struct GetPost {
|
||||||
pub struct GetPostResponse {
|
pub struct GetPostResponse {
|
||||||
pub post_view: PostView,
|
pub post_view: PostView,
|
||||||
pub comments: Vec<CommentView>,
|
pub comments: Vec<CommentView>,
|
||||||
pub community: CommunityView,
|
|
||||||
pub moderators: Vec<CommunityModeratorView>,
|
pub moderators: Vec<CommunityModeratorView>,
|
||||||
pub online: usize,
|
pub online: usize,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use lemmy_db::{
|
use lemmy_db::{
|
||||||
aggregates::site_aggregates::SiteAggregates,
|
|
||||||
source::{category::*, user::*},
|
source::{category::*, user::*},
|
||||||
views::{
|
views::{
|
||||||
comment_view::CommentView,
|
comment_view::CommentView,
|
||||||
|
@ -101,16 +100,14 @@ pub struct GetSite {
|
||||||
pub auth: Option<String>,
|
pub auth: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO combine siteresponse and getsiteresponse
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct SiteResponse {
|
pub struct SiteResponse {
|
||||||
pub site: SiteView,
|
pub site_view: SiteView,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct GetSiteResponse {
|
pub struct GetSiteResponse {
|
||||||
pub site: Option<SiteView>, // Because the site might not be set up yet
|
pub site_view: Option<SiteView>, // Because the site might not be set up yet
|
||||||
pub counts: SiteAggregates,
|
|
||||||
pub admins: Vec<UserViewSafe>,
|
pub admins: Vec<UserViewSafe>,
|
||||||
pub banned: Vec<UserViewSafe>,
|
pub banned: Vec<UserViewSafe>,
|
||||||
pub online: usize,
|
pub online: usize,
|
||||||
|
|
|
@ -48,8 +48,8 @@ pub struct CaptchaResponse {
|
||||||
pub struct SaveUserSettings {
|
pub struct SaveUserSettings {
|
||||||
pub show_nsfw: bool,
|
pub show_nsfw: bool,
|
||||||
pub theme: String,
|
pub theme: String,
|
||||||
pub default_sort_type: i16,
|
pub default_sort_type: String,
|
||||||
pub default_listing_type: i16,
|
pub default_listing_type: String,
|
||||||
pub lang: String,
|
pub lang: String,
|
||||||
pub avatar: Option<String>,
|
pub avatar: Option<String>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<String>,
|
||||||
|
@ -84,8 +84,8 @@ pub struct GetUserDetails {
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct GetUserDetailsResponse {
|
pub struct GetUserDetailsResponse {
|
||||||
pub user: Option<UserViewSafe>,
|
pub user_view: Option<UserViewSafe>,
|
||||||
pub user_dangerous: Option<UserViewDangerous>,
|
pub user_view_dangerous: Option<UserViewDangerous>,
|
||||||
pub follows: Vec<CommunityFollowerView>,
|
pub follows: Vec<CommunityFollowerView>,
|
||||||
pub moderates: Vec<CommunityModeratorView>,
|
pub moderates: Vec<CommunityModeratorView>,
|
||||||
pub comments: Vec<CommentView>,
|
pub comments: Vec<CommentView>,
|
||||||
|
@ -123,7 +123,7 @@ pub struct AddAdminResponse {
|
||||||
pub struct BanUser {
|
pub struct BanUser {
|
||||||
pub user_id: i32,
|
pub user_id: i32,
|
||||||
pub ban: bool,
|
pub ban: bool,
|
||||||
pub remove_data: Option<bool>,
|
pub remove_data: bool,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub expires: Option<i64>,
|
pub expires: Option<i64>,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
|
@ -131,7 +131,7 @@ pub struct BanUser {
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct BanUserResponse {
|
pub struct BanUserResponse {
|
||||||
pub user: UserViewSafe,
|
pub user_view: UserViewSafe,
|
||||||
pub banned: bool,
|
pub banned: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,12 +224,12 @@ pub struct GetPrivateMessages {
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct PrivateMessagesResponse {
|
pub struct PrivateMessagesResponse {
|
||||||
pub messages: Vec<PrivateMessageView>,
|
pub private_messages: Vec<PrivateMessageView>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct PrivateMessageResponse {
|
pub struct PrivateMessageResponse {
|
||||||
pub message: PrivateMessageView,
|
pub private_message_view: PrivateMessageView,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
-- Site aggregates
|
-- Site aggregates
|
||||||
drop table site_aggregates;
|
drop table site_aggregates;
|
||||||
|
drop trigger site_aggregates_site on site;
|
||||||
drop trigger site_aggregates_user on user_;
|
drop trigger site_aggregates_user on user_;
|
||||||
drop trigger site_aggregates_post on post;
|
drop trigger site_aggregates_post on post;
|
||||||
drop trigger site_aggregates_comment on comment;
|
drop trigger site_aggregates_comment on comment;
|
||||||
drop trigger site_aggregates_community on community;
|
drop trigger site_aggregates_community on community;
|
||||||
drop function
|
drop function
|
||||||
|
site_aggregates_site,
|
||||||
site_aggregates_user,
|
site_aggregates_user,
|
||||||
site_aggregates_post,
|
site_aggregates_post,
|
||||||
site_aggregates_comment,
|
site_aggregates_comment,
|
||||||
|
|
|
@ -1,17 +1,38 @@
|
||||||
-- Add site aggregates
|
-- Add site aggregates
|
||||||
create table site_aggregates (
|
create table site_aggregates (
|
||||||
id serial primary key,
|
id serial primary key,
|
||||||
users bigint not null,
|
site_id int references site on update cascade on delete cascade not null,
|
||||||
posts bigint not null,
|
users bigint not null default 0,
|
||||||
comments bigint not null,
|
posts bigint not null default 0,
|
||||||
communities bigint not null
|
comments bigint not null default 0,
|
||||||
|
communities bigint not null default 0
|
||||||
);
|
);
|
||||||
|
|
||||||
insert into site_aggregates (users, posts, comments, communities)
|
insert into site_aggregates (site_id, users, posts, comments, communities)
|
||||||
select ( select coalesce(count(*), 0) from user_) as users,
|
select id as site_id,
|
||||||
|
( select coalesce(count(*), 0) from user_) as users,
|
||||||
( select coalesce(count(*), 0) from post) as posts,
|
( select coalesce(count(*), 0) from post) as posts,
|
||||||
( select coalesce(count(*), 0) from comment) as comments,
|
( select coalesce(count(*), 0) from comment) as comments,
|
||||||
( select coalesce(count(*), 0) from community) as communities;
|
( select coalesce(count(*), 0) from community) as communities
|
||||||
|
from site;
|
||||||
|
|
||||||
|
-- initial site add
|
||||||
|
create function site_aggregates_site()
|
||||||
|
returns trigger language plpgsql
|
||||||
|
as $$
|
||||||
|
begin
|
||||||
|
IF (TG_OP = 'INSERT') THEN
|
||||||
|
insert into site_aggregates (site_id) values (NEW.id);
|
||||||
|
ELSIF (TG_OP = 'DELETE') THEN
|
||||||
|
delete from site_aggregates where site_id = OLD.id;
|
||||||
|
END IF;
|
||||||
|
return null;
|
||||||
|
end $$;
|
||||||
|
|
||||||
|
create trigger site_aggregates_site
|
||||||
|
after insert or delete on site
|
||||||
|
for each row
|
||||||
|
execute procedure site_aggregates_site();
|
||||||
|
|
||||||
-- Add site aggregate triggers
|
-- Add site aggregate triggers
|
||||||
-- user
|
-- user
|
||||||
|
|
Loading…
Reference in a new issue