Merge pull request #1428 from LemmyNet/split_user_table

Split user table
This commit is contained in:
Nutomic 2021-03-19 13:20:23 +00:00 committed by GitHub
commit e25bcb35d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
125 changed files with 4119 additions and 3171 deletions

View file

@ -36,6 +36,7 @@ steps:
environment: environment:
LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy
RUST_BACKTRACE: 1 RUST_BACKTRACE: 1
RUST_TEST_THREADS: 1
CARGO_HOME: /drone/src/.cargo CARGO_HOME: /drone/src/.cargo
commands: commands:
- sudo apt-get update - sudo apt-get update
@ -116,6 +117,7 @@ steps:
environment: environment:
LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy
RUST_BACKTRACE: 1 RUST_BACKTRACE: 1
RUST_TEST_THREADS: 1
CARGO_HOME: /drone/src/.cargo CARGO_HOME: /drone/src/.cargo
commands: commands:
- apt-get update - apt-get update

View file

@ -1 +1 @@
0.9.9 0.10.0-rc.5

View file

@ -16,7 +16,7 @@
"eslint": "^7.18.0", "eslint": "^7.18.0",
"eslint-plugin-jane": "^9.0.3", "eslint-plugin-jane": "^9.0.3",
"jest": "^26.6.3", "jest": "^26.6.3",
"lemmy-js-client": "0.9.1-rc.1", "lemmy-js-client": "0.10.0-rc.4",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"prettier": "^2.1.2", "prettier": "^2.1.2",
"ts-jest": "^26.4.4", "ts-jest": "^26.4.4",

View file

@ -33,9 +33,6 @@ function assertCommunityFederation(
); );
expect(communityOne.creator.actor_id).toBe(communityTwo.creator.actor_id); expect(communityOne.creator.actor_id).toBe(communityTwo.creator.actor_id);
expect(communityOne.community.nsfw).toBe(communityTwo.community.nsfw); expect(communityOne.community.nsfw).toBe(communityTwo.community.nsfw);
expect(communityOne.community.category_id).toBe(
communityTwo.community.category_id
);
expect(communityOne.community.removed).toBe(communityTwo.community.removed); expect(communityOne.community.removed).toBe(communityTwo.community.removed);
expect(communityOne.community.deleted).toBe(communityTwo.community.deleted); expect(communityOne.community.deleted).toBe(communityTwo.community.deleted);
} }

View file

@ -20,9 +20,9 @@ import {
getPost, getPost,
unfollowRemotes, unfollowRemotes,
searchForUser, searchForUser,
banUserFromSite, banPersonFromSite,
searchPostLocal, searchPostLocal,
banUserFromCommunity, banPersonFromCommunity,
} from './shared'; } from './shared';
import { PostView, CommunityView } from 'lemmy-js-client'; import { PostView, CommunityView } from 'lemmy-js-client';
@ -305,7 +305,7 @@ test('Enforce site ban for federated user', async () => {
expect(alphaUser).toBeDefined(); expect(alphaUser).toBeDefined();
// ban alpha from beta site // ban alpha from beta site
let banAlpha = await banUserFromSite(beta, alphaUser.user.id, true); let banAlpha = await banPersonFromSite(beta, alphaUser.person.id, true);
expect(banAlpha.banned).toBe(true); expect(banAlpha.banned).toBe(true);
// Alpha makes post on beta // Alpha makes post on beta
@ -321,7 +321,7 @@ test('Enforce site ban for federated user', async () => {
expect(betaPost).toBeUndefined(); expect(betaPost).toBeUndefined();
// Unban alpha // Unban alpha
let unBanAlpha = await banUserFromSite(beta, alphaUser.user.id, false); let unBanAlpha = await banPersonFromSite(beta, alphaUser.person.id, false);
expect(unBanAlpha.banned).toBe(false); expect(unBanAlpha.banned).toBe(false);
}); });
@ -332,8 +332,8 @@ test('Enforce community ban for federated user', async () => {
expect(alphaUser).toBeDefined(); expect(alphaUser).toBeDefined();
// ban alpha from beta site // ban alpha from beta site
await banUserFromCommunity(beta, alphaUser.user.id, 2, false); await banPersonFromCommunity(beta, alphaUser.person.id, 2, false);
let banAlpha = await banUserFromCommunity(beta, alphaUser.user.id, 2, true); let banAlpha = await banPersonFromCommunity(beta, alphaUser.person.id, 2, true);
expect(banAlpha.banned).toBe(true); expect(banAlpha.banned).toBe(true);
// Alpha makes post on beta // Alpha makes post on beta
@ -349,9 +349,9 @@ test('Enforce community ban for federated user', async () => {
expect(betaPost).toBeUndefined(); expect(betaPost).toBeUndefined();
// Unban alpha // Unban alpha
let unBanAlpha = await banUserFromCommunity( let unBanAlpha = await banPersonFromCommunity(
beta, beta,
alphaUser.user.id, alphaUser.person.id,
2, 2,
false false
); );

View file

@ -25,7 +25,7 @@ import {
CreateCommunity, CreateCommunity,
DeleteCommunity, DeleteCommunity,
RemoveCommunity, RemoveCommunity,
GetUserMentions, GetPersonMentions,
CreateCommentLike, CreateCommentLike,
CreatePostLike, CreatePostLike,
EditPrivateMessage, EditPrivateMessage,
@ -36,15 +36,15 @@ import {
GetPost, GetPost,
PrivateMessageResponse, PrivateMessageResponse,
PrivateMessagesResponse, PrivateMessagesResponse,
GetUserMentionsResponse, GetPersonMentionsResponse,
SaveUserSettings, SaveUserSettings,
SortType, SortType,
ListingType, ListingType,
GetSiteResponse, GetSiteResponse,
SearchType, SearchType,
LemmyHttp, LemmyHttp,
BanUserResponse, BanPersonResponse,
BanUser, BanPerson,
BanFromCommunity, BanFromCommunity,
BanFromCommunityResponse, BanFromCommunityResponse,
Post, Post,
@ -289,32 +289,32 @@ export async function searchForUser(
return api.client.search(form); return api.client.search(form);
} }
export async function banUserFromSite( export async function banPersonFromSite(
api: API, api: API,
user_id: number, person_id: number,
ban: boolean ban: boolean
): Promise<BanUserResponse> { ): Promise<BanPersonResponse> {
// Make sure lemmy-beta/c/main is cached on lemmy_alpha // Make sure lemmy-beta/c/main is cached on lemmy_alpha
// Use short-hand search url // Use short-hand search url
let form: BanUser = { let form: BanPerson = {
user_id, person_id,
ban, ban,
remove_data: false, remove_data: false,
auth: api.auth, auth: api.auth,
}; };
return api.client.banUser(form); return api.client.banPerson(form);
} }
export async function banUserFromCommunity( export async function banPersonFromCommunity(
api: API, api: API,
user_id: number, person_id: number,
community_id: number, community_id: number,
ban: boolean ban: boolean
): Promise<BanFromCommunityResponse> { ): Promise<BanFromCommunityResponse> {
// Make sure lemmy-beta/c/main is cached on lemmy_alpha // Make sure lemmy-beta/c/main is cached on lemmy_alpha
// Use short-hand search url // Use short-hand search url
let form: BanFromCommunity = { let form: BanFromCommunity = {
user_id, person_id,
community_id, community_id,
remove_data: false, remove_data: false,
ban, ban,
@ -413,13 +413,13 @@ export async function removeComment(
return api.client.removeComment(form); return api.client.removeComment(form);
} }
export async function getMentions(api: API): Promise<GetUserMentionsResponse> { export async function getMentions(api: API): Promise<GetPersonMentionsResponse> {
let form: GetUserMentions = { let form: GetPersonMentions = {
sort: SortType.New, sort: SortType.New,
unread_only: false, unread_only: false,
auth: api.auth, auth: api.auth,
}; };
return api.client.getUserMentions(form); return api.client.getPersonMentions(form);
} }
export async function likeComment( export async function likeComment(
@ -448,7 +448,6 @@ export async function createCommunity(
description, description,
icon, icon,
banner, banner,
category_id: 1,
nsfw: false, nsfw: false,
auth: api.auth, auth: api.auth,
}; };

View file

@ -8,7 +8,7 @@ import {
getSite, getSite,
} from './shared'; } from './shared';
import { import {
UserViewSafe, PersonViewSafe,
SaveUserSettings, SaveUserSettings,
SortType, SortType,
ListingType, ListingType,
@ -17,14 +17,14 @@ import {
let auth: string; let auth: string;
let apShortname: string; let apShortname: string;
function assertUserFederation(userOne: UserViewSafe, userTwo: UserViewSafe) { function assertUserFederation(userOne: PersonViewSafe, userTwo: PersonViewSafe) {
expect(userOne.user.name).toBe(userTwo.user.name); expect(userOne.person.name).toBe(userTwo.person.name);
expect(userOne.user.preferred_username).toBe(userTwo.user.preferred_username); expect(userOne.person.preferred_username).toBe(userTwo.person.preferred_username);
expect(userOne.user.bio).toBe(userTwo.user.bio); expect(userOne.person.bio).toBe(userTwo.person.bio);
expect(userOne.user.actor_id).toBe(userTwo.user.actor_id); expect(userOne.person.actor_id).toBe(userTwo.person.actor_id);
expect(userOne.user.avatar).toBe(userTwo.user.avatar); expect(userOne.person.avatar).toBe(userTwo.person.avatar);
expect(userOne.user.banner).toBe(userTwo.user.banner); expect(userOne.person.banner).toBe(userTwo.person.banner);
expect(userOne.user.published).toBe(userTwo.user.published); expect(userOne.person.published).toBe(userTwo.person.published);
} }
test('Create user', async () => { test('Create user', async () => {
@ -34,7 +34,7 @@ test('Create user', async () => {
let site = await getSite(alpha, auth); let site = await getSite(alpha, auth);
expect(site.my_user).toBeDefined(); expect(site.my_user).toBeDefined();
apShortname = `@${site.my_user.name}@lemmy-alpha:8541`; apShortname = `@${site.my_user.person.name}@lemmy-alpha:8541`;
}); });
test('Set some user settings, check that they are federated', async () => { test('Set some user settings, check that they are federated', async () => {

View file

@ -3233,10 +3233,10 @@ language-tags@^1.0.5:
dependencies: dependencies:
language-subtag-registry "~0.3.2" language-subtag-registry "~0.3.2"
lemmy-js-client@0.9.1-rc.1: lemmy-js-client@0.10.0-rc.4:
version "0.9.1-rc.1" version "0.10.0-rc.4"
resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.9.1-rc.1.tgz#afe3cb0d4852f849dd087a4756a3771bc920a907" resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.10.0-rc.4.tgz#ac6fe6940fc5f73260ddb166ce0ef3c0520901fc"
integrity sha512-aVvo4IeJvIPUvypipk4GnyLB6nVQVLfB0arYrMkVV4L7zrZ/0pGtpkMDLaOAj/KpA6O0u9eLmaou5RberZQolA== integrity sha512-yJPnvGaWneOOwjKEqb4qXtQk+4DbRgO+hEzSin2GgUgnxluY43gemwiCPt6EnV+j4ueKoi0+QORVg2RuRC2PaQ==
leven@^3.1.0: leven@^3.1.0:
version "3.1.0" version "3.1.0"

View file

@ -2,9 +2,9 @@ use crate::{
check_community_ban, check_community_ban,
check_downvotes_enabled, check_downvotes_enabled,
collect_moderated_communities, collect_moderated_communities,
get_local_user_view_from_jwt,
get_local_user_view_from_jwt_opt,
get_post, get_post,
get_user_from_jwt,
get_user_from_jwt_opt,
is_mod_or_admin, is_mod_or_admin,
Perform, Perform,
}; };
@ -48,7 +48,7 @@ impl Perform for CreateComment {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<CommentResponse, LemmyError> { ) -> Result<CommentResponse, LemmyError> {
let data: &CreateComment = &self; let data: &CreateComment = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let content_slurs_removed = remove_slurs(&data.content.to_owned()); let content_slurs_removed = remove_slurs(&data.content.to_owned());
@ -56,7 +56,7 @@ impl Perform for CreateComment {
let post_id = data.post_id; let post_id = data.post_id;
let post = get_post(post_id, context.pool()).await?; let post = get_post(post_id, context.pool()).await?;
check_community_ban(user.id, post.community_id, context.pool()).await?; check_community_ban(local_user_view.person.id, post.community_id, context.pool()).await?;
// Check if post is locked, no new comments // Check if post is locked, no new comments
if post.locked { if post.locked {
@ -80,7 +80,7 @@ impl Perform for CreateComment {
content: content_slurs_removed, content: content_slurs_removed,
parent_id: data.parent_id.to_owned(), parent_id: data.parent_id.to_owned(),
post_id: data.post_id, post_id: data.post_id,
creator_id: user.id, creator_id: local_user_view.person.id,
removed: None, removed: None,
deleted: None, deleted: None,
read: None, read: None,
@ -115,7 +115,9 @@ impl Perform for CreateComment {
Err(_e) => return Err(ApiError::err("couldnt_create_comment").into()), Err(_e) => return Err(ApiError::err("couldnt_create_comment").into()),
}; };
updated_comment.send_create(&user, context).await?; updated_comment
.send_create(&local_user_view.person, context)
.await?;
// Scan the comment for user mentions, add those rows // Scan the comment for user mentions, add those rows
let post_id = post.id; let post_id = post.id;
@ -123,7 +125,7 @@ impl Perform for CreateComment {
let recipient_ids = send_local_notifs( let recipient_ids = send_local_notifs(
mentions, mentions,
updated_comment.clone(), updated_comment.clone(),
&user, local_user_view.person.clone(),
post, post,
context.pool(), context.pool(),
true, true,
@ -134,7 +136,7 @@ impl Perform for CreateComment {
let like_form = CommentLikeForm { let like_form = CommentLikeForm {
comment_id: inserted_comment.id, comment_id: inserted_comment.id,
post_id, post_id,
user_id: user.id, person_id: local_user_view.person.id,
score: 1, score: 1,
}; };
@ -143,17 +145,19 @@ impl Perform for CreateComment {
return Err(ApiError::err("couldnt_like_comment").into()); return Err(ApiError::err("couldnt_like_comment").into());
} }
updated_comment.send_like(&user, context).await?; updated_comment
.send_like(&local_user_view.person, context)
.await?;
let user_id = user.id; let person_id = local_user_view.person.id;
let mut comment_view = blocking(context.pool(), move |conn| { let mut comment_view = blocking(context.pool(), move |conn| {
CommentView::read(&conn, inserted_comment.id, Some(user_id)) CommentView::read(&conn, inserted_comment.id, Some(person_id))
}) })
.await??; .await??;
// If its a comment to yourself, mark it as read // If its a comment to yourself, mark it as read
let comment_id = comment_view.comment.id; let comment_id = comment_view.comment.id;
if user.id == comment_view.get_recipient_id() { if local_user_view.person.id == comment_view.get_recipient_id() {
match blocking(context.pool(), move |conn| { match blocking(context.pool(), move |conn| {
Comment::update_read(conn, comment_id, true) Comment::update_read(conn, comment_id, true)
}) })
@ -193,7 +197,7 @@ impl Perform for EditComment {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<CommentResponse, LemmyError> { ) -> Result<CommentResponse, LemmyError> {
let data: &EditComment = &self; let data: &EditComment = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let comment_id = data.comment_id; let comment_id = data.comment_id;
let orig_comment = blocking(context.pool(), move |conn| { let orig_comment = blocking(context.pool(), move |conn| {
@ -201,10 +205,15 @@ impl Perform for EditComment {
}) })
.await??; .await??;
check_community_ban(user.id, orig_comment.community.id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_comment.community.id,
context.pool(),
)
.await?;
// Verify that only the creator can edit // Verify that only the creator can edit
if user.id != orig_comment.creator.id { if local_user_view.person.id != orig_comment.creator.id {
return Err(ApiError::err("no_comment_edit_allowed").into()); return Err(ApiError::err("no_comment_edit_allowed").into());
} }
@ -221,7 +230,9 @@ impl Perform for EditComment {
}; };
// Send the apub update // Send the apub update
updated_comment.send_update(&user, context).await?; updated_comment
.send_update(&local_user_view.person, context)
.await?;
// Do the mentions / recipients // Do the mentions / recipients
let updated_comment_content = updated_comment.content.to_owned(); let updated_comment_content = updated_comment.content.to_owned();
@ -229,7 +240,7 @@ impl Perform for EditComment {
let recipient_ids = send_local_notifs( let recipient_ids = send_local_notifs(
mentions, mentions,
updated_comment, updated_comment,
&user, local_user_view.person.clone(),
orig_comment.post, orig_comment.post,
context.pool(), context.pool(),
false, false,
@ -237,9 +248,9 @@ impl Perform for EditComment {
.await?; .await?;
let comment_id = data.comment_id; let comment_id = data.comment_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let comment_view = blocking(context.pool(), move |conn| { let comment_view = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment_id, Some(user_id)) CommentView::read(conn, comment_id, Some(person_id))
}) })
.await??; .await??;
@ -269,7 +280,7 @@ impl Perform for DeleteComment {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<CommentResponse, LemmyError> { ) -> Result<CommentResponse, LemmyError> {
let data: &DeleteComment = &self; let data: &DeleteComment = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let comment_id = data.comment_id; let comment_id = data.comment_id;
let orig_comment = blocking(context.pool(), move |conn| { let orig_comment = blocking(context.pool(), move |conn| {
@ -277,10 +288,15 @@ impl Perform for DeleteComment {
}) })
.await??; .await??;
check_community_ban(user.id, orig_comment.community.id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_comment.community.id,
context.pool(),
)
.await?;
// Verify that only the creator can delete // Verify that only the creator can delete
if user.id != orig_comment.creator.id { if local_user_view.person.id != orig_comment.creator.id {
return Err(ApiError::err("no_comment_edit_allowed").into()); return Err(ApiError::err("no_comment_edit_allowed").into());
} }
@ -297,16 +313,20 @@ impl Perform for DeleteComment {
// Send the apub message // Send the apub message
if deleted { if deleted {
updated_comment.send_delete(&user, context).await?; updated_comment
.send_delete(&local_user_view.person, context)
.await?;
} else { } else {
updated_comment.send_undo_delete(&user, context).await?; updated_comment
.send_undo_delete(&local_user_view.person, context)
.await?;
} }
// Refetch it // Refetch it
let comment_id = data.comment_id; let comment_id = data.comment_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let comment_view = blocking(context.pool(), move |conn| { let comment_view = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment_id, Some(user_id)) CommentView::read(conn, comment_id, Some(person_id))
}) })
.await??; .await??;
@ -316,7 +336,7 @@ impl Perform for DeleteComment {
let recipient_ids = send_local_notifs( let recipient_ids = send_local_notifs(
mentions, mentions,
updated_comment, updated_comment,
&user, local_user_view.person.clone(),
comment_view_2.post, comment_view_2.post,
context.pool(), context.pool(),
false, false,
@ -349,7 +369,7 @@ impl Perform for RemoveComment {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<CommentResponse, LemmyError> { ) -> Result<CommentResponse, LemmyError> {
let data: &RemoveComment = &self; let data: &RemoveComment = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let comment_id = data.comment_id; let comment_id = data.comment_id;
let orig_comment = blocking(context.pool(), move |conn| { let orig_comment = blocking(context.pool(), move |conn| {
@ -357,10 +377,20 @@ impl Perform for RemoveComment {
}) })
.await??; .await??;
check_community_ban(user.id, orig_comment.community.id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_comment.community.id,
context.pool(),
)
.await?;
// Verify that only a mod or admin can remove // Verify that only a mod or admin can remove
is_mod_or_admin(context.pool(), user.id, orig_comment.community.id).await?; is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_comment.community.id,
)
.await?;
// Do the remove // Do the remove
let removed = data.removed; let removed = data.removed;
@ -375,7 +405,7 @@ impl Perform for RemoveComment {
// Mod tables // Mod tables
let form = ModRemoveCommentForm { let form = ModRemoveCommentForm {
mod_user_id: user.id, mod_person_id: local_user_view.person.id,
comment_id: data.comment_id, comment_id: data.comment_id,
removed: Some(removed), removed: Some(removed),
reason: data.reason.to_owned(), reason: data.reason.to_owned(),
@ -387,16 +417,20 @@ impl Perform for RemoveComment {
// Send the apub message // Send the apub message
if removed { if removed {
updated_comment.send_remove(&user, context).await?; updated_comment
.send_remove(&local_user_view.person, context)
.await?;
} else { } else {
updated_comment.send_undo_remove(&user, context).await?; updated_comment
.send_undo_remove(&local_user_view.person, context)
.await?;
} }
// Refetch it // Refetch it
let comment_id = data.comment_id; let comment_id = data.comment_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let comment_view = blocking(context.pool(), move |conn| { let comment_view = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment_id, Some(user_id)) CommentView::read(conn, comment_id, Some(person_id))
}) })
.await??; .await??;
@ -407,7 +441,7 @@ impl Perform for RemoveComment {
let recipient_ids = send_local_notifs( let recipient_ids = send_local_notifs(
mentions, mentions,
updated_comment, updated_comment,
&user, local_user_view.person.clone(),
comment_view_2.post, comment_view_2.post,
context.pool(), context.pool(),
false, false,
@ -440,7 +474,7 @@ impl Perform for MarkCommentAsRead {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<CommentResponse, LemmyError> { ) -> Result<CommentResponse, LemmyError> {
let data: &MarkCommentAsRead = &self; let data: &MarkCommentAsRead = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let comment_id = data.comment_id; let comment_id = data.comment_id;
let orig_comment = blocking(context.pool(), move |conn| { let orig_comment = blocking(context.pool(), move |conn| {
@ -448,10 +482,15 @@ impl Perform for MarkCommentAsRead {
}) })
.await??; .await??;
check_community_ban(user.id, orig_comment.community.id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_comment.community.id,
context.pool(),
)
.await?;
// Verify that only the recipient can mark as read // Verify that only the recipient can mark as read
if user.id != orig_comment.get_recipient_id() { if local_user_view.person.id != orig_comment.get_recipient_id() {
return Err(ApiError::err("no_comment_edit_allowed").into()); return Err(ApiError::err("no_comment_edit_allowed").into());
} }
@ -468,9 +507,9 @@ impl Perform for MarkCommentAsRead {
// Refetch it // Refetch it
let comment_id = data.comment_id; let comment_id = data.comment_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let comment_view = blocking(context.pool(), move |conn| { let comment_view = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment_id, Some(user_id)) CommentView::read(conn, comment_id, Some(person_id))
}) })
.await??; .await??;
@ -494,11 +533,11 @@ impl Perform for SaveComment {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<CommentResponse, LemmyError> { ) -> Result<CommentResponse, LemmyError> {
let data: &SaveComment = &self; let data: &SaveComment = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let comment_saved_form = CommentSavedForm { let comment_saved_form = CommentSavedForm {
comment_id: data.comment_id, comment_id: data.comment_id,
user_id: user.id, person_id: local_user_view.person.id,
}; };
if data.save { if data.save {
@ -514,9 +553,9 @@ impl Perform for SaveComment {
} }
let comment_id = data.comment_id; let comment_id = data.comment_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let comment_view = blocking(context.pool(), move |conn| { let comment_view = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment_id, Some(user_id)) CommentView::read(conn, comment_id, Some(person_id))
}) })
.await??; .await??;
@ -538,7 +577,7 @@ impl Perform for CreateCommentLike {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<CommentResponse, LemmyError> { ) -> Result<CommentResponse, LemmyError> {
let data: &CreateCommentLike = &self; let data: &CreateCommentLike = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let mut recipient_ids = Vec::new(); let mut recipient_ids = Vec::new();
@ -551,7 +590,12 @@ impl Perform for CreateCommentLike {
}) })
.await??; .await??;
check_community_ban(user.id, orig_comment.community.id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_comment.community.id,
context.pool(),
)
.await?;
// Add parent user to recipients // Add parent user to recipients
recipient_ids.push(orig_comment.get_recipient_id()); recipient_ids.push(orig_comment.get_recipient_id());
@ -559,14 +603,14 @@ impl Perform for CreateCommentLike {
let like_form = CommentLikeForm { let like_form = CommentLikeForm {
comment_id: data.comment_id, comment_id: data.comment_id,
post_id: orig_comment.post.id, post_id: orig_comment.post.id,
user_id: user.id, person_id: local_user_view.person.id,
score: data.score, score: data.score,
}; };
// Remove any likes first // Remove any likes first
let user_id = user.id; let person_id = local_user_view.person.id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
CommentLike::remove(conn, user_id, comment_id) CommentLike::remove(conn, person_id, comment_id)
}) })
.await??; .await??;
@ -581,19 +625,23 @@ impl Perform for CreateCommentLike {
} }
if like_form.score == 1 { if like_form.score == 1 {
comment.send_like(&user, context).await?; comment.send_like(&local_user_view.person, context).await?;
} else if like_form.score == -1 { } else if like_form.score == -1 {
comment.send_dislike(&user, context).await?; comment
.send_dislike(&local_user_view.person, context)
.await?;
} }
} else { } else {
comment.send_undo_like(&user, context).await?; comment
.send_undo_like(&local_user_view.person, context)
.await?;
} }
// Have to refetch the comment to get the current state // Have to refetch the comment to get the current state
let comment_id = data.comment_id; let comment_id = data.comment_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let liked_comment = blocking(context.pool(), move |conn| { let liked_comment = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment_id, Some(user_id)) CommentView::read(conn, comment_id, Some(person_id))
}) })
.await??; .await??;
@ -623,8 +671,8 @@ impl Perform for GetComments {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<GetCommentsResponse, LemmyError> { ) -> Result<GetCommentsResponse, LemmyError> {
let data: &GetComments = &self; let data: &GetComments = &self;
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
let user_id = user.map(|u| u.id); let person_id = local_user_view.map(|u| u.person.id);
let type_ = ListingType::from_str(&data.type_)?; let type_ = ListingType::from_str(&data.type_)?;
let sort = SortType::from_str(&data.sort)?; let sort = SortType::from_str(&data.sort)?;
@ -639,7 +687,7 @@ impl Perform for GetComments {
.sort(&sort) .sort(&sort)
.community_id(community_id) .community_id(community_id)
.community_name(community_name) .community_name(community_name)
.my_user_id(user_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.list() .list()
@ -665,7 +713,7 @@ impl Perform for CreateCommentReport {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<CreateCommentReportResponse, LemmyError> { ) -> Result<CreateCommentReportResponse, LemmyError> {
let data: &CreateCommentReport = &self; let data: &CreateCommentReport = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// check size of report and check for whitespace // check size of report and check for whitespace
let reason = data.reason.trim(); let reason = data.reason.trim();
@ -676,17 +724,17 @@ impl Perform for CreateCommentReport {
return Err(ApiError::err("report_too_long").into()); return Err(ApiError::err("report_too_long").into());
} }
let user_id = user.id; let person_id = local_user_view.person.id;
let comment_id = data.comment_id; let comment_id = data.comment_id;
let comment_view = blocking(context.pool(), move |conn| { let comment_view = blocking(context.pool(), move |conn| {
CommentView::read(&conn, comment_id, None) CommentView::read(&conn, comment_id, None)
}) })
.await??; .await??;
check_community_ban(user_id, comment_view.community.id, context.pool()).await?; check_community_ban(person_id, comment_view.community.id, context.pool()).await?;
let report_form = CommentReportForm { let report_form = CommentReportForm {
creator_id: user_id, creator_id: person_id,
comment_id, comment_id,
original_comment_text: comment_view.comment.content, original_comment_text: comment_view.comment.content,
reason: data.reason.to_owned(), reason: data.reason.to_owned(),
@ -706,7 +754,7 @@ impl Perform for CreateCommentReport {
context.chat_server().do_send(SendUserRoomMessage { context.chat_server().do_send(SendUserRoomMessage {
op: UserOperation::CreateCommentReport, op: UserOperation::CreateCommentReport,
response: res.clone(), response: res.clone(),
recipient_id: user.id, local_recipient_id: local_user_view.person.id,
websocket_id, websocket_id,
}); });
@ -732,7 +780,7 @@ impl Perform for ResolveCommentReport {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<ResolveCommentReportResponse, LemmyError> { ) -> Result<ResolveCommentReportResponse, LemmyError> {
let data: &ResolveCommentReport = &self; let data: &ResolveCommentReport = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let report_id = data.report_id; let report_id = data.report_id;
let report = blocking(context.pool(), move |conn| { let report = blocking(context.pool(), move |conn| {
@ -740,15 +788,15 @@ impl Perform for ResolveCommentReport {
}) })
.await??; .await??;
let user_id = user.id; let person_id = local_user_view.person.id;
is_mod_or_admin(context.pool(), user_id, report.community.id).await?; is_mod_or_admin(context.pool(), person_id, report.community.id).await?;
let resolved = data.resolved; let resolved = data.resolved;
let resolve_fun = move |conn: &'_ _| { let resolve_fun = move |conn: &'_ _| {
if resolved { if resolved {
CommentReport::resolve(conn, report_id, user_id) CommentReport::resolve(conn, report_id, person_id)
} else { } else {
CommentReport::unresolve(conn, report_id, user_id) CommentReport::unresolve(conn, report_id, person_id)
} }
}; };
@ -785,12 +833,12 @@ impl Perform for ListCommentReports {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<ListCommentReportsResponse, LemmyError> { ) -> Result<ListCommentReportsResponse, LemmyError> {
let data: &ListCommentReports = &self; let data: &ListCommentReports = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let user_id = user.id; let person_id = local_user_view.person.id;
let community_id = data.community; let community_id = data.community;
let community_ids = let community_ids =
collect_moderated_communities(user_id, community_id, context.pool()).await?; collect_moderated_communities(person_id, community_id, context.pool()).await?;
let page = data.page; let page = data.page;
let limit = data.limit; let limit = data.limit;
@ -808,7 +856,7 @@ impl Perform for ListCommentReports {
context.chat_server().do_send(SendUserRoomMessage { context.chat_server().do_send(SendUserRoomMessage {
op: UserOperation::ListCommentReports, op: UserOperation::ListCommentReports,
response: res.clone(), response: res.clone(),
recipient_id: user.id, local_recipient_id: local_user_view.person.id,
websocket_id, websocket_id,
}); });

View file

@ -1,7 +1,7 @@
use crate::{ use crate::{
check_community_ban, check_community_ban,
get_user_from_jwt, get_local_user_view_from_jwt,
get_user_from_jwt_opt, get_local_user_view_from_jwt_opt,
is_admin, is_admin,
is_mod_or_admin, is_mod_or_admin,
Perform, Perform,
@ -41,7 +41,7 @@ use lemmy_db_views_actor::{
community_follower_view::CommunityFollowerView, community_follower_view::CommunityFollowerView,
community_moderator_view::CommunityModeratorView, community_moderator_view::CommunityModeratorView,
community_view::{CommunityQueryBuilder, CommunityView}, community_view::{CommunityQueryBuilder, CommunityView},
user_view::UserViewSafe, person_view::PersonViewSafe,
}; };
use lemmy_utils::{ use lemmy_utils::{
apub::generate_actor_keypair, apub::generate_actor_keypair,
@ -68,8 +68,8 @@ impl Perform for GetCommunity {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<GetCommunityResponse, LemmyError> { ) -> Result<GetCommunityResponse, LemmyError> {
let data: &GetCommunity = &self; let data: &GetCommunity = &self;
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
let user_id = user.map(|u| u.id); let person_id = local_user_view.map(|u| u.person.id);
let community_id = match data.id { let community_id = match data.id {
Some(id) => id, Some(id) => id,
@ -88,7 +88,7 @@ impl Perform for GetCommunity {
}; };
let community_view = match blocking(context.pool(), move |conn| { let community_view = match blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, user_id) CommunityView::read(conn, community_id, person_id)
}) })
.await? .await?
{ {
@ -132,7 +132,7 @@ impl Perform for CreateCommunity {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<CommunityResponse, LemmyError> { ) -> Result<CommunityResponse, LemmyError> {
let data: &CreateCommunity = &self; let data: &CreateCommunity = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
check_slurs(&data.name)?; check_slurs(&data.name)?;
check_slurs(&data.title)?; check_slurs(&data.title)?;
@ -166,7 +166,7 @@ impl Perform for CreateCommunity {
description: data.description.to_owned(), description: data.description.to_owned(),
icon, icon,
banner, banner,
creator_id: user.id, creator_id: local_user_view.person.id,
removed: None, removed: None,
deleted: None, deleted: None,
nsfw: data.nsfw, nsfw: data.nsfw,
@ -194,7 +194,7 @@ impl Perform for CreateCommunity {
// The community creator becomes a moderator // The community creator becomes a moderator
let community_moderator_form = CommunityModeratorForm { let community_moderator_form = CommunityModeratorForm {
community_id: inserted_community.id, community_id: inserted_community.id,
user_id: user.id, person_id: local_user_view.person.id,
}; };
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form); let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
@ -205,7 +205,7 @@ impl Perform for CreateCommunity {
// Follow your own community // Follow your own community
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: inserted_community.id, community_id: inserted_community.id,
user_id: user.id, person_id: local_user_view.person.id,
pending: false, pending: false,
}; };
@ -214,9 +214,9 @@ impl Perform for CreateCommunity {
return Err(ApiError::err("community_follower_already_exists").into()); return Err(ApiError::err("community_follower_already_exists").into());
} }
let user_id = user.id; let person_id = local_user_view.person.id;
let community_view = blocking(context.pool(), move |conn| { let community_view = blocking(context.pool(), move |conn| {
CommunityView::read(conn, inserted_community.id, Some(user_id)) CommunityView::read(conn, inserted_community.id, Some(person_id))
}) })
.await??; .await??;
@ -234,7 +234,7 @@ impl Perform for EditCommunity {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<CommunityResponse, LemmyError> { ) -> Result<CommunityResponse, LemmyError> {
let data: &EditCommunity = &self; let data: &EditCommunity = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
check_slurs(&data.title)?; check_slurs(&data.title)?;
check_slurs_opt(&data.description)?; check_slurs_opt(&data.description)?;
@ -246,7 +246,7 @@ impl Perform for EditCommunity {
.map(|v| v.into_iter().map(|m| m.moderator.id).collect()) .map(|v| v.into_iter().map(|m| m.moderator.id).collect())
}) })
.await??; .await??;
if !mods.contains(&user.id) { if !mods.contains(&local_user_view.person.id) {
return Err(ApiError::err("not_a_moderator").into()); return Err(ApiError::err("not_a_moderator").into());
} }
@ -295,9 +295,9 @@ impl Perform for EditCommunity {
// process for communities and users // process for communities and users
let community_id = data.community_id; let community_id = data.community_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let community_view = blocking(context.pool(), move |conn| { let community_view = blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, Some(user_id)) CommunityView::read(conn, community_id, Some(person_id))
}) })
.await??; .await??;
@ -319,7 +319,7 @@ impl Perform for DeleteCommunity {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<CommunityResponse, LemmyError> { ) -> Result<CommunityResponse, LemmyError> {
let data: &DeleteCommunity = &self; let data: &DeleteCommunity = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Verify its the creator (only a creator can delete the community) // Verify its the creator (only a creator can delete the community)
let community_id = data.community_id; let community_id = data.community_id;
@ -327,7 +327,7 @@ impl Perform for DeleteCommunity {
Community::read(conn, community_id) Community::read(conn, community_id)
}) })
.await??; .await??;
if read_community.creator_id != user.id { if read_community.creator_id != local_user_view.person.id {
return Err(ApiError::err("no_community_edit_allowed").into()); return Err(ApiError::err("no_community_edit_allowed").into());
} }
@ -351,9 +351,9 @@ impl Perform for DeleteCommunity {
} }
let community_id = data.community_id; let community_id = data.community_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let community_view = blocking(context.pool(), move |conn| { let community_view = blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, Some(user_id)) CommunityView::read(conn, community_id, Some(person_id))
}) })
.await??; .await??;
@ -375,10 +375,10 @@ impl Perform for RemoveCommunity {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<CommunityResponse, LemmyError> { ) -> Result<CommunityResponse, LemmyError> {
let data: &RemoveCommunity = &self; let data: &RemoveCommunity = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Verify its an admin (only an admin can remove a community) // Verify its an admin (only an admin can remove a community)
is_admin(context.pool(), user.id).await?; is_admin(&local_user_view)?;
// Do the remove // Do the remove
let community_id = data.community_id; let community_id = data.community_id;
@ -398,7 +398,7 @@ impl Perform for RemoveCommunity {
None => None, None => None,
}; };
let form = ModRemoveCommunityForm { let form = ModRemoveCommunityForm {
mod_user_id: user.id, mod_person_id: local_user_view.person.id,
community_id: data.community_id, community_id: data.community_id,
removed: Some(removed), removed: Some(removed),
reason: data.reason.to_owned(), reason: data.reason.to_owned(),
@ -417,9 +417,9 @@ impl Perform for RemoveCommunity {
} }
let community_id = data.community_id; let community_id = data.community_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let community_view = blocking(context.pool(), move |conn| { let community_view = blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, Some(user_id)) CommunityView::read(conn, community_id, Some(person_id))
}) })
.await??; .await??;
@ -441,15 +441,16 @@ impl Perform for ListCommunities {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<ListCommunitiesResponse, LemmyError> { ) -> Result<ListCommunitiesResponse, LemmyError> {
let data: &ListCommunities = &self; let data: &ListCommunities = &self;
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
let user_id = match &user { let person_id = match &local_user_view {
Some(user) => Some(user.id), Some(uv) => Some(uv.person.id),
None => None, None => None,
}; };
let show_nsfw = match &user { // Don't show NSFW by default
Some(user) => user.show_nsfw, let show_nsfw = match &local_user_view {
Some(uv) => uv.local_user.show_nsfw,
None => false, None => false,
}; };
@ -463,7 +464,7 @@ impl Perform for ListCommunities {
.listing_type(&type_) .listing_type(&type_)
.sort(&sort) .sort(&sort)
.show_nsfw(show_nsfw) .show_nsfw(show_nsfw)
.my_user_id(user_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.list() .list()
@ -485,7 +486,7 @@ impl Perform for FollowCommunity {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<CommunityResponse, LemmyError> { ) -> Result<CommunityResponse, LemmyError> {
let data: &FollowCommunity = &self; let data: &FollowCommunity = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let community_id = data.community_id; let community_id = data.community_id;
let community = blocking(context.pool(), move |conn| { let community = blocking(context.pool(), move |conn| {
@ -494,13 +495,13 @@ impl Perform for FollowCommunity {
.await??; .await??;
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: data.community_id, community_id: data.community_id,
user_id: user.id, person_id: local_user_view.person.id,
pending: false, pending: false,
}; };
if community.local { if community.local {
if data.follow { if data.follow {
check_community_ban(user.id, community_id, context.pool()).await?; check_community_ban(local_user_view.person.id, community_id, context.pool()).await?;
let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form); let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form);
if blocking(context.pool(), follow).await?.is_err() { if blocking(context.pool(), follow).await?.is_err() {
@ -516,9 +517,15 @@ impl Perform for FollowCommunity {
} else if data.follow { } else if data.follow {
// Dont actually add to the community followers here, because you need // Dont actually add to the community followers here, because you need
// to wait for the accept // to wait for the accept
user.send_follow(&community.actor_id(), context).await?; local_user_view
.person
.send_follow(&community.actor_id(), context)
.await?;
} else { } else {
user.send_unfollow(&community.actor_id(), context).await?; local_user_view
.person
.send_unfollow(&community.actor_id(), context)
.await?;
let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form); let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
if blocking(context.pool(), unfollow).await?.is_err() { if blocking(context.pool(), unfollow).await?.is_err() {
return Err(ApiError::err("community_follower_already_exists").into()); return Err(ApiError::err("community_follower_already_exists").into());
@ -526,9 +533,9 @@ impl Perform for FollowCommunity {
} }
let community_id = data.community_id; let community_id = data.community_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let mut community_view = blocking(context.pool(), move |conn| { let mut community_view = blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, Some(user_id)) CommunityView::read(conn, community_id, Some(person_id))
}) })
.await??; .await??;
@ -553,11 +560,11 @@ impl Perform for GetFollowedCommunities {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<GetFollowedCommunitiesResponse, LemmyError> { ) -> Result<GetFollowedCommunitiesResponse, LemmyError> {
let data: &GetFollowedCommunities = &self; let data: &GetFollowedCommunities = &self;
let user = get_user_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 communities = match blocking(context.pool(), move |conn| { let communities = match blocking(context.pool(), move |conn| {
CommunityFollowerView::for_user(conn, user_id) CommunityFollowerView::for_person(conn, person_id)
}) })
.await? .await?
{ {
@ -580,21 +587,21 @@ impl Perform for BanFromCommunity {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<BanFromCommunityResponse, LemmyError> { ) -> Result<BanFromCommunityResponse, LemmyError> {
let data: &BanFromCommunity = &self; let data: &BanFromCommunity = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let community_id = data.community_id; let community_id = data.community_id;
let banned_user_id = data.user_id; let banned_person_id = data.person_id;
// Verify that only mods or admins can ban // Verify that only mods or admins can ban
is_mod_or_admin(context.pool(), user.id, community_id).await?; is_mod_or_admin(context.pool(), local_user_view.person.id, community_id).await?;
let community_user_ban_form = CommunityUserBanForm { let community_user_ban_form = CommunityPersonBanForm {
community_id: data.community_id, community_id: data.community_id,
user_id: data.user_id, person_id: data.person_id,
}; };
if data.ban { if data.ban {
let ban = move |conn: &'_ _| CommunityUserBan::ban(conn, &community_user_ban_form); let ban = move |conn: &'_ _| CommunityPersonBan::ban(conn, &community_user_ban_form);
if blocking(context.pool(), ban).await?.is_err() { if blocking(context.pool(), ban).await?.is_err() {
return Err(ApiError::err("community_user_already_banned").into()); return Err(ApiError::err("community_user_already_banned").into());
} }
@ -602,7 +609,7 @@ impl Perform for BanFromCommunity {
// Also unsubscribe them from the community, if they are subscribed // Also unsubscribe them from the community, if they are subscribed
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: data.community_id, community_id: data.community_id,
user_id: banned_user_id, person_id: banned_person_id,
pending: false, pending: false,
}; };
blocking(context.pool(), move |conn: &'_ _| { blocking(context.pool(), move |conn: &'_ _| {
@ -611,7 +618,7 @@ impl Perform for BanFromCommunity {
.await? .await?
.ok(); .ok();
} else { } else {
let unban = move |conn: &'_ _| CommunityUserBan::unban(conn, &community_user_ban_form); let unban = move |conn: &'_ _| CommunityPersonBan::unban(conn, &community_user_ban_form);
if blocking(context.pool(), unban).await?.is_err() { if blocking(context.pool(), unban).await?.is_err() {
return Err(ApiError::err("community_user_already_banned").into()); return Err(ApiError::err("community_user_already_banned").into());
} }
@ -621,7 +628,7 @@ impl Perform for BanFromCommunity {
if data.remove_data { if data.remove_data {
// Posts // Posts
blocking(context.pool(), move |conn: &'_ _| { blocking(context.pool(), move |conn: &'_ _| {
Post::update_removed_for_creator(conn, banned_user_id, Some(community_id), true) Post::update_removed_for_creator(conn, banned_person_id, Some(community_id), true)
}) })
.await??; .await??;
@ -629,7 +636,7 @@ impl Perform for BanFromCommunity {
// TODO Diesel doesn't allow updates with joins, so this has to be a loop // TODO Diesel doesn't allow updates with joins, so this has to be a loop
let comments = blocking(context.pool(), move |conn| { let comments = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(conn) CommentQueryBuilder::create(conn)
.creator_id(banned_user_id) .creator_id(banned_person_id)
.community_id(community_id) .community_id(community_id)
.limit(std::i64::MAX) .limit(std::i64::MAX)
.list() .list()
@ -653,8 +660,8 @@ impl Perform for BanFromCommunity {
}; };
let form = ModBanFromCommunityForm { let form = ModBanFromCommunityForm {
mod_user_id: user.id, mod_person_id: local_user_view.person.id,
other_user_id: data.user_id, other_person_id: data.person_id,
community_id: data.community_id, community_id: data.community_id,
reason: data.reason.to_owned(), reason: data.reason.to_owned(),
banned: Some(data.ban), banned: Some(data.ban),
@ -665,14 +672,14 @@ impl Perform for BanFromCommunity {
}) })
.await??; .await??;
let user_id = data.user_id; let person_id = data.person_id;
let user_view = blocking(context.pool(), move |conn| { let person_view = blocking(context.pool(), move |conn| {
UserViewSafe::read(conn, user_id) PersonViewSafe::read(conn, person_id)
}) })
.await??; .await??;
let res = BanFromCommunityResponse { let res = BanFromCommunityResponse {
user_view, person_view,
banned: data.ban, banned: data.ban,
}; };
@ -697,17 +704,17 @@ impl Perform for AddModToCommunity {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<AddModToCommunityResponse, LemmyError> { ) -> Result<AddModToCommunityResponse, LemmyError> {
let data: &AddModToCommunity = &self; let data: &AddModToCommunity = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let community_moderator_form = CommunityModeratorForm { let community_moderator_form = CommunityModeratorForm {
community_id: data.community_id, community_id: data.community_id,
user_id: data.user_id, person_id: data.person_id,
}; };
let community_id = data.community_id; let community_id = data.community_id;
// Verify that only mods or admins can add mod // Verify that only mods or admins can add mod
is_mod_or_admin(context.pool(), user.id, community_id).await?; is_mod_or_admin(context.pool(), local_user_view.person.id, community_id).await?;
if data.added { if data.added {
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form); let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
@ -723,8 +730,8 @@ impl Perform for AddModToCommunity {
// Mod tables // Mod tables
let form = ModAddCommunityForm { let form = ModAddCommunityForm {
mod_user_id: user.id, mod_person_id: local_user_view.person.id,
other_user_id: data.user_id, other_person_id: data.person_id,
community_id: data.community_id, community_id: data.community_id,
removed: Some(!data.added), removed: Some(!data.added),
}; };
@ -762,7 +769,7 @@ impl Perform for TransferCommunity {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<GetCommunityResponse, LemmyError> { ) -> Result<GetCommunityResponse, LemmyError> {
let data: &TransferCommunity = &self; let data: &TransferCommunity = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let community_id = data.community_id; let community_id = data.community_id;
let read_community = blocking(context.pool(), move |conn| { let read_community = blocking(context.pool(), move |conn| {
@ -775,25 +782,28 @@ impl Perform for TransferCommunity {
}) })
.await??; .await??;
let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??; let mut admins = blocking(context.pool(), move |conn| PersonViewSafe::admins(conn)).await??;
// Making sure the creator, if an admin, is at the top // Making sure the creator, if an admin, is at the top
let creator_index = admins let creator_index = admins
.iter() .iter()
.position(|r| r.user.id == site_creator_id) .position(|r| r.person.id == site_creator_id)
.context(location_info!())?; .context(location_info!())?;
let creator_user = admins.remove(creator_index); let creator_person = admins.remove(creator_index);
admins.insert(0, creator_user); admins.insert(0, creator_person);
// Make sure user is the creator, or an admin // Make sure user is the creator, or an admin
if user.id != read_community.creator_id if local_user_view.person.id != read_community.creator_id
&& !admins.iter().map(|a| a.user.id).any(|x| x == user.id) && !admins
.iter()
.map(|a| a.person.id)
.any(|x| x == local_user_view.person.id)
{ {
return Err(ApiError::err("not_an_admin").into()); return Err(ApiError::err("not_an_admin").into());
} }
let community_id = data.community_id; let community_id = data.community_id;
let new_creator = data.user_id; let new_creator = data.person_id;
let update = move |conn: &'_ _| Community::update_creator(conn, community_id, new_creator); let update = move |conn: &'_ _| Community::update_creator(conn, community_id, new_creator);
if blocking(context.pool(), update).await?.is_err() { if blocking(context.pool(), update).await?.is_err() {
return Err(ApiError::err("couldnt_update_community").into()); return Err(ApiError::err("couldnt_update_community").into());
@ -807,10 +817,10 @@ impl Perform for TransferCommunity {
.await??; .await??;
let creator_index = community_mods let creator_index = community_mods
.iter() .iter()
.position(|r| r.moderator.id == data.user_id) .position(|r| r.moderator.id == data.person_id)
.context(location_info!())?; .context(location_info!())?;
let creator_user = community_mods.remove(creator_index); let creator_person = community_mods.remove(creator_index);
community_mods.insert(0, creator_user); community_mods.insert(0, creator_person);
let community_id = data.community_id; let community_id = data.community_id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
@ -822,7 +832,7 @@ impl Perform for TransferCommunity {
for cmod in &community_mods { for cmod in &community_mods {
let community_moderator_form = CommunityModeratorForm { let community_moderator_form = CommunityModeratorForm {
community_id: cmod.community.id, community_id: cmod.community.id,
user_id: cmod.moderator.id, person_id: cmod.moderator.id,
}; };
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form); let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
@ -833,8 +843,8 @@ impl Perform for TransferCommunity {
// Mod tables // Mod tables
let form = ModAddCommunityForm { let form = ModAddCommunityForm {
mod_user_id: user.id, mod_person_id: local_user_view.person.id,
other_user_id: data.user_id, other_person_id: data.person_id,
community_id: data.community_id, community_id: data.community_id,
removed: Some(false), removed: Some(false),
}; };
@ -844,9 +854,9 @@ impl Perform for TransferCommunity {
.await??; .await??;
let community_id = data.community_id; let community_id = data.community_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let community_view = match blocking(context.pool(), move |conn| { let community_view = match blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, Some(user_id)) CommunityView::read(conn, community_id, Some(person_id))
}) })
.await? .await?
{ {
@ -879,7 +889,7 @@ fn send_community_websocket(
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
op: UserOperation, op: UserOperation,
) { ) {
// Strip out the user id and subscribed when sending to others // Strip out the person id and subscribed when sending to others
let mut res_sent = res.clone(); let mut res_sent = res.clone();
res_sent.community_view.subscribed = false; res_sent.community_view.subscribed = false;

View file

@ -3,16 +3,15 @@ use lemmy_api_structs::{
blocking, blocking,
comment::*, comment::*,
community::*, community::*,
person::*,
post::*, post::*,
site::*, site::*,
user::*,
websocket::*, websocket::*,
}; };
use lemmy_db_queries::{ use lemmy_db_queries::{
source::{ source::{
community::{CommunityModerator_, Community_}, community::{CommunityModerator_, Community_},
site::Site_, site::Site_,
user::UserSafeSettings_,
}, },
Crud, Crud,
DbPool, DbPool,
@ -21,10 +20,10 @@ use lemmy_db_schema::source::{
community::{Community, CommunityModerator}, community::{Community, CommunityModerator},
post::Post, post::Post,
site::Site, site::Site,
user::{UserSafeSettings, User_},
}; };
use lemmy_db_views::local_user_view::{LocalUserSettingsView, LocalUserView};
use lemmy_db_views_actor::{ use lemmy_db_views_actor::{
community_user_ban_view::CommunityUserBanView, community_person_ban_view::CommunityPersonBanView,
community_view::CommunityView, community_view::CommunityView,
}; };
use lemmy_utils::{ use lemmy_utils::{
@ -41,10 +40,10 @@ use url::Url;
pub mod comment; pub mod comment;
pub mod community; pub mod community;
pub mod local_user;
pub mod post; pub mod post;
pub mod routes; pub mod routes;
pub mod site; pub mod site;
pub mod user;
pub mod websocket; pub mod websocket;
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
@ -60,11 +59,11 @@ pub trait Perform {
pub(crate) async fn is_mod_or_admin( pub(crate) async fn is_mod_or_admin(
pool: &DbPool, pool: &DbPool,
user_id: i32, person_id: i32,
community_id: i32, community_id: i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let is_mod_or_admin = blocking(pool, move |conn| { let is_mod_or_admin = blocking(pool, move |conn| {
CommunityView::is_mod_or_admin(conn, user_id, community_id) CommunityView::is_mod_or_admin(conn, person_id, community_id)
}) })
.await?; .await?;
if !is_mod_or_admin { if !is_mod_or_admin {
@ -72,9 +71,9 @@ pub(crate) async fn is_mod_or_admin(
} }
Ok(()) Ok(())
} }
pub async fn is_admin(pool: &DbPool, user_id: i32) -> Result<(), LemmyError> {
let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??; pub fn is_admin(local_user_view: &LocalUserView) -> Result<(), LemmyError> {
if !user.admin { if !local_user_view.local_user.admin {
return Err(ApiError::err("not_an_admin").into()); return Err(ApiError::err("not_an_admin").into());
} }
Ok(()) Ok(())
@ -87,63 +86,73 @@ pub(crate) async fn get_post(post_id: i32, pool: &DbPool) -> Result<Post, LemmyE
} }
} }
pub(crate) async fn get_user_from_jwt(jwt: &str, pool: &DbPool) -> Result<User_, LemmyError> { pub(crate) async fn get_local_user_view_from_jwt(
jwt: &str,
pool: &DbPool,
) -> Result<LocalUserView, LemmyError> {
let claims = match Claims::decode(&jwt) { let claims = match Claims::decode(&jwt) {
Ok(claims) => claims.claims, Ok(claims) => claims.claims,
Err(_e) => return Err(ApiError::err("not_logged_in").into()), Err(_e) => return Err(ApiError::err("not_logged_in").into()),
}; };
let user_id = claims.id; let local_user_id = claims.local_user_id;
let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??; let local_user_view =
blocking(pool, move |conn| LocalUserView::read(conn, local_user_id)).await??;
// Check for a site ban // Check for a site ban
if user.banned { if local_user_view.person.banned {
return Err(ApiError::err("site_ban").into()); return Err(ApiError::err("site_ban").into());
} }
Ok(user) Ok(local_user_view)
} }
pub(crate) async fn get_user_from_jwt_opt( pub(crate) async fn get_local_user_view_from_jwt_opt(
jwt: &Option<String>, jwt: &Option<String>,
pool: &DbPool, pool: &DbPool,
) -> Result<Option<User_>, LemmyError> { ) -> Result<Option<LocalUserView>, LemmyError> {
match jwt { match jwt {
Some(jwt) => Ok(Some(get_user_from_jwt(jwt, pool).await?)), Some(jwt) => Ok(Some(get_local_user_view_from_jwt(jwt, pool).await?)),
None => Ok(None), None => Ok(None),
} }
} }
pub(crate) async fn get_user_safe_settings_from_jwt( pub(crate) async fn get_local_user_settings_view_from_jwt(
jwt: &str, jwt: &str,
pool: &DbPool, pool: &DbPool,
) -> Result<UserSafeSettings, LemmyError> { ) -> Result<LocalUserSettingsView, LemmyError> {
let claims = match Claims::decode(&jwt) { let claims = match Claims::decode(&jwt) {
Ok(claims) => claims.claims, Ok(claims) => claims.claims,
Err(_e) => return Err(ApiError::err("not_logged_in").into()), Err(_e) => return Err(ApiError::err("not_logged_in").into()),
}; };
let user_id = claims.id; let local_user_id = claims.local_user_id;
let user = blocking(pool, move |conn| UserSafeSettings::read(conn, user_id)).await??; let local_user_view = blocking(pool, move |conn| {
LocalUserSettingsView::read(conn, local_user_id)
})
.await??;
// Check for a site ban // Check for a site ban
if user.banned { if local_user_view.person.banned {
return Err(ApiError::err("site_ban").into()); return Err(ApiError::err("site_ban").into());
} }
Ok(user) Ok(local_user_view)
} }
pub(crate) async fn get_user_safe_settings_from_jwt_opt( pub(crate) async fn get_local_user_settings_view_from_jwt_opt(
jwt: &Option<String>, jwt: &Option<String>,
pool: &DbPool, pool: &DbPool,
) -> Result<Option<UserSafeSettings>, LemmyError> { ) -> Result<Option<LocalUserSettingsView>, LemmyError> {
match jwt { match jwt {
Some(jwt) => Ok(Some(get_user_safe_settings_from_jwt(jwt, pool).await?)), Some(jwt) => Ok(Some(
get_local_user_settings_view_from_jwt(jwt, pool).await?,
)),
None => Ok(None), None => Ok(None),
} }
} }
pub(crate) async fn check_community_ban( pub(crate) async fn check_community_ban(
user_id: i32, person_id: i32,
community_id: i32, community_id: i32,
pool: &DbPool, pool: &DbPool,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let is_banned = move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok(); let is_banned =
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
if blocking(pool, is_banned).await? { if blocking(pool, is_banned).await? {
Err(ApiError::err("community_ban").into()) Err(ApiError::err("community_ban").into())
} else { } else {
@ -165,21 +174,21 @@ pub(crate) async fn check_downvotes_enabled(score: i16, pool: &DbPool) -> Result
/// or if a community_id is supplied validates the user is a moderator /// or if a community_id is supplied validates the user is a moderator
/// of that community and returns the community id in a vec /// of that community and returns the community id in a vec
/// ///
/// * `user_id` - the user id of the moderator /// * `person_id` - the person id of the moderator
/// * `community_id` - optional community id to check for moderator privileges /// * `community_id` - optional community id to check for moderator privileges
/// * `pool` - the diesel db pool /// * `pool` - the diesel db pool
pub(crate) async fn collect_moderated_communities( pub(crate) async fn collect_moderated_communities(
user_id: i32, person_id: i32,
community_id: Option<i32>, community_id: Option<i32>,
pool: &DbPool, pool: &DbPool,
) -> Result<Vec<i32>, LemmyError> { ) -> Result<Vec<i32>, LemmyError> {
if let Some(community_id) = community_id { if let Some(community_id) = community_id {
// if the user provides a community_id, just check for mod/admin privileges // if the user provides a community_id, just check for mod/admin privileges
is_mod_or_admin(pool, user_id, community_id).await?; is_mod_or_admin(pool, person_id, community_id).await?;
Ok(vec![community_id]) Ok(vec![community_id])
} else { } else {
let ids = blocking(pool, move |conn: &'_ _| { let ids = blocking(pool, move |conn: &'_ _| {
CommunityModerator::get_user_moderated_communities(conn, user_id) CommunityModerator::get_person_moderated_communities(conn, person_id)
}) })
.await??; .await??;
Ok(ids) Ok(ids)
@ -236,17 +245,17 @@ pub async fn match_websocket_operation(
UserOperation::Login => do_websocket_operation::<Login>(context, id, op, data).await, UserOperation::Login => do_websocket_operation::<Login>(context, id, op, data).await,
UserOperation::Register => do_websocket_operation::<Register>(context, id, op, data).await, UserOperation::Register => do_websocket_operation::<Register>(context, id, op, data).await,
UserOperation::GetCaptcha => do_websocket_operation::<GetCaptcha>(context, id, op, data).await, UserOperation::GetCaptcha => do_websocket_operation::<GetCaptcha>(context, id, op, data).await,
UserOperation::GetUserDetails => { UserOperation::GetPersonDetails => {
do_websocket_operation::<GetUserDetails>(context, id, op, data).await do_websocket_operation::<GetPersonDetails>(context, id, op, data).await
} }
UserOperation::GetReplies => do_websocket_operation::<GetReplies>(context, id, op, data).await, UserOperation::GetReplies => do_websocket_operation::<GetReplies>(context, id, op, data).await,
UserOperation::AddAdmin => do_websocket_operation::<AddAdmin>(context, id, op, data).await, UserOperation::AddAdmin => do_websocket_operation::<AddAdmin>(context, id, op, data).await,
UserOperation::BanUser => do_websocket_operation::<BanUser>(context, id, op, data).await, UserOperation::BanPerson => do_websocket_operation::<BanPerson>(context, id, op, data).await,
UserOperation::GetUserMentions => { UserOperation::GetPersonMentions => {
do_websocket_operation::<GetUserMentions>(context, id, op, data).await do_websocket_operation::<GetPersonMentions>(context, id, op, data).await
} }
UserOperation::MarkUserMentionAsRead => { UserOperation::MarkPersonMentionAsRead => {
do_websocket_operation::<MarkUserMentionAsRead>(context, id, op, data).await do_websocket_operation::<MarkPersonMentionAsRead>(context, id, op, data).await
} }
UserOperation::MarkAllAsRead => { UserOperation::MarkAllAsRead => {
do_websocket_operation::<MarkAllAsRead>(context, id, op, data).await do_websocket_operation::<MarkAllAsRead>(context, id, op, data).await

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@ use crate::{
check_community_ban, check_community_ban,
check_downvotes_enabled, check_downvotes_enabled,
collect_moderated_communities, collect_moderated_communities,
get_user_from_jwt, get_local_user_view_from_jwt,
get_user_from_jwt_opt, get_local_user_view_from_jwt_opt,
is_mod_or_admin, is_mod_or_admin,
Perform, Perform,
}; };
@ -60,7 +60,7 @@ impl Perform for CreatePost {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<PostResponse, LemmyError> { ) -> Result<PostResponse, LemmyError> {
let data: &CreatePost = &self; let data: &CreatePost = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
check_slurs(&data.name)?; check_slurs(&data.name)?;
check_slurs_opt(&data.body)?; check_slurs_opt(&data.body)?;
@ -69,7 +69,7 @@ impl Perform for CreatePost {
return Err(ApiError::err("invalid_post_title").into()); return Err(ApiError::err("invalid_post_title").into());
} }
check_community_ban(user.id, data.community_id, context.pool()).await?; check_community_ban(local_user_view.person.id, data.community_id, context.pool()).await?;
// Fetch Iframely and pictrs cached image // Fetch Iframely and pictrs cached image
let data_url = data.url.as_ref(); let data_url = data.url.as_ref();
@ -81,7 +81,7 @@ impl Perform for CreatePost {
url: data_url.map(|u| u.to_owned().into()), url: data_url.map(|u| u.to_owned().into()),
body: data.body.to_owned(), body: data.body.to_owned(),
community_id: data.community_id, community_id: data.community_id,
creator_id: user.id, creator_id: local_user_view.person.id,
removed: None, removed: None,
deleted: None, deleted: None,
nsfw: data.nsfw, nsfw: data.nsfw,
@ -122,12 +122,14 @@ impl Perform for CreatePost {
Err(_e) => return Err(ApiError::err("couldnt_create_post").into()), Err(_e) => return Err(ApiError::err("couldnt_create_post").into()),
}; };
updated_post.send_create(&user, context).await?; updated_post
.send_create(&local_user_view.person, context)
.await?;
// They like their own post by default // They like their own post by default
let like_form = PostLikeForm { let like_form = PostLikeForm {
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: user.id, person_id: local_user_view.person.id,
score: 1, score: 1,
}; };
@ -136,12 +138,14 @@ impl Perform for CreatePost {
return Err(ApiError::err("couldnt_like_post").into()); return Err(ApiError::err("couldnt_like_post").into());
} }
updated_post.send_like(&user, context).await?; updated_post
.send_like(&local_user_view.person, context)
.await?;
// Refetch the view // Refetch the view
let inserted_post_id = inserted_post.id; let inserted_post_id = inserted_post.id;
let post_view = match blocking(context.pool(), move |conn| { let post_view = match blocking(context.pool(), move |conn| {
PostView::read(conn, inserted_post_id, Some(user.id)) PostView::read(conn, inserted_post_id, Some(local_user_view.person.id))
}) })
.await? .await?
{ {
@ -171,12 +175,12 @@ impl Perform for GetPost {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<GetPostResponse, LemmyError> { ) -> Result<GetPostResponse, LemmyError> {
let data: &GetPost = &self; let data: &GetPost = &self;
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
let user_id = user.map(|u| u.id); let person_id = local_user_view.map(|u| u.person.id);
let id = data.id; let id = data.id;
let post_view = match blocking(context.pool(), move |conn| { let post_view = match blocking(context.pool(), move |conn| {
PostView::read(conn, id, user_id) PostView::read(conn, id, person_id)
}) })
.await? .await?
{ {
@ -187,7 +191,7 @@ impl Perform for GetPost {
let id = data.id; let id = data.id;
let comments = blocking(context.pool(), move |conn| { let comments = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(conn) CommentQueryBuilder::create(conn)
.my_user_id(user_id) .my_person_id(person_id)
.post_id(id) .post_id(id)
.limit(9999) .limit(9999)
.list() .list()
@ -202,7 +206,7 @@ impl Perform for GetPost {
// Necessary for the sidebar // Necessary for the sidebar
let community_view = match blocking(context.pool(), move |conn| { let community_view = match blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, user_id) CommunityView::read(conn, community_id, person_id)
}) })
.await? .await?
{ {
@ -237,15 +241,15 @@ impl Perform for GetPosts {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<GetPostsResponse, LemmyError> { ) -> Result<GetPostsResponse, LemmyError> {
let data: &GetPosts = &self; let data: &GetPosts = &self;
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
let user_id = match &user { let person_id = match &local_user_view {
Some(user) => Some(user.id), Some(uv) => Some(uv.person.id),
None => None, None => None,
}; };
let show_nsfw = match &user { let show_nsfw = match &local_user_view {
Some(user) => user.show_nsfw, Some(uv) => uv.local_user.show_nsfw,
None => false, None => false,
}; };
@ -263,7 +267,7 @@ impl Perform for GetPosts {
.show_nsfw(show_nsfw) .show_nsfw(show_nsfw)
.community_id(community_id) .community_id(community_id)
.community_name(community_name) .community_name(community_name)
.my_user_id(user_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.list() .list()
@ -288,7 +292,7 @@ impl Perform for CreatePostLike {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<PostResponse, LemmyError> { ) -> Result<PostResponse, LemmyError> {
let data: &CreatePostLike = &self; let data: &CreatePostLike = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Don't do a downvote if site has downvotes disabled // Don't do a downvote if site has downvotes disabled
check_downvotes_enabled(data.score, context.pool()).await?; check_downvotes_enabled(data.score, context.pool()).await?;
@ -297,18 +301,18 @@ impl Perform for CreatePostLike {
let post_id = data.post_id; let post_id = data.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_community_ban(user.id, post.community_id, context.pool()).await?; check_community_ban(local_user_view.person.id, post.community_id, context.pool()).await?;
let like_form = PostLikeForm { let like_form = PostLikeForm {
post_id: data.post_id, post_id: data.post_id,
user_id: user.id, person_id: local_user_view.person.id,
score: data.score, score: data.score,
}; };
// Remove any likes first // Remove any likes first
let user_id = user.id; let person_id = local_user_view.person.id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
PostLike::remove(conn, user_id, post_id) PostLike::remove(conn, person_id, post_id)
}) })
.await??; .await??;
@ -322,18 +326,20 @@ impl Perform for CreatePostLike {
} }
if like_form.score == 1 { if like_form.score == 1 {
post.send_like(&user, context).await?; post.send_like(&local_user_view.person, context).await?;
} else if like_form.score == -1 { } else if like_form.score == -1 {
post.send_dislike(&user, context).await?; post.send_dislike(&local_user_view.person, context).await?;
} }
} else { } else {
post.send_undo_like(&user, context).await?; post
.send_undo_like(&local_user_view.person, context)
.await?;
} }
let post_id = data.post_id; let post_id = data.post_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let post_view = match blocking(context.pool(), move |conn| { let post_view = match blocking(context.pool(), move |conn| {
PostView::read(conn, post_id, Some(user_id)) PostView::read(conn, post_id, Some(person_id))
}) })
.await? .await?
{ {
@ -363,7 +369,7 @@ impl Perform for EditPost {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<PostResponse, LemmyError> { ) -> Result<PostResponse, LemmyError> {
let data: &EditPost = &self; let data: &EditPost = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
check_slurs(&data.name)?; check_slurs(&data.name)?;
check_slurs_opt(&data.body)?; check_slurs_opt(&data.body)?;
@ -375,10 +381,15 @@ impl Perform for EditPost {
let post_id = data.post_id; let post_id = data.post_id;
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_community_ban(user.id, orig_post.community_id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_post.community_id,
context.pool(),
)
.await?;
// Verify that only the creator can edit // Verify that only the creator can edit
if !Post::is_post_creator(user.id, orig_post.creator_id) { if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
return Err(ApiError::err("no_post_edit_allowed").into()); return Err(ApiError::err("no_post_edit_allowed").into());
} }
@ -427,11 +438,13 @@ impl Perform for EditPost {
}; };
// Send apub update // Send apub update
updated_post.send_update(&user, context).await?; updated_post
.send_update(&local_user_view.person, context)
.await?;
let post_id = data.post_id; let post_id = data.post_id;
let post_view = blocking(context.pool(), move |conn| { let post_view = blocking(context.pool(), move |conn| {
PostView::read(conn, post_id, Some(user.id)) PostView::read(conn, post_id, Some(local_user_view.person.id))
}) })
.await??; .await??;
@ -457,15 +470,20 @@ impl Perform for DeletePost {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<PostResponse, LemmyError> { ) -> Result<PostResponse, LemmyError> {
let data: &DeletePost = &self; let data: &DeletePost = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let post_id = data.post_id; let post_id = data.post_id;
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_community_ban(user.id, orig_post.community_id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_post.community_id,
context.pool(),
)
.await?;
// Verify that only the creator can delete // Verify that only the creator can delete
if !Post::is_post_creator(user.id, orig_post.creator_id) { if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
return Err(ApiError::err("no_post_edit_allowed").into()); return Err(ApiError::err("no_post_edit_allowed").into());
} }
@ -479,15 +497,19 @@ impl Perform for DeletePost {
// apub updates // apub updates
if deleted { if deleted {
updated_post.send_delete(&user, context).await?; updated_post
.send_delete(&local_user_view.person, context)
.await?;
} else { } else {
updated_post.send_undo_delete(&user, context).await?; updated_post
.send_undo_delete(&local_user_view.person, context)
.await?;
} }
// Refetch the post // Refetch the post
let post_id = data.post_id; let post_id = data.post_id;
let post_view = blocking(context.pool(), move |conn| { let post_view = blocking(context.pool(), move |conn| {
PostView::read(conn, post_id, Some(user.id)) PostView::read(conn, post_id, Some(local_user_view.person.id))
}) })
.await??; .await??;
@ -513,15 +535,25 @@ impl Perform for RemovePost {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<PostResponse, LemmyError> { ) -> Result<PostResponse, LemmyError> {
let data: &RemovePost = &self; let data: &RemovePost = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let post_id = data.post_id; let post_id = data.post_id;
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_community_ban(user.id, orig_post.community_id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_post.community_id,
context.pool(),
)
.await?;
// Verify that only the mods can remove // Verify that only the mods can remove
is_mod_or_admin(context.pool(), user.id, orig_post.community_id).await?; is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_post.community_id,
)
.await?;
// Update the post // Update the post
let post_id = data.post_id; let post_id = data.post_id;
@ -533,7 +565,7 @@ impl Perform for RemovePost {
// Mod tables // Mod tables
let form = ModRemovePostForm { let form = ModRemovePostForm {
mod_user_id: user.id, mod_person_id: local_user_view.person.id,
post_id: data.post_id, post_id: data.post_id,
removed: Some(removed), removed: Some(removed),
reason: data.reason.to_owned(), reason: data.reason.to_owned(),
@ -545,16 +577,20 @@ impl Perform for RemovePost {
// apub updates // apub updates
if removed { if removed {
updated_post.send_remove(&user, context).await?; updated_post
.send_remove(&local_user_view.person, context)
.await?;
} else { } else {
updated_post.send_undo_remove(&user, context).await?; updated_post
.send_undo_remove(&local_user_view.person, context)
.await?;
} }
// Refetch the post // Refetch the post
let post_id = data.post_id; let post_id = data.post_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let post_view = blocking(context.pool(), move |conn| { let post_view = blocking(context.pool(), move |conn| {
PostView::read(conn, post_id, Some(user_id)) PostView::read(conn, post_id, Some(person_id))
}) })
.await??; .await??;
@ -580,15 +616,25 @@ impl Perform for LockPost {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<PostResponse, LemmyError> { ) -> Result<PostResponse, LemmyError> {
let data: &LockPost = &self; let data: &LockPost = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let post_id = data.post_id; let post_id = data.post_id;
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_community_ban(user.id, orig_post.community_id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_post.community_id,
context.pool(),
)
.await?;
// Verify that only the mods can lock // Verify that only the mods can lock
is_mod_or_admin(context.pool(), user.id, orig_post.community_id).await?; is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_post.community_id,
)
.await?;
// Update the post // Update the post
let post_id = data.post_id; let post_id = data.post_id;
@ -600,19 +646,21 @@ impl Perform for LockPost {
// Mod tables // Mod tables
let form = ModLockPostForm { let form = ModLockPostForm {
mod_user_id: user.id, mod_person_id: local_user_view.person.id,
post_id: data.post_id, post_id: data.post_id,
locked: Some(locked), locked: Some(locked),
}; };
blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??; blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??;
// apub updates // apub updates
updated_post.send_update(&user, context).await?; updated_post
.send_update(&local_user_view.person, context)
.await?;
// Refetch the post // Refetch the post
let post_id = data.post_id; let post_id = data.post_id;
let post_view = blocking(context.pool(), move |conn| { let post_view = blocking(context.pool(), move |conn| {
PostView::read(conn, post_id, Some(user.id)) PostView::read(conn, post_id, Some(local_user_view.person.id))
}) })
.await??; .await??;
@ -638,15 +686,25 @@ impl Perform for StickyPost {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<PostResponse, LemmyError> { ) -> Result<PostResponse, LemmyError> {
let data: &StickyPost = &self; let data: &StickyPost = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let post_id = data.post_id; let post_id = data.post_id;
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_community_ban(user.id, orig_post.community_id, context.pool()).await?; check_community_ban(
local_user_view.person.id,
orig_post.community_id,
context.pool(),
)
.await?;
// Verify that only the mods can sticky // Verify that only the mods can sticky
is_mod_or_admin(context.pool(), user.id, orig_post.community_id).await?; is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_post.community_id,
)
.await?;
// Update the post // Update the post
let post_id = data.post_id; let post_id = data.post_id;
@ -658,7 +716,7 @@ impl Perform for StickyPost {
// Mod tables // Mod tables
let form = ModStickyPostForm { let form = ModStickyPostForm {
mod_user_id: user.id, mod_person_id: local_user_view.person.id,
post_id: data.post_id, post_id: data.post_id,
stickied: Some(stickied), stickied: Some(stickied),
}; };
@ -669,12 +727,14 @@ impl Perform for StickyPost {
// Apub updates // Apub updates
// TODO stickied should pry work like locked for ease of use // TODO stickied should pry work like locked for ease of use
updated_post.send_update(&user, context).await?; updated_post
.send_update(&local_user_view.person, context)
.await?;
// Refetch the post // Refetch the post
let post_id = data.post_id; let post_id = data.post_id;
let post_view = blocking(context.pool(), move |conn| { let post_view = blocking(context.pool(), move |conn| {
PostView::read(conn, post_id, Some(user.id)) PostView::read(conn, post_id, Some(local_user_view.person.id))
}) })
.await??; .await??;
@ -700,11 +760,11 @@ impl Perform for SavePost {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<PostResponse, LemmyError> { ) -> Result<PostResponse, LemmyError> {
let data: &SavePost = &self; let data: &SavePost = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let post_saved_form = PostSavedForm { let post_saved_form = PostSavedForm {
post_id: data.post_id, post_id: data.post_id,
user_id: user.id, person_id: local_user_view.person.id,
}; };
if data.save { if data.save {
@ -720,9 +780,9 @@ impl Perform for SavePost {
} }
let post_id = data.post_id; let post_id = data.post_id;
let user_id = user.id; let person_id = local_user_view.person.id;
let post_view = blocking(context.pool(), move |conn| { let post_view = blocking(context.pool(), move |conn| {
PostView::read(conn, post_id, Some(user_id)) PostView::read(conn, post_id, Some(person_id))
}) })
.await??; .await??;
@ -741,7 +801,7 @@ impl Perform for CreatePostReport {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<CreatePostReportResponse, LemmyError> { ) -> Result<CreatePostReportResponse, LemmyError> {
let data: &CreatePostReport = &self; let data: &CreatePostReport = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// check size of report and check for whitespace // check size of report and check for whitespace
let reason = data.reason.trim(); let reason = data.reason.trim();
@ -752,17 +812,17 @@ impl Perform for CreatePostReport {
return Err(ApiError::err("report_too_long").into()); return Err(ApiError::err("report_too_long").into());
} }
let user_id = user.id; let person_id = local_user_view.person.id;
let post_id = data.post_id; let post_id = data.post_id;
let post_view = blocking(context.pool(), move |conn| { let post_view = blocking(context.pool(), move |conn| {
PostView::read(&conn, post_id, None) PostView::read(&conn, post_id, None)
}) })
.await??; .await??;
check_community_ban(user_id, post_view.community.id, context.pool()).await?; check_community_ban(person_id, post_view.community.id, context.pool()).await?;
let report_form = PostReportForm { let report_form = PostReportForm {
creator_id: user_id, creator_id: person_id,
post_id, post_id,
original_post_name: post_view.post.name, original_post_name: post_view.post.name,
original_post_url: post_view.post.url, original_post_url: post_view.post.url,
@ -784,7 +844,7 @@ impl Perform for CreatePostReport {
context.chat_server().do_send(SendUserRoomMessage { context.chat_server().do_send(SendUserRoomMessage {
op: UserOperation::CreatePostReport, op: UserOperation::CreatePostReport,
response: res.clone(), response: res.clone(),
recipient_id: user.id, local_recipient_id: local_user_view.local_user.id,
websocket_id, websocket_id,
}); });
@ -810,7 +870,7 @@ impl Perform for ResolvePostReport {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<ResolvePostReportResponse, LemmyError> { ) -> Result<ResolvePostReportResponse, LemmyError> {
let data: &ResolvePostReport = &self; let data: &ResolvePostReport = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let report_id = data.report_id; let report_id = data.report_id;
let report = blocking(context.pool(), move |conn| { let report = blocking(context.pool(), move |conn| {
@ -818,15 +878,15 @@ impl Perform for ResolvePostReport {
}) })
.await??; .await??;
let user_id = user.id; let person_id = local_user_view.person.id;
is_mod_or_admin(context.pool(), user_id, report.community.id).await?; is_mod_or_admin(context.pool(), person_id, report.community.id).await?;
let resolved = data.resolved; let resolved = data.resolved;
let resolve_fun = move |conn: &'_ _| { let resolve_fun = move |conn: &'_ _| {
if resolved { if resolved {
PostReport::resolve(conn, report_id, user_id) PostReport::resolve(conn, report_id, person_id)
} else { } else {
PostReport::unresolve(conn, report_id, user_id) PostReport::unresolve(conn, report_id, person_id)
} }
}; };
@ -862,12 +922,12 @@ impl Perform for ListPostReports {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<ListPostReportsResponse, LemmyError> { ) -> Result<ListPostReportsResponse, LemmyError> {
let data: &ListPostReports = &self; let data: &ListPostReports = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
let user_id = user.id; let person_id = local_user_view.person.id;
let community_id = data.community; let community_id = data.community;
let community_ids = let community_ids =
collect_moderated_communities(user_id, community_id, context.pool()).await?; collect_moderated_communities(person_id, community_id, context.pool()).await?;
let page = data.page; let page = data.page;
let limit = data.limit; let limit = data.limit;
@ -885,7 +945,7 @@ impl Perform for ListPostReports {
context.chat_server().do_send(SendUserRoomMessage { context.chat_server().do_send(SendUserRoomMessage {
op: UserOperation::ListPostReports, op: UserOperation::ListPostReports,
response: res.clone(), response: res.clone(),
recipient_id: user.id, local_recipient_id: local_user_view.local_user.id,
websocket_id, websocket_id,
}); });

View file

@ -1,6 +1,6 @@
use crate::Perform; use crate::Perform;
use actix_web::{error::ErrorBadRequest, *}; use actix_web::{error::ErrorBadRequest, *};
use lemmy_api_structs::{comment::*, community::*, post::*, site::*, user::*, websocket::*}; use lemmy_api_structs::{comment::*, community::*, person::*, post::*, site::*, websocket::*};
use lemmy_utils::rate_limit::RateLimit; use lemmy_utils::rate_limit::RateLimit;
use lemmy_websocket::{routes::chat_route, LemmyContext}; use lemmy_websocket::{routes::chat_route, LemmyContext};
use serde::Deserialize; use serde::Deserialize;
@ -137,11 +137,11 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
.service( .service(
web::scope("/user") web::scope("/user")
.wrap(rate_limit.message()) .wrap(rate_limit.message())
.route("", web::get().to(route_get::<GetUserDetails>)) .route("", web::get().to(route_get::<GetPersonDetails>))
.route("/mention", web::get().to(route_get::<GetUserMentions>)) .route("/mention", web::get().to(route_get::<GetPersonMentions>))
.route( .route(
"/mention/mark_as_read", "/mention/mark_as_read",
web::post().to(route_post::<MarkUserMentionAsRead>), web::post().to(route_post::<MarkPersonMentionAsRead>),
) )
.route("/replies", web::get().to(route_get::<GetReplies>)) .route("/replies", web::get().to(route_get::<GetReplies>))
.route( .route(
@ -150,7 +150,7 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
) )
.route("/join", web::post().to(route_post::<UserJoin>)) .route("/join", web::post().to(route_post::<UserJoin>))
// Admin action. I don't like that it's in /user // Admin action. I don't like that it's in /user
.route("/ban", web::post().to(route_post::<BanUser>)) .route("/ban", web::post().to(route_post::<BanPerson>))
// Account actions. I don't like that they're in /user maybe /accounts // Account actions. I don't like that they're in /user maybe /accounts
.route("/login", web::post().to(route_post::<Login>)) .route("/login", web::post().to(route_post::<Login>))
.route("/get_captcha", web::get().to(route_get::<GetCaptcha>)) .route("/get_captcha", web::get().to(route_get::<GetCaptcha>))

View file

@ -1,15 +1,15 @@
use crate::{ use crate::{
build_federated_instances, build_federated_instances,
get_user_from_jwt, get_local_user_settings_view_from_jwt,
get_user_from_jwt_opt, get_local_user_settings_view_from_jwt_opt,
get_user_safe_settings_from_jwt, get_local_user_view_from_jwt,
get_user_safe_settings_from_jwt_opt, get_local_user_view_from_jwt_opt,
is_admin, is_admin,
Perform, Perform,
}; };
use actix_web::web::Data; use actix_web::web::Data;
use anyhow::Context; use anyhow::Context;
use lemmy_api_structs::{blocking, site::*, user::Register}; use lemmy_api_structs::{blocking, person::Register, site::*};
use lemmy_apub::fetcher::search::search_by_apub_id; use lemmy_apub::fetcher::search::search_by_apub_id;
use lemmy_db_queries::{ use lemmy_db_queries::{
diesel_option_overwrite_to_url, diesel_option_overwrite_to_url,
@ -32,7 +32,7 @@ use lemmy_db_views::{
}; };
use lemmy_db_views_actor::{ use lemmy_db_views_actor::{
community_view::CommunityQueryBuilder, community_view::CommunityQueryBuilder,
user_view::{UserQueryBuilder, UserViewSafe}, person_view::{PersonQueryBuilder, PersonViewSafe},
}; };
use lemmy_db_views_moderator::{ use lemmy_db_views_moderator::{
mod_add_community_view::ModAddCommunityView, mod_add_community_view::ModAddCommunityView,
@ -74,36 +74,36 @@ impl Perform for GetModlog {
let data: &GetModlog = &self; let data: &GetModlog = &self;
let community_id = data.community_id; let community_id = data.community_id;
let mod_user_id = data.mod_user_id; let mod_person_id = data.mod_person_id;
let page = data.page; let page = data.page;
let limit = data.limit; let limit = data.limit;
let removed_posts = blocking(context.pool(), move |conn| { let removed_posts = blocking(context.pool(), move |conn| {
ModRemovePostView::list(conn, community_id, mod_user_id, page, limit) ModRemovePostView::list(conn, community_id, mod_person_id, page, limit)
}) })
.await??; .await??;
let locked_posts = blocking(context.pool(), move |conn| { let locked_posts = blocking(context.pool(), move |conn| {
ModLockPostView::list(conn, community_id, mod_user_id, page, limit) ModLockPostView::list(conn, community_id, mod_person_id, page, limit)
}) })
.await??; .await??;
let stickied_posts = blocking(context.pool(), move |conn| { let stickied_posts = blocking(context.pool(), move |conn| {
ModStickyPostView::list(conn, community_id, mod_user_id, page, limit) ModStickyPostView::list(conn, community_id, mod_person_id, page, limit)
}) })
.await??; .await??;
let removed_comments = blocking(context.pool(), move |conn| { let removed_comments = blocking(context.pool(), move |conn| {
ModRemoveCommentView::list(conn, community_id, mod_user_id, page, limit) ModRemoveCommentView::list(conn, community_id, mod_person_id, page, limit)
}) })
.await??; .await??;
let banned_from_community = blocking(context.pool(), move |conn| { let banned_from_community = blocking(context.pool(), move |conn| {
ModBanFromCommunityView::list(conn, community_id, mod_user_id, page, limit) ModBanFromCommunityView::list(conn, community_id, mod_person_id, page, limit)
}) })
.await??; .await??;
let added_to_community = blocking(context.pool(), move |conn| { let added_to_community = blocking(context.pool(), move |conn| {
ModAddCommunityView::list(conn, community_id, mod_user_id, page, limit) ModAddCommunityView::list(conn, community_id, mod_person_id, page, limit)
}) })
.await??; .await??;
@ -111,9 +111,9 @@ impl Perform for GetModlog {
let (removed_communities, banned, added) = if data.community_id.is_none() { let (removed_communities, banned, added) = if data.community_id.is_none() {
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
Ok(( Ok((
ModRemoveCommunityView::list(conn, mod_user_id, page, limit)?, ModRemoveCommunityView::list(conn, mod_person_id, page, limit)?,
ModBanView::list(conn, mod_user_id, page, limit)?, ModBanView::list(conn, mod_person_id, page, limit)?,
ModAddView::list(conn, mod_user_id, page, limit)?, ModAddView::list(conn, mod_person_id, page, limit)?,
)) as Result<_, LemmyError> )) as Result<_, LemmyError>
}) })
.await?? .await??
@ -152,20 +152,20 @@ impl Perform for CreateSite {
return Err(ApiError::err("site_already_exists").into()); return Err(ApiError::err("site_already_exists").into());
}; };
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
check_slurs(&data.name)?; check_slurs(&data.name)?;
check_slurs_opt(&data.description)?; check_slurs_opt(&data.description)?;
// Make sure user is an admin // Make sure user is an admin
is_admin(context.pool(), user.id).await?; is_admin(&local_user_view)?;
let site_form = SiteForm { let site_form = SiteForm {
name: data.name.to_owned(), name: data.name.to_owned(),
description: data.description.to_owned(), description: data.description.to_owned(),
icon: Some(data.icon.to_owned().map(|url| url.into())), icon: Some(data.icon.to_owned().map(|url| url.into())),
banner: Some(data.banner.to_owned().map(|url| url.into())), banner: Some(data.banner.to_owned().map(|url| url.into())),
creator_id: user.id, creator_id: local_user_view.person.id,
enable_downvotes: data.enable_downvotes, enable_downvotes: data.enable_downvotes,
open_registration: data.open_registration, open_registration: data.open_registration,
enable_nsfw: data.enable_nsfw, enable_nsfw: data.enable_nsfw,
@ -192,13 +192,13 @@ impl Perform for EditSite {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<SiteResponse, LemmyError> { ) -> Result<SiteResponse, LemmyError> {
let data: &EditSite = &self; let data: &EditSite = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
check_slurs(&data.name)?; check_slurs(&data.name)?;
check_slurs_opt(&data.description)?; check_slurs_opt(&data.description)?;
// Make sure user is an admin // Make sure user is an admin
is_admin(context.pool(), user.id).await?; is_admin(&local_user_view)?;
let found_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??; let found_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
@ -283,20 +283,20 @@ impl Perform for GetSite {
} }
}; };
let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??; let mut admins = blocking(context.pool(), move |conn| PersonViewSafe::admins(conn)).await??;
// Make sure the site creator is the top admin // Make sure the site creator is the top admin
if let Some(site_view) = site_view.to_owned() { if let Some(site_view) = site_view.to_owned() {
let site_creator_id = site_view.creator.id; let site_creator_id = site_view.creator.id;
// TODO investigate why this is sometimes coming back null // TODO investigate why this is sometimes coming back null
// Maybe user_.admin isn't being set to true? // Maybe user_.admin isn't being set to true?
if let Some(creator_index) = admins.iter().position(|r| r.user.id == site_creator_id) { if let Some(creator_index) = admins.iter().position(|r| r.person.id == site_creator_id) {
let creator_user = admins.remove(creator_index); let creator_person = admins.remove(creator_index);
admins.insert(0, creator_user); admins.insert(0, creator_person);
} }
} }
let banned = blocking(context.pool(), move |conn| UserViewSafe::banned(conn)).await??; let banned = blocking(context.pool(), move |conn| PersonViewSafe::banned(conn)).await??;
let online = context let online = context
.chat_server() .chat_server()
@ -304,7 +304,7 @@ impl Perform for GetSite {
.await .await
.unwrap_or(1); .unwrap_or(1);
let my_user = get_user_safe_settings_from_jwt_opt(&data.auth, context.pool()).await?; let my_user = get_local_user_settings_view_from_jwt_opt(&data.auth, context.pool()).await?;
let federated_instances = build_federated_instances(context.pool()).await?; let federated_instances = build_federated_instances(context.pool()).await?;
Ok(GetSiteResponse { Ok(GetSiteResponse {
@ -335,8 +335,8 @@ impl Perform for Search {
Err(e) => debug!("Failed to resolve search query as activitypub ID: {}", e), Err(e) => debug!("Failed to resolve search query as activitypub ID: {}", e),
} }
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
let user_id = user.map(|u| u.id); let person_id = local_user_view.map(|u| u.person.id);
let type_ = SearchType::from_str(&data.type_)?; let type_ = SearchType::from_str(&data.type_)?;
@ -361,7 +361,7 @@ impl Perform for Search {
.show_nsfw(true) .show_nsfw(true)
.community_id(community_id) .community_id(community_id)
.community_name(community_name) .community_name(community_name)
.my_user_id(user_id) .my_person_id(person_id)
.search_term(q) .search_term(q)
.page(page) .page(page)
.limit(limit) .limit(limit)
@ -374,7 +374,7 @@ impl Perform for Search {
CommentQueryBuilder::create(&conn) CommentQueryBuilder::create(&conn)
.sort(&sort) .sort(&sort)
.search_term(q) .search_term(q)
.my_user_id(user_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.list() .list()
@ -386,7 +386,7 @@ impl Perform for Search {
CommunityQueryBuilder::create(conn) CommunityQueryBuilder::create(conn)
.sort(&sort) .sort(&sort)
.search_term(q) .search_term(q)
.my_user_id(user_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.list() .list()
@ -395,7 +395,7 @@ impl Perform for Search {
} }
SearchType::Users => { SearchType::Users => {
users = blocking(context.pool(), move |conn| { users = blocking(context.pool(), move |conn| {
UserQueryBuilder::create(conn) PersonQueryBuilder::create(conn)
.sort(&sort) .sort(&sort)
.search_term(q) .search_term(q)
.page(page) .page(page)
@ -411,7 +411,7 @@ impl Perform for Search {
.show_nsfw(true) .show_nsfw(true)
.community_id(community_id) .community_id(community_id)
.community_name(community_name) .community_name(community_name)
.my_user_id(user_id) .my_person_id(person_id)
.search_term(q) .search_term(q)
.page(page) .page(page)
.limit(limit) .limit(limit)
@ -426,7 +426,7 @@ impl Perform for Search {
CommentQueryBuilder::create(conn) CommentQueryBuilder::create(conn)
.sort(&sort) .sort(&sort)
.search_term(q) .search_term(q)
.my_user_id(user_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.list() .list()
@ -440,7 +440,7 @@ impl Perform for Search {
CommunityQueryBuilder::create(conn) CommunityQueryBuilder::create(conn)
.sort(&sort) .sort(&sort)
.search_term(q) .search_term(q)
.my_user_id(user_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.list() .list()
@ -451,7 +451,7 @@ impl Perform for Search {
let sort = SortType::from_str(&data.sort)?; let sort = SortType::from_str(&data.sort)?;
users = blocking(context.pool(), move |conn| { users = blocking(context.pool(), move |conn| {
UserQueryBuilder::create(conn) PersonQueryBuilder::create(conn)
.sort(&sort) .sort(&sort)
.search_term(q) .search_term(q)
.page(page) .page(page)
@ -465,7 +465,7 @@ impl Perform for Search {
PostQueryBuilder::create(conn) PostQueryBuilder::create(conn)
.sort(&sort) .sort(&sort)
.show_nsfw(true) .show_nsfw(true)
.my_user_id(user_id) .my_person_id(person_id)
.community_id(community_id) .community_id(community_id)
.community_name(community_name) .community_name(community_name)
.url_search(q) .url_search(q)
@ -498,18 +498,18 @@ impl Perform for TransferSite {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<GetSiteResponse, LemmyError> { ) -> Result<GetSiteResponse, LemmyError> {
let data: &TransferSite = &self; let data: &TransferSite = &self;
let user = get_user_safe_settings_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
is_admin(context.pool(), user.id).await?; is_admin(&local_user_view)?;
let read_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??; let read_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
// Make sure user is the creator // Make sure user is the creator
if read_site.creator_id != user.id { if read_site.creator_id != local_user_view.person.id {
return Err(ApiError::err("not_an_admin").into()); return Err(ApiError::err("not_an_admin").into());
} }
let new_creator_id = data.user_id; let new_creator_id = data.person_id;
let transfer_site = move |conn: &'_ _| Site::transfer(conn, new_creator_id); let transfer_site = move |conn: &'_ _| Site::transfer(conn, new_creator_id);
if blocking(context.pool(), transfer_site).await?.is_err() { if blocking(context.pool(), transfer_site).await?.is_err() {
return Err(ApiError::err("couldnt_update_site").into()); return Err(ApiError::err("couldnt_update_site").into());
@ -517,8 +517,8 @@ impl Perform for TransferSite {
// Mod tables // Mod tables
let form = ModAddForm { let form = ModAddForm {
mod_user_id: user.id, mod_person_id: local_user_view.person.id,
other_user_id: data.user_id, other_person_id: data.person_id,
removed: Some(false), removed: Some(false),
}; };
@ -526,24 +526,26 @@ impl Perform for TransferSite {
let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??; let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??; let mut admins = blocking(context.pool(), move |conn| PersonViewSafe::admins(conn)).await??;
let creator_index = admins let creator_index = admins
.iter() .iter()
.position(|r| r.user.id == site_view.creator.id) .position(|r| r.person.id == site_view.creator.id)
.context(location_info!())?; .context(location_info!())?;
let creator_user = admins.remove(creator_index); let creator_person = admins.remove(creator_index);
admins.insert(0, creator_user); admins.insert(0, creator_person);
let banned = blocking(context.pool(), move |conn| UserViewSafe::banned(conn)).await??; let banned = blocking(context.pool(), move |conn| PersonViewSafe::banned(conn)).await??;
let federated_instances = build_federated_instances(context.pool()).await?; let federated_instances = build_federated_instances(context.pool()).await?;
let my_user = Some(get_local_user_settings_view_from_jwt(&data.auth, context.pool()).await?);
Ok(GetSiteResponse { Ok(GetSiteResponse {
site_view: Some(site_view), site_view: Some(site_view),
admins, admins,
banned, banned,
online: 0, online: 0,
version: version::VERSION.to_string(), version: version::VERSION.to_string(),
my_user: Some(user), my_user,
federated_instances, federated_instances,
}) })
} }
@ -559,10 +561,10 @@ impl Perform for GetSiteConfig {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<GetSiteConfigResponse, LemmyError> { ) -> Result<GetSiteConfigResponse, LemmyError> {
let data: &GetSiteConfig = &self; let data: &GetSiteConfig = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Only let admins read this // Only let admins read this
is_admin(context.pool(), user.id).await?; is_admin(&local_user_view)?;
let config_hjson = Settings::read_config_file()?; let config_hjson = Settings::read_config_file()?;
@ -580,11 +582,10 @@ impl Perform for SaveSiteConfig {
_websocket_id: Option<ConnectionId>, _websocket_id: Option<ConnectionId>,
) -> Result<GetSiteConfigResponse, LemmyError> { ) -> Result<GetSiteConfigResponse, LemmyError> {
let data: &SaveSiteConfig = &self; let data: &SaveSiteConfig = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Only let admins read this // Only let admins read this
let user_id = user.id; is_admin(&local_user_view)?;
is_admin(context.pool(), user_id).await?;
// Make sure docker doesn't have :ro at the end of the volume, so its not a read-only filesystem // Make sure docker doesn't have :ro at the end of the volume, so its not a read-only filesystem
let config_hjson = match Settings::save_config_file(&data.config_hjson) { let config_hjson = match Settings::save_config_file(&data.config_hjson) {

View file

@ -1,4 +1,4 @@
use crate::{get_user_from_jwt, Perform}; use crate::{get_local_user_view_from_jwt, Perform};
use actix_web::web::Data; use actix_web::web::Data;
use lemmy_api_structs::websocket::*; use lemmy_api_structs::websocket::*;
use lemmy_utils::{ConnectionId, LemmyError}; use lemmy_utils::{ConnectionId, LemmyError};
@ -17,11 +17,11 @@ impl Perform for UserJoin {
websocket_id: Option<ConnectionId>, websocket_id: Option<ConnectionId>,
) -> Result<UserJoinResponse, LemmyError> { ) -> Result<UserJoinResponse, LemmyError> {
let data: &UserJoin = &self; let data: &UserJoin = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
if let Some(ws_id) = websocket_id { if let Some(ws_id) = websocket_id {
context.chat_server().do_send(JoinUserRoom { context.chat_server().do_send(JoinUserRoom {
user_id: user.id, local_user_id: local_user_view.local_user.id,
id: ws_id, id: ws_id,
}); });
} }

View file

@ -2,7 +2,7 @@ use lemmy_db_views_actor::{
community_follower_view::CommunityFollowerView, community_follower_view::CommunityFollowerView,
community_moderator_view::CommunityModeratorView, community_moderator_view::CommunityModeratorView,
community_view::CommunityView, community_view::CommunityView,
user_view::UserViewSafe, person_view::PersonViewSafe,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -53,7 +53,7 @@ pub struct ListCommunitiesResponse {
#[derive(Deserialize, Clone)] #[derive(Deserialize, Clone)]
pub struct BanFromCommunity { pub struct BanFromCommunity {
pub community_id: i32, pub community_id: i32,
pub user_id: i32, pub person_id: i32,
pub ban: bool, pub ban: bool,
pub remove_data: bool, pub remove_data: bool,
pub reason: Option<String>, pub reason: Option<String>,
@ -63,14 +63,14 @@ pub struct BanFromCommunity {
#[derive(Serialize, Clone)] #[derive(Serialize, Clone)]
pub struct BanFromCommunityResponse { pub struct BanFromCommunityResponse {
pub user_view: UserViewSafe, pub person_view: PersonViewSafe,
pub banned: bool, pub banned: bool,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct AddModToCommunity { pub struct AddModToCommunity {
pub community_id: i32, pub community_id: i32,
pub user_id: i32, pub person_id: i32,
pub added: bool, pub added: bool,
pub auth: String, pub auth: String,
} }
@ -127,6 +127,6 @@ pub struct GetFollowedCommunitiesResponse {
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct TransferCommunity { pub struct TransferCommunity {
pub community_id: i32, pub community_id: i32,
pub user_id: i32, pub person_id: i32,
pub auth: String, pub auth: String,
} }

View file

@ -1,18 +1,19 @@
pub mod comment; pub mod comment;
pub mod community; pub mod community;
pub mod person;
pub mod post; pub mod post;
pub mod site; pub mod site;
pub mod user;
pub mod websocket; pub mod websocket;
use diesel::PgConnection; use diesel::PgConnection;
use lemmy_db_queries::{source::user::User, Crud, DbPool}; use lemmy_db_queries::{Crud, DbPool};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::Comment, comment::Comment,
person::Person,
person_mention::{PersonMention, PersonMentionForm},
post::Post, post::Post,
user::User_,
user_mention::{UserMention, UserMentionForm},
}; };
use lemmy_db_views::local_user_view::LocalUserView;
use lemmy_utils::{email::send_email, settings::structs::Settings, utils::MentionData, LemmyError}; use lemmy_utils::{email::send_email, settings::structs::Settings, utils::MentionData, LemmyError};
use log::error; use log::error;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -54,14 +55,13 @@ where
pub async fn send_local_notifs( pub async fn send_local_notifs(
mentions: Vec<MentionData>, mentions: Vec<MentionData>,
comment: Comment, comment: Comment,
user: &User_, person: Person,
post: Post, post: Post,
pool: &DbPool, pool: &DbPool,
do_send_email: bool, do_send_email: bool,
) -> Result<Vec<i32>, LemmyError> { ) -> Result<Vec<i32>, LemmyError> {
let user2 = user.clone();
let ids = blocking(pool, move |conn| { let ids = blocking(pool, move |conn| {
do_send_local_notifs(conn, &mentions, &comment, &user2, &post, do_send_email) do_send_local_notifs(conn, &mentions, &comment, &person, &post, do_send_email)
}) })
.await?; .await?;
@ -72,7 +72,7 @@ fn do_send_local_notifs(
conn: &PgConnection, conn: &PgConnection,
mentions: &[MentionData], mentions: &[MentionData],
comment: &Comment, comment: &Comment,
user: &User_, person: &Person,
post: &Post, post: &Post,
do_send_email: bool, do_send_email: bool,
) -> Vec<i32> { ) -> Vec<i32> {
@ -81,31 +81,31 @@ fn do_send_local_notifs(
// Send the local mentions // Send the local mentions
for mention in mentions for mention in mentions
.iter() .iter()
.filter(|m| m.is_local() && m.name.ne(&user.name)) .filter(|m| m.is_local() && m.name.ne(&person.name))
.collect::<Vec<&MentionData>>() .collect::<Vec<&MentionData>>()
{ {
if let Ok(mention_user) = User_::read_from_name(&conn, &mention.name) { if let Ok(mention_user_view) = LocalUserView::read_from_name(&conn, &mention.name) {
// TODO // TODO
// At some point, make it so you can't tag the parent creator either // At some point, make it so you can't tag the parent creator either
// This can cause two notifications, one for reply and the other for mention // This can cause two notifications, one for reply and the other for mention
recipient_ids.push(mention_user.id); recipient_ids.push(mention_user_view.local_user.id);
let user_mention_form = UserMentionForm { let user_mention_form = PersonMentionForm {
recipient_id: mention_user.id, recipient_id: mention_user_view.person.id,
comment_id: comment.id, comment_id: comment.id,
read: None, read: None,
}; };
// Allow this to fail softly, since comment edits might re-update or replace it // Allow this to fail softly, since comment edits might re-update or replace it
// Let the uniqueness handle this fail // Let the uniqueness handle this fail
let _ = UserMention::create(&conn, &user_mention_form); PersonMention::create(&conn, &user_mention_form).ok();
// Send an email to those users that have notifications on // Send an email to those local users that have notifications on
if do_send_email && mention_user.send_notifications_to_email { if do_send_email {
send_email_to_user( send_email_to_user(
mention_user, &mention_user_view,
"Mentioned by", "Mentioned by",
"User Mention", "Person Mention",
&comment.content, &comment.content,
) )
} }
@ -116,12 +116,20 @@ fn do_send_local_notifs(
match comment.parent_id { match comment.parent_id {
Some(parent_id) => { Some(parent_id) => {
if let Ok(parent_comment) = Comment::read(&conn, parent_id) { if let Ok(parent_comment) = Comment::read(&conn, parent_id) {
if parent_comment.creator_id != user.id { // Don't send a notif to yourself
if let Ok(parent_user) = User_::read(&conn, parent_comment.creator_id) { if parent_comment.creator_id != person.id {
recipient_ids.push(parent_user.id); // Get the parent commenter local_user
if let Ok(parent_user_view) = LocalUserView::read_person(&conn, parent_comment.creator_id)
{
recipient_ids.push(parent_user_view.local_user.id);
if do_send_email && parent_user.send_notifications_to_email { if do_send_email {
send_email_to_user(parent_user, "Reply from", "Comment Reply", &comment.content) send_email_to_user(
&parent_user_view,
"Reply from",
"Comment Reply",
&comment.content,
)
} }
} }
} }
@ -129,12 +137,17 @@ fn do_send_local_notifs(
} }
// Its a post // Its a post
None => { None => {
if post.creator_id != user.id { if post.creator_id != person.id {
if let Ok(parent_user) = User_::read(&conn, post.creator_id) { if let Ok(parent_user_view) = LocalUserView::read_person(&conn, post.creator_id) {
recipient_ids.push(parent_user.id); recipient_ids.push(parent_user_view.local_user.id);
if do_send_email && parent_user.send_notifications_to_email { if do_send_email {
send_email_to_user(parent_user, "Reply from", "Post Reply", &comment.content) send_email_to_user(
&parent_user_view,
"Reply from",
"Post Reply",
&comment.content,
)
} }
} }
} }
@ -143,26 +156,31 @@ fn do_send_local_notifs(
recipient_ids recipient_ids
} }
pub fn send_email_to_user(user: User_, subject_text: &str, body_text: &str, comment_content: &str) { pub fn send_email_to_user(
if user.banned { local_user_view: &LocalUserView,
subject_text: &str,
body_text: &str,
comment_content: &str,
) {
if local_user_view.person.banned || !local_user_view.local_user.send_notifications_to_email {
return; return;
} }
if let Some(user_email) = user.email { if let Some(user_email) = &local_user_view.local_user.email {
let subject = &format!( let subject = &format!(
"{} - {} {}", "{} - {} {}",
subject_text, subject_text,
Settings::get().hostname(), Settings::get().hostname(),
user.name, local_user_view.person.name,
); );
let html = &format!( let html = &format!(
"<h1>{}</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>", "<h1>{}</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
body_text, body_text,
user.name, local_user_view.person.name,
comment_content, comment_content,
Settings::get().get_protocol_and_hostname() Settings::get().get_protocol_and_hostname()
); );
match send_email(subject, &user_email, &user.name, html) { match send_email(subject, &user_email, &local_user_view.person.name, html) {
Ok(_o) => _o, Ok(_o) => _o,
Err(e) => error!("{}", e), Err(e) => error!("{}", e),
}; };

View file

@ -6,8 +6,8 @@ use lemmy_db_views::{
use lemmy_db_views_actor::{ use lemmy_db_views_actor::{
community_follower_view::CommunityFollowerView, community_follower_view::CommunityFollowerView,
community_moderator_view::CommunityModeratorView, community_moderator_view::CommunityModeratorView,
user_mention_view::UserMentionView, person_mention_view::PersonMentionView,
user_view::UserViewSafe, person_view::PersonViewSafe,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -45,11 +45,11 @@ pub struct CaptchaResponse {
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct SaveUserSettings { pub struct SaveUserSettings {
pub show_nsfw: bool, pub show_nsfw: Option<bool>,
pub theme: String, pub theme: Option<String>,
pub default_sort_type: i16, pub default_sort_type: Option<i16>,
pub default_listing_type: i16, pub default_listing_type: Option<i16>,
pub lang: String, pub lang: Option<String>,
pub avatar: Option<String>, pub avatar: Option<String>,
pub banner: Option<String>, pub banner: Option<String>,
pub preferred_username: Option<String>, pub preferred_username: Option<String>,
@ -59,8 +59,8 @@ pub struct SaveUserSettings {
pub new_password: Option<String>, pub new_password: Option<String>,
pub new_password_verify: Option<String>, pub new_password_verify: Option<String>,
pub old_password: Option<String>, pub old_password: Option<String>,
pub show_avatars: bool, pub show_avatars: Option<bool>,
pub send_notifications_to_email: bool, pub send_notifications_to_email: Option<bool>,
pub auth: String, pub auth: String,
} }
@ -70,8 +70,8 @@ pub struct LoginResponse {
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct GetUserDetails { pub struct GetPersonDetails {
pub user_id: Option<i32>, pub person_id: Option<i32>,
pub username: Option<String>, pub username: Option<String>,
pub sort: String, pub sort: String,
pub page: Option<i64>, pub page: Option<i64>,
@ -82,8 +82,8 @@ pub struct GetUserDetails {
} }
#[derive(Serialize)] #[derive(Serialize)]
pub struct GetUserDetailsResponse { pub struct GetPersonDetailsResponse {
pub user_view: UserViewSafe, pub person_view: PersonViewSafe,
pub follows: Vec<CommunityFollowerView>, pub follows: Vec<CommunityFollowerView>,
pub moderates: Vec<CommunityModeratorView>, pub moderates: Vec<CommunityModeratorView>,
pub comments: Vec<CommentView>, pub comments: Vec<CommentView>,
@ -96,8 +96,8 @@ pub struct GetRepliesResponse {
} }
#[derive(Serialize)] #[derive(Serialize)]
pub struct GetUserMentionsResponse { pub struct GetPersonMentionsResponse {
pub mentions: Vec<UserMentionView>, pub mentions: Vec<PersonMentionView>,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -107,19 +107,19 @@ pub struct MarkAllAsRead {
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct AddAdmin { pub struct AddAdmin {
pub user_id: i32, pub person_id: i32,
pub added: bool, pub added: bool,
pub auth: String, pub auth: String,
} }
#[derive(Serialize, Clone)] #[derive(Serialize, Clone)]
pub struct AddAdminResponse { pub struct AddAdminResponse {
pub admins: Vec<UserViewSafe>, pub admins: Vec<PersonViewSafe>,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct BanUser { pub struct BanPerson {
pub user_id: i32, pub person_id: i32,
pub ban: bool, pub ban: bool,
pub remove_data: bool, pub remove_data: bool,
pub reason: Option<String>, pub reason: Option<String>,
@ -128,8 +128,8 @@ pub struct BanUser {
} }
#[derive(Serialize, Clone)] #[derive(Serialize, Clone)]
pub struct BanUserResponse { pub struct BanPersonResponse {
pub user_view: UserViewSafe, pub person_view: PersonViewSafe,
pub banned: bool, pub banned: bool,
} }
@ -143,7 +143,7 @@ pub struct GetReplies {
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct GetUserMentions { pub struct GetPersonMentions {
pub sort: String, pub sort: String,
pub page: Option<i64>, pub page: Option<i64>,
pub limit: Option<i64>, pub limit: Option<i64>,
@ -152,15 +152,15 @@ pub struct GetUserMentions {
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct MarkUserMentionAsRead { pub struct MarkPersonMentionAsRead {
pub user_mention_id: i32, pub person_mention_id: i32,
pub read: bool, pub read: bool,
pub auth: String, pub auth: String,
} }
#[derive(Serialize, Clone)] #[derive(Serialize, Clone)]
pub struct UserMentionResponse { pub struct PersonMentionResponse {
pub user_mention_view: UserMentionView, pub person_mention_view: PersonMentionView,
} }
#[derive(Deserialize)] #[derive(Deserialize)]

View file

@ -1,6 +1,10 @@
use lemmy_db_schema::source::user::UserSafeSettings; use lemmy_db_views::{
use lemmy_db_views::{comment_view::CommentView, post_view::PostView, site_view::SiteView}; comment_view::CommentView,
use lemmy_db_views_actor::{community_view::CommunityView, user_view::UserViewSafe}; 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::{ use lemmy_db_views_moderator::{
mod_add_community_view::ModAddCommunityView, mod_add_community_view::ModAddCommunityView,
mod_add_view::ModAddView, mod_add_view::ModAddView,
@ -33,12 +37,12 @@ pub struct SearchResponse {
pub comments: Vec<CommentView>, pub comments: Vec<CommentView>,
pub posts: Vec<PostView>, pub posts: Vec<PostView>,
pub communities: Vec<CommunityView>, pub communities: Vec<CommunityView>,
pub users: Vec<UserViewSafe>, pub users: Vec<PersonViewSafe>,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct GetModlog { pub struct GetModlog {
pub mod_user_id: Option<i32>, pub mod_person_id: Option<i32>,
pub community_id: Option<i32>, pub community_id: Option<i32>,
pub page: Option<i64>, pub page: Option<i64>,
pub limit: Option<i64>, pub limit: Option<i64>,
@ -94,17 +98,17 @@ pub struct SiteResponse {
#[derive(Serialize)] #[derive(Serialize)]
pub struct GetSiteResponse { pub struct GetSiteResponse {
pub site_view: Option<SiteView>, // Because the site might not be set up yet pub site_view: Option<SiteView>, // Because the site might not be set up yet
pub admins: Vec<UserViewSafe>, pub admins: Vec<PersonViewSafe>,
pub banned: Vec<UserViewSafe>, pub banned: Vec<PersonViewSafe>,
pub online: usize, pub online: usize,
pub version: String, pub version: String,
pub my_user: Option<UserSafeSettings>, pub my_user: Option<LocalUserSettingsView>,
pub federated_instances: Option<FederatedInstances>, // Federation may be disabled pub federated_instances: Option<FederatedInstances>, // Federation may be disabled
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct TransferSite { pub struct TransferSite {
pub user_id: i32, pub person_id: i32,
pub auth: String, pub auth: String,
} }

View file

@ -1,4 +1,4 @@
use crate::{activities::receive::get_actor_as_user, objects::FromApub, ActorType, NoteExt}; use crate::{activities::receive::get_actor_as_person, objects::FromApub, ActorType, NoteExt};
use activitystreams::{ use activitystreams::{
activity::{ActorAndObjectRefExt, Create, Dislike, Like, Remove, Update}, activity::{ActorAndObjectRefExt, Create, Dislike, Like, Remove, Update},
base::ExtendsExt, base::ExtendsExt,
@ -19,11 +19,11 @@ pub(crate) async fn receive_create_comment(
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let user = get_actor_as_user(&create, context, request_counter).await?; let person = get_actor_as_person(&create, context, request_counter).await?;
let note = NoteExt::from_any_base(create.object().to_owned().one().context(location_info!())?)? let note = NoteExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?; .context(location_info!())?;
let comment = Comment::from_apub(&note, context, user.actor_id(), request_counter).await?; let comment = Comment::from_apub(&note, context, person.actor_id(), request_counter).await?;
let post_id = comment.post_id; let post_id = comment.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
@ -33,8 +33,15 @@ pub(crate) async fn receive_create_comment(
// Its much easier to scrape them from the comment body, since the API has to do that // Its much easier to scrape them from the comment body, since the API has to do that
// anyway. // anyway.
let mentions = scrape_text_for_mentions(&comment.content); let mentions = scrape_text_for_mentions(&comment.content);
let recipient_ids = let recipient_ids = send_local_notifs(
send_local_notifs(mentions, comment.clone(), &user, post, context.pool(), true).await?; mentions,
comment.clone(),
person,
post,
context.pool(),
true,
)
.await?;
// Refetch the view // Refetch the view
let comment_view = blocking(context.pool(), move |conn| { let comment_view = blocking(context.pool(), move |conn| {
@ -64,9 +71,9 @@ pub(crate) async fn receive_update_comment(
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let note = NoteExt::from_any_base(update.object().to_owned().one().context(location_info!())?)? let note = NoteExt::from_any_base(update.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?; .context(location_info!())?;
let user = get_actor_as_user(&update, context, request_counter).await?; let person = get_actor_as_person(&update, context, request_counter).await?;
let comment = Comment::from_apub(&note, context, user.actor_id(), request_counter).await?; let comment = Comment::from_apub(&note, context, person.actor_id(), request_counter).await?;
let comment_id = comment.id; let comment_id = comment.id;
let post_id = comment.post_id; let post_id = comment.post_id;
@ -74,7 +81,7 @@ pub(crate) async fn receive_update_comment(
let mentions = scrape_text_for_mentions(&comment.content); let mentions = scrape_text_for_mentions(&comment.content);
let recipient_ids = let recipient_ids =
send_local_notifs(mentions, comment, &user, post, context.pool(), false).await?; send_local_notifs(mentions, comment, person, post, context.pool(), false).await?;
// Refetch the view // Refetch the view
let comment_view = blocking(context.pool(), move |conn| { let comment_view = blocking(context.pool(), move |conn| {
@ -103,18 +110,18 @@ pub(crate) async fn receive_like_comment(
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let user = get_actor_as_user(&like, context, request_counter).await?; let person = get_actor_as_person(&like, context, request_counter).await?;
let comment_id = comment.id; let comment_id = comment.id;
let like_form = CommentLikeForm { let like_form = CommentLikeForm {
comment_id, comment_id,
post_id: comment.post_id, post_id: comment.post_id,
user_id: user.id, person_id: person.id,
score: 1, score: 1,
}; };
let user_id = user.id; let person_id = person.id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
CommentLike::remove(conn, user_id, comment_id)?; CommentLike::remove(conn, person_id, comment_id)?;
CommentLike::like(conn, &like_form) CommentLike::like(conn, &like_form)
}) })
.await??; .await??;
@ -148,18 +155,18 @@ pub(crate) async fn receive_dislike_comment(
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let user = get_actor_as_user(&dislike, context, request_counter).await?; let person = get_actor_as_person(&dislike, context, request_counter).await?;
let comment_id = comment.id; let comment_id = comment.id;
let like_form = CommentLikeForm { let like_form = CommentLikeForm {
comment_id, comment_id,
post_id: comment.post_id, post_id: comment.post_id,
user_id: user.id, person_id: person.id,
score: -1, score: -1,
}; };
let user_id = user.id; let person_id = person.id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
CommentLike::remove(conn, user_id, comment_id)?; CommentLike::remove(conn, person_id, comment_id)?;
CommentLike::like(conn, &like_form) CommentLike::like(conn, &like_form)
}) })
.await??; .await??;

View file

@ -1,4 +1,4 @@
use crate::activities::receive::get_actor_as_user; use crate::activities::receive::get_actor_as_person;
use activitystreams::activity::{Dislike, Like}; use activitystreams::activity::{Dislike, Like};
use lemmy_api_structs::{blocking, comment::CommentResponse}; use lemmy_api_structs::{blocking, comment::CommentResponse};
use lemmy_db_queries::{source::comment::Comment_, Likeable}; use lemmy_db_queries::{source::comment::Comment_, Likeable};
@ -13,12 +13,12 @@ pub(crate) async fn receive_undo_like_comment(
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let user = get_actor_as_user(like, context, request_counter).await?; let person = get_actor_as_person(like, context, request_counter).await?;
let comment_id = comment.id; let comment_id = comment.id;
let user_id = user.id; let person_id = person.id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
CommentLike::remove(conn, user_id, comment_id) CommentLike::remove(conn, person_id, comment_id)
}) })
.await??; .await??;
@ -51,12 +51,12 @@ pub(crate) async fn receive_undo_dislike_comment(
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let user = get_actor_as_user(dislike, context, request_counter).await?; let person = get_actor_as_person(dislike, context, request_counter).await?;
let comment_id = comment.id; let comment_id = comment.id;
let user_id = user.id; let person_id = person.id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
CommentLike::remove(conn, user_id, comment_id) CommentLike::remove(conn, person_id, comment_id)
}) })
.await??; .await??;

View file

@ -1,11 +1,11 @@
use crate::fetcher::user::get_or_fetch_and_upsert_user; use crate::fetcher::person::get_or_fetch_and_upsert_person;
use activitystreams::{ use activitystreams::{
activity::{ActorAndObjectRef, ActorAndObjectRefExt}, activity::{ActorAndObjectRef, ActorAndObjectRefExt},
base::{AsBase, BaseExt}, base::{AsBase, BaseExt},
error::DomainError, error::DomainError,
}; };
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use lemmy_db_schema::source::user::User_; use lemmy_db_schema::source::person::Person;
use lemmy_utils::{location_info, LemmyError}; use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use log::debug; use log::debug;
@ -28,18 +28,18 @@ where
Err(anyhow!("Activity not supported").into()) Err(anyhow!("Activity not supported").into())
} }
/// Reads the actor field of an activity and returns the corresponding `User_`. /// Reads the actor field of an activity and returns the corresponding `Person`.
pub(crate) async fn get_actor_as_user<T, A>( pub(crate) async fn get_actor_as_person<T, A>(
activity: &T, activity: &T,
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<User_, LemmyError> ) -> Result<Person, LemmyError>
where where
T: AsBase<A> + ActorAndObjectRef, T: AsBase<A> + ActorAndObjectRef,
{ {
let actor = activity.actor()?; let actor = activity.actor()?;
let user_uri = actor.as_single_xsd_any_uri().context(location_info!())?; let person_uri = actor.as_single_xsd_any_uri().context(location_info!())?;
get_or_fetch_and_upsert_user(&user_uri, context, request_counter).await get_or_fetch_and_upsert_person(&person_uri, context, request_counter).await
} }
/// Ensure that the ID of an incoming activity comes from the same domain as the actor. Optionally /// Ensure that the ID of an incoming activity comes from the same domain as the actor. Optionally

View file

@ -1,4 +1,4 @@
use crate::{activities::receive::get_actor_as_user, objects::FromApub, ActorType, PageExt}; use crate::{activities::receive::get_actor_as_person, objects::FromApub, ActorType, PageExt};
use activitystreams::{ use activitystreams::{
activity::{Create, Dislike, Like, Remove, Update}, activity::{Create, Dislike, Like, Remove, Update},
prelude::*, prelude::*,
@ -16,11 +16,11 @@ pub(crate) async fn receive_create_post(
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let user = get_actor_as_user(&create, context, request_counter).await?; let person = get_actor_as_person(&create, context, request_counter).await?;
let page = PageExt::from_any_base(create.object().to_owned().one().context(location_info!())?)? let page = PageExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?; .context(location_info!())?;
let post = Post::from_apub(&page, context, user.actor_id(), request_counter).await?; let post = Post::from_apub(&page, context, person.actor_id(), request_counter).await?;
// Refetch the view // Refetch the view
let post_id = post.id; let post_id = post.id;
@ -45,11 +45,11 @@ pub(crate) async fn receive_update_post(
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let user = get_actor_as_user(&update, context, request_counter).await?; let person = get_actor_as_person(&update, context, request_counter).await?;
let page = PageExt::from_any_base(update.object().to_owned().one().context(location_info!())?)? let page = PageExt::from_any_base(update.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?; .context(location_info!())?;
let post = Post::from_apub(&page, context, user.actor_id(), request_counter).await?; let post = Post::from_apub(&page, context, person.actor_id(), request_counter).await?;
let post_id = post.id; let post_id = post.id;
// Refetch the view // Refetch the view
@ -75,17 +75,17 @@ pub(crate) async fn receive_like_post(
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let user = get_actor_as_user(&like, context, request_counter).await?; let person = get_actor_as_person(&like, context, request_counter).await?;
let post_id = post.id; let post_id = post.id;
let like_form = PostLikeForm { let like_form = PostLikeForm {
post_id, post_id,
user_id: user.id, person_id: person.id,
score: 1, score: 1,
}; };
let user_id = user.id; let person_id = person.id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
PostLike::remove(conn, user_id, post_id)?; PostLike::remove(conn, person_id, post_id)?;
PostLike::like(conn, &like_form) PostLike::like(conn, &like_form)
}) })
.await??; .await??;
@ -113,17 +113,17 @@ pub(crate) async fn receive_dislike_post(
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let user = get_actor_as_user(&dislike, context, request_counter).await?; let person = get_actor_as_person(&dislike, context, request_counter).await?;
let post_id = post.id; let post_id = post.id;
let like_form = PostLikeForm { let like_form = PostLikeForm {
post_id, post_id,
user_id: user.id, person_id: person.id,
score: -1, score: -1,
}; };
let user_id = user.id; let person_id = person.id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
PostLike::remove(conn, user_id, post_id)?; PostLike::remove(conn, person_id, post_id)?;
PostLike::like(conn, &like_form) PostLike::like(conn, &like_form)
}) })
.await??; .await??;

View file

@ -1,4 +1,4 @@
use crate::activities::receive::get_actor_as_user; use crate::activities::receive::get_actor_as_person;
use activitystreams::activity::{Dislike, Like}; use activitystreams::activity::{Dislike, Like};
use lemmy_api_structs::{blocking, post::PostResponse}; use lemmy_api_structs::{blocking, post::PostResponse};
use lemmy_db_queries::{source::post::Post_, Likeable}; use lemmy_db_queries::{source::post::Post_, Likeable};
@ -13,12 +13,12 @@ pub(crate) async fn receive_undo_like_post(
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let user = get_actor_as_user(like, context, request_counter).await?; let person = get_actor_as_person(like, context, request_counter).await?;
let post_id = post.id; let post_id = post.id;
let user_id = user.id; let person_id = person.id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
PostLike::remove(conn, user_id, post_id) PostLike::remove(conn, person_id, post_id)
}) })
.await??; .await??;
@ -45,12 +45,12 @@ pub(crate) async fn receive_undo_dislike_post(
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let user = get_actor_as_user(dislike, context, request_counter).await?; let person = get_actor_as_person(dislike, context, request_counter).await?;
let post_id = post.id; let post_id = post.id;
let user_id = user.id; let person_id = person.id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
PostLike::remove(conn, user_id, post_id) PostLike::remove(conn, person_id, post_id)
}) })
.await??; .await??;

View file

@ -1,7 +1,7 @@
use crate::{ use crate::{
activities::receive::verify_activity_domains_valid, activities::receive::verify_activity_domains_valid,
check_is_apub_id_valid, check_is_apub_id_valid,
fetcher::user::get_or_fetch_and_upsert_user, fetcher::person::get_or_fetch_and_upsert_person,
inbox::get_activity_to_and_cc, inbox::get_activity_to_and_cc,
objects::FromApub, objects::FromApub,
NoteExt, NoteExt,
@ -13,10 +13,10 @@ use activitystreams::{
public, public,
}; };
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use lemmy_api_structs::{blocking, user::PrivateMessageResponse}; use lemmy_api_structs::{blocking, person::PrivateMessageResponse};
use lemmy_db_queries::source::private_message::PrivateMessage_; use lemmy_db_queries::source::private_message::PrivateMessage_;
use lemmy_db_schema::source::private_message::PrivateMessage; use lemmy_db_schema::source::private_message::PrivateMessage;
use lemmy_db_views::private_message_view::PrivateMessageView; use lemmy_db_views::{local_user_view::LocalUserView, private_message_view::PrivateMessageView};
use lemmy_utils::{location_info, LemmyError}; use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperation}; use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperation};
use url::Url; use url::Url;
@ -50,12 +50,19 @@ pub(crate) async fn receive_create_private_message(
private_message_view: message, private_message_view: message,
}; };
// Send notifications to the local recipient, if one exists
let recipient_id = res.private_message_view.recipient.id; let recipient_id = res.private_message_view.recipient.id;
let local_recipient_id = blocking(context.pool(), move |conn| {
LocalUserView::read_person(conn, recipient_id)
})
.await??
.local_user
.id;
context.chat_server().do_send(SendUserRoomMessage { context.chat_server().do_send(SendUserRoomMessage {
op: UserOperation::CreatePrivateMessage, op: UserOperation::CreatePrivateMessage,
response: res, response: res,
recipient_id, local_recipient_id,
websocket_id: None, websocket_id: None,
}); });
@ -91,11 +98,17 @@ pub(crate) async fn receive_update_private_message(
}; };
let recipient_id = res.private_message_view.recipient.id; let recipient_id = res.private_message_view.recipient.id;
let local_recipient_id = blocking(context.pool(), move |conn| {
LocalUserView::read_person(conn, recipient_id)
})
.await??
.local_user
.id;
context.chat_server().do_send(SendUserRoomMessage { context.chat_server().do_send(SendUserRoomMessage {
op: UserOperation::EditPrivateMessage, op: UserOperation::EditPrivateMessage,
response: res, response: res,
recipient_id, local_recipient_id,
websocket_id: None, websocket_id: None,
}); });
@ -123,11 +136,19 @@ pub(crate) async fn receive_delete_private_message(
let res = PrivateMessageResponse { let res = PrivateMessageResponse {
private_message_view: message, private_message_view: message,
}; };
let recipient_id = res.private_message_view.recipient.id; let recipient_id = res.private_message_view.recipient.id;
let local_recipient_id = blocking(context.pool(), move |conn| {
LocalUserView::read_person(conn, recipient_id)
})
.await??
.local_user
.id;
context.chat_server().do_send(SendUserRoomMessage { context.chat_server().do_send(SendUserRoomMessage {
op: UserOperation::EditPrivateMessage, op: UserOperation::EditPrivateMessage,
response: res, response: res,
recipient_id, local_recipient_id,
websocket_id: None, websocket_id: None,
}); });
@ -160,11 +181,19 @@ pub(crate) async fn receive_undo_delete_private_message(
let res = PrivateMessageResponse { let res = PrivateMessageResponse {
private_message_view: message, private_message_view: message,
}; };
let recipient_id = res.private_message_view.recipient.id; let recipient_id = res.private_message_view.recipient.id;
let local_recipient_id = blocking(context.pool(), move |conn| {
LocalUserView::read_person(conn, recipient_id)
})
.await??
.local_user
.id;
context.chat_server().do_send(SendUserRoomMessage { context.chat_server().do_send(SendUserRoomMessage {
op: UserOperation::EditPrivateMessage, op: UserOperation::EditPrivateMessage,
response: res, response: res,
recipient_id, local_recipient_id,
websocket_id: None, websocket_id: None,
}); });
@ -181,19 +210,19 @@ where
{ {
let to_and_cc = get_activity_to_and_cc(activity); let to_and_cc = get_activity_to_and_cc(activity);
if to_and_cc.len() != 1 { if to_and_cc.len() != 1 {
return Err(anyhow!("Private message can only be addressed to one user").into()); return Err(anyhow!("Private message can only be addressed to one person").into());
} }
if to_and_cc.contains(&public()) { if to_and_cc.contains(&public()) {
return Err(anyhow!("Private message cant be public").into()); return Err(anyhow!("Private message cant be public").into());
} }
let user_id = activity let person_id = activity
.actor()? .actor()?
.to_owned() .to_owned()
.single_xsd_any_uri() .single_xsd_any_uri()
.context(location_info!())?; .context(location_info!())?;
check_is_apub_id_valid(&user_id)?; check_is_apub_id_valid(&person_id)?;
// check that the sender is a user, not a community // check that the sender is a person, not a community
get_or_fetch_and_upsert_user(&user_id, &context, request_counter).await?; get_or_fetch_and_upsert_person(&person_id, &context, request_counter).await?;
Ok(()) Ok(())
} }

View file

@ -2,7 +2,7 @@ use crate::{
activities::send::generate_activity_id, activities::send::generate_activity_id,
activity_queue::{send_comment_mentions, send_to_community}, activity_queue::{send_comment_mentions, send_to_community},
extensions::context::lemmy_context, extensions::context::lemmy_context,
fetcher::user::get_or_fetch_and_upsert_user, fetcher::person::get_or_fetch_and_upsert_person,
objects::ToApub, objects::ToApub,
ActorType, ActorType,
ApubLikeableType, ApubLikeableType,
@ -28,7 +28,7 @@ use anyhow::anyhow;
use itertools::Itertools; use itertools::Itertools;
use lemmy_api_structs::{blocking, WebFingerResponse}; use lemmy_api_structs::{blocking, WebFingerResponse};
use lemmy_db_queries::{Crud, DbPool}; use lemmy_db_queries::{Crud, DbPool};
use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post, user::User_}; use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
use lemmy_utils::{ use lemmy_utils::{
request::{retry, RecvError}, request::{retry, RecvError},
settings::structs::Settings, settings::structs::Settings,
@ -44,8 +44,8 @@ use url::Url;
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl ApubObjectType for Comment { impl ApubObjectType for Comment {
/// Send out information about a newly created comment, to the followers of the community and /// Send out information about a newly created comment, to the followers of the community and
/// mentioned users. /// mentioned persons.
async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_create(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let note = self.to_apub(context.pool()).await?; let note = self.to_apub(context.pool()).await?;
let post_id = self.post_id; let post_id = self.post_id;
@ -77,8 +77,8 @@ impl ApubObjectType for Comment {
} }
/// Send out information about an edited post, to the followers of the community and mentioned /// Send out information about an edited post, to the followers of the community and mentioned
/// users. /// persons.
async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_update(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let note = self.to_apub(context.pool()).await?; let note = self.to_apub(context.pool()).await?;
let post_id = self.post_id; let post_id = self.post_id;
@ -109,7 +109,7 @@ impl ApubObjectType for Comment {
Ok(()) Ok(())
} }
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let post_id = self.post_id; let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
@ -135,7 +135,7 @@ impl ApubObjectType for Comment {
async fn send_undo_delete( async fn send_undo_delete(
&self, &self,
creator: &User_, creator: &Person,
context: &LemmyContext, context: &LemmyContext,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let post_id = self.post_id; let post_id = self.post_id;
@ -173,7 +173,7 @@ impl ApubObjectType for Comment {
Ok(()) Ok(())
} }
async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_remove(&self, mod_: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let post_id = self.post_id; let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
@ -197,7 +197,11 @@ impl ApubObjectType for Comment {
Ok(()) Ok(())
} }
async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_undo_remove(
&self,
mod_: &Person,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let post_id = self.post_id; let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
@ -236,7 +240,7 @@ impl ApubObjectType for Comment {
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl ApubLikeableType for Comment { impl ApubLikeableType for Comment {
async fn send_like(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_like(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let post_id = self.post_id; let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
@ -260,7 +264,7 @@ impl ApubLikeableType for Comment {
Ok(()) Ok(())
} }
async fn send_dislike(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_dislike(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let post_id = self.post_id; let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
@ -286,7 +290,7 @@ impl ApubLikeableType for Comment {
async fn send_undo_like( async fn send_undo_like(
&self, &self,
creator: &User_, creator: &Person,
context: &LemmyContext, context: &LemmyContext,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let post_id = self.post_id; let post_id = self.post_id;
@ -342,7 +346,7 @@ impl MentionsAndAddresses {
/// This takes a comment, and builds a list of to_addresses, inboxes, /// This takes a comment, and builds a list of to_addresses, inboxes,
/// and mention tags, so they know where to be sent to. /// and mention tags, so they know where to be sent to.
/// Addresses are the users / addresses that go in the cc field. /// Addresses are the persons / addresses that go in the cc field.
async fn collect_non_local_mentions( async fn collect_non_local_mentions(
comment: &Comment, comment: &Comment,
community: &Community, community: &Community,
@ -356,7 +360,7 @@ async fn collect_non_local_mentions(
// Add the mention tag // Add the mention tag
let mut tags = Vec::new(); let mut tags = Vec::new();
// Get the user IDs for any mentions // Get the person IDs for any mentions
let mentions = scrape_text_for_mentions(&comment.content) let mentions = scrape_text_for_mentions(&comment.content)
.into_iter() .into_iter()
// Filter only the non-local ones // Filter only the non-local ones
@ -369,8 +373,8 @@ async fn collect_non_local_mentions(
debug!("mention actor_id: {}", actor_id); debug!("mention actor_id: {}", actor_id);
addressed_ccs.push(actor_id.to_owned().to_string().parse()?); addressed_ccs.push(actor_id.to_owned().to_string().parse()?);
let mention_user = get_or_fetch_and_upsert_user(&actor_id, context, &mut 0).await?; let mention_person = get_or_fetch_and_upsert_person(&actor_id, context, &mut 0).await?;
inboxes.push(mention_user.get_shared_inbox_or_inbox_url()); inboxes.push(mention_person.get_shared_inbox_or_inbox_url());
let mut mention_tag = Mention::new(); let mut mention_tag = Mention::new();
mention_tag.set_href(actor_id).set_name(mention.full_name()); mention_tag.set_href(actor_id).set_name(mention.full_name());
@ -387,9 +391,12 @@ async fn collect_non_local_mentions(
}) })
} }
/// Returns the apub ID of the user this comment is responding to. Meaning, in case this is a /// Returns the apub ID of the person this comment is responding to. Meaning, in case this is a
/// top-level comment, the creator of the post, otherwise the creator of the parent comment. /// top-level comment, the creator of the post, otherwise the creator of the parent comment.
async fn get_comment_parent_creator(pool: &DbPool, comment: &Comment) -> Result<User_, LemmyError> { async fn get_comment_parent_creator(
pool: &DbPool,
comment: &Comment,
) -> Result<Person, LemmyError> {
let parent_creator_id = if let Some(parent_comment_id) = comment.parent_id { let parent_creator_id = if let Some(parent_comment_id) = comment.parent_id {
let parent_comment = let parent_comment =
blocking(pool, move |conn| Comment::read(conn, parent_comment_id)).await??; blocking(pool, move |conn| Comment::read(conn, parent_comment_id)).await??;
@ -399,10 +406,10 @@ async fn get_comment_parent_creator(pool: &DbPool, comment: &Comment) -> Result<
let parent_post = blocking(pool, move |conn| Post::read(conn, parent_post_id)).await??; let parent_post = blocking(pool, move |conn| Post::read(conn, parent_post_id)).await??;
parent_post.creator_id parent_post.creator_id
}; };
Ok(blocking(pool, move |conn| User_::read(conn, parent_creator_id)).await??) Ok(blocking(pool, move |conn| Person::read(conn, parent_creator_id)).await??)
} }
/// Turns a user id like `@name@example.com` into an apub ID, like `https://example.com/user/name`, /// Turns a person id like `@name@example.com` into an apub ID, like `https://example.com/user/name`,
/// using webfinger. /// using webfinger.
async fn fetch_webfinger_url(mention: &MentionData, client: &Client) -> Result<Url, LemmyError> { async fn fetch_webfinger_url(mention: &MentionData, client: &Client) -> Result<Url, LemmyError> {
let fetch_url = format!( let fetch_url = format!(

View file

@ -3,7 +3,7 @@ use crate::{
activity_queue::{send_activity_single_dest, send_to_community_followers}, activity_queue::{send_activity_single_dest, send_to_community_followers},
check_is_apub_id_valid, check_is_apub_id_valid,
extensions::context::lemmy_context, extensions::context::lemmy_context,
fetcher::user::get_or_fetch_and_upsert_user, fetcher::person::get_or_fetch_and_upsert_person,
insert_activity, insert_activity,
ActorType, ActorType,
}; };
@ -71,7 +71,7 @@ impl ActorType for Community {
unimplemented!() unimplemented!()
} }
/// As a local community, accept the follow request from a remote user. /// As a local community, accept the follow request from a remote person.
async fn send_accept_follow( async fn send_accept_follow(
&self, &self,
follow: Follow, follow: Follow,
@ -81,7 +81,7 @@ impl ActorType for Community {
.actor()? .actor()?
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.context(location_info!())?; .context(location_info!())?;
let user = get_or_fetch_and_upsert_user(actor_uri, context, &mut 0).await?; let person = get_or_fetch_and_upsert_person(actor_uri, context, &mut 0).await?;
let mut accept = Accept::new( let mut accept = Accept::new(
self.actor_id.to_owned().into_inner(), self.actor_id.to_owned().into_inner(),
@ -90,9 +90,9 @@ impl ActorType for Community {
accept accept
.set_many_contexts(lemmy_context()?) .set_many_contexts(lemmy_context()?)
.set_id(generate_activity_id(AcceptType::Accept)?) .set_id(generate_activity_id(AcceptType::Accept)?)
.set_to(user.actor_id()); .set_to(person.actor_id());
send_activity_single_dest(accept, self, user.inbox_url.into(), context).await?; send_activity_single_dest(accept, self, person.inbox_url.into(), context).await?;
Ok(()) Ok(())
} }

View file

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

View file

@ -17,14 +17,14 @@ use lemmy_api_structs::blocking;
use lemmy_db_queries::{ApubObject, DbPool, Followable}; use lemmy_db_queries::{ApubObject, DbPool, Followable};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
community::{Community, CommunityFollower, CommunityFollowerForm}, community::{Community, CommunityFollower, CommunityFollowerForm},
user::User_, person::Person,
}; };
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use url::Url; use url::Url;
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl ActorType for User_ { impl ActorType for Person {
fn is_local(&self) -> bool { fn is_local(&self) -> bool {
self.local self.local
} }
@ -48,7 +48,7 @@ impl ActorType for User_ {
.into() .into()
} }
/// As a given local user, send out a follow request to a remote community. /// As a given local person, send out a follow request to a remote community.
async fn send_follow( async fn send_follow(
&self, &self,
follow_actor_id: &Url, follow_actor_id: &Url,
@ -62,7 +62,7 @@ impl ActorType for User_ {
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: community.id, community_id: community.id,
user_id: self.id, person_id: self.id,
pending: true, pending: true,
}; };
blocking(&context.pool(), move |conn| { blocking(&context.pool(), move |conn| {

View file

@ -23,14 +23,14 @@ use activitystreams::{
}; };
use lemmy_api_structs::blocking; use lemmy_api_structs::blocking;
use lemmy_db_queries::Crud; use lemmy_db_queries::Crud;
use lemmy_db_schema::source::{community::Community, post::Post, user::User_}; use lemmy_db_schema::source::{community::Community, person::Person, post::Post};
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl ApubObjectType for Post { impl ApubObjectType for Post {
/// Send out information about a newly created post, to the followers of the community. /// Send out information about a newly created post, to the followers of the community.
async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_create(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let page = self.to_apub(context.pool()).await?; let page = self.to_apub(context.pool()).await?;
let community_id = self.community_id; let community_id = self.community_id;
@ -54,7 +54,7 @@ impl ApubObjectType for Post {
} }
/// Send out information about an edited post, to the followers of the community. /// Send out information about an edited post, to the followers of the community.
async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_update(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let page = self.to_apub(context.pool()).await?; let page = self.to_apub(context.pool()).await?;
let community_id = self.community_id; let community_id = self.community_id;
@ -77,7 +77,7 @@ impl ApubObjectType for Post {
Ok(()) Ok(())
} }
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let community_id = self.community_id; let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| { let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id) Community::read(conn, community_id)
@ -100,7 +100,7 @@ impl ApubObjectType for Post {
async fn send_undo_delete( async fn send_undo_delete(
&self, &self,
creator: &User_, creator: &Person,
context: &LemmyContext, context: &LemmyContext,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let community_id = self.community_id; let community_id = self.community_id;
@ -134,7 +134,7 @@ impl ApubObjectType for Post {
Ok(()) Ok(())
} }
async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_remove(&self, mod_: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let community_id = self.community_id; let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| { let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id) Community::read(conn, community_id)
@ -155,7 +155,11 @@ impl ApubObjectType for Post {
Ok(()) Ok(())
} }
async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_undo_remove(
&self,
mod_: &Person,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let community_id = self.community_id; let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| { let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id) Community::read(conn, community_id)
@ -190,7 +194,7 @@ impl ApubObjectType for Post {
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl ApubLikeableType for Post { impl ApubLikeableType for Post {
async fn send_like(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_like(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let community_id = self.community_id; let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| { let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id) Community::read(conn, community_id)
@ -211,7 +215,7 @@ impl ApubLikeableType for Post {
Ok(()) Ok(())
} }
async fn send_dislike(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_dislike(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let community_id = self.community_id; let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| { let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id) Community::read(conn, community_id)
@ -234,7 +238,7 @@ impl ApubLikeableType for Post {
async fn send_undo_like( async fn send_undo_like(
&self, &self,
creator: &User_, creator: &Person,
context: &LemmyContext, context: &LemmyContext,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let community_id = self.community_id; let community_id = self.community_id;

View file

@ -18,18 +18,19 @@ use activitystreams::{
}; };
use lemmy_api_structs::blocking; use lemmy_api_structs::blocking;
use lemmy_db_queries::Crud; use lemmy_db_queries::Crud;
use lemmy_db_schema::source::{private_message::PrivateMessage, user::User_}; use lemmy_db_schema::source::{person::Person, private_message::PrivateMessage};
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl ApubObjectType for PrivateMessage { impl ApubObjectType for PrivateMessage {
/// Send out information about a newly created private message /// Send out information about a newly created private message
async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_create(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let note = self.to_apub(context.pool()).await?; let note = self.to_apub(context.pool()).await?;
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; let recipient =
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
let mut create = Create::new( let mut create = Create::new(
creator.actor_id.to_owned().into_inner(), creator.actor_id.to_owned().into_inner(),
@ -46,11 +47,12 @@ impl ApubObjectType for PrivateMessage {
} }
/// Send out information about an edited private message, to the followers of the community. /// Send out information about an edited private message, to the followers of the community.
async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_update(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let note = self.to_apub(context.pool()).await?; let note = self.to_apub(context.pool()).await?;
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; let recipient =
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
let mut update = Update::new( let mut update = Update::new(
creator.actor_id.to_owned().into_inner(), creator.actor_id.to_owned().into_inner(),
@ -65,9 +67,10 @@ impl ApubObjectType for PrivateMessage {
Ok(()) Ok(())
} }
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; let recipient =
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
let mut delete = Delete::new( let mut delete = Delete::new(
creator.actor_id.to_owned().into_inner(), creator.actor_id.to_owned().into_inner(),
@ -84,11 +87,12 @@ impl ApubObjectType for PrivateMessage {
async fn send_undo_delete( async fn send_undo_delete(
&self, &self,
creator: &User_, creator: &Person,
context: &LemmyContext, context: &LemmyContext,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; let recipient =
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
let mut delete = Delete::new( let mut delete = Delete::new(
creator.actor_id.to_owned().into_inner(), creator.actor_id.to_owned().into_inner(),
@ -113,13 +117,13 @@ impl ApubObjectType for PrivateMessage {
Ok(()) Ok(())
} }
async fn send_remove(&self, _mod_: &User_, _context: &LemmyContext) -> Result<(), LemmyError> { async fn send_remove(&self, _mod_: &Person, _context: &LemmyContext) -> Result<(), LemmyError> {
unimplemented!() unimplemented!()
} }
async fn send_undo_remove( async fn send_undo_remove(
&self, &self,
_mod_: &User_, _mod_: &Person,
_context: &LemmyContext, _context: &LemmyContext,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
unimplemented!() unimplemented!()

View file

@ -21,7 +21,7 @@ use background_jobs::{
}; };
use itertools::Itertools; use itertools::Itertools;
use lemmy_db_queries::DbPool; use lemmy_db_queries::DbPool;
use lemmy_db_schema::source::{community::Community, user::User_}; use lemmy_db_schema::source::{community::Community, person::Person};
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError}; use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use log::{debug, warn}; use log::{debug, warn};
@ -112,7 +112,7 @@ where
Ok(()) Ok(())
} }
/// Sends an activity from a local user to a remote community. /// Sends an activity from a local person to a remote community.
/// ///
/// * `activity` the activity to send /// * `activity` the activity to send
/// * `creator` the creator of the activity /// * `creator` the creator of the activity
@ -120,7 +120,7 @@ where
/// ///
pub(crate) async fn send_to_community<T, Kind>( pub(crate) async fn send_to_community<T, Kind>(
activity: T, activity: T,
creator: &User_, creator: &Person,
community: &Community, community: &Community,
context: &LemmyContext, context: &LemmyContext,
) -> Result<(), LemmyError> ) -> Result<(), LemmyError>
@ -157,13 +157,13 @@ where
Ok(()) Ok(())
} }
/// Sends notification to any users mentioned in a comment /// Sends notification to any persons mentioned in a comment
/// ///
/// * `creator` user who created the comment /// * `creator` person who created the comment
/// * `mentions` list of inboxes of users which are mentioned in the comment /// * `mentions` list of inboxes of persons which are mentioned in the comment
/// * `activity` either a `Create/Note` or `Update/Note` /// * `activity` either a `Create/Note` or `Update/Note`
pub(crate) async fn send_comment_mentions<T, Kind>( pub(crate) async fn send_comment_mentions<T, Kind>(
creator: &User_, creator: &Person,
mentions: Vec<Url>, mentions: Vec<Url>,
activity: T, activity: T,
context: &LemmyContext, context: &LemmyContext,

View file

@ -95,7 +95,7 @@ pub(crate) fn verify_signature(
} }
} }
/// Extension for actor public key, which is needed on user and community for HTTP signatures. /// Extension for actor public key, which is needed on person and community for HTTP signatures.
/// ///
/// Taken from: https://docs.rs/activitystreams/0.5.0-alpha.17/activitystreams/ext/index.html /// Taken from: https://docs.rs/activitystreams/0.5.0-alpha.17/activitystreams/ext/index.html
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]

View file

@ -1,11 +1,11 @@
use crate::{ use crate::{
fetcher::{ fetcher::{
fetch::fetch_remote_object, fetch::fetch_remote_object,
get_or_fetch_and_upsert_user, get_or_fetch_and_upsert_person,
is_deleted, is_deleted,
should_refetch_actor, should_refetch_actor,
}, },
inbox::user_inbox::receive_announce, inbox::person_inbox::receive_announce,
objects::FromApub, objects::FromApub,
GroupExt, GroupExt,
}; };
@ -92,7 +92,7 @@ async fn fetch_remote_community(
let mut creator_and_moderators = Vec::new(); let mut creator_and_moderators = Vec::new();
for uri in creator_and_moderator_uris { for uri in creator_and_moderator_uris {
let c_or_m = get_or_fetch_and_upsert_user(uri, context, recursion_counter).await?; let c_or_m = get_or_fetch_and_upsert_person(uri, context, recursion_counter).await?;
creator_and_moderators.push(c_or_m); creator_and_moderators.push(c_or_m);
} }
@ -104,7 +104,7 @@ async fn fetch_remote_community(
for mod_ in creator_and_moderators { for mod_ in creator_and_moderators {
let community_moderator_form = CommunityModeratorForm { let community_moderator_form = CommunityModeratorForm {
community_id, community_id,
user_id: mod_.id, person_id: mod_.id,
}; };
CommunityModerator::join(conn, &community_moderator_form)?; CommunityModerator::join(conn, &community_moderator_form)?;

View file

@ -1,14 +1,14 @@
pub(crate) mod community; pub(crate) mod community;
mod fetch; mod fetch;
pub(crate) mod objects; pub(crate) mod objects;
pub(crate) mod person;
pub mod search; pub mod search;
pub(crate) mod user;
use crate::{ use crate::{
fetcher::{ fetcher::{
community::get_or_fetch_and_upsert_community, community::get_or_fetch_and_upsert_community,
fetch::FetchError, fetch::FetchError,
user::get_or_fetch_and_upsert_user, person::get_or_fetch_and_upsert_person,
}, },
ActorType, ActorType,
}; };
@ -37,8 +37,8 @@ where
false false
} }
/// Get a remote actor from its apub ID (either a user or a community). Thin wrapper around /// Get a remote actor from its apub ID (either a person or a community). Thin wrapper around
/// `get_or_fetch_and_upsert_user()` and `get_or_fetch_and_upsert_community()`. /// `get_or_fetch_and_upsert_person()` and `get_or_fetch_and_upsert_community()`.
/// ///
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database. /// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
/// Otherwise it is fetched from the remote instance, stored and returned. /// Otherwise it is fetched from the remote instance, stored and returned.
@ -50,7 +50,7 @@ pub(crate) async fn get_or_fetch_and_upsert_actor(
let community = get_or_fetch_and_upsert_community(apub_id, context, recursion_counter).await; let community = get_or_fetch_and_upsert_community(apub_id, context, recursion_counter).await;
let actor: Box<dyn ActorType> = match community { let actor: Box<dyn ActorType> = match community {
Ok(c) => Box::new(c), Ok(c) => Box::new(c),
Err(_) => Box::new(get_or_fetch_and_upsert_user(apub_id, context, recursion_counter).await?), Err(_) => Box::new(get_or_fetch_and_upsert_person(apub_id, context, recursion_counter).await?),
}; };
Ok(actor) Ok(actor)
} }

View file

@ -6,65 +6,67 @@ use crate::{
use anyhow::anyhow; use anyhow::anyhow;
use diesel::result::Error::NotFound; use diesel::result::Error::NotFound;
use lemmy_api_structs::blocking; use lemmy_api_structs::blocking;
use lemmy_db_queries::{source::user::User, ApubObject}; use lemmy_db_queries::{source::person::Person_, ApubObject};
use lemmy_db_schema::source::user::User_; use lemmy_db_schema::source::person::Person;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use log::debug; use log::debug;
use url::Url; use url::Url;
/// Get a user from its apub ID. /// Get a person from its apub ID.
/// ///
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database. /// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
/// Otherwise it is fetched from the remote instance, stored and returned. /// Otherwise it is fetched from the remote instance, stored and returned.
pub(crate) async fn get_or_fetch_and_upsert_user( pub(crate) async fn get_or_fetch_and_upsert_person(
apub_id: &Url, apub_id: &Url,
context: &LemmyContext, context: &LemmyContext,
recursion_counter: &mut i32, recursion_counter: &mut i32,
) -> Result<User_, LemmyError> { ) -> Result<Person, LemmyError> {
let apub_id_owned = apub_id.to_owned(); let apub_id_owned = apub_id.to_owned();
let user = blocking(context.pool(), move |conn| { let person = blocking(context.pool(), move |conn| {
User_::read_from_apub_id(conn, &apub_id_owned.into()) Person::read_from_apub_id(conn, &apub_id_owned.into())
}) })
.await?; .await?;
match user { match person {
// If its older than a day, re-fetch it // If its older than a day, re-fetch it
Ok(u) if !u.local && should_refetch_actor(u.last_refreshed_at) => { Ok(u) if !u.local && should_refetch_actor(u.last_refreshed_at) => {
debug!("Fetching and updating from remote user: {}", apub_id); debug!("Fetching and updating from remote person: {}", apub_id);
let person = let person =
fetch_remote_object::<PersonExt>(context.client(), apub_id, recursion_counter).await; fetch_remote_object::<PersonExt>(context.client(), apub_id, recursion_counter).await;
if is_deleted(&person) { if is_deleted(&person) {
// TODO: use User_::update_deleted() once implemented // TODO: use Person::update_deleted() once implemented
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
User_::delete_account(conn, u.id) Person::delete_account(conn, u.id)
}) })
.await??; .await??;
return Err(anyhow!("User was deleted by remote instance").into()); return Err(anyhow!("Person was deleted by remote instance").into());
} else if person.is_err() { } else if person.is_err() {
return Ok(u); return Ok(u);
} }
let user = User_::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 user_id = user.id; let person_id = person.id;
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
User_::mark_as_updated(conn, user_id) Person::mark_as_updated(conn, person_id)
}) })
.await??; .await??;
Ok(user) Ok(person)
} }
Ok(u) => Ok(u), Ok(u) => Ok(u),
Err(NotFound {}) => { Err(NotFound {}) => {
debug!("Fetching and creating remote user: {}", apub_id); debug!("Fetching and creating remote person: {}", apub_id);
let person = let person =
fetch_remote_object::<PersonExt>(context.client(), apub_id, recursion_counter).await?; fetch_remote_object::<PersonExt>(context.client(), apub_id, recursion_counter).await?;
let user = User_::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(user) Ok(person)
} }
Err(e) => Err(e.into()), Err(e) => Err(e.into()),
} }

View file

@ -2,7 +2,7 @@ use crate::{
fetcher::{ fetcher::{
fetch::fetch_remote_object, fetch::fetch_remote_object,
get_or_fetch_and_upsert_community, get_or_fetch_and_upsert_community,
get_or_fetch_and_upsert_user, get_or_fetch_and_upsert_person,
is_deleted, is_deleted,
}, },
find_object_by_id, find_object_by_id,
@ -20,21 +20,21 @@ use lemmy_db_queries::{
source::{ source::{
comment::Comment_, comment::Comment_,
community::Community_, community::Community_,
person::Person_,
post::Post_, post::Post_,
private_message::PrivateMessage_, private_message::PrivateMessage_,
user::User,
}, },
SearchType, SearchType,
}; };
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::Comment, comment::Comment,
community::Community, community::Community,
person::Person,
post::Post, post::Post,
private_message::PrivateMessage, private_message::PrivateMessage,
user::User_,
}; };
use lemmy_db_views::{comment_view::CommentView, post_view::PostView}; use lemmy_db_views::{comment_view::CommentView, post_view::PostView};
use lemmy_db_views_actor::{community_view::CommunityView, user_view::UserViewSafe}; use lemmy_db_views_actor::{community_view::CommunityView, person_view::PersonViewSafe};
use lemmy_utils::{settings::structs::Settings, LemmyError}; use lemmy_utils::{settings::structs::Settings, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use log::debug; use log::debug;
@ -66,7 +66,7 @@ pub async fn search_by_apub_id(
debug!("Search for {}", query); debug!("Search for {}", query);
let split = query.split('@').collect::<Vec<&str>>(); let split = query.split('@').collect::<Vec<&str>>();
// User type will look like ['', username, instance] // Person type will look like ['', username, instance]
// Community will look like [!community, instance] // Community will look like [!community, instance]
let (name, instance) = if split.len() == 3 { let (name, instance) = if split.len() == 3 {
(format!("/u/{}", split[1]), split[2]) (format!("/u/{}", split[1]), split[2])
@ -122,13 +122,13 @@ async fn build_response(
match fetch_response { match fetch_response {
SearchAcceptedObjects::Person(p) => { SearchAcceptedObjects::Person(p) => {
let user_uri = p.inner.id(domain)?.context("person has no id")?; let person_uri = p.inner.id(domain)?.context("person has no id")?;
let user = get_or_fetch_and_upsert_user(&user_uri, context, recursion_counter).await?; let person = get_or_fetch_and_upsert_person(&person_uri, context, recursion_counter).await?;
response.users = vec![ response.users = vec![
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
UserViewSafe::read(conn, user.id) PersonViewSafe::read(conn, person.id)
}) })
.await??, .await??,
]; ];
@ -182,10 +182,10 @@ async fn delete_object_locally(query_url: &Url, context: &LemmyContext) -> Resul
}) })
.await??; .await??;
} }
Object::User(u) => { Object::Person(u) => {
// TODO: implement update_deleted() for user, move it to ApubObject trait // TODO: implement update_deleted() for user, move it to ApubObject trait
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
User_::delete_account(conn, u.id) Person::delete_account(conn, u.id)
}) })
.await??; .await??;
} }

View file

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

View file

@ -10,69 +10,69 @@ use activitystreams::{
}; };
use actix_web::{body::Body, web, HttpResponse}; use actix_web::{body::Body, web, HttpResponse};
use lemmy_api_structs::blocking; use lemmy_api_structs::blocking;
use lemmy_db_queries::source::user::User; use lemmy_db_queries::source::person::Person_;
use lemmy_db_schema::source::user::User_; use lemmy_db_schema::source::person::Person;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use serde::Deserialize; use serde::Deserialize;
use url::Url; use url::Url;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct UserQuery { pub struct PersonQuery {
user_name: String, user_name: String,
} }
/// Return the ActivityPub json representation of a local user over HTTP. /// Return the ActivityPub json representation of a local person over HTTP.
pub async fn get_apub_user_http( pub async fn get_apub_person_http(
info: web::Path<UserQuery>, info: web::Path<PersonQuery>,
context: web::Data<LemmyContext>, context: web::Data<LemmyContext>,
) -> Result<HttpResponse<Body>, LemmyError> { ) -> Result<HttpResponse<Body>, LemmyError> {
let user_name = info.into_inner().user_name; let user_name = info.into_inner().user_name;
// TODO: this needs to be able to read deleted users, so that it can send tombstones // TODO: this needs to be able to read deleted persons, so that it can send tombstones
let user = blocking(context.pool(), move |conn| { let person = blocking(context.pool(), move |conn| {
User_::find_by_email_or_username(conn, &user_name) Person::find_by_name(conn, &user_name)
}) })
.await??; .await??;
if !user.deleted { if !person.deleted {
let apub = user.to_apub(context.pool()).await?; let apub = person.to_apub(context.pool()).await?;
Ok(create_apub_response(&apub)) Ok(create_apub_response(&apub))
} else { } else {
Ok(create_apub_tombstone_response(&user.to_tombstone()?)) Ok(create_apub_tombstone_response(&person.to_tombstone()?))
} }
} }
pub async fn get_apub_user_outbox( pub async fn get_apub_person_outbox(
info: web::Path<UserQuery>, info: web::Path<PersonQuery>,
context: web::Data<LemmyContext>, context: web::Data<LemmyContext>,
) -> Result<HttpResponse<Body>, LemmyError> { ) -> Result<HttpResponse<Body>, LemmyError> {
let user = blocking(context.pool(), move |conn| { let person = blocking(context.pool(), move |conn| {
User_::read_from_name(&conn, &info.user_name) Person::find_by_name(&conn, &info.user_name)
}) })
.await??; .await??;
// TODO: populate the user outbox // TODO: populate the person outbox
let mut collection = OrderedCollection::new(); let mut collection = OrderedCollection::new();
collection collection
.set_many_items(Vec::<Url>::new()) .set_many_items(Vec::<Url>::new())
.set_many_contexts(lemmy_context()?) .set_many_contexts(lemmy_context()?)
.set_id(user.get_outbox_url()?) .set_id(person.get_outbox_url()?)
.set_total_items(0_u64); .set_total_items(0_u64);
Ok(create_apub_response(&collection)) Ok(create_apub_response(&collection))
} }
pub async fn get_apub_user_inbox( pub async fn get_apub_person_inbox(
info: web::Path<UserQuery>, info: web::Path<PersonQuery>,
context: web::Data<LemmyContext>, context: web::Data<LemmyContext>,
) -> Result<HttpResponse<Body>, LemmyError> { ) -> Result<HttpResponse<Body>, LemmyError> {
let user = blocking(context.pool(), move |conn| { let person = blocking(context.pool(), move |conn| {
User_::read_from_name(&conn, &info.user_name) Person::find_by_name(&conn, &info.user_name)
}) })
.await??; .await??;
let mut collection = OrderedCollection::new(); let mut collection = OrderedCollection::new();
collection collection
.set_id(format!("{}/inbox", user.actor_id.into_inner()).parse()?) .set_id(format!("{}/inbox", person.actor_id.into_inner()).parse()?)
.set_many_contexts(lemmy_context()?); .set_many_contexts(lemmy_context()?);
Ok(create_apub_response(&collection)) Ok(create_apub_response(&collection))
} }

View file

@ -30,9 +30,9 @@ use lemmy_api_structs::blocking;
use lemmy_db_queries::{source::community::Community_, ApubObject, DbPool, Followable}; use lemmy_db_queries::{source::community::Community_, ApubObject, DbPool, Followable};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
community::{Community, CommunityFollower, CommunityFollowerForm}, community::{Community, CommunityFollower, CommunityFollowerForm},
user::User_, person::Person,
}; };
use lemmy_db_views_actor::community_user_ban_view::CommunityUserBanView; use lemmy_db_views_actor::community_person_ban_view::CommunityPersonBanView;
use lemmy_utils::{location_info, LemmyError}; use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use log::info; use log::info;
@ -44,8 +44,8 @@ use url::Url;
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[serde(rename_all = "PascalCase")] #[serde(rename_all = "PascalCase")]
pub enum CommunityValidTypes { pub enum CommunityValidTypes {
Follow, // follow request from a user Follow, // follow request from a person
Undo, // unfollow from a user Undo, // unfollow from a person
Create, // create post or comment Create, // create post or comment
Update, // update post or comment Update, // update post or comment
Like, // upvote post or comment Like, // upvote post or comment
@ -113,21 +113,21 @@ pub(crate) async fn community_receive_message(
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
// Only users can send activities to the community, so we can get the actor as user // Only persons can send activities to the community, so we can get the actor as person
// unconditionally. // unconditionally.
let actor_id = actor.actor_id(); let actor_id = actor.actor_id();
let user = blocking(&context.pool(), move |conn| { let person = blocking(&context.pool(), move |conn| {
User_::read_from_apub_id(&conn, &actor_id.into()) Person::read_from_apub_id(&conn, &actor_id.into())
}) })
.await??; .await??;
check_community_or_site_ban(&user, to_community.id, context.pool()).await?; check_community_or_site_ban(&person, to_community.id, context.pool()).await?;
let any_base = activity.clone().into_any_base()?; let any_base = activity.clone().into_any_base()?;
let actor_url = actor.actor_id(); let actor_url = actor.actor_id();
let activity_kind = activity.kind().context(location_info!())?; let activity_kind = activity.kind().context(location_info!())?;
let do_announce = match activity_kind { let do_announce = match activity_kind {
CommunityValidTypes::Follow => { CommunityValidTypes::Follow => {
handle_follow(any_base.clone(), user, &to_community, &context).await?; handle_follow(any_base.clone(), person, &to_community, &context).await?;
false false
} }
CommunityValidTypes::Undo => { CommunityValidTypes::Undo => {
@ -162,7 +162,7 @@ pub(crate) async fn community_receive_message(
} }
CommunityValidTypes::Remove => { CommunityValidTypes::Remove => {
// TODO: we dont support remote mods, so this is ignored for now // TODO: we dont support remote mods, so this is ignored for now
//receive_remove_for_community(context, any_base.clone(), &user_url).await? //receive_remove_for_community(context, any_base.clone(), &person_url).await?
false false
} }
}; };
@ -178,20 +178,20 @@ pub(crate) async fn community_receive_message(
Ok(HttpResponse::Ok().finish()) Ok(HttpResponse::Ok().finish())
} }
/// Handle a follow request from a remote user, adding the user as follower and returning an /// Handle a follow request from a remote person, adding the person as follower and returning an
/// Accept activity. /// Accept activity.
async fn handle_follow( async fn handle_follow(
activity: AnyBase, activity: AnyBase,
user: User_, person: Person,
community: &Community, community: &Community,
context: &LemmyContext, context: &LemmyContext,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let follow = Follow::from_any_base(activity)?.context(location_info!())?; let follow = Follow::from_any_base(activity)?.context(location_info!())?;
verify_activity_domains_valid(&follow, &user.actor_id(), false)?; verify_activity_domains_valid(&follow, &person.actor_id(), false)?;
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: community.id, community_id: community.id,
user_id: user.id, person_id: person.id,
pending: false, pending: false,
}; };
@ -226,27 +226,27 @@ async fn handle_undo(
} }
} }
/// Handle `Undo/Follow` from a user, removing the user from followers list. /// Handle `Undo/Follow` from a person, removing the person from followers list.
async fn handle_undo_follow( async fn handle_undo_follow(
activity: AnyBase, activity: AnyBase,
user_url: Url, person_url: Url,
community: &Community, community: &Community,
context: &LemmyContext, context: &LemmyContext,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let undo = Undo::from_any_base(activity)?.context(location_info!())?; let undo = Undo::from_any_base(activity)?.context(location_info!())?;
verify_activity_domains_valid(&undo, &user_url, true)?; verify_activity_domains_valid(&undo, &person_url, true)?;
let object = undo.object().to_owned().one().context(location_info!())?; let object = undo.object().to_owned().one().context(location_info!())?;
let follow = Follow::from_any_base(object)?.context(location_info!())?; let follow = Follow::from_any_base(object)?.context(location_info!())?;
verify_activity_domains_valid(&follow, &user_url, false)?; verify_activity_domains_valid(&follow, &person_url, false)?;
let user = blocking(&context.pool(), move |conn| { let person = blocking(&context.pool(), move |conn| {
User_::read_from_apub_id(&conn, &user_url.into()) Person::read_from_apub_id(&conn, &person_url.into())
}) })
.await??; .await??;
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: community.id, community_id: community.id,
user_id: user.id, person_id: person.id,
pending: false, pending: false,
}; };
@ -260,17 +260,18 @@ async fn handle_undo_follow(
} }
pub(crate) async fn check_community_or_site_ban( pub(crate) async fn check_community_or_site_ban(
user: &User_, person: &Person,
community_id: i32, community_id: i32,
pool: &DbPool, pool: &DbPool,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
if user.banned { if person.banned {
return Err(anyhow!("User is banned from site").into()); return Err(anyhow!("Person is banned from site").into());
} }
let user_id = user.id; let person_id = person.id;
let is_banned = move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok(); let is_banned =
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
if blocking(pool, is_banned).await? { if blocking(pool, is_banned).await? {
return Err(anyhow!("User is banned from community").into()); return Err(anyhow!("Person is banned from community").into());
} }
Ok(()) Ok(())

View file

@ -18,7 +18,7 @@ use lemmy_db_queries::{
ApubObject, ApubObject,
DbPool, DbPool,
}; };
use lemmy_db_schema::source::{activity::Activity, community::Community, user::User_}; use lemmy_db_schema::source::{activity::Activity, community::Community, person::Person};
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError}; use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use serde::Serialize; use serde::Serialize;
@ -26,9 +26,9 @@ use std::fmt::Debug;
use url::Url; use url::Url;
pub mod community_inbox; pub mod community_inbox;
pub mod person_inbox;
mod receive_for_community; mod receive_for_community;
pub mod shared_inbox; pub mod shared_inbox;
pub mod user_inbox;
pub(crate) fn get_activity_id<T, Kind>(activity: &T, creator_uri: &Url) -> Result<Url, LemmyError> pub(crate) fn get_activity_id<T, Kind>(activity: &T, creator_uri: &Url) -> Result<Url, LemmyError>
where where
@ -119,17 +119,17 @@ where
} }
/// Returns true if `to_and_cc` contains at least one local user. /// Returns true if `to_and_cc` contains at least one local user.
pub(crate) async fn is_addressed_to_local_user( pub(crate) async fn is_addressed_to_local_person(
to_and_cc: &[Url], to_and_cc: &[Url],
pool: &DbPool, pool: &DbPool,
) -> Result<bool, LemmyError> { ) -> Result<bool, LemmyError> {
for url in to_and_cc { for url in to_and_cc {
let url = url.to_owned(); let url = url.to_owned();
let user = blocking(&pool, move |conn| { let person = blocking(&pool, move |conn| {
User_::read_from_apub_id(&conn, &url.into()) Person::read_from_apub_id(&conn, &url.into())
}) })
.await?; .await?;
if let Ok(u) = user { if let Ok(u) = person {
if u.local { if u.local {
return Ok(true); return Ok(true);
} }

View file

@ -25,7 +25,7 @@ use crate::{
inbox_verify_http_signature, inbox_verify_http_signature,
is_activity_already_known, is_activity_already_known,
is_addressed_to_community_followers, is_addressed_to_community_followers,
is_addressed_to_local_user, is_addressed_to_local_person,
is_addressed_to_public, is_addressed_to_public,
receive_for_community::{ receive_for_community::{
receive_create_for_community, receive_create_for_community,
@ -49,11 +49,11 @@ use actix_web::{web, HttpRequest, HttpResponse};
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use diesel::NotFound; use diesel::NotFound;
use lemmy_api_structs::blocking; use lemmy_api_structs::blocking;
use lemmy_db_queries::{source::user::User, ApubObject, Followable}; use lemmy_db_queries::{source::person::Person_, ApubObject, Followable};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
community::{Community, CommunityFollower}, community::{Community, CommunityFollower},
person::Person,
private_message::PrivateMessage, private_message::PrivateMessage,
user::User_,
}; };
use lemmy_utils::{location_info, LemmyError}; use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -63,10 +63,10 @@ use std::fmt::Debug;
use strum_macros::EnumString; use strum_macros::EnumString;
use url::Url; use url::Url;
/// Allowed activities for user inbox. /// Allowed activities for person inbox.
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[serde(rename_all = "PascalCase")] #[serde(rename_all = "PascalCase")]
pub enum UserValidTypes { pub enum PersonValidTypes {
Accept, // community accepted our follow request Accept, // community accepted our follow request
Create, // create private message Create, // create private message
Update, // edit private message Update, // edit private message
@ -76,12 +76,12 @@ pub enum UserValidTypes {
Announce, // post, comment or vote in community Announce, // post, comment or vote in community
} }
pub type UserAcceptedActivities = ActorAndObject<UserValidTypes>; pub type PersonAcceptedActivities = ActorAndObject<PersonValidTypes>;
/// Handler for all incoming activities to user inboxes. /// Handler for all incoming activities to person inboxes.
pub async fn user_inbox( pub async fn person_inbox(
request: HttpRequest, request: HttpRequest,
input: web::Json<UserAcceptedActivities>, input: web::Json<PersonAcceptedActivities>,
path: web::Path<String>, path: web::Path<String>,
context: web::Data<LemmyContext>, context: web::Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
@ -98,29 +98,29 @@ pub async fn user_inbox(
// Check if the activity is actually meant for us // Check if the activity is actually meant for us
let username = path.into_inner(); let username = path.into_inner();
let user = blocking(&context.pool(), move |conn| { let person = blocking(&context.pool(), move |conn| {
User_::read_from_name(&conn, &username) Person::find_by_name(&conn, &username)
}) })
.await??; .await??;
let to_and_cc = get_activity_to_and_cc(&activity); let to_and_cc = get_activity_to_and_cc(&activity);
// TODO: we should also accept activities that are sent to community followers // TODO: we should also accept activities that are sent to community followers
if !to_and_cc.contains(&&user.actor_id()) { if !to_and_cc.contains(&&person.actor_id()) {
return Err(anyhow!("Activity delivered to wrong user").into()); return Err(anyhow!("Activity delivered to wrong person").into());
} }
assert_activity_not_local(&activity)?; assert_activity_not_local(&activity)?;
insert_activity(&activity_id, activity.clone(), false, true, context.pool()).await?; insert_activity(&activity_id, activity.clone(), false, true, context.pool()).await?;
debug!( debug!(
"User {} received activity {:?} from {}", "Person {} received activity {:?} from {}",
user.name, person.name,
&activity.id_unchecked(), &activity.id_unchecked(),
&actor.actor_id() &actor.actor_id()
); );
user_receive_message( person_receive_message(
activity.clone(), activity.clone(),
Some(user.clone()), Some(person.clone()),
actor.as_ref(), actor.as_ref(),
&context, &context,
request_counter, request_counter,
@ -129,43 +129,43 @@ pub async fn user_inbox(
} }
/// Receives Accept/Follow, Announce, private messages and community (undo) remove, (undo) delete /// Receives Accept/Follow, Announce, private messages and community (undo) remove, (undo) delete
pub(crate) async fn user_receive_message( pub(crate) async fn person_receive_message(
activity: UserAcceptedActivities, activity: PersonAcceptedActivities,
to_user: Option<User_>, to_person: Option<Person>,
actor: &dyn ActorType, actor: &dyn ActorType,
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
is_for_user_inbox(context, &activity).await?; is_for_person_inbox(context, &activity).await?;
let any_base = activity.clone().into_any_base()?; let any_base = activity.clone().into_any_base()?;
let kind = activity.kind().context(location_info!())?; let kind = activity.kind().context(location_info!())?;
let actor_url = actor.actor_id(); let actor_url = actor.actor_id();
match kind { match kind {
UserValidTypes::Accept => { PersonValidTypes::Accept => {
receive_accept( receive_accept(
&context, &context,
any_base, any_base,
actor, actor,
to_user.expect("user provided"), to_person.expect("person provided"),
request_counter, request_counter,
) )
.await?; .await?;
} }
UserValidTypes::Announce => { PersonValidTypes::Announce => {
receive_announce(&context, any_base, actor, request_counter).await? receive_announce(&context, any_base, actor, request_counter).await?
} }
UserValidTypes::Create => { PersonValidTypes::Create => {
receive_create(&context, any_base, actor_url, request_counter).await? receive_create(&context, any_base, actor_url, request_counter).await?
} }
UserValidTypes::Update => { PersonValidTypes::Update => {
receive_update(&context, any_base, actor_url, request_counter).await? receive_update(&context, any_base, actor_url, request_counter).await?
} }
UserValidTypes::Delete => { PersonValidTypes::Delete => {
receive_delete(context, any_base, &actor_url, request_counter).await? receive_delete(context, any_base, &actor_url, request_counter).await?
} }
UserValidTypes::Undo => receive_undo(context, any_base, &actor_url, request_counter).await?, PersonValidTypes::Undo => receive_undo(context, any_base, &actor_url, request_counter).await?,
UserValidTypes::Remove => receive_remove_community(&context, any_base, &actor_url).await?, PersonValidTypes::Remove => receive_remove_community(&context, any_base, &actor_url).await?,
}; };
// TODO: would be logical to move websocket notification code here // TODO: would be logical to move websocket notification code here
@ -173,16 +173,16 @@ pub(crate) async fn user_receive_message(
Ok(HttpResponse::Ok().finish()) Ok(HttpResponse::Ok().finish())
} }
/// Returns true if the activity is addressed directly to one or more local users, or if it is /// Returns true if the activity is addressed directly to one or more local persons, or if it is
/// addressed to the followers collection of a remote community, and at least one local user follows /// addressed to the followers collection of a remote community, and at least one local person follows
/// it. /// it.
async fn is_for_user_inbox( async fn is_for_person_inbox(
context: &LemmyContext, context: &LemmyContext,
activity: &UserAcceptedActivities, activity: &PersonAcceptedActivities,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let to_and_cc = get_activity_to_and_cc(activity); let to_and_cc = get_activity_to_and_cc(activity);
// Check if it is addressed directly to any local user // Check if it is addressed directly to any local person
if is_addressed_to_local_user(&to_and_cc, context.pool()).await? { if is_addressed_to_local_person(&to_and_cc, context.pool()).await? {
return Ok(()); return Ok(());
} }
@ -205,7 +205,7 @@ async fn is_for_user_inbox(
} }
} }
Err(anyhow!("Not addressed for any local user").into()) Err(anyhow!("Not addressed for any local person").into())
} }
/// Handle accepted follows. /// Handle accepted follows.
@ -213,7 +213,7 @@ async fn receive_accept(
context: &LemmyContext, context: &LemmyContext,
activity: AnyBase, activity: AnyBase,
actor: &dyn ActorType, actor: &dyn ActorType,
user: User_, person: Person,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let accept = Accept::from_any_base(activity)?.context(location_info!())?; let accept = Accept::from_any_base(activity)?.context(location_info!())?;
@ -221,7 +221,7 @@ async fn receive_accept(
let object = accept.object().to_owned().one().context(location_info!())?; let object = accept.object().to_owned().one().context(location_info!())?;
let follow = Follow::from_any_base(object)?.context(location_info!())?; let follow = Follow::from_any_base(object)?.context(location_info!())?;
verify_activity_domains_valid(&follow, &user.actor_id(), false)?; verify_activity_domains_valid(&follow, &person.actor_id(), false)?;
let community_uri = accept let community_uri = accept
.actor()? .actor()?
@ -233,10 +233,10 @@ async fn receive_accept(
get_or_fetch_and_upsert_community(&community_uri, context, request_counter).await?; get_or_fetch_and_upsert_community(&community_uri, context, request_counter).await?;
let community_id = community.id; let community_id = community.id;
let user_id = user.id; let person_id = person.id;
// This will throw an error if no follow was requested // This will throw an error if no follow was requested
blocking(&context.pool(), move |conn| { blocking(&context.pool(), move |conn| {
CommunityFollower::follow_accepted(conn, community_id, user_id) CommunityFollower::follow_accepted(conn, community_id, person_id)
}) })
.await??; .await??;

View file

@ -58,7 +58,7 @@ enum PageOrNote {
} }
/// This file is for post/comment activities received by the community, and for post/comment /// This file is for post/comment activities received by the community, and for post/comment
/// activities announced by the community and received by the user. /// activities announced by the community and received by the person.
/// A post or comment being created /// A post or comment being created
pub(in crate::inbox) async fn receive_create_for_community( pub(in crate::inbox) async fn receive_create_for_community(

View file

@ -7,8 +7,8 @@ use crate::{
inbox_verify_http_signature, inbox_verify_http_signature,
is_activity_already_known, is_activity_already_known,
is_addressed_to_community_followers, is_addressed_to_community_followers,
is_addressed_to_local_user, is_addressed_to_local_person,
user_inbox::{user_receive_message, UserAcceptedActivities}, person_inbox::{person_receive_message, PersonAcceptedActivities},
}, },
insert_activity, insert_activity,
}; };
@ -69,9 +69,9 @@ pub async fn shared_inbox(
let mut res: Option<HttpResponse> = None; let mut res: Option<HttpResponse> = None;
let to_and_cc = get_activity_to_and_cc(&activity); let to_and_cc = get_activity_to_and_cc(&activity);
// Handle community first, so in case the sender is banned by the community, it will error out. // Handle community first, so in case the sender is banned by the community, it will error out.
// If we handled the user receive first, the activity would be inserted to the database before the // If we handled the person receive first, the activity would be inserted to the database before the
// community could check for bans. // community could check for bans.
// Note that an activity can be addressed to a community and to a user (or multiple users) at the // Note that an activity can be addressed to a community and to a person (or multiple persons) at the
// same time. In this case we still only handle it once, to avoid duplicate websocket // same time. In this case we still only handle it once, to avoid duplicate websocket
// notifications. // notifications.
let community = extract_local_community_from_destinations(&to_and_cc, context.pool()).await?; let community = extract_local_community_from_destinations(&to_and_cc, context.pool()).await?;
@ -88,13 +88,13 @@ pub async fn shared_inbox(
) )
.await?, .await?,
); );
} else if is_addressed_to_local_user(&to_and_cc, context.pool()).await? { } else if is_addressed_to_local_person(&to_and_cc, context.pool()).await? {
let user_activity = UserAcceptedActivities::from_any_base(activity_any_base.clone())? let person_activity = PersonAcceptedActivities::from_any_base(activity_any_base.clone())?
.context(location_info!())?; .context(location_info!())?;
// `to_user` is only used for follow activities (which we dont receive here), so no need to pass // `to_person` is only used for follow activities (which we dont receive here), so no need to pass
// it in // it in
user_receive_message( person_receive_message(
user_activity, person_activity,
None, None,
actor.as_ref(), actor.as_ref(),
&context, &context,
@ -105,11 +105,11 @@ pub async fn shared_inbox(
.await? .await?
.is_some() .is_some()
{ {
let user_activity = UserAcceptedActivities::from_any_base(activity_any_base.clone())? let person_activity = PersonAcceptedActivities::from_any_base(activity_any_base.clone())?
.context(location_info!())?; .context(location_info!())?;
res = Some( res = Some(
user_receive_message( person_receive_message(
user_activity, person_activity,
None, None,
actor.as_ref(), actor.as_ref(),
&context, &context,

View file

@ -31,9 +31,9 @@ use lemmy_db_schema::{
activity::Activity, activity::Activity,
comment::Comment, comment::Comment,
community::Community, community::Community,
person::Person as DbPerson,
post::Post, post::Post,
private_message::PrivateMessage, private_message::PrivateMessage,
user::User_,
}, },
DbUrl, DbUrl,
}; };
@ -45,7 +45,7 @@ use url::{ParseError, Url};
/// Activitystreams type for community /// Activitystreams type for community
type GroupExt = Ext2<ApActor<ApObject<Group>>, GroupExtension, PublicKeyExtension>; type GroupExt = Ext2<ApActor<ApObject<Group>>, GroupExtension, PublicKeyExtension>;
/// Activitystreams type for user /// Activitystreams type for person
type PersonExt = Ext1<ApActor<ApObject<Person>>, PublicKeyExtension>; type PersonExt = Ext1<ApActor<ApObject<Person>>, PublicKeyExtension>;
/// Activitystreams type for post /// Activitystreams type for post
type PageExt = Ext1<ApObject<Page>, PageExtension>; type PageExt = Ext1<ApObject<Page>, PageExtension>;
@ -121,27 +121,41 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
/// and actors in Lemmy. /// and actors in Lemmy.
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
pub trait ApubObjectType { pub trait ApubObjectType {
async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; async fn send_create(&self, creator: &DbPerson, context: &LemmyContext)
async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; -> Result<(), LemmyError>;
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; async fn send_update(&self, creator: &DbPerson, context: &LemmyContext)
-> Result<(), LemmyError>;
async fn send_delete(&self, creator: &DbPerson, context: &LemmyContext)
-> Result<(), LemmyError>;
async fn send_undo_delete( async fn send_undo_delete(
&self, &self,
creator: &User_, 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, context: &LemmyContext,
) -> Result<(), LemmyError>; ) -> Result<(), LemmyError>;
async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError>;
async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError>;
} }
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
pub trait ApubLikeableType { pub trait ApubLikeableType {
async fn send_like(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; async fn send_like(&self, creator: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>;
async fn send_dislike(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; async fn send_dislike(
async fn send_undo_like(&self, creator: &User_, context: &LemmyContext) &self,
-> Result<(), LemmyError>; creator: &DbPerson,
context: &LemmyContext,
) -> Result<(), LemmyError>;
async fn send_undo_like(
&self,
creator: &DbPerson,
context: &LemmyContext,
) -> Result<(), LemmyError>;
} }
/// Common methods provided by ActivityPub actors (community and user). Not all methods are /// Common methods provided by ActivityPub actors (community and person). Not all methods are
/// implemented by all actors. /// implemented by all actors.
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
pub trait ActorType { pub trait ActorType {
@ -209,7 +223,7 @@ pub trait ActorType {
pub enum EndpointType { pub enum EndpointType {
Community, Community,
User, Person,
Post, Post,
Comment, Comment,
PrivateMessage, PrivateMessage,
@ -222,7 +236,7 @@ pub fn generate_apub_endpoint(
) -> Result<DbUrl, ParseError> { ) -> Result<DbUrl, ParseError> {
let point = match endpoint_type { let point = match endpoint_type {
EndpointType::Community => "c", EndpointType::Community => "c",
EndpointType::User => "u", EndpointType::Person => "u",
EndpointType::Post => "post", EndpointType::Post => "post",
EndpointType::Comment => "comment", EndpointType::Comment => "comment",
EndpointType::PrivateMessage => "private_message", EndpointType::PrivateMessage => "private_message",
@ -316,11 +330,11 @@ pub(crate) async fn find_post_or_comment_by_id(
} }
pub(crate) enum Object { pub(crate) enum Object {
Comment(Comment), Comment(Box<Comment>),
Post(Post), Post(Box<Post>),
Community(Community), Community(Box<Community>),
User(User_), Person(Box<DbPerson>),
PrivateMessage(PrivateMessage), PrivateMessage(Box<PrivateMessage>),
} }
pub(crate) async fn find_object_by_id( pub(crate) async fn find_object_by_id(
@ -330,18 +344,18 @@ pub(crate) async fn find_object_by_id(
let ap_id = apub_id.clone(); let ap_id = apub_id.clone();
if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await { if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await {
return Ok(match pc { return Ok(match pc {
PostOrComment::Post(p) => Object::Post(*p), PostOrComment::Post(p) => Object::Post(Box::new(*p)),
PostOrComment::Comment(c) => Object::Comment(*c), PostOrComment::Comment(c) => Object::Comment(Box::new(*c)),
}); });
} }
let ap_id = apub_id.clone(); let ap_id = apub_id.clone();
let user = blocking(context.pool(), move |conn| { let person = blocking(context.pool(), move |conn| {
User_::read_from_apub_id(conn, &ap_id.into()) DbPerson::read_from_apub_id(conn, &ap_id.into())
}) })
.await?; .await?;
if let Ok(u) = user { if let Ok(u) = person {
return Ok(Object::User(u)); return Ok(Object::Person(Box::new(u)));
} }
let ap_id = apub_id.clone(); let ap_id = apub_id.clone();
@ -350,7 +364,7 @@ pub(crate) async fn find_object_by_id(
}) })
.await?; .await?;
if let Ok(c) = community { if let Ok(c) = community {
return Ok(Object::Community(c)); return Ok(Object::Community(Box::new(c)));
} }
let private_message = blocking(context.pool(), move |conn| { let private_message = blocking(context.pool(), move |conn| {
@ -358,7 +372,7 @@ pub(crate) async fn find_object_by_id(
}) })
.await?; .await?;
if let Ok(pm) = private_message { if let Ok(pm) = private_message {
return Ok(Object::PrivateMessage(pm)); return Ok(Object::PrivateMessage(Box::new(pm)));
} }
Err(NotFound.into()) Err(NotFound.into())

View file

@ -6,7 +6,7 @@ use crate::{
check_object_for_community_or_site_ban, check_object_for_community_or_site_ban,
create_tombstone, create_tombstone,
get_object_from_apub, get_object_from_apub,
get_or_fetch_and_upsert_user, get_or_fetch_and_upsert_person,
get_source_markdown_value, get_source_markdown_value,
set_content_and_source, set_content_and_source,
FromApub, FromApub,
@ -25,8 +25,8 @@ use lemmy_api_structs::blocking;
use lemmy_db_queries::{Crud, DbPool}; use lemmy_db_queries::{Crud, DbPool};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::{Comment, CommentForm}, comment::{Comment, CommentForm},
person::Person,
post::Post, post::Post,
user::User_,
}; };
use lemmy_utils::{ use lemmy_utils::{
location_info, location_info,
@ -44,7 +44,7 @@ impl ToApub for Comment {
let mut comment = ApObject::new(Note::new()); let mut comment = ApObject::new(Note::new());
let creator_id = self.creator_id; let creator_id = self.creator_id;
let creator = blocking(pool, move |conn| User_::read(conn, creator_id)).await??; let creator = blocking(pool, move |conn| Person::read(conn, creator_id)).await??;
let post_id = self.post_id; let post_id = self.post_id;
let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
@ -135,7 +135,8 @@ impl FromApubToForm<NoteExt> for CommentForm {
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.context(location_info!())?; .context(location_info!())?;
let creator = get_or_fetch_and_upsert_user(creator_actor_id, context, request_counter).await?; let creator =
get_or_fetch_and_upsert_person(creator_actor_id, context, request_counter).await?;
let mut in_reply_tos = note let mut in_reply_tos = note
.in_reply_to() .in_reply_to()

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
extensions::{context::lemmy_context, group_extensions::GroupExtension}, extensions::{context::lemmy_context, group_extensions::GroupExtension},
fetcher::user::get_or_fetch_and_upsert_user, fetcher::person::get_or_fetch_and_upsert_person,
objects::{ objects::{
check_object_domain, check_object_domain,
create_tombstone, create_tombstone,
@ -143,7 +143,7 @@ impl FromApubToForm<GroupExt> for CommunityForm {
.as_xsd_any_uri() .as_xsd_any_uri()
.context(location_info!())?; .context(location_info!())?;
let creator = get_or_fetch_and_upsert_user(creator_uri, context, request_counter).await?; let creator = get_or_fetch_and_upsert_person(creator_uri, context, request_counter).await?;
let name = group let name = group
.inner .inner
.preferred_username() .preferred_username()

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
check_is_apub_id_valid, check_is_apub_id_valid,
fetcher::{community::get_or_fetch_and_upsert_community, user::get_or_fetch_and_upsert_user}, fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
inbox::community_inbox::check_community_or_site_ban, inbox::community_inbox::check_community_or_site_ban,
}; };
use activitystreams::{ use activitystreams::{
@ -26,9 +26,9 @@ use url::Url;
pub(crate) mod comment; pub(crate) mod comment;
pub(crate) mod community; pub(crate) mod community;
pub(crate) mod person;
pub(crate) mod post; pub(crate) mod post;
pub(crate) mod private_message; pub(crate) mod private_message;
pub(crate) mod user;
/// Trait for converting an object or actor into the respective ActivityPub type. /// Trait for converting an object or actor into the respective ActivityPub type.
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
@ -212,13 +212,13 @@ pub(in crate::objects) async fn check_object_for_community_or_site_ban<T, Kind>(
where where
T: ObjectExt<Kind>, T: ObjectExt<Kind>,
{ {
let user_id = object let person_id = object
.attributed_to() .attributed_to()
.context(location_info!())? .context(location_info!())?
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.context(location_info!())?; .context(location_info!())?;
let user = get_or_fetch_and_upsert_user(user_id, context, request_counter).await?; let person = get_or_fetch_and_upsert_person(person_id, context, request_counter).await?;
check_community_or_site_ban(&user, community_id, context.pool()).await check_community_or_site_ban(&person, community_id, context.pool()).await
} }
pub(in crate::objects) async fn get_to_community<T, Kind>( pub(in crate::objects) async fn get_to_community<T, Kind>(

View file

@ -22,7 +22,7 @@ use lemmy_api_structs::blocking;
use lemmy_db_queries::{ApubObject, DbPool}; use lemmy_db_queries::{ApubObject, DbPool};
use lemmy_db_schema::{ use lemmy_db_schema::{
naive_now, naive_now,
source::user::{UserForm, User_}, source::person::{Person as DbPerson, PersonForm},
}; };
use lemmy_utils::{ use lemmy_utils::{
location_info, location_info,
@ -34,7 +34,7 @@ use lemmy_websocket::LemmyContext;
use url::Url; use url::Url;
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl ToApub for User_ { impl ToApub for DbPerson {
type ApubType = PersonExt; type ApubType = PersonExt;
async fn to_apub(&self, _pool: &DbPool) -> Result<PersonExt, LemmyError> { async fn to_apub(&self, _pool: &DbPool) -> Result<PersonExt, LemmyError> {
@ -85,7 +85,7 @@ impl ToApub for User_ {
} }
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl FromApub for User_ { impl FromApub for DbPerson {
type ApubType = PersonExt; type ApubType = PersonExt;
async fn from_apub( async fn from_apub(
@ -93,26 +93,29 @@ impl FromApub for User_ {
context: &LemmyContext, context: &LemmyContext,
expected_domain: Url, expected_domain: Url,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<User_, LemmyError> { ) -> Result<DbPerson, LemmyError> {
let user_id = person.id_unchecked().context(location_info!())?.to_owned(); let person_id = person.id_unchecked().context(location_info!())?.to_owned();
let domain = user_id.domain().context(location_info!())?; let domain = person_id.domain().context(location_info!())?;
if domain == Settings::get().hostname() { if domain == Settings::get().hostname() {
let user = blocking(context.pool(), move |conn| { let person = blocking(context.pool(), move |conn| {
User_::read_from_apub_id(conn, &user_id.into()) DbPerson::read_from_apub_id(conn, &person_id.into())
}) })
.await??; .await??;
Ok(user) Ok(person)
} else { } else {
let user_form = let person_form =
UserForm::from_apub(person, context, expected_domain, request_counter).await?; PersonForm::from_apub(person, context, expected_domain, request_counter).await?;
let user = blocking(context.pool(), move |conn| User_::upsert(conn, &user_form)).await??; let person = blocking(context.pool(), move |conn| {
Ok(user) DbPerson::upsert(conn, &person_form)
})
.await??;
Ok(person)
} }
} }
} }
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl FromApubToForm<PersonExt> for UserForm { impl FromApubToForm<PersonExt> for PersonForm {
async fn from_apub( async fn from_apub(
person: &PersonExt, person: &PersonExt,
_context: &LemmyContext, _context: &LemmyContext,
@ -167,30 +170,20 @@ impl FromApubToForm<PersonExt> for UserForm {
check_slurs_opt(&preferred_username)?; check_slurs_opt(&preferred_username)?;
check_slurs_opt(&bio)?; check_slurs_opt(&bio)?;
Ok(UserForm { Ok(PersonForm {
name, name,
preferred_username: Some(preferred_username), preferred_username: Some(preferred_username),
password_encrypted: "".to_string(),
admin: false,
banned: None, banned: None,
email: None, deleted: None,
avatar: avatar.map(|o| o.map(|i| i.into())), avatar: avatar.map(|o| o.map(|i| i.into())),
banner: banner.map(|o| o.map(|i| i.into())), banner: banner.map(|o| o.map(|i| i.into())),
published: person.inner.published().map(|u| u.to_owned().naive_local()), published: person.inner.published().map(|u| u.to_owned().naive_local()),
updated: person.updated().map(|u| u.to_owned().naive_local()), updated: person.updated().map(|u| u.to_owned().naive_local()),
show_nsfw: false,
theme: "".to_string(),
default_sort_type: 0,
default_listing_type: 0,
lang: "".to_string(),
show_avatars: false,
send_notifications_to_email: false,
matrix_user_id: None,
actor_id: Some(check_object_domain(person, expected_domain)?), actor_id: Some(check_object_domain(person, expected_domain)?),
bio: Some(bio), bio: Some(bio),
local: false, local: Some(false),
private_key: None, private_key: None,
public_key: Some(person.ext_one.public_key.to_owned().public_key_pem), public_key: Some(Some(person.ext_one.public_key.to_owned().public_key_pem)),
last_refreshed_at: Some(naive_now()), last_refreshed_at: Some(naive_now()),
inbox_url: Some(person.inner.inbox()?.to_owned().into()), inbox_url: Some(person.inner.inbox()?.to_owned().into()),
shared_inbox_url: Some(shared_inbox), shared_inbox_url: Some(shared_inbox),

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
extensions::{context::lemmy_context, page_extension::PageExtension}, extensions::{context::lemmy_context, page_extension::PageExtension},
fetcher::user::get_or_fetch_and_upsert_user, fetcher::person::get_or_fetch_and_upsert_person,
objects::{ objects::{
check_object_domain, check_object_domain,
check_object_for_community_or_site_ban, check_object_for_community_or_site_ban,
@ -28,8 +28,8 @@ use lemmy_db_schema::{
self, self,
source::{ source::{
community::Community, community::Community,
person::Person,
post::{Post, PostForm}, post::{Post, PostForm},
user::User_,
}, },
}; };
use lemmy_utils::{ use lemmy_utils::{
@ -50,7 +50,7 @@ impl ToApub for Post {
let mut page = ApObject::new(Page::new()); let mut page = ApObject::new(Page::new());
let creator_id = self.creator_id; let creator_id = self.creator_id;
let creator = blocking(pool, move |conn| User_::read(conn, creator_id)).await??; let creator = blocking(pool, move |conn| Person::read(conn, creator_id)).await??;
let community_id = self.community_id; let community_id = self.community_id;
let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??;
@ -142,7 +142,8 @@ impl FromApubToForm<PageExt> for PostForm {
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.context(location_info!())?; .context(location_info!())?;
let creator = get_or_fetch_and_upsert_user(creator_actor_id, context, request_counter).await?; let creator =
get_or_fetch_and_upsert_person(creator_actor_id, context, request_counter).await?;
let community = get_to_community(page, context, request_counter).await?; let community = get_to_community(page, context, request_counter).await?;

View file

@ -1,7 +1,7 @@
use crate::{ use crate::{
check_is_apub_id_valid, check_is_apub_id_valid,
extensions::context::lemmy_context, extensions::context::lemmy_context,
fetcher::user::get_or_fetch_and_upsert_user, fetcher::person::get_or_fetch_and_upsert_person,
objects::{ objects::{
check_object_domain, check_object_domain,
create_tombstone, create_tombstone,
@ -22,8 +22,8 @@ use anyhow::Context;
use lemmy_api_structs::blocking; use lemmy_api_structs::blocking;
use lemmy_db_queries::{Crud, DbPool}; use lemmy_db_queries::{Crud, DbPool};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
person::Person,
private_message::{PrivateMessage, PrivateMessageForm}, private_message::{PrivateMessage, PrivateMessageForm},
user::User_,
}; };
use lemmy_utils::{location_info, utils::convert_datetime, LemmyError}; use lemmy_utils::{location_info, utils::convert_datetime, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -37,10 +37,10 @@ impl ToApub for PrivateMessage {
let mut private_message = ApObject::new(Note::new()); let mut private_message = ApObject::new(Note::new());
let creator_id = self.creator_id; let creator_id = self.creator_id;
let creator = blocking(pool, move |conn| User_::read(conn, creator_id)).await??; let creator = blocking(pool, move |conn| Person::read(conn, creator_id)).await??;
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; let recipient = blocking(pool, move |conn| Person::read(conn, recipient_id)).await??;
private_message private_message
.set_many_contexts(lemmy_context()?) .set_many_contexts(lemmy_context()?)
@ -97,7 +97,8 @@ impl FromApubToForm<NoteExt> for PrivateMessageForm {
.single_xsd_any_uri() .single_xsd_any_uri()
.context(location_info!())?; .context(location_info!())?;
let creator = get_or_fetch_and_upsert_user(&creator_actor_id, context, request_counter).await?; let creator =
get_or_fetch_and_upsert_person(&creator_actor_id, context, request_counter).await?;
let recipient_actor_id = note let recipient_actor_id = note
.to() .to()
.context(location_info!())? .context(location_info!())?
@ -105,7 +106,7 @@ impl FromApubToForm<NoteExt> for PrivateMessageForm {
.single_xsd_any_uri() .single_xsd_any_uri()
.context(location_info!())?; .context(location_info!())?;
let recipient = let recipient =
get_or_fetch_and_upsert_user(&recipient_actor_id, context, request_counter).await?; get_or_fetch_and_upsert_person(&recipient_actor_id, context, request_counter).await?;
let ap_id = note.id_unchecked().context(location_info!())?.to_string(); let ap_id = note.id_unchecked().context(location_info!())?.to_string();
check_is_apub_id_valid(&Url::parse(&ap_id)?)?; check_is_apub_id_valid(&Url::parse(&ap_id)?)?;

View file

@ -8,10 +8,14 @@ use crate::{
get_apub_community_outbox, get_apub_community_outbox,
}, },
get_activity, get_activity,
person::{get_apub_person_http, get_apub_person_inbox, get_apub_person_outbox},
post::get_apub_post, post::get_apub_post,
user::{get_apub_user_http, get_apub_user_inbox, get_apub_user_outbox},
}, },
inbox::{community_inbox::community_inbox, shared_inbox::shared_inbox, user_inbox::user_inbox}, inbox::{
community_inbox::community_inbox,
person_inbox::person_inbox,
shared_inbox::shared_inbox,
},
APUB_JSON_CONTENT_TYPE, APUB_JSON_CONTENT_TYPE,
}; };
use actix_web::*; use actix_web::*;
@ -53,9 +57,12 @@ pub fn config(cfg: &mut web::ServiceConfig) {
"/c/{community_name}/inbox", "/c/{community_name}/inbox",
web::get().to(get_apub_community_inbox), web::get().to(get_apub_community_inbox),
) )
.route("/u/{user_name}", web::get().to(get_apub_user_http)) .route("/u/{user_name}", web::get().to(get_apub_person_http))
.route("/u/{user_name}/outbox", web::get().to(get_apub_user_outbox)) .route(
.route("/u/{user_name}/inbox", web::get().to(get_apub_user_inbox)) "/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("/post/{post_id}", web::get().to(get_apub_post))
.route("/comment/{comment_id}", web::get().to(get_apub_comment)) .route("/comment/{comment_id}", web::get().to(get_apub_comment))
.route("/activities/{type_}/{id}", web::get().to(get_activity)), .route("/activities/{type_}/{id}", web::get().to(get_activity)),
@ -66,7 +73,7 @@ pub fn config(cfg: &mut web::ServiceConfig) {
.wrap(digest_verifier) .wrap(digest_verifier)
.guard(header_guard_content_type) .guard(header_guard_content_type)
.route("/c/{community_name}/inbox", web::post().to(community_inbox)) .route("/c/{community_name}/inbox", web::post().to(community_inbox))
.route("/u/{user_name}/inbox", web::post().to(user_inbox)) .route("/u/{user_name}/inbox", web::post().to(person_inbox))
.route("/inbox", web::post().to(shared_inbox)), .route("/inbox", web::post().to(shared_inbox)),
); );
} }

View file

@ -28,14 +28,12 @@ mod tests {
establish_unpooled_connection, establish_unpooled_connection,
Crud, Crud,
Likeable, Likeable,
ListingType,
SortType,
}; };
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::{Comment, CommentForm, CommentLike, CommentLikeForm}, comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
community::{Community, CommunityForm}, community::{Community, CommunityForm},
person::{Person, PersonForm},
post::{Post, PostForm}, post::{Post, PostForm},
user::{UserForm, User_},
}; };
use serial_test::serial; use serial_test::serial;
@ -44,28 +42,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let new_user = UserForm { let new_person = PersonForm {
name: "thommy_comment_agg".into(), name: "thommy_comment_agg".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -73,30 +61,20 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_user = User_::create(&conn, &new_user).unwrap(); let inserted_person = Person::create(&conn, &new_person).unwrap();
let another_user = UserForm { let another_person = PersonForm {
name: "jerry_comment_agg".into(), name: "jerry_comment_agg".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -104,11 +82,11 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let another_inserted_user = User_::create(&conn, &another_user).unwrap(); let another_inserted_person = Person::create(&conn, &another_person).unwrap();
let new_community = CommunityForm { let new_community = CommunityForm {
name: "TIL_comment_agg".into(), name: "TIL_comment_agg".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
nsfw: false, nsfw: false,
@ -134,7 +112,7 @@ mod tests {
name: "A test post".into(), name: "A test post".into(),
url: None, url: None,
body: None, body: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
community_id: inserted_community.id, community_id: inserted_community.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -155,7 +133,7 @@ mod tests {
let comment_form = CommentForm { let comment_form = CommentForm {
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -171,7 +149,7 @@ mod tests {
let child_comment_form = CommentForm { let child_comment_form = CommentForm {
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -188,7 +166,7 @@ mod tests {
let comment_like = CommentLikeForm { let comment_like = CommentLikeForm {
comment_id: inserted_comment.id, comment_id: inserted_comment.id,
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
score: 1, score: 1,
}; };
@ -200,11 +178,11 @@ mod tests {
assert_eq!(1, comment_aggs_before_delete.upvotes); assert_eq!(1, comment_aggs_before_delete.upvotes);
assert_eq!(0, comment_aggs_before_delete.downvotes); assert_eq!(0, comment_aggs_before_delete.downvotes);
// Add a post dislike from the other user // Add a post dislike from the other person
let comment_dislike = CommentLikeForm { let comment_dislike = CommentLikeForm {
comment_id: inserted_comment.id, comment_id: inserted_comment.id,
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: another_inserted_user.id, person_id: another_inserted_person.id,
score: -1, score: -1,
}; };
@ -217,7 +195,7 @@ mod tests {
assert_eq!(1, comment_aggs_after_dislike.downvotes); assert_eq!(1, comment_aggs_after_dislike.downvotes);
// Remove the first comment like // Remove the first comment like
CommentLike::remove(&conn, inserted_user.id, inserted_comment.id).unwrap(); CommentLike::remove(&conn, inserted_person.id, inserted_comment.id).unwrap();
let after_like_remove = CommentAggregates::read(&conn, inserted_comment.id).unwrap(); let after_like_remove = CommentAggregates::read(&conn, inserted_comment.id).unwrap();
assert_eq!(-1, after_like_remove.score); assert_eq!(-1, after_like_remove.score);
assert_eq!(0, after_like_remove.upvotes); assert_eq!(0, after_like_remove.upvotes);
@ -231,8 +209,8 @@ mod tests {
assert!(after_delete.is_err()); assert!(after_delete.is_err());
// This should delete all the associated rows, and fire triggers // This should delete all the associated rows, and fire triggers
User_::delete(&conn, another_inserted_user.id).unwrap(); Person::delete(&conn, another_inserted_person.id).unwrap();
let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap(); let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
assert_eq!(1, user_num_deleted); assert_eq!(1, person_num_deleted);
} }
} }

View file

@ -32,14 +32,12 @@ mod tests {
establish_unpooled_connection, establish_unpooled_connection,
Crud, Crud,
Followable, Followable,
ListingType,
SortType,
}; };
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::{Comment, CommentForm}, comment::{Comment, CommentForm},
community::{Community, CommunityFollower, CommunityFollowerForm, CommunityForm}, community::{Community, CommunityFollower, CommunityFollowerForm, CommunityForm},
person::{Person, PersonForm},
post::{Post, PostForm}, post::{Post, PostForm},
user::{UserForm, User_},
}; };
use serial_test::serial; use serial_test::serial;
@ -48,28 +46,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let new_user = UserForm { let new_person = PersonForm {
name: "thommy_community_agg".into(), name: "thommy_community_agg".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -77,30 +65,20 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_user = User_::create(&conn, &new_user).unwrap(); let inserted_person = Person::create(&conn, &new_person).unwrap();
let another_user = UserForm { let another_person = PersonForm {
name: "jerry_community_agg".into(), name: "jerry_community_agg".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -108,11 +86,11 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let another_inserted_user = User_::create(&conn, &another_user).unwrap(); let another_inserted_person = Person::create(&conn, &another_person).unwrap();
let new_community = CommunityForm { let new_community = CommunityForm {
name: "TIL_community_agg".into(), name: "TIL_community_agg".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
nsfw: false, nsfw: false,
@ -136,7 +114,7 @@ mod tests {
let another_community = CommunityForm { let another_community = CommunityForm {
name: "TIL_community_agg_2".into(), name: "TIL_community_agg_2".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
nsfw: false, nsfw: false,
@ -158,25 +136,25 @@ mod tests {
let another_inserted_community = Community::create(&conn, &another_community).unwrap(); let another_inserted_community = Community::create(&conn, &another_community).unwrap();
let first_user_follow = CommunityFollowerForm { let first_person_follow = CommunityFollowerForm {
community_id: inserted_community.id, community_id: inserted_community.id,
user_id: inserted_user.id, person_id: inserted_person.id,
pending: false, pending: false,
}; };
CommunityFollower::follow(&conn, &first_user_follow).unwrap(); CommunityFollower::follow(&conn, &first_person_follow).unwrap();
let second_user_follow = CommunityFollowerForm { let second_person_follow = CommunityFollowerForm {
community_id: inserted_community.id, community_id: inserted_community.id,
user_id: another_inserted_user.id, person_id: another_inserted_person.id,
pending: false, pending: false,
}; };
CommunityFollower::follow(&conn, &second_user_follow).unwrap(); CommunityFollower::follow(&conn, &second_person_follow).unwrap();
let another_community_follow = CommunityFollowerForm { let another_community_follow = CommunityFollowerForm {
community_id: another_inserted_community.id, community_id: another_inserted_community.id,
user_id: inserted_user.id, person_id: inserted_person.id,
pending: false, pending: false,
}; };
@ -186,7 +164,7 @@ mod tests {
name: "A test post".into(), name: "A test post".into(),
url: None, url: None,
body: None, body: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
community_id: inserted_community.id, community_id: inserted_community.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -207,7 +185,7 @@ mod tests {
let comment_form = CommentForm { let comment_form = CommentForm {
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -223,7 +201,7 @@ mod tests {
let child_comment_form = CommentForm { let child_comment_form = CommentForm {
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -252,12 +230,12 @@ mod tests {
assert_eq!(0, another_community_aggs.comments); assert_eq!(0, another_community_aggs.comments);
// Unfollow test // Unfollow test
CommunityFollower::unfollow(&conn, &second_user_follow).unwrap(); CommunityFollower::unfollow(&conn, &second_person_follow).unwrap();
let after_unfollow = CommunityAggregates::read(&conn, inserted_community.id).unwrap(); let after_unfollow = CommunityAggregates::read(&conn, inserted_community.id).unwrap();
assert_eq!(1, after_unfollow.subscribers); assert_eq!(1, after_unfollow.subscribers);
// Follow again just for the later tests // Follow again just for the later tests
CommunityFollower::follow(&conn, &second_user_follow).unwrap(); CommunityFollower::follow(&conn, &second_person_follow).unwrap();
let after_follow_again = CommunityAggregates::read(&conn, inserted_community.id).unwrap(); let after_follow_again = CommunityAggregates::read(&conn, inserted_community.id).unwrap();
assert_eq!(2, after_follow_again.subscribers); assert_eq!(2, after_follow_again.subscribers);
@ -267,14 +245,14 @@ mod tests {
assert_eq!(0, after_parent_post_delete.comments); assert_eq!(0, after_parent_post_delete.comments);
assert_eq!(0, after_parent_post_delete.posts); assert_eq!(0, after_parent_post_delete.posts);
// Remove the 2nd user // Remove the 2nd person
User_::delete(&conn, another_inserted_user.id).unwrap(); Person::delete(&conn, another_inserted_person.id).unwrap();
let after_user_delete = CommunityAggregates::read(&conn, inserted_community.id).unwrap(); let after_person_delete = CommunityAggregates::read(&conn, inserted_community.id).unwrap();
assert_eq!(1, after_user_delete.subscribers); assert_eq!(1, after_person_delete.subscribers);
// This should delete all the associated rows, and fire triggers // This should delete all the associated rows, and fire triggers
let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap(); let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
assert_eq!(1, user_num_deleted); assert_eq!(1, person_num_deleted);
// Should be none found, since the creator was deleted // Should be none found, since the creator was deleted
let after_delete = CommunityAggregates::read(&conn, inserted_community.id); let after_delete = CommunityAggregates::read(&conn, inserted_community.id);

View file

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

View file

@ -1,22 +1,22 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_schema::schema::user_aggregates; use lemmy_db_schema::schema::person_aggregates;
use serde::Serialize; use serde::Serialize;
#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)] #[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
#[table_name = "user_aggregates"] #[table_name = "person_aggregates"]
pub struct UserAggregates { pub struct PersonAggregates {
pub id: i32, pub id: i32,
pub user_id: i32, pub person_id: i32,
pub post_count: i64, pub post_count: i64,
pub post_score: i64, pub post_score: i64,
pub comment_count: i64, pub comment_count: i64,
pub comment_score: i64, pub comment_score: i64,
} }
impl UserAggregates { impl PersonAggregates {
pub fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> { pub fn read(conn: &PgConnection, person_id: i32) -> Result<Self, Error> {
user_aggregates::table person_aggregates::table
.filter(user_aggregates::user_id.eq(user_id)) .filter(person_aggregates::person_id.eq(person_id))
.first::<Self>(conn) .first::<Self>(conn)
} }
} }
@ -24,18 +24,16 @@ impl UserAggregates {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{
aggregates::user_aggregates::UserAggregates, aggregates::person_aggregates::PersonAggregates,
establish_unpooled_connection, establish_unpooled_connection,
Crud, Crud,
Likeable, Likeable,
ListingType,
SortType,
}; };
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::{Comment, CommentForm, CommentLike, CommentLikeForm}, comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
community::{Community, CommunityForm}, community::{Community, CommunityForm},
person::{Person, PersonForm},
post::{Post, PostForm, PostLike, PostLikeForm}, post::{Post, PostForm, PostLike, PostLikeForm},
user::{UserForm, User_},
}; };
use serial_test::serial; use serial_test::serial;
@ -44,28 +42,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let new_user = UserForm { let new_person = PersonForm {
name: "thommy_user_agg".into(), name: "thommy_user_agg".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -73,30 +61,20 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_user = User_::create(&conn, &new_user).unwrap(); let inserted_person = Person::create(&conn, &new_person).unwrap();
let another_user = UserForm { let another_person = PersonForm {
name: "jerry_user_agg".into(), name: "jerry_user_agg".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -104,11 +82,11 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let another_inserted_user = User_::create(&conn, &another_user).unwrap(); let another_inserted_person = Person::create(&conn, &another_person).unwrap();
let new_community = CommunityForm { let new_community = CommunityForm {
name: "TIL_site_agg".into(), name: "TIL_site_agg".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
nsfw: false, nsfw: false,
@ -134,7 +112,7 @@ mod tests {
name: "A test post".into(), name: "A test post".into(),
url: None, url: None,
body: None, body: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
community_id: inserted_community.id, community_id: inserted_community.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -155,7 +133,7 @@ mod tests {
let post_like = PostLikeForm { let post_like = PostLikeForm {
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
score: 1, score: 1,
}; };
@ -163,7 +141,7 @@ mod tests {
let comment_form = CommentForm { let comment_form = CommentForm {
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -179,7 +157,7 @@ mod tests {
let mut comment_like = CommentLikeForm { let mut comment_like = CommentLikeForm {
comment_id: inserted_comment.id, comment_id: inserted_comment.id,
user_id: inserted_user.id, person_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
score: 1, score: 1,
}; };
@ -188,7 +166,7 @@ mod tests {
let mut child_comment_form = CommentForm { let mut child_comment_form = CommentForm {
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -204,28 +182,29 @@ mod tests {
let child_comment_like = CommentLikeForm { let child_comment_like = CommentLikeForm {
comment_id: inserted_child_comment.id, comment_id: inserted_child_comment.id,
user_id: another_inserted_user.id, person_id: another_inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
score: 1, score: 1,
}; };
let _inserted_child_comment_like = CommentLike::like(&conn, &child_comment_like).unwrap(); let _inserted_child_comment_like = CommentLike::like(&conn, &child_comment_like).unwrap();
let user_aggregates_before_delete = UserAggregates::read(&conn, inserted_user.id).unwrap(); let person_aggregates_before_delete =
PersonAggregates::read(&conn, inserted_person.id).unwrap();
assert_eq!(1, user_aggregates_before_delete.post_count); assert_eq!(1, person_aggregates_before_delete.post_count);
assert_eq!(1, user_aggregates_before_delete.post_score); assert_eq!(1, person_aggregates_before_delete.post_score);
assert_eq!(2, user_aggregates_before_delete.comment_count); assert_eq!(2, person_aggregates_before_delete.comment_count);
assert_eq!(2, user_aggregates_before_delete.comment_score); assert_eq!(2, person_aggregates_before_delete.comment_score);
// Remove a post like // Remove a post like
PostLike::remove(&conn, inserted_user.id, inserted_post.id).unwrap(); PostLike::remove(&conn, inserted_person.id, inserted_post.id).unwrap();
let after_post_like_remove = UserAggregates::read(&conn, inserted_user.id).unwrap(); let after_post_like_remove = PersonAggregates::read(&conn, inserted_person.id).unwrap();
assert_eq!(0, after_post_like_remove.post_score); assert_eq!(0, after_post_like_remove.post_score);
// Remove a parent comment (the scores should also be removed) // Remove a parent comment (the scores should also be removed)
Comment::delete(&conn, inserted_comment.id).unwrap(); Comment::delete(&conn, inserted_comment.id).unwrap();
let after_parent_comment_delete = UserAggregates::read(&conn, inserted_user.id).unwrap(); let after_parent_comment_delete = PersonAggregates::read(&conn, inserted_person.id).unwrap();
assert_eq!(0, after_parent_comment_delete.comment_count); assert_eq!(0, after_parent_comment_delete.comment_count);
assert_eq!(0, after_parent_comment_delete.comment_score); assert_eq!(0, after_parent_comment_delete.comment_score);
@ -235,24 +214,24 @@ mod tests {
Comment::create(&conn, &child_comment_form).unwrap(); Comment::create(&conn, &child_comment_form).unwrap();
comment_like.comment_id = new_parent_comment.id; comment_like.comment_id = new_parent_comment.id;
CommentLike::like(&conn, &comment_like).unwrap(); CommentLike::like(&conn, &comment_like).unwrap();
let after_comment_add = UserAggregates::read(&conn, inserted_user.id).unwrap(); let after_comment_add = PersonAggregates::read(&conn, inserted_person.id).unwrap();
assert_eq!(2, after_comment_add.comment_count); assert_eq!(2, after_comment_add.comment_count);
assert_eq!(1, after_comment_add.comment_score); assert_eq!(1, after_comment_add.comment_score);
Post::delete(&conn, inserted_post.id).unwrap(); Post::delete(&conn, inserted_post.id).unwrap();
let after_post_delete = UserAggregates::read(&conn, inserted_user.id).unwrap(); let after_post_delete = PersonAggregates::read(&conn, inserted_person.id).unwrap();
assert_eq!(0, after_post_delete.comment_score); assert_eq!(0, after_post_delete.comment_score);
assert_eq!(0, after_post_delete.comment_count); assert_eq!(0, after_post_delete.comment_count);
assert_eq!(0, after_post_delete.post_score); assert_eq!(0, after_post_delete.post_score);
assert_eq!(0, after_post_delete.post_count); assert_eq!(0, after_post_delete.post_count);
// This should delete all the associated rows, and fire triggers // This should delete all the associated rows, and fire triggers
let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap(); let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
assert_eq!(1, user_num_deleted); assert_eq!(1, person_num_deleted);
User_::delete(&conn, another_inserted_user.id).unwrap(); Person::delete(&conn, another_inserted_person.id).unwrap();
// Should be none found // Should be none found
let after_delete = UserAggregates::read(&conn, inserted_user.id); let after_delete = PersonAggregates::read(&conn, inserted_person.id);
assert!(after_delete.is_err()); assert!(after_delete.is_err());
} }
} }

View file

@ -32,14 +32,12 @@ mod tests {
establish_unpooled_connection, establish_unpooled_connection,
Crud, Crud,
Likeable, Likeable,
ListingType,
SortType,
}; };
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::{Comment, CommentForm}, comment::{Comment, CommentForm},
community::{Community, CommunityForm}, community::{Community, CommunityForm},
person::{Person, PersonForm},
post::{Post, PostForm, PostLike, PostLikeForm}, post::{Post, PostForm, PostLike, PostLikeForm},
user::{UserForm, User_},
}; };
use serial_test::serial; use serial_test::serial;
@ -48,28 +46,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let new_user = UserForm { let new_person = PersonForm {
name: "thommy_community_agg".into(), name: "thommy_community_agg".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -77,30 +65,20 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_user = User_::create(&conn, &new_user).unwrap(); let inserted_person = Person::create(&conn, &new_person).unwrap();
let another_user = UserForm { let another_person = PersonForm {
name: "jerry_community_agg".into(), name: "jerry_community_agg".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -108,11 +86,11 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let another_inserted_user = User_::create(&conn, &another_user).unwrap(); let another_inserted_person = Person::create(&conn, &another_person).unwrap();
let new_community = CommunityForm { let new_community = CommunityForm {
name: "TIL_community_agg".into(), name: "TIL_community_agg".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
nsfw: false, nsfw: false,
@ -138,7 +116,7 @@ mod tests {
name: "A test post".into(), name: "A test post".into(),
url: None, url: None,
body: None, body: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
community_id: inserted_community.id, community_id: inserted_community.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -159,7 +137,7 @@ mod tests {
let comment_form = CommentForm { let comment_form = CommentForm {
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -175,7 +153,7 @@ mod tests {
let child_comment_form = CommentForm { let child_comment_form = CommentForm {
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -191,7 +169,7 @@ mod tests {
let post_like = PostLikeForm { let post_like = PostLikeForm {
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
score: 1, score: 1,
}; };
@ -204,10 +182,10 @@ mod tests {
assert_eq!(1, post_aggs_before_delete.upvotes); assert_eq!(1, post_aggs_before_delete.upvotes);
assert_eq!(0, post_aggs_before_delete.downvotes); assert_eq!(0, post_aggs_before_delete.downvotes);
// Add a post dislike from the other user // Add a post dislike from the other person
let post_dislike = PostLikeForm { let post_dislike = PostLikeForm {
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: another_inserted_user.id, person_id: another_inserted_person.id,
score: -1, score: -1,
}; };
@ -229,7 +207,7 @@ mod tests {
assert_eq!(1, after_comment_delete.downvotes); assert_eq!(1, after_comment_delete.downvotes);
// Remove the first post like // Remove the first post like
PostLike::remove(&conn, inserted_user.id, inserted_post.id).unwrap(); PostLike::remove(&conn, inserted_person.id, inserted_post.id).unwrap();
let after_like_remove = PostAggregates::read(&conn, inserted_post.id).unwrap(); let after_like_remove = PostAggregates::read(&conn, inserted_post.id).unwrap();
assert_eq!(0, after_like_remove.comments); assert_eq!(0, after_like_remove.comments);
assert_eq!(-1, after_like_remove.score); assert_eq!(-1, after_like_remove.score);
@ -237,9 +215,9 @@ mod tests {
assert_eq!(1, after_like_remove.downvotes); assert_eq!(1, after_like_remove.downvotes);
// This should delete all the associated rows, and fire triggers // This should delete all the associated rows, and fire triggers
User_::delete(&conn, another_inserted_user.id).unwrap(); Person::delete(&conn, another_inserted_person.id).unwrap();
let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap(); let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
assert_eq!(1, user_num_deleted); assert_eq!(1, person_num_deleted);
// Should be none found, since the creator was deleted // Should be none found, since the creator was deleted
let after_delete = PostAggregates::read(&conn, inserted_post.id); let after_delete = PostAggregates::read(&conn, inserted_post.id);

View file

@ -25,19 +25,13 @@ impl SiteAggregates {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{aggregates::site_aggregates::SiteAggregates, establish_unpooled_connection, Crud};
aggregates::site_aggregates::SiteAggregates,
establish_unpooled_connection,
Crud,
ListingType,
SortType,
};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::{Comment, CommentForm}, comment::{Comment, CommentForm},
community::{Community, CommunityForm}, community::{Community, CommunityForm},
person::{Person, PersonForm},
post::{Post, PostForm}, post::{Post, PostForm},
site::{Site, SiteForm}, site::{Site, SiteForm},
user::{UserForm, User_},
}; };
use serial_test::serial; use serial_test::serial;
@ -46,28 +40,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let new_user = UserForm { let new_person = PersonForm {
name: "thommy_site_agg".into(), name: "thommy_site_agg".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -75,14 +59,14 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_user = User_::create(&conn, &new_user).unwrap(); let inserted_person = Person::create(&conn, &new_person).unwrap();
let site_form = SiteForm { let site_form = SiteForm {
name: "test_site".into(), name: "test_site".into(),
description: None, description: None,
icon: None, icon: None,
banner: None, banner: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
enable_downvotes: true, enable_downvotes: true,
open_registration: true, open_registration: true,
enable_nsfw: true, enable_nsfw: true,
@ -93,7 +77,7 @@ mod tests {
let new_community = CommunityForm { let new_community = CommunityForm {
name: "TIL_site_agg".into(), name: "TIL_site_agg".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
nsfw: false, nsfw: false,
@ -119,7 +103,7 @@ mod tests {
name: "A test post".into(), name: "A test post".into(),
url: None, url: None,
body: None, body: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
community_id: inserted_community.id, community_id: inserted_community.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -142,7 +126,7 @@ mod tests {
let comment_form = CommentForm { let comment_form = CommentForm {
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -159,7 +143,7 @@ mod tests {
let child_comment_form = CommentForm { let child_comment_form = CommentForm {
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -187,8 +171,8 @@ mod tests {
assert_eq!(0, site_aggregates_after_post_delete.comments); assert_eq!(0, site_aggregates_after_post_delete.comments);
// This shouuld delete all the associated rows, and fire triggers // This shouuld delete all the associated rows, and fire triggers
let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap(); let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
assert_eq!(1, user_num_deleted); assert_eq!(1, person_num_deleted);
let after_delete = SiteAggregates::read(&conn); let after_delete = SiteAggregates::read(&conn);
assert!(after_delete.is_err()); assert!(after_delete.is_err());

View file

@ -47,7 +47,7 @@ pub trait Followable<T> {
fn follow(conn: &PgConnection, form: &T) -> Result<Self, Error> fn follow(conn: &PgConnection, form: &T) -> Result<Self, Error>
where where
Self: Sized; Self: Sized;
fn follow_accepted(conn: &PgConnection, community_id: i32, user_id: i32) -> Result<Self, Error> fn follow_accepted(conn: &PgConnection, community_id: i32, person_id: i32) -> Result<Self, Error>
where where
Self: Sized; Self: Sized;
fn unfollow(conn: &PgConnection, form: &T) -> Result<usize, Error> fn unfollow(conn: &PgConnection, form: &T) -> Result<usize, Error>
@ -69,7 +69,7 @@ pub trait Likeable<T> {
fn like(conn: &PgConnection, form: &T) -> Result<Self, Error> fn like(conn: &PgConnection, form: &T) -> Result<Self, Error>
where where
Self: Sized; Self: Sized;
fn remove(conn: &PgConnection, user_id: i32, item_id: i32) -> Result<usize, Error> fn remove(conn: &PgConnection, person_id: i32, item_id: i32) -> Result<usize, Error>
where where
Self: Sized; Self: Sized;
} }

View file

@ -122,16 +122,10 @@ impl Activity_ for Activity {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::{ use crate::{establish_unpooled_connection, source::activity::Activity_};
establish_unpooled_connection,
source::activity::Activity_,
Crud,
ListingType,
SortType,
};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
activity::{Activity, ActivityForm}, activity::{Activity, ActivityForm},
user::{UserForm, User_}, person::{Person, PersonForm},
}; };
use serde_json::Value; use serde_json::Value;
use serial_test::serial; use serial_test::serial;
@ -142,28 +136,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let creator_form = UserForm { let creator_form = PersonForm {
name: "activity_creator_pm".into(), name: "activity_creator_pm".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -171,7 +155,7 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_creator = User_::create(&conn, &creator_form).unwrap(); let inserted_creator = Person::create(&conn, &creator_form).unwrap();
let ap_id: DbUrl = Url::parse( let ap_id: DbUrl = Url::parse(
"https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c", "https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c",
@ -214,7 +198,7 @@ mod tests {
let read_activity = Activity::read(&conn, inserted_activity.id).unwrap(); let read_activity = Activity::read(&conn, inserted_activity.id).unwrap();
let read_activity_by_apub_id = Activity::read_from_apub_id(&conn, &ap_id).unwrap(); let read_activity_by_apub_id = Activity::read_from_apub_id(&conn, &ap_id).unwrap();
User_::delete(&conn, inserted_creator.id).unwrap(); Person::delete(&conn, inserted_creator.id).unwrap();
Activity::delete(&conn, inserted_activity.id).unwrap(); Activity::delete(&conn, inserted_activity.id).unwrap();
assert_eq!(expected_activity, read_activity); assert_eq!(expected_activity, read_activity);

View file

@ -166,17 +166,17 @@ impl Likeable<CommentLikeForm> for CommentLike {
use lemmy_db_schema::schema::comment_like::dsl::*; use lemmy_db_schema::schema::comment_like::dsl::*;
insert_into(comment_like) insert_into(comment_like)
.values(comment_like_form) .values(comment_like_form)
.on_conflict((comment_id, user_id)) .on_conflict((comment_id, person_id))
.do_update() .do_update()
.set(comment_like_form) .set(comment_like_form)
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
fn remove(conn: &PgConnection, user_id: i32, comment_id: i32) -> Result<usize, Error> { fn remove(conn: &PgConnection, person_id: i32, comment_id: i32) -> Result<usize, Error> {
use lemmy_db_schema::schema::comment_like::dsl; use lemmy_db_schema::schema::comment_like::dsl;
diesel::delete( diesel::delete(
dsl::comment_like dsl::comment_like
.filter(dsl::comment_id.eq(comment_id)) .filter(dsl::comment_id.eq(comment_id))
.filter(dsl::user_id.eq(user_id)), .filter(dsl::person_id.eq(person_id)),
) )
.execute(conn) .execute(conn)
} }
@ -187,7 +187,7 @@ impl Saveable<CommentSavedForm> for CommentSaved {
use lemmy_db_schema::schema::comment_saved::dsl::*; use lemmy_db_schema::schema::comment_saved::dsl::*;
insert_into(comment_saved) insert_into(comment_saved)
.values(comment_saved_form) .values(comment_saved_form)
.on_conflict((comment_id, user_id)) .on_conflict((comment_id, person_id))
.do_update() .do_update()
.set(comment_saved_form) .set(comment_saved_form)
.get_result::<Self>(conn) .get_result::<Self>(conn)
@ -197,7 +197,7 @@ impl Saveable<CommentSavedForm> for CommentSaved {
diesel::delete( diesel::delete(
comment_saved comment_saved
.filter(comment_id.eq(comment_saved_form.comment_id)) .filter(comment_id.eq(comment_saved_form.comment_id))
.filter(user_id.eq(comment_saved_form.user_id)), .filter(person_id.eq(comment_saved_form.person_id)),
) )
.execute(conn) .execute(conn)
} }
@ -205,12 +205,12 @@ impl Saveable<CommentSavedForm> for CommentSaved {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{establish_unpooled_connection, Crud, Likeable, ListingType, Saveable, SortType}; use crate::{establish_unpooled_connection, Crud, Likeable, Saveable};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::*, comment::*,
community::{Community, CommunityForm}, community::{Community, CommunityForm},
person::{Person, PersonForm},
post::*, post::*,
user::{UserForm, User_},
}; };
use serial_test::serial; use serial_test::serial;
@ -219,28 +219,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let new_user = UserForm { let new_person = PersonForm {
name: "terry".into(), name: "terry".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -248,13 +238,13 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_user = User_::create(&conn, &new_user).unwrap(); let inserted_person = Person::create(&conn, &new_person).unwrap();
let new_community = CommunityForm { let new_community = CommunityForm {
name: "test community".to_string(), name: "test community".to_string(),
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
removed: None, removed: None,
deleted: None, deleted: None,
updated: None, updated: None,
@ -276,7 +266,7 @@ mod tests {
let new_post = PostForm { let new_post = PostForm {
name: "A test post".into(), name: "A test post".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
url: None, url: None,
body: None, body: None,
community_id: inserted_community.id, community_id: inserted_community.id,
@ -299,7 +289,7 @@ mod tests {
let comment_form = CommentForm { let comment_form = CommentForm {
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -316,7 +306,7 @@ mod tests {
let expected_comment = Comment { let expected_comment = Comment {
id: inserted_comment.id, id: inserted_comment.id,
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: false, removed: false,
deleted: false, deleted: false,
@ -330,7 +320,7 @@ mod tests {
let child_comment_form = CommentForm { let child_comment_form = CommentForm {
content: "A child comment".into(), content: "A child comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
parent_id: Some(inserted_comment.id), parent_id: Some(inserted_comment.id),
removed: None, removed: None,
@ -348,7 +338,7 @@ mod tests {
let comment_like_form = CommentLikeForm { let comment_like_form = CommentLikeForm {
comment_id: inserted_comment.id, comment_id: inserted_comment.id,
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
score: 1, score: 1,
}; };
@ -358,7 +348,7 @@ mod tests {
id: inserted_comment_like.id, id: inserted_comment_like.id,
comment_id: inserted_comment.id, comment_id: inserted_comment.id,
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
published: inserted_comment_like.published, published: inserted_comment_like.published,
score: 1, score: 1,
}; };
@ -366,7 +356,7 @@ mod tests {
// Comment Saved // Comment Saved
let comment_saved_form = CommentSavedForm { let comment_saved_form = CommentSavedForm {
comment_id: inserted_comment.id, comment_id: inserted_comment.id,
user_id: inserted_user.id, person_id: inserted_person.id,
}; };
let inserted_comment_saved = CommentSaved::save(&conn, &comment_saved_form).unwrap(); let inserted_comment_saved = CommentSaved::save(&conn, &comment_saved_form).unwrap();
@ -374,19 +364,19 @@ mod tests {
let expected_comment_saved = CommentSaved { let expected_comment_saved = CommentSaved {
id: inserted_comment_saved.id, id: inserted_comment_saved.id,
comment_id: inserted_comment.id, comment_id: inserted_comment.id,
user_id: inserted_user.id, person_id: inserted_person.id,
published: inserted_comment_saved.published, published: inserted_comment_saved.published,
}; };
let read_comment = Comment::read(&conn, inserted_comment.id).unwrap(); let read_comment = Comment::read(&conn, inserted_comment.id).unwrap();
let updated_comment = Comment::update(&conn, inserted_comment.id, &comment_form).unwrap(); let updated_comment = Comment::update(&conn, inserted_comment.id, &comment_form).unwrap();
let like_removed = CommentLike::remove(&conn, inserted_user.id, inserted_comment.id).unwrap(); let like_removed = CommentLike::remove(&conn, inserted_person.id, inserted_comment.id).unwrap();
let saved_removed = CommentSaved::unsave(&conn, &comment_saved_form).unwrap(); let saved_removed = CommentSaved::unsave(&conn, &comment_saved_form).unwrap();
let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap(); let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap();
Comment::delete(&conn, inserted_child_comment.id).unwrap(); Comment::delete(&conn, inserted_child_comment.id).unwrap();
Post::delete(&conn, inserted_post.id).unwrap(); Post::delete(&conn, inserted_post.id).unwrap();
Community::delete(&conn, inserted_community.id).unwrap(); Community::delete(&conn, inserted_community.id).unwrap();
User_::delete(&conn, inserted_user.id).unwrap(); Person::delete(&conn, inserted_person.id).unwrap();
assert_eq!(expected_comment, read_comment); assert_eq!(expected_comment, read_comment);
assert_eq!(expected_comment, inserted_comment); assert_eq!(expected_comment, inserted_comment);

View file

@ -9,8 +9,8 @@ use lemmy_db_schema::{
CommunityForm, CommunityForm,
CommunityModerator, CommunityModerator,
CommunityModeratorForm, CommunityModeratorForm,
CommunityUserBan, CommunityPersonBan,
CommunityUserBanForm, CommunityPersonBanForm,
}, },
DbUrl, DbUrl,
}; };
@ -209,23 +209,23 @@ impl Community_ for Community {
impl Joinable<CommunityModeratorForm> for CommunityModerator { impl Joinable<CommunityModeratorForm> for CommunityModerator {
fn join( fn join(
conn: &PgConnection, conn: &PgConnection,
community_user_form: &CommunityModeratorForm, community_moderator_form: &CommunityModeratorForm,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
use lemmy_db_schema::schema::community_moderator::dsl::*; use lemmy_db_schema::schema::community_moderator::dsl::*;
insert_into(community_moderator) insert_into(community_moderator)
.values(community_user_form) .values(community_moderator_form)
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
fn leave( fn leave(
conn: &PgConnection, conn: &PgConnection,
community_user_form: &CommunityModeratorForm, community_moderator_form: &CommunityModeratorForm,
) -> Result<usize, Error> { ) -> Result<usize, Error> {
use lemmy_db_schema::schema::community_moderator::dsl::*; use lemmy_db_schema::schema::community_moderator::dsl::*;
diesel::delete( diesel::delete(
community_moderator community_moderator
.filter(community_id.eq(community_user_form.community_id)) .filter(community_id.eq(community_moderator_form.community_id))
.filter(user_id.eq(community_user_form.user_id)), .filter(person_id.eq(community_moderator_form.person_id)),
) )
.execute(conn) .execute(conn)
} }
@ -233,9 +233,9 @@ impl Joinable<CommunityModeratorForm> for CommunityModerator {
pub trait CommunityModerator_ { pub trait CommunityModerator_ {
fn delete_for_community(conn: &PgConnection, for_community_id: i32) -> Result<usize, Error>; fn delete_for_community(conn: &PgConnection, for_community_id: i32) -> Result<usize, Error>;
fn get_user_moderated_communities( fn get_person_moderated_communities(
conn: &PgConnection, conn: &PgConnection,
for_user_id: i32, for_person_id: i32,
) -> Result<Vec<i32>, Error>; ) -> Result<Vec<i32>, Error>;
} }
@ -245,38 +245,38 @@ impl CommunityModerator_ for CommunityModerator {
diesel::delete(community_moderator.filter(community_id.eq(for_community_id))).execute(conn) diesel::delete(community_moderator.filter(community_id.eq(for_community_id))).execute(conn)
} }
fn get_user_moderated_communities( fn get_person_moderated_communities(
conn: &PgConnection, conn: &PgConnection,
for_user_id: i32, for_person_id: i32,
) -> Result<Vec<i32>, Error> { ) -> Result<Vec<i32>, Error> {
use lemmy_db_schema::schema::community_moderator::dsl::*; use lemmy_db_schema::schema::community_moderator::dsl::*;
community_moderator community_moderator
.filter(user_id.eq(for_user_id)) .filter(person_id.eq(for_person_id))
.select(community_id) .select(community_id)
.load::<i32>(conn) .load::<i32>(conn)
} }
} }
impl Bannable<CommunityUserBanForm> for CommunityUserBan { impl Bannable<CommunityPersonBanForm> for CommunityPersonBan {
fn ban( fn ban(
conn: &PgConnection, conn: &PgConnection,
community_user_ban_form: &CommunityUserBanForm, community_person_ban_form: &CommunityPersonBanForm,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
use lemmy_db_schema::schema::community_user_ban::dsl::*; use lemmy_db_schema::schema::community_person_ban::dsl::*;
insert_into(community_user_ban) insert_into(community_person_ban)
.values(community_user_ban_form) .values(community_person_ban_form)
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
fn unban( fn unban(
conn: &PgConnection, conn: &PgConnection,
community_user_ban_form: &CommunityUserBanForm, community_person_ban_form: &CommunityPersonBanForm,
) -> Result<usize, Error> { ) -> Result<usize, Error> {
use lemmy_db_schema::schema::community_user_ban::dsl::*; use lemmy_db_schema::schema::community_person_ban::dsl::*;
diesel::delete( diesel::delete(
community_user_ban community_person_ban
.filter(community_id.eq(community_user_ban_form.community_id)) .filter(community_id.eq(community_person_ban_form.community_id))
.filter(user_id.eq(community_user_ban_form.user_id)), .filter(person_id.eq(community_person_ban_form.person_id)),
) )
.execute(conn) .execute(conn)
} }
@ -290,12 +290,16 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
use lemmy_db_schema::schema::community_follower::dsl::*; use lemmy_db_schema::schema::community_follower::dsl::*;
insert_into(community_follower) insert_into(community_follower)
.values(community_follower_form) .values(community_follower_form)
.on_conflict((community_id, user_id)) .on_conflict((community_id, person_id))
.do_update() .do_update()
.set(community_follower_form) .set(community_follower_form)
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
fn follow_accepted(conn: &PgConnection, community_id_: i32, user_id_: i32) -> Result<Self, Error> fn follow_accepted(
conn: &PgConnection,
community_id_: i32,
person_id_: i32,
) -> Result<Self, Error>
where where
Self: Sized, Self: Sized,
{ {
@ -303,7 +307,7 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
diesel::update( diesel::update(
community_follower community_follower
.filter(community_id.eq(community_id_)) .filter(community_id.eq(community_id_))
.filter(user_id.eq(user_id_)), .filter(person_id.eq(person_id_)),
) )
.set(pending.eq(true)) .set(pending.eq(true))
.get_result::<Self>(conn) .get_result::<Self>(conn)
@ -316,7 +320,7 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
diesel::delete( diesel::delete(
community_follower community_follower
.filter(community_id.eq(&community_follower_form.community_id)) .filter(community_id.eq(&community_follower_form.community_id))
.filter(user_id.eq(&community_follower_form.user_id)), .filter(person_id.eq(&community_follower_form.person_id)),
) )
.execute(conn) .execute(conn)
} }
@ -333,16 +337,8 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{establish_unpooled_connection, Bannable, Crud, Followable, Joinable};
establish_unpooled_connection, use lemmy_db_schema::source::{community::*, person::*};
Bannable,
Crud,
Followable,
Joinable,
ListingType,
SortType,
};
use lemmy_db_schema::source::{community::*, user::*};
use serial_test::serial; use serial_test::serial;
#[test] #[test]
@ -350,28 +346,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let new_user = UserForm { let new_person = PersonForm {
name: "bobbee".into(), name: "bobbee".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -379,11 +365,11 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_user = User_::create(&conn, &new_user).unwrap(); let inserted_person = Person::create(&conn, &new_person).unwrap();
let new_community = CommunityForm { let new_community = CommunityForm {
name: "TIL".into(), name: "TIL".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
nsfw: false, nsfw: false,
@ -407,7 +393,7 @@ mod tests {
let expected_community = Community { let expected_community = Community {
id: inserted_community.id, id: inserted_community.id,
creator_id: inserted_user.id, creator_id: inserted_person.id,
name: "TIL".into(), name: "TIL".into(),
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
@ -430,7 +416,7 @@ mod tests {
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: inserted_community.id, community_id: inserted_community.id,
user_id: inserted_user.id, person_id: inserted_person.id,
pending: false, pending: false,
}; };
@ -440,55 +426,56 @@ mod tests {
let expected_community_follower = CommunityFollower { let expected_community_follower = CommunityFollower {
id: inserted_community_follower.id, id: inserted_community_follower.id,
community_id: inserted_community.id, community_id: inserted_community.id,
user_id: inserted_user.id, person_id: inserted_person.id,
pending: Some(false), pending: Some(false),
published: inserted_community_follower.published, published: inserted_community_follower.published,
}; };
let community_user_form = CommunityModeratorForm { let community_moderator_form = CommunityModeratorForm {
community_id: inserted_community.id, community_id: inserted_community.id,
user_id: inserted_user.id, person_id: inserted_person.id,
}; };
let inserted_community_user = CommunityModerator::join(&conn, &community_user_form).unwrap(); let inserted_community_moderator =
CommunityModerator::join(&conn, &community_moderator_form).unwrap();
let expected_community_user = CommunityModerator { let expected_community_moderator = CommunityModerator {
id: inserted_community_user.id, id: inserted_community_moderator.id,
community_id: inserted_community.id, community_id: inserted_community.id,
user_id: inserted_user.id, person_id: inserted_person.id,
published: inserted_community_user.published, published: inserted_community_moderator.published,
}; };
let community_user_ban_form = CommunityUserBanForm { let community_person_ban_form = CommunityPersonBanForm {
community_id: inserted_community.id, community_id: inserted_community.id,
user_id: inserted_user.id, person_id: inserted_person.id,
}; };
let inserted_community_user_ban = let inserted_community_person_ban =
CommunityUserBan::ban(&conn, &community_user_ban_form).unwrap(); CommunityPersonBan::ban(&conn, &community_person_ban_form).unwrap();
let expected_community_user_ban = CommunityUserBan { let expected_community_person_ban = CommunityPersonBan {
id: inserted_community_user_ban.id, id: inserted_community_person_ban.id,
community_id: inserted_community.id, community_id: inserted_community.id,
user_id: inserted_user.id, person_id: inserted_person.id,
published: inserted_community_user_ban.published, published: inserted_community_person_ban.published,
}; };
let read_community = Community::read(&conn, inserted_community.id).unwrap(); let read_community = Community::read(&conn, inserted_community.id).unwrap();
let updated_community = let updated_community =
Community::update(&conn, inserted_community.id, &new_community).unwrap(); Community::update(&conn, inserted_community.id, &new_community).unwrap();
let ignored_community = CommunityFollower::unfollow(&conn, &community_follower_form).unwrap(); let ignored_community = CommunityFollower::unfollow(&conn, &community_follower_form).unwrap();
let left_community = CommunityModerator::leave(&conn, &community_user_form).unwrap(); let left_community = CommunityModerator::leave(&conn, &community_moderator_form).unwrap();
let unban = CommunityUserBan::unban(&conn, &community_user_ban_form).unwrap(); let unban = CommunityPersonBan::unban(&conn, &community_person_ban_form).unwrap();
let num_deleted = Community::delete(&conn, inserted_community.id).unwrap(); let num_deleted = Community::delete(&conn, inserted_community.id).unwrap();
User_::delete(&conn, inserted_user.id).unwrap(); Person::delete(&conn, inserted_person.id).unwrap();
assert_eq!(expected_community, read_community); assert_eq!(expected_community, read_community);
assert_eq!(expected_community, inserted_community); assert_eq!(expected_community, inserted_community);
assert_eq!(expected_community, updated_community); assert_eq!(expected_community, updated_community);
assert_eq!(expected_community_follower, inserted_community_follower); assert_eq!(expected_community_follower, inserted_community_follower);
assert_eq!(expected_community_user, inserted_community_user); assert_eq!(expected_community_moderator, inserted_community_moderator);
assert_eq!(expected_community_user_ban, inserted_community_user_ban); assert_eq!(expected_community_person_ban, inserted_community_person_ban);
assert_eq!(1, ignored_community); assert_eq!(1, ignored_community);
assert_eq!(1, left_community); assert_eq!(1, left_community);
assert_eq!(1, unban); assert_eq!(1, unban);

View file

@ -0,0 +1,121 @@
use crate::Crud;
use bcrypt::{hash, DEFAULT_COST};
use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
schema::local_user::dsl::*,
source::local_user::{LocalUser, LocalUserForm},
};
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);
impl ToSafe for LocalUser {
type SafeColumns = Columns;
fn safe_columns_tuple() -> Self::SafeColumns {
(id, person_id, admin, matrix_user_id)
}
}
}
mod safe_settings_type {
use crate::ToSafeSettings;
use lemmy_db_schema::{schema::local_user::columns::*, source::local_user::LocalUser};
type Columns = (
id,
person_id,
email,
admin,
show_nsfw,
theme,
default_sort_type,
default_listing_type,
lang,
show_avatars,
send_notifications_to_email,
matrix_user_id,
);
impl ToSafeSettings for LocalUser {
type SafeSettingsColumns = Columns;
/// Includes everything but the hashed password
fn safe_settings_columns_tuple() -> Self::SafeSettingsColumns {
(
id,
person_id,
email,
admin,
show_nsfw,
theme,
default_sort_type,
default_listing_type,
lang,
show_avatars,
send_notifications_to_email,
matrix_user_id,
)
}
}
}
pub trait LocalUser_ {
fn register(conn: &PgConnection, form: &LocalUserForm) -> Result<LocalUser, Error>;
fn update_password(
conn: &PgConnection,
local_user_id: i32,
new_password: &str,
) -> Result<LocalUser, Error>;
fn add_admin(conn: &PgConnection, person_id: i32, added: bool) -> Result<LocalUser, Error>;
}
impl LocalUser_ for LocalUser {
fn register(conn: &PgConnection, form: &LocalUserForm) -> 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)
}
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),))
.get_result::<Self>(conn)
}
fn add_admin(conn: &PgConnection, for_person_id: i32, added: bool) -> Result<Self, Error> {
diesel::update(local_user.filter(person_id.eq(for_person_id)))
.set(admin.eq(added))
.get_result::<Self>(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)
}
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)
}
fn update(conn: &PgConnection, local_user_id: i32, form: &LocalUserForm) -> Result<Self, Error> {
diesel::update(local_user.find(local_user_id))
.set(form)
.get_result::<Self>(conn)
}
}

View file

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

View file

@ -197,8 +197,8 @@ impl Crud<ModAddForm> for ModAdd {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{establish_unpooled_connection, Crud, ListingType, SortType}; use crate::{establish_unpooled_connection, Crud};
use lemmy_db_schema::source::{comment::*, community::*, moderator::*, post::*, user::*}; use lemmy_db_schema::source::{comment::*, community::*, moderator::*, person::*, post::*};
use serial_test::serial; use serial_test::serial;
// use Crud; // use Crud;
@ -207,28 +207,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let new_mod = UserForm { let new_mod = PersonForm {
name: "the mod".into(), name: "the mod".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -236,30 +226,20 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_mod = User_::create(&conn, &new_mod).unwrap(); let inserted_mod = Person::create(&conn, &new_mod).unwrap();
let new_user = UserForm { let new_person = PersonForm {
name: "jim2".into(), name: "jim2".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -267,13 +247,13 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_user = User_::create(&conn, &new_user).unwrap(); let inserted_person = Person::create(&conn, &new_person).unwrap();
let new_community = CommunityForm { let new_community = CommunityForm {
name: "mod_community".to_string(), name: "mod_community".to_string(),
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
removed: None, removed: None,
deleted: None, deleted: None,
updated: None, updated: None,
@ -297,7 +277,7 @@ mod tests {
name: "A test post thweep".into(), name: "A test post thweep".into(),
url: None, url: None,
body: None, body: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
community_id: inserted_community.id, community_id: inserted_community.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -318,7 +298,7 @@ mod tests {
let comment_form = CommentForm { let comment_form = CommentForm {
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -336,7 +316,7 @@ mod tests {
// remove post // remove post
let mod_remove_post_form = ModRemovePostForm { let mod_remove_post_form = ModRemovePostForm {
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
post_id: inserted_post.id, post_id: inserted_post.id,
reason: None, reason: None,
removed: None, removed: None,
@ -346,7 +326,7 @@ mod tests {
let expected_mod_remove_post = ModRemovePost { let expected_mod_remove_post = ModRemovePost {
id: inserted_mod_remove_post.id, id: inserted_mod_remove_post.id,
post_id: inserted_post.id, post_id: inserted_post.id,
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
reason: None, reason: None,
removed: Some(true), removed: Some(true),
when_: inserted_mod_remove_post.when_, when_: inserted_mod_remove_post.when_,
@ -355,7 +335,7 @@ mod tests {
// lock post // lock post
let mod_lock_post_form = ModLockPostForm { let mod_lock_post_form = ModLockPostForm {
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
post_id: inserted_post.id, post_id: inserted_post.id,
locked: None, locked: None,
}; };
@ -364,7 +344,7 @@ mod tests {
let expected_mod_lock_post = ModLockPost { let expected_mod_lock_post = ModLockPost {
id: inserted_mod_lock_post.id, id: inserted_mod_lock_post.id,
post_id: inserted_post.id, post_id: inserted_post.id,
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
locked: Some(true), locked: Some(true),
when_: inserted_mod_lock_post.when_, when_: inserted_mod_lock_post.when_,
}; };
@ -372,7 +352,7 @@ mod tests {
// sticky post // sticky post
let mod_sticky_post_form = ModStickyPostForm { let mod_sticky_post_form = ModStickyPostForm {
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
post_id: inserted_post.id, post_id: inserted_post.id,
stickied: None, stickied: None,
}; };
@ -381,7 +361,7 @@ mod tests {
let expected_mod_sticky_post = ModStickyPost { let expected_mod_sticky_post = ModStickyPost {
id: inserted_mod_sticky_post.id, id: inserted_mod_sticky_post.id,
post_id: inserted_post.id, post_id: inserted_post.id,
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
stickied: Some(true), stickied: Some(true),
when_: inserted_mod_sticky_post.when_, when_: inserted_mod_sticky_post.when_,
}; };
@ -389,7 +369,7 @@ mod tests {
// comment // comment
let mod_remove_comment_form = ModRemoveCommentForm { let mod_remove_comment_form = ModRemoveCommentForm {
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
comment_id: inserted_comment.id, comment_id: inserted_comment.id,
reason: None, reason: None,
removed: None, removed: None,
@ -401,7 +381,7 @@ mod tests {
let expected_mod_remove_comment = ModRemoveComment { let expected_mod_remove_comment = ModRemoveComment {
id: inserted_mod_remove_comment.id, id: inserted_mod_remove_comment.id,
comment_id: inserted_comment.id, comment_id: inserted_comment.id,
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
reason: None, reason: None,
removed: Some(true), removed: Some(true),
when_: inserted_mod_remove_comment.when_, when_: inserted_mod_remove_comment.when_,
@ -410,7 +390,7 @@ mod tests {
// community // community
let mod_remove_community_form = ModRemoveCommunityForm { let mod_remove_community_form = ModRemoveCommunityForm {
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
community_id: inserted_community.id, community_id: inserted_community.id,
reason: None, reason: None,
removed: None, removed: None,
@ -423,7 +403,7 @@ mod tests {
let expected_mod_remove_community = ModRemoveCommunity { let expected_mod_remove_community = ModRemoveCommunity {
id: inserted_mod_remove_community.id, id: inserted_mod_remove_community.id,
community_id: inserted_community.id, community_id: inserted_community.id,
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
reason: None, reason: None,
removed: Some(true), removed: Some(true),
expires: None, expires: None,
@ -433,8 +413,8 @@ mod tests {
// ban from community // ban from community
let mod_ban_from_community_form = ModBanFromCommunityForm { let mod_ban_from_community_form = ModBanFromCommunityForm {
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
other_user_id: inserted_user.id, other_person_id: inserted_person.id,
community_id: inserted_community.id, community_id: inserted_community.id,
reason: None, reason: None,
banned: None, banned: None,
@ -447,8 +427,8 @@ mod tests {
let expected_mod_ban_from_community = ModBanFromCommunity { let expected_mod_ban_from_community = ModBanFromCommunity {
id: inserted_mod_ban_from_community.id, id: inserted_mod_ban_from_community.id,
community_id: inserted_community.id, community_id: inserted_community.id,
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
other_user_id: inserted_user.id, other_person_id: inserted_person.id,
reason: None, reason: None,
banned: Some(true), banned: Some(true),
expires: None, expires: None,
@ -458,8 +438,8 @@ mod tests {
// ban // ban
let mod_ban_form = ModBanForm { let mod_ban_form = ModBanForm {
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
other_user_id: inserted_user.id, other_person_id: inserted_person.id,
reason: None, reason: None,
banned: None, banned: None,
expires: None, expires: None,
@ -468,8 +448,8 @@ mod tests {
let read_mod_ban = ModBan::read(&conn, inserted_mod_ban.id).unwrap(); let read_mod_ban = ModBan::read(&conn, inserted_mod_ban.id).unwrap();
let expected_mod_ban = ModBan { let expected_mod_ban = ModBan {
id: inserted_mod_ban.id, id: inserted_mod_ban.id,
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
other_user_id: inserted_user.id, other_person_id: inserted_person.id,
reason: None, reason: None,
banned: Some(true), banned: Some(true),
expires: None, expires: None,
@ -479,8 +459,8 @@ mod tests {
// mod add community // mod add community
let mod_add_community_form = ModAddCommunityForm { let mod_add_community_form = ModAddCommunityForm {
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
other_user_id: inserted_user.id, other_person_id: inserted_person.id,
community_id: inserted_community.id, community_id: inserted_community.id,
removed: None, removed: None,
}; };
@ -491,8 +471,8 @@ mod tests {
let expected_mod_add_community = ModAddCommunity { let expected_mod_add_community = ModAddCommunity {
id: inserted_mod_add_community.id, id: inserted_mod_add_community.id,
community_id: inserted_community.id, community_id: inserted_community.id,
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
other_user_id: inserted_user.id, other_person_id: inserted_person.id,
removed: Some(false), removed: Some(false),
when_: inserted_mod_add_community.when_, when_: inserted_mod_add_community.when_,
}; };
@ -500,16 +480,16 @@ mod tests {
// mod add // mod add
let mod_add_form = ModAddForm { let mod_add_form = ModAddForm {
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
other_user_id: inserted_user.id, other_person_id: inserted_person.id,
removed: None, removed: None,
}; };
let inserted_mod_add = ModAdd::create(&conn, &mod_add_form).unwrap(); let inserted_mod_add = ModAdd::create(&conn, &mod_add_form).unwrap();
let read_mod_add = ModAdd::read(&conn, inserted_mod_add.id).unwrap(); let read_mod_add = ModAdd::read(&conn, inserted_mod_add.id).unwrap();
let expected_mod_add = ModAdd { let expected_mod_add = ModAdd {
id: inserted_mod_add.id, id: inserted_mod_add.id,
mod_user_id: inserted_mod.id, mod_person_id: inserted_mod.id,
other_user_id: inserted_user.id, other_person_id: inserted_person.id,
removed: Some(false), removed: Some(false),
when_: inserted_mod_add.when_, when_: inserted_mod_add.when_,
}; };
@ -517,8 +497,8 @@ mod tests {
Comment::delete(&conn, inserted_comment.id).unwrap(); Comment::delete(&conn, inserted_comment.id).unwrap();
Post::delete(&conn, inserted_post.id).unwrap(); Post::delete(&conn, inserted_post.id).unwrap();
Community::delete(&conn, inserted_community.id).unwrap(); Community::delete(&conn, inserted_community.id).unwrap();
User_::delete(&conn, inserted_user.id).unwrap(); Person::delete(&conn, inserted_person.id).unwrap();
User_::delete(&conn, inserted_mod.id).unwrap(); Person::delete(&conn, inserted_mod.id).unwrap();
assert_eq!(expected_mod_remove_post, read_mod_remove_post); assert_eq!(expected_mod_remove_post, read_mod_remove_post);
assert_eq!(expected_mod_lock_post, read_mod_lock_post); assert_eq!(expected_mod_lock_post, read_mod_lock_post);

View file

@ -28,7 +28,7 @@ impl Crud<PasswordResetRequestForm> for PasswordResetRequest {
pub trait PasswordResetRequest_ { pub trait PasswordResetRequest_ {
fn create_token( fn create_token(
conn: &PgConnection, conn: &PgConnection,
from_user_id: i32, from_local_user_id: i32,
token: &str, token: &str,
) -> Result<PasswordResetRequest, Error>; ) -> Result<PasswordResetRequest, Error>;
fn read_from_token(conn: &PgConnection, token: &str) -> Result<PasswordResetRequest, Error>; fn read_from_token(conn: &PgConnection, token: &str) -> Result<PasswordResetRequest, Error>;
@ -37,7 +37,7 @@ pub trait PasswordResetRequest_ {
impl PasswordResetRequest_ for PasswordResetRequest { impl PasswordResetRequest_ for PasswordResetRequest {
fn create_token( fn create_token(
conn: &PgConnection, conn: &PgConnection,
from_user_id: i32, from_local_user_id: i32,
token: &str, token: &str,
) -> Result<PasswordResetRequest, Error> { ) -> Result<PasswordResetRequest, Error> {
let mut hasher = Sha256::new(); let mut hasher = Sha256::new();
@ -45,7 +45,7 @@ impl PasswordResetRequest_ for PasswordResetRequest {
let token_hash: String = bytes_to_hex(hasher.finalize().to_vec()); let token_hash: String = bytes_to_hex(hasher.finalize().to_vec());
let form = PasswordResetRequestForm { let form = PasswordResetRequestForm {
user_id: from_user_id, local_user_id: from_local_user_id,
token_encrypted: token_hash, token_encrypted: token_hash,
}; };
@ -76,10 +76,12 @@ mod tests {
establish_unpooled_connection, establish_unpooled_connection,
source::password_reset_request::PasswordResetRequest_, source::password_reset_request::PasswordResetRequest_,
Crud, Crud,
ListingType,
SortType,
}; };
use lemmy_db_schema::source::{password_reset_request::PasswordResetRequest, user::*}; use lemmy_db_schema::source::{
local_user::{LocalUser, LocalUserForm},
password_reset_request::PasswordResetRequest,
person::*,
};
use serial_test::serial; use serial_test::serial;
#[test] #[test]
@ -87,28 +89,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let new_user = UserForm { let new_person = PersonForm {
name: "thommy prw".into(), name: "thommy prw".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -116,23 +108,40 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_user = User_::create(&conn, &new_user).unwrap(); let inserted_person = Person::create(&conn, &new_person).unwrap();
let new_local_user = LocalUserForm {
person_id: inserted_person.id,
password_encrypted: "pass".to_string(),
email: None,
matrix_user_id: None,
admin: None,
show_nsfw: None,
theme: None,
default_sort_type: None,
default_listing_type: None,
lang: None,
show_avatars: None,
send_notifications_to_email: None,
};
let inserted_local_user = LocalUser::create(&conn, &new_local_user).unwrap();
let token = "nope"; let token = "nope";
let token_encrypted_ = "ca3704aa0b06f5954c79ee837faa152d84d6b2d42838f0637a15eda8337dbdce"; let token_encrypted_ = "ca3704aa0b06f5954c79ee837faa152d84d6b2d42838f0637a15eda8337dbdce";
let inserted_password_reset_request = let inserted_password_reset_request =
PasswordResetRequest::create_token(&conn, inserted_user.id, token).unwrap(); PasswordResetRequest::create_token(&conn, inserted_local_user.id, token).unwrap();
let expected_password_reset_request = PasswordResetRequest { let expected_password_reset_request = PasswordResetRequest {
id: inserted_password_reset_request.id, id: inserted_password_reset_request.id,
user_id: inserted_user.id, local_user_id: inserted_local_user.id,
token_encrypted: token_encrypted_.to_string(), token_encrypted: token_encrypted_.to_string(),
published: inserted_password_reset_request.published, published: inserted_password_reset_request.published,
}; };
let read_password_reset_request = PasswordResetRequest::read_from_token(&conn, token).unwrap(); let read_password_reset_request = PasswordResetRequest::read_from_token(&conn, token).unwrap();
let num_deleted = User_::delete(&conn, inserted_user.id).unwrap(); let num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
assert_eq!(expected_password_reset_request, read_password_reset_request); assert_eq!(expected_password_reset_request, read_password_reset_request);
assert_eq!( assert_eq!(

View file

@ -0,0 +1,289 @@
use crate::{ApubObject, Crud};
use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
naive_now,
schema::person::dsl::*,
source::person::{Person, PersonForm},
DbUrl,
};
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,
);
impl ToSafe for Person {
type SafeColumns = Columns;
fn safe_columns_tuple() -> Self::SafeColumns {
(
id,
name,
preferred_username,
avatar,
banned,
published,
updated,
actor_id,
bio,
local,
banner,
deleted,
inbox_url,
shared_inbox_url,
)
}
}
}
mod safe_type_alias_1 {
use crate::ToSafe;
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,
);
impl ToSafe for PersonAlias1 {
type SafeColumns = Columns;
fn safe_columns_tuple() -> Self::SafeColumns {
(
id,
name,
preferred_username,
avatar,
banned,
published,
updated,
actor_id,
bio,
local,
banner,
deleted,
inbox_url,
shared_inbox_url,
)
}
}
}
mod safe_type_alias_2 {
use crate::ToSafe;
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,
);
impl ToSafe for PersonAlias2 {
type SafeColumns = Columns;
fn safe_columns_tuple() -> Self::SafeColumns {
(
id,
name,
preferred_username,
avatar,
banned,
published,
updated,
actor_id,
bio,
local,
banner,
deleted,
inbox_url,
shared_inbox_url,
)
}
}
}
impl Crud<PersonForm> for Person {
fn read(conn: &PgConnection, person_id: i32) -> Result<Self, Error> {
person
.filter(deleted.eq(false))
.find(person_id)
.first::<Self>(conn)
}
fn delete(conn: &PgConnection, person_id: i32) -> Result<usize, Error> {
diesel::delete(person.find(person_id)).execute(conn)
}
fn create(conn: &PgConnection, form: &PersonForm) -> Result<Self, Error> {
insert_into(person).values(form).get_result::<Self>(conn)
}
fn update(conn: &PgConnection, person_id: i32, form: &PersonForm) -> Result<Self, Error> {
diesel::update(person.find(person_id))
.set(form)
.get_result::<Self>(conn)
}
}
impl ApubObject<PersonForm> for Person {
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
use lemmy_db_schema::schema::person::dsl::*;
person
.filter(deleted.eq(false))
.filter(actor_id.eq(object_id))
.first::<Self>(conn)
}
fn upsert(conn: &PgConnection, person_form: &PersonForm) -> Result<Person, Error> {
insert_into(person)
.values(person_form)
.on_conflict(actor_id)
.do_update()
.set(person_form)
.get_result::<Self>(conn)
}
}
pub trait Person_ {
fn ban_person(conn: &PgConnection, person_id: i32, ban: bool) -> 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)
}
fn find_by_name(conn: &PgConnection, from_name: &str) -> Result<Person, Error> {
person
.filter(deleted.eq(false))
.filter(local.eq(true))
.filter(name.ilike(from_name))
.first::<Person>(conn)
}
fn mark_as_updated(conn: &PgConnection, person_id: i32) -> Result<Person, Error> {
diesel::update(person.find(person_id))
.set((last_refreshed_at.eq(naive_now()),))
.get_result::<Self>(conn)
}
fn delete_account(conn: &PgConnection, person_id: i32) -> Result<Person, Error> {
use lemmy_db_schema::schema::local_user;
// Set the local user info to none
diesel::update(local_user::table.filter(local_user::person_id.eq(person_id)))
.set((
local_user::email.eq::<Option<String>>(None),
local_user::matrix_user_id.eq::<Option<String>>(None),
))
.execute(conn)?;
diesel::update(person.find(person_id))
.set((
preferred_username.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::person::*};
#[test]
fn test_crud() {
let conn = establish_unpooled_connection();
let new_person = PersonForm {
name: "holly".into(),
preferred_username: None,
avatar: None,
banner: None,
banned: None,
deleted: None,
published: None,
updated: None,
actor_id: None,
bio: None,
local: None,
private_key: None,
public_key: None,
last_refreshed_at: None,
inbox_url: None,
shared_inbox_url: None,
};
let inserted_person = Person::create(&conn, &new_person).unwrap();
let expected_person = Person {
id: inserted_person.id,
name: "holly".into(),
preferred_username: None,
avatar: None,
banner: None,
banned: false,
deleted: false,
published: inserted_person.published,
updated: None,
actor_id: inserted_person.actor_id.to_owned(),
bio: None,
local: true,
private_key: None,
public_key: None,
last_refreshed_at: inserted_person.published,
inbox_url: inserted_person.inbox_url.to_owned(),
shared_inbox_url: None,
};
let read_person = Person::read(&conn, inserted_person.id).unwrap();
let updated_person = Person::update(&conn, inserted_person.id, &new_person).unwrap();
let num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
assert_eq!(expected_person, read_person);
assert_eq!(expected_person, inserted_person);
assert_eq!(expected_person, updated_person);
assert_eq!(1, num_deleted);
}
}

View file

@ -1,57 +1,57 @@
use crate::Crud; use crate::Crud;
use diesel::{dsl::*, result::Error, *}; use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::source::user_mention::*; use lemmy_db_schema::source::person_mention::*;
impl Crud<UserMentionForm> for UserMention { impl Crud<PersonMentionForm> for PersonMention {
fn read(conn: &PgConnection, user_mention_id: i32) -> Result<Self, Error> { fn read(conn: &PgConnection, person_mention_id: i32) -> Result<Self, Error> {
use lemmy_db_schema::schema::user_mention::dsl::*; use lemmy_db_schema::schema::person_mention::dsl::*;
user_mention.find(user_mention_id).first::<Self>(conn) person_mention.find(person_mention_id).first::<Self>(conn)
} }
fn create(conn: &PgConnection, user_mention_form: &UserMentionForm) -> Result<Self, Error> { fn create(conn: &PgConnection, person_mention_form: &PersonMentionForm) -> Result<Self, Error> {
use lemmy_db_schema::schema::user_mention::dsl::*; use lemmy_db_schema::schema::person_mention::dsl::*;
// since the return here isnt utilized, we dont need to do an update // since the return here isnt utilized, we dont need to do an update
// but get_result doesnt return the existing row here // but get_result doesnt return the existing row here
insert_into(user_mention) insert_into(person_mention)
.values(user_mention_form) .values(person_mention_form)
.on_conflict((recipient_id, comment_id)) .on_conflict((recipient_id, comment_id))
.do_update() .do_update()
.set(user_mention_form) .set(person_mention_form)
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
fn update( fn update(
conn: &PgConnection, conn: &PgConnection,
user_mention_id: i32, person_mention_id: i32,
user_mention_form: &UserMentionForm, person_mention_form: &PersonMentionForm,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
use lemmy_db_schema::schema::user_mention::dsl::*; use lemmy_db_schema::schema::person_mention::dsl::*;
diesel::update(user_mention.find(user_mention_id)) diesel::update(person_mention.find(person_mention_id))
.set(user_mention_form) .set(person_mention_form)
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
} }
pub trait UserMention_ { pub trait PersonMention_ {
fn update_read( fn update_read(
conn: &PgConnection, conn: &PgConnection,
user_mention_id: i32, person_mention_id: i32,
new_read: bool, new_read: bool,
) -> Result<UserMention, Error>; ) -> Result<PersonMention, Error>;
fn mark_all_as_read( fn mark_all_as_read(
conn: &PgConnection, conn: &PgConnection,
for_recipient_id: i32, for_recipient_id: i32,
) -> Result<Vec<UserMention>, Error>; ) -> Result<Vec<PersonMention>, Error>;
} }
impl UserMention_ for UserMention { impl PersonMention_ for PersonMention {
fn update_read( fn update_read(
conn: &PgConnection, conn: &PgConnection,
user_mention_id: i32, person_mention_id: i32,
new_read: bool, new_read: bool,
) -> Result<UserMention, Error> { ) -> Result<PersonMention, Error> {
use lemmy_db_schema::schema::user_mention::dsl::*; use lemmy_db_schema::schema::person_mention::dsl::*;
diesel::update(user_mention.find(user_mention_id)) diesel::update(person_mention.find(person_mention_id))
.set(read.eq(new_read)) .set(read.eq(new_read))
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
@ -59,10 +59,10 @@ impl UserMention_ for UserMention {
fn mark_all_as_read( fn mark_all_as_read(
conn: &PgConnection, conn: &PgConnection,
for_recipient_id: i32, for_recipient_id: i32,
) -> Result<Vec<UserMention>, Error> { ) -> Result<Vec<PersonMention>, Error> {
use lemmy_db_schema::schema::user_mention::dsl::*; use lemmy_db_schema::schema::person_mention::dsl::*;
diesel::update( diesel::update(
user_mention person_mention
.filter(recipient_id.eq(for_recipient_id)) .filter(recipient_id.eq(for_recipient_id))
.filter(read.eq(false)), .filter(read.eq(false)),
) )
@ -73,13 +73,13 @@ impl UserMention_ for UserMention {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{establish_unpooled_connection, Crud, ListingType, SortType}; use crate::{establish_unpooled_connection, Crud};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::*, comment::*,
community::{Community, CommunityForm}, community::{Community, CommunityForm},
person::*,
person_mention::*,
post::*, post::*,
user::*,
user_mention::*,
}; };
use serial_test::serial; use serial_test::serial;
@ -88,28 +88,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let new_user = UserForm { let new_person = PersonForm {
name: "terrylake".into(), name: "terrylake".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -117,30 +107,20 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_user = User_::create(&conn, &new_user).unwrap(); let inserted_person = Person::create(&conn, &new_person).unwrap();
let recipient_form = UserForm { let recipient_form = PersonForm {
name: "terrylakes recipient".into(), name: "terrylakes recipient".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -148,13 +128,13 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_recipient = User_::create(&conn, &recipient_form).unwrap(); let inserted_recipient = Person::create(&conn, &recipient_form).unwrap();
let new_community = CommunityForm { let new_community = CommunityForm {
name: "test community lake".to_string(), name: "test community lake".to_string(),
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
removed: None, removed: None,
deleted: None, deleted: None,
updated: None, updated: None,
@ -176,7 +156,7 @@ mod tests {
let new_post = PostForm { let new_post = PostForm {
name: "A test post".into(), name: "A test post".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
url: None, url: None,
body: None, body: None,
community_id: inserted_community.id, community_id: inserted_community.id,
@ -199,7 +179,7 @@ mod tests {
let comment_form = CommentForm { let comment_form = CommentForm {
content: "A test comment".into(), content: "A test comment".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -213,15 +193,15 @@ mod tests {
let inserted_comment = Comment::create(&conn, &comment_form).unwrap(); let inserted_comment = Comment::create(&conn, &comment_form).unwrap();
let user_mention_form = UserMentionForm { let person_mention_form = PersonMentionForm {
recipient_id: inserted_recipient.id, recipient_id: inserted_recipient.id,
comment_id: inserted_comment.id, comment_id: inserted_comment.id,
read: None, read: None,
}; };
let inserted_mention = UserMention::create(&conn, &user_mention_form).unwrap(); let inserted_mention = PersonMention::create(&conn, &person_mention_form).unwrap();
let expected_mention = UserMention { let expected_mention = PersonMention {
id: inserted_mention.id, id: inserted_mention.id,
recipient_id: inserted_mention.recipient_id, recipient_id: inserted_mention.recipient_id,
comment_id: inserted_mention.comment_id, comment_id: inserted_mention.comment_id,
@ -229,14 +209,14 @@ mod tests {
published: inserted_mention.published, published: inserted_mention.published,
}; };
let read_mention = UserMention::read(&conn, inserted_mention.id).unwrap(); let read_mention = PersonMention::read(&conn, inserted_mention.id).unwrap();
let updated_mention = let updated_mention =
UserMention::update(&conn, inserted_mention.id, &user_mention_form).unwrap(); PersonMention::update(&conn, inserted_mention.id, &person_mention_form).unwrap();
Comment::delete(&conn, inserted_comment.id).unwrap(); Comment::delete(&conn, inserted_comment.id).unwrap();
Post::delete(&conn, inserted_post.id).unwrap(); Post::delete(&conn, inserted_post.id).unwrap();
Community::delete(&conn, inserted_community.id).unwrap(); Community::delete(&conn, inserted_community.id).unwrap();
User_::delete(&conn, inserted_user.id).unwrap(); Person::delete(&conn, inserted_person.id).unwrap();
User_::delete(&conn, inserted_recipient.id).unwrap(); Person::delete(&conn, inserted_recipient.id).unwrap();
assert_eq!(expected_mention, read_mention); assert_eq!(expected_mention, read_mention);
assert_eq!(expected_mention, inserted_mention); assert_eq!(expected_mention, inserted_mention);

View file

@ -54,7 +54,7 @@ pub trait Post_ {
) -> Result<Vec<Post>, Error>; ) -> Result<Vec<Post>, Error>;
fn update_locked(conn: &PgConnection, post_id: i32, new_locked: bool) -> Result<Post, Error>; fn update_locked(conn: &PgConnection, post_id: i32, new_locked: bool) -> Result<Post, Error>;
fn update_stickied(conn: &PgConnection, post_id: i32, new_stickied: bool) -> Result<Post, Error>; fn update_stickied(conn: &PgConnection, post_id: i32, new_stickied: bool) -> Result<Post, Error>;
fn is_post_creator(user_id: i32, post_creator_id: i32) -> bool; fn is_post_creator(person_id: i32, post_creator_id: i32) -> bool;
} }
impl Post_ for Post { impl Post_ for Post {
@ -141,8 +141,8 @@ impl Post_ for Post {
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
fn is_post_creator(user_id: i32, post_creator_id: i32) -> bool { fn is_post_creator(person_id: i32, post_creator_id: i32) -> bool {
user_id == post_creator_id person_id == post_creator_id
} }
} }
@ -168,17 +168,17 @@ impl Likeable<PostLikeForm> for PostLike {
use lemmy_db_schema::schema::post_like::dsl::*; use lemmy_db_schema::schema::post_like::dsl::*;
insert_into(post_like) insert_into(post_like)
.values(post_like_form) .values(post_like_form)
.on_conflict((post_id, user_id)) .on_conflict((post_id, person_id))
.do_update() .do_update()
.set(post_like_form) .set(post_like_form)
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
fn remove(conn: &PgConnection, user_id: i32, post_id: i32) -> Result<usize, Error> { fn remove(conn: &PgConnection, person_id: i32, post_id: i32) -> Result<usize, Error> {
use lemmy_db_schema::schema::post_like::dsl; use lemmy_db_schema::schema::post_like::dsl;
diesel::delete( diesel::delete(
dsl::post_like dsl::post_like
.filter(dsl::post_id.eq(post_id)) .filter(dsl::post_id.eq(post_id))
.filter(dsl::user_id.eq(user_id)), .filter(dsl::person_id.eq(person_id)),
) )
.execute(conn) .execute(conn)
} }
@ -189,7 +189,7 @@ impl Saveable<PostSavedForm> for PostSaved {
use lemmy_db_schema::schema::post_saved::dsl::*; use lemmy_db_schema::schema::post_saved::dsl::*;
insert_into(post_saved) insert_into(post_saved)
.values(post_saved_form) .values(post_saved_form)
.on_conflict((post_id, user_id)) .on_conflict((post_id, person_id))
.do_update() .do_update()
.set(post_saved_form) .set(post_saved_form)
.get_result::<Self>(conn) .get_result::<Self>(conn)
@ -199,7 +199,7 @@ impl Saveable<PostSavedForm> for PostSaved {
diesel::delete( diesel::delete(
post_saved post_saved
.filter(post_id.eq(post_saved_form.post_id)) .filter(post_id.eq(post_saved_form.post_id))
.filter(user_id.eq(post_saved_form.user_id)), .filter(person_id.eq(post_saved_form.person_id)),
) )
.execute(conn) .execute(conn)
} }
@ -218,7 +218,7 @@ impl Readable<PostReadForm> for PostRead {
diesel::delete( diesel::delete(
post_read post_read
.filter(post_id.eq(post_read_form.post_id)) .filter(post_id.eq(post_read_form.post_id))
.filter(user_id.eq(post_read_form.user_id)), .filter(person_id.eq(post_read_form.person_id)),
) )
.execute(conn) .execute(conn)
} }
@ -226,10 +226,10 @@ impl Readable<PostReadForm> for PostRead {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{establish_unpooled_connection, source::post::*, ListingType, SortType}; use crate::{establish_unpooled_connection, source::post::*};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
community::{Community, CommunityForm}, community::{Community, CommunityForm},
user::*, person::*,
}; };
use serial_test::serial; use serial_test::serial;
@ -238,28 +238,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let new_user = UserForm { let new_person = PersonForm {
name: "jim".into(), name: "jim".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -267,13 +257,13 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_user = User_::create(&conn, &new_user).unwrap(); let inserted_person = Person::create(&conn, &new_person).unwrap();
let new_community = CommunityForm { let new_community = CommunityForm {
name: "test community_3".to_string(), name: "test community_3".to_string(),
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
removed: None, removed: None,
deleted: None, deleted: None,
updated: None, updated: None,
@ -297,7 +287,7 @@ mod tests {
name: "A test post".into(), name: "A test post".into(),
url: None, url: None,
body: None, body: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
community_id: inserted_community.id, community_id: inserted_community.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -321,7 +311,7 @@ mod tests {
name: "A test post".into(), name: "A test post".into(),
url: None, url: None,
body: None, body: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
community_id: inserted_community.id, community_id: inserted_community.id,
published: inserted_post.published, published: inserted_post.published,
removed: false, removed: false,
@ -341,7 +331,7 @@ mod tests {
// Post Like // Post Like
let post_like_form = PostLikeForm { let post_like_form = PostLikeForm {
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
score: 1, score: 1,
}; };
@ -350,7 +340,7 @@ mod tests {
let expected_post_like = PostLike { let expected_post_like = PostLike {
id: inserted_post_like.id, id: inserted_post_like.id,
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
published: inserted_post_like.published, published: inserted_post_like.published,
score: 1, score: 1,
}; };
@ -358,7 +348,7 @@ mod tests {
// Post Save // Post Save
let post_saved_form = PostSavedForm { let post_saved_form = PostSavedForm {
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
}; };
let inserted_post_saved = PostSaved::save(&conn, &post_saved_form).unwrap(); let inserted_post_saved = PostSaved::save(&conn, &post_saved_form).unwrap();
@ -366,14 +356,14 @@ mod tests {
let expected_post_saved = PostSaved { let expected_post_saved = PostSaved {
id: inserted_post_saved.id, id: inserted_post_saved.id,
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
published: inserted_post_saved.published, published: inserted_post_saved.published,
}; };
// Post Read // Post Read
let post_read_form = PostReadForm { let post_read_form = PostReadForm {
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
}; };
let inserted_post_read = PostRead::mark_as_read(&conn, &post_read_form).unwrap(); let inserted_post_read = PostRead::mark_as_read(&conn, &post_read_form).unwrap();
@ -381,18 +371,18 @@ mod tests {
let expected_post_read = PostRead { let expected_post_read = PostRead {
id: inserted_post_read.id, id: inserted_post_read.id,
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
published: inserted_post_read.published, published: inserted_post_read.published,
}; };
let read_post = Post::read(&conn, inserted_post.id).unwrap(); let read_post = Post::read(&conn, inserted_post.id).unwrap();
let updated_post = Post::update(&conn, inserted_post.id, &new_post).unwrap(); let updated_post = Post::update(&conn, inserted_post.id, &new_post).unwrap();
let like_removed = PostLike::remove(&conn, inserted_user.id, inserted_post.id).unwrap(); let like_removed = PostLike::remove(&conn, inserted_person.id, inserted_post.id).unwrap();
let saved_removed = PostSaved::unsave(&conn, &post_saved_form).unwrap(); let saved_removed = PostSaved::unsave(&conn, &post_saved_form).unwrap();
let read_removed = PostRead::mark_as_unread(&conn, &post_read_form).unwrap(); let read_removed = PostRead::mark_as_unread(&conn, &post_read_form).unwrap();
let num_deleted = Post::delete(&conn, inserted_post.id).unwrap(); let num_deleted = Post::delete(&conn, inserted_post.id).unwrap();
Community::delete(&conn, inserted_community.id).unwrap(); Community::delete(&conn, inserted_community.id).unwrap();
User_::delete(&conn, inserted_user.id).unwrap(); Person::delete(&conn, inserted_person.id).unwrap();
assert_eq!(expected_post, read_post); assert_eq!(expected_post, read_post);
assert_eq!(expected_post, inserted_post); assert_eq!(expected_post, inserted_post);

View file

@ -139,14 +139,8 @@ impl PrivateMessage_ for PrivateMessage {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{establish_unpooled_connection, source::private_message::PrivateMessage_, Crud};
establish_unpooled_connection, use lemmy_db_schema::source::{person::*, private_message::*};
source::private_message::PrivateMessage_,
Crud,
ListingType,
SortType,
};
use lemmy_db_schema::source::{private_message::*, user::*};
use serial_test::serial; use serial_test::serial;
#[test] #[test]
@ -154,28 +148,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let creator_form = UserForm { let creator_form = PersonForm {
name: "creator_pm".into(), name: "creator_pm".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -183,30 +167,20 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_creator = User_::create(&conn, &creator_form).unwrap(); let inserted_creator = Person::create(&conn, &creator_form).unwrap();
let recipient_form = UserForm { let recipient_form = PersonForm {
name: "recipient_pm".into(), name: "recipient_pm".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -214,7 +188,7 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_recipient = User_::create(&conn, &recipient_form).unwrap(); let inserted_recipient = Person::create(&conn, &recipient_form).unwrap();
let private_message_form = PrivateMessageForm { let private_message_form = PrivateMessageForm {
content: "A test private message".into(), content: "A test private message".into(),
@ -250,8 +224,8 @@ mod tests {
PrivateMessage::update_deleted(&conn, inserted_private_message.id, true).unwrap(); PrivateMessage::update_deleted(&conn, inserted_private_message.id, true).unwrap();
let marked_read_private_message = let marked_read_private_message =
PrivateMessage::update_read(&conn, inserted_private_message.id, true).unwrap(); PrivateMessage::update_read(&conn, inserted_private_message.id, true).unwrap();
User_::delete(&conn, inserted_creator.id).unwrap(); Person::delete(&conn, inserted_creator.id).unwrap();
User_::delete(&conn, inserted_recipient.id).unwrap(); Person::delete(&conn, inserted_recipient.id).unwrap();
assert_eq!(expected_private_message, read_private_message); assert_eq!(expected_private_message, read_private_message);
assert_eq!(expected_private_message, updated_private_message); assert_eq!(expected_private_message, updated_private_message);

View file

@ -1,460 +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 find_by_email(conn: &PgConnection, from_email: &str) -> Result<User_, Error>;
fn get_profile_url(&self, hostname: &str) -> String;
fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
}
impl User for User_ {
fn register(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
let mut edited_user = form.clone();
let password_hash =
hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
edited_user.password_encrypted = password_hash;
Self::create(&conn, &edited_user)
}
// TODO do more individual updates like these
fn update_password(conn: &PgConnection, user_id: i32, new_password: &str) -> Result<Self, Error> {
let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password");
diesel::update(user_.find(user_id))
.set((
password_encrypted.eq(password_hash),
updated.eq(naive_now()),
))
.get_result::<Self>(conn)
}
fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result<Self, Error> {
user_
.filter(local.eq(true))
.filter(deleted.eq(false))
.filter(name.eq(from_user_name))
.first::<Self>(conn)
}
fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result<Self, Error> {
diesel::update(user_.find(user_id))
.set(admin.eq(added))
.get_result::<Self>(conn)
}
fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<Self, Error> {
diesel::update(user_.find(user_id))
.set(banned.eq(ban))
.get_result::<Self>(conn)
}
fn find_by_email_or_username(
conn: &PgConnection,
username_or_email: &str,
) -> Result<Self, Error> {
if is_email_regex(username_or_email) {
Self::find_by_email(conn, username_or_email)
} else {
Self::find_by_username(conn, username_or_email)
}
}
fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error> {
user_
.filter(deleted.eq(false))
.filter(local.eq(true))
.filter(name.ilike(username))
.first::<User_>(conn)
}
fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<User_, Error> {
user_
.filter(deleted.eq(false))
.filter(local.eq(true))
.filter(email.eq(from_email))
.first::<User_>(conn)
}
fn get_profile_url(&self, hostname: &str) -> String {
format!(
"{}://{}/u/{}",
Settings::get().get_protocol_string(),
hostname,
self.name
)
}
fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
diesel::update(user_.find(user_id))
.set((last_refreshed_at.eq(naive_now()),))
.get_result::<Self>(conn)
}
fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
diesel::update(user_.find(user_id))
.set((
preferred_username.eq::<Option<String>>(None),
email.eq::<Option<String>>(None),
matrix_user_id.eq::<Option<String>>(None),
bio.eq::<Option<String>>(None),
deleted.eq(true),
updated.eq(naive_now()),
))
.get_result::<Self>(conn)
}
}
#[cfg(test)]
mod tests {
use crate::{establish_unpooled_connection, source::user::*, ListingType, SortType};
use serial_test::serial;
#[test]
#[serial]
fn test_crud() {
let conn = establish_unpooled_connection();
let new_user = UserForm {
name: "thommy".into(),
preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None,
banner: None,
admin: false,
banned: Some(false),
published: None,
updated: None,
show_nsfw: false,
theme: "browser".into(),
default_sort_type: SortType::Hot as i16,
default_listing_type: ListingType::Subscribed as i16,
lang: "browser".into(),
show_avatars: true,
send_notifications_to_email: false,
actor_id: None,
bio: None,
local: true,
private_key: None,
public_key: None,
last_refreshed_at: None,
inbox_url: None,
shared_inbox_url: None,
};
let inserted_user = User_::create(&conn, &new_user).unwrap();
let expected_user = User_ {
id: inserted_user.id,
name: "thommy".into(),
preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None,
banner: None,
admin: false,
banned: false,
published: inserted_user.published,
updated: None,
show_nsfw: false,
theme: "browser".into(),
default_sort_type: SortType::Hot as i16,
default_listing_type: ListingType::Subscribed as i16,
lang: "browser".into(),
show_avatars: true,
send_notifications_to_email: false,
actor_id: inserted_user.actor_id.to_owned(),
bio: None,
local: true,
private_key: None,
public_key: None,
last_refreshed_at: inserted_user.published,
deleted: false,
inbox_url: inserted_user.inbox_url.to_owned(),
shared_inbox_url: None,
};
let read_user = User_::read(&conn, inserted_user.id).unwrap();
let updated_user = User_::update(&conn, inserted_user.id, &new_user).unwrap();
let num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
assert_eq!(expected_user, read_user);
assert_eq!(expected_user, inserted_user);
assert_eq!(expected_user, updated_user);
assert_eq!(1, num_deleted);
}
}

View file

@ -41,7 +41,7 @@ table! {
table! { table! {
comment_like (id) { comment_like (id) {
id -> Int4, id -> Int4,
user_id -> Int4, person_id -> Int4,
comment_id -> Int4, comment_id -> Int4,
post_id -> Int4, post_id -> Int4,
score -> Int2, score -> Int2,
@ -67,7 +67,7 @@ table! {
comment_saved (id) { comment_saved (id) {
id -> Int4, id -> Int4,
comment_id -> Int4, comment_id -> Int4,
user_id -> Int4, person_id -> Int4,
published -> Timestamp, published -> Timestamp,
} }
} }
@ -89,11 +89,11 @@ table! {
private_key -> Nullable<Text>, private_key -> Nullable<Text>,
public_key -> Nullable<Text>, public_key -> Nullable<Text>,
last_refreshed_at -> Timestamp, last_refreshed_at -> Timestamp,
icon -> Nullable<Text>, icon -> Nullable<Varchar>,
banner -> Nullable<Text>, banner -> Nullable<Varchar>,
followers_url -> Text, followers_url -> Varchar,
inbox_url -> Text, inbox_url -> Varchar,
shared_inbox_url -> Nullable<Text>, shared_inbox_url -> Nullable<Varchar>,
} }
} }
@ -116,7 +116,7 @@ table! {
community_follower (id) { community_follower (id) {
id -> Int4, id -> Int4,
community_id -> Int4, community_id -> Int4,
user_id -> Int4, person_id -> Int4,
published -> Timestamp, published -> Timestamp,
pending -> Nullable<Bool>, pending -> Nullable<Bool>,
} }
@ -126,25 +126,43 @@ table! {
community_moderator (id) { community_moderator (id) {
id -> Int4, id -> Int4,
community_id -> Int4, community_id -> Int4,
user_id -> Int4, person_id -> Int4,
published -> Timestamp, published -> Timestamp,
} }
} }
table! { table! {
community_user_ban (id) { community_person_ban (id) {
id -> Int4, id -> Int4,
community_id -> Int4, community_id -> Int4,
user_id -> Int4, person_id -> Int4,
published -> Timestamp, published -> Timestamp,
} }
} }
table! {
local_user (id) {
id -> Int4,
person_id -> Int4,
password_encrypted -> Text,
email -> Nullable<Text>,
admin -> Bool,
show_nsfw -> Bool,
theme -> Varchar,
default_sort_type -> Int2,
default_listing_type -> Int2,
lang -> Varchar,
show_avatars -> Bool,
send_notifications_to_email -> Bool,
matrix_user_id -> Nullable<Text>,
}
}
table! { table! {
mod_add (id) { mod_add (id) {
id -> Int4, id -> Int4,
mod_user_id -> Int4, mod_person_id -> Int4,
other_user_id -> Int4, other_person_id -> Int4,
removed -> Nullable<Bool>, removed -> Nullable<Bool>,
when_ -> Timestamp, when_ -> Timestamp,
} }
@ -153,8 +171,8 @@ table! {
table! { table! {
mod_add_community (id) { mod_add_community (id) {
id -> Int4, id -> Int4,
mod_user_id -> Int4, mod_person_id -> Int4,
other_user_id -> Int4, other_person_id -> Int4,
community_id -> Int4, community_id -> Int4,
removed -> Nullable<Bool>, removed -> Nullable<Bool>,
when_ -> Timestamp, when_ -> Timestamp,
@ -164,8 +182,8 @@ table! {
table! { table! {
mod_ban (id) { mod_ban (id) {
id -> Int4, id -> Int4,
mod_user_id -> Int4, mod_person_id -> Int4,
other_user_id -> Int4, other_person_id -> Int4,
reason -> Nullable<Text>, reason -> Nullable<Text>,
banned -> Nullable<Bool>, banned -> Nullable<Bool>,
expires -> Nullable<Timestamp>, expires -> Nullable<Timestamp>,
@ -176,8 +194,8 @@ table! {
table! { table! {
mod_ban_from_community (id) { mod_ban_from_community (id) {
id -> Int4, id -> Int4,
mod_user_id -> Int4, mod_person_id -> Int4,
other_user_id -> Int4, other_person_id -> Int4,
community_id -> Int4, community_id -> Int4,
reason -> Nullable<Text>, reason -> Nullable<Text>,
banned -> Nullable<Bool>, banned -> Nullable<Bool>,
@ -189,7 +207,7 @@ table! {
table! { table! {
mod_lock_post (id) { mod_lock_post (id) {
id -> Int4, id -> Int4,
mod_user_id -> Int4, mod_person_id -> Int4,
post_id -> Int4, post_id -> Int4,
locked -> Nullable<Bool>, locked -> Nullable<Bool>,
when_ -> Timestamp, when_ -> Timestamp,
@ -199,7 +217,7 @@ table! {
table! { table! {
mod_remove_comment (id) { mod_remove_comment (id) {
id -> Int4, id -> Int4,
mod_user_id -> Int4, mod_person_id -> Int4,
comment_id -> Int4, comment_id -> Int4,
reason -> Nullable<Text>, reason -> Nullable<Text>,
removed -> Nullable<Bool>, removed -> Nullable<Bool>,
@ -210,7 +228,7 @@ table! {
table! { table! {
mod_remove_community (id) { mod_remove_community (id) {
id -> Int4, id -> Int4,
mod_user_id -> Int4, mod_person_id -> Int4,
community_id -> Int4, community_id -> Int4,
reason -> Nullable<Text>, reason -> Nullable<Text>,
removed -> Nullable<Bool>, removed -> Nullable<Bool>,
@ -222,7 +240,7 @@ table! {
table! { table! {
mod_remove_post (id) { mod_remove_post (id) {
id -> Int4, id -> Int4,
mod_user_id -> Int4, mod_person_id -> Int4,
post_id -> Int4, post_id -> Int4,
reason -> Nullable<Text>, reason -> Nullable<Text>,
removed -> Nullable<Bool>, removed -> Nullable<Bool>,
@ -233,7 +251,7 @@ table! {
table! { table! {
mod_sticky_post (id) { mod_sticky_post (id) {
id -> Int4, id -> Int4,
mod_user_id -> Int4, mod_person_id -> Int4,
post_id -> Int4, post_id -> Int4,
stickied -> Nullable<Bool>, stickied -> Nullable<Bool>,
when_ -> Timestamp, when_ -> Timestamp,
@ -243,9 +261,60 @@ table! {
table! { table! {
password_reset_request (id) { password_reset_request (id) {
id -> Int4, id -> Int4,
user_id -> Int4,
token_encrypted -> Text, token_encrypted -> Text,
published -> Timestamp, published -> Timestamp,
local_user_id -> Int4,
}
}
table! {
person (id) {
id -> Int4,
name -> Varchar,
preferred_username -> Nullable<Varchar>,
avatar -> Nullable<Varchar>,
banned -> Bool,
published -> Timestamp,
updated -> Nullable<Timestamp>,
actor_id -> Varchar,
bio -> Nullable<Text>,
local -> Bool,
private_key -> Nullable<Text>,
public_key -> Nullable<Text>,
last_refreshed_at -> Timestamp,
banner -> Nullable<Varchar>,
deleted -> Bool,
inbox_url -> Varchar,
shared_inbox_url -> Nullable<Varchar>,
}
}
table! {
person_aggregates (id) {
id -> Int4,
person_id -> Int4,
post_count -> Int8,
post_score -> Int8,
comment_count -> Int8,
comment_score -> Int8,
}
}
table! {
person_ban (id) {
id -> Int4,
person_id -> Int4,
published -> Timestamp,
}
}
table! {
person_mention (id) {
id -> Int4,
recipient_id -> Int4,
comment_id -> Int4,
read -> Bool,
published -> Timestamp,
} }
} }
@ -253,7 +322,7 @@ table! {
post (id) { post (id) {
id -> Int4, id -> Int4,
name -> Varchar, name -> Varchar,
url -> Nullable<Text>, url -> Nullable<Varchar>,
body -> Nullable<Text>, body -> Nullable<Text>,
creator_id -> Int4, creator_id -> Int4,
community_id -> Int4, community_id -> Int4,
@ -292,7 +361,7 @@ table! {
post_like (id) { post_like (id) {
id -> Int4, id -> Int4,
post_id -> Int4, post_id -> Int4,
user_id -> Int4, person_id -> Int4,
score -> Int2, score -> Int2,
published -> Timestamp, published -> Timestamp,
} }
@ -302,7 +371,7 @@ table! {
post_read (id) { post_read (id) {
id -> Int4, id -> Int4,
post_id -> Int4, post_id -> Int4,
user_id -> Int4, person_id -> Int4,
published -> Timestamp, published -> Timestamp,
} }
} }
@ -327,7 +396,7 @@ table! {
post_saved (id) { post_saved (id) {
id -> Int4, id -> Int4,
post_id -> Int4, post_id -> Int4,
user_id -> Int4, person_id -> Int4,
published -> Timestamp, published -> Timestamp,
} }
} }
@ -358,8 +427,8 @@ table! {
enable_downvotes -> Bool, enable_downvotes -> Bool,
open_registration -> Bool, open_registration -> Bool,
enable_nsfw -> Bool, enable_nsfw -> Bool,
icon -> Nullable<Text>, icon -> Nullable<Varchar>,
banner -> Nullable<Text>, banner -> Nullable<Varchar>,
} }
} }
@ -378,68 +447,6 @@ table! {
} }
} }
table! {
user_ (id) {
id -> Int4,
name -> Varchar,
preferred_username -> Nullable<Varchar>,
password_encrypted -> Text,
email -> Nullable<Text>,
avatar -> Nullable<Text>,
admin -> Bool,
banned -> Bool,
published -> Timestamp,
updated -> Nullable<Timestamp>,
show_nsfw -> Bool,
theme -> Varchar,
default_sort_type -> Int2,
default_listing_type -> Int2,
lang -> Varchar,
show_avatars -> Bool,
send_notifications_to_email -> Bool,
matrix_user_id -> Nullable<Text>,
actor_id -> Varchar,
bio -> Nullable<Text>,
local -> Bool,
private_key -> Nullable<Text>,
public_key -> Nullable<Text>,
last_refreshed_at -> Timestamp,
banner -> Nullable<Text>,
deleted -> Bool,
inbox_url -> Text,
shared_inbox_url -> Nullable<Text>,
}
}
table! {
user_aggregates (id) {
id -> Int4,
user_id -> Int4,
post_count -> Int8,
post_score -> Int8,
comment_count -> Int8,
comment_score -> Int8,
}
}
table! {
user_ban (id) {
id -> Int4,
user_id -> Int4,
published -> Timestamp,
}
}
table! {
user_mention (id) {
id -> Int4,
recipient_id -> Int4,
comment_id -> Int4,
read -> Bool,
published -> Timestamp,
}
}
// These are necessary since diesel doesn't have self joins / aliases // These are necessary since diesel doesn't have self joins / aliases
table! { table! {
comment_alias_1 (id) { comment_alias_1 (id) {
@ -459,122 +466,105 @@ table! {
} }
table! { table! {
user_alias_1 (id) { person_alias_1 (id) {
id -> Int4, id -> Int4,
name -> Varchar, name -> Varchar,
preferred_username -> Nullable<Varchar>, preferred_username -> Nullable<Varchar>,
password_encrypted -> Text, avatar -> Nullable<Varchar>,
email -> Nullable<Text>,
avatar -> Nullable<Text>,
admin -> Bool,
banned -> Bool, banned -> Bool,
published -> Timestamp, published -> Timestamp,
updated -> Nullable<Timestamp>, updated -> Nullable<Timestamp>,
show_nsfw -> Bool,
theme -> Varchar,
default_sort_type -> Int2,
default_listing_type -> Int2,
lang -> Varchar,
show_avatars -> Bool,
send_notifications_to_email -> Bool,
matrix_user_id -> Nullable<Text>,
actor_id -> Varchar, actor_id -> Varchar,
bio -> Nullable<Text>, bio -> Nullable<Text>,
local -> Bool, local -> Bool,
private_key -> Nullable<Text>, private_key -> Nullable<Text>,
public_key -> Nullable<Text>, public_key -> Nullable<Text>,
last_refreshed_at -> Timestamp, last_refreshed_at -> Timestamp,
banner -> Nullable<Text>, banner -> Nullable<Varchar>,
deleted -> Bool, deleted -> Bool,
inbox_url -> Varchar,
shared_inbox_url -> Nullable<Varchar>,
} }
} }
table! { table! {
user_alias_2 (id) { person_alias_2 (id) {
id -> Int4, id -> Int4,
name -> Varchar, name -> Varchar,
preferred_username -> Nullable<Varchar>, preferred_username -> Nullable<Varchar>,
password_encrypted -> Text, avatar -> Nullable<Varchar>,
email -> Nullable<Text>,
avatar -> Nullable<Text>,
admin -> Bool,
banned -> Bool, banned -> Bool,
published -> Timestamp, published -> Timestamp,
updated -> Nullable<Timestamp>, updated -> Nullable<Timestamp>,
show_nsfw -> Bool,
theme -> Varchar,
default_sort_type -> Int2,
default_listing_type -> Int2,
lang -> Varchar,
show_avatars -> Bool,
send_notifications_to_email -> Bool,
matrix_user_id -> Nullable<Text>,
actor_id -> Varchar, actor_id -> Varchar,
bio -> Nullable<Text>, bio -> Nullable<Text>,
local -> Bool, local -> Bool,
private_key -> Nullable<Text>, private_key -> Nullable<Text>,
public_key -> Nullable<Text>, public_key -> Nullable<Text>,
last_refreshed_at -> Timestamp, last_refreshed_at -> Timestamp,
banner -> Nullable<Text>, banner -> Nullable<Varchar>,
deleted -> Bool, deleted -> Bool,
inbox_url -> Varchar,
shared_inbox_url -> Nullable<Varchar>,
} }
} }
joinable!(comment_alias_1 -> user_alias_1 (creator_id)); joinable!(comment_alias_1 -> person_alias_1 (creator_id));
joinable!(comment -> comment_alias_1 (parent_id)); joinable!(comment -> comment_alias_1 (parent_id));
joinable!(user_mention -> user_alias_1 (recipient_id)); joinable!(person_mention -> person_alias_1 (recipient_id));
joinable!(post -> user_alias_1 (creator_id)); joinable!(post -> person_alias_1 (creator_id));
joinable!(comment -> user_alias_1 (creator_id)); joinable!(comment -> person_alias_1 (creator_id));
joinable!(post_report -> user_alias_2 (resolver_id)); joinable!(post_report -> person_alias_2 (resolver_id));
joinable!(comment_report -> user_alias_2 (resolver_id)); joinable!(comment_report -> person_alias_2 (resolver_id));
joinable!(comment -> person (creator_id));
joinable!(comment -> post (post_id)); joinable!(comment -> post (post_id));
joinable!(comment -> user_ (creator_id));
joinable!(comment_aggregates -> comment (comment_id)); joinable!(comment_aggregates -> comment (comment_id));
joinable!(comment_like -> comment (comment_id)); joinable!(comment_like -> comment (comment_id));
joinable!(comment_like -> person (person_id));
joinable!(comment_like -> post (post_id)); joinable!(comment_like -> post (post_id));
joinable!(comment_like -> user_ (user_id));
joinable!(comment_report -> comment (comment_id)); joinable!(comment_report -> comment (comment_id));
joinable!(comment_saved -> comment (comment_id)); joinable!(comment_saved -> comment (comment_id));
joinable!(comment_saved -> user_ (user_id)); joinable!(comment_saved -> person (person_id));
joinable!(community -> user_ (creator_id)); joinable!(community -> person (creator_id));
joinable!(community_aggregates -> community (community_id)); joinable!(community_aggregates -> community (community_id));
joinable!(community_follower -> community (community_id)); joinable!(community_follower -> community (community_id));
joinable!(community_follower -> user_ (user_id)); joinable!(community_follower -> person (person_id));
joinable!(community_moderator -> community (community_id)); joinable!(community_moderator -> community (community_id));
joinable!(community_moderator -> user_ (user_id)); joinable!(community_moderator -> person (person_id));
joinable!(community_user_ban -> community (community_id)); joinable!(community_person_ban -> community (community_id));
joinable!(community_user_ban -> user_ (user_id)); joinable!(community_person_ban -> person (person_id));
joinable!(local_user -> person (person_id));
joinable!(mod_add_community -> community (community_id)); joinable!(mod_add_community -> community (community_id));
joinable!(mod_ban_from_community -> community (community_id)); joinable!(mod_ban_from_community -> community (community_id));
joinable!(mod_lock_post -> person (mod_person_id));
joinable!(mod_lock_post -> post (post_id)); joinable!(mod_lock_post -> post (post_id));
joinable!(mod_lock_post -> user_ (mod_user_id));
joinable!(mod_remove_comment -> comment (comment_id)); joinable!(mod_remove_comment -> comment (comment_id));
joinable!(mod_remove_comment -> user_ (mod_user_id)); joinable!(mod_remove_comment -> person (mod_person_id));
joinable!(mod_remove_community -> community (community_id)); joinable!(mod_remove_community -> community (community_id));
joinable!(mod_remove_community -> user_ (mod_user_id)); joinable!(mod_remove_community -> person (mod_person_id));
joinable!(mod_remove_post -> person (mod_person_id));
joinable!(mod_remove_post -> post (post_id)); joinable!(mod_remove_post -> post (post_id));
joinable!(mod_remove_post -> user_ (mod_user_id)); joinable!(mod_sticky_post -> person (mod_person_id));
joinable!(mod_sticky_post -> post (post_id)); joinable!(mod_sticky_post -> post (post_id));
joinable!(mod_sticky_post -> user_ (mod_user_id)); joinable!(password_reset_request -> local_user (local_user_id));
joinable!(password_reset_request -> user_ (user_id)); joinable!(person_aggregates -> person (person_id));
joinable!(person_ban -> person (person_id));
joinable!(person_mention -> comment (comment_id));
joinable!(person_mention -> person (recipient_id));
joinable!(post -> community (community_id)); joinable!(post -> community (community_id));
joinable!(post -> user_ (creator_id)); joinable!(post -> person (creator_id));
joinable!(post_aggregates -> post (post_id)); joinable!(post_aggregates -> post (post_id));
joinable!(post_like -> person (person_id));
joinable!(post_like -> post (post_id)); joinable!(post_like -> post (post_id));
joinable!(post_like -> user_ (user_id)); joinable!(post_read -> person (person_id));
joinable!(post_read -> post (post_id)); joinable!(post_read -> post (post_id));
joinable!(post_read -> user_ (user_id));
joinable!(post_report -> post (post_id)); joinable!(post_report -> post (post_id));
joinable!(post_saved -> person (person_id));
joinable!(post_saved -> post (post_id)); joinable!(post_saved -> post (post_id));
joinable!(post_saved -> user_ (user_id)); joinable!(site -> person (creator_id));
joinable!(site -> user_ (creator_id));
joinable!(site_aggregates -> site (site_id)); joinable!(site_aggregates -> site (site_id));
joinable!(user_aggregates -> user_ (user_id));
joinable!(user_ban -> user_ (user_id));
joinable!(user_mention -> comment (comment_id));
joinable!(user_mention -> user_ (recipient_id));
allow_tables_to_appear_in_same_query!( allow_tables_to_appear_in_same_query!(
activity, activity,
@ -587,7 +577,8 @@ allow_tables_to_appear_in_same_query!(
community_aggregates, community_aggregates,
community_follower, community_follower,
community_moderator, community_moderator,
community_user_ban, community_person_ban,
local_user,
mod_add, mod_add,
mod_add_community, mod_add_community,
mod_ban, mod_ban,
@ -598,6 +589,10 @@ allow_tables_to_appear_in_same_query!(
mod_remove_post, mod_remove_post,
mod_sticky_post, mod_sticky_post,
password_reset_request, password_reset_request,
person,
person_aggregates,
person_ban,
person_mention,
post, post,
post_aggregates, post_aggregates,
post_like, post_like,
@ -607,11 +602,7 @@ allow_tables_to_appear_in_same_query!(
private_message, private_message,
site, site,
site_aggregates, site_aggregates,
user_,
user_aggregates,
user_ban,
user_mention,
comment_alias_1, comment_alias_1,
user_alias_1, person_alias_1,
user_alias_2, person_alias_2,
); );

View file

@ -69,7 +69,7 @@ pub struct CommentForm {
#[table_name = "comment_like"] #[table_name = "comment_like"]
pub struct CommentLike { pub struct CommentLike {
pub id: i32, pub id: i32,
pub user_id: i32, pub person_id: i32,
pub comment_id: i32, pub comment_id: i32,
pub post_id: i32, // TODO this is redundant pub post_id: i32, // TODO this is redundant
pub score: i16, pub score: i16,
@ -79,7 +79,7 @@ pub struct CommentLike {
#[derive(Insertable, AsChangeset, Clone)] #[derive(Insertable, AsChangeset, Clone)]
#[table_name = "comment_like"] #[table_name = "comment_like"]
pub struct CommentLikeForm { pub struct CommentLikeForm {
pub user_id: i32, pub person_id: i32,
pub comment_id: i32, pub comment_id: i32,
pub post_id: i32, // TODO this is redundant pub post_id: i32, // TODO this is redundant
pub score: i16, pub score: i16,
@ -91,7 +91,7 @@ pub struct CommentLikeForm {
pub struct CommentSaved { pub struct CommentSaved {
pub id: i32, pub id: i32,
pub comment_id: i32, pub comment_id: i32,
pub user_id: i32, pub person_id: i32,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
} }
@ -99,5 +99,5 @@ pub struct CommentSaved {
#[table_name = "comment_saved"] #[table_name = "comment_saved"]
pub struct CommentSavedForm { pub struct CommentSavedForm {
pub comment_id: i32, pub comment_id: i32,
pub user_id: i32, pub person_id: i32,
} }

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
schema::{community, community_follower, community_moderator, community_user_ban}, schema::{community, community_follower, community_moderator, community_person_ban},
DbUrl, DbUrl,
}; };
use serde::Serialize; use serde::Serialize;
@ -79,7 +79,7 @@ pub struct CommunityForm {
pub struct CommunityModerator { pub struct CommunityModerator {
pub id: i32, pub id: i32,
pub community_id: i32, pub community_id: i32,
pub user_id: i32, pub person_id: i32,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
} }
@ -87,24 +87,24 @@ pub struct CommunityModerator {
#[table_name = "community_moderator"] #[table_name = "community_moderator"]
pub struct CommunityModeratorForm { pub struct CommunityModeratorForm {
pub community_id: i32, pub community_id: i32,
pub user_id: i32, pub person_id: i32,
} }
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)] #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
#[belongs_to(Community)] #[belongs_to(Community)]
#[table_name = "community_user_ban"] #[table_name = "community_person_ban"]
pub struct CommunityUserBan { pub struct CommunityPersonBan {
pub id: i32, pub id: i32,
pub community_id: i32, pub community_id: i32,
pub user_id: i32, pub person_id: i32,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
} }
#[derive(Insertable, AsChangeset, Clone)] #[derive(Insertable, AsChangeset, Clone)]
#[table_name = "community_user_ban"] #[table_name = "community_person_ban"]
pub struct CommunityUserBanForm { pub struct CommunityPersonBanForm {
pub community_id: i32, pub community_id: i32,
pub user_id: i32, pub person_id: i32,
} }
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)] #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
@ -113,7 +113,7 @@ pub struct CommunityUserBanForm {
pub struct CommunityFollower { pub struct CommunityFollower {
pub id: i32, pub id: i32,
pub community_id: i32, pub community_id: i32,
pub user_id: i32, pub person_id: i32,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
pub pending: Option<bool>, pub pending: Option<bool>,
} }
@ -122,6 +122,6 @@ pub struct CommunityFollower {
#[table_name = "community_follower"] #[table_name = "community_follower"]
pub struct CommunityFollowerForm { pub struct CommunityFollowerForm {
pub community_id: i32, pub community_id: i32,
pub user_id: i32, pub person_id: i32,
pub pending: bool, pub pending: bool,
} }

View file

@ -0,0 +1,56 @@
use crate::schema::local_user;
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>,
}
// 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 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 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>,
}

View file

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

View file

@ -15,7 +15,7 @@ use serde::Serialize;
#[table_name = "mod_remove_post"] #[table_name = "mod_remove_post"]
pub struct ModRemovePost { pub struct ModRemovePost {
pub id: i32, pub id: i32,
pub mod_user_id: i32, pub mod_person_id: i32,
pub post_id: i32, pub post_id: i32,
pub reason: Option<String>, pub reason: Option<String>,
pub removed: Option<bool>, pub removed: Option<bool>,
@ -25,7 +25,7 @@ pub struct ModRemovePost {
#[derive(Insertable, AsChangeset)] #[derive(Insertable, AsChangeset)]
#[table_name = "mod_remove_post"] #[table_name = "mod_remove_post"]
pub struct ModRemovePostForm { pub struct ModRemovePostForm {
pub mod_user_id: i32, pub mod_person_id: i32,
pub post_id: i32, pub post_id: i32,
pub reason: Option<String>, pub reason: Option<String>,
pub removed: Option<bool>, pub removed: Option<bool>,
@ -35,7 +35,7 @@ pub struct ModRemovePostForm {
#[table_name = "mod_lock_post"] #[table_name = "mod_lock_post"]
pub struct ModLockPost { pub struct ModLockPost {
pub id: i32, pub id: i32,
pub mod_user_id: i32, pub mod_person_id: i32,
pub post_id: i32, pub post_id: i32,
pub locked: Option<bool>, pub locked: Option<bool>,
pub when_: chrono::NaiveDateTime, pub when_: chrono::NaiveDateTime,
@ -44,7 +44,7 @@ pub struct ModLockPost {
#[derive(Insertable, AsChangeset)] #[derive(Insertable, AsChangeset)]
#[table_name = "mod_lock_post"] #[table_name = "mod_lock_post"]
pub struct ModLockPostForm { pub struct ModLockPostForm {
pub mod_user_id: i32, pub mod_person_id: i32,
pub post_id: i32, pub post_id: i32,
pub locked: Option<bool>, pub locked: Option<bool>,
} }
@ -53,7 +53,7 @@ pub struct ModLockPostForm {
#[table_name = "mod_sticky_post"] #[table_name = "mod_sticky_post"]
pub struct ModStickyPost { pub struct ModStickyPost {
pub id: i32, pub id: i32,
pub mod_user_id: i32, pub mod_person_id: i32,
pub post_id: i32, pub post_id: i32,
pub stickied: Option<bool>, pub stickied: Option<bool>,
pub when_: chrono::NaiveDateTime, pub when_: chrono::NaiveDateTime,
@ -62,7 +62,7 @@ pub struct ModStickyPost {
#[derive(Insertable, AsChangeset)] #[derive(Insertable, AsChangeset)]
#[table_name = "mod_sticky_post"] #[table_name = "mod_sticky_post"]
pub struct ModStickyPostForm { pub struct ModStickyPostForm {
pub mod_user_id: i32, pub mod_person_id: i32,
pub post_id: i32, pub post_id: i32,
pub stickied: Option<bool>, pub stickied: Option<bool>,
} }
@ -71,7 +71,7 @@ pub struct ModStickyPostForm {
#[table_name = "mod_remove_comment"] #[table_name = "mod_remove_comment"]
pub struct ModRemoveComment { pub struct ModRemoveComment {
pub id: i32, pub id: i32,
pub mod_user_id: i32, pub mod_person_id: i32,
pub comment_id: i32, pub comment_id: i32,
pub reason: Option<String>, pub reason: Option<String>,
pub removed: Option<bool>, pub removed: Option<bool>,
@ -81,7 +81,7 @@ pub struct ModRemoveComment {
#[derive(Insertable, AsChangeset)] #[derive(Insertable, AsChangeset)]
#[table_name = "mod_remove_comment"] #[table_name = "mod_remove_comment"]
pub struct ModRemoveCommentForm { pub struct ModRemoveCommentForm {
pub mod_user_id: i32, pub mod_person_id: i32,
pub comment_id: i32, pub comment_id: i32,
pub reason: Option<String>, pub reason: Option<String>,
pub removed: Option<bool>, pub removed: Option<bool>,
@ -91,7 +91,7 @@ pub struct ModRemoveCommentForm {
#[table_name = "mod_remove_community"] #[table_name = "mod_remove_community"]
pub struct ModRemoveCommunity { pub struct ModRemoveCommunity {
pub id: i32, pub id: i32,
pub mod_user_id: i32, pub mod_person_id: i32,
pub community_id: i32, pub community_id: i32,
pub reason: Option<String>, pub reason: Option<String>,
pub removed: Option<bool>, pub removed: Option<bool>,
@ -102,7 +102,7 @@ pub struct ModRemoveCommunity {
#[derive(Insertable, AsChangeset)] #[derive(Insertable, AsChangeset)]
#[table_name = "mod_remove_community"] #[table_name = "mod_remove_community"]
pub struct ModRemoveCommunityForm { pub struct ModRemoveCommunityForm {
pub mod_user_id: i32, pub mod_person_id: i32,
pub community_id: i32, pub community_id: i32,
pub reason: Option<String>, pub reason: Option<String>,
pub removed: Option<bool>, pub removed: Option<bool>,
@ -113,8 +113,8 @@ pub struct ModRemoveCommunityForm {
#[table_name = "mod_ban_from_community"] #[table_name = "mod_ban_from_community"]
pub struct ModBanFromCommunity { pub struct ModBanFromCommunity {
pub id: i32, pub id: i32,
pub mod_user_id: i32, pub mod_person_id: i32,
pub other_user_id: i32, pub other_person_id: i32,
pub community_id: i32, pub community_id: i32,
pub reason: Option<String>, pub reason: Option<String>,
pub banned: Option<bool>, pub banned: Option<bool>,
@ -125,8 +125,8 @@ pub struct ModBanFromCommunity {
#[derive(Insertable, AsChangeset)] #[derive(Insertable, AsChangeset)]
#[table_name = "mod_ban_from_community"] #[table_name = "mod_ban_from_community"]
pub struct ModBanFromCommunityForm { pub struct ModBanFromCommunityForm {
pub mod_user_id: i32, pub mod_person_id: i32,
pub other_user_id: i32, pub other_person_id: i32,
pub community_id: i32, pub community_id: i32,
pub reason: Option<String>, pub reason: Option<String>,
pub banned: Option<bool>, pub banned: Option<bool>,
@ -137,8 +137,8 @@ pub struct ModBanFromCommunityForm {
#[table_name = "mod_ban"] #[table_name = "mod_ban"]
pub struct ModBan { pub struct ModBan {
pub id: i32, pub id: i32,
pub mod_user_id: i32, pub mod_person_id: i32,
pub other_user_id: i32, pub other_person_id: i32,
pub reason: Option<String>, pub reason: Option<String>,
pub banned: Option<bool>, pub banned: Option<bool>,
pub expires: Option<chrono::NaiveDateTime>, pub expires: Option<chrono::NaiveDateTime>,
@ -148,8 +148,8 @@ pub struct ModBan {
#[derive(Insertable, AsChangeset)] #[derive(Insertable, AsChangeset)]
#[table_name = "mod_ban"] #[table_name = "mod_ban"]
pub struct ModBanForm { pub struct ModBanForm {
pub mod_user_id: i32, pub mod_person_id: i32,
pub other_user_id: i32, pub other_person_id: i32,
pub reason: Option<String>, pub reason: Option<String>,
pub banned: Option<bool>, pub banned: Option<bool>,
pub expires: Option<chrono::NaiveDateTime>, pub expires: Option<chrono::NaiveDateTime>,
@ -159,8 +159,8 @@ pub struct ModBanForm {
#[table_name = "mod_add_community"] #[table_name = "mod_add_community"]
pub struct ModAddCommunity { pub struct ModAddCommunity {
pub id: i32, pub id: i32,
pub mod_user_id: i32, pub mod_person_id: i32,
pub other_user_id: i32, pub other_person_id: i32,
pub community_id: i32, pub community_id: i32,
pub removed: Option<bool>, pub removed: Option<bool>,
pub when_: chrono::NaiveDateTime, pub when_: chrono::NaiveDateTime,
@ -169,8 +169,8 @@ pub struct ModAddCommunity {
#[derive(Insertable, AsChangeset)] #[derive(Insertable, AsChangeset)]
#[table_name = "mod_add_community"] #[table_name = "mod_add_community"]
pub struct ModAddCommunityForm { pub struct ModAddCommunityForm {
pub mod_user_id: i32, pub mod_person_id: i32,
pub other_user_id: i32, pub other_person_id: i32,
pub community_id: i32, pub community_id: i32,
pub removed: Option<bool>, pub removed: Option<bool>,
} }
@ -179,8 +179,8 @@ pub struct ModAddCommunityForm {
#[table_name = "mod_add"] #[table_name = "mod_add"]
pub struct ModAdd { pub struct ModAdd {
pub id: i32, pub id: i32,
pub mod_user_id: i32, pub mod_person_id: i32,
pub other_user_id: i32, pub other_person_id: i32,
pub removed: Option<bool>, pub removed: Option<bool>,
pub when_: chrono::NaiveDateTime, pub when_: chrono::NaiveDateTime,
} }
@ -188,7 +188,7 @@ pub struct ModAdd {
#[derive(Insertable, AsChangeset)] #[derive(Insertable, AsChangeset)]
#[table_name = "mod_add"] #[table_name = "mod_add"]
pub struct ModAddForm { pub struct ModAddForm {
pub mod_user_id: i32, pub mod_person_id: i32,
pub other_user_id: i32, pub other_person_id: i32,
pub removed: Option<bool>, pub removed: Option<bool>,
} }

View file

@ -4,14 +4,14 @@ use crate::schema::password_reset_request;
#[table_name = "password_reset_request"] #[table_name = "password_reset_request"]
pub struct PasswordResetRequest { pub struct PasswordResetRequest {
pub id: i32, pub id: i32,
pub user_id: i32,
pub token_encrypted: String, pub token_encrypted: String,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
pub local_user_id: i32,
} }
#[derive(Insertable, AsChangeset)] #[derive(Insertable, AsChangeset)]
#[table_name = "password_reset_request"] #[table_name = "password_reset_request"]
pub struct PasswordResetRequestForm { pub struct PasswordResetRequestForm {
pub user_id: i32, pub local_user_id: i32,
pub token_encrypted: String, pub token_encrypted: String,
} }

View file

@ -1,30 +1,19 @@
use crate::{ use crate::{
schema::{user_, user_alias_1, user_alias_2}, schema::{person, person_alias_1, person_alias_2},
DbUrl, DbUrl,
}; };
use serde::Serialize; use serde::Serialize;
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_"] #[table_name = "person"]
pub struct User_ { pub struct Person {
pub id: i32, pub id: i32,
pub name: String, pub name: String,
pub preferred_username: Option<String>, pub preferred_username: Option<String>,
pub password_encrypted: String,
pub email: Option<String>,
pub avatar: Option<DbUrl>, pub avatar: Option<DbUrl>,
pub admin: bool,
pub banned: bool, pub banned: bool,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
pub updated: 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<String>,
pub actor_id: DbUrl, pub actor_id: DbUrl,
pub bio: Option<String>, pub bio: Option<String>,
pub local: bool, pub local: bool,
@ -37,19 +26,17 @@ pub struct User_ {
pub shared_inbox_url: Option<DbUrl>, pub shared_inbox_url: Option<DbUrl>,
} }
/// A safe representation of user, without the sensitive info /// A safe representation of person, without the sensitive info
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_"] #[table_name = "person"]
pub struct UserSafe { pub struct PersonSafe {
pub id: i32, pub id: i32,
pub name: String, pub name: String,
pub preferred_username: Option<String>, pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>, pub avatar: Option<DbUrl>,
pub admin: bool,
pub banned: bool, pub banned: bool,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>, pub updated: Option<chrono::NaiveDateTime>,
pub matrix_user_id: Option<String>,
pub actor_id: DbUrl, pub actor_id: DbUrl,
pub bio: Option<String>, pub bio: Option<String>,
pub local: bool, pub local: bool,
@ -59,56 +46,16 @@ pub struct UserSafe {
pub shared_inbox_url: Option<DbUrl>, pub shared_inbox_url: Option<DbUrl>,
} }
/// A safe user view with only settings
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_"] #[table_name = "person_alias_1"]
pub struct UserSafeSettings { pub struct PersonAlias1 {
pub id: i32, pub id: i32,
pub name: String, pub name: String,
pub preferred_username: Option<String>, pub preferred_username: Option<String>,
pub email: Option<String>,
pub avatar: Option<DbUrl>, pub avatar: Option<DbUrl>,
pub admin: bool,
pub banned: bool, pub banned: bool,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
pub updated: 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<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 actor_id: DbUrl,
pub bio: Option<String>, pub bio: Option<String>,
pub local: bool, pub local: bool,
@ -117,48 +64,39 @@ pub struct UserAlias1 {
pub last_refreshed_at: chrono::NaiveDateTime, pub last_refreshed_at: chrono::NaiveDateTime,
pub banner: Option<DbUrl>, pub banner: Option<DbUrl>,
pub deleted: bool, pub deleted: bool,
pub inbox_url: DbUrl,
pub shared_inbox_url: Option<DbUrl>,
} }
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_alias_1"] #[table_name = "person_alias_1"]
pub struct UserSafeAlias1 { pub struct PersonSafeAlias1 {
pub id: i32, pub id: i32,
pub name: String, pub name: String,
pub preferred_username: Option<String>, pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>, pub avatar: Option<DbUrl>,
pub admin: bool,
pub banned: bool, pub banned: bool,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>, pub updated: Option<chrono::NaiveDateTime>,
pub matrix_user_id: Option<String>,
pub actor_id: DbUrl, pub actor_id: DbUrl,
pub bio: Option<String>, pub bio: Option<String>,
pub local: bool, pub local: bool,
pub banner: Option<DbUrl>, pub banner: Option<DbUrl>,
pub deleted: bool, pub deleted: bool,
pub inbox_url: DbUrl,
pub shared_inbox_url: Option<DbUrl>,
} }
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_alias_2"] #[table_name = "person_alias_2"]
pub struct UserAlias2 { pub struct PersonAlias2 {
pub id: i32, pub id: i32,
pub name: String, pub name: String,
pub preferred_username: Option<String>, pub preferred_username: Option<String>,
pub password_encrypted: String,
pub email: Option<String>,
pub avatar: Option<DbUrl>, pub avatar: Option<DbUrl>,
pub admin: bool,
pub banned: bool, pub banned: bool,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
pub updated: 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<String>,
pub actor_id: DbUrl, pub actor_id: DbUrl,
pub bio: Option<String>, pub bio: Option<String>,
pub local: bool, pub local: bool,
@ -167,54 +105,46 @@ pub struct UserAlias2 {
pub last_refreshed_at: chrono::NaiveDateTime, pub last_refreshed_at: chrono::NaiveDateTime,
pub banner: Option<DbUrl>, pub banner: Option<DbUrl>,
pub deleted: bool, pub deleted: bool,
pub inbox_url: DbUrl,
pub shared_inbox_url: Option<DbUrl>,
} }
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_alias_2"] #[table_name = "person_alias_1"]
pub struct UserSafeAlias2 { pub struct PersonSafeAlias2 {
pub id: i32, pub id: i32,
pub name: String, pub name: String,
pub preferred_username: Option<String>, pub preferred_username: Option<String>,
pub avatar: Option<DbUrl>, pub avatar: Option<DbUrl>,
pub admin: bool,
pub banned: bool, pub banned: bool,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>, pub updated: Option<chrono::NaiveDateTime>,
pub matrix_user_id: Option<String>,
pub actor_id: DbUrl, pub actor_id: DbUrl,
pub bio: Option<String>, pub bio: Option<String>,
pub local: bool, pub local: bool,
pub banner: Option<DbUrl>, pub banner: Option<DbUrl>,
pub deleted: bool, pub deleted: bool,
pub inbox_url: DbUrl,
pub shared_inbox_url: Option<DbUrl>,
} }
#[derive(Insertable, AsChangeset, Clone)] #[derive(Insertable, AsChangeset, Clone)]
#[table_name = "user_"] #[table_name = "person"]
pub struct UserForm { pub struct PersonForm {
pub name: String, pub name: String,
pub preferred_username: Option<Option<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 avatar: Option<Option<DbUrl>>,
pub banned: Option<bool>,
pub published: Option<chrono::NaiveDateTime>, pub published: Option<chrono::NaiveDateTime>,
pub updated: 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 actor_id: Option<DbUrl>,
pub bio: Option<Option<String>>, pub bio: Option<Option<String>>,
pub local: bool, pub local: Option<bool>,
pub private_key: Option<String>, pub private_key: Option<Option<String>>,
pub public_key: Option<String>, pub public_key: Option<Option<String>>,
pub last_refreshed_at: Option<chrono::NaiveDateTime>, pub last_refreshed_at: Option<chrono::NaiveDateTime>,
pub banner: Option<Option<DbUrl>>, pub banner: Option<Option<DbUrl>>,
pub deleted: Option<bool>,
pub inbox_url: Option<DbUrl>, pub inbox_url: Option<DbUrl>,
pub shared_inbox_url: Option<Option<DbUrl>>, pub shared_inbox_url: Option<Option<DbUrl>>,
} }

View file

@ -1,10 +1,10 @@
use crate::{schema::user_mention, source::comment::Comment}; use crate::{schema::person_mention, source::comment::Comment};
use serde::Serialize; use serde::Serialize;
#[derive(Clone, Queryable, Associations, Identifiable, PartialEq, Debug, Serialize)] #[derive(Clone, Queryable, Associations, Identifiable, PartialEq, Debug, Serialize)]
#[belongs_to(Comment)] #[belongs_to(Comment)]
#[table_name = "user_mention"] #[table_name = "person_mention"]
pub struct UserMention { pub struct PersonMention {
pub id: i32, pub id: i32,
pub recipient_id: i32, pub recipient_id: i32,
pub comment_id: i32, pub comment_id: i32,
@ -13,8 +13,8 @@ pub struct UserMention {
} }
#[derive(Insertable, AsChangeset)] #[derive(Insertable, AsChangeset)]
#[table_name = "user_mention"] #[table_name = "person_mention"]
pub struct UserMentionForm { pub struct PersonMentionForm {
pub recipient_id: i32, pub recipient_id: i32,
pub comment_id: i32, pub comment_id: i32,
pub read: Option<bool>, pub read: Option<bool>,

View file

@ -57,7 +57,7 @@ pub struct PostForm {
pub struct PostLike { pub struct PostLike {
pub id: i32, pub id: i32,
pub post_id: i32, pub post_id: i32,
pub user_id: i32, pub person_id: i32,
pub score: i16, pub score: i16,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
} }
@ -66,7 +66,7 @@ pub struct PostLike {
#[table_name = "post_like"] #[table_name = "post_like"]
pub struct PostLikeForm { pub struct PostLikeForm {
pub post_id: i32, pub post_id: i32,
pub user_id: i32, pub person_id: i32,
pub score: i16, pub score: i16,
} }
@ -76,7 +76,7 @@ pub struct PostLikeForm {
pub struct PostSaved { pub struct PostSaved {
pub id: i32, pub id: i32,
pub post_id: i32, pub post_id: i32,
pub user_id: i32, pub person_id: i32,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
} }
@ -84,7 +84,7 @@ pub struct PostSaved {
#[table_name = "post_saved"] #[table_name = "post_saved"]
pub struct PostSavedForm { pub struct PostSavedForm {
pub post_id: i32, pub post_id: i32,
pub user_id: i32, pub person_id: i32,
} }
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)] #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
@ -92,11 +92,8 @@ pub struct PostSavedForm {
#[table_name = "post_read"] #[table_name = "post_read"]
pub struct PostRead { pub struct PostRead {
pub id: i32, pub id: i32,
pub post_id: i32, pub post_id: i32,
pub person_id: i32,
pub user_id: i32,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
} }
@ -104,6 +101,5 @@ pub struct PostRead {
#[table_name = "post_read"] #[table_name = "post_read"]
pub struct PostReadForm { pub struct PostReadForm {
pub post_id: i32, pub post_id: i32,
pub person_id: i32,
pub user_id: i32,
} }

View file

@ -1,13 +1,13 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec}; use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{comment, comment_report, community, post, user_, user_alias_1, user_alias_2}, schema::{comment, comment_report, community, person, person_alias_1, person_alias_2, post},
source::{ source::{
comment::Comment, comment::Comment,
comment_report::CommentReport, comment_report::CommentReport,
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2},
post::Post, post::Post,
user::{UserAlias1, UserAlias2, UserSafe, UserSafeAlias1, UserSafeAlias2, User_},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -18,9 +18,9 @@ pub struct CommentReportView {
pub comment: Comment, pub comment: Comment,
pub post: Post, pub post: Post,
pub community: CommunitySafe, pub community: CommunitySafe,
pub creator: UserSafe, pub creator: PersonSafe,
pub comment_creator: UserSafeAlias1, pub comment_creator: PersonSafeAlias1,
pub resolver: Option<UserSafeAlias2>, pub resolver: Option<PersonSafeAlias2>,
} }
type CommentReportViewTuple = ( type CommentReportViewTuple = (
@ -28,9 +28,9 @@ type CommentReportViewTuple = (
Comment, Comment,
Post, Post,
CommunitySafe, CommunitySafe,
UserSafe, PersonSafe,
UserSafeAlias1, PersonSafeAlias1,
Option<UserSafeAlias2>, Option<PersonSafeAlias2>,
); );
impl CommentReportView { impl CommentReportView {
@ -44,19 +44,19 @@ impl CommentReportView {
.inner_join(comment::table) .inner_join(comment::table)
.inner_join(post::table.on(comment::post_id.eq(post::id))) .inner_join(post::table.on(comment::post_id.eq(post::id)))
.inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(user_::table.on(comment_report::creator_id.eq(user_::id))) .inner_join(person::table.on(comment_report::creator_id.eq(person::id)))
.inner_join(user_alias_1::table.on(post::creator_id.eq(user_alias_1::id))) .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id)))
.left_join( .left_join(
user_alias_2::table.on(comment_report::resolver_id.eq(user_alias_2::id.nullable())), person_alias_2::table.on(comment_report::resolver_id.eq(person_alias_2::id.nullable())),
) )
.select(( .select((
comment_report::all_columns, comment_report::all_columns,
comment::all_columns, comment::all_columns,
post::all_columns, post::all_columns,
Community::safe_columns_tuple(), Community::safe_columns_tuple(),
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
UserAlias1::safe_columns_tuple(), PersonAlias1::safe_columns_tuple(),
UserAlias2::safe_columns_tuple().nullable(), PersonAlias2::safe_columns_tuple().nullable(),
)) ))
.first::<CommentReportViewTuple>(conn)?; .first::<CommentReportViewTuple>(conn)?;
@ -75,7 +75,7 @@ impl CommentReportView {
/// ///
/// * `community_ids` - a Vec<i32> of community_ids to get a count for /// * `community_ids` - a Vec<i32> of community_ids to get a count for
/// TODO this eq_any is a bad way to do this, would be better to join to communitymoderator /// TODO this eq_any is a bad way to do this, would be better to join to communitymoderator
/// for a user id /// for a person id
pub fn get_report_count(conn: &PgConnection, community_ids: &[i32]) -> Result<i64, Error> { pub fn get_report_count(conn: &PgConnection, community_ids: &[i32]) -> Result<i64, Error> {
use diesel::dsl::*; use diesel::dsl::*;
comment_report::table comment_report::table
@ -135,19 +135,19 @@ impl<'a> CommentReportQueryBuilder<'a> {
.inner_join(comment::table) .inner_join(comment::table)
.inner_join(post::table.on(comment::post_id.eq(post::id))) .inner_join(post::table.on(comment::post_id.eq(post::id)))
.inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(user_::table.on(comment_report::creator_id.eq(user_::id))) .inner_join(person::table.on(comment_report::creator_id.eq(person::id)))
.inner_join(user_alias_1::table.on(post::creator_id.eq(user_alias_1::id))) .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id)))
.left_join( .left_join(
user_alias_2::table.on(comment_report::resolver_id.eq(user_alias_2::id.nullable())), person_alias_2::table.on(comment_report::resolver_id.eq(person_alias_2::id.nullable())),
) )
.select(( .select((
comment_report::all_columns, comment_report::all_columns,
comment::all_columns, comment::all_columns,
post::all_columns, post::all_columns,
Community::safe_columns_tuple(), Community::safe_columns_tuple(),
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
UserAlias1::safe_columns_tuple(), PersonAlias1::safe_columns_tuple(),
UserAlias2::safe_columns_tuple().nullable(), PersonAlias2::safe_columns_tuple().nullable(),
)) ))
.into_boxed(); .into_boxed();

View file

@ -19,16 +19,16 @@ use lemmy_db_schema::{
comment_saved, comment_saved,
community, community,
community_follower, community_follower,
community_user_ban, community_person_ban,
person,
person_alias_1,
post, post,
user_,
user_alias_1,
}, },
source::{ source::{
comment::{Comment, CommentAlias1, CommentSaved}, comment::{Comment, CommentAlias1, CommentSaved},
community::{Community, CommunityFollower, CommunitySafe, CommunityUserBan}, community::{Community, CommunityFollower, CommunityPersonBan, CommunitySafe},
person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
post::Post, post::Post,
user::{UserAlias1, UserSafe, UserSafeAlias1, User_},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -36,12 +36,12 @@ use serde::Serialize;
#[derive(Debug, PartialEq, Serialize, Clone)] #[derive(Debug, PartialEq, Serialize, Clone)]
pub struct CommentView { pub struct CommentView {
pub comment: Comment, pub comment: Comment,
pub creator: UserSafe, pub creator: PersonSafe,
pub recipient: Option<UserSafeAlias1>, // Left joins to comment and user pub recipient: Option<PersonSafeAlias1>, // Left joins to comment and person
pub post: Post, pub post: Post,
pub community: CommunitySafe, pub community: CommunitySafe,
pub counts: CommentAggregates, pub counts: CommentAggregates,
pub creator_banned_from_community: bool, // Left Join to CommunityUserBan pub creator_banned_from_community: bool, // Left Join to CommunityPersonBan
pub subscribed: bool, // Left join to CommunityFollower pub subscribed: bool, // Left join to CommunityFollower
pub saved: bool, // Left join to CommentSaved pub saved: bool, // Left join to CommentSaved
pub my_vote: Option<i16>, // Left join to CommentLike pub my_vote: Option<i16>, // Left join to CommentLike
@ -49,13 +49,13 @@ pub struct CommentView {
type CommentViewTuple = ( type CommentViewTuple = (
Comment, Comment,
UserSafe, PersonSafe,
Option<CommentAlias1>, Option<CommentAlias1>,
Option<UserSafeAlias1>, Option<PersonSafeAlias1>,
Post, Post,
CommunitySafe, CommunitySafe,
CommentAggregates, CommentAggregates,
Option<CommunityUserBan>, Option<CommunityPersonBan>,
Option<CommunityFollower>, Option<CommunityFollower>,
Option<CommentSaved>, Option<CommentSaved>,
Option<i16>, Option<i16>,
@ -65,10 +65,10 @@ impl CommentView {
pub fn read( pub fn read(
conn: &PgConnection, conn: &PgConnection,
comment_id: i32, comment_id: i32,
my_user_id: Option<i32>, my_person_id: Option<i32>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
// The left join below will return None in this case // The left join below will return None in this case
let user_id_join = my_user_id.unwrap_or(-1); let person_id_join = my_person_id.unwrap_or(-1);
let ( let (
comment, comment,
@ -84,59 +84,59 @@ impl CommentView {
comment_like, comment_like,
) = comment::table ) = comment::table
.find(comment_id) .find(comment_id)
.inner_join(user_::table) .inner_join(person::table)
// recipient here // recipient here
.left_join(comment_alias_1::table.on(comment_alias_1::id.nullable().eq(comment::parent_id))) .left_join(comment_alias_1::table.on(comment_alias_1::id.nullable().eq(comment::parent_id)))
.left_join(user_alias_1::table.on(user_alias_1::id.eq(comment_alias_1::creator_id))) .left_join(person_alias_1::table.on(person_alias_1::id.eq(comment_alias_1::creator_id)))
.inner_join(post::table) .inner_join(post::table)
.inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(comment_aggregates::table) .inner_join(comment_aggregates::table)
.left_join( .left_join(
community_user_ban::table.on( community_person_ban::table.on(
community::id community::id
.eq(community_user_ban::community_id) .eq(community_person_ban::community_id)
.and(community_user_ban::user_id.eq(comment::creator_id)), .and(community_person_ban::person_id.eq(comment::creator_id)),
), ),
) )
.left_join( .left_join(
community_follower::table.on( community_follower::table.on(
post::community_id post::community_id
.eq(community_follower::community_id) .eq(community_follower::community_id)
.and(community_follower::user_id.eq(user_id_join)), .and(community_follower::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
comment_saved::table.on( comment_saved::table.on(
comment::id comment::id
.eq(comment_saved::comment_id) .eq(comment_saved::comment_id)
.and(comment_saved::user_id.eq(user_id_join)), .and(comment_saved::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
comment_like::table.on( comment_like::table.on(
comment::id comment::id
.eq(comment_like::comment_id) .eq(comment_like::comment_id)
.and(comment_like::user_id.eq(user_id_join)), .and(comment_like::person_id.eq(person_id_join)),
), ),
) )
.select(( .select((
comment::all_columns, comment::all_columns,
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
comment_alias_1::all_columns.nullable(), comment_alias_1::all_columns.nullable(),
UserAlias1::safe_columns_tuple().nullable(), PersonAlias1::safe_columns_tuple().nullable(),
post::all_columns, post::all_columns,
Community::safe_columns_tuple(), Community::safe_columns_tuple(),
comment_aggregates::all_columns, comment_aggregates::all_columns,
community_user_ban::all_columns.nullable(), community_person_ban::all_columns.nullable(),
community_follower::all_columns.nullable(), community_follower::all_columns.nullable(),
comment_saved::all_columns.nullable(), comment_saved::all_columns.nullable(),
comment_like::score.nullable(), comment_like::score.nullable(),
)) ))
.first::<CommentViewTuple>(conn)?; .first::<CommentViewTuple>(conn)?;
// If a user is given, then my_vote, if None, should be 0, not null // If a person is given, then my_vote, if None, should be 0, not null
// Necessary to differentiate between other user's votes // Necessary to differentiate between other person's votes
let my_vote = if my_user_id.is_some() && comment_like.is_none() { let my_vote = if my_person_id.is_some() && comment_like.is_none() {
Some(0) Some(0)
} else { } else {
comment_like comment_like
@ -156,7 +156,7 @@ impl CommentView {
}) })
} }
/// Gets the recipient user id. /// Gets the recipient person id.
/// If there is no parent comment, its the post creator /// If there is no parent comment, its the post creator
pub fn get_recipient_id(&self) -> i32 { pub fn get_recipient_id(&self) -> i32 {
match &self.recipient { match &self.recipient {
@ -175,7 +175,7 @@ pub struct CommentQueryBuilder<'a> {
post_id: Option<i32>, post_id: Option<i32>,
creator_id: Option<i32>, creator_id: Option<i32>,
recipient_id: Option<i32>, recipient_id: Option<i32>,
my_user_id: Option<i32>, my_person_id: Option<i32>,
search_term: Option<String>, search_term: Option<String>,
saved_only: bool, saved_only: bool,
unread_only: bool, unread_only: bool,
@ -194,7 +194,7 @@ impl<'a> CommentQueryBuilder<'a> {
post_id: None, post_id: None,
creator_id: None, creator_id: None,
recipient_id: None, recipient_id: None,
my_user_id: None, my_person_id: None,
search_term: None, search_term: None,
saved_only: false, saved_only: false,
unread_only: false, unread_only: false,
@ -233,8 +233,8 @@ impl<'a> CommentQueryBuilder<'a> {
self self
} }
pub fn my_user_id<T: MaybeOptional<i32>>(mut self, my_user_id: T) -> Self { pub fn my_person_id<T: MaybeOptional<i32>>(mut self, my_person_id: T) -> Self {
self.my_user_id = my_user_id.get_optional(); self.my_person_id = my_person_id.get_optional();
self self
} }
@ -272,53 +272,53 @@ impl<'a> CommentQueryBuilder<'a> {
use diesel::dsl::*; use diesel::dsl::*;
// The left join below will return None in this case // The left join below will return None in this case
let user_id_join = self.my_user_id.unwrap_or(-1); let person_id_join = self.my_person_id.unwrap_or(-1);
let mut query = comment::table let mut query = comment::table
.inner_join(user_::table) .inner_join(person::table)
// recipient here // recipient here
.left_join(comment_alias_1::table.on(comment_alias_1::id.nullable().eq(comment::parent_id))) .left_join(comment_alias_1::table.on(comment_alias_1::id.nullable().eq(comment::parent_id)))
.left_join(user_alias_1::table.on(user_alias_1::id.eq(comment_alias_1::creator_id))) .left_join(person_alias_1::table.on(person_alias_1::id.eq(comment_alias_1::creator_id)))
.inner_join(post::table) .inner_join(post::table)
.inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(comment_aggregates::table) .inner_join(comment_aggregates::table)
.left_join( .left_join(
community_user_ban::table.on( community_person_ban::table.on(
community::id community::id
.eq(community_user_ban::community_id) .eq(community_person_ban::community_id)
.and(community_user_ban::user_id.eq(comment::creator_id)), .and(community_person_ban::person_id.eq(comment::creator_id)),
), ),
) )
.left_join( .left_join(
community_follower::table.on( community_follower::table.on(
post::community_id post::community_id
.eq(community_follower::community_id) .eq(community_follower::community_id)
.and(community_follower::user_id.eq(user_id_join)), .and(community_follower::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
comment_saved::table.on( comment_saved::table.on(
comment::id comment::id
.eq(comment_saved::comment_id) .eq(comment_saved::comment_id)
.and(comment_saved::user_id.eq(user_id_join)), .and(comment_saved::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
comment_like::table.on( comment_like::table.on(
comment::id comment::id
.eq(comment_like::comment_id) .eq(comment_like::comment_id)
.and(comment_like::user_id.eq(user_id_join)), .and(comment_like::person_id.eq(person_id_join)),
), ),
) )
.select(( .select((
comment::all_columns, comment::all_columns,
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
comment_alias_1::all_columns.nullable(), comment_alias_1::all_columns.nullable(),
UserAlias1::safe_columns_tuple().nullable(), PersonAlias1::safe_columns_tuple().nullable(),
post::all_columns, post::all_columns,
Community::safe_columns_tuple(), Community::safe_columns_tuple(),
comment_aggregates::all_columns, comment_aggregates::all_columns,
community_user_ban::all_columns.nullable(), community_person_ban::all_columns.nullable(),
community_follower::all_columns.nullable(), community_follower::all_columns.nullable(),
comment_saved::all_columns.nullable(), comment_saved::all_columns.nullable(),
comment_like::score.nullable(), comment_like::score.nullable(),
@ -329,7 +329,7 @@ impl<'a> CommentQueryBuilder<'a> {
if let Some(recipient_id) = self.recipient_id { if let Some(recipient_id) = self.recipient_id {
query = query query = query
// TODO needs lots of testing // TODO needs lots of testing
.filter(user_alias_1::id.eq(recipient_id)) // Gets the comment replies .filter(person_alias_1::id.eq(recipient_id)) // Gets the comment replies
.or_filter( .or_filter(
comment::parent_id comment::parent_id
.is_null() .is_null()
@ -367,7 +367,7 @@ impl<'a> CommentQueryBuilder<'a> {
query = match self.listing_type { query = match self.listing_type {
// ListingType::Subscribed => query.filter(community_follower::subscribed.eq(true)), // ListingType::Subscribed => query.filter(community_follower::subscribed.eq(true)),
ListingType::Subscribed => query.filter(community_follower::user_id.is_not_null()), // TODO could be this: and(community_follower::user_id.eq(user_id_join)), ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)),
ListingType::Local => query.filter(community::local.eq(true)), ListingType::Local => query.filter(community::local.eq(true)),
_ => query, _ => query,
}; };
@ -439,10 +439,8 @@ mod tests {
establish_unpooled_connection, establish_unpooled_connection,
Crud, Crud,
Likeable, Likeable,
ListingType,
SortType,
}; };
use lemmy_db_schema::source::{comment::*, community::*, post::*, user::*}; use lemmy_db_schema::source::{comment::*, community::*, person::*, post::*};
use serial_test::serial; use serial_test::serial;
#[test] #[test]
@ -450,28 +448,18 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let new_user = UserForm { let new_person = PersonForm {
name: "timmy".into(), name: "timmy".into(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
admin: false, banned: None,
banned: Some(false), deleted: None,
published: None, published: None,
updated: 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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -479,13 +467,13 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_user = User_::create(&conn, &new_user).unwrap(); let inserted_person = Person::create(&conn, &new_person).unwrap();
let new_community = CommunityForm { let new_community = CommunityForm {
name: "test community 5".to_string(), name: "test community 5".to_string(),
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
removed: None, removed: None,
deleted: None, deleted: None,
updated: None, updated: None,
@ -507,7 +495,7 @@ mod tests {
let new_post = PostForm { let new_post = PostForm {
name: "A test post 2".into(), name: "A test post 2".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
url: None, url: None,
body: None, body: None,
community_id: inserted_community.id, community_id: inserted_community.id,
@ -530,7 +518,7 @@ mod tests {
let comment_form = CommentForm { let comment_form = CommentForm {
content: "A test comment 32".into(), content: "A test comment 32".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
parent_id: None, parent_id: None,
removed: None, removed: None,
@ -547,7 +535,7 @@ mod tests {
let comment_like_form = CommentLikeForm { let comment_like_form = CommentLikeForm {
comment_id: inserted_comment.id, comment_id: inserted_comment.id,
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
score: 1, score: 1,
}; };
@ -555,7 +543,7 @@ mod tests {
let agg = CommentAggregates::read(&conn, inserted_comment.id).unwrap(); let agg = CommentAggregates::read(&conn, inserted_comment.id).unwrap();
let expected_comment_view_no_user = CommentView { let expected_comment_view_no_person = CommentView {
creator_banned_from_community: false, creator_banned_from_community: false,
my_vote: None, my_vote: None,
subscribed: false, subscribed: false,
@ -563,7 +551,7 @@ mod tests {
comment: Comment { comment: Comment {
id: inserted_comment.id, id: inserted_comment.id,
content: "A test comment 32".into(), content: "A test comment 32".into(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
post_id: inserted_post.id, post_id: inserted_post.id,
parent_id: None, parent_id: None,
removed: false, removed: false,
@ -574,29 +562,27 @@ mod tests {
updated: None, updated: None,
local: true, local: true,
}, },
creator: UserSafe { creator: PersonSafe {
id: inserted_user.id, id: inserted_person.id,
name: "timmy".into(), name: "timmy".into(),
preferred_username: None, preferred_username: None,
published: inserted_user.published, published: inserted_person.published,
avatar: None, avatar: None,
actor_id: inserted_user.actor_id.to_owned(), actor_id: inserted_person.actor_id.to_owned(),
local: true, local: true,
banned: false, banned: false,
deleted: false, deleted: false,
bio: None, bio: None,
banner: None, banner: None,
admin: false,
updated: None, updated: None,
matrix_user_id: None, inbox_url: inserted_person.inbox_url.to_owned(),
inbox_url: inserted_user.inbox_url.to_owned(),
shared_inbox_url: None, shared_inbox_url: None,
}, },
recipient: None, recipient: None,
post: Post { post: Post {
id: inserted_post.id, id: inserted_post.id,
name: inserted_post.name.to_owned(), name: inserted_post.name.to_owned(),
creator_id: inserted_user.id, creator_id: inserted_person.id,
url: None, url: None,
body: None, body: None,
published: inserted_post.published, published: inserted_post.published,
@ -625,7 +611,7 @@ mod tests {
local: true, local: true,
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
updated: None, updated: None,
banner: None, banner: None,
published: inserted_community.published, published: inserted_community.published,
@ -640,30 +626,33 @@ mod tests {
}, },
}; };
let mut expected_comment_view_with_user = expected_comment_view_no_user.to_owned(); let mut expected_comment_view_with_person = expected_comment_view_no_person.to_owned();
expected_comment_view_with_user.my_vote = Some(1); expected_comment_view_with_person.my_vote = Some(1);
let read_comment_views_no_user = CommentQueryBuilder::create(&conn) let read_comment_views_no_person = CommentQueryBuilder::create(&conn)
.post_id(inserted_post.id) .post_id(inserted_post.id)
.list() .list()
.unwrap(); .unwrap();
let read_comment_views_with_user = CommentQueryBuilder::create(&conn) let read_comment_views_with_person = CommentQueryBuilder::create(&conn)
.post_id(inserted_post.id) .post_id(inserted_post.id)
.my_user_id(inserted_user.id) .my_person_id(inserted_person.id)
.list() .list()
.unwrap(); .unwrap();
let like_removed = CommentLike::remove(&conn, inserted_user.id, inserted_comment.id).unwrap(); let like_removed = CommentLike::remove(&conn, inserted_person.id, inserted_comment.id).unwrap();
let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap(); let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap();
Post::delete(&conn, inserted_post.id).unwrap(); Post::delete(&conn, inserted_post.id).unwrap();
Community::delete(&conn, inserted_community.id).unwrap(); Community::delete(&conn, inserted_community.id).unwrap();
User_::delete(&conn, inserted_user.id).unwrap(); Person::delete(&conn, inserted_person.id).unwrap();
assert_eq!(expected_comment_view_no_user, read_comment_views_no_user[0]);
assert_eq!( assert_eq!(
expected_comment_view_with_user, expected_comment_view_no_person,
read_comment_views_with_user[0] read_comment_views_no_person[0]
);
assert_eq!(
expected_comment_view_with_person,
read_comment_views_with_person[0]
); );
assert_eq!(1, num_deleted); assert_eq!(1, num_deleted);
assert_eq!(1, like_removed); assert_eq!(1, like_removed);

View file

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

View file

@ -0,0 +1,145 @@
use diesel::{result::Error, *};
use lemmy_db_queries::{aggregates::person_aggregates::PersonAggregates, ToSafe, ToSafeSettings};
use lemmy_db_schema::{
schema::{local_user, person, person_aggregates},
source::{
local_user::{LocalUser, LocalUserSettings},
person::{Person, PersonSafe},
},
};
use serde::Serialize;
#[derive(Debug, Serialize, Clone)]
pub struct LocalUserView {
pub local_user: LocalUser,
pub person: Person,
pub counts: PersonAggregates,
}
type LocalUserViewTuple = (LocalUser, Person, PersonAggregates);
impl LocalUserView {
pub fn read(conn: &PgConnection, local_user_id: i32) -> Result<Self, Error> {
let (local_user, person, counts) = local_user::table
.find(local_user_id)
.inner_join(person::table)
.inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
.select((
local_user::all_columns,
person::all_columns,
person_aggregates::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
Ok(Self {
local_user,
person,
counts,
})
}
pub fn read_person(conn: &PgConnection, person_id: i32) -> Result<Self, Error> {
let (local_user, person, counts) = local_user::table
.filter(person::id.eq(person_id))
.inner_join(person::table)
.inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
.select((
local_user::all_columns,
person::all_columns,
person_aggregates::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
Ok(Self {
local_user,
person,
counts,
})
}
// TODO check where this is used
pub fn read_from_name(conn: &PgConnection, name: &str) -> Result<Self, Error> {
let (local_user, person, counts) = local_user::table
.filter(person::name.eq(name))
.inner_join(person::table)
.inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
.select((
local_user::all_columns,
person::all_columns,
person_aggregates::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 (local_user, person, counts) = local_user::table
.inner_join(person::table)
.inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
.filter(
person::name
.ilike(name_or_email)
.or(local_user::email.ilike(name_or_email)),
)
.select((
local_user::all_columns,
person::all_columns,
person_aggregates::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
Ok(Self {
person,
counts,
local_user,
})
}
pub fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<Self, Error> {
let (local_user, person, counts) = local_user::table
.inner_join(person::table)
.inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
.filter(local_user::email.eq(from_email))
.select((
local_user::all_columns,
person::all_columns,
person_aggregates::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
Ok(Self {
person,
counts,
local_user,
})
}
}
#[derive(Debug, Serialize, Clone)]
pub struct LocalUserSettingsView {
pub local_user: LocalUserSettings,
pub person: PersonSafe,
pub counts: PersonAggregates,
}
type LocalUserSettingsViewTuple = (LocalUserSettings, PersonSafe, PersonAggregates);
impl LocalUserSettingsView {
pub fn read(conn: &PgConnection, local_user_id: i32) -> Result<Self, Error> {
let (local_user, person, counts) = local_user::table
.find(local_user_id)
.inner_join(person::table)
.inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
.select((
LocalUser::safe_settings_columns_tuple(),
Person::safe_columns_tuple(),
person_aggregates::all_columns,
))
.first::<LocalUserSettingsViewTuple>(conn)?;
Ok(Self {
person,
counts,
local_user,
})
}
}

View file

@ -1,12 +1,12 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec}; use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{community, post, post_report, user_, user_alias_1, user_alias_2}, schema::{community, person, person_alias_1, person_alias_2, post, post_report},
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2},
post::Post, post::Post,
post_report::PostReport, post_report::PostReport,
user::{UserAlias1, UserAlias2, UserSafe, UserSafeAlias1, UserSafeAlias2, User_},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -16,18 +16,18 @@ pub struct PostReportView {
pub post_report: PostReport, pub post_report: PostReport,
pub post: Post, pub post: Post,
pub community: CommunitySafe, pub community: CommunitySafe,
pub creator: UserSafe, pub creator: PersonSafe,
pub post_creator: UserSafeAlias1, pub post_creator: PersonSafeAlias1,
pub resolver: Option<UserSafeAlias2>, pub resolver: Option<PersonSafeAlias2>,
} }
type PostReportViewTuple = ( type PostReportViewTuple = (
PostReport, PostReport,
Post, Post,
CommunitySafe, CommunitySafe,
UserSafe, PersonSafe,
UserSafeAlias1, PersonSafeAlias1,
Option<UserSafeAlias2>, Option<PersonSafeAlias2>,
); );
impl PostReportView { impl PostReportView {
@ -39,16 +39,18 @@ impl PostReportView {
.find(report_id) .find(report_id)
.inner_join(post::table) .inner_join(post::table)
.inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(user_::table.on(post_report::creator_id.eq(user_::id))) .inner_join(person::table.on(post_report::creator_id.eq(person::id)))
.inner_join(user_alias_1::table.on(post::creator_id.eq(user_alias_1::id))) .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id)))
.left_join(user_alias_2::table.on(post_report::resolver_id.eq(user_alias_2::id.nullable()))) .left_join(
person_alias_2::table.on(post_report::resolver_id.eq(person_alias_2::id.nullable())),
)
.select(( .select((
post_report::all_columns, post_report::all_columns,
post::all_columns, post::all_columns,
Community::safe_columns_tuple(), Community::safe_columns_tuple(),
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
UserAlias1::safe_columns_tuple(), PersonAlias1::safe_columns_tuple(),
UserAlias2::safe_columns_tuple().nullable(), PersonAlias2::safe_columns_tuple().nullable(),
)) ))
.first::<PostReportViewTuple>(conn)?; .first::<PostReportViewTuple>(conn)?;
@ -66,7 +68,7 @@ impl PostReportView {
/// ///
/// * `community_ids` - a Vec<i32> of community_ids to get a count for /// * `community_ids` - a Vec<i32> of community_ids to get a count for
/// TODO this eq_any is a bad way to do this, would be better to join to communitymoderator /// TODO this eq_any is a bad way to do this, would be better to join to communitymoderator
/// for a user id /// for a person id
pub fn get_report_count(conn: &PgConnection, community_ids: &[i32]) -> Result<i64, Error> { pub fn get_report_count(conn: &PgConnection, community_ids: &[i32]) -> Result<i64, Error> {
use diesel::dsl::*; use diesel::dsl::*;
post_report::table post_report::table
@ -124,16 +126,18 @@ impl<'a> PostReportQueryBuilder<'a> {
let mut query = post_report::table let mut query = post_report::table
.inner_join(post::table) .inner_join(post::table)
.inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(user_::table.on(post_report::creator_id.eq(user_::id))) .inner_join(person::table.on(post_report::creator_id.eq(person::id)))
.inner_join(user_alias_1::table.on(post::creator_id.eq(user_alias_1::id))) .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id)))
.left_join(user_alias_2::table.on(post_report::resolver_id.eq(user_alias_2::id.nullable()))) .left_join(
person_alias_2::table.on(post_report::resolver_id.eq(person_alias_2::id.nullable())),
)
.select(( .select((
post_report::all_columns, post_report::all_columns,
post::all_columns, post::all_columns,
Community::safe_columns_tuple(), Community::safe_columns_tuple(),
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
UserAlias1::safe_columns_tuple(), PersonAlias1::safe_columns_tuple(),
UserAlias2::safe_columns_tuple().nullable(), PersonAlias2::safe_columns_tuple().nullable(),
)) ))
.into_boxed(); .into_boxed();

View file

@ -14,18 +14,18 @@ use lemmy_db_schema::{
schema::{ schema::{
community, community,
community_follower, community_follower,
community_user_ban, community_person_ban,
person,
post, post,
post_aggregates, post_aggregates,
post_like, post_like,
post_read, post_read,
post_saved, post_saved,
user_,
}, },
source::{ source::{
community::{Community, CommunityFollower, CommunitySafe, CommunityUserBan}, community::{Community, CommunityFollower, CommunityPersonBan, CommunitySafe},
person::{Person, PersonSafe},
post::{Post, PostRead, PostSaved}, post::{Post, PostRead, PostSaved},
user::{UserSafe, User_},
}, },
}; };
use log::debug; use log::debug;
@ -34,9 +34,9 @@ use serde::Serialize;
#[derive(Debug, PartialEq, Serialize, Clone)] #[derive(Debug, PartialEq, Serialize, Clone)]
pub struct PostView { pub struct PostView {
pub post: Post, pub post: Post,
pub creator: UserSafe, pub creator: PersonSafe,
pub community: CommunitySafe, pub community: CommunitySafe,
pub creator_banned_from_community: bool, // Left Join to CommunityUserBan pub creator_banned_from_community: bool, // Left Join to CommunityPersonBan
pub counts: PostAggregates, pub counts: PostAggregates,
pub subscribed: bool, // Left join to CommunityFollower pub subscribed: bool, // Left join to CommunityFollower
pub saved: bool, // Left join to PostSaved pub saved: bool, // Left join to PostSaved
@ -46,9 +46,9 @@ pub struct PostView {
type PostViewTuple = ( type PostViewTuple = (
Post, Post,
UserSafe, PersonSafe,
CommunitySafe, CommunitySafe,
Option<CommunityUserBan>, Option<CommunityPersonBan>,
PostAggregates, PostAggregates,
Option<CommunityFollower>, Option<CommunityFollower>,
Option<PostSaved>, Option<PostSaved>,
@ -57,9 +57,9 @@ type PostViewTuple = (
); );
impl PostView { impl PostView {
pub fn read(conn: &PgConnection, post_id: i32, my_user_id: Option<i32>) -> Result<Self, Error> { pub fn read(conn: &PgConnection, post_id: i32, my_person_id: Option<i32>) -> Result<Self, Error> {
// The left join below will return None in this case // The left join below will return None in this case
let user_id_join = my_user_id.unwrap_or(-1); let person_id_join = my_person_id.unwrap_or(-1);
let ( let (
post, post,
@ -73,13 +73,13 @@ impl PostView {
post_like, post_like,
) = post::table ) = post::table
.find(post_id) .find(post_id)
.inner_join(user_::table) .inner_join(person::table)
.inner_join(community::table) .inner_join(community::table)
.left_join( .left_join(
community_user_ban::table.on( community_person_ban::table.on(
post::community_id post::community_id
.eq(community_user_ban::community_id) .eq(community_person_ban::community_id)
.and(community_user_ban::user_id.eq(post::creator_id)), .and(community_person_ban::person_id.eq(post::creator_id)),
), ),
) )
.inner_join(post_aggregates::table) .inner_join(post_aggregates::table)
@ -87,35 +87,35 @@ impl PostView {
community_follower::table.on( community_follower::table.on(
post::community_id post::community_id
.eq(community_follower::community_id) .eq(community_follower::community_id)
.and(community_follower::user_id.eq(user_id_join)), .and(community_follower::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
post_saved::table.on( post_saved::table.on(
post::id post::id
.eq(post_saved::post_id) .eq(post_saved::post_id)
.and(post_saved::user_id.eq(user_id_join)), .and(post_saved::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
post_read::table.on( post_read::table.on(
post::id post::id
.eq(post_read::post_id) .eq(post_read::post_id)
.and(post_read::user_id.eq(user_id_join)), .and(post_read::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
post_like::table.on( post_like::table.on(
post::id post::id
.eq(post_like::post_id) .eq(post_like::post_id)
.and(post_like::user_id.eq(user_id_join)), .and(post_like::person_id.eq(person_id_join)),
), ),
) )
.select(( .select((
post::all_columns, post::all_columns,
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
Community::safe_columns_tuple(), Community::safe_columns_tuple(),
community_user_ban::all_columns.nullable(), community_person_ban::all_columns.nullable(),
post_aggregates::all_columns, post_aggregates::all_columns,
community_follower::all_columns.nullable(), community_follower::all_columns.nullable(),
post_saved::all_columns.nullable(), post_saved::all_columns.nullable(),
@ -124,9 +124,9 @@ impl PostView {
)) ))
.first::<PostViewTuple>(conn)?; .first::<PostViewTuple>(conn)?;
// If a user is given, then my_vote, if None, should be 0, not null // If a person is given, then my_vote, if None, should be 0, not null
// Necessary to differentiate between other user's votes // Necessary to differentiate between other person's votes
let my_vote = if my_user_id.is_some() && post_like.is_none() { let my_vote = if my_person_id.is_some() && post_like.is_none() {
Some(0) Some(0)
} else { } else {
post_like post_like
@ -153,7 +153,7 @@ pub struct PostQueryBuilder<'a> {
creator_id: Option<i32>, creator_id: Option<i32>,
community_id: Option<i32>, community_id: Option<i32>,
community_name: Option<String>, community_name: Option<String>,
my_user_id: Option<i32>, my_person_id: Option<i32>,
search_term: Option<String>, search_term: Option<String>,
url_search: Option<String>, url_search: Option<String>,
show_nsfw: bool, show_nsfw: bool,
@ -172,7 +172,7 @@ impl<'a> PostQueryBuilder<'a> {
creator_id: None, creator_id: None,
community_id: None, community_id: None,
community_name: None, community_name: None,
my_user_id: None, my_person_id: None,
search_term: None, search_term: None,
url_search: None, url_search: None,
show_nsfw: true, show_nsfw: true,
@ -198,8 +198,8 @@ impl<'a> PostQueryBuilder<'a> {
self self
} }
pub fn my_user_id<T: MaybeOptional<i32>>(mut self, my_user_id: T) -> Self { pub fn my_person_id<T: MaybeOptional<i32>>(mut self, my_person_id: T) -> Self {
self.my_user_id = my_user_id.get_optional(); self.my_person_id = my_person_id.get_optional();
self self
} }
@ -247,16 +247,16 @@ impl<'a> PostQueryBuilder<'a> {
use diesel::dsl::*; use diesel::dsl::*;
// The left join below will return None in this case // The left join below will return None in this case
let user_id_join = self.my_user_id.unwrap_or(-1); let person_id_join = self.my_person_id.unwrap_or(-1);
let mut query = post::table let mut query = post::table
.inner_join(user_::table) .inner_join(person::table)
.inner_join(community::table) .inner_join(community::table)
.left_join( .left_join(
community_user_ban::table.on( community_person_ban::table.on(
post::community_id post::community_id
.eq(community_user_ban::community_id) .eq(community_person_ban::community_id)
.and(community_user_ban::user_id.eq(community::creator_id)), .and(community_person_ban::person_id.eq(community::creator_id)),
), ),
) )
.inner_join(post_aggregates::table) .inner_join(post_aggregates::table)
@ -264,35 +264,35 @@ impl<'a> PostQueryBuilder<'a> {
community_follower::table.on( community_follower::table.on(
post::community_id post::community_id
.eq(community_follower::community_id) .eq(community_follower::community_id)
.and(community_follower::user_id.eq(user_id_join)), .and(community_follower::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
post_saved::table.on( post_saved::table.on(
post::id post::id
.eq(post_saved::post_id) .eq(post_saved::post_id)
.and(post_saved::user_id.eq(user_id_join)), .and(post_saved::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
post_read::table.on( post_read::table.on(
post::id post::id
.eq(post_read::post_id) .eq(post_read::post_id)
.and(post_read::user_id.eq(user_id_join)), .and(post_read::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
post_like::table.on( post_like::table.on(
post::id post::id
.eq(post_like::post_id) .eq(post_like::post_id)
.and(post_like::user_id.eq(user_id_join)), .and(post_like::person_id.eq(person_id_join)),
), ),
) )
.select(( .select((
post::all_columns, post::all_columns,
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
Community::safe_columns_tuple(), Community::safe_columns_tuple(),
community_user_ban::all_columns.nullable(), community_person_ban::all_columns.nullable(),
post_aggregates::all_columns, post_aggregates::all_columns,
community_follower::all_columns.nullable(), community_follower::all_columns.nullable(),
post_saved::all_columns.nullable(), post_saved::all_columns.nullable(),
@ -302,7 +302,7 @@ impl<'a> PostQueryBuilder<'a> {
.into_boxed(); .into_boxed();
query = match self.listing_type { query = match self.listing_type {
ListingType::Subscribed => query.filter(community_follower::user_id.is_not_null()), // TODO could be this: and(community_follower::user_id.eq(user_id_join)), ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)),
ListingType::Local => query.filter(community::local.eq(true)), ListingType::Local => query.filter(community::local.eq(true)),
_ => query, _ => query,
}; };
@ -333,7 +333,7 @@ impl<'a> PostQueryBuilder<'a> {
); );
} }
// If its for a specific user, show the removed / deleted // If its for a specific person, show the removed / deleted
if let Some(creator_id) = self.creator_id { if let Some(creator_id) = self.creator_id {
query = query.filter(post::creator_id.eq(creator_id)); query = query.filter(post::creator_id.eq(creator_id));
} }
@ -433,7 +433,7 @@ mod tests {
ListingType, ListingType,
SortType, SortType,
}; };
use lemmy_db_schema::source::{community::*, post::*, user::*}; use lemmy_db_schema::source::{community::*, person::*, post::*};
use serial_test::serial; use serial_test::serial;
#[test] #[test]
@ -441,32 +441,22 @@ mod tests {
fn test_crud() { fn test_crud() {
let conn = establish_unpooled_connection(); let conn = establish_unpooled_connection();
let user_name = "tegan".to_string(); let person_name = "tegan".to_string();
let community_name = "test_community_3".to_string(); let community_name = "test_community_3".to_string();
let post_name = "test post 3".to_string(); let post_name = "test post 3".to_string();
let new_user = UserForm { let new_person = PersonForm {
name: user_name.to_owned(), name: person_name.to_owned(),
preferred_username: None, preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
banned: None,
deleted: None,
published: None, published: None,
updated: None, updated: None,
admin: false,
banned: Some(false),
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, actor_id: None,
bio: None, bio: None,
local: true, local: None,
private_key: None, private_key: None,
public_key: None, public_key: None,
last_refreshed_at: None, last_refreshed_at: None,
@ -474,13 +464,13 @@ mod tests {
shared_inbox_url: None, shared_inbox_url: None,
}; };
let inserted_user = User_::create(&conn, &new_user).unwrap(); let inserted_person = Person::create(&conn, &new_person).unwrap();
let new_community = CommunityForm { let new_community = CommunityForm {
name: community_name.to_owned(), name: community_name.to_owned(),
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
removed: None, removed: None,
deleted: None, deleted: None,
updated: None, updated: None,
@ -504,7 +494,7 @@ mod tests {
name: post_name.to_owned(), name: post_name.to_owned(),
url: None, url: None,
body: None, body: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
community_id: inserted_community.id, community_id: inserted_community.id,
removed: None, removed: None,
deleted: None, deleted: None,
@ -525,7 +515,7 @@ mod tests {
let post_like_form = PostLikeForm { let post_like_form = PostLikeForm {
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
score: 1, score: 1,
}; };
@ -534,38 +524,38 @@ mod tests {
let expected_post_like = PostLike { let expected_post_like = PostLike {
id: inserted_post_like.id, id: inserted_post_like.id,
post_id: inserted_post.id, post_id: inserted_post.id,
user_id: inserted_user.id, person_id: inserted_person.id,
published: inserted_post_like.published, published: inserted_post_like.published,
score: 1, score: 1,
}; };
let read_post_listings_with_user = PostQueryBuilder::create(&conn) let read_post_listings_with_person = PostQueryBuilder::create(&conn)
.listing_type(&ListingType::Community) .listing_type(&ListingType::Community)
.sort(&SortType::New) .sort(&SortType::New)
.community_id(inserted_community.id) .community_id(inserted_community.id)
.my_user_id(inserted_user.id) .my_person_id(inserted_person.id)
.list() .list()
.unwrap(); .unwrap();
let read_post_listings_no_user = PostQueryBuilder::create(&conn) let read_post_listings_no_person = PostQueryBuilder::create(&conn)
.listing_type(&ListingType::Community) .listing_type(&ListingType::Community)
.sort(&SortType::New) .sort(&SortType::New)
.community_id(inserted_community.id) .community_id(inserted_community.id)
.list() .list()
.unwrap(); .unwrap();
let read_post_listing_no_user = PostView::read(&conn, inserted_post.id, None).unwrap(); let read_post_listing_no_person = PostView::read(&conn, inserted_post.id, None).unwrap();
let read_post_listing_with_user = let read_post_listing_with_person =
PostView::read(&conn, inserted_post.id, Some(inserted_user.id)).unwrap(); PostView::read(&conn, inserted_post.id, Some(inserted_person.id)).unwrap();
let agg = PostAggregates::read(&conn, inserted_post.id).unwrap(); let agg = PostAggregates::read(&conn, inserted_post.id).unwrap();
// the non user version // the non person version
let expected_post_listing_no_user = PostView { let expected_post_listing_no_person = PostView {
post: Post { post: Post {
id: inserted_post.id, id: inserted_post.id,
name: post_name, name: post_name,
creator_id: inserted_user.id, creator_id: inserted_person.id,
url: None, url: None,
body: None, body: None,
published: inserted_post.published, published: inserted_post.published,
@ -584,22 +574,20 @@ mod tests {
local: true, local: true,
}, },
my_vote: None, my_vote: None,
creator: UserSafe { creator: PersonSafe {
id: inserted_user.id, id: inserted_person.id,
name: user_name, name: person_name,
preferred_username: None, preferred_username: None,
published: inserted_user.published, published: inserted_person.published,
avatar: None, avatar: None,
actor_id: inserted_user.actor_id.to_owned(), actor_id: inserted_person.actor_id.to_owned(),
local: true, local: true,
banned: false, banned: false,
deleted: false, deleted: false,
bio: None, bio: None,
banner: None, banner: None,
admin: false,
updated: None, updated: None,
matrix_user_id: None, inbox_url: inserted_person.inbox_url.to_owned(),
inbox_url: inserted_user.inbox_url.to_owned(),
shared_inbox_url: None, shared_inbox_url: None,
}, },
creator_banned_from_community: false, creator_banned_from_community: false,
@ -614,7 +602,7 @@ mod tests {
local: true, local: true,
title: "nada".to_owned(), title: "nada".to_owned(),
description: None, description: None,
creator_id: inserted_user.id, creator_id: inserted_person.id,
updated: None, updated: None,
banner: None, banner: None,
published: inserted_community.published, published: inserted_community.published,
@ -637,26 +625,32 @@ mod tests {
}; };
// TODO More needs to be added here // TODO More needs to be added here
let mut expected_post_listing_with_user = expected_post_listing_no_user.to_owned(); let mut expected_post_listing_with_user = expected_post_listing_no_person.to_owned();
expected_post_listing_with_user.my_vote = Some(1); expected_post_listing_with_user.my_vote = Some(1);
let like_removed = PostLike::remove(&conn, inserted_user.id, inserted_post.id).unwrap(); let like_removed = PostLike::remove(&conn, inserted_person.id, inserted_post.id).unwrap();
let num_deleted = Post::delete(&conn, inserted_post.id).unwrap(); let num_deleted = Post::delete(&conn, inserted_post.id).unwrap();
Community::delete(&conn, inserted_community.id).unwrap(); Community::delete(&conn, inserted_community.id).unwrap();
User_::delete(&conn, inserted_user.id).unwrap(); Person::delete(&conn, inserted_person.id).unwrap();
// The with user // The with user
assert_eq!( assert_eq!(
expected_post_listing_with_user, expected_post_listing_with_user,
read_post_listings_with_user[0] read_post_listings_with_person[0]
); );
assert_eq!(expected_post_listing_with_user, read_post_listing_with_user); assert_eq!(
assert_eq!(1, read_post_listings_with_user.len()); expected_post_listing_with_user,
read_post_listing_with_person
);
assert_eq!(1, read_post_listings_with_person.len());
// Without the user // Without the user
assert_eq!(expected_post_listing_no_user, read_post_listings_no_user[0]); assert_eq!(
assert_eq!(expected_post_listing_no_user, read_post_listing_no_user); expected_post_listing_no_person,
assert_eq!(1, read_post_listings_no_user.len()); 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());
// assert_eq!(expected_post, inserted_post); // assert_eq!(expected_post, inserted_post);
// assert_eq!(expected_post, updated_post); // assert_eq!(expected_post, updated_post);

View file

@ -1,10 +1,10 @@
use diesel::{pg::Pg, result::Error, *}; use diesel::{pg::Pg, result::Error, *};
use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec}; use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{private_message, user_, user_alias_1}, schema::{person, person_alias_1, private_message},
source::{ source::{
person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
private_message::PrivateMessage, private_message::PrivateMessage,
user::{UserAlias1, UserSafe, UserSafeAlias1, User_},
}, },
}; };
use log::debug; use log::debug;
@ -13,23 +13,23 @@ use serde::Serialize;
#[derive(Debug, PartialEq, Serialize, Clone)] #[derive(Debug, PartialEq, Serialize, Clone)]
pub struct PrivateMessageView { pub struct PrivateMessageView {
pub private_message: PrivateMessage, pub private_message: PrivateMessage,
pub creator: UserSafe, pub creator: PersonSafe,
pub recipient: UserSafeAlias1, pub recipient: PersonSafeAlias1,
} }
type PrivateMessageViewTuple = (PrivateMessage, UserSafe, UserSafeAlias1); type PrivateMessageViewTuple = (PrivateMessage, PersonSafe, PersonSafeAlias1);
impl PrivateMessageView { impl PrivateMessageView {
pub fn read(conn: &PgConnection, private_message_id: i32) -> Result<Self, Error> { pub fn read(conn: &PgConnection, private_message_id: i32) -> Result<Self, Error> {
let (private_message, creator, recipient) = private_message::table let (private_message, creator, recipient) = private_message::table
.find(private_message_id) .find(private_message_id)
.inner_join(user_::table.on(private_message::creator_id.eq(user_::id))) .inner_join(person::table.on(private_message::creator_id.eq(person::id)))
.inner_join(user_alias_1::table.on(private_message::recipient_id.eq(user_alias_1::id))) .inner_join(person_alias_1::table.on(private_message::recipient_id.eq(person_alias_1::id)))
.order_by(private_message::published.desc()) .order_by(private_message::published.desc())
.select(( .select((
private_message::all_columns, private_message::all_columns,
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
UserAlias1::safe_columns_tuple(), PersonAlias1::safe_columns_tuple(),
)) ))
.first::<PrivateMessageViewTuple>(conn)?; .first::<PrivateMessageViewTuple>(conn)?;
@ -77,12 +77,12 @@ impl<'a> PrivateMessageQueryBuilder<'a> {
pub fn list(self) -> Result<Vec<PrivateMessageView>, Error> { pub fn list(self) -> Result<Vec<PrivateMessageView>, Error> {
let mut query = private_message::table let mut query = private_message::table
.inner_join(user_::table.on(private_message::creator_id.eq(user_::id))) .inner_join(person::table.on(private_message::creator_id.eq(person::id)))
.inner_join(user_alias_1::table.on(private_message::recipient_id.eq(user_alias_1::id))) .inner_join(person_alias_1::table.on(private_message::recipient_id.eq(person_alias_1::id)))
.select(( .select((
private_message::all_columns, private_message::all_columns,
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
UserAlias1::safe_columns_tuple(), PersonAlias1::safe_columns_tuple(),
)) ))
.into_boxed(); .into_boxed();

View file

@ -1,10 +1,10 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{aggregates::site_aggregates::SiteAggregates, ToSafe}; use lemmy_db_queries::{aggregates::site_aggregates::SiteAggregates, ToSafe};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{site, site_aggregates, user_}, schema::{person, site, site_aggregates},
source::{ source::{
person::{Person, PersonSafe},
site::Site, site::Site,
user::{UserSafe, User_},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -12,21 +12,21 @@ use serde::Serialize;
#[derive(Debug, Serialize, Clone)] #[derive(Debug, Serialize, Clone)]
pub struct SiteView { pub struct SiteView {
pub site: Site, pub site: Site,
pub creator: UserSafe, pub creator: PersonSafe,
pub counts: SiteAggregates, pub counts: SiteAggregates,
} }
impl SiteView { impl SiteView {
pub fn read(conn: &PgConnection) -> Result<Self, Error> { pub fn read(conn: &PgConnection) -> Result<Self, Error> {
let (site, creator, counts) = site::table let (site, creator, counts) = site::table
.inner_join(user_::table) .inner_join(person::table)
.inner_join(site_aggregates::table) .inner_join(site_aggregates::table)
.select(( .select((
site::all_columns, site::all_columns,
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
site_aggregates::all_columns, site_aggregates::all_columns,
)) ))
.first::<(Site, UserSafe, SiteAggregates)>(conn)?; .first::<(Site, PersonSafe, SiteAggregates)>(conn)?;
Ok(SiteView { Ok(SiteView {
site, site,

View file

@ -1,10 +1,10 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{ToSafe, ViewToVec}; use lemmy_db_queries::{ToSafe, ViewToVec};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{community, community_follower, user_}, schema::{community, community_follower, person},
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
user::{UserSafe, User_}, person::{Person, PersonSafe},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -12,17 +12,20 @@ use serde::Serialize;
#[derive(Debug, Serialize, Clone)] #[derive(Debug, Serialize, Clone)]
pub struct CommunityFollowerView { pub struct CommunityFollowerView {
pub community: CommunitySafe, pub community: CommunitySafe,
pub follower: UserSafe, pub follower: PersonSafe,
} }
type CommunityFollowerViewTuple = (CommunitySafe, UserSafe); type CommunityFollowerViewTuple = (CommunitySafe, PersonSafe);
impl CommunityFollowerView { impl CommunityFollowerView {
pub fn for_community(conn: &PgConnection, community_id: i32) -> Result<Vec<Self>, Error> { pub fn for_community(conn: &PgConnection, community_id: i32) -> Result<Vec<Self>, Error> {
let res = community_follower::table let res = community_follower::table
.inner_join(community::table) .inner_join(community::table)
.inner_join(user_::table) .inner_join(person::table)
.select((Community::safe_columns_tuple(), User_::safe_columns_tuple())) .select((
Community::safe_columns_tuple(),
Person::safe_columns_tuple(),
))
.filter(community_follower::community_id.eq(community_id)) .filter(community_follower::community_id.eq(community_id))
.order_by(community_follower::published) .order_by(community_follower::published)
.load::<CommunityFollowerViewTuple>(conn)?; .load::<CommunityFollowerViewTuple>(conn)?;
@ -30,12 +33,15 @@ impl CommunityFollowerView {
Ok(Self::from_tuple_to_vec(res)) Ok(Self::from_tuple_to_vec(res))
} }
pub fn for_user(conn: &PgConnection, user_id: i32) -> Result<Vec<Self>, Error> { pub fn for_person(conn: &PgConnection, person_id: i32) -> Result<Vec<Self>, Error> {
let res = community_follower::table let res = community_follower::table
.inner_join(community::table) .inner_join(community::table)
.inner_join(user_::table) .inner_join(person::table)
.select((Community::safe_columns_tuple(), User_::safe_columns_tuple())) .select((
.filter(community_follower::user_id.eq(user_id)) Community::safe_columns_tuple(),
Person::safe_columns_tuple(),
))
.filter(community_follower::person_id.eq(person_id))
.order_by(community_follower::published) .order_by(community_follower::published)
.load::<CommunityFollowerViewTuple>(conn)?; .load::<CommunityFollowerViewTuple>(conn)?;

View file

@ -1,10 +1,10 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{ToSafe, ViewToVec}; use lemmy_db_queries::{ToSafe, ViewToVec};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{community, community_moderator, user_}, schema::{community, community_moderator, person},
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
user::{UserSafe, User_}, person::{Person, PersonSafe},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -12,17 +12,20 @@ use serde::Serialize;
#[derive(Debug, Serialize, Clone)] #[derive(Debug, Serialize, Clone)]
pub struct CommunityModeratorView { pub struct CommunityModeratorView {
pub community: CommunitySafe, pub community: CommunitySafe,
pub moderator: UserSafe, pub moderator: PersonSafe,
} }
type CommunityModeratorViewTuple = (CommunitySafe, UserSafe); type CommunityModeratorViewTuple = (CommunitySafe, PersonSafe);
impl CommunityModeratorView { impl CommunityModeratorView {
pub fn for_community(conn: &PgConnection, community_id: i32) -> Result<Vec<Self>, Error> { pub fn for_community(conn: &PgConnection, community_id: i32) -> Result<Vec<Self>, Error> {
let res = community_moderator::table let res = community_moderator::table
.inner_join(community::table) .inner_join(community::table)
.inner_join(user_::table) .inner_join(person::table)
.select((Community::safe_columns_tuple(), User_::safe_columns_tuple())) .select((
Community::safe_columns_tuple(),
Person::safe_columns_tuple(),
))
.filter(community_moderator::community_id.eq(community_id)) .filter(community_moderator::community_id.eq(community_id))
.order_by(community_moderator::published) .order_by(community_moderator::published)
.load::<CommunityModeratorViewTuple>(conn)?; .load::<CommunityModeratorViewTuple>(conn)?;
@ -30,12 +33,15 @@ impl CommunityModeratorView {
Ok(Self::from_tuple_to_vec(res)) Ok(Self::from_tuple_to_vec(res))
} }
pub fn for_user(conn: &PgConnection, user_id: i32) -> Result<Vec<Self>, Error> { pub fn for_person(conn: &PgConnection, person_id: i32) -> Result<Vec<Self>, Error> {
let res = community_moderator::table let res = community_moderator::table
.inner_join(community::table) .inner_join(community::table)
.inner_join(user_::table) .inner_join(person::table)
.select((Community::safe_columns_tuple(), User_::safe_columns_tuple())) .select((
.filter(community_moderator::user_id.eq(user_id)) Community::safe_columns_tuple(),
Person::safe_columns_tuple(),
))
.filter(community_moderator::person_id.eq(person_id))
.order_by(community_moderator::published) .order_by(community_moderator::published)
.load::<CommunityModeratorViewTuple>(conn)?; .load::<CommunityModeratorViewTuple>(conn)?;

View file

@ -0,0 +1,38 @@
use diesel::{result::Error, *};
use lemmy_db_queries::ToSafe;
use lemmy_db_schema::{
schema::{community, community_person_ban, person},
source::{
community::{Community, CommunitySafe},
person::{Person, PersonSafe},
},
};
use serde::Serialize;
#[derive(Debug, Serialize, Clone)]
pub struct CommunityPersonBanView {
pub community: CommunitySafe,
pub person: PersonSafe,
}
impl CommunityPersonBanView {
pub fn get(
conn: &PgConnection,
from_person_id: i32,
from_community_id: i32,
) -> Result<Self, Error> {
let (community, person) = community_person_ban::table
.inner_join(community::table)
.inner_join(person::table)
.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)
.first::<(CommunitySafe, PersonSafe)>(conn)?;
Ok(CommunityPersonBanView { community, person })
}
}

View file

@ -1,35 +0,0 @@
use diesel::{result::Error, *};
use lemmy_db_queries::ToSafe;
use lemmy_db_schema::{
schema::{community, community_user_ban, user_},
source::{
community::{Community, CommunitySafe},
user::{UserSafe, User_},
},
};
use serde::Serialize;
#[derive(Debug, Serialize, Clone)]
pub struct CommunityUserBanView {
pub community: CommunitySafe,
pub user: UserSafe,
}
impl CommunityUserBanView {
pub fn get(
conn: &PgConnection,
from_user_id: i32,
from_community_id: i32,
) -> Result<Self, Error> {
let (community, user) = community_user_ban::table
.inner_join(community::table)
.inner_join(user_::table)
.select((Community::safe_columns_tuple(), User_::safe_columns_tuple()))
.filter(community_user_ban::community_id.eq(from_community_id))
.filter(community_user_ban::user_id.eq(from_user_id))
.order_by(community_user_ban::published)
.first::<(CommunitySafe, UserSafe)>(conn)?;
Ok(CommunityUserBanView { community, user })
}
}

View file

@ -1,4 +1,4 @@
use crate::{community_moderator_view::CommunityModeratorView, user_view::UserViewSafe}; use crate::{community_moderator_view::CommunityModeratorView, person_view::PersonViewSafe};
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{ use lemmy_db_queries::{
aggregates::community_aggregates::CommunityAggregates, aggregates::community_aggregates::CommunityAggregates,
@ -12,10 +12,10 @@ use lemmy_db_queries::{
ViewToVec, ViewToVec,
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{community, community_aggregates, community_follower, user_}, schema::{community, community_aggregates, community_follower, person},
source::{ source::{
community::{Community, CommunityFollower, CommunitySafe}, community::{Community, CommunityFollower, CommunitySafe},
user::{UserSafe, User_}, person::{Person, PersonSafe},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -23,14 +23,14 @@ use serde::Serialize;
#[derive(Debug, Serialize, Clone)] #[derive(Debug, Serialize, Clone)]
pub struct CommunityView { pub struct CommunityView {
pub community: CommunitySafe, pub community: CommunitySafe,
pub creator: UserSafe, pub creator: PersonSafe,
pub subscribed: bool, pub subscribed: bool,
pub counts: CommunityAggregates, pub counts: CommunityAggregates,
} }
type CommunityViewTuple = ( type CommunityViewTuple = (
CommunitySafe, CommunitySafe,
UserSafe, PersonSafe,
CommunityAggregates, CommunityAggregates,
Option<CommunityFollower>, Option<CommunityFollower>,
); );
@ -39,25 +39,25 @@ impl CommunityView {
pub fn read( pub fn read(
conn: &PgConnection, conn: &PgConnection,
community_id: i32, community_id: i32,
my_user_id: Option<i32>, my_person_id: Option<i32>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
// The left join below will return None in this case // The left join below will return None in this case
let user_id_join = my_user_id.unwrap_or(-1); let person_id_join = my_person_id.unwrap_or(-1);
let (community, creator, counts, follower) = community::table let (community, creator, counts, follower) = community::table
.find(community_id) .find(community_id)
.inner_join(user_::table) .inner_join(person::table)
.inner_join(community_aggregates::table) .inner_join(community_aggregates::table)
.left_join( .left_join(
community_follower::table.on( community_follower::table.on(
community::id community::id
.eq(community_follower::community_id) .eq(community_follower::community_id)
.and(community_follower::user_id.eq(user_id_join)), .and(community_follower::person_id.eq(person_id_join)),
), ),
) )
.select(( .select((
Community::safe_columns_tuple(), Community::safe_columns_tuple(),
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
community_aggregates::all_columns, community_aggregates::all_columns,
community_follower::all_columns.nullable(), community_follower::all_columns.nullable(),
)) ))
@ -78,15 +78,16 @@ impl CommunityView {
&mut CommunityModeratorView::for_community(conn, community_id) &mut CommunityModeratorView::for_community(conn, community_id)
.map(|v| v.into_iter().map(|m| m.moderator.id).collect())?, .map(|v| v.into_iter().map(|m| m.moderator.id).collect())?,
); );
mods_and_admins mods_and_admins.append(
.append(&mut UserViewSafe::admins(conn).map(|v| v.into_iter().map(|a| a.user.id).collect())?); &mut PersonViewSafe::admins(conn).map(|v| v.into_iter().map(|a| a.person.id).collect())?,
);
Ok(mods_and_admins) Ok(mods_and_admins)
} }
pub fn is_mod_or_admin(conn: &PgConnection, user_id: i32, community_id: i32) -> bool { pub fn is_mod_or_admin(conn: &PgConnection, person_id: i32, community_id: i32) -> bool {
Self::community_mods_and_admins(conn, community_id) Self::community_mods_and_admins(conn, community_id)
.unwrap_or_default() .unwrap_or_default()
.contains(&user_id) .contains(&person_id)
} }
} }
@ -94,7 +95,7 @@ pub struct CommunityQueryBuilder<'a> {
conn: &'a PgConnection, conn: &'a PgConnection,
listing_type: &'a ListingType, listing_type: &'a ListingType,
sort: &'a SortType, sort: &'a SortType,
my_user_id: Option<i32>, my_person_id: Option<i32>,
show_nsfw: bool, show_nsfw: bool,
search_term: Option<String>, search_term: Option<String>,
page: Option<i64>, page: Option<i64>,
@ -105,7 +106,7 @@ impl<'a> CommunityQueryBuilder<'a> {
pub fn create(conn: &'a PgConnection) -> Self { pub fn create(conn: &'a PgConnection) -> Self {
CommunityQueryBuilder { CommunityQueryBuilder {
conn, conn,
my_user_id: None, my_person_id: None,
listing_type: &ListingType::All, listing_type: &ListingType::All,
sort: &SortType::Hot, sort: &SortType::Hot,
show_nsfw: true, show_nsfw: true,
@ -135,8 +136,8 @@ impl<'a> CommunityQueryBuilder<'a> {
self self
} }
pub fn my_user_id<T: MaybeOptional<i32>>(mut self, my_user_id: T) -> Self { pub fn my_person_id<T: MaybeOptional<i32>>(mut self, my_person_id: T) -> Self {
self.my_user_id = my_user_id.get_optional(); self.my_person_id = my_person_id.get_optional();
self self
} }
@ -152,21 +153,21 @@ impl<'a> CommunityQueryBuilder<'a> {
pub fn list(self) -> Result<Vec<CommunityView>, Error> { pub fn list(self) -> Result<Vec<CommunityView>, Error> {
// The left join below will return None in this case // The left join below will return None in this case
let user_id_join = self.my_user_id.unwrap_or(-1); let person_id_join = self.my_person_id.unwrap_or(-1);
let mut query = community::table let mut query = community::table
.inner_join(user_::table) .inner_join(person::table)
.inner_join(community_aggregates::table) .inner_join(community_aggregates::table)
.left_join( .left_join(
community_follower::table.on( community_follower::table.on(
community::id community::id
.eq(community_follower::community_id) .eq(community_follower::community_id)
.and(community_follower::user_id.eq(user_id_join)), .and(community_follower::person_id.eq(person_id_join)),
), ),
) )
.select(( .select((
Community::safe_columns_tuple(), Community::safe_columns_tuple(),
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
community_aggregates::all_columns, community_aggregates::all_columns,
community_follower::all_columns.nullable(), community_follower::all_columns.nullable(),
)) ))
@ -202,7 +203,7 @@ impl<'a> CommunityQueryBuilder<'a> {
}; };
query = match self.listing_type { query = match self.listing_type {
ListingType::Subscribed => query.filter(community_follower::user_id.is_not_null()), // TODO could be this: and(community_follower::user_id.eq(user_id_join)), ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)),
ListingType::Local => query.filter(community::local.eq(true)), ListingType::Local => query.filter(community::local.eq(true)),
_ => query, _ => query,
}; };

View file

@ -1,6 +1,6 @@
pub mod community_follower_view; pub mod community_follower_view;
pub mod community_moderator_view; pub mod community_moderator_view;
pub mod community_user_ban_view; pub mod community_person_ban_view;
pub mod community_view; pub mod community_view;
pub mod user_mention_view; pub mod person_mention_view;
pub mod user_view; pub mod person_view;

View file

@ -16,62 +16,62 @@ use lemmy_db_schema::{
comment_saved, comment_saved,
community, community,
community_follower, community_follower,
community_user_ban, community_person_ban,
person,
person_alias_1,
person_mention,
post, post,
user_,
user_alias_1,
user_mention,
}, },
source::{ source::{
comment::{Comment, CommentSaved}, comment::{Comment, CommentSaved},
community::{Community, CommunityFollower, CommunitySafe, CommunityUserBan}, community::{Community, CommunityFollower, CommunityPersonBan, CommunitySafe},
person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
person_mention::PersonMention,
post::Post, post::Post,
user::{UserAlias1, UserSafe, UserSafeAlias1, User_},
user_mention::UserMention,
}, },
}; };
use serde::Serialize; use serde::Serialize;
#[derive(Debug, PartialEq, Serialize, Clone)] #[derive(Debug, PartialEq, Serialize, Clone)]
pub struct UserMentionView { pub struct PersonMentionView {
pub user_mention: UserMention, pub person_mention: PersonMention,
pub comment: Comment, pub comment: Comment,
pub creator: UserSafe, pub creator: PersonSafe,
pub post: Post, pub post: Post,
pub community: CommunitySafe, pub community: CommunitySafe,
pub recipient: UserSafeAlias1, pub recipient: PersonSafeAlias1,
pub counts: CommentAggregates, pub counts: CommentAggregates,
pub creator_banned_from_community: bool, // Left Join to CommunityUserBan pub creator_banned_from_community: bool, // Left Join to CommunityPersonBan
pub subscribed: bool, // Left join to CommunityFollower pub subscribed: bool, // Left join to CommunityFollower
pub saved: bool, // Left join to CommentSaved pub saved: bool, // Left join to CommentSaved
pub my_vote: Option<i16>, // Left join to CommentLike pub my_vote: Option<i16>, // Left join to CommentLike
} }
type UserMentionViewTuple = ( type PersonMentionViewTuple = (
UserMention, PersonMention,
Comment, Comment,
UserSafe, PersonSafe,
Post, Post,
CommunitySafe, CommunitySafe,
UserSafeAlias1, PersonSafeAlias1,
CommentAggregates, CommentAggregates,
Option<CommunityUserBan>, Option<CommunityPersonBan>,
Option<CommunityFollower>, Option<CommunityFollower>,
Option<CommentSaved>, Option<CommentSaved>,
Option<i16>, Option<i16>,
); );
impl UserMentionView { impl PersonMentionView {
pub fn read( pub fn read(
conn: &PgConnection, conn: &PgConnection,
user_mention_id: i32, person_mention_id: i32,
my_user_id: Option<i32>, my_person_id: Option<i32>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
// The left join below will return None in this case // The left join below will return None in this case
let user_id_join = my_user_id.unwrap_or(-1); let person_id_join = my_person_id.unwrap_or(-1);
let ( let (
user_mention, person_mention,
comment, comment,
creator, creator,
post, post,
@ -82,59 +82,59 @@ impl UserMentionView {
subscribed, subscribed,
saved, saved,
my_vote, my_vote,
) = user_mention::table ) = person_mention::table
.find(user_mention_id) .find(person_mention_id)
.inner_join(comment::table) .inner_join(comment::table)
.inner_join(user_::table.on(comment::creator_id.eq(user_::id))) .inner_join(person::table.on(comment::creator_id.eq(person::id)))
.inner_join(post::table.on(comment::post_id.eq(post::id))) .inner_join(post::table.on(comment::post_id.eq(post::id)))
.inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(user_alias_1::table) .inner_join(person_alias_1::table)
.inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id))) .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id)))
.left_join( .left_join(
community_user_ban::table.on( community_person_ban::table.on(
community::id community::id
.eq(community_user_ban::community_id) .eq(community_person_ban::community_id)
.and(community_user_ban::user_id.eq(comment::creator_id)), .and(community_person_ban::person_id.eq(comment::creator_id)),
), ),
) )
.left_join( .left_join(
community_follower::table.on( community_follower::table.on(
post::community_id post::community_id
.eq(community_follower::community_id) .eq(community_follower::community_id)
.and(community_follower::user_id.eq(user_id_join)), .and(community_follower::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
comment_saved::table.on( comment_saved::table.on(
comment::id comment::id
.eq(comment_saved::comment_id) .eq(comment_saved::comment_id)
.and(comment_saved::user_id.eq(user_id_join)), .and(comment_saved::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
comment_like::table.on( comment_like::table.on(
comment::id comment::id
.eq(comment_like::comment_id) .eq(comment_like::comment_id)
.and(comment_like::user_id.eq(user_id_join)), .and(comment_like::person_id.eq(person_id_join)),
), ),
) )
.select(( .select((
user_mention::all_columns, person_mention::all_columns,
comment::all_columns, comment::all_columns,
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
post::all_columns, post::all_columns,
Community::safe_columns_tuple(), Community::safe_columns_tuple(),
UserAlias1::safe_columns_tuple(), PersonAlias1::safe_columns_tuple(),
comment_aggregates::all_columns, comment_aggregates::all_columns,
community_user_ban::all_columns.nullable(), community_person_ban::all_columns.nullable(),
community_follower::all_columns.nullable(), community_follower::all_columns.nullable(),
comment_saved::all_columns.nullable(), comment_saved::all_columns.nullable(),
comment_like::score.nullable(), comment_like::score.nullable(),
)) ))
.first::<UserMentionViewTuple>(conn)?; .first::<PersonMentionViewTuple>(conn)?;
Ok(UserMentionView { Ok(PersonMentionView {
user_mention, person_mention,
comment, comment,
creator, creator,
post, post,
@ -149,9 +149,9 @@ impl UserMentionView {
} }
} }
pub struct UserMentionQueryBuilder<'a> { pub struct PersonMentionQueryBuilder<'a> {
conn: &'a PgConnection, conn: &'a PgConnection,
my_user_id: Option<i32>, my_person_id: Option<i32>,
recipient_id: Option<i32>, recipient_id: Option<i32>,
sort: &'a SortType, sort: &'a SortType,
unread_only: bool, unread_only: bool,
@ -159,11 +159,11 @@ pub struct UserMentionQueryBuilder<'a> {
limit: Option<i64>, limit: Option<i64>,
} }
impl<'a> UserMentionQueryBuilder<'a> { impl<'a> PersonMentionQueryBuilder<'a> {
pub fn create(conn: &'a PgConnection) -> Self { pub fn create(conn: &'a PgConnection) -> Self {
UserMentionQueryBuilder { PersonMentionQueryBuilder {
conn, conn,
my_user_id: None, my_person_id: None,
recipient_id: None, recipient_id: None,
sort: &SortType::New, sort: &SortType::New,
unread_only: false, unread_only: false,
@ -187,8 +187,8 @@ impl<'a> UserMentionQueryBuilder<'a> {
self self
} }
pub fn my_user_id<T: MaybeOptional<i32>>(mut self, my_user_id: T) -> Self { pub fn my_person_id<T: MaybeOptional<i32>>(mut self, my_person_id: T) -> Self {
self.my_user_id = my_user_id.get_optional(); self.my_person_id = my_person_id.get_optional();
self self
} }
@ -202,56 +202,56 @@ impl<'a> UserMentionQueryBuilder<'a> {
self self
} }
pub fn list(self) -> Result<Vec<UserMentionView>, Error> { pub fn list(self) -> Result<Vec<PersonMentionView>, Error> {
use diesel::dsl::*; use diesel::dsl::*;
// The left join below will return None in this case // The left join below will return None in this case
let user_id_join = self.my_user_id.unwrap_or(-1); let person_id_join = self.my_person_id.unwrap_or(-1);
let mut query = user_mention::table let mut query = person_mention::table
.inner_join(comment::table) .inner_join(comment::table)
.inner_join(user_::table.on(comment::creator_id.eq(user_::id))) .inner_join(person::table.on(comment::creator_id.eq(person::id)))
.inner_join(post::table.on(comment::post_id.eq(post::id))) .inner_join(post::table.on(comment::post_id.eq(post::id)))
.inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(user_alias_1::table) .inner_join(person_alias_1::table)
.inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id))) .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id)))
.left_join( .left_join(
community_user_ban::table.on( community_person_ban::table.on(
community::id community::id
.eq(community_user_ban::community_id) .eq(community_person_ban::community_id)
.and(community_user_ban::user_id.eq(comment::creator_id)), .and(community_person_ban::person_id.eq(comment::creator_id)),
), ),
) )
.left_join( .left_join(
community_follower::table.on( community_follower::table.on(
post::community_id post::community_id
.eq(community_follower::community_id) .eq(community_follower::community_id)
.and(community_follower::user_id.eq(user_id_join)), .and(community_follower::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
comment_saved::table.on( comment_saved::table.on(
comment::id comment::id
.eq(comment_saved::comment_id) .eq(comment_saved::comment_id)
.and(comment_saved::user_id.eq(user_id_join)), .and(comment_saved::person_id.eq(person_id_join)),
), ),
) )
.left_join( .left_join(
comment_like::table.on( comment_like::table.on(
comment::id comment::id
.eq(comment_like::comment_id) .eq(comment_like::comment_id)
.and(comment_like::user_id.eq(user_id_join)), .and(comment_like::person_id.eq(person_id_join)),
), ),
) )
.select(( .select((
user_mention::all_columns, person_mention::all_columns,
comment::all_columns, comment::all_columns,
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
post::all_columns, post::all_columns,
Community::safe_columns_tuple(), Community::safe_columns_tuple(),
UserAlias1::safe_columns_tuple(), PersonAlias1::safe_columns_tuple(),
comment_aggregates::all_columns, comment_aggregates::all_columns,
community_user_ban::all_columns.nullable(), community_person_ban::all_columns.nullable(),
community_follower::all_columns.nullable(), community_follower::all_columns.nullable(),
comment_saved::all_columns.nullable(), comment_saved::all_columns.nullable(),
comment_like::score.nullable(), comment_like::score.nullable(),
@ -259,11 +259,11 @@ impl<'a> UserMentionQueryBuilder<'a> {
.into_boxed(); .into_boxed();
if let Some(recipient_id) = self.recipient_id { if let Some(recipient_id) = self.recipient_id {
query = query.filter(user_mention::recipient_id.eq(recipient_id)); query = query.filter(person_mention::recipient_id.eq(recipient_id));
} }
if self.unread_only { if self.unread_only {
query = query.filter(user_mention::read.eq(false)); query = query.filter(person_mention::read.eq(false));
} }
query = match self.sort { query = match self.sort {
@ -293,19 +293,19 @@ impl<'a> UserMentionQueryBuilder<'a> {
let res = query let res = query
.limit(limit) .limit(limit)
.offset(offset) .offset(offset)
.load::<UserMentionViewTuple>(self.conn)?; .load::<PersonMentionViewTuple>(self.conn)?;
Ok(UserMentionView::from_tuple_to_vec(res)) Ok(PersonMentionView::from_tuple_to_vec(res))
} }
} }
impl ViewToVec for UserMentionView { impl ViewToVec for PersonMentionView {
type DbTuple = UserMentionViewTuple; type DbTuple = PersonMentionViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .iter()
.map(|a| Self { .map(|a| Self {
user_mention: a.0.to_owned(), person_mention: a.0.to_owned(),
comment: a.1.to_owned(), comment: a.1.to_owned(),
creator: a.2.to_owned(), creator: a.2.to_owned(),
post: a.3.to_owned(), post: a.3.to_owned(),

View file

@ -0,0 +1,152 @@
use diesel::{dsl::*, result::Error, *};
use lemmy_db_queries::{
aggregates::person_aggregates::PersonAggregates,
fuzzy_search,
limit_and_offset,
MaybeOptional,
SortType,
ToSafe,
ViewToVec,
};
use lemmy_db_schema::{
schema::{local_user, person, person_aggregates},
source::person::{Person, PersonSafe},
};
use serde::Serialize;
#[derive(Debug, Serialize, Clone)]
pub struct PersonViewSafe {
pub person: PersonSafe,
pub counts: PersonAggregates,
}
type PersonViewSafeTuple = (PersonSafe, PersonAggregates);
impl PersonViewSafe {
pub fn read(conn: &PgConnection, id: i32) -> Result<Self, Error> {
let (person, counts) = person::table
.find(id)
.inner_join(person_aggregates::table)
.select((Person::safe_columns_tuple(), person_aggregates::all_columns))
.first::<PersonViewSafeTuple>(conn)?;
Ok(Self { person, counts })
}
pub fn admins(conn: &PgConnection) -> Result<Vec<Self>, Error> {
let admins = person::table
.inner_join(person_aggregates::table)
.inner_join(local_user::table)
.select((Person::safe_columns_tuple(), person_aggregates::all_columns))
.filter(local_user::admin.eq(true))
.order_by(person::published)
.load::<PersonViewSafeTuple>(conn)?;
Ok(Self::from_tuple_to_vec(admins))
}
pub fn banned(conn: &PgConnection) -> Result<Vec<Self>, Error> {
let banned = person::table
.inner_join(person_aggregates::table)
.select((Person::safe_columns_tuple(), person_aggregates::all_columns))
.filter(person::banned.eq(true))
.load::<PersonViewSafeTuple>(conn)?;
Ok(Self::from_tuple_to_vec(banned))
}
}
pub struct PersonQueryBuilder<'a> {
conn: &'a PgConnection,
sort: &'a SortType,
search_term: Option<String>,
page: Option<i64>,
limit: Option<i64>,
}
impl<'a> PersonQueryBuilder<'a> {
pub fn create(conn: &'a PgConnection) -> Self {
PersonQueryBuilder {
conn,
search_term: None,
sort: &SortType::Hot,
page: None,
limit: None,
}
}
pub fn sort(mut self, sort: &'a SortType) -> Self {
self.sort = sort;
self
}
pub fn search_term<T: MaybeOptional<String>>(mut self, search_term: T) -> Self {
self.search_term = search_term.get_optional();
self
}
pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
self.page = page.get_optional();
self
}
pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
self.limit = limit.get_optional();
self
}
pub fn list(self) -> Result<Vec<PersonViewSafe>, Error> {
let mut query = person::table
.inner_join(person_aggregates::table)
.select((Person::safe_columns_tuple(), person_aggregates::all_columns))
.into_boxed();
if let Some(search_term) = self.search_term {
query = query.filter(person::name.ilike(fuzzy_search(&search_term)));
}
query = match self.sort {
SortType::Hot => query
.order_by(person_aggregates::comment_score.desc())
.then_order_by(person::published.desc()),
SortType::Active => query
.order_by(person_aggregates::comment_score.desc())
.then_order_by(person::published.desc()),
SortType::New | SortType::MostComments | SortType::NewComments => {
query.order_by(person::published.desc())
}
SortType::TopAll => query.order_by(person_aggregates::comment_score.desc()),
SortType::TopYear => query
.filter(person::published.gt(now - 1.years()))
.order_by(person_aggregates::comment_score.desc()),
SortType::TopMonth => query
.filter(person::published.gt(now - 1.months()))
.order_by(person_aggregates::comment_score.desc()),
SortType::TopWeek => query
.filter(person::published.gt(now - 1.weeks()))
.order_by(person_aggregates::comment_score.desc()),
SortType::TopDay => query
.filter(person::published.gt(now - 1.days()))
.order_by(person_aggregates::comment_score.desc()),
};
let (limit, offset) = limit_and_offset(self.page, self.limit);
query = query.limit(limit).offset(offset);
let res = query.load::<PersonViewSafeTuple>(self.conn)?;
Ok(PersonViewSafe::from_tuple_to_vec(res))
}
}
impl ViewToVec for PersonViewSafe {
type DbTuple = PersonViewSafeTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items
.iter()
.map(|a| Self {
person: a.0.to_owned(),
counts: a.1.to_owned(),
})
.collect::<Vec<Self>>()
}
}

View file

@ -1,151 +0,0 @@
use diesel::{dsl::*, result::Error, *};
use lemmy_db_queries::{
aggregates::user_aggregates::UserAggregates,
fuzzy_search,
limit_and_offset,
MaybeOptional,
SortType,
ToSafe,
ViewToVec,
};
use lemmy_db_schema::{
schema::{user_, user_aggregates},
source::user::{UserSafe, User_},
};
use serde::Serialize;
#[derive(Debug, Serialize, Clone)]
pub struct UserViewSafe {
pub user: UserSafe,
pub counts: UserAggregates,
}
type UserViewSafeTuple = (UserSafe, UserAggregates);
impl UserViewSafe {
pub fn read(conn: &PgConnection, id: i32) -> Result<Self, Error> {
let (user, counts) = user_::table
.find(id)
.inner_join(user_aggregates::table)
.select((User_::safe_columns_tuple(), user_aggregates::all_columns))
.first::<UserViewSafeTuple>(conn)?;
Ok(Self { user, counts })
}
pub fn admins(conn: &PgConnection) -> Result<Vec<Self>, Error> {
let admins = user_::table
.inner_join(user_aggregates::table)
.select((User_::safe_columns_tuple(), user_aggregates::all_columns))
.filter(user_::admin.eq(true))
.order_by(user_::published)
.load::<UserViewSafeTuple>(conn)?;
Ok(Self::from_tuple_to_vec(admins))
}
pub fn banned(conn: &PgConnection) -> Result<Vec<Self>, Error> {
let banned = user_::table
.inner_join(user_aggregates::table)
.select((User_::safe_columns_tuple(), user_aggregates::all_columns))
.filter(user_::banned.eq(true))
.load::<UserViewSafeTuple>(conn)?;
Ok(Self::from_tuple_to_vec(banned))
}
}
pub struct UserQueryBuilder<'a> {
conn: &'a PgConnection,
sort: &'a SortType,
search_term: Option<String>,
page: Option<i64>,
limit: Option<i64>,
}
impl<'a> UserQueryBuilder<'a> {
pub fn create(conn: &'a PgConnection) -> Self {
UserQueryBuilder {
conn,
search_term: None,
sort: &SortType::Hot,
page: None,
limit: None,
}
}
pub fn sort(mut self, sort: &'a SortType) -> Self {
self.sort = sort;
self
}
pub fn search_term<T: MaybeOptional<String>>(mut self, search_term: T) -> Self {
self.search_term = search_term.get_optional();
self
}
pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
self.page = page.get_optional();
self
}
pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
self.limit = limit.get_optional();
self
}
pub fn list(self) -> Result<Vec<UserViewSafe>, Error> {
let mut query = user_::table
.inner_join(user_aggregates::table)
.select((User_::safe_columns_tuple(), user_aggregates::all_columns))
.into_boxed();
if let Some(search_term) = self.search_term {
query = query.filter(user_::name.ilike(fuzzy_search(&search_term)));
}
query = match self.sort {
SortType::Hot => query
.order_by(user_aggregates::comment_score.desc())
.then_order_by(user_::published.desc()),
SortType::Active => query
.order_by(user_aggregates::comment_score.desc())
.then_order_by(user_::published.desc()),
SortType::New | SortType::MostComments | SortType::NewComments => {
query.order_by(user_::published.desc())
}
SortType::TopAll => query.order_by(user_aggregates::comment_score.desc()),
SortType::TopYear => query
.filter(user_::published.gt(now - 1.years()))
.order_by(user_aggregates::comment_score.desc()),
SortType::TopMonth => query
.filter(user_::published.gt(now - 1.months()))
.order_by(user_aggregates::comment_score.desc()),
SortType::TopWeek => query
.filter(user_::published.gt(now - 1.weeks()))
.order_by(user_aggregates::comment_score.desc()),
SortType::TopDay => query
.filter(user_::published.gt(now - 1.days()))
.order_by(user_aggregates::comment_score.desc()),
};
let (limit, offset) = limit_and_offset(self.page, self.limit);
query = query.limit(limit).offset(offset);
let res = query.load::<UserViewSafeTuple>(self.conn)?;
Ok(UserViewSafe::from_tuple_to_vec(res))
}
}
impl ViewToVec for UserViewSafe {
type DbTuple = UserViewSafeTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items
.iter()
.map(|a| Self {
user: a.0.to_owned(),
counts: a.1.to_owned(),
})
.collect::<Vec<Self>>()
}
}

View file

@ -1,11 +1,11 @@
use diesel::{result::Error, *}; use diesel::{result::Error, *};
use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec};
use lemmy_db_schema::{ use lemmy_db_schema::{
schema::{community, mod_add_community, user_, user_alias_1}, schema::{community, mod_add_community, person, person_alias_1},
source::{ source::{
community::{Community, CommunitySafe}, community::{Community, CommunitySafe},
moderator::ModAddCommunity, moderator::ModAddCommunity,
user::{UserAlias1, UserSafe, UserSafeAlias1, User_}, person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
}, },
}; };
use serde::Serialize; use serde::Serialize;
@ -13,35 +13,37 @@ use serde::Serialize;
#[derive(Debug, Serialize, Clone)] #[derive(Debug, Serialize, Clone)]
pub struct ModAddCommunityView { pub struct ModAddCommunityView {
pub mod_add_community: ModAddCommunity, pub mod_add_community: ModAddCommunity,
pub moderator: UserSafe, pub moderator: PersonSafe,
pub community: CommunitySafe, pub community: CommunitySafe,
pub modded_user: UserSafeAlias1, pub modded_person: PersonSafeAlias1,
} }
type ModAddCommunityViewTuple = (ModAddCommunity, UserSafe, CommunitySafe, UserSafeAlias1); type ModAddCommunityViewTuple = (ModAddCommunity, PersonSafe, CommunitySafe, PersonSafeAlias1);
impl ModAddCommunityView { impl ModAddCommunityView {
pub fn list( pub fn list(
conn: &PgConnection, conn: &PgConnection,
community_id: Option<i32>, community_id: Option<i32>,
mod_user_id: Option<i32>, mod_person_id: Option<i32>,
page: Option<i64>, page: Option<i64>,
limit: Option<i64>, limit: Option<i64>,
) -> Result<Vec<Self>, Error> { ) -> Result<Vec<Self>, Error> {
let mut query = mod_add_community::table let mut query = mod_add_community::table
.inner_join(user_::table.on(mod_add_community::mod_user_id.eq(user_::id))) .inner_join(person::table.on(mod_add_community::mod_person_id.eq(person::id)))
.inner_join(community::table) .inner_join(community::table)
.inner_join(user_alias_1::table.on(mod_add_community::other_user_id.eq(user_alias_1::id))) .inner_join(
person_alias_1::table.on(mod_add_community::other_person_id.eq(person_alias_1::id)),
)
.select(( .select((
mod_add_community::all_columns, mod_add_community::all_columns,
User_::safe_columns_tuple(), Person::safe_columns_tuple(),
Community::safe_columns_tuple(), Community::safe_columns_tuple(),
UserAlias1::safe_columns_tuple(), PersonAlias1::safe_columns_tuple(),
)) ))
.into_boxed(); .into_boxed();
if let Some(mod_user_id) = mod_user_id { if let Some(mod_person_id) = mod_person_id {
query = query.filter(mod_add_community::mod_user_id.eq(mod_user_id)); query = query.filter(mod_add_community::mod_person_id.eq(mod_person_id));
}; };
if let Some(community_id) = community_id { if let Some(community_id) = community_id {
@ -69,7 +71,7 @@ impl ViewToVec for ModAddCommunityView {
mod_add_community: a.0.to_owned(), mod_add_community: a.0.to_owned(),
moderator: a.1.to_owned(), moderator: a.1.to_owned(),
community: a.2.to_owned(), community: a.2.to_owned(),
modded_user: a.3.to_owned(), modded_person: a.3.to_owned(),
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

Some files were not shown because too many files have changed in this diff Show more