A first pass.

pull/1428/head
Dessalines 3 years ago
parent ddf4a667b1
commit 9cb4dad4b4

@ -2,9 +2,9 @@ use crate::{
check_community_ban,
check_downvotes_enabled,
collect_moderated_communities,
get_post,
get_local_user_view_from_jwt,
get_local_user_view_from_jwt_opt,
get_post,
is_mod_or_admin,
Perform,
};
@ -115,7 +115,9 @@ impl Perform for CreateComment {
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
let post_id = post.id;
@ -143,7 +145,9 @@ impl Perform for CreateComment {
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 mut comment_view = blocking(context.pool(), move |conn| {
@ -201,7 +205,12 @@ impl Perform for EditComment {
})
.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
if local_user_view.person.id != orig_comment.creator.id {
@ -221,7 +230,9 @@ impl Perform for EditComment {
};
// 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
let updated_comment_content = updated_comment.content.to_owned();
@ -277,7 +288,12 @@ impl Perform for DeleteComment {
})
.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
if local_user_view.person.id != orig_comment.creator.id {
@ -297,9 +313,13 @@ impl Perform for DeleteComment {
// Send the apub message
if deleted {
updated_comment.send_delete(&local_user_view.person, context).await?;
updated_comment
.send_delete(&local_user_view.person, context)
.await?;
} 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
@ -357,10 +377,20 @@ impl Perform for RemoveComment {
})
.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
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
let removed = data.removed;
@ -387,9 +417,13 @@ impl Perform for RemoveComment {
// Send the apub message
if removed {
updated_comment.send_remove(&local_user_view.person, context).await?;
updated_comment
.send_remove(&local_user_view.person, context)
.await?;
} 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
@ -448,7 +482,12 @@ impl Perform for MarkCommentAsRead {
})
.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
if local_user_view.person.id != orig_comment.get_recipient_id() {
@ -551,7 +590,12 @@ impl Perform for CreateCommentLike {
})
.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
recipient_ids.push(orig_comment.get_recipient_id());
@ -583,10 +627,14 @@ impl Perform for CreateCommentLike {
if like_form.score == 1 {
comment.send_like(&local_user_view.person, context).await?;
} 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 {
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

@ -517,9 +517,15 @@ impl Perform for FollowCommunity {
} else if data.follow {
// Dont actually add to the community followers here, because you need
// 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 {
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);
if blocking(context.pool(), unfollow).await?.is_err() {
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
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());
}

@ -3,17 +3,15 @@ use lemmy_api_structs::{
blocking,
comment::*,
community::*,
person::*,
post::*,
site::*,
person::*,
websocket::*,
};
use lemmy_db_queries::{
source::{
community::{CommunityModerator_, Community_},
site::Site_,
local_user::LocalUserSettings_,
local_user::LocalUser_,
},
Crud,
DbPool,
@ -22,15 +20,12 @@ use lemmy_db_schema::source::{
community::{Community, CommunityModerator},
post::Post,
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::{
community_person_ban_view::CommunityPersonBanView,
community_view::CommunityView,
};
use lemmy_db_views::local_user_view::{LocalUserView, LocalUserSettingsView};
use lemmy_utils::{
claims::Claims,
settings::structs::Settings,
@ -45,10 +40,10 @@ use url::Url;
pub mod comment;
pub mod community;
pub mod local_user;
pub mod post;
pub mod routes;
pub mod site;
pub mod user;
pub mod websocket;
#[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) {
Ok(claims) => claims.claims,
Err(_e) => return Err(ApiError::err("not_logged_in").into()),
};
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
if local_user_view.person.banned {
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) {
Ok(claims) => claims.claims,
Err(_e) => return Err(ApiError::err("not_logged_in").into()),
};
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
if local_user_view.person.banned {
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,
) -> Result<Option<LocalUserSettingsView>, LemmyError> {
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),
}
}
@ -153,7 +162,8 @@ pub(crate) async fn check_community_ban(
community_id: i32,
pool: &DbPool,
) -> 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? {
Err(ApiError::err("community_ban").into())
} else {

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

@ -122,7 +122,9 @@ impl Perform for CreatePost {
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
let like_form = PostLikeForm {
@ -136,7 +138,9 @@ impl Perform for CreatePost {
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
let inserted_post_id = inserted_post.id;
@ -327,7 +331,9 @@ impl Perform for CreatePostLike {
post.send_dislike(&local_user_view.person, context).await?;
}
} 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;
@ -375,7 +381,12 @@ impl Perform for EditPost {
let post_id = data.post_id;
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
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
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_view = blocking(context.pool(), move |conn| {
@ -462,7 +475,12 @@ impl Perform for DeletePost {
let post_id = data.post_id;
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
if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
@ -479,9 +497,13 @@ impl Perform for DeletePost {
// apub updates
if deleted {
updated_post.send_delete(&local_user_view.person, context).await?;
updated_post
.send_delete(&local_user_view.person, context)
.await?;
} 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
@ -518,10 +540,20 @@ impl Perform for RemovePost {
let post_id = data.post_id;
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
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
let post_id = data.post_id;
@ -545,9 +577,13 @@ impl Perform for RemovePost {
// apub updates
if removed {
updated_post.send_remove(&local_user_view.person, context).await?;
updated_post
.send_remove(&local_user_view.person, context)
.await?;
} 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
@ -585,10 +621,20 @@ impl Perform for LockPost {
let post_id = data.post_id;
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
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
let post_id = data.post_id;
@ -607,7 +653,9 @@ impl Perform for LockPost {
blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??;
// 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
let post_id = data.post_id;
@ -643,10 +691,20 @@ impl Perform for StickyPost {
let post_id = data.post_id;
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
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
let post_id = data.post_id;
@ -669,7 +727,9 @@ impl Perform for StickyPost {
// Apub updates
// 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
let post_id = data.post_id;

@ -1,6 +1,6 @@
use crate::Perform;
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_websocket::{routes::chat_route, LemmyContext};
use serde::Deserialize;

@ -1,14 +1,15 @@
use crate::{
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_opt,
get_local_user_settings_view_from_jwt_opt,
is_admin,
Perform,
};
use actix_web::web::Data;
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_db_queries::{
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 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 {
site_view: Some(site_view),
admins,
banned,
online: 0,
version: version::VERSION.to_string(),
my_user: Some(local_user_view),
my_user,
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?;
// Only let admins read this
let person_id = local_user_view.person.id;
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

@ -1,17 +1,17 @@
pub mod comment;
pub mod community;
pub mod person;
pub mod post;
pub mod site;
pub mod person;
pub mod websocket;
use diesel::PgConnection;
use lemmy_db_queries::{Crud, DbPool};
use lemmy_db_schema::source::{
comment::Comment,
post::Post,
person::Person,
person_mention::{PersonMention, PersonMentionForm},
post::Post,
};
use lemmy_db_views::local_user_view::LocalUserView;
use lemmy_utils::{email::send_email, settings::structs::Settings, utils::MentionData, LemmyError};
@ -119,11 +119,17 @@ fn do_send_local_notifs(
Some(parent_id) => {
if let Ok(parent_comment) = Comment::read(&conn, parent_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);
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
None => {
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);
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
}
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 {
return;
}

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

@ -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_moderator::{
mod_add_community_view::ModAddCommunityView,

@ -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
// anyway.
let mentions = scrape_text_for_mentions(&comment.content);
let recipient_ids =
send_local_notifs(mentions, comment.clone(), person, post, context.pool(), true).await?;
let recipient_ids = send_local_notifs(
mentions,
comment.clone(),
person,
post,
context.pool(),
true,
)
.await?;
// Refetch the view
let comment_view = blocking(context.pool(), move |conn| {

@ -28,7 +28,7 @@ use anyhow::anyhow;
use itertools::Itertools;
use lemmy_api_structs::{blocking, WebFingerResponse};
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::{
request::{retry, RecvError},
settings::structs::Settings,
@ -197,7 +197,11 @@ impl ApubObjectType for Comment {
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 = 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
/// 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_comment =
blocking(pool, move |conn| Comment::read(conn, parent_comment_id)).await??;

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

@ -23,7 +23,7 @@ use activitystreams::{
};
use lemmy_api_structs::blocking;
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_websocket::LemmyContext;
@ -155,7 +155,11 @@ impl ApubObjectType for Post {
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 = blocking(context.pool(), move |conn| {
Community::read(conn, community_id)

@ -18,7 +18,7 @@ use activitystreams::{
};
use lemmy_api_structs::blocking;
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_websocket::LemmyContext;
@ -29,7 +29,8 @@ impl ApubObjectType for PrivateMessage {
let note = self.to_apub(context.pool()).await?;
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(
creator.actor_id.to_owned().into_inner(),
@ -50,7 +51,8 @@ impl ApubObjectType for PrivateMessage {
let note = self.to_apub(context.pool()).await?;
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(
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> {
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(
creator.actor_id.to_owned().into_inner(),
@ -88,7 +91,8 @@ impl ApubObjectType for PrivateMessage {
context: &LemmyContext,
) -> Result<(), LemmyError> {
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(
creator.actor_id.to_owned().into_inner(),

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

@ -46,7 +46,8 @@ pub(crate) async fn get_or_fetch_and_upsert_person(
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;
blocking(context.pool(), move |conn| {
@ -62,7 +63,8 @@ pub(crate) async fn get_or_fetch_and_upsert_person(
let person =
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)
}

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

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

@ -268,7 +268,8 @@ pub(crate) async fn check_community_or_site_ban(
return Err(anyhow!("Person is banned from site").into());
}
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? {
return Err(anyhow!("Person is banned from community").into());
}

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

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

@ -31,9 +31,9 @@ use lemmy_db_schema::{
activity::Activity,
comment::Comment,
community::Community,
person::Person as DbPerson,
post::Post,
private_message::PrivateMessage,
person::Person as DbPerson,
},
DbUrl,
};
@ -121,24 +121,38 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
/// and actors in Lemmy.
#[async_trait::async_trait(?Send)]
pub trait ApubObjectType {
async fn send_create(&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_create(&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(
&self,
creator: &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)]
pub trait ApubLikeableType {
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_undo_like(&self, creator: &DbPerson, context: &LemmyContext)
-> Result<(), LemmyError>;
async fn send_dislike(
&self,
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
@ -316,11 +330,11 @@ pub(crate) async fn find_post_or_comment_by_id(
}
pub(crate) enum Object {
Comment(Comment),
Post(Post),
Community(Community),
Person(DbPerson),
PrivateMessage(PrivateMessage),
Comment(Box<Comment>),
Post(Box<Post>),
Community(Box<Community>),
Person(Box<DbPerson>),
PrivateMessage(Box<PrivateMessage>),
}
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();
if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await {
return Ok(match pc {
PostOrComment::Post(p) => Object::Post(*p),
PostOrComment::Comment(c) => Object::Comment(*c),
PostOrComment::Post(p) => Object::Post(Box::new(*p)),
PostOrComment::Comment(c) => Object::Comment(Box::new(*c)),
});
}
@ -341,7 +355,7 @@ pub(crate) async fn find_object_by_id(
})
.await?;
if let Ok(u) = person {
return Ok(Object::Person(u));
return Ok(Object::Person(Box::new(u)));
}
let ap_id = apub_id.clone();
@ -350,7 +364,7 @@ pub(crate) async fn find_object_by_id(
})
.await?;
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| {
@ -358,7 +372,7 @@ pub(crate) async fn find_object_by_id(
})
.await?;
if let Ok(pm) = private_message {
return Ok(Object::PrivateMessage(pm));
return Ok(Object::PrivateMessage(Box::new(pm)));
}
Err(NotFound.into())

@ -25,8 +25,8 @@ use lemmy_api_structs::blocking;
use lemmy_db_queries::{Crud, DbPool};
use lemmy_db_schema::source::{
comment::{Comment, CommentForm},
post::Post,
person::Person,
post::Post,
};
use lemmy_utils::{
location_info,
@ -135,7 +135,8 @@ impl FromApubToForm<NoteExt> for CommentForm {
.as_single_xsd_any_uri()
.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
.in_reply_to()

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

@ -22,7 +22,7 @@ use lemmy_api_structs::blocking;
use lemmy_db_queries::{ApubObject, DbPool};
use lemmy_db_schema::{
naive_now,
source::person::{PersonForm, Person as DbPerson},
source::person::{Person as DbPerson, PersonForm},
};
use lemmy_utils::{
location_info,
@ -105,7 +105,10 @@ impl FromApub for DbPerson {
} else {
let person_form =
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)
}
}

@ -28,8 +28,8 @@ use lemmy_db_schema::{
self,
source::{
community::Community,
post::{Post, PostForm},
person::Person,
post::{Post, PostForm},
},
};
use lemmy_utils::{
@ -142,7 +142,8 @@ impl FromApubToForm<PageExt> for PostForm {
.as_single_xsd_any_uri()
.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?;

@ -22,8 +22,8 @@ use anyhow::Context;
use lemmy_api_structs::blocking;
use lemmy_db_queries::{Crud, DbPool};
use lemmy_db_schema::source::{
private_message::{PrivateMessage, PrivateMessageForm},
person::Person,
private_message::{PrivateMessage, PrivateMessageForm},
};
use lemmy_utils::{location_info, utils::convert_datetime, LemmyError};
use lemmy_websocket::LemmyContext;
@ -97,7 +97,8 @@ impl FromApubToForm<NoteExt> for PrivateMessageForm {
.single_xsd_any_uri()
.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
.to()
.context(location_info!())?

@ -8,10 +8,14 @@ use crate::{
get_apub_community_outbox,
},
get_activity,
post::get_apub_post,
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,
};
use actix_web::*;
@ -54,7 +58,10 @@ pub fn config(cfg: &mut web::ServiceConfig) {
web::get().to(get_apub_community_inbox),
)
.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("/post/{post_id}", web::get().to(get_apub_post))
.route("/comment/{comment_id}", web::get().to(get_apub_comment))

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

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

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

@ -32,8 +32,8 @@ mod tests {
use lemmy_db_schema::source::{
comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
community::{Community, CommunityForm},
person::{Person, PersonForm},
post::{Post, PostForm, PostLike, PostLikeForm},
person::{PersonForm, Person},
};
use serial_test::serial;
@ -189,7 +189,8 @@ mod tests {
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_score);

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

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

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

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

@ -295,7 +295,11 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
.set(community_follower_form)
.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
Self: Sized,
{
@ -333,13 +337,7 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
#[cfg(test)]
mod tests {
use crate::{
establish_unpooled_connection,
Bannable,
Crud,
Followable,
Joinable,
};
use crate::{establish_unpooled_connection, Bannable, Crud, Followable, Joinable};
use lemmy_db_schema::source::{community::*, person::*};
use serial_test::serial;
@ -438,7 +436,8 @@ mod tests {
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 {
id: inserted_community_moderator.id,

@ -1,30 +1,21 @@
use crate::{is_email_regex, 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 crate::{Crud, ToSafeSettings};
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 {
use crate::ToSafe;
use lemmy_db_schema::{schema::local_user::columns::*, source::local_user::LocalUser};
type Columns = (
id,
person_id,
admin,
matrix_user_id,
);
type Columns = (id, person_id, admin, matrix_user_id);
impl ToSafe for LocalUser {
type SafeColumns = Columns;
fn safe_columns_tuple() -> Self::SafeColumns {
(
id,
person_id,
admin,
matrix_user_id,
)
(id, person_id, admin, matrix_user_id)
}
}
}
@ -50,7 +41,7 @@ mod safe_settings_type {
impl ToSafeSettings for LocalUser {
type SafeSettingsColumns = Columns;
/// Includes everything but the hashed password
fn safe_settings_columns_tuple() -> Self::SafeSettingsColumns {
(
@ -73,10 +64,12 @@ mod safe_settings_type {
pub trait LocalUser_ {
fn register(conn: &PgConnection, form: &LocalUserForm) -> Result<LocalUser, Error>;
fn update_password(conn: &PgConnection, person_id: i32, new_password: &str)
-> Result<LocalUser, Error>;
fn update_password(
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 find_by_email(conn: &PgConnection, from_email: &str) -> 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
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");
diesel::update(local_user.find(local_user_id))
.set((
password_encrypted.eq(password_hash),
))
.set((password_encrypted.eq(password_hash),))
.get_result::<Self>(conn)
}
@ -108,33 +103,25 @@ impl LocalUser_ for LocalUser {
.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?
fn find_by_person(conn: &PgConnection, for_person_id: i32) -> Result<LocalUser, Error> {
local_user
.filter(person_id.eq(for_person_id))
.first::<LocalUser>(conn)
}
}
impl Crud<LocalUserForm> for LocalUser {
fn read(conn: &PgConnection, local_user_id: i32) -> Result<Self, Error> {
local_user
.find(local_user_id)
.first::<Self>(conn)
local_user.find(local_user_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, local_user_id: i32) -> Result<usize, Error> {
diesel::delete(local_user.find(local_user_id)).execute(conn)
}
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> {
diesel::update(local_user.find(local_user_id))

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

@ -198,7 +198,7 @@ impl Crud<ModAddForm> for ModAdd {
#[cfg(test)]
mod tests {
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 Crud;

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

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

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

@ -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);
}
}

@ -4,53 +4,53 @@ use serde::Serialize;
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "local_user"]
pub struct LocalUser {
pub id: i32,
pub person_id: i32,
pub password_encrypted: String,
pub email: Option<String>,
pub admin: bool,
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 id: i32,
pub person_id: i32,
pub password_encrypted: String,
pub email: Option<String>,
pub admin: bool,
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>,
}
// TODO redo these, check table defaults
#[derive(Insertable, AsChangeset, Clone)]
#[table_name = "local_user"]
pub struct LocalUserForm {
pub person_id: i32,
pub password_encrypted: String,
pub person_id: i32,
pub password_encrypted: String,
pub email: Option<Option<String>>,
pub admin: Option<bool>,
pub show_nsfw: Option<bool>,
pub theme: Option<String>,
pub default_sort_type: Option<i16>,
pub default_listing_type: Option<i16>,
pub lang: Option<String>,
pub show_avatars: Option<bool>,
pub send_notifications_to_email: Option<bool>,
pub admin: Option<bool>,
pub show_nsfw: Option<bool>,
pub theme: Option<String>,
pub default_sort_type: Option<i16>,
pub default_listing_type: Option<i16>,
pub lang: Option<String>,
pub show_avatars: Option<bool>,
pub send_notifications_to_email: Option<bool>,
pub matrix_user_id: Option<Option<String>>,
}
/// A local user view that removes password encrypted
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "local_user"]
pub struct LocalUserSettings{
pub id: i32,
pub person_id: i32,
pub email: Option<String>,
pub admin: bool,
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 struct LocalUserSettings {
pub id: i32,
pub person_id: i32,
pub email: Option<String>,
pub admin: bool,
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>,
}

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

@ -7,145 +7,144 @@ use serde::Serialize;
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "person"]
pub struct Person {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
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>,
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
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 = "person"]
pub struct PersonSafe {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
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>,
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
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>,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "person_alias_1"]
pub struct PersonAlias1 {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
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>,
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
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>,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "person_alias_1"]
pub struct PersonSafeAlias1 {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
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>,
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
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>,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "person_alias_2"]
pub struct PersonAlias2 {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
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>,
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
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>,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "person_alias_1"]
pub struct PersonSafeAlias2 {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
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>,
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
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>,
}
#[derive(Insertable, AsChangeset, Clone)]
#[table_name = "person"]
pub struct PersonForm {
pub name: String,
pub name: String,
pub preferred_username: Option<Option<String>>,
pub avatar: Option<Option<DbUrl>>,
pub banned: Option<bool>,
pub banned: Option<bool>,
pub published: Option<chrono::NaiveDateTime>,
pub updated: Option<chrono::NaiveDateTime>,
pub actor_id: Option<DbUrl>,
pub bio: Option<Option<String>>,
pub local: Option<bool>,
pub private_key: Option<Option<String>>,
pub public_key: Option<Option<String>>,
pub actor_id: Option<DbUrl>,
pub bio: Option<Option<String>>,
pub local: Option<bool>,
pub private_key: Option<Option<String>>,
pub public_key: Option<Option<String>>,
pub last_refreshed_at: Option<chrono::NaiveDateTime>,
pub banner: Option<Option<DbUrl>>,
pub deleted: Option<bool>,
pub inbox_url: Option<DbUrl>,
pub deleted: Option<bool>,
pub inbox_url: Option<DbUrl>,
pub shared_inbox_url: Option<Option<DbUrl>>,
}

@ -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>>,
}

@ -1,13 +1,13 @@
use diesel::{result::Error, *};
use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec};
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::{
comment::Comment,
comment_report::CommentReport,
community::{Community, CommunitySafe},
person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2},
post::Post,
person::{PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2, Person},
},
};
use serde::Serialize;

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

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

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

@ -1,12 +1,12 @@
use diesel::{result::Error, *};
use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec};
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::{
community::{Community, CommunitySafe},
person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2},
post::Post,
post_report::PostReport,
person::{PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2, Person},
},
};
use serde::Serialize;
@ -41,7 +41,9 @@ impl PostReportView {
.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_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((
post_report::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(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)))
.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((
post_report::all_columns,
post::all_columns,

@ -15,17 +15,17 @@ use lemmy_db_schema::{
community,
community_follower,
community_person_ban,
person,
post,
post_aggregates,
post_like,
post_read,
post_saved,
person,
},
source::{
community::{Community, CommunityFollower, CommunitySafe, CommunityPersonBan},
community::{Community, CommunityFollower, CommunityPersonBan, CommunitySafe},
person::{Person, PersonSafe},
post::{Post, PostRead, PostSaved},
person::{PersonSafe, Person},
},
};
use log::debug;
@ -433,7 +433,7 @@ mod tests {
ListingType,
SortType,
};
use lemmy_db_schema::source::{community::*, post::*, person::*};
use lemmy_db_schema::source::{community::*, person::*, post::*};
use serial_test::serial;
#[test]
@ -638,11 +638,17 @@ mod tests {
expected_post_listing_with_user,
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());
// 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!(1, read_post_listings_no_person.len());

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

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

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

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

@ -4,7 +4,7 @@ use lemmy_db_schema::{
schema::{community, community_person_ban, person},
source::{
community::{Community, CommunitySafe},
person::{PersonSafe, Person},
person::{Person, PersonSafe},
},
};
use serde::Serialize;
@ -24,7 +24,10 @@ impl CommunityPersonBanView {
let (community, person) = community_person_ban::table
.inner_join(community::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::person_id.eq(from_person_id))
.order_by(community_person_ban::published)

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

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

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

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

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

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

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

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

@ -1,13 +1,13 @@
use diesel::{result::Error, *};
use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec};
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::{
comment::Comment,
community::{Community, CommunitySafe},
moderator::ModRemoveComment,
person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
post::Post,
person::{PersonAlias1, PersonSafe, PersonSafeAlias1, Person},
},
};
use serde::Serialize;

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

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

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

@ -19,9 +19,9 @@ use lemmy_db_schema::{
source::{
comment::Comment,
community::{Community, CommunityForm},
person::{Person, PersonForm},
post::Post,
private_message::PrivateMessage,
user::{UserForm, User_},
},
};
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> {
use lemmy_db_schema::schema::user_::dsl::*;
use lemmy_db_schema::schema::person::dsl::*;
info!("Running user_updates_2020_04_02");
// 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(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 form = UserForm {
name: cuser.name.to_owned(),
email: Some(cuser.email.to_owned()),
matrix_user_id: Some(cuser.matrix_user_id.to_owned()),
avatar: Some(cuser.avatar.to_owned()),
banner: Some(cuser.banner.to_owned()),
password_encrypted: cuser.password_encrypted.to_owned(),
preferred_username: Some(cuser.preferred_username.to_owned()),
published: Some(cuser.published),
let form = PersonForm {
name: cperson.name.to_owned(),
avatar: None,
banner: None,
preferred_username: None,
published: None,
updated: None,
admin: cuser.admin,
banned: Some(cuser.banned),
show_nsfw: cuser.show_nsfw,
theme: cuser.theme.to_owned(),
default_sort_type: cuser.default_sort_type,
default_listing_type: cuser.default_listing_type,
lang: cuser.lang.to_owned(),
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),
banned: None,
deleted: None,
actor_id: Some(generate_apub_endpoint(EndpointType::Person, &cperson.name)?),
bio: None,
local: None,
private_key: Some(Some(keypair.private_key)),
public_key: Some(Some(keypair.public_key)),
last_refreshed_at: Some(naive_now()),
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(())
}
@ -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> {
info!("Running apub_columns_2021_02_02");
{
use lemmy_db_schema::schema::user_::dsl::*;
let users = user_
use lemmy_db_schema::schema::person::dsl::*;
let persons = person
.filter(inbox_url.like("http://changeme_%"))
.load::<User_>(conn)?;
.load::<Person>(conn)?;
for u in &users {
let inbox_url_ = generate_inbox_url(&u.actor_id)?;
let shared_inbox_url_ = generate_shared_inbox_url(&u.actor_id)?;
diesel::update(user_.find(u.id))
for p in &persons {
let inbox_url_ = generate_inbox_url(&p.actor_id)?;
let shared_inbox_url_ = generate_shared_inbox_url(&p.actor_id)?;
diesel::update(person.find(p.id))
.set((
inbox_url.eq(inbox_url_),
shared_inbox_url.eq(shared_inbox_url_),
))
.get_result::<User_>(conn)?;
.get_result::<Person>(conn)?;
}
}

Loading…
Cancel
Save