A first pass.

This commit is contained in:
Dessalines 2021-03-10 23:43:11 -05:00
parent ddf4a667b1
commit 9cb4dad4b4
73 changed files with 1010 additions and 1394 deletions

View file

@ -2,9 +2,9 @@ use crate::{
check_community_ban, check_community_ban,
check_downvotes_enabled, check_downvotes_enabled,
collect_moderated_communities, collect_moderated_communities,
get_post,
get_local_user_view_from_jwt, get_local_user_view_from_jwt,
get_local_user_view_from_jwt_opt, get_local_user_view_from_jwt_opt,
get_post,
is_mod_or_admin, is_mod_or_admin,
Perform, Perform,
}; };
@ -115,7 +115,9 @@ impl Perform for CreateComment {
Err(_e) => return Err(ApiError::err("couldnt_create_comment").into()), Err(_e) => return Err(ApiError::err("couldnt_create_comment").into()),
}; };
updated_comment.send_create(&local_user_view.person, context).await?; updated_comment
.send_create(&local_user_view.person, 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 post_id = post.id;
@ -143,7 +145,9 @@ impl Perform for CreateComment {
return Err(ApiError::err("couldnt_like_comment").into()); return Err(ApiError::err("couldnt_like_comment").into());
} }
updated_comment.send_like(&local_user_view.person, context).await?; updated_comment
.send_like(&local_user_view.person, context)
.await?;
let person_id = local_user_view.person.id; let person_id = local_user_view.person.id;
let mut comment_view = blocking(context.pool(), move |conn| { let mut comment_view = blocking(context.pool(), move |conn| {
@ -201,7 +205,12 @@ impl Perform for EditComment {
}) })
.await??; .await??;
check_community_ban(local_user_view.person.id, orig_comment.community.id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_comment.community.id,
context.pool(),
)
.await?;
// Verify that only the creator can edit // Verify that only the creator can edit
if local_user_view.person.id != orig_comment.creator.id { if local_user_view.person.id != orig_comment.creator.id {
@ -221,7 +230,9 @@ impl Perform for EditComment {
}; };
// Send the apub update // Send the apub update
updated_comment.send_update(&local_user_view.person, context).await?; updated_comment
.send_update(&local_user_view.person, context)
.await?;
// Do the mentions / recipients // Do the mentions / recipients
let updated_comment_content = updated_comment.content.to_owned(); let updated_comment_content = updated_comment.content.to_owned();
@ -277,7 +288,12 @@ impl Perform for DeleteComment {
}) })
.await??; .await??;
check_community_ban(local_user_view.person.id, orig_comment.community.id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_comment.community.id,
context.pool(),
)
.await?;
// Verify that only the creator can delete // Verify that only the creator can delete
if local_user_view.person.id != orig_comment.creator.id { if local_user_view.person.id != orig_comment.creator.id {
@ -297,9 +313,13 @@ impl Perform for DeleteComment {
// Send the apub message // Send the apub message
if deleted { if deleted {
updated_comment.send_delete(&local_user_view.person, context).await?; updated_comment
.send_delete(&local_user_view.person, context)
.await?;
} else { } else {
updated_comment.send_undo_delete(&local_user_view.person, context).await?; updated_comment
.send_undo_delete(&local_user_view.person, context)
.await?;
} }
// Refetch it // Refetch it
@ -357,10 +377,20 @@ impl Perform for RemoveComment {
}) })
.await??; .await??;
check_community_ban(local_user_view.person.id, orig_comment.community.id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_comment.community.id,
context.pool(),
)
.await?;
// Verify that only a mod or admin can remove // Verify that only a mod or admin can remove
is_mod_or_admin(context.pool(), local_user_view.person.id, orig_comment.community.id).await?; is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_comment.community.id,
)
.await?;
// Do the remove // Do the remove
let removed = data.removed; let removed = data.removed;
@ -387,9 +417,13 @@ impl Perform for RemoveComment {
// Send the apub message // Send the apub message
if removed { if removed {
updated_comment.send_remove(&local_user_view.person, context).await?; updated_comment
.send_remove(&local_user_view.person, context)
.await?;
} else { } else {
updated_comment.send_undo_remove(&local_user_view.person, context).await?; updated_comment
.send_undo_remove(&local_user_view.person, context)
.await?;
} }
// Refetch it // Refetch it
@ -448,7 +482,12 @@ impl Perform for MarkCommentAsRead {
}) })
.await??; .await??;
check_community_ban(local_user_view.person.id, orig_comment.community.id, context.pool()).await?; check_community_ban(
local_user_view.person.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
if local_user_view.person.id != orig_comment.get_recipient_id() { if local_user_view.person.id != orig_comment.get_recipient_id() {
@ -551,7 +590,12 @@ impl Perform for CreateCommentLike {
}) })
.await??; .await??;
check_community_ban(local_user_view.person.id, orig_comment.community.id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_comment.community.id,
context.pool(),
)
.await?;
// Add parent user to recipients // Add parent user to recipients
recipient_ids.push(orig_comment.get_recipient_id()); recipient_ids.push(orig_comment.get_recipient_id());
@ -583,10 +627,14 @@ impl Perform for CreateCommentLike {
if like_form.score == 1 { if like_form.score == 1 {
comment.send_like(&local_user_view.person, context).await?; comment.send_like(&local_user_view.person, context).await?;
} else if like_form.score == -1 { } else if like_form.score == -1 {
comment.send_dislike(&local_user_view.person, context).await?; comment
.send_dislike(&local_user_view.person, context)
.await?;
} }
} else { } else {
comment.send_undo_like(&local_user_view.person, context).await?; comment
.send_undo_like(&local_user_view.person, context)
.await?;
} }
// Have to refetch the comment to get the current state // Have to refetch the comment to get the current state

View file

@ -517,9 +517,15 @@ impl Perform for FollowCommunity {
} else if data.follow { } else if data.follow {
// Dont actually add to the community followers here, because you need // Dont actually add to the community followers here, because you need
// to wait for the accept // to wait for the accept
local_user_view.person.send_follow(&community.actor_id(), context).await?; local_user_view
.person
.send_follow(&community.actor_id(), context)
.await?;
} else { } else {
local_user_view.person.send_unfollow(&community.actor_id(), context).await?; local_user_view
.person
.send_unfollow(&community.actor_id(), context)
.await?;
let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form); let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
if blocking(context.pool(), unfollow).await?.is_err() { if blocking(context.pool(), unfollow).await?.is_err() {
return Err(ApiError::err("community_follower_already_exists").into()); return Err(ApiError::err("community_follower_already_exists").into());
@ -788,7 +794,10 @@ impl Perform for TransferCommunity {
// Make sure user is the creator, or an admin // Make sure user is the creator, or an admin
if local_user_view.person.id != read_community.creator_id if local_user_view.person.id != read_community.creator_id
&& !admins.iter().map(|a| a.person.id).any(|x| x == local_user_view.person.id) && !admins
.iter()
.map(|a| a.person.id)
.any(|x| x == local_user_view.person.id)
{ {
return Err(ApiError::err("not_an_admin").into()); return Err(ApiError::err("not_an_admin").into());
} }

View file

@ -3,17 +3,15 @@ use lemmy_api_structs::{
blocking, blocking,
comment::*, comment::*,
community::*, community::*,
person::*,
post::*, post::*,
site::*, site::*,
person::*,
websocket::*, websocket::*,
}; };
use lemmy_db_queries::{ use lemmy_db_queries::{
source::{ source::{
community::{CommunityModerator_, Community_}, community::{CommunityModerator_, Community_},
site::Site_, site::Site_,
local_user::LocalUserSettings_,
local_user::LocalUser_,
}, },
Crud, Crud,
DbPool, DbPool,
@ -22,15 +20,12 @@ use lemmy_db_schema::source::{
community::{Community, CommunityModerator}, community::{Community, CommunityModerator},
post::Post, post::Post,
site::Site, site::Site,
person::{Person, PersonSafe},
local_user::LocalUserSettings,
local_user::LocalUser,
}; };
use lemmy_db_views::local_user_view::{LocalUserSettingsView, LocalUserView};
use lemmy_db_views_actor::{ use lemmy_db_views_actor::{
community_person_ban_view::CommunityPersonBanView, community_person_ban_view::CommunityPersonBanView,
community_view::CommunityView, community_view::CommunityView,
}; };
use lemmy_db_views::local_user_view::{LocalUserView, LocalUserSettingsView};
use lemmy_utils::{ use lemmy_utils::{
claims::Claims, claims::Claims,
settings::structs::Settings, settings::structs::Settings,
@ -45,10 +40,10 @@ use url::Url;
pub mod comment; pub mod comment;
pub mod community; pub mod community;
pub mod local_user;
pub mod post; pub mod post;
pub mod routes; pub mod routes;
pub mod site; pub mod site;
pub mod user;
pub mod websocket; pub mod websocket;
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
@ -100,13 +95,19 @@ pub(crate) async fn get_post(post_id: i32, pool: &DbPool) -> Result<Post, LemmyE
} }
} }
pub(crate) async fn get_local_user_view_from_jwt(jwt: &str, pool: &DbPool) -> Result<LocalUserView, LemmyError> { pub(crate) async fn get_local_user_view_from_jwt(
jwt: &str,
pool: &DbPool,
) -> Result<LocalUserView, LemmyError> {
let claims = match Claims::decode(&jwt) { let claims = match Claims::decode(&jwt) {
Ok(claims) => claims.claims, Ok(claims) => claims.claims,
Err(_e) => return Err(ApiError::err("not_logged_in").into()), Err(_e) => return Err(ApiError::err("not_logged_in").into()),
}; };
let person_id = claims.id; let person_id = claims.id;
let local_user_view = blocking(pool, move |conn| LocalUserView::read(conn, person_id)).await??; let local_user_view = blocking(pool, move |conn| {
LocalUserView::read_person(conn, person_id)
})
.await??;
// Check for a site ban // Check for a site ban
if local_user_view.person.banned { if local_user_view.person.banned {
return Err(ApiError::err("site_ban").into()); return Err(ApiError::err("site_ban").into());
@ -124,13 +125,19 @@ pub(crate) async fn get_local_user_view_from_jwt_opt(
} }
} }
pub(crate) async fn get_local_user_settings_view_from_jwt(jwt: &str, pool: &DbPool) -> Result<LocalUserSettingsView, LemmyError> { pub(crate) async fn get_local_user_settings_view_from_jwt(
jwt: &str,
pool: &DbPool,
) -> Result<LocalUserSettingsView, LemmyError> {
let claims = match Claims::decode(&jwt) { let claims = match Claims::decode(&jwt) {
Ok(claims) => claims.claims, Ok(claims) => claims.claims,
Err(_e) => return Err(ApiError::err("not_logged_in").into()), Err(_e) => return Err(ApiError::err("not_logged_in").into()),
}; };
let person_id = claims.id; let person_id = claims.id;
let local_user_view = blocking(pool, move |conn| LocalUserSettingsView::read(conn, person_id)).await??; let local_user_view = blocking(pool, move |conn| {
LocalUserSettingsView::read(conn, person_id)
})
.await??;
// Check for a site ban // Check for a site ban
if local_user_view.person.banned { if local_user_view.person.banned {
return Err(ApiError::err("site_ban").into()); return Err(ApiError::err("site_ban").into());
@ -143,7 +150,9 @@ pub(crate) async fn get_local_user_settings_view_from_jwt_opt(
pool: &DbPool, pool: &DbPool,
) -> Result<Option<LocalUserSettingsView>, LemmyError> { ) -> Result<Option<LocalUserSettingsView>, LemmyError> {
match jwt { match jwt {
Some(jwt) => Ok(Some(get_local_user_settings_view_from_jwt(jwt, pool).await?)), Some(jwt) => Ok(Some(
get_local_user_settings_view_from_jwt(jwt, pool).await?,
)),
None => Ok(None), None => Ok(None),
} }
} }
@ -153,7 +162,8 @@ pub(crate) async fn check_community_ban(
community_id: i32, community_id: i32,
pool: &DbPool, pool: &DbPool,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let is_banned = move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok(); let is_banned =
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
if blocking(pool, is_banned).await? { if blocking(pool, is_banned).await? {
Err(ApiError::err("community_ban").into()) Err(ApiError::err("community_ban").into())
} else { } else {

View file

@ -12,7 +12,7 @@ use anyhow::Context;
use bcrypt::verify; use bcrypt::verify;
use captcha::{gen, Difficulty}; use captcha::{gen, Difficulty};
use chrono::Duration; use chrono::Duration;
use lemmy_api_structs::{blocking, send_email_to_user, person::*}; use lemmy_api_structs::{blocking, person::*, send_email_to_user};
use lemmy_apub::{ use lemmy_apub::{
generate_apub_endpoint, generate_apub_endpoint,
generate_followers_url, generate_followers_url,
@ -27,12 +27,13 @@ use lemmy_db_queries::{
source::{ source::{
comment::Comment_, comment::Comment_,
community::Community_, community::Community_,
local_user::LocalUser_,
password_reset_request::PasswordResetRequest_, password_reset_request::PasswordResetRequest_,
person::Person_,
person_mention::PersonMention_,
post::Post_, post::Post_,
private_message::PrivateMessage_, private_message::PrivateMessage_,
site::Site_, site::Site_,
person::Person_,
person_mention::PersonMention_,
}, },
Crud, Crud,
Followable, Followable,
@ -40,14 +41,28 @@ use lemmy_db_queries::{
ListingType, ListingType,
SortType, SortType,
}; };
use lemmy_db_schema::{naive_now, source::{comment::Comment, community::*, local_user::LocalUserForm, moderator::*, password_reset_request::*, person::*, person_mention::*, post::Post, private_message::*, site::*}}; use lemmy_db_schema::{
naive_now,
source::{
comment::Comment,
community::*,
local_user::{LocalUser, LocalUserForm},
moderator::*,
password_reset_request::*,
person::*,
person_mention::*,
post::Post,
private_message::*,
site::*,
},
};
use lemmy_db_views::{ use lemmy_db_views::{
comment_report_view::CommentReportView, comment_report_view::CommentReportView,
comment_view::CommentQueryBuilder, comment_view::CommentQueryBuilder,
local_user_view::LocalUserView,
post_report_view::PostReportView, post_report_view::PostReportView,
post_view::PostQueryBuilder, post_view::PostQueryBuilder,
private_message_view::{PrivateMessageQueryBuilder, PrivateMessageView}, private_message_view::{PrivateMessageQueryBuilder, PrivateMessageView},
local_user_view::LocalUserView,
}; };
use lemmy_db_views_actor::{ use lemmy_db_views_actor::{
community_follower_view::CommunityFollowerView, community_follower_view::CommunityFollowerView,
@ -103,7 +118,11 @@ impl Perform for Login {
}; };
// Verify the password // Verify the password
let valid: bool = verify(&data.password, &local_user_view.local_user.password_encrypted).unwrap_or(false); let valid: bool = verify(
&data.password,
&local_user_view.local_user.password_encrypted,
)
.unwrap_or(false);
if !valid { if !valid {
return Err(ApiError::err("password_incorrect").into()); return Err(ApiError::err("password_incorrect").into());
} }
@ -186,18 +205,11 @@ impl Perform for Register {
updated: None, updated: None,
banned: None, banned: None,
deleted: None, deleted: None,
show_nsfw: data.show_nsfw,
theme: "browser".into(),
default_sort_type: SortType::Active as i16,
default_listing_type: ListingType::Subscribed as i16,
lang: "browser".into(),
show_avatars: true,
send_notifications_to_email: false,
actor_id: Some(actor_id.clone()), actor_id: Some(actor_id.clone()),
bio: None, bio: None,
local: true, local: Some(true),
private_key: Some(actor_keypair.private_key), private_key: Some(Some(actor_keypair.private_key)),
public_key: Some(actor_keypair.public_key), public_key: Some(Some(actor_keypair.public_key)),
last_refreshed_at: None, last_refreshed_at: None,
inbox_url: Some(generate_inbox_url(&actor_id)?), inbox_url: Some(generate_inbox_url(&actor_id)?),
shared_inbox_url: Some(Some(generate_shared_inbox_url(&actor_id)?)), shared_inbox_url: Some(Some(generate_shared_inbox_url(&actor_id)?)),
@ -209,8 +221,8 @@ impl Perform for Register {
}) })
.await? .await?
{ {
Ok(user) => user, Ok(u) => u,
Err(e) => { Err(_) => {
return Err(ApiError::err("user_already_exists").into()); return Err(ApiError::err("user_already_exists").into());
} }
}; };
@ -221,11 +233,17 @@ impl Perform for Register {
email: Some(data.email.to_owned()), email: Some(data.email.to_owned()),
matrix_user_id: None, matrix_user_id: None,
password_encrypted: data.password.to_owned(), password_encrypted: data.password.to_owned(),
admin: no_admins, admin: Some(no_admins),
show_nsfw: Some(data.show_nsfw),
theme: Some("browser".into()),
default_sort_type: Some(SortType::Active as i16),
default_listing_type: Some(ListingType::Subscribed as i16),
lang: Some("browser".into()),
show_avatars: Some(true),
send_notifications_to_email: Some(false),
}; };
let inserted_local_user = match blocking(context.pool(), move |conn| { match blocking(context.pool(), move |conn| {
LocalUser::register(conn, &local_user_form) LocalUser::register(conn, &local_user_form)
}) })
.await? .await?
@ -241,13 +259,15 @@ impl Perform for Register {
}; };
// If the local user creation errored, then delete that person // If the local user creation errored, then delete that person
blocking(context.pool(), move |conn| Person::delete(&conn, inserted_person.id)).await??; blocking(context.pool(), move |conn| {
Person::delete(&conn, inserted_person.id)
})
.await??;
return Err(ApiError::err(err_type).into()); return Err(ApiError::err(err_type).into());
} }
}; };
let main_community_keypair = generate_actor_keypair()?; let main_community_keypair = generate_actor_keypair()?;
// Create the main community if it doesn't exist // Create the main community if it doesn't exist
@ -374,7 +394,7 @@ impl Perform for SaveUserSettings {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<LoginResponse, LemmyError> { ) -> Result<LoginResponse, LemmyError> {
let data: &SaveUserSettings = &self; let data: &SaveUserSettings = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let avatar = diesel_option_overwrite_to_url(&data.avatar)?; let avatar = diesel_option_overwrite_to_url(&data.avatar)?;
let banner = diesel_option_overwrite_to_url(&data.banner)?; let banner = diesel_option_overwrite_to_url(&data.banner)?;
@ -395,7 +415,8 @@ impl Perform for SaveUserSettings {
} }
} }
let user_id = user.id; let local_user_id = local_user_view.local_user.id;
let person_id = local_user_view.person.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 {
@ -410,13 +431,15 @@ 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 = verify(old_password, &user.password_encrypted).unwrap_or(false); let valid: bool =
verify(old_password, &local_user_view.local_user.password_encrypted)
.unwrap_or(false);
if !valid { if !valid {
return Err(ApiError::err("password_incorrect").into()); return Err(ApiError::err("password_incorrect").into());
} }
let new_password = new_password.to_owned(); let new_password = new_password.to_owned();
let user = blocking(context.pool(), move |conn| { let user = blocking(context.pool(), move |conn| {
User_::update_password(conn, user_id, &new_password) LocalUser::update_password(conn, local_user_id, &new_password)
}) })
.await??; .await??;
user.password_encrypted user.password_encrypted
@ -427,25 +450,48 @@ impl Perform for SaveUserSettings {
None => return Err(ApiError::err("passwords_dont_match").into()), None => return Err(ApiError::err("passwords_dont_match").into()),
} }
} }
None => user.password_encrypted, None => local_user_view.local_user.password_encrypted,
}; };
let default_listing_type = data.default_listing_type; let default_listing_type = data.default_listing_type;
let default_sort_type = data.default_sort_type; let default_sort_type = data.default_sort_type;
let user_form = UserForm { let person_form = PersonForm {
name: user.name, name: local_user_view.person.name,
email,
matrix_user_id,
avatar, avatar,
banner, banner,
inbox_url: None, inbox_url: None,
password_encrypted,
preferred_username, preferred_username,
published: Some(user.published), published: None,
updated: Some(naive_now()), updated: Some(naive_now()),
admin: user.admin, banned: None,
banned: Some(user.banned), deleted: None,
actor_id: None,
bio,
local: None,
private_key: None,
public_key: None,
last_refreshed_at: None,
shared_inbox_url: None,
};
let person_res = blocking(context.pool(), move |conn| {
Person::update(conn, person_id, &person_form)
})
.await?;
let updated_person: Person = match person_res {
Ok(p) => p,
Err(_) => {
return Err(ApiError::err("user_already_exists").into());
}
};
let local_user_form = LocalUserForm {
person_id,
email,
matrix_user_id,
password_encrypted,
admin: None,
show_nsfw: data.show_nsfw, show_nsfw: data.show_nsfw,
theme: data.theme.to_owned(), theme: data.theme.to_owned(),
default_sort_type, default_sort_type,
@ -453,24 +499,17 @@ impl Perform for SaveUserSettings {
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(user.actor_id),
bio,
local: user.local,
private_key: user.private_key,
public_key: user.public_key,
last_refreshed_at: None,
shared_inbox_url: None,
}; };
let res = blocking(context.pool(), move |conn| { let local_user_res = blocking(context.pool(), move |conn| {
User_::update(conn, user_id, &user_form) LocalUser::update(conn, local_user_id, &local_user_form)
}) })
.await?; .await?;
let updated_user: User_ = match res { match local_user_res {
Ok(user) => user, Ok(user) => user,
Err(e) => { Err(e) => {
let err_type = if e.to_string() let err_type = if e.to_string()
== "duplicate key value violates unique constraint \"user__email_key\"" == "duplicate key value violates unique constraint \"local_user_email_key\""
{ {
"email_already_exists" "email_already_exists"
} else { } else {
@ -483,25 +522,25 @@ impl Perform for SaveUserSettings {
// Return the jwt // Return the jwt
Ok(LoginResponse { Ok(LoginResponse {
jwt: Claims::jwt(updated_user.id, Settings::get().hostname())?, jwt: Claims::jwt(updated_person.id, Settings::get().hostname())?,
}) })
} }
} }
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl Perform for GetUserDetails { impl Perform for GetPersonDetails {
type Response = GetUserDetailsResponse; type Response = GetPersonDetailsResponse;
async fn perform( async fn perform(
&self, &self,
context: &Data<LemmyContext>, context: &Data<LemmyContext>,
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<GetUserDetailsResponse, LemmyError> { ) -> Result<GetPersonDetailsResponse, LemmyError> {
let data: &GetUserDetails = &self; let data: &GetPersonDetails = &self;
let user = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
let show_nsfw = match &user { let show_nsfw = match &local_user_view {
Some(user) => user.show_nsfw, Some(uv) => uv.local_user.show_nsfw,
None => false, None => false,
}; };
@ -511,26 +550,26 @@ impl Perform for GetUserDetails {
.username .username
.to_owned() .to_owned()
.unwrap_or_else(|| "admin".to_string()); .unwrap_or_else(|| "admin".to_string());
let user_details_id = match data.user_id { let person_details_id = match data.person_id {
Some(id) => id, Some(id) => id,
None => { None => {
let user = blocking(context.pool(), move |conn| { let person = blocking(context.pool(), move |conn| {
User_::read_from_name(conn, &username) Person::find_by_name(conn, &username)
}) })
.await?; .await?;
match user { match person {
Ok(user) => user.id, Ok(p) => p.id,
Err(_e) => return Err(ApiError::err("couldnt_find_that_username_or_email").into()), Err(_e) => return Err(ApiError::err("couldnt_find_that_username_or_email").into()),
} }
} }
}; };
let user_id = user.map(|u| u.id); let person_id = local_user_view.map(|uv| uv.person.id);
// You don't need to return settings for the user, since this comes back with GetSite // You don't need to return settings for the user, since this comes back with GetSite
// `my_user` // `my_user`
let user_view = blocking(context.pool(), move |conn| { let person_view = blocking(context.pool(), move |conn| {
UserViewSafe::read(conn, user_details_id) PersonViewSafe::read(conn, person_details_id)
}) })
.await??; .await??;
@ -545,12 +584,12 @@ impl Perform for GetUserDetails {
.show_nsfw(show_nsfw) .show_nsfw(show_nsfw)
.saved_only(saved_only) .saved_only(saved_only)
.community_id(community_id) .community_id(community_id)
.my_user_id(user_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit); .limit(limit);
let mut comments_query = CommentQueryBuilder::create(conn) let mut comments_query = CommentQueryBuilder::create(conn)
.my_person_id(user_id) .my_person_id(person_id)
.sort(&sort) .sort(&sort)
.saved_only(saved_only) .saved_only(saved_only)
.page(page) .page(page)
@ -559,8 +598,8 @@ impl Perform for GetUserDetails {
// If its saved only, you don't care what creator it was // 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 // Or, if its not saved, then you only want it for that specific creator
if !saved_only { if !saved_only {
posts_query = posts_query.creator_id(user_details_id); posts_query = posts_query.creator_id(person_details_id);
comments_query = comments_query.creator_id(user_details_id); comments_query = comments_query.creator_id(person_details_id);
} }
let posts = posts_query.list()?; let posts = posts_query.list()?;
@ -571,22 +610,22 @@ impl Perform for GetUserDetails {
.await??; .await??;
let mut follows = vec![]; let mut follows = vec![];
if let Some(uid) = user_id { if let Some(pid) = person_id {
if uid == user_details_id { if pid == person_details_id {
follows = blocking(context.pool(), move |conn| { follows = blocking(context.pool(), move |conn| {
CommunityFollowerView::for_user(conn, user_details_id) CommunityFollowerView::for_person(conn, person_details_id)
}) })
.await??; .await??;
} }
}; };
let moderates = blocking(context.pool(), move |conn| { let moderates = blocking(context.pool(), move |conn| {
CommunityModeratorView::for_person(conn, user_details_id) CommunityModeratorView::for_person(conn, person_details_id)
}) })
.await??; .await??;
// Return the jwt // Return the jwt
Ok(GetUserDetailsResponse { Ok(GetPersonDetailsResponse {
user_view, person_view,
follows, follows,
moderates, moderates,
comments, comments,
@ -605,22 +644,28 @@ impl Perform for AddAdmin {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<AddAdminResponse, LemmyError> { ) -> Result<AddAdminResponse, LemmyError> {
let data: &AddAdmin = &self; let data: &AddAdmin = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Make sure user is an admin // Make sure user is an admin
is_admin(context.pool(), user.id).await?; is_admin(&local_user_view)?;
let added = data.added; let added = data.added;
let added_user_id = data.user_id; let added_local_user_id = data.local_user_id;
let add_admin = move |conn: &'_ _| User_::add_admin(conn, added_user_id, added); let added_admin = match blocking(context.pool(), move |conn| {
if blocking(context.pool(), add_admin).await?.is_err() { LocalUser::add_admin(conn, added_local_user_id, added)
return Err(ApiError::err("couldnt_update_user").into()); })
} .await?
{
Ok(a) => a,
Err(_) => {
return Err(ApiError::err("couldnt_update_user").into());
}
};
// Mod tables // Mod tables
let form = ModAddForm { let form = ModAddForm {
mod_person_id: user.id, mod_person_id: local_user_view.person.id,
other_person_id: data.user_id, other_person_id: added_admin.person_id,
removed: Some(!data.added), removed: Some(!data.added),
}; };
@ -631,13 +676,13 @@ impl Perform for AddAdmin {
}) })
.await??; .await??;
let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??; let mut admins = blocking(context.pool(), move |conn| PersonViewSafe::admins(conn)).await??;
let creator_index = admins let creator_index = admins
.iter() .iter()
.position(|r| r.user.id == site_creator_id) .position(|r| r.person.id == site_creator_id)
.context(location_info!())?; .context(location_info!())?;
let creator_user = admins.remove(creator_index); let creator_person = admins.remove(creator_index);
admins.insert(0, creator_user); admins.insert(0, creator_person);
let res = AddAdminResponse { admins }; let res = AddAdminResponse { admins };
@ -652,24 +697,24 @@ impl Perform for AddAdmin {
} }
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl Perform for BanUser { impl Perform for BanPerson {
type Response = BanUserResponse; type Response = BanPersonResponse;
async fn perform( async fn perform(
&self, &self,
context: &Data<LemmyContext>, context: &Data<LemmyContext>,
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<BanUserResponse, LemmyError> { ) -> Result<BanPersonResponse, LemmyError> {
let data: &BanUser = &self; let data: &BanPerson = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Make sure user is an admin // Make sure user is an admin
is_admin(context.pool(), user.id).await?; is_admin(&local_user_view)?;
let ban = data.ban; let ban = data.ban;
let banned_user_id = data.user_id; let banned_person_id = data.person_id;
let ban_user = move |conn: &'_ _| User_::ban_user(conn, banned_user_id, ban); let ban_person = move |conn: &'_ _| Person::ban_person(conn, banned_person_id, ban);
if blocking(context.pool(), ban_user).await?.is_err() { if blocking(context.pool(), ban_person).await?.is_err() {
return Err(ApiError::err("couldnt_update_user").into()); return Err(ApiError::err("couldnt_update_user").into());
} }
@ -677,19 +722,19 @@ impl Perform for BanUser {
if 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, true) Post::update_removed_for_creator(conn, banned_person_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, true) Community::update_removed_for_creator(conn, banned_person_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, true) Comment::update_removed_for_creator(conn, banned_person_id, true)
}) })
.await??; .await??;
} }
@ -701,8 +746,8 @@ impl Perform for BanUser {
}; };
let form = ModBanForm { let form = ModBanForm {
mod_person_id: user.id, mod_person_id: local_user_view.person.id,
other_person_id: data.user_id, other_person_id: data.person_id,
reason: data.reason.to_owned(), reason: data.reason.to_owned(),
banned: Some(data.ban), banned: Some(data.ban),
expires, expires,
@ -710,14 +755,14 @@ impl Perform for BanUser {
blocking(context.pool(), move |conn| ModBan::create(conn, &form)).await??; blocking(context.pool(), move |conn| ModBan::create(conn, &form)).await??;
let user_id = data.user_id; let person_id = data.person_id;
let user_view = blocking(context.pool(), move |conn| { let person_view = blocking(context.pool(), move |conn| {
UserViewSafe::read(conn, user_id) PersonViewSafe::read(conn, person_id)
}) })
.await??; .await??;
let res = BanUserResponse { let res = BanPersonResponse {
user_view, person_view,
banned: data.ban, banned: data.ban,
}; };
@ -741,20 +786,20 @@ impl Perform for GetReplies {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<GetRepliesResponse, LemmyError> { ) -> Result<GetRepliesResponse, LemmyError> {
let data: &GetReplies = &self; let data: &GetReplies = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let sort = SortType::from_str(&data.sort)?; let sort = SortType::from_str(&data.sort)?;
let page = data.page; let page = data.page;
let limit = data.limit; let limit = data.limit;
let unread_only = data.unread_only; let unread_only = data.unread_only;
let user_id = user.id; let person_id = local_user_view.person.id;
let replies = blocking(context.pool(), move |conn| { let replies = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(conn) CommentQueryBuilder::create(conn)
.sort(&sort) .sort(&sort)
.unread_only(unread_only) .unread_only(unread_only)
.recipient_id(user_id) .recipient_id(person_id)
.my_person_id(user_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.list() .list()
@ -766,27 +811,27 @@ impl Perform for GetReplies {
} }
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl Perform for GetUserMentions { impl Perform for GetPersonMentions {
type Response = GetUserMentionsResponse; type Response = GetPersonMentionsResponse;
async fn perform( async fn perform(
&self, &self,
context: &Data<LemmyContext>, context: &Data<LemmyContext>,
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<GetUserMentionsResponse, LemmyError> { ) -> Result<GetPersonMentionsResponse, LemmyError> {
let data: &GetUserMentions = &self; let data: &GetPersonMentions = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let sort = SortType::from_str(&data.sort)?; let sort = SortType::from_str(&data.sort)?;
let page = data.page; let page = data.page;
let limit = data.limit; let limit = data.limit;
let unread_only = data.unread_only; let unread_only = data.unread_only;
let user_id = user.id; let person_id = local_user_view.person.id;
let mentions = blocking(context.pool(), move |conn| { let mentions = blocking(context.pool(), move |conn| {
UserMentionQueryBuilder::create(conn) PersonMentionQueryBuilder::create(conn)
.recipient_id(user_id) .recipient_id(person_id)
.my_user_id(user_id) .my_person_id(person_id)
.sort(&sort) .sort(&sort)
.unread_only(unread_only) .unread_only(unread_only)
.page(page) .page(page)
@ -795,47 +840,50 @@ impl Perform for GetUserMentions {
}) })
.await??; .await??;
Ok(GetUserMentionsResponse { mentions }) Ok(GetPersonMentionsResponse { mentions })
} }
} }
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl Perform for MarkUserMentionAsRead { impl Perform for MarkPersonMentionAsRead {
type Response = UserMentionResponse; type Response = PersonMentionResponse;
async fn perform( async fn perform(
&self, &self,
context: &Data<LemmyContext>, context: &Data<LemmyContext>,
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<UserMentionResponse, LemmyError> { ) -> Result<PersonMentionResponse, LemmyError> {
let data: &MarkUserMentionAsRead = &self; let data: &MarkPersonMentionAsRead = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let user_mention_id = data.user_mention_id; let person_mention_id = data.person_mention_id;
let read_user_mention = blocking(context.pool(), move |conn| { let read_person_mention = blocking(context.pool(), move |conn| {
UserMention::read(conn, user_mention_id) PersonMention::read(conn, person_mention_id)
}) })
.await??; .await??;
if user.id != read_user_mention.recipient_id { if local_user_view.person.id != read_person_mention.recipient_id {
return Err(ApiError::err("couldnt_update_comment").into()); return Err(ApiError::err("couldnt_update_comment").into());
} }
let user_mention_id = read_user_mention.id; let person_mention_id = read_person_mention.id;
let read = data.read; let read = data.read;
let update_mention = move |conn: &'_ _| UserMention::update_read(conn, user_mention_id, read); let update_mention =
move |conn: &'_ _| PersonMention::update_read(conn, person_mention_id, read);
if blocking(context.pool(), update_mention).await?.is_err() { if blocking(context.pool(), update_mention).await?.is_err() {
return Err(ApiError::err("couldnt_update_comment").into()); return Err(ApiError::err("couldnt_update_comment").into());
}; };
let user_mention_id = read_user_mention.id; let person_mention_id = read_person_mention.id;
let user_id = user.id; let person_id = local_user_view.person.id;
let user_mention_view = blocking(context.pool(), move |conn| { let person_mention_view = blocking(context.pool(), move |conn| {
UserMentionView::read(conn, user_mention_id, Some(user_id)) PersonMentionView::read(conn, person_mention_id, Some(person_id))
}) })
.await??; .await??;
Ok(UserMentionResponse { user_mention_view }) Ok(PersonMentionResponse {
person_mention_view,
})
} }
} }
@ -849,13 +897,13 @@ impl Perform for MarkAllAsRead {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<GetRepliesResponse, LemmyError> { ) -> Result<GetRepliesResponse, LemmyError> {
let data: &MarkAllAsRead = &self; let data: &MarkAllAsRead = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let user_id = user.id; let person_id = local_user_view.person.id;
let replies = blocking(context.pool(), move |conn| { let replies = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(conn) CommentQueryBuilder::create(conn)
.my_person_id(user_id) .my_person_id(person_id)
.recipient_id(user_id) .recipient_id(person_id)
.unread_only(true) .unread_only(true)
.page(1) .page(1)
.limit(999) .limit(999)
@ -875,8 +923,9 @@ impl Perform for MarkAllAsRead {
} }
// Mark all user mentions as read // Mark all user mentions as read
let update_user_mentions = move |conn: &'_ _| UserMention::mark_all_as_read(conn, user_id); let update_person_mentions =
if blocking(context.pool(), update_user_mentions) move |conn: &'_ _| PersonMention::mark_all_as_read(conn, person_id);
if blocking(context.pool(), update_person_mentions)
.await? .await?
.is_err() .is_err()
{ {
@ -884,7 +933,7 @@ impl Perform for MarkAllAsRead {
} }
// Mark all private_messages as read // Mark all private_messages as read
let update_pm = move |conn: &'_ _| PrivateMessage::mark_all_as_read(conn, user_id); let update_pm = move |conn: &'_ _| PrivateMessage::mark_all_as_read(conn, person_id);
if blocking(context.pool(), update_pm).await?.is_err() { if blocking(context.pool(), update_pm).await?.is_err() {
return Err(ApiError::err("couldnt_update_private_message").into()); return Err(ApiError::err("couldnt_update_private_message").into());
} }
@ -903,29 +952,33 @@ impl Perform for DeleteAccount {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<LoginResponse, LemmyError> { ) -> Result<LoginResponse, LemmyError> {
let data: &DeleteAccount = &self; let data: &DeleteAccount = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Verify the password // Verify the password
let valid: bool = verify(&data.password, &user.password_encrypted).unwrap_or(false); let valid: bool = verify(
&data.password,
&local_user_view.local_user.password_encrypted,
)
.unwrap_or(false);
if !valid { if !valid {
return Err(ApiError::err("password_incorrect").into()); return Err(ApiError::err("password_incorrect").into());
} }
// Comments // Comments
let user_id = user.id; let person_id = local_user_view.person.id;
let permadelete = move |conn: &'_ _| Comment::permadelete_for_creator(conn, user_id); let permadelete = move |conn: &'_ _| Comment::permadelete_for_creator(conn, person_id);
if blocking(context.pool(), permadelete).await?.is_err() { if blocking(context.pool(), permadelete).await?.is_err() {
return Err(ApiError::err("couldnt_update_comment").into()); return Err(ApiError::err("couldnt_update_comment").into());
} }
// Posts // Posts
let permadelete = move |conn: &'_ _| Post::permadelete_for_creator(conn, user_id); let permadelete = move |conn: &'_ _| Post::permadelete_for_creator(conn, person_id);
if blocking(context.pool(), permadelete).await?.is_err() { if blocking(context.pool(), permadelete).await?.is_err() {
return Err(ApiError::err("couldnt_update_post").into()); return Err(ApiError::err("couldnt_update_post").into());
} }
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
User_::delete_account(conn, user_id) Person::delete_account(conn, person_id)
}) })
.await??; .await??;
@ -948,12 +1001,12 @@ impl Perform for PasswordReset {
// Fetch that email // Fetch that email
let email = data.email.clone(); let email = data.email.clone();
let user = match blocking(context.pool(), move |conn| { let local_user_view = match blocking(context.pool(), move |conn| {
User_::find_by_email(conn, &email) LocalUserView::find_by_email(conn, &email)
}) })
.await? .await?
{ {
Ok(user) => user, Ok(lu) => lu,
Err(_e) => return Err(ApiError::err("couldnt_find_that_username_or_email").into()), Err(_e) => return Err(ApiError::err("couldnt_find_that_username_or_email").into()),
}; };
@ -962,19 +1015,19 @@ impl Perform for PasswordReset {
// Insert the row // Insert the row
let token2 = token.clone(); let token2 = token.clone();
let user_id = user.id; let local_user_id = local_user_view.local_user.id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
PasswordResetRequest::create_token(conn, user_id, &token2) PasswordResetRequest::create_token(conn, local_user_id, &token2)
}) })
.await??; .await??;
// Email the pure token to the user. // Email the pure token to the user.
// TODO no i18n support here. // TODO no i18n support here.
let user_email = &user.email.expect("email"); let email = &local_user_view.local_user.email.expect("email");
let subject = &format!("Password reset for {}", user.name); let subject = &format!("Password reset for {}", local_user_view.person.name);
let hostname = &Settings::get().get_protocol_and_hostname(); let hostname = &Settings::get().get_protocol_and_hostname();
let html = &format!("<h1>Password Reset Request for {}</h1><br><a href={}/password_change/{}>Click here to reset your password</a>", user.name, hostname, &token); let html = &format!("<h1>Password Reset Request for {}</h1><br><a href={}/password_change/{}>Click here to reset your password</a>", local_user_view.person.name, hostname, &token);
match send_email(subject, user_email, &user.name, html) { match send_email(subject, email, &local_user_view.person.name, html) {
Ok(_o) => _o, Ok(_o) => _o,
Err(_e) => return Err(ApiError::err(&_e).into()), Err(_e) => return Err(ApiError::err(&_e).into()),
}; };
@ -996,7 +1049,7 @@ impl Perform for PasswordChange {
// Fetch the user_id from the token // Fetch the user_id from the token
let token = data.token.clone(); let token = data.token.clone();
let user_id = blocking(context.pool(), move |conn| { let local_user_id = blocking(context.pool(), move |conn| {
PasswordResetRequest::read_from_token(conn, &token).map(|p| p.local_user_id) PasswordResetRequest::read_from_token(conn, &token).map(|p| p.local_user_id)
}) })
.await??; .await??;
@ -1010,18 +1063,18 @@ impl Perform for PasswordChange {
// Update the user with the new password // Update the user with the new password
let password = data.password.clone(); let password = data.password.clone();
let updated_user = match blocking(context.pool(), move |conn| { let updated_local_user = match blocking(context.pool(), move |conn| {
User_::update_password(conn, user_id, &password) LocalUser::update_password(conn, local_user_id, &password)
}) })
.await? .await?
{ {
Ok(user) => user, Ok(u) => u,
Err(_e) => return Err(ApiError::err("couldnt_update_user").into()), Err(_e) => return Err(ApiError::err("couldnt_update_user").into()),
}; };
// Return the jwt // Return the jwt
Ok(LoginResponse { Ok(LoginResponse {
jwt: Claims::jwt(updated_user.id, Settings::get().hostname())?, jwt: Claims::jwt(updated_local_user.id, Settings::get().hostname())?,
}) })
} }
} }
@ -1036,13 +1089,13 @@ impl Perform for CreatePrivateMessage {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<PrivateMessageResponse, LemmyError> { ) -> Result<PrivateMessageResponse, LemmyError> {
let data: &CreatePrivateMessage = &self; let data: &CreatePrivateMessage = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let content_slurs_removed = remove_slurs(&data.content.to_owned()); let content_slurs_removed = remove_slurs(&data.content.to_owned());
let private_message_form = PrivateMessageForm { let private_message_form = PrivateMessageForm {
content: content_slurs_removed.to_owned(), content: content_slurs_removed.to_owned(),
creator_id: user.id, creator_id: local_user_view.person.id,
recipient_id: data.recipient_id, recipient_id: data.recipient_id,
deleted: None, deleted: None,
read: None, read: None,
@ -1084,28 +1137,32 @@ impl Perform for CreatePrivateMessage {
Err(_e) => return Err(ApiError::err("couldnt_create_private_message").into()), Err(_e) => return Err(ApiError::err("couldnt_create_private_message").into()),
}; };
updated_private_message.send_create(&user, context).await?; updated_private_message
.send_create(&local_user_view.person, context)
.await?;
// Send notifications to the recipient // Send notifications to the recipient
let recipient_id = data.recipient_id; let recipient_id = data.recipient_id;
let recipient_user = let recipient = blocking(context.pool(), move |conn| {
blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; LocalUserView::read_person(conn, recipient_id)
if recipient_user.send_notifications_to_email { })
.await??;
if recipient.local_user.send_notifications_to_email {
send_email_to_user( send_email_to_user(
recipient_user, recipient,
"Private Message from", "Private Message from",
"Private Message", "Private Message",
&content_slurs_removed, &content_slurs_removed,
); );
} }
let message = blocking(context.pool(), move |conn| { let private_message_view = blocking(context.pool(), move |conn| {
PrivateMessageView::read(conn, inserted_private_message.id) PrivateMessageView::read(conn, inserted_private_message.id)
}) })
.await??; .await??;
let res = PrivateMessageResponse { let res = PrivateMessageResponse {
private_message_view: message, private_message_view,
}; };
context.chat_server().do_send(SendUserRoomMessage { context.chat_server().do_send(SendUserRoomMessage {
@ -1129,7 +1186,7 @@ impl Perform for EditPrivateMessage {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<PrivateMessageResponse, LemmyError> { ) -> Result<PrivateMessageResponse, LemmyError> {
let data: &EditPrivateMessage = &self; let data: &EditPrivateMessage = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Checking permissions // Checking permissions
let private_message_id = data.private_message_id; let private_message_id = data.private_message_id;
@ -1137,7 +1194,7 @@ impl Perform for EditPrivateMessage {
PrivateMessage::read(conn, private_message_id) PrivateMessage::read(conn, private_message_id)
}) })
.await??; .await??;
if user.id != orig_private_message.creator_id { if local_user_view.person.id != orig_private_message.creator_id {
return Err(ApiError::err("no_private_message_edit_allowed").into()); return Err(ApiError::err("no_private_message_edit_allowed").into());
} }
@ -1154,17 +1211,19 @@ impl Perform for EditPrivateMessage {
}; };
// Send the apub update // Send the apub update
updated_private_message.send_update(&user, context).await?; updated_private_message
.send_update(&local_user_view.person, context)
.await?;
let private_message_id = data.private_message_id; let private_message_id = data.private_message_id;
let message = blocking(context.pool(), move |conn| { let private_message_view = blocking(context.pool(), move |conn| {
PrivateMessageView::read(conn, private_message_id) PrivateMessageView::read(conn, private_message_id)
}) })
.await??; .await??;
let recipient_id = message.recipient.id; let recipient_id = private_message_view.recipient.id;
let res = PrivateMessageResponse { let res = PrivateMessageResponse {
private_message_view: message, private_message_view,
}; };
context.chat_server().do_send(SendUserRoomMessage { context.chat_server().do_send(SendUserRoomMessage {
@ -1188,7 +1247,7 @@ impl Perform for DeletePrivateMessage {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<PrivateMessageResponse, LemmyError> { ) -> Result<PrivateMessageResponse, LemmyError> {
let data: &DeletePrivateMessage = &self; let data: &DeletePrivateMessage = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Checking permissions // Checking permissions
let private_message_id = data.private_message_id; let private_message_id = data.private_message_id;
@ -1196,7 +1255,7 @@ impl Perform for DeletePrivateMessage {
PrivateMessage::read(conn, private_message_id) PrivateMessage::read(conn, private_message_id)
}) })
.await??; .await??;
if user.id != orig_private_message.creator_id { if local_user_view.person.id != orig_private_message.creator_id {
return Err(ApiError::err("no_private_message_edit_allowed").into()); return Err(ApiError::err("no_private_message_edit_allowed").into());
} }
@ -1214,22 +1273,24 @@ impl Perform for DeletePrivateMessage {
// Send the apub update // Send the apub update
if data.deleted { if data.deleted {
updated_private_message.send_delete(&user, context).await?; updated_private_message
.send_delete(&local_user_view.person, context)
.await?;
} else { } else {
updated_private_message updated_private_message
.send_undo_delete(&user, context) .send_undo_delete(&local_user_view.person, context)
.await?; .await?;
} }
let private_message_id = data.private_message_id; let private_message_id = data.private_message_id;
let message = blocking(context.pool(), move |conn| { let private_message_view = blocking(context.pool(), move |conn| {
PrivateMessageView::read(conn, private_message_id) PrivateMessageView::read(conn, private_message_id)
}) })
.await??; .await??;
let recipient_id = message.recipient.id; let recipient_id = private_message_view.recipient.id;
let res = PrivateMessageResponse { let res = PrivateMessageResponse {
private_message_view: message, private_message_view,
}; };
context.chat_server().do_send(SendUserRoomMessage { context.chat_server().do_send(SendUserRoomMessage {
@ -1253,7 +1314,7 @@ impl Perform for MarkPrivateMessageAsRead {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<PrivateMessageResponse, LemmyError> { ) -> Result<PrivateMessageResponse, LemmyError> {
let data: &MarkPrivateMessageAsRead = &self; let data: &MarkPrivateMessageAsRead = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Checking permissions // Checking permissions
let private_message_id = data.private_message_id; let private_message_id = data.private_message_id;
@ -1261,7 +1322,7 @@ impl Perform for MarkPrivateMessageAsRead {
PrivateMessage::read(conn, private_message_id) PrivateMessage::read(conn, private_message_id)
}) })
.await??; .await??;
if user.id != orig_private_message.recipient_id { if local_user_view.person.id != orig_private_message.recipient_id {
return Err(ApiError::err("couldnt_update_private_message").into()); return Err(ApiError::err("couldnt_update_private_message").into());
} }
@ -1280,14 +1341,14 @@ impl Perform for MarkPrivateMessageAsRead {
// No need to send an apub update // No need to send an apub update
let private_message_id = data.private_message_id; let private_message_id = data.private_message_id;
let message = blocking(context.pool(), move |conn| { let private_message_view = blocking(context.pool(), move |conn| {
PrivateMessageView::read(conn, private_message_id) PrivateMessageView::read(conn, private_message_id)
}) })
.await??; .await??;
let recipient_id = message.recipient.id; let recipient_id = private_message_view.recipient.id;
let res = PrivateMessageResponse { let res = PrivateMessageResponse {
private_message_view: message, private_message_view,
}; };
context.chat_server().do_send(SendUserRoomMessage { context.chat_server().do_send(SendUserRoomMessage {
@ -1311,14 +1372,14 @@ impl Perform for GetPrivateMessages {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<PrivateMessagesResponse, LemmyError> { ) -> Result<PrivateMessagesResponse, LemmyError> {
let data: &GetPrivateMessages = &self; let data: &GetPrivateMessages = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let user_id = user.id; let person_id = local_user_view.person.id;
let page = data.page; let page = data.page;
let limit = data.limit; let limit = data.limit;
let unread_only = data.unread_only; let unread_only = data.unread_only;
let messages = blocking(context.pool(), move |conn| { let messages = blocking(context.pool(), move |conn| {
PrivateMessageQueryBuilder::create(&conn, user_id) PrivateMessageQueryBuilder::create(&conn, person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.unread_only(unread_only) .unread_only(unread_only)
@ -1342,12 +1403,12 @@ impl Perform for GetReportCount {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<GetReportCountResponse, LemmyError> { ) -> Result<GetReportCountResponse, LemmyError> {
let data: &GetReportCount = &self; let data: &GetReportCount = &self;
let user = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let user_id = user.id; let person_id = local_user_view.person.id;
let community_id = data.community; let community_id = data.community;
let community_ids = let community_ids =
collect_moderated_communities(user_id, community_id, context.pool()).await?; collect_moderated_communities(person_id, community_id, context.pool()).await?;
let res = { let res = {
if community_ids.is_empty() { if community_ids.is_empty() {
@ -1380,7 +1441,7 @@ impl Perform for GetReportCount {
context.chat_server().do_send(SendUserRoomMessage { context.chat_server().do_send(SendUserRoomMessage {
op: UserOperation::GetReportCount, op: UserOperation::GetReportCount,
response: res.clone(), response: res.clone(),
recipient_id: user.id, recipient_id: local_user_view.person.id,
websocket_id, websocket_id,
}); });

View file

@ -122,7 +122,9 @@ impl Perform for CreatePost {
Err(_e) => return Err(ApiError::err("couldnt_create_post").into()), Err(_e) => return Err(ApiError::err("couldnt_create_post").into()),
}; };
updated_post.send_create(&local_user_view.person, context).await?; updated_post
.send_create(&local_user_view.person, context)
.await?;
// They like their own post by default // They like their own post by default
let like_form = PostLikeForm { let like_form = PostLikeForm {
@ -136,7 +138,9 @@ impl Perform for CreatePost {
return Err(ApiError::err("couldnt_like_post").into()); return Err(ApiError::err("couldnt_like_post").into());
} }
updated_post.send_like(&local_user_view.person, context).await?; updated_post
.send_like(&local_user_view.person, context)
.await?;
// Refetch the view // Refetch the view
let inserted_post_id = inserted_post.id; let inserted_post_id = inserted_post.id;
@ -327,7 +331,9 @@ impl Perform for CreatePostLike {
post.send_dislike(&local_user_view.person, context).await?; post.send_dislike(&local_user_view.person, context).await?;
} }
} else { } else {
post.send_undo_like(&local_user_view.person, context).await?; post
.send_undo_like(&local_user_view.person, context)
.await?;
} }
let post_id = data.post_id; let post_id = data.post_id;
@ -375,7 +381,12 @@ impl Perform for EditPost {
let post_id = data.post_id; let post_id = data.post_id;
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_community_ban(local_user_view.person.id, orig_post.community_id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_post.community_id,
context.pool(),
)
.await?;
// Verify that only the creator can edit // Verify that only the creator can edit
if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) { if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
@ -427,7 +438,9 @@ impl Perform for EditPost {
}; };
// Send apub update // Send apub update
updated_post.send_update(&local_user_view.person, context).await?; updated_post
.send_update(&local_user_view.person, context)
.await?;
let post_id = data.post_id; let post_id = data.post_id;
let post_view = blocking(context.pool(), move |conn| { let post_view = blocking(context.pool(), move |conn| {
@ -462,7 +475,12 @@ impl Perform for DeletePost {
let post_id = data.post_id; let post_id = data.post_id;
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_community_ban(local_user_view.person.id, orig_post.community_id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_post.community_id,
context.pool(),
)
.await?;
// Verify that only the creator can delete // Verify that only the creator can delete
if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) { if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
@ -479,9 +497,13 @@ impl Perform for DeletePost {
// apub updates // apub updates
if deleted { if deleted {
updated_post.send_delete(&local_user_view.person, context).await?; updated_post
.send_delete(&local_user_view.person, context)
.await?;
} else { } else {
updated_post.send_undo_delete(&local_user_view.person, context).await?; updated_post
.send_undo_delete(&local_user_view.person, context)
.await?;
} }
// Refetch the post // Refetch the post
@ -518,10 +540,20 @@ impl Perform for RemovePost {
let post_id = data.post_id; let post_id = data.post_id;
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_community_ban(local_user_view.person.id, orig_post.community_id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_post.community_id,
context.pool(),
)
.await?;
// Verify that only the mods can remove // Verify that only the mods can remove
is_mod_or_admin(context.pool(), local_user_view.person.id, orig_post.community_id).await?; is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_post.community_id,
)
.await?;
// Update the post // Update the post
let post_id = data.post_id; let post_id = data.post_id;
@ -545,9 +577,13 @@ impl Perform for RemovePost {
// apub updates // apub updates
if removed { if removed {
updated_post.send_remove(&local_user_view.person, context).await?; updated_post
.send_remove(&local_user_view.person, context)
.await?;
} else { } else {
updated_post.send_undo_remove(&local_user_view.person, context).await?; updated_post
.send_undo_remove(&local_user_view.person, context)
.await?;
} }
// Refetch the post // Refetch the post
@ -585,10 +621,20 @@ impl Perform for LockPost {
let post_id = data.post_id; let post_id = data.post_id;
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_community_ban(local_user_view.person.id, orig_post.community_id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_post.community_id,
context.pool(),
)
.await?;
// Verify that only the mods can lock // Verify that only the mods can lock
is_mod_or_admin(context.pool(), local_user_view.person.id, orig_post.community_id).await?; is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_post.community_id,
)
.await?;
// Update the post // Update the post
let post_id = data.post_id; let post_id = data.post_id;
@ -607,7 +653,9 @@ impl Perform for LockPost {
blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??; blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??;
// apub updates // apub updates
updated_post.send_update(&local_user_view.person, context).await?; updated_post
.send_update(&local_user_view.person, context)
.await?;
// Refetch the post // Refetch the post
let post_id = data.post_id; let post_id = data.post_id;
@ -643,10 +691,20 @@ impl Perform for StickyPost {
let post_id = data.post_id; let post_id = data.post_id;
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_community_ban(local_user_view.person.id, orig_post.community_id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_post.community_id,
context.pool(),
)
.await?;
// Verify that only the mods can sticky // Verify that only the mods can sticky
is_mod_or_admin(context.pool(), local_user_view.person.id, orig_post.community_id).await?; is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_post.community_id,
)
.await?;
// Update the post // Update the post
let post_id = data.post_id; let post_id = data.post_id;
@ -669,7 +727,9 @@ impl Perform for StickyPost {
// Apub updates // Apub updates
// TODO stickied should pry work like locked for ease of use // TODO stickied should pry work like locked for ease of use
updated_post.send_update(&local_user_view.person, context).await?; updated_post
.send_update(&local_user_view.person, context)
.await?;
// Refetch the post // Refetch the post
let post_id = data.post_id; let post_id = data.post_id;

View file

@ -1,6 +1,6 @@
use crate::Perform; use crate::Perform;
use actix_web::{error::ErrorBadRequest, *}; use actix_web::{error::ErrorBadRequest, *};
use lemmy_api_structs::{comment::*, community::*, post::*, site::*, person::*, websocket::*}; use lemmy_api_structs::{comment::*, community::*, person::*, post::*, site::*, websocket::*};
use lemmy_utils::rate_limit::RateLimit; use lemmy_utils::rate_limit::RateLimit;
use lemmy_websocket::{routes::chat_route, LemmyContext}; use lemmy_websocket::{routes::chat_route, LemmyContext};
use serde::Deserialize; use serde::Deserialize;

View file

@ -1,14 +1,15 @@
use crate::{ use crate::{
build_federated_instances, build_federated_instances,
get_local_user_settings_view_from_jwt,
get_local_user_settings_view_from_jwt_opt,
get_local_user_view_from_jwt, get_local_user_view_from_jwt,
get_local_user_view_from_jwt_opt, get_local_user_view_from_jwt_opt,
get_local_user_settings_view_from_jwt_opt,
is_admin, is_admin,
Perform, Perform,
}; };
use actix_web::web::Data; use actix_web::web::Data;
use anyhow::Context; use anyhow::Context;
use lemmy_api_structs::{blocking, site::*, person::Register}; use lemmy_api_structs::{blocking, person::Register, site::*};
use lemmy_apub::fetcher::search::search_by_apub_id; use lemmy_apub::fetcher::search::search_by_apub_id;
use lemmy_db_queries::{ use lemmy_db_queries::{
diesel_option_overwrite_to_url, diesel_option_overwrite_to_url,
@ -536,13 +537,15 @@ impl Perform for TransferSite {
let banned = blocking(context.pool(), move |conn| PersonViewSafe::banned(conn)).await??; let banned = blocking(context.pool(), move |conn| PersonViewSafe::banned(conn)).await??;
let federated_instances = build_federated_instances(context.pool()).await?; let federated_instances = build_federated_instances(context.pool()).await?;
let my_user = Some(get_local_user_settings_view_from_jwt(&data.auth, context.pool()).await?);
Ok(GetSiteResponse { Ok(GetSiteResponse {
site_view: 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(local_user_view), my_user,
federated_instances, federated_instances,
}) })
} }
@ -582,7 +585,6 @@ impl Perform for SaveSiteConfig {
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Only let admins read this // Only let admins read this
let person_id = local_user_view.person.id;
is_admin(&local_user_view)?; is_admin(&local_user_view)?;
// 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

View file

@ -1,17 +1,17 @@
pub mod comment; pub mod comment;
pub mod community; pub mod community;
pub mod person;
pub mod post; pub mod post;
pub mod site; pub mod site;
pub mod person;
pub mod websocket; pub mod websocket;
use diesel::PgConnection; use diesel::PgConnection;
use lemmy_db_queries::{Crud, DbPool}; use lemmy_db_queries::{Crud, DbPool};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::Comment, comment::Comment,
post::Post,
person::Person, person::Person,
person_mention::{PersonMention, PersonMentionForm}, person_mention::{PersonMention, PersonMentionForm},
post::Post,
}; };
use lemmy_db_views::local_user_view::LocalUserView; use lemmy_db_views::local_user_view::LocalUserView;
use lemmy_utils::{email::send_email, settings::structs::Settings, utils::MentionData, LemmyError}; use lemmy_utils::{email::send_email, settings::structs::Settings, utils::MentionData, LemmyError};
@ -119,11 +119,17 @@ fn do_send_local_notifs(
Some(parent_id) => { Some(parent_id) => {
if let Ok(parent_comment) = Comment::read(&conn, parent_id) { if let Ok(parent_comment) = Comment::read(&conn, parent_id) {
if parent_comment.creator_id != person.id { if parent_comment.creator_id != person.id {
if let Ok(parent_user_view) = LocalUserView::read(&conn, parent_comment.creator_id) { if let Ok(parent_user_view) = LocalUserView::read_person(&conn, parent_comment.creator_id)
{
recipient_ids.push(parent_user_view.person.id); recipient_ids.push(parent_user_view.person.id);
if do_send_email && parent_user_view.local_user.send_notifications_to_email { if do_send_email && parent_user_view.local_user.send_notifications_to_email {
send_email_to_user(parent_user_view, "Reply from", "Comment Reply", &comment.content) send_email_to_user(
parent_user_view,
"Reply from",
"Comment Reply",
&comment.content,
)
} }
} }
} }
@ -132,11 +138,16 @@ fn do_send_local_notifs(
// Its a post // Its a post
None => { None => {
if post.creator_id != person.id { if post.creator_id != person.id {
if let Ok(parent_user_view) = LocalUserView::read(&conn, post.creator_id) { if let Ok(parent_user_view) = LocalUserView::read_person(&conn, post.creator_id) {
recipient_ids.push(parent_user_view.person.id); recipient_ids.push(parent_user_view.person.id);
if do_send_email && parent_user_view.local_user.send_notifications_to_email { if do_send_email && parent_user_view.local_user.send_notifications_to_email {
send_email_to_user(parent_user_view, "Reply from", "Post Reply", &comment.content) send_email_to_user(
parent_user_view,
"Reply from",
"Post Reply",
&comment.content,
)
} }
} }
} }
@ -145,7 +156,12 @@ fn do_send_local_notifs(
recipient_ids recipient_ids
} }
pub fn send_email_to_user(local_user_view: LocalUserView, subject_text: &str, body_text: &str, comment_content: &str) { pub fn send_email_to_user(
local_user_view: LocalUserView,
subject_text: &str,
body_text: &str,
comment_content: &str,
) {
if local_user_view.person.banned { if local_user_view.person.banned {
return; return;
} }

View file

@ -45,11 +45,11 @@ pub struct CaptchaResponse {
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct SaveUserSettings { pub struct SaveUserSettings {
pub show_nsfw: bool, pub show_nsfw: Option<bool>,
pub theme: String, pub theme: Option<String>,
pub default_sort_type: i16, pub default_sort_type: Option<i16>,
pub default_listing_type: i16, pub default_listing_type: Option<i16>,
pub lang: String, pub lang: Option<String>,
pub avatar: Option<String>, pub avatar: Option<String>,
pub banner: Option<String>, pub banner: Option<String>,
pub preferred_username: Option<String>, pub preferred_username: Option<String>,
@ -59,8 +59,8 @@ pub struct SaveUserSettings {
pub new_password: Option<String>, pub new_password: Option<String>,
pub new_password_verify: Option<String>, pub new_password_verify: Option<String>,
pub old_password: Option<String>, pub old_password: Option<String>,
pub show_avatars: bool, pub show_avatars: Option<bool>,
pub send_notifications_to_email: bool, pub send_notifications_to_email: Option<bool>,
pub auth: String, pub auth: String,
} }
@ -107,7 +107,7 @@ pub struct MarkAllAsRead {
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct AddAdmin { pub struct AddAdmin {
pub person_id: i32, pub local_user_id: i32,
pub added: bool, pub added: bool,
pub auth: String, pub auth: String,
} }

View file

@ -1,4 +1,9 @@
use lemmy_db_views::{comment_view::CommentView, post_view::PostView, site_view::SiteView, local_user_view::LocalUserSettingsView}; use lemmy_db_views::{
comment_view::CommentView,
local_user_view::LocalUserSettingsView,
post_view::PostView,
site_view::SiteView,
};
use lemmy_db_views_actor::{community_view::CommunityView, person_view::PersonViewSafe}; use lemmy_db_views_actor::{community_view::CommunityView, person_view::PersonViewSafe};
use lemmy_db_views_moderator::{ use lemmy_db_views_moderator::{
mod_add_community_view::ModAddCommunityView, mod_add_community_view::ModAddCommunityView,

View file

@ -33,8 +33,15 @@ pub(crate) async fn receive_create_comment(
// Its much easier to scrape them from the comment body, since the API has to do that // Its much easier to scrape them from the comment body, since the API has to do that
// anyway. // anyway.
let mentions = scrape_text_for_mentions(&comment.content); let mentions = scrape_text_for_mentions(&comment.content);
let recipient_ids = let recipient_ids = send_local_notifs(
send_local_notifs(mentions, comment.clone(), person, post, context.pool(), true).await?; mentions,
comment.clone(),
person,
post,
context.pool(),
true,
)
.await?;
// Refetch the view // Refetch the view
let comment_view = blocking(context.pool(), move |conn| { let comment_view = blocking(context.pool(), move |conn| {

View file

@ -28,7 +28,7 @@ use anyhow::anyhow;
use itertools::Itertools; use itertools::Itertools;
use lemmy_api_structs::{blocking, WebFingerResponse}; use lemmy_api_structs::{blocking, WebFingerResponse};
use lemmy_db_queries::{Crud, DbPool}; use lemmy_db_queries::{Crud, DbPool};
use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post, person::Person}; use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
use lemmy_utils::{ use lemmy_utils::{
request::{retry, RecvError}, request::{retry, RecvError},
settings::structs::Settings, settings::structs::Settings,
@ -197,7 +197,11 @@ impl ApubObjectType for Comment {
Ok(()) Ok(())
} }
async fn send_undo_remove(&self, mod_: &Person, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_undo_remove(
&self,
mod_: &Person,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let post_id = self.post_id; let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
@ -389,7 +393,10 @@ async fn collect_non_local_mentions(
/// Returns the apub ID of the person this comment is responding to. Meaning, in case this is a /// Returns the apub ID of the person this comment is responding to. Meaning, in case this is a
/// top-level comment, the creator of the post, otherwise the creator of the parent comment. /// top-level comment, the creator of the post, otherwise the creator of the parent comment.
async fn get_comment_parent_creator(pool: &DbPool, comment: &Comment) -> Result<Person, LemmyError> { async fn get_comment_parent_creator(
pool: &DbPool,
comment: &Comment,
) -> Result<Person, LemmyError> {
let parent_creator_id = if let Some(parent_comment_id) = comment.parent_id { let parent_creator_id = if let Some(parent_comment_id) = comment.parent_id {
let parent_comment = let parent_comment =
blocking(pool, move |conn| Comment::read(conn, parent_comment_id)).await??; blocking(pool, move |conn| Comment::read(conn, parent_comment_id)).await??;

View file

@ -4,9 +4,9 @@ use uuid::Uuid;
pub(crate) mod comment; pub(crate) mod comment;
pub(crate) mod community; pub(crate) mod community;
pub(crate) mod person;
pub(crate) mod post; pub(crate) mod post;
pub(crate) mod private_message; pub(crate) mod private_message;
pub(crate) mod person;
/// Generate a unique ID for an activity, in the format: /// Generate a unique ID for an activity, in the format:
/// `http(s)://example.com/receive/create/202daf0a-1489-45df-8d2e-c8a3173fed36` /// `http(s)://example.com/receive/create/202daf0a-1489-45df-8d2e-c8a3173fed36`

View file

@ -23,7 +23,7 @@ use activitystreams::{
}; };
use lemmy_api_structs::blocking; use lemmy_api_structs::blocking;
use lemmy_db_queries::Crud; use lemmy_db_queries::Crud;
use lemmy_db_schema::source::{community::Community, post::Post, person::Person}; use lemmy_db_schema::source::{community::Community, person::Person, post::Post};
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -155,7 +155,11 @@ impl ApubObjectType for Post {
Ok(()) Ok(())
} }
async fn send_undo_remove(&self, mod_: &Person, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_undo_remove(
&self,
mod_: &Person,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let community_id = self.community_id; let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| { let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id) Community::read(conn, community_id)

View file

@ -18,7 +18,7 @@ use activitystreams::{
}; };
use lemmy_api_structs::blocking; use lemmy_api_structs::blocking;
use lemmy_db_queries::Crud; use lemmy_db_queries::Crud;
use lemmy_db_schema::source::{private_message::PrivateMessage, person::Person}; use lemmy_db_schema::source::{person::Person, private_message::PrivateMessage};
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -29,7 +29,8 @@ impl ApubObjectType for PrivateMessage {
let note = self.to_apub(context.pool()).await?; let note = self.to_apub(context.pool()).await?;
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??; let recipient =
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
let mut create = Create::new( let mut create = Create::new(
creator.actor_id.to_owned().into_inner(), creator.actor_id.to_owned().into_inner(),
@ -50,7 +51,8 @@ impl ApubObjectType for PrivateMessage {
let note = self.to_apub(context.pool()).await?; let note = self.to_apub(context.pool()).await?;
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??; let recipient =
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
let mut update = Update::new( let mut update = Update::new(
creator.actor_id.to_owned().into_inner(), creator.actor_id.to_owned().into_inner(),
@ -67,7 +69,8 @@ impl ApubObjectType for PrivateMessage {
async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??; let recipient =
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
let mut delete = Delete::new( let mut delete = Delete::new(
creator.actor_id.to_owned().into_inner(), creator.actor_id.to_owned().into_inner(),
@ -88,7 +91,8 @@ impl ApubObjectType for PrivateMessage {
context: &LemmyContext, context: &LemmyContext,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??; let recipient =
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
let mut delete = Delete::new( let mut delete = Delete::new(
creator.actor_id.to_owned().into_inner(), creator.actor_id.to_owned().into_inner(),

View file

@ -1,8 +1,8 @@
pub(crate) mod community; pub(crate) mod community;
mod fetch; mod fetch;
pub(crate) mod objects; pub(crate) mod objects;
pub mod search;
pub(crate) mod person; pub(crate) mod person;
pub mod search;
use crate::{ use crate::{
fetcher::{ fetcher::{

View file

@ -46,7 +46,8 @@ pub(crate) async fn get_or_fetch_and_upsert_person(
return Ok(u); return Ok(u);
} }
let person = Person::from_apub(&person?, context, apub_id.to_owned(), recursion_counter).await?; let person =
Person::from_apub(&person?, context, apub_id.to_owned(), recursion_counter).await?;
let person_id = person.id; let person_id = person.id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
@ -62,7 +63,8 @@ pub(crate) async fn get_or_fetch_and_upsert_person(
let person = let person =
fetch_remote_object::<PersonExt>(context.client(), apub_id, recursion_counter).await?; fetch_remote_object::<PersonExt>(context.client(), apub_id, recursion_counter).await?;
let person = Person::from_apub(&person, context, apub_id.to_owned(), recursion_counter).await?; let person =
Person::from_apub(&person, context, apub_id.to_owned(), recursion_counter).await?;
Ok(person) Ok(person)
} }

View file

@ -20,18 +20,18 @@ use lemmy_db_queries::{
source::{ source::{
comment::Comment_, comment::Comment_,
community::Community_, community::Community_,
person::Person_,
post::Post_, post::Post_,
private_message::PrivateMessage_, private_message::PrivateMessage_,
person::Person_,
}, },
SearchType, SearchType,
}; };
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::Comment, comment::Comment,
community::Community, community::Community,
person::Person,
post::Post, post::Post,
private_message::PrivateMessage, private_message::PrivateMessage,
person::Person,
}; };
use lemmy_db_views::{comment_view::CommentView, post_view::PostView}; use lemmy_db_views::{comment_view::CommentView, post_view::PostView};
use lemmy_db_views_actor::{community_view::CommunityView, person_view::PersonViewSafe}; use lemmy_db_views_actor::{community_view::CommunityView, person_view::PersonViewSafe};

View file

@ -11,8 +11,8 @@ use url::Url;
pub mod comment; pub mod comment;
pub mod community; pub mod community;
pub mod post;
pub mod person; pub mod person;
pub mod post;
/// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub /// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub
/// headers. /// headers.

View file

@ -268,7 +268,8 @@ pub(crate) async fn check_community_or_site_ban(
return Err(anyhow!("Person is banned from site").into()); return Err(anyhow!("Person is banned from site").into());
} }
let person_id = person.id; let person_id = person.id;
let is_banned = move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok(); let is_banned =
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
if blocking(pool, is_banned).await? { if blocking(pool, is_banned).await? {
return Err(anyhow!("Person is banned from community").into()); return Err(anyhow!("Person is banned from community").into());
} }

View file

@ -26,9 +26,9 @@ use std::fmt::Debug;
use url::Url; use url::Url;
pub mod community_inbox; pub mod community_inbox;
pub mod person_inbox;
mod receive_for_community; mod receive_for_community;
pub mod shared_inbox; pub mod shared_inbox;
pub mod person_inbox;
pub(crate) fn get_activity_id<T, Kind>(activity: &T, creator_uri: &Url) -> Result<Url, LemmyError> pub(crate) fn get_activity_id<T, Kind>(activity: &T, creator_uri: &Url) -> Result<Url, LemmyError>
where where

View file

@ -52,8 +52,8 @@ use lemmy_api_structs::blocking;
use lemmy_db_queries::{source::person::Person_, ApubObject, Followable}; use lemmy_db_queries::{source::person::Person_, ApubObject, Followable};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
community::{Community, CommunityFollower}, community::{Community, CommunityFollower},
private_message::PrivateMessage,
person::Person, person::Person,
private_message::PrivateMessage,
}; };
use lemmy_utils::{location_info, LemmyError}; use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;

View file

@ -31,9 +31,9 @@ use lemmy_db_schema::{
activity::Activity, activity::Activity,
comment::Comment, comment::Comment,
community::Community, community::Community,
person::Person as DbPerson,
post::Post, post::Post,
private_message::PrivateMessage, private_message::PrivateMessage,
person::Person as DbPerson,
}, },
DbUrl, DbUrl,
}; };
@ -121,24 +121,38 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
/// and actors in Lemmy. /// and actors in Lemmy.
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
pub trait ApubObjectType { pub trait ApubObjectType {
async fn send_create(&self, creator: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>; async fn send_create(&self, creator: &DbPerson, context: &LemmyContext)
async fn send_update(&self, creator: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>; -> Result<(), LemmyError>;
async fn send_delete(&self, creator: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>; async fn send_update(&self, creator: &DbPerson, context: &LemmyContext)
-> Result<(), LemmyError>;
async fn send_delete(&self, creator: &DbPerson, context: &LemmyContext)
-> Result<(), LemmyError>;
async fn send_undo_delete( async fn send_undo_delete(
&self, &self,
creator: &DbPerson, creator: &DbPerson,
context: &LemmyContext, context: &LemmyContext,
) -> Result<(), LemmyError>; ) -> Result<(), LemmyError>;
async fn send_remove(&self, mod_: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>; async fn send_remove(&self, mod_: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>;
async fn send_undo_remove(&self, mod_: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>; async fn send_undo_remove(
&self,
mod_: &DbPerson,
context: &LemmyContext,
) -> Result<(), LemmyError>;
} }
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
pub trait ApubLikeableType { pub trait ApubLikeableType {
async fn send_like(&self, creator: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>; async fn send_like(&self, creator: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>;
async fn send_dislike(&self, creator: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>; async fn send_dislike(
async fn send_undo_like(&self, creator: &DbPerson, context: &LemmyContext) &self,
-> Result<(), LemmyError>; creator: &DbPerson,
context: &LemmyContext,
) -> Result<(), LemmyError>;
async fn send_undo_like(
&self,
creator: &DbPerson,
context: &LemmyContext,
) -> Result<(), LemmyError>;
} }
/// Common methods provided by ActivityPub actors (community and person). Not all methods are /// Common methods provided by ActivityPub actors (community and person). Not all methods are
@ -316,11 +330,11 @@ pub(crate) async fn find_post_or_comment_by_id(
} }
pub(crate) enum Object { pub(crate) enum Object {
Comment(Comment), Comment(Box<Comment>),
Post(Post), Post(Box<Post>),
Community(Community), Community(Box<Community>),
Person(DbPerson), Person(Box<DbPerson>),
PrivateMessage(PrivateMessage), PrivateMessage(Box<PrivateMessage>),
} }
pub(crate) async fn find_object_by_id( pub(crate) async fn find_object_by_id(
@ -330,8 +344,8 @@ pub(crate) async fn find_object_by_id(
let ap_id = apub_id.clone(); let ap_id = apub_id.clone();
if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await { if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await {
return Ok(match pc { return Ok(match pc {
PostOrComment::Post(p) => Object::Post(*p), PostOrComment::Post(p) => Object::Post(Box::new(*p)),
PostOrComment::Comment(c) => Object::Comment(*c), PostOrComment::Comment(c) => Object::Comment(Box::new(*c)),
}); });
} }
@ -341,7 +355,7 @@ pub(crate) async fn find_object_by_id(
}) })
.await?; .await?;
if let Ok(u) = person { if let Ok(u) = person {
return Ok(Object::Person(u)); return Ok(Object::Person(Box::new(u)));
} }
let ap_id = apub_id.clone(); let ap_id = apub_id.clone();
@ -350,7 +364,7 @@ pub(crate) async fn find_object_by_id(
}) })
.await?; .await?;
if let Ok(c) = community { if let Ok(c) = community {
return Ok(Object::Community(c)); return Ok(Object::Community(Box::new(c)));
} }
let private_message = blocking(context.pool(), move |conn| { let private_message = blocking(context.pool(), move |conn| {
@ -358,7 +372,7 @@ pub(crate) async fn find_object_by_id(
}) })
.await?; .await?;
if let Ok(pm) = private_message { if let Ok(pm) = private_message {
return Ok(Object::PrivateMessage(pm)); return Ok(Object::PrivateMessage(Box::new(pm)));
} }
Err(NotFound.into()) Err(NotFound.into())

View file

@ -25,8 +25,8 @@ use lemmy_api_structs::blocking;
use lemmy_db_queries::{Crud, DbPool}; use lemmy_db_queries::{Crud, DbPool};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::{Comment, CommentForm}, comment::{Comment, CommentForm},
post::Post,
person::Person, person::Person,
post::Post,
}; };
use lemmy_utils::{ use lemmy_utils::{
location_info, location_info,
@ -135,7 +135,8 @@ impl FromApubToForm<NoteExt> for CommentForm {
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.context(location_info!())?; .context(location_info!())?;
let creator = get_or_fetch_and_upsert_person(creator_actor_id, context, request_counter).await?; let creator =
get_or_fetch_and_upsert_person(creator_actor_id, context, request_counter).await?;
let mut in_reply_tos = note let mut in_reply_tos = note
.in_reply_to() .in_reply_to()

View file

@ -26,9 +26,9 @@ use url::Url;
pub(crate) mod comment; pub(crate) mod comment;
pub(crate) mod community; pub(crate) mod community;
pub(crate) mod person;
pub(crate) mod post; pub(crate) mod post;
pub(crate) mod private_message; pub(crate) mod private_message;
pub(crate) mod person;
/// Trait for converting an object or actor into the respective ActivityPub type. /// Trait for converting an object or actor into the respective ActivityPub type.
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]

View file

@ -22,7 +22,7 @@ use lemmy_api_structs::blocking;
use lemmy_db_queries::{ApubObject, DbPool}; use lemmy_db_queries::{ApubObject, DbPool};
use lemmy_db_schema::{ use lemmy_db_schema::{
naive_now, naive_now,
source::person::{PersonForm, Person as DbPerson}, source::person::{Person as DbPerson, PersonForm},
}; };
use lemmy_utils::{ use lemmy_utils::{
location_info, location_info,
@ -105,7 +105,10 @@ impl FromApub for DbPerson {
} else { } else {
let person_form = let person_form =
PersonForm::from_apub(person, context, expected_domain, request_counter).await?; PersonForm::from_apub(person, context, expected_domain, request_counter).await?;
let person = blocking(context.pool(), move |conn| DbPerson::upsert(conn, &person_form)).await??; let person = blocking(context.pool(), move |conn| {
DbPerson::upsert(conn, &person_form)
})
.await??;
Ok(person) Ok(person)
} }
} }

View file

@ -28,8 +28,8 @@ use lemmy_db_schema::{
self, self,
source::{ source::{
community::Community, community::Community,
post::{Post, PostForm},
person::Person, person::Person,
post::{Post, PostForm},
}, },
}; };
use lemmy_utils::{ use lemmy_utils::{
@ -142,7 +142,8 @@ impl FromApubToForm<PageExt> for PostForm {
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.context(location_info!())?; .context(location_info!())?;
let creator = get_or_fetch_and_upsert_person(creator_actor_id, context, request_counter).await?; let creator =
get_or_fetch_and_upsert_person(creator_actor_id, context, request_counter).await?;
let community = get_to_community(page, context, request_counter).await?; let community = get_to_community(page, context, request_counter).await?;

View file

@ -22,8 +22,8 @@ use anyhow::Context;
use lemmy_api_structs::blocking; use lemmy_api_structs::blocking;
use lemmy_db_queries::{Crud, DbPool}; use lemmy_db_queries::{Crud, DbPool};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
private_message::{PrivateMessage, PrivateMessageForm},
person::Person, person::Person,
private_message::{PrivateMessage, PrivateMessageForm},
}; };
use lemmy_utils::{location_info, utils::convert_datetime, LemmyError}; use lemmy_utils::{location_info, utils::convert_datetime, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -97,7 +97,8 @@ impl FromApubToForm<NoteExt> for PrivateMessageForm {
.single_xsd_any_uri() .single_xsd_any_uri()
.context(location_info!())?; .context(location_info!())?;
let creator = get_or_fetch_and_upsert_person(&creator_actor_id, context, request_counter).await?; let creator =
get_or_fetch_and_upsert_person(&creator_actor_id, context, request_counter).await?;
let recipient_actor_id = note let recipient_actor_id = note
.to() .to()
.context(location_info!())? .context(location_info!())?

View file

@ -8,10 +8,14 @@ use crate::{
get_apub_community_outbox, get_apub_community_outbox,
}, },
get_activity, get_activity,
post::get_apub_post,
person::{get_apub_person_http, get_apub_person_inbox, get_apub_person_outbox}, person::{get_apub_person_http, get_apub_person_inbox, get_apub_person_outbox},
post::get_apub_post,
},
inbox::{
community_inbox::community_inbox,
person_inbox::person_inbox,
shared_inbox::shared_inbox,
}, },
inbox::{community_inbox::community_inbox, shared_inbox::shared_inbox, person_inbox::person_inbox},
APUB_JSON_CONTENT_TYPE, APUB_JSON_CONTENT_TYPE,
}; };
use actix_web::*; use actix_web::*;
@ -54,7 +58,10 @@ pub fn config(cfg: &mut web::ServiceConfig) {
web::get().to(get_apub_community_inbox), web::get().to(get_apub_community_inbox),
) )
.route("/u/{user_name}", web::get().to(get_apub_person_http)) .route("/u/{user_name}", web::get().to(get_apub_person_http))
.route("/u/{user_name}/outbox", web::get().to(get_apub_person_outbox)) .route(
"/u/{user_name}/outbox",
web::get().to(get_apub_person_outbox),
)
.route("/u/{user_name}/inbox", web::get().to(get_apub_person_inbox)) .route("/u/{user_name}/inbox", web::get().to(get_apub_person_inbox))
.route("/post/{post_id}", web::get().to(get_apub_post)) .route("/post/{post_id}", web::get().to(get_apub_post))
.route("/comment/{comment_id}", web::get().to(get_apub_comment)) .route("/comment/{comment_id}", web::get().to(get_apub_comment))

View file

@ -32,8 +32,8 @@ mod tests {
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::{Comment, CommentForm, CommentLike, CommentLikeForm}, comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
community::{Community, CommunityForm}, community::{Community, CommunityForm},
person::{Person, PersonForm},
post::{Post, PostForm}, post::{Post, PostForm},
person::{PersonForm, Person},
}; };
use serial_test::serial; use serial_test::serial;

View file

@ -36,8 +36,8 @@ mod tests {
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::{Comment, CommentForm}, comment::{Comment, CommentForm},
community::{Community, CommunityFollower, CommunityFollowerForm, CommunityForm}, community::{Community, CommunityFollower, CommunityFollowerForm, CommunityForm},
person::{Person, PersonForm},
post::{Post, PostForm}, post::{Post, PostForm},
person::{PersonForm, Person},
}; };
use serial_test::serial; use serial_test::serial;

View file

@ -1,5 +1,5 @@
pub mod comment_aggregates; pub mod comment_aggregates;
pub mod community_aggregates; pub mod community_aggregates;
pub mod person_aggregates;
pub mod post_aggregates; pub mod post_aggregates;
pub mod site_aggregates; pub mod site_aggregates;
pub mod person_aggregates;

View file

@ -32,8 +32,8 @@ mod tests {
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::{Comment, CommentForm, CommentLike, CommentLikeForm}, comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
community::{Community, CommunityForm}, community::{Community, CommunityForm},
person::{Person, PersonForm},
post::{Post, PostForm, PostLike, PostLikeForm}, post::{Post, PostForm, PostLike, PostLikeForm},
person::{PersonForm, Person},
}; };
use serial_test::serial; use serial_test::serial;
@ -189,7 +189,8 @@ mod tests {
let _inserted_child_comment_like = CommentLike::like(&conn, &child_comment_like).unwrap(); let _inserted_child_comment_like = CommentLike::like(&conn, &child_comment_like).unwrap();
let person_aggregates_before_delete = PersonAggregates::read(&conn, inserted_person.id).unwrap(); let person_aggregates_before_delete =
PersonAggregates::read(&conn, inserted_person.id).unwrap();
assert_eq!(1, person_aggregates_before_delete.post_count); assert_eq!(1, person_aggregates_before_delete.post_count);
assert_eq!(1, person_aggregates_before_delete.post_score); assert_eq!(1, person_aggregates_before_delete.post_score);

View file

@ -36,8 +36,8 @@ mod tests {
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::{Comment, CommentForm}, comment::{Comment, CommentForm},
community::{Community, CommunityForm}, community::{Community, CommunityForm},
person::{Person, PersonForm},
post::{Post, PostForm, PostLike, PostLikeForm}, post::{Post, PostForm, PostLike, PostLikeForm},
person::{PersonForm, Person},
}; };
use serial_test::serial; use serial_test::serial;

View file

@ -25,17 +25,13 @@ impl SiteAggregates {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{aggregates::site_aggregates::SiteAggregates, establish_unpooled_connection, Crud};
aggregates::site_aggregates::SiteAggregates,
establish_unpooled_connection,
Crud,
};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::{Comment, CommentForm}, comment::{Comment, CommentForm},
community::{Community, CommunityForm}, community::{Community, CommunityForm},
person::{Person, PersonForm},
post::{Post, PostForm}, post::{Post, PostForm},
site::{Site, SiteForm}, site::{Site, SiteForm},
person::{PersonForm, Person},
}; };
use serial_test::serial; use serial_test::serial;

View file

@ -122,13 +122,10 @@ impl Activity_ for Activity {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::{ use crate::{establish_unpooled_connection, source::activity::Activity_};
establish_unpooled_connection,
source::activity::Activity_,
};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
activity::{Activity, ActivityForm}, activity::{Activity, ActivityForm},
person::{PersonForm, Person}, person::{Person, PersonForm},
}; };
use serde_json::Value; use serde_json::Value;
use serial_test::serial; use serial_test::serial;

View file

@ -209,8 +209,8 @@ mod tests {
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::*, comment::*,
community::{Community, CommunityForm}, community::{Community, CommunityForm},
person::{Person, PersonForm},
post::*, post::*,
person::{PersonForm, Person},
}; };
use serial_test::serial; use serial_test::serial;

View file

@ -295,7 +295,11 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
.set(community_follower_form) .set(community_follower_form)
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
fn follow_accepted(conn: &PgConnection, community_id_: i32, person_id_: i32) -> Result<Self, Error> fn follow_accepted(
conn: &PgConnection,
community_id_: i32,
person_id_: i32,
) -> Result<Self, Error>
where where
Self: Sized, Self: Sized,
{ {
@ -333,13 +337,7 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{establish_unpooled_connection, Bannable, Crud, Followable, Joinable};
establish_unpooled_connection,
Bannable,
Crud,
Followable,
Joinable,
};
use lemmy_db_schema::source::{community::*, person::*}; use lemmy_db_schema::source::{community::*, person::*};
use serial_test::serial; use serial_test::serial;
@ -438,7 +436,8 @@ mod tests {
person_id: inserted_person.id, person_id: inserted_person.id,
}; };
let inserted_community_moderator = CommunityModerator::join(&conn, &community_moderator_form).unwrap(); let inserted_community_moderator =
CommunityModerator::join(&conn, &community_moderator_form).unwrap();
let expected_community_moderator = CommunityModerator { let expected_community_moderator = CommunityModerator {
id: inserted_community_moderator.id, id: inserted_community_moderator.id,

View file

@ -1,30 +1,21 @@
use crate::{is_email_regex, Crud, ToSafeSettings}; use crate::{Crud, ToSafeSettings};
use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::source::local_user::LocalUserSettings;
use lemmy_db_schema::schema::local_user::dsl::*;
use lemmy_db_schema::source::local_user::{LocalUser, LocalUserForm};
use bcrypt::{hash, DEFAULT_COST}; use bcrypt::{hash, DEFAULT_COST};
use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
schema::local_user::dsl::*,
source::local_user::{LocalUser, LocalUserForm, LocalUserSettings},
};
mod safe_type { mod safe_type {
use crate::ToSafe; use crate::ToSafe;
use lemmy_db_schema::{schema::local_user::columns::*, source::local_user::LocalUser}; use lemmy_db_schema::{schema::local_user::columns::*, source::local_user::LocalUser};
type Columns = ( type Columns = (id, person_id, admin, matrix_user_id);
id,
person_id,
admin,
matrix_user_id,
);
impl ToSafe for LocalUser { impl ToSafe for LocalUser {
type SafeColumns = Columns; type SafeColumns = Columns;
fn safe_columns_tuple() -> Self::SafeColumns { fn safe_columns_tuple() -> Self::SafeColumns {
( (id, person_id, admin, matrix_user_id)
id,
person_id,
admin,
matrix_user_id,
)
} }
} }
} }
@ -73,10 +64,12 @@ mod safe_settings_type {
pub trait LocalUser_ { pub trait LocalUser_ {
fn register(conn: &PgConnection, form: &LocalUserForm) -> Result<LocalUser, Error>; fn register(conn: &PgConnection, form: &LocalUserForm) -> Result<LocalUser, Error>;
fn update_password(conn: &PgConnection, person_id: i32, new_password: &str) fn update_password(
-> Result<LocalUser, Error>; conn: &PgConnection,
local_user_id: i32,
new_password: &str,
) -> Result<LocalUser, Error>;
fn add_admin(conn: &PgConnection, local_user_id: i32, added: bool) -> Result<LocalUser, Error>; fn add_admin(conn: &PgConnection, local_user_id: i32, added: bool) -> Result<LocalUser, Error>;
fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<LocalUser, Error>;
fn find_by_person(conn: &PgConnection, from_person_id: i32) -> Result<LocalUser, Error>; fn find_by_person(conn: &PgConnection, from_person_id: i32) -> Result<LocalUser, Error>;
} }
@ -91,13 +84,15 @@ impl LocalUser_ for LocalUser {
} }
// TODO do more individual updates like these // TODO do more individual updates like these
fn update_password(conn: &PgConnection, local_user_id: i32, new_password: &str) -> Result<Self, Error> { fn update_password(
conn: &PgConnection,
local_user_id: i32,
new_password: &str,
) -> Result<Self, Error> {
let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password"); let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password");
diesel::update(local_user.find(local_user_id)) diesel::update(local_user.find(local_user_id))
.set(( .set((password_encrypted.eq(password_hash),))
password_encrypted.eq(password_hash),
))
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
@ -108,33 +103,25 @@ impl LocalUser_ for LocalUser {
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
// TODO is this used?
fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<LocalUser, Error> {
local_user
.filter(email.eq(from_email))
.first::<LocalUser>(conn)
}
// TODO is this used? // TODO is this used?
fn find_by_person(conn: &PgConnection, for_person_id: i32) -> Result<LocalUser, Error> { fn find_by_person(conn: &PgConnection, for_person_id: i32) -> Result<LocalUser, Error> {
local_user local_user
.filter(person_id.eq(for_person_id)) .filter(person_id.eq(for_person_id))
.first::<LocalUser>(conn) .first::<LocalUser>(conn)
} }
} }
impl Crud<LocalUserForm> for LocalUser { impl Crud<LocalUserForm> for LocalUser {
fn read(conn: &PgConnection, local_user_id: i32) -> Result<Self, Error> { fn read(conn: &PgConnection, local_user_id: i32) -> Result<Self, Error> {
local_user local_user.find(local_user_id).first::<Self>(conn)
.find(local_user_id)
.first::<Self>(conn)
} }
fn delete(conn: &PgConnection, local_user_id: i32) -> Result<usize, Error> { fn delete(conn: &PgConnection, local_user_id: i32) -> Result<usize, Error> {
diesel::delete(local_user.find(local_user_id)).execute(conn) diesel::delete(local_user.find(local_user_id)).execute(conn)
} }
fn create(conn: &PgConnection, form: &LocalUserForm) -> Result<Self, Error> { fn create(conn: &PgConnection, form: &LocalUserForm) -> Result<Self, Error> {
insert_into(local_user).values(form).get_result::<Self>(conn) insert_into(local_user)
.values(form)
.get_result::<Self>(conn)
} }
fn update(conn: &PgConnection, local_user_id: i32, form: &LocalUserForm) -> Result<Self, Error> { fn update(conn: &PgConnection, local_user_id: i32, form: &LocalUserForm) -> Result<Self, Error> {
diesel::update(local_user.find(local_user_id)) diesel::update(local_user.find(local_user_id))

View file

@ -2,12 +2,12 @@ pub mod activity;
pub mod comment; pub mod comment;
pub mod comment_report; pub mod comment_report;
pub mod community; pub mod community;
pub mod local_user;
pub mod moderator; pub mod moderator;
pub mod password_reset_request; pub mod password_reset_request;
pub mod person;
pub mod person_mention;
pub mod post; pub mod post;
pub mod post_report; pub mod post_report;
pub mod private_message; pub mod private_message;
pub mod site; pub mod site;
pub mod person;
pub mod person_mention;
pub mod local_user;

View file

@ -198,7 +198,7 @@ impl Crud<ModAddForm> for ModAdd {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{establish_unpooled_connection, Crud}; use crate::{establish_unpooled_connection, Crud};
use lemmy_db_schema::source::{comment::*, community::*, moderator::*, post::*, person::*}; use lemmy_db_schema::source::{comment::*, community::*, moderator::*, person::*, post::*};
use serial_test::serial; use serial_test::serial;
// use Crud; // use Crud;

View file

@ -1,32 +1,31 @@
use crate::{is_email_regex, ApubObject, Crud}; use crate::{ApubObject, Crud};
use diesel::{dsl::*, result::Error, *}; use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{ use lemmy_db_schema::{
naive_now, naive_now,
schema::person::dsl::*, schema::person::dsl::*,
source::person::{PersonForm, Person}, source::person::{Person, PersonForm},
DbUrl, DbUrl,
}; };
use lemmy_utils::settings::structs::Settings;
mod safe_type { mod safe_type {
use crate::ToSafe; use crate::ToSafe;
use lemmy_db_schema::{schema::person::columns::*, source::person::Person}; use lemmy_db_schema::{schema::person::columns::*, source::person::Person};
type Columns = ( type Columns = (
id, id,
name, name,
preferred_username, preferred_username,
avatar, avatar,
banned, banned,
published, published,
updated, updated,
actor_id, actor_id,
bio, bio,
local, local,
banner, banner,
deleted, deleted,
inbox_url, inbox_url,
shared_inbox_url, shared_inbox_url,
); );
impl ToSafe for Person { impl ToSafe for Person {
@ -57,20 +56,20 @@ mod safe_type_alias_1 {
use lemmy_db_schema::{schema::person_alias_1::columns::*, source::person::PersonAlias1}; use lemmy_db_schema::{schema::person_alias_1::columns::*, source::person::PersonAlias1};
type Columns = ( type Columns = (
id, id,
name, name,
preferred_username, preferred_username,
avatar, avatar,
banned, banned,
published, published,
updated, updated,
actor_id, actor_id,
bio, bio,
local, local,
banner, banner,
deleted, deleted,
inbox_url, inbox_url,
shared_inbox_url, shared_inbox_url,
); );
impl ToSafe for PersonAlias1 { impl ToSafe for PersonAlias1 {
@ -101,20 +100,20 @@ mod safe_type_alias_2 {
use lemmy_db_schema::{schema::person_alias_2::columns::*, source::person::PersonAlias2}; use lemmy_db_schema::{schema::person_alias_2::columns::*, source::person::PersonAlias2};
type Columns = ( type Columns = (
id, id,
name, name,
preferred_username, preferred_username,
avatar, avatar,
banned, banned,
published, published,
updated, updated,
actor_id, actor_id,
bio, bio,
local, local,
banner, banner,
deleted, deleted,
inbox_url, inbox_url,
shared_inbox_url, shared_inbox_url,
); );
impl ToSafe for PersonAlias2 { impl ToSafe for PersonAlias2 {
@ -181,36 +180,19 @@ impl ApubObject<PersonForm> for Person {
pub trait Person_ { pub trait Person_ {
fn ban_person(conn: &PgConnection, person_id: i32, ban: bool) -> Result<Person, Error>; fn ban_person(conn: &PgConnection, person_id: i32, ban: bool) -> Result<Person, Error>;
// TODO
// fn find_by_email_or_name(
// conn: &PgConnection,
// name_or_email: &str,
// ) -> Result<Person, Error>;
fn find_by_name(conn: &PgConnection, name: &str) -> Result<Person, Error>; fn find_by_name(conn: &PgConnection, name: &str) -> Result<Person, Error>;
fn mark_as_updated(conn: &PgConnection, person_id: i32) -> Result<Person, Error>; fn mark_as_updated(conn: &PgConnection, person_id: i32) -> Result<Person, Error>;
fn delete_account(conn: &PgConnection, person_id: i32) -> Result<Person, Error>; fn delete_account(conn: &PgConnection, person_id: i32) -> Result<Person, Error>;
} }
impl Person_ for Person { impl Person_ for Person {
fn ban_person(conn: &PgConnection, person_id: i32, ban: bool) -> Result<Self, Error> { fn ban_person(conn: &PgConnection, person_id: i32, ban: bool) -> Result<Self, Error> {
diesel::update(person.find(person_id)) diesel::update(person.find(person_id))
.set(banned.eq(ban)) .set(banned.eq(ban))
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
// TODO this needs to get moved to aggregates i think // TODO is this used?
// fn find_by_email_or_name(
// conn: &PgConnection,
// name_or_email: &str,
// ) -> Result<Self, Error> {
// if is_email_regex(name_or_email) {
// Self::find_by_email(conn, name_or_email)
// } else {
// Self::find_by_name(conn, name_or_email)
// }
// }
fn find_by_name(conn: &PgConnection, from_name: &str) -> Result<Person, Error> { fn find_by_name(conn: &PgConnection, from_name: &str) -> Result<Person, Error> {
person person
.filter(deleted.eq(false)) .filter(deleted.eq(false))

View file

@ -77,9 +77,9 @@ mod tests {
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::*, comment::*,
community::{Community, CommunityForm}, community::{Community, CommunityForm},
post::*,
person::*, person::*,
person_mention::*, person_mention::*,
post::*,
}; };
use serial_test::serial; use serial_test::serial;

View file

@ -139,12 +139,8 @@ impl PrivateMessage_ for PrivateMessage {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{establish_unpooled_connection, source::private_message::PrivateMessage_, Crud};
establish_unpooled_connection, use lemmy_db_schema::source::{person::*, private_message::*};
source::private_message::PrivateMessage_,
Crud,
};
use lemmy_db_schema::source::{private_message::*, person::*};
use serial_test::serial; use serial_test::serial;
#[test] #[test]

View file

@ -1,459 +0,0 @@
use crate::{is_email_regex, ApubObject, Crud, ToSafeSettings};
use bcrypt::{hash, DEFAULT_COST};
use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
naive_now,
schema::user_::dsl::*,
source::user::{UserForm, UserSafeSettings, User_},
DbUrl,
};
use lemmy_utils::settings::structs::Settings;
mod safe_type {
use crate::ToSafe;
use lemmy_db_schema::{schema::user_::columns::*, source::user::User_};
type Columns = (
id,
name,
preferred_username,
avatar,
admin,
banned,
published,
updated,
matrix_user_id,
actor_id,
bio,
local,
banner,
deleted,
inbox_url,
shared_inbox_url,
);
impl ToSafe for User_ {
type SafeColumns = Columns;
fn safe_columns_tuple() -> Self::SafeColumns {
(
id,
name,
preferred_username,
avatar,
admin,
banned,
published,
updated,
matrix_user_id,
actor_id,
bio,
local,
banner,
deleted,
inbox_url,
shared_inbox_url,
)
}
}
}
mod safe_type_alias_1 {
use crate::ToSafe;
use lemmy_db_schema::{schema::user_alias_1::columns::*, source::user::UserAlias1};
type Columns = (
id,
name,
preferred_username,
avatar,
admin,
banned,
published,
updated,
matrix_user_id,
actor_id,
bio,
local,
banner,
deleted,
);
impl ToSafe for UserAlias1 {
type SafeColumns = Columns;
fn safe_columns_tuple() -> Self::SafeColumns {
(
id,
name,
preferred_username,
avatar,
admin,
banned,
published,
updated,
matrix_user_id,
actor_id,
bio,
local,
banner,
deleted,
)
}
}
}
mod safe_type_alias_2 {
use crate::ToSafe;
use lemmy_db_schema::{schema::user_alias_2::columns::*, source::user::UserAlias2};
type Columns = (
id,
name,
preferred_username,
avatar,
admin,
banned,
published,
updated,
matrix_user_id,
actor_id,
bio,
local,
banner,
deleted,
);
impl ToSafe for UserAlias2 {
type SafeColumns = Columns;
fn safe_columns_tuple() -> Self::SafeColumns {
(
id,
name,
preferred_username,
avatar,
admin,
banned,
published,
updated,
matrix_user_id,
actor_id,
bio,
local,
banner,
deleted,
)
}
}
}
mod safe_settings_type {
use crate::ToSafeSettings;
use lemmy_db_schema::{schema::user_::columns::*, source::user::User_};
type Columns = (
id,
name,
preferred_username,
email,
avatar,
admin,
banned,
published,
updated,
show_nsfw,
theme,
default_sort_type,
default_listing_type,
lang,
show_avatars,
send_notifications_to_email,
matrix_user_id,
actor_id,
bio,
local,
last_refreshed_at,
banner,
deleted,
);
impl ToSafeSettings for User_ {
type SafeSettingsColumns = Columns;
fn safe_settings_columns_tuple() -> Self::SafeSettingsColumns {
(
id,
name,
preferred_username,
email,
avatar,
admin,
banned,
published,
updated,
show_nsfw,
theme,
default_sort_type,
default_listing_type,
lang,
show_avatars,
send_notifications_to_email,
matrix_user_id,
actor_id,
bio,
local,
last_refreshed_at,
banner,
deleted,
)
}
}
}
pub trait UserSafeSettings_ {
fn read(conn: &PgConnection, user_id: i32) -> Result<UserSafeSettings, Error>;
}
impl UserSafeSettings_ for UserSafeSettings {
fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
user_
.select(User_::safe_settings_columns_tuple())
.filter(deleted.eq(false))
.find(user_id)
.first::<Self>(conn)
}
}
impl Crud<UserForm> for User_ {
fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
user_
.filter(deleted.eq(false))
.find(user_id)
.first::<Self>(conn)
}
fn delete(conn: &PgConnection, user_id: i32) -> Result<usize, Error> {
diesel::delete(user_.find(user_id)).execute(conn)
}
fn create(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
insert_into(user_).values(form).get_result::<Self>(conn)
}
fn update(conn: &PgConnection, user_id: i32, form: &UserForm) -> Result<Self, Error> {
diesel::update(user_.find(user_id))
.set(form)
.get_result::<Self>(conn)
}
}
impl ApubObject<UserForm> for User_ {
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
use lemmy_db_schema::schema::user_::dsl::*;
user_
.filter(deleted.eq(false))
.filter(actor_id.eq(object_id))
.first::<Self>(conn)
}
fn upsert(conn: &PgConnection, user_form: &UserForm) -> Result<User_, Error> {
insert_into(user_)
.values(user_form)
.on_conflict(actor_id)
.do_update()
.set(user_form)
.get_result::<Self>(conn)
}
}
pub trait User {
fn register(conn: &PgConnection, form: &UserForm) -> Result<User_, Error>;
fn update_password(conn: &PgConnection, user_id: i32, new_password: &str)
-> Result<User_, Error>;
fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result<User_, Error>;
fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result<User_, Error>;
fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<User_, Error>;
fn find_by_email_or_username(
conn: &PgConnection,
username_or_email: &str,
) -> Result<User_, Error>;
fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error>;
fn get_profile_url(&self, hostname: &str) -> String;
fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
}
impl User for User_ {
fn register(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
let mut edited_user = form.clone();
let password_hash =
hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
edited_user.password_encrypted = password_hash;
Self::create(&conn, &edited_user)
}
// TODO do more individual updates like these
fn update_password(conn: &PgConnection, user_id: i32, new_password: &str) -> Result<Self, Error> {
let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password");
diesel::update(user_.find(user_id))
.set((
password_encrypted.eq(password_hash),
updated.eq(naive_now()),
))
.get_result::<Self>(conn)
}
fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result<Self, Error> {
user_
.filter(local.eq(true))
.filter(deleted.eq(false))
.filter(name.eq(from_user_name))
.first::<Self>(conn)
}
fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result<Self, Error> {
diesel::update(user_.find(user_id))
.set(admin.eq(added))
.get_result::<Self>(conn)
}
fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<Self, Error> {
diesel::update(user_.find(user_id))
.set(banned.eq(ban))
.get_result::<Self>(conn)
}
fn find_by_email_or_username(
conn: &PgConnection,
username_or_email: &str,
) -> Result<Self, Error> {
if is_email_regex(username_or_email) {
Self::find_by_email(conn, username_or_email)
} else {
Self::find_by_username(conn, username_or_email)
}
}
fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error> {
user_
.filter(deleted.eq(false))
.filter(local.eq(true))
.filter(name.ilike(username))
.first::<User_>(conn)
}
fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<User_, Error> {
user_
.filter(deleted.eq(false))
.filter(local.eq(true))
.filter(email.eq(from_email))
.first::<User_>(conn)
}
fn get_profile_url(&self, hostname: &str) -> String {
format!(
"{}://{}/u/{}",
Settings::get().get_protocol_string(),
hostname,
self.name
)
}
fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
diesel::update(user_.find(user_id))
.set((last_refreshed_at.eq(naive_now()),))
.get_result::<Self>(conn)
}
fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
diesel::update(user_.find(user_id))
.set((
preferred_username.eq::<Option<String>>(None),
email.eq::<Option<String>>(None),
matrix_user_id.eq::<Option<String>>(None),
bio.eq::<Option<String>>(None),
deleted.eq(true),
updated.eq(naive_now()),
))
.get_result::<Self>(conn)
}
}
#[cfg(test)]
mod tests {
use crate::{establish_unpooled_connection, source::user::*, ListingType, SortType};
use serial_test::serial;
#[test]
#[serial]
fn test_crud() {
let conn = establish_unpooled_connection();
let new_user = UserForm {
name: "thommy".into(),
preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None,
banner: None,
admin: false,
banned: Some(false),
published: None,
updated: None,
show_nsfw: false,
theme: "browser".into(),
default_sort_type: SortType::Hot as i16,
default_listing_type: ListingType::Subscribed as i16,
lang: "browser".into(),
show_avatars: true,
send_notifications_to_email: false,
actor_id: None,
bio: None,
local: true,
private_key: None,
public_key: None,
last_refreshed_at: None,
inbox_url: None,
shared_inbox_url: None,
};
let inserted_user = User_::create(&conn, &new_user).unwrap();
let expected_user = User_ {
id: inserted_user.id,
name: "thommy".into(),
preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None,
banner: None,
admin: false,
banned: false,
published: inserted_user.published,
updated: None,
show_nsfw: false,
theme: "browser".into(),
default_sort_type: SortType::Hot as i16,
default_listing_type: ListingType::Subscribed as i16,
lang: "browser".into(),
show_avatars: true,
send_notifications_to_email: false,
actor_id: inserted_user.actor_id.to_owned(),
bio: None,
local: true,
private_key: None,
public_key: None,
last_refreshed_at: inserted_user.published,
deleted: false,
inbox_url: inserted_user.inbox_url.to_owned(),
shared_inbox_url: None,
};
let read_user = User_::read(&conn, inserted_user.id).unwrap();
let updated_user = User_::update(&conn, inserted_user.id, &new_user).unwrap();
let num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
assert_eq!(expected_user, read_user);
assert_eq!(expected_user, inserted_user);
assert_eq!(expected_user, updated_user);
assert_eq!(1, num_deleted);
}
}

View file

@ -40,7 +40,7 @@ pub struct LocalUserForm {
/// A local user view that removes password encrypted /// A local user view that removes password encrypted
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "local_user"] #[table_name = "local_user"]
pub struct LocalUserSettings{ pub struct LocalUserSettings {
pub id: i32, pub id: i32,
pub person_id: i32, pub person_id: i32,
pub email: Option<String>, pub email: Option<String>,

View file

@ -2,12 +2,12 @@ pub mod activity;
pub mod comment; pub mod comment;
pub mod comment_report; pub mod comment_report;
pub mod community; pub mod community;
pub mod local_user;
pub mod moderator; pub mod moderator;
pub mod password_reset_request; pub mod password_reset_request;
pub mod person;
pub mod person_mention;
pub mod post; pub mod post;
pub mod post_report; pub mod post_report;
pub mod private_message; pub mod private_message;
pub mod site; pub mod site;
pub mod person;
pub mod person_mention;
pub mod local_user;

View file

@ -46,7 +46,6 @@ pub struct PersonSafe {
pub shared_inbox_url: Option<DbUrl>, pub shared_inbox_url: Option<DbUrl>,
} }
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "person_alias_1"] #[table_name = "person_alias_1"]
pub struct PersonAlias1 { pub struct PersonAlias1 {

View file

@ -1,220 +0,0 @@
use crate::{
schema::{user_, user_alias_1, user_alias_2},
DbUrl,
};
use serde::Serialize;
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_"]
pub struct User_ {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub password_encrypted: String,
pub email: Option<String>,
pub avatar: Option<DbUrl>,
pub admin: bool,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
pub show_nsfw: bool,
pub theme: String,
pub default_sort_type: i16,
pub default_listing_type: i16,
pub lang: String,
pub show_avatars: bool,
pub send_notifications_to_email: bool,
pub matrix_user_id: Option<String>,
pub actor_id: DbUrl,
pub bio: Option<String>,
pub local: bool,
pub private_key: Option<String>,
pub public_key: Option<String>,
pub last_refreshed_at: chrono::NaiveDateTime,
pub banner: Option<DbUrl>,
pub deleted: bool,
pub inbox_url: DbUrl,
pub shared_inbox_url: Option<DbUrl>,
}
/// A safe representation of user, without the sensitive info
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_"]
pub struct UserSafe {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub admin: bool,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
pub matrix_user_id: Option<String>,
pub actor_id: DbUrl,
pub bio: Option<String>,
pub local: bool,
pub banner: Option<DbUrl>,
pub deleted: bool,
pub inbox_url: DbUrl,
pub shared_inbox_url: Option<DbUrl>,
}
/// A safe user view with only settings
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_"]
pub struct UserSafeSettings {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub email: Option<String>,
pub avatar: Option<DbUrl>,
pub admin: bool,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
pub show_nsfw: bool,
pub theme: String,
pub default_sort_type: i16,
pub default_listing_type: i16,
pub lang: String,
pub show_avatars: bool,
pub send_notifications_to_email: bool,
pub matrix_user_id: Option<String>,
pub actor_id: DbUrl,
pub bio: Option<String>,
pub local: bool,
pub last_refreshed_at: chrono::NaiveDateTime,
pub banner: Option<DbUrl>,
pub deleted: bool,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_alias_1"]
pub struct UserAlias1 {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub password_encrypted: String,
pub email: Option<String>,
pub avatar: Option<DbUrl>,
pub admin: bool,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
pub show_nsfw: bool,
pub theme: String,
pub default_sort_type: i16,
pub default_listing_type: i16,
pub lang: String,
pub show_avatars: bool,
pub send_notifications_to_email: bool,
pub matrix_user_id: Option<String>,
pub actor_id: DbUrl,
pub bio: Option<String>,
pub local: bool,
pub private_key: Option<String>,
pub public_key: Option<String>,
pub last_refreshed_at: chrono::NaiveDateTime,
pub banner: Option<DbUrl>,
pub deleted: bool,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_alias_1"]
pub struct UserSafeAlias1 {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub admin: bool,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
pub matrix_user_id: Option<String>,
pub actor_id: DbUrl,
pub bio: Option<String>,
pub local: bool,
pub banner: Option<DbUrl>,
pub deleted: bool,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_alias_2"]
pub struct UserAlias2 {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub password_encrypted: String,
pub email: Option<String>,
pub avatar: Option<DbUrl>,
pub admin: bool,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
pub show_nsfw: bool,
pub theme: String,
pub default_sort_type: i16,
pub default_listing_type: i16,
pub lang: String,
pub show_avatars: bool,
pub send_notifications_to_email: bool,
pub matrix_user_id: Option<String>,
pub actor_id: DbUrl,
pub bio: Option<String>,
pub local: bool,
pub private_key: Option<String>,
pub public_key: Option<String>,
pub last_refreshed_at: chrono::NaiveDateTime,
pub banner: Option<DbUrl>,
pub deleted: bool,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_alias_2"]
pub struct UserSafeAlias2 {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub admin: bool,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
pub matrix_user_id: Option<String>,
pub actor_id: DbUrl,
pub bio: Option<String>,
pub local: bool,
pub banner: Option<DbUrl>,
pub deleted: bool,
}
#[derive(Insertable, AsChangeset, Clone)]
#[table_name = "user_"]
pub struct UserForm {
pub name: String,
pub preferred_username: Option<Option<String>>,
pub password_encrypted: String,
pub admin: bool,
pub banned: Option<bool>,
pub email: Option<Option<String>>,
pub avatar: Option<Option<DbUrl>>,
pub published: Option<chrono::NaiveDateTime>,
pub updated: Option<chrono::NaiveDateTime>,
pub show_nsfw: bool,
pub theme: String,
pub default_sort_type: i16,
pub default_listing_type: i16,
pub lang: String,
pub show_avatars: bool,
pub send_notifications_to_email: bool,
pub matrix_user_id: Option<Option<String>>,
pub actor_id: Option<DbUrl>,
pub bio: Option<Option<String>>,
pub local: bool,
pub private_key: Option<String>,
pub public_key: Option<String>,
pub last_refreshed_at: Option<chrono::NaiveDateTime>,
pub banner: Option<Option<DbUrl>>,
pub inbox_url: Option<DbUrl>,
pub shared_inbox_url: Option<Option<DbUrl>>,
}

View file

@ -1,13 +1,13 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec}; use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{comment, comment_report, community, post, person, person_alias_1, person_alias_2}, schema::{comment, comment_report, community, person, person_alias_1, person_alias_2, post},
source::{ source::{
comment::Comment, comment::Comment,
comment_report::CommentReport, comment_report::CommentReport,
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2},
post::Post, post::Post,
person::{PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2, Person},
}, },
}; };
use serde::Serialize; use serde::Serialize;

View file

@ -20,15 +20,15 @@ use lemmy_db_schema::{
community, community,
community_follower, community_follower,
community_person_ban, community_person_ban,
post,
person, person,
person_alias_1, person_alias_1,
post,
}, },
source::{ source::{
comment::{Comment, CommentAlias1, CommentSaved}, comment::{Comment, CommentAlias1, CommentSaved},
community::{Community, CommunityFollower, CommunitySafe, CommunityPersonBan}, community::{Community, CommunityFollower, CommunityPersonBan, CommunitySafe},
person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
post::Post, post::Post,
person::{PersonAlias1, PersonSafe, PersonSafeAlias1, Person},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -440,7 +440,7 @@ mod tests {
Crud, Crud,
Likeable, Likeable,
}; };
use lemmy_db_schema::source::{comment::*, community::*, post::*, person::*}; use lemmy_db_schema::source::{comment::*, community::*, person::*, post::*};
use serial_test::serial; use serial_test::serial;
#[test] #[test]
@ -646,7 +646,10 @@ mod tests {
Community::delete(&conn, inserted_community.id).unwrap(); Community::delete(&conn, inserted_community.id).unwrap();
Person::delete(&conn, inserted_person.id).unwrap(); Person::delete(&conn, inserted_person.id).unwrap();
assert_eq!(expected_comment_view_no_person, read_comment_views_no_person[0]); assert_eq!(
expected_comment_view_no_person,
read_comment_views_no_person[0]
);
assert_eq!( assert_eq!(
expected_comment_view_with_person, expected_comment_view_with_person,
read_comment_views_with_person[0] read_comment_views_with_person[0]

View file

@ -3,8 +3,8 @@ extern crate serial_test;
pub mod comment_report_view; pub mod comment_report_view;
pub mod comment_view; pub mod comment_view;
pub mod local_user_view;
pub mod post_report_view; pub mod post_report_view;
pub mod post_view; pub mod post_view;
pub mod private_message_view; pub mod private_message_view;
pub mod site_view; pub mod site_view;
pub mod local_user_view;

View file

@ -1,13 +1,11 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{ use lemmy_db_queries::{aggregates::person_aggregates::PersonAggregates, ToSafe, ToSafeSettings};
aggregates::person_aggregates::PersonAggregates,
ToSafe,
ToSafeSettings,
};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{person, person_aggregates, local_user}, schema::{local_user, person, person_aggregates},
source::person::{PersonSafe, Person}, source::{
source::local_user::{LocalUser, LocalUserSettings}, local_user::{LocalUser, LocalUserSettings},
person::{Person, PersonSafe},
},
}; };
use serde::Serialize; use serde::Serialize;
@ -21,14 +19,22 @@ pub struct LocalUserView {
type LocalUserViewTuple = (Person, PersonAggregates, LocalUser); type LocalUserViewTuple = (Person, PersonAggregates, LocalUser);
impl LocalUserView { impl LocalUserView {
pub fn read(conn: &PgConnection, person_id: i32) -> Result<Self, Error> { pub fn read_person(conn: &PgConnection, person_id: i32) -> Result<Self, Error> {
let (person, counts, local_user) = person::table let (person, counts, local_user) = person::table
.find(person_id) .find(person_id)
.inner_join(person_aggregates::table) .inner_join(person_aggregates::table)
.inner_join(local_user::table) .inner_join(local_user::table)
.select((person::all_columns, person_aggregates::all_columns, local_user::all_columns)) .select((
person::all_columns,
person_aggregates::all_columns,
local_user::all_columns,
))
.first::<LocalUserViewTuple>(conn)?; .first::<LocalUserViewTuple>(conn)?;
Ok(Self { person, counts, local_user }) Ok(Self {
person,
counts,
local_user,
})
} }
// TODO check where this is used // TODO check where this is used
@ -37,22 +43,57 @@ impl LocalUserView {
.filter(person::name.eq(name)) .filter(person::name.eq(name))
.inner_join(person_aggregates::table) .inner_join(person_aggregates::table)
.inner_join(local_user::table) .inner_join(local_user::table)
.select((person::all_columns, person_aggregates::all_columns, local_user::all_columns)) .select((
person::all_columns,
person_aggregates::all_columns,
local_user::all_columns,
))
.first::<LocalUserViewTuple>(conn)?; .first::<LocalUserViewTuple>(conn)?;
Ok(Self { person, counts, local_user }) Ok(Self {
person,
counts,
local_user,
})
} }
pub fn find_by_email_or_name( pub fn find_by_email_or_name(conn: &PgConnection, name_or_email: &str) -> Result<Self, Error> {
conn: &PgConnection,
name_or_email: &str,
) -> Result<Self, Error> {
let (person, counts, local_user) = person::table let (person, counts, local_user) = person::table
.inner_join(person_aggregates::table) .inner_join(person_aggregates::table)
.inner_join(local_user::table) .inner_join(local_user::table)
.filter(person::name.ilike(name_or_email).or(local_user::email.ilike(name_or_email))) .filter(
.select((person::all_columns, person_aggregates::all_columns, local_user::all_columns)) person::name
.ilike(name_or_email)
.or(local_user::email.ilike(name_or_email)),
)
.select((
person::all_columns,
person_aggregates::all_columns,
local_user::all_columns,
))
.first::<LocalUserViewTuple>(conn)?; .first::<LocalUserViewTuple>(conn)?;
Ok(Self { person, counts, local_user }) Ok(Self {
person,
counts,
local_user,
})
}
pub fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<Self, Error> {
let (person, counts, local_user) = person::table
.inner_join(person_aggregates::table)
.inner_join(local_user::table)
.filter(local_user::email.eq(from_email))
.select((
person::all_columns,
person_aggregates::all_columns,
local_user::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
Ok(Self {
person,
counts,
local_user,
})
} }
} }
@ -71,8 +112,16 @@ impl LocalUserSettingsView {
.find(person_id) .find(person_id)
.inner_join(person_aggregates::table) .inner_join(person_aggregates::table)
.inner_join(local_user::table) .inner_join(local_user::table)
.select((Person::safe_columns_tuple(), person_aggregates::all_columns, LocalUser::safe_settings_columns_tuple())) .select((
Person::safe_columns_tuple(),
person_aggregates::all_columns,
LocalUser::safe_settings_columns_tuple(),
))
.first::<LocalUserSettingsViewTuple>(conn)?; .first::<LocalUserSettingsViewTuple>(conn)?;
Ok(Self { person, counts, local_user }) Ok(Self {
person,
counts,
local_user,
})
} }
} }

View file

@ -1,12 +1,12 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec}; use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{community, post, post_report, person, person_alias_1, person_alias_2}, schema::{community, person, person_alias_1, person_alias_2, post, post_report},
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2},
post::Post, post::Post,
post_report::PostReport, post_report::PostReport,
person::{PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2, Person},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -41,7 +41,9 @@ impl PostReportView {
.inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(person::table.on(post_report::creator_id.eq(person::id))) .inner_join(person::table.on(post_report::creator_id.eq(person::id)))
.inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id))) .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id)))
.left_join(person_alias_2::table.on(post_report::resolver_id.eq(person_alias_2::id.nullable()))) .left_join(
person_alias_2::table.on(post_report::resolver_id.eq(person_alias_2::id.nullable())),
)
.select(( .select((
post_report::all_columns, post_report::all_columns,
post::all_columns, post::all_columns,
@ -126,7 +128,9 @@ impl<'a> PostReportQueryBuilder<'a> {
.inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(person::table.on(post_report::creator_id.eq(person::id))) .inner_join(person::table.on(post_report::creator_id.eq(person::id)))
.inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id))) .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id)))
.left_join(person_alias_2::table.on(post_report::resolver_id.eq(person_alias_2::id.nullable()))) .left_join(
person_alias_2::table.on(post_report::resolver_id.eq(person_alias_2::id.nullable())),
)
.select(( .select((
post_report::all_columns, post_report::all_columns,
post::all_columns, post::all_columns,

View file

@ -15,17 +15,17 @@ use lemmy_db_schema::{
community, community,
community_follower, community_follower,
community_person_ban, community_person_ban,
person,
post, post,
post_aggregates, post_aggregates,
post_like, post_like,
post_read, post_read,
post_saved, post_saved,
person,
}, },
source::{ source::{
community::{Community, CommunityFollower, CommunitySafe, CommunityPersonBan}, community::{Community, CommunityFollower, CommunityPersonBan, CommunitySafe},
person::{Person, PersonSafe},
post::{Post, PostRead, PostSaved}, post::{Post, PostRead, PostSaved},
person::{PersonSafe, Person},
}, },
}; };
use log::debug; use log::debug;
@ -433,7 +433,7 @@ mod tests {
ListingType, ListingType,
SortType, SortType,
}; };
use lemmy_db_schema::source::{community::*, post::*, person::*}; use lemmy_db_schema::source::{community::*, person::*, post::*};
use serial_test::serial; use serial_test::serial;
#[test] #[test]
@ -638,11 +638,17 @@ mod tests {
expected_post_listing_with_user, expected_post_listing_with_user,
read_post_listings_with_person[0] read_post_listings_with_person[0]
); );
assert_eq!(expected_post_listing_with_user, read_post_listing_with_person); assert_eq!(
expected_post_listing_with_user,
read_post_listing_with_person
);
assert_eq!(1, read_post_listings_with_person.len()); assert_eq!(1, read_post_listings_with_person.len());
// Without the user // Without the user
assert_eq!(expected_post_listing_no_person, read_post_listings_no_person[0]); assert_eq!(
expected_post_listing_no_person,
read_post_listings_no_person[0]
);
assert_eq!(expected_post_listing_no_person, read_post_listing_no_person); assert_eq!(expected_post_listing_no_person, read_post_listing_no_person);
assert_eq!(1, read_post_listings_no_person.len()); assert_eq!(1, read_post_listings_no_person.len());

View file

@ -1,10 +1,10 @@
use diesel::{pg::Pg, result::Error, *}; use diesel::{pg::Pg, result::Error, *};
use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec}; use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{private_message, person, person_alias_1}, schema::{person, person_alias_1, private_message},
source::{ source::{
person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
private_message::PrivateMessage, private_message::PrivateMessage,
person::{PersonAlias1, PersonSafe, PersonSafeAlias1, Person},
}, },
}; };
use log::debug; use log::debug;

View file

@ -1,10 +1,10 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{aggregates::site_aggregates::SiteAggregates, ToSafe}; use lemmy_db_queries::{aggregates::site_aggregates::SiteAggregates, ToSafe};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{site, site_aggregates, person}, schema::{person, site, site_aggregates},
source::{ source::{
person::{Person, PersonSafe},
site::Site, site::Site,
person::{PersonSafe, Person},
}, },
}; };
use serde::Serialize; use serde::Serialize;

View file

@ -4,7 +4,7 @@ use lemmy_db_schema::{
schema::{community, community_follower, person}, schema::{community, community_follower, person},
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
person::{PersonSafe, Person}, person::{Person, PersonSafe},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -22,7 +22,10 @@ impl CommunityFollowerView {
let res = community_follower::table let res = community_follower::table
.inner_join(community::table) .inner_join(community::table)
.inner_join(person::table) .inner_join(person::table)
.select((Community::safe_columns_tuple(), Person::safe_columns_tuple())) .select((
Community::safe_columns_tuple(),
Person::safe_columns_tuple(),
))
.filter(community_follower::community_id.eq(community_id)) .filter(community_follower::community_id.eq(community_id))
.order_by(community_follower::published) .order_by(community_follower::published)
.load::<CommunityFollowerViewTuple>(conn)?; .load::<CommunityFollowerViewTuple>(conn)?;
@ -34,7 +37,10 @@ impl CommunityFollowerView {
let res = community_follower::table let res = community_follower::table
.inner_join(community::table) .inner_join(community::table)
.inner_join(person::table) .inner_join(person::table)
.select((Community::safe_columns_tuple(), Person::safe_columns_tuple())) .select((
Community::safe_columns_tuple(),
Person::safe_columns_tuple(),
))
.filter(community_follower::person_id.eq(person_id)) .filter(community_follower::person_id.eq(person_id))
.order_by(community_follower::published) .order_by(community_follower::published)
.load::<CommunityFollowerViewTuple>(conn)?; .load::<CommunityFollowerViewTuple>(conn)?;

View file

@ -4,7 +4,7 @@ use lemmy_db_schema::{
schema::{community, community_moderator, person}, schema::{community, community_moderator, person},
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
person::{PersonSafe, Person}, person::{Person, PersonSafe},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -22,7 +22,10 @@ impl CommunityModeratorView {
let res = community_moderator::table let res = community_moderator::table
.inner_join(community::table) .inner_join(community::table)
.inner_join(person::table) .inner_join(person::table)
.select((Community::safe_columns_tuple(), Person::safe_columns_tuple())) .select((
Community::safe_columns_tuple(),
Person::safe_columns_tuple(),
))
.filter(community_moderator::community_id.eq(community_id)) .filter(community_moderator::community_id.eq(community_id))
.order_by(community_moderator::published) .order_by(community_moderator::published)
.load::<CommunityModeratorViewTuple>(conn)?; .load::<CommunityModeratorViewTuple>(conn)?;
@ -34,7 +37,10 @@ impl CommunityModeratorView {
let res = community_moderator::table let res = community_moderator::table
.inner_join(community::table) .inner_join(community::table)
.inner_join(person::table) .inner_join(person::table)
.select((Community::safe_columns_tuple(), Person::safe_columns_tuple())) .select((
Community::safe_columns_tuple(),
Person::safe_columns_tuple(),
))
.filter(community_moderator::person_id.eq(person_id)) .filter(community_moderator::person_id.eq(person_id))
.order_by(community_moderator::published) .order_by(community_moderator::published)
.load::<CommunityModeratorViewTuple>(conn)?; .load::<CommunityModeratorViewTuple>(conn)?;

View file

@ -4,7 +4,7 @@ use lemmy_db_schema::{
schema::{community, community_person_ban, person}, schema::{community, community_person_ban, person},
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
person::{PersonSafe, Person}, person::{Person, PersonSafe},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -24,7 +24,10 @@ impl CommunityPersonBanView {
let (community, person) = community_person_ban::table let (community, person) = community_person_ban::table
.inner_join(community::table) .inner_join(community::table)
.inner_join(person::table) .inner_join(person::table)
.select((Community::safe_columns_tuple(), Person::safe_columns_tuple())) .select((
Community::safe_columns_tuple(),
Person::safe_columns_tuple(),
))
.filter(community_person_ban::community_id.eq(from_community_id)) .filter(community_person_ban::community_id.eq(from_community_id))
.filter(community_person_ban::person_id.eq(from_person_id)) .filter(community_person_ban::person_id.eq(from_person_id))
.order_by(community_person_ban::published) .order_by(community_person_ban::published)

View file

@ -15,7 +15,7 @@ use lemmy_db_schema::{
schema::{community, community_aggregates, community_follower, person}, schema::{community, community_aggregates, community_follower, person},
source::{ source::{
community::{Community, CommunityFollower, CommunitySafe}, community::{Community, CommunityFollower, CommunitySafe},
person::{PersonSafe, Person}, person::{Person, PersonSafe},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -78,8 +78,9 @@ impl CommunityView {
&mut CommunityModeratorView::for_community(conn, community_id) &mut CommunityModeratorView::for_community(conn, community_id)
.map(|v| v.into_iter().map(|m| m.moderator.id).collect())?, .map(|v| v.into_iter().map(|m| m.moderator.id).collect())?,
); );
mods_and_admins mods_and_admins.append(
.append(&mut PersonViewSafe::admins(conn).map(|v| v.into_iter().map(|a| a.person.id).collect())?); &mut PersonViewSafe::admins(conn).map(|v| v.into_iter().map(|a| a.person.id).collect())?,
);
Ok(mods_and_admins) Ok(mods_and_admins)
} }

View file

@ -17,17 +17,17 @@ use lemmy_db_schema::{
community, community,
community_follower, community_follower,
community_person_ban, community_person_ban,
post,
person, person,
person_alias_1, person_alias_1,
person_mention, person_mention,
post,
}, },
source::{ source::{
comment::{Comment, CommentSaved}, comment::{Comment, CommentSaved},
community::{Community, CommunityFollower, CommunitySafe, CommunityPersonBan}, community::{Community, CommunityFollower, CommunityPersonBan, CommunitySafe},
post::Post, person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
person::{PersonAlias1, PersonSafe, PersonSafeAlias1, Person},
person_mention::PersonMention, person_mention::PersonMention,
post::Post,
}, },
}; };
use serde::Serialize; use serde::Serialize;

View file

@ -9,8 +9,8 @@ use lemmy_db_queries::{
ViewToVec, ViewToVec,
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{person, person_aggregates, local_user}, schema::{local_user, person, person_aggregates},
source::person::{PersonSafe, Person}, source::person::{Person, PersonSafe},
}; };
use serde::Serialize; use serde::Serialize;

View file

@ -5,7 +5,7 @@ use lemmy_db_schema::{
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
moderator::ModAddCommunity, moderator::ModAddCommunity,
person::{PersonAlias1, PersonSafe, PersonSafeAlias1, Person}, person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -31,7 +31,9 @@ impl ModAddCommunityView {
let mut query = mod_add_community::table let mut query = mod_add_community::table
.inner_join(person::table.on(mod_add_community::mod_person_id.eq(person::id))) .inner_join(person::table.on(mod_add_community::mod_person_id.eq(person::id)))
.inner_join(community::table) .inner_join(community::table)
.inner_join(person_alias_1::table.on(mod_add_community::other_person_id.eq(person_alias_1::id))) .inner_join(
person_alias_1::table.on(mod_add_community::other_person_id.eq(person_alias_1::id)),
)
.select(( .select((
mod_add_community::all_columns, mod_add_community::all_columns,
Person::safe_columns_tuple(), Person::safe_columns_tuple(),

View file

@ -4,7 +4,7 @@ use lemmy_db_schema::{
schema::{mod_add, person, person_alias_1}, schema::{mod_add, person, person_alias_1},
source::{ source::{
moderator::ModAdd, moderator::ModAdd,
person::{PersonAlias1, PersonSafe, PersonSafeAlias1, Person}, person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
}, },
}; };
use serde::Serialize; use serde::Serialize;

View file

@ -5,7 +5,7 @@ use lemmy_db_schema::{
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
moderator::ModBanFromCommunity, moderator::ModBanFromCommunity,
person::{PersonAlias1, PersonSafe, PersonSafeAlias1, Person}, person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -18,7 +18,12 @@ pub struct ModBanFromCommunityView {
pub banned_person: PersonSafeAlias1, pub banned_person: PersonSafeAlias1,
} }
type ModBanFromCommunityViewTuple = (ModBanFromCommunity, PersonSafe, CommunitySafe, PersonSafeAlias1); type ModBanFromCommunityViewTuple = (
ModBanFromCommunity,
PersonSafe,
CommunitySafe,
PersonSafeAlias1,
);
impl ModBanFromCommunityView { impl ModBanFromCommunityView {
pub fn list( pub fn list(

View file

@ -4,7 +4,7 @@ use lemmy_db_schema::{
schema::{mod_ban, person, person_alias_1}, schema::{mod_ban, person, person_alias_1},
source::{ source::{
moderator::ModBan, moderator::ModBan,
person::{PersonAlias1, PersonSafe, PersonSafeAlias1, Person}, person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
}, },
}; };
use serde::Serialize; use serde::Serialize;

View file

@ -1,12 +1,12 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{community, mod_lock_post, post, person}, schema::{community, mod_lock_post, person, post},
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
moderator::ModLockPost, moderator::ModLockPost,
person::{Person, PersonSafe},
post::Post, post::Post,
person::{PersonSafe, Person},
}, },
}; };
use serde::Serialize; use serde::Serialize;

View file

@ -1,13 +1,13 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{comment, community, mod_remove_comment, post, person, person_alias_1}, schema::{comment, community, mod_remove_comment, person, person_alias_1, post},
source::{ source::{
comment::Comment, comment::Comment,
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
moderator::ModRemoveComment, moderator::ModRemoveComment,
person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
post::Post, post::Post,
person::{PersonAlias1, PersonSafe, PersonSafeAlias1, Person},
}, },
}; };
use serde::Serialize; use serde::Serialize;

View file

@ -5,7 +5,7 @@ use lemmy_db_schema::{
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
moderator::ModRemoveCommunity, moderator::ModRemoveCommunity,
person::{PersonSafe, Person}, person::{Person, PersonSafe},
}, },
}; };
use serde::Serialize; use serde::Serialize;

View file

@ -1,12 +1,12 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{community, mod_remove_post, post, person}, schema::{community, mod_remove_post, person, post},
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
moderator::ModRemovePost, moderator::ModRemovePost,
person::{Person, PersonSafe},
post::Post, post::Post,
person::{PersonSafe, Person},
}, },
}; };
use serde::Serialize; use serde::Serialize;

View file

@ -1,12 +1,12 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{community, mod_sticky_post, post, person}, schema::{community, mod_sticky_post, person, post},
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
moderator::ModStickyPost, moderator::ModStickyPost,
person::{Person, PersonSafe},
post::Post, post::Post,
person::{PersonSafe, Person},
}, },
}; };
use serde::Serialize; use serde::Serialize;

View file

@ -19,9 +19,9 @@ use lemmy_db_schema::{
source::{ source::{
comment::Comment, comment::Comment,
community::{Community, CommunityForm}, community::{Community, CommunityForm},
person::{Person, PersonForm},
post::Post, post::Post,
private_message::PrivateMessage, private_message::PrivateMessage,
user::{UserForm, User_},
}, },
}; };
use lemmy_utils::{apub::generate_actor_keypair, settings::structs::Settings, LemmyError}; use lemmy_utils::{apub::generate_actor_keypair, settings::structs::Settings, LemmyError};
@ -40,52 +40,42 @@ pub fn run_advanced_migrations(conn: &PgConnection) -> Result<(), LemmyError> {
} }
fn user_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> { fn user_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> {
use lemmy_db_schema::schema::user_::dsl::*; use lemmy_db_schema::schema::person::dsl::*;
info!("Running user_updates_2020_04_02"); info!("Running user_updates_2020_04_02");
// Update the actor_id, private_key, and public_key, last_refreshed_at // Update the actor_id, private_key, and public_key, last_refreshed_at
let incorrect_users = user_ let incorrect_persons = person
.filter(actor_id.like("http://changeme_%")) .filter(actor_id.like("http://changeme_%"))
.filter(local.eq(true)) .filter(local.eq(true))
.load::<User_>(conn)?; .load::<Person>(conn)?;
for cuser in &incorrect_users { for cperson in &incorrect_persons {
let keypair = generate_actor_keypair()?; let keypair = generate_actor_keypair()?;
let form = UserForm { let form = PersonForm {
name: cuser.name.to_owned(), name: cperson.name.to_owned(),
email: Some(cuser.email.to_owned()), avatar: None,
matrix_user_id: Some(cuser.matrix_user_id.to_owned()), banner: None,
avatar: Some(cuser.avatar.to_owned()), preferred_username: None,
banner: Some(cuser.banner.to_owned()), published: None,
password_encrypted: cuser.password_encrypted.to_owned(),
preferred_username: Some(cuser.preferred_username.to_owned()),
published: Some(cuser.published),
updated: None, updated: None,
admin: cuser.admin, banned: None,
banned: Some(cuser.banned), deleted: None,
show_nsfw: cuser.show_nsfw, actor_id: Some(generate_apub_endpoint(EndpointType::Person, &cperson.name)?),
theme: cuser.theme.to_owned(), bio: None,
default_sort_type: cuser.default_sort_type, local: None,
default_listing_type: cuser.default_listing_type, private_key: Some(Some(keypair.private_key)),
lang: cuser.lang.to_owned(), public_key: Some(Some(keypair.public_key)),
show_avatars: cuser.show_avatars,
send_notifications_to_email: cuser.send_notifications_to_email,
actor_id: Some(generate_apub_endpoint(EndpointType::Person, &cuser.name)?),
bio: Some(cuser.bio.to_owned()),
local: cuser.local,
private_key: Some(keypair.private_key),
public_key: Some(keypair.public_key),
last_refreshed_at: Some(naive_now()), last_refreshed_at: Some(naive_now()),
inbox_url: None, inbox_url: None,
shared_inbox_url: None, shared_inbox_url: None,
}; };
User_::update(&conn, cuser.id, &form)?; Person::update(&conn, cperson.id, &form)?;
} }
info!("{} user rows updated.", incorrect_users.len()); info!("{} person rows updated.", incorrect_persons.len());
Ok(()) Ok(())
} }
@ -231,20 +221,20 @@ fn post_thumbnail_url_updates_2020_07_27(conn: &PgConnection) -> Result<(), Lemm
fn apub_columns_2021_02_02(conn: &PgConnection) -> Result<(), LemmyError> { fn apub_columns_2021_02_02(conn: &PgConnection) -> Result<(), LemmyError> {
info!("Running apub_columns_2021_02_02"); info!("Running apub_columns_2021_02_02");
{ {
use lemmy_db_schema::schema::user_::dsl::*; use lemmy_db_schema::schema::person::dsl::*;
let users = user_ let persons = person
.filter(inbox_url.like("http://changeme_%")) .filter(inbox_url.like("http://changeme_%"))
.load::<User_>(conn)?; .load::<Person>(conn)?;
for u in &users { for p in &persons {
let inbox_url_ = generate_inbox_url(&u.actor_id)?; let inbox_url_ = generate_inbox_url(&p.actor_id)?;
let shared_inbox_url_ = generate_shared_inbox_url(&u.actor_id)?; let shared_inbox_url_ = generate_shared_inbox_url(&p.actor_id)?;
diesel::update(user_.find(u.id)) diesel::update(person.find(p.id))
.set(( .set((
inbox_url.eq(inbox_url_), inbox_url.eq(inbox_url_),
shared_inbox_url.eq(shared_inbox_url_), shared_inbox_url.eq(shared_inbox_url_),
)) ))
.get_result::<User_>(conn)?; .get_result::<Person>(conn)?;
} }
} }