Added async to views and schema.

This commit is contained in:
Dessalines 2022-10-23 18:19:19 -04:00
parent c631cbd6c8
commit 39294a051c
53 changed files with 1507 additions and 793 deletions

View file

@ -38,8 +38,8 @@ once_cell = { version = "1.15.0", optional = true }
diesel_ltree = "0.3.0"
typed-builder = "0.10.0"
async-trait = "0.1.58"
tokio = "1.21.2"
[dev-dependencies]
serial_test = "0.9.0"
tokio = "1.21.2"

View file

@ -2,14 +2,18 @@ use crate::{
aggregates::structs::CommentAggregates,
newtypes::CommentId,
schema::comment_aggregates,
utils::{get_conn, DbPool},
};
use diesel::{result::Error, *};
use diesel::{result::Error, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
impl CommentAggregates {
pub fn read(conn: &mut PgConnection, comment_id: CommentId) -> Result<Self, Error> {
pub async fn read(pool: &DbPool, comment_id: CommentId) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
comment_aggregates::table
.filter(comment_aggregates::comment_id.eq(comment_id))
.first::<Self>(conn)
.await
}
}
@ -42,7 +46,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_person = Person::create(conn, &new_person).unwrap();
let inserted_person = Person::create(pool, &new_person).await.unwrap();
let another_person = PersonInsertForm::builder()
.name("jerry_comment_agg".into())
@ -50,7 +54,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let another_inserted_person = Person::create(conn, &another_person).unwrap();
let another_inserted_person = Person::create(pool, &another_person).await.unwrap();
let new_community = CommunityInsertForm::builder()
.name("TIL_comment_agg".into())
@ -59,7 +63,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_community = Community::create(conn, &new_community).unwrap();
let inserted_community = Community::create(pool, &new_community).await.unwrap();
let new_post = PostInsertForm::builder()
.name("A test post".into())
@ -67,7 +71,7 @@ mod tests {
.community_id(inserted_community.id)
.build();
let inserted_post = Post::create(conn, &new_post).unwrap();
let inserted_post = Post::create(pool, &new_post).await.unwrap();
let comment_form = CommentInsertForm::builder()
.content("A test comment".into())
@ -75,7 +79,7 @@ mod tests {
.post_id(inserted_post.id)
.build();
let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
let child_comment_form = CommentInsertForm::builder()
.content("A test comment".into())
@ -84,7 +88,9 @@ mod tests {
.build();
let _inserted_child_comment =
Comment::create(conn, &child_comment_form, Some(&inserted_comment.path)).unwrap();
Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
.await
.unwrap();
let comment_like = CommentLikeForm {
comment_id: inserted_comment.id,
@ -93,9 +99,11 @@ mod tests {
score: 1,
};
CommentLike::like(conn, &comment_like).unwrap();
CommentLike::like(pool, &comment_like).await.unwrap();
let comment_aggs_before_delete = CommentAggregates::read(conn, inserted_comment.id).unwrap();
let comment_aggs_before_delete = CommentAggregates::read(pool, inserted_comment.id)
.await
.unwrap();
assert_eq!(1, comment_aggs_before_delete.score);
assert_eq!(1, comment_aggs_before_delete.upvotes);
@ -109,37 +117,47 @@ mod tests {
score: -1,
};
CommentLike::like(conn, &comment_dislike).unwrap();
CommentLike::like(pool, &comment_dislike).await.unwrap();
let comment_aggs_after_dislike = CommentAggregates::read(conn, inserted_comment.id).unwrap();
let comment_aggs_after_dislike = CommentAggregates::read(pool, inserted_comment.id)
.await
.unwrap();
assert_eq!(0, comment_aggs_after_dislike.score);
assert_eq!(1, comment_aggs_after_dislike.upvotes);
assert_eq!(1, comment_aggs_after_dislike.downvotes);
// Remove the first comment like
CommentLike::remove(conn, inserted_person.id, inserted_comment.id).unwrap();
let after_like_remove = CommentAggregates::read(conn, inserted_comment.id).unwrap();
CommentLike::remove(pool, inserted_person.id, inserted_comment.id)
.await
.unwrap();
let after_like_remove = CommentAggregates::read(pool, inserted_comment.id)
.await
.unwrap();
assert_eq!(-1, after_like_remove.score);
assert_eq!(0, after_like_remove.upvotes);
assert_eq!(1, after_like_remove.downvotes);
// Remove the parent post
Post::delete(conn, inserted_post.id).unwrap();
Post::delete(pool, inserted_post.id).await.unwrap();
// Should be none found, since the post was deleted
let after_delete = CommentAggregates::read(conn, inserted_comment.id);
let after_delete = CommentAggregates::read(pool, inserted_comment.id).await;
assert!(after_delete.is_err());
// This should delete all the associated rows, and fire triggers
Person::delete(conn, another_inserted_person.id).unwrap();
let person_num_deleted = Person::delete(conn, inserted_person.id).unwrap();
Person::delete(pool, another_inserted_person.id)
.await
.unwrap();
let person_num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
assert_eq!(1, person_num_deleted);
// Delete the community
let community_num_deleted = Community::delete(conn, inserted_community.id).unwrap();
let community_num_deleted = Community::delete(pool, inserted_community.id)
.await
.unwrap();
assert_eq!(1, community_num_deleted);
Instance::delete(conn, inserted_instance.id).unwrap();
Instance::delete(pool, inserted_instance.id).await.unwrap();
}
}

View file

@ -2,14 +2,18 @@ use crate::{
aggregates::structs::CommunityAggregates,
newtypes::CommunityId,
schema::community_aggregates,
utils::{get_conn, DbPool},
};
use diesel::{result::Error, *};
use diesel::{result::Error, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
impl CommunityAggregates {
pub fn read(conn: &mut PgConnection, community_id: CommunityId) -> Result<Self, Error> {
pub async fn read(pool: &DbPool, community_id: CommunityId) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
community_aggregates::table
.filter(community_aggregates::community_id.eq(community_id))
.first::<Self>(conn)
.await
}
}
@ -25,16 +29,16 @@ mod tests {
post::{Post, PostInsertForm},
},
traits::{Crud, Followable},
utils::establish_unpooled_connection,
utils::build_db_pool_for_tests,
};
use serial_test::serial;
#[test]
#[tokio::test]
#[serial]
fn test_crud() {
let conn = &mut establish_unpooled_connection();
async fn test_crud() {
let pool = &build_db_pool_for_tests().await;
let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
let new_person = PersonInsertForm::builder()
.name("thommy_community_agg".into())
@ -42,7 +46,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_person = Person::create(conn, &new_person).unwrap();
let inserted_person = Person::create(pool, &new_person).await.unwrap();
let another_person = PersonInsertForm::builder()
.name("jerry_community_agg".into())
@ -50,7 +54,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let another_inserted_person = Person::create(conn, &another_person).unwrap();
let another_inserted_person = Person::create(pool, &another_person).await.unwrap();
let new_community = CommunityInsertForm::builder()
.name("TIL_community_agg".into())
@ -59,7 +63,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_community = Community::create(conn, &new_community).unwrap();
let inserted_community = Community::create(pool, &new_community).await.unwrap();
let another_community = CommunityInsertForm::builder()
.name("TIL_community_agg_2".into())
@ -68,7 +72,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let another_inserted_community = Community::create(conn, &another_community).unwrap();
let another_inserted_community = Community::create(pool, &another_community).await.unwrap();
let first_person_follow = CommunityFollowerForm {
community_id: inserted_community.id,
@ -76,7 +80,9 @@ mod tests {
pending: false,
};
CommunityFollower::follow(conn, &first_person_follow).unwrap();
CommunityFollower::follow(pool, &first_person_follow)
.await
.unwrap();
let second_person_follow = CommunityFollowerForm {
community_id: inserted_community.id,
@ -84,7 +90,9 @@ mod tests {
pending: false,
};
CommunityFollower::follow(conn, &second_person_follow).unwrap();
CommunityFollower::follow(pool, &second_person_follow)
.await
.unwrap();
let another_community_follow = CommunityFollowerForm {
community_id: another_inserted_community.id,
@ -92,7 +100,9 @@ mod tests {
pending: false,
};
CommunityFollower::follow(conn, &another_community_follow).unwrap();
CommunityFollower::follow(pool, &another_community_follow)
.await
.unwrap();
let new_post = PostInsertForm::builder()
.name("A test post".into())
@ -100,7 +110,7 @@ mod tests {
.community_id(inserted_community.id)
.build();
let inserted_post = Post::create(conn, &new_post).unwrap();
let inserted_post = Post::create(pool, &new_post).await.unwrap();
let comment_form = CommentInsertForm::builder()
.content("A test comment".into())
@ -108,7 +118,7 @@ mod tests {
.post_id(inserted_post.id)
.build();
let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
let child_comment_form = CommentInsertForm::builder()
.content("A test comment".into())
@ -117,57 +127,78 @@ mod tests {
.build();
let _inserted_child_comment =
Comment::create(conn, &child_comment_form, Some(&inserted_comment.path)).unwrap();
Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
.await
.unwrap();
let community_aggregates_before_delete =
CommunityAggregates::read(conn, inserted_community.id).unwrap();
let community_aggregates_before_delete = CommunityAggregates::read(pool, inserted_community.id)
.await
.unwrap();
assert_eq!(2, community_aggregates_before_delete.subscribers);
assert_eq!(1, community_aggregates_before_delete.posts);
assert_eq!(2, community_aggregates_before_delete.comments);
// Test the other community
let another_community_aggs =
CommunityAggregates::read(conn, another_inserted_community.id).unwrap();
let another_community_aggs = CommunityAggregates::read(pool, another_inserted_community.id)
.await
.unwrap();
assert_eq!(1, another_community_aggs.subscribers);
assert_eq!(0, another_community_aggs.posts);
assert_eq!(0, another_community_aggs.comments);
// Unfollow test
CommunityFollower::unfollow(conn, &second_person_follow).unwrap();
let after_unfollow = CommunityAggregates::read(conn, inserted_community.id).unwrap();
CommunityFollower::unfollow(pool, &second_person_follow)
.await
.unwrap();
let after_unfollow = CommunityAggregates::read(pool, inserted_community.id)
.await
.unwrap();
assert_eq!(1, after_unfollow.subscribers);
// Follow again just for the later tests
CommunityFollower::follow(conn, &second_person_follow).unwrap();
let after_follow_again = CommunityAggregates::read(conn, inserted_community.id).unwrap();
CommunityFollower::follow(pool, &second_person_follow)
.await
.unwrap();
let after_follow_again = CommunityAggregates::read(pool, inserted_community.id)
.await
.unwrap();
assert_eq!(2, after_follow_again.subscribers);
// Remove a parent comment (the comment count should also be 0)
Post::delete(conn, inserted_post.id).unwrap();
let after_parent_post_delete = CommunityAggregates::read(conn, inserted_community.id).unwrap();
Post::delete(pool, inserted_post.id).await.unwrap();
let after_parent_post_delete = CommunityAggregates::read(pool, inserted_community.id)
.await
.unwrap();
assert_eq!(0, after_parent_post_delete.comments);
assert_eq!(0, after_parent_post_delete.posts);
// Remove the 2nd person
Person::delete(conn, another_inserted_person.id).unwrap();
let after_person_delete = CommunityAggregates::read(conn, inserted_community.id).unwrap();
Person::delete(pool, another_inserted_person.id)
.await
.unwrap();
let after_person_delete = CommunityAggregates::read(pool, inserted_community.id)
.await
.unwrap();
assert_eq!(1, after_person_delete.subscribers);
// This should delete all the associated rows, and fire triggers
let person_num_deleted = Person::delete(conn, inserted_person.id).unwrap();
let person_num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
assert_eq!(1, person_num_deleted);
// Delete the community
let community_num_deleted = Community::delete(conn, inserted_community.id).unwrap();
let community_num_deleted = Community::delete(pool, inserted_community.id)
.await
.unwrap();
assert_eq!(1, community_num_deleted);
let another_community_num_deleted =
Community::delete(conn, another_inserted_community.id).unwrap();
let another_community_num_deleted = Community::delete(pool, another_inserted_community.id)
.await
.unwrap();
assert_eq!(1, another_community_num_deleted);
// Should be none found, since the creator was deleted
let after_delete = CommunityAggregates::read(conn, inserted_community.id);
let after_delete = CommunityAggregates::read(pool, inserted_community.id).await;
assert!(after_delete.is_err());
}
}

View file

@ -1,11 +1,19 @@
use crate::{aggregates::structs::PersonAggregates, newtypes::PersonId, schema::person_aggregates};
use diesel::{result::Error, *};
use crate::{
aggregates::structs::PersonAggregates,
newtypes::PersonId,
schema::person_aggregates,
utils::{get_conn, DbPool},
};
use diesel::{result::Error, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
impl PersonAggregates {
pub fn read(conn: &mut PgConnection, person_id: PersonId) -> Result<Self, Error> {
pub async fn read(pool: &DbPool, person_id: PersonId) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
person_aggregates::table
.filter(person_aggregates::person_id.eq(person_id))
.first::<Self>(conn)
.await
}
}
@ -21,16 +29,16 @@ mod tests {
post::{Post, PostInsertForm, PostLike, PostLikeForm},
},
traits::{Crud, Likeable},
utils::establish_unpooled_connection,
utils::build_db_pool_for_tests,
};
use serial_test::serial;
#[test]
#[tokio::test]
#[serial]
fn test_crud() {
let conn = &mut establish_unpooled_connection();
async fn test_crud() {
let pool = &build_db_pool_for_tests().await;
let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
let new_person = PersonInsertForm::builder()
.name("thommy_user_agg".into())
@ -38,7 +46,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_person = Person::create(conn, &new_person).unwrap();
let inserted_person = Person::create(pool, &new_person).await.unwrap();
let another_person = PersonInsertForm::builder()
.name("jerry_user_agg".into())
@ -46,7 +54,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let another_inserted_person = Person::create(conn, &another_person).unwrap();
let another_inserted_person = Person::create(pool, &another_person).await.unwrap();
let new_community = CommunityInsertForm::builder()
.name("TIL_site_agg".into())
@ -55,7 +63,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_community = Community::create(conn, &new_community).unwrap();
let inserted_community = Community::create(pool, &new_community).await.unwrap();
let new_post = PostInsertForm::builder()
.name("A test post".into())
@ -63,7 +71,7 @@ mod tests {
.community_id(inserted_community.id)
.build();
let inserted_post = Post::create(conn, &new_post).unwrap();
let inserted_post = Post::create(pool, &new_post).await.unwrap();
let post_like = PostLikeForm {
post_id: inserted_post.id,
@ -71,7 +79,7 @@ mod tests {
score: 1,
};
let _inserted_post_like = PostLike::like(conn, &post_like).unwrap();
let _inserted_post_like = PostLike::like(pool, &post_like).await.unwrap();
let comment_form = CommentInsertForm::builder()
.content("A test comment".into())
@ -79,7 +87,7 @@ mod tests {
.post_id(inserted_post.id)
.build();
let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
let mut comment_like = CommentLikeForm {
comment_id: inserted_comment.id,
@ -88,7 +96,7 @@ mod tests {
score: 1,
};
let _inserted_comment_like = CommentLike::like(conn, &comment_like).unwrap();
let _inserted_comment_like = CommentLike::like(pool, &comment_like).await.unwrap();
let child_comment_form = CommentInsertForm::builder()
.content("A test comment".into())
@ -97,7 +105,9 @@ mod tests {
.build();
let inserted_child_comment =
Comment::create(conn, &child_comment_form, Some(&inserted_comment.path)).unwrap();
Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
.await
.unwrap();
let child_comment_like = CommentLikeForm {
comment_id: inserted_child_comment.id,
@ -106,9 +116,11 @@ mod tests {
score: 1,
};
let _inserted_child_comment_like = CommentLike::like(conn, &child_comment_like).unwrap();
let _inserted_child_comment_like = CommentLike::like(pool, &child_comment_like).await.unwrap();
let person_aggregates_before_delete = PersonAggregates::read(conn, inserted_person.id).unwrap();
let person_aggregates_before_delete = PersonAggregates::read(pool, inserted_person.id)
.await
.unwrap();
assert_eq!(1, person_aggregates_before_delete.post_count);
assert_eq!(1, person_aggregates_before_delete.post_score);
@ -116,47 +128,65 @@ mod tests {
assert_eq!(2, person_aggregates_before_delete.comment_score);
// Remove a post like
PostLike::remove(conn, inserted_person.id, inserted_post.id).unwrap();
let after_post_like_remove = PersonAggregates::read(conn, inserted_person.id).unwrap();
PostLike::remove(pool, inserted_person.id, inserted_post.id)
.await
.unwrap();
let after_post_like_remove = PersonAggregates::read(pool, inserted_person.id)
.await
.unwrap();
assert_eq!(0, after_post_like_remove.post_score);
// Remove a parent comment (the scores should also be removed)
Comment::delete(conn, inserted_comment.id).unwrap();
Comment::delete(conn, inserted_child_comment.id).unwrap();
let after_parent_comment_delete = PersonAggregates::read(conn, inserted_person.id).unwrap();
Comment::delete(pool, inserted_comment.id).await.unwrap();
Comment::delete(pool, inserted_child_comment.id)
.await
.unwrap();
let after_parent_comment_delete = PersonAggregates::read(pool, inserted_person.id)
.await
.unwrap();
assert_eq!(0, after_parent_comment_delete.comment_count);
assert_eq!(0, after_parent_comment_delete.comment_score);
// Add in the two comments again, then delete the post.
let new_parent_comment = Comment::create(conn, &comment_form, None).unwrap();
let new_parent_comment = Comment::create(pool, &comment_form, None).await.unwrap();
let _new_child_comment =
Comment::create(conn, &child_comment_form, Some(&new_parent_comment.path)).unwrap();
Comment::create(pool, &child_comment_form, Some(&new_parent_comment.path))
.await
.unwrap();
comment_like.comment_id = new_parent_comment.id;
CommentLike::like(conn, &comment_like).unwrap();
let after_comment_add = PersonAggregates::read(conn, inserted_person.id).unwrap();
CommentLike::like(pool, &comment_like).await.unwrap();
let after_comment_add = PersonAggregates::read(pool, inserted_person.id)
.await
.unwrap();
assert_eq!(2, after_comment_add.comment_count);
assert_eq!(1, after_comment_add.comment_score);
Post::delete(conn, inserted_post.id).unwrap();
let after_post_delete = PersonAggregates::read(conn, inserted_person.id).unwrap();
Post::delete(pool, inserted_post.id).await.unwrap();
let after_post_delete = PersonAggregates::read(pool, inserted_person.id)
.await
.unwrap();
assert_eq!(0, after_post_delete.comment_score);
assert_eq!(0, after_post_delete.comment_count);
assert_eq!(0, after_post_delete.post_score);
assert_eq!(0, after_post_delete.post_count);
// This should delete all the associated rows, and fire triggers
let person_num_deleted = Person::delete(conn, inserted_person.id).unwrap();
let person_num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
assert_eq!(1, person_num_deleted);
Person::delete(conn, another_inserted_person.id).unwrap();
Person::delete(pool, another_inserted_person.id)
.await
.unwrap();
// Delete the community
let community_num_deleted = Community::delete(conn, inserted_community.id).unwrap();
let community_num_deleted = Community::delete(pool, inserted_community.id)
.await
.unwrap();
assert_eq!(1, community_num_deleted);
// Should be none found
let after_delete = PersonAggregates::read(conn, inserted_person.id);
let after_delete = PersonAggregates::read(pool, inserted_person.id).await;
assert!(after_delete.is_err());
Instance::delete(conn, inserted_instance.id).unwrap();
Instance::delete(pool, inserted_instance.id).await.unwrap();
}
}

View file

@ -1,27 +1,29 @@
use crate::{
aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm},
diesel::BoolExpressionMethods,
newtypes::{PersonId, PostId},
schema::person_post_aggregates::dsl::*,
utils::{get_conn, DbPool},
};
use diesel::{result::Error, *};
use diesel::{insert_into, result::Error, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
impl PersonPostAggregates {
pub fn upsert(conn: &mut PgConnection, form: &PersonPostAggregatesForm) -> Result<Self, Error> {
use crate::schema::person_post_aggregates::dsl::*;
pub async fn upsert(pool: &DbPool, form: &PersonPostAggregatesForm) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
insert_into(person_post_aggregates)
.values(form)
.on_conflict((person_id, post_id))
.do_update()
.set(form)
.get_result::<Self>(conn)
.await
}
pub fn read(
conn: &mut PgConnection,
person_id_: PersonId,
post_id_: PostId,
) -> Result<Self, Error> {
use crate::schema::person_post_aggregates::dsl::*;
pub async fn read(pool: &DbPool, person_id_: PersonId, post_id_: PostId) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
person_post_aggregates
.filter(post_id.eq(post_id_).and(person_id.eq(person_id_)))
.first::<Self>(conn)
.await
}
}

View file

@ -1,11 +1,19 @@
use crate::{aggregates::structs::PostAggregates, newtypes::PostId, schema::post_aggregates};
use diesel::{result::Error, *};
use crate::{
aggregates::structs::PostAggregates,
newtypes::PostId,
schema::post_aggregates,
utils::{get_conn, DbPool},
};
use diesel::{result::Error, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
impl PostAggregates {
pub fn read(conn: &mut PgConnection, post_id: PostId) -> Result<Self, Error> {
pub async fn read(pool: &DbPool, post_id: PostId) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
post_aggregates::table
.filter(post_aggregates::post_id.eq(post_id))
.first::<Self>(conn)
.await
}
}
@ -21,16 +29,16 @@ mod tests {
post::{Post, PostInsertForm, PostLike, PostLikeForm},
},
traits::{Crud, Likeable},
utils::establish_unpooled_connection,
utils::build_db_pool_for_tests,
};
use serial_test::serial;
#[test]
#[tokio::test]
#[serial]
fn test_crud() {
let conn = &mut establish_unpooled_connection();
async fn test_crud() {
let pool = &build_db_pool_for_tests().await;
let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
let new_person = PersonInsertForm::builder()
.name("thommy_community_agg".into())
@ -38,7 +46,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_person = Person::create(conn, &new_person).unwrap();
let inserted_person = Person::create(pool, &new_person).await.unwrap();
let another_person = PersonInsertForm::builder()
.name("jerry_community_agg".into())
@ -46,7 +54,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let another_inserted_person = Person::create(conn, &another_person).unwrap();
let another_inserted_person = Person::create(pool, &another_person).await.unwrap();
let new_community = CommunityInsertForm::builder()
.name("TIL_community_agg".into())
@ -55,7 +63,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_community = Community::create(conn, &new_community).unwrap();
let inserted_community = Community::create(pool, &new_community).await.unwrap();
let new_post = PostInsertForm::builder()
.name("A test post".into())
@ -63,7 +71,7 @@ mod tests {
.community_id(inserted_community.id)
.build();
let inserted_post = Post::create(conn, &new_post).unwrap();
let inserted_post = Post::create(pool, &new_post).await.unwrap();
let comment_form = CommentInsertForm::builder()
.content("A test comment".into())
@ -71,7 +79,7 @@ mod tests {
.post_id(inserted_post.id)
.build();
let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
let child_comment_form = CommentInsertForm::builder()
.content("A test comment".into())
@ -80,7 +88,9 @@ mod tests {
.build();
let inserted_child_comment =
Comment::create(conn, &child_comment_form, Some(&inserted_comment.path)).unwrap();
Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
.await
.unwrap();
let post_like = PostLikeForm {
post_id: inserted_post.id,
@ -88,9 +98,9 @@ mod tests {
score: 1,
};
PostLike::like(conn, &post_like).unwrap();
PostLike::like(pool, &post_like).await.unwrap();
let post_aggs_before_delete = PostAggregates::read(conn, inserted_post.id).unwrap();
let post_aggs_before_delete = PostAggregates::read(pool, inserted_post.id).await.unwrap();
assert_eq!(2, post_aggs_before_delete.comments);
assert_eq!(1, post_aggs_before_delete.score);
@ -104,9 +114,9 @@ mod tests {
score: -1,
};
PostLike::like(conn, &post_dislike).unwrap();
PostLike::like(pool, &post_dislike).await.unwrap();
let post_aggs_after_dislike = PostAggregates::read(conn, inserted_post.id).unwrap();
let post_aggs_after_dislike = PostAggregates::read(pool, inserted_post.id).await.unwrap();
assert_eq!(2, post_aggs_after_dislike.comments);
assert_eq!(0, post_aggs_after_dislike.score);
@ -114,35 +124,43 @@ mod tests {
assert_eq!(1, post_aggs_after_dislike.downvotes);
// Remove the comments
Comment::delete(conn, inserted_comment.id).unwrap();
Comment::delete(conn, inserted_child_comment.id).unwrap();
let after_comment_delete = PostAggregates::read(conn, inserted_post.id).unwrap();
Comment::delete(pool, inserted_comment.id).await.unwrap();
Comment::delete(pool, inserted_child_comment.id)
.await
.unwrap();
let after_comment_delete = PostAggregates::read(pool, inserted_post.id).await.unwrap();
assert_eq!(0, after_comment_delete.comments);
assert_eq!(0, after_comment_delete.score);
assert_eq!(1, after_comment_delete.upvotes);
assert_eq!(1, after_comment_delete.downvotes);
// Remove the first post like
PostLike::remove(conn, inserted_person.id, inserted_post.id).unwrap();
let after_like_remove = PostAggregates::read(conn, inserted_post.id).unwrap();
PostLike::remove(pool, inserted_person.id, inserted_post.id)
.await
.unwrap();
let after_like_remove = PostAggregates::read(pool, inserted_post.id).await.unwrap();
assert_eq!(0, after_like_remove.comments);
assert_eq!(-1, after_like_remove.score);
assert_eq!(0, after_like_remove.upvotes);
assert_eq!(1, after_like_remove.downvotes);
// This should delete all the associated rows, and fire triggers
Person::delete(conn, another_inserted_person.id).unwrap();
let person_num_deleted = Person::delete(conn, inserted_person.id).unwrap();
Person::delete(pool, another_inserted_person.id)
.await
.unwrap();
let person_num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
assert_eq!(1, person_num_deleted);
// Delete the community
let community_num_deleted = Community::delete(conn, inserted_community.id).unwrap();
let community_num_deleted = Community::delete(pool, inserted_community.id)
.await
.unwrap();
assert_eq!(1, community_num_deleted);
// Should be none found, since the creator was deleted
let after_delete = PostAggregates::read(conn, inserted_post.id);
let after_delete = PostAggregates::read(pool, inserted_post.id).await;
assert!(after_delete.is_err());
Instance::delete(conn, inserted_instance.id).unwrap();
Instance::delete(pool, inserted_instance.id).await.unwrap();
}
}

View file

@ -1,9 +1,15 @@
use crate::{aggregates::structs::SiteAggregates, schema::site_aggregates};
use diesel::{result::Error, *};
use crate::{
aggregates::structs::SiteAggregates,
schema::site_aggregates,
utils::{get_conn, DbPool},
};
use diesel::result::Error;
use diesel_async::RunQueryDsl;
impl SiteAggregates {
pub fn read(conn: &mut PgConnection) -> Result<Self, Error> {
site_aggregates::table.first::<Self>(conn)
pub async fn read(pool: &DbPool) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
site_aggregates::table.first::<Self>(conn).await
}
}
@ -20,16 +26,16 @@ mod tests {
site::{Site, SiteInsertForm},
},
traits::Crud,
utils::establish_unpooled_connection,
utils::build_db_pool_for_tests,
};
use serial_test::serial;
#[test]
#[tokio::test]
#[serial]
fn test_crud() {
let conn = &mut establish_unpooled_connection();
async fn test_crud() {
let pool = &build_db_pool_for_tests().await;
let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
let new_person = PersonInsertForm::builder()
.name("thommy_site_agg".into())
@ -37,14 +43,14 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_person = Person::create(conn, &new_person).unwrap();
let inserted_person = Person::create(pool, &new_person).await.unwrap();
let site_form = SiteInsertForm::builder()
.name("test_site".into())
.instance_id(inserted_instance.id)
.build();
let inserted_site = Site::create(conn, &site_form).unwrap();
let inserted_site = Site::create(pool, &site_form).await.unwrap();
let new_community = CommunityInsertForm::builder()
.name("TIL_site_agg".into())
@ -53,7 +59,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_community = Community::create(conn, &new_community).unwrap();
let inserted_community = Community::create(pool, &new_community).await.unwrap();
let new_post = PostInsertForm::builder()
.name("A test post".into())
@ -62,8 +68,8 @@ mod tests {
.build();
// Insert two of those posts
let inserted_post = Post::create(conn, &new_post).unwrap();
let _inserted_post_again = Post::create(conn, &new_post).unwrap();
let inserted_post = Post::create(pool, &new_post).await.unwrap();
let _inserted_post_again = Post::create(pool, &new_post).await.unwrap();
let comment_form = CommentInsertForm::builder()
.content("A test comment".into())
@ -72,7 +78,7 @@ mod tests {
.build();
// Insert two of those comments
let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
let child_comment_form = CommentInsertForm::builder()
.content("A test comment".into())
@ -81,9 +87,11 @@ mod tests {
.build();
let _inserted_child_comment =
Comment::create(conn, &child_comment_form, Some(&inserted_comment.path)).unwrap();
Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
.await
.unwrap();
let site_aggregates_before_delete = SiteAggregates::read(conn).unwrap();
let site_aggregates_before_delete = SiteAggregates::read(pool).await.unwrap();
// TODO: this is unstable, sometimes it returns 0 users, sometimes 1
//assert_eq!(0, site_aggregates_before_delete.users);
@ -92,27 +100,29 @@ mod tests {
assert_eq!(2, site_aggregates_before_delete.comments);
// Try a post delete
Post::delete(conn, inserted_post.id).unwrap();
let site_aggregates_after_post_delete = SiteAggregates::read(conn).unwrap();
Post::delete(pool, inserted_post.id).await.unwrap();
let site_aggregates_after_post_delete = SiteAggregates::read(pool).await.unwrap();
assert_eq!(1, site_aggregates_after_post_delete.posts);
assert_eq!(0, site_aggregates_after_post_delete.comments);
// This shouuld delete all the associated rows, and fire triggers
let person_num_deleted = Person::delete(conn, inserted_person.id).unwrap();
let person_num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
assert_eq!(1, person_num_deleted);
// Delete the community
let community_num_deleted = Community::delete(conn, inserted_community.id).unwrap();
let community_num_deleted = Community::delete(pool, inserted_community.id)
.await
.unwrap();
assert_eq!(1, community_num_deleted);
// Site should still exist, it can without a site creator.
let after_delete_creator = SiteAggregates::read(conn);
let after_delete_creator = SiteAggregates::read(pool).await;
assert!(after_delete_creator.is_ok());
Site::delete(conn, inserted_site.id).unwrap();
let after_delete_site = SiteAggregates::read(conn);
Site::delete(pool, inserted_site.id).await.unwrap();
let after_delete_site = SiteAggregates::read(pool).await;
assert!(after_delete_site.is_err());
Instance::delete(conn, inserted_instance.id).unwrap();
Instance::delete(pool, inserted_instance.id).await.unwrap();
}
}

View file

@ -1,20 +1,21 @@
use crate::{
diesel::JoinOnDsl,
newtypes::{CommunityId, LanguageId, LocalUserId, SiteId},
schema::{local_site, local_user_language::dsl::*, site, site_language},
schema::{local_site, site, site_language},
source::{actor_language::*, language::Language},
utils::{get_conn, DbPool},
};
use diesel::{delete, dsl::*, insert_into, result::Error, select, ExpressionMethods, QueryDsl};
use diesel_async::{AsyncPgConnection, RunQueryDsl};
use lemmy_utils::error::LemmyError;
use once_cell::sync::OnceCell;
use tokio::sync::OnceCell;
impl LocalUserLanguage {
pub async fn read(
pool: &DbPool,
for_local_user_id: LocalUserId,
) -> Result<Vec<LanguageId>, Error> {
use crate::schema::local_user_language::dsl::*;
let conn = &mut get_conn(&pool).await?;
conn
@ -84,12 +85,12 @@ impl SiteLanguage {
pub async fn read(pool: &DbPool, for_site_id: SiteId) -> Result<Vec<LanguageId>, Error> {
let conn = &mut get_conn(&pool).await?;
let langs = site_language
.filter(site_id.eq(for_site_id))
.select(language_id)
let langs = site_language::table
.filter(site_language::site_id.eq(for_site_id))
.select(site_language::language_id)
.load(conn)
.await?;
convert_read_languages(conn, langs)
convert_read_languages(conn, langs).await
}
pub async fn update(
@ -99,25 +100,35 @@ impl SiteLanguage {
) -> Result<(), Error> {
let conn = &mut get_conn(&pool).await?;
conn.build_transaction().read_write().run(|conn| {
// Clear the current languages
delete(site_language.filter(site_id.eq(for_site_id))).execute(conn)?;
conn
.build_transaction()
.run(|conn| {
Box::pin(async move {
use crate::schema::site_language::dsl::*;
let lang_ids = convert_update_languages(conn, language_ids)?;
for l in lang_ids {
let form = SiteLanguageForm {
site_id: for_site_id,
language_id: l,
};
insert_into(site_language)
.values(form)
.get_result::<Self>(conn)?;
}
// Clear the current languages
delete(site_language.filter(site_id.eq(for_site_id)))
.execute(conn)
.await;
CommunityLanguage::limit_languages(conn)?;
let lang_ids = convert_update_languages(conn, language_ids).await?;
for l in lang_ids {
let form = SiteLanguageForm {
site_id: for_site_id,
language_id: l,
};
insert_into(site_language)
.values(form)
.get_result::<Self>(conn)
.await;
}
Ok(())
})
CommunityLanguage::limit_languages(conn).await;
Ok(())
}) as _
})
.await
}
}
@ -129,13 +140,16 @@ impl CommunityLanguage {
for_community_id: CommunityId,
) -> Result<(), LemmyError> {
use crate::schema::community_language::dsl::*;
let conn = &mut get_conn(&pool).await?;
if let Some(for_language_id) = for_language_id {
let is_allowed = select(exists(
community_language
.filter(language_id.eq(for_language_id))
.filter(community_id.eq(for_community_id)),
))
.get_result(conn)?;
.get_result(conn)
.await?;
if is_allowed {
Ok(())
@ -151,7 +165,7 @@ impl CommunityLanguage {
/// also part of site languages. This is because post/comment language is only checked against
/// community language, and it shouldnt be possible to post content in languages which are not
/// allowed by local site.
async fn limit_languages(pool: &DbPool) -> Result<(), Error> {
async fn limit_languages(conn: &mut AsyncPgConnection) -> Result<(), Error> {
use crate::schema::{
community::dsl as c,
community_language::dsl as cl,
@ -163,10 +177,13 @@ impl CommunityLanguage {
.filter(c::local)
.filter(sl::language_id.is_null())
.select(cl::language_id)
.get_results(conn)?;
.get_results(conn)
.await?;
for c in community_languages {
delete(cl::community_language.filter(cl::language_id.eq(c))).execute(conn)?;
delete(cl::community_language.filter(cl::language_id.eq(c)))
.execute(conn)
.await;
}
Ok(())
}
@ -176,11 +193,14 @@ impl CommunityLanguage {
for_community_id: CommunityId,
) -> Result<Vec<LanguageId>, Error> {
use crate::schema::community_language::dsl::*;
let conn = &mut get_conn(&pool).await?;
let langs = community_language
.filter(community_id.eq(for_community_id))
.select(language_id)
.get_results(conn)?;
convert_read_languages(conn, langs)
.get_results(conn)
.await?;
convert_read_languages(conn, langs).await
}
pub async fn update(
@ -188,25 +208,36 @@ impl CommunityLanguage {
mut language_ids: Vec<LanguageId>,
for_community_id: CommunityId,
) -> Result<(), Error> {
conn.build_transaction().read_write().run(|conn| {
use crate::schema::community_language::dsl::*;
// Clear the current languages
delete(community_language.filter(community_id.eq(for_community_id))).execute(conn)?;
let conn = &mut get_conn(&pool).await?;
if language_ids.is_empty() {
language_ids = SiteLanguage::read_local(conn)?;
}
for l in language_ids {
let form = CommunityLanguageForm {
community_id: for_community_id,
language_id: l,
};
insert_into(community_language)
.values(form)
.get_result::<Self>(conn)?;
}
Ok(())
})
if language_ids.is_empty() {
language_ids = SiteLanguage::read_local(pool).await?;
}
conn
.build_transaction()
.run(|conn| {
Box::pin(async move {
use crate::schema::community_language::dsl::*;
// Clear the current languages
delete(community_language.filter(community_id.eq(for_community_id)))
.execute(conn)
.await;
for l in language_ids {
let form = CommunityLanguageForm {
community_id: for_community_id,
language_id: l,
};
insert_into(community_language)
.values(form)
.get_result::<Self>(conn)
.await;
}
Ok(())
}) as _
})
.await
}
}
@ -215,13 +246,15 @@ pub async fn default_post_language(
community_id: CommunityId,
local_user_id: LocalUserId,
) -> Result<Option<LanguageId>, Error> {
let conn = &mut get_conn(&pool).await?;
use crate::schema::{community_language::dsl as cl, local_user_language::dsl as ul};
let intersection = ul::local_user_language
.inner_join(cl::community_language.on(ul::language_id.eq(cl::language_id)))
.filter(ul::local_user_id.eq(local_user_id))
.filter(cl::community_id.eq(community_id))
.select(cl::language_id)
.get_results::<LanguageId>(conn)?;
.get_results::<LanguageId>(conn)
.await?;
if intersection.len() == 1 {
Ok(Some(intersection[0]))
@ -237,7 +270,8 @@ async fn convert_update_languages(
) -> Result<Vec<LanguageId>, Error> {
if language_ids.is_empty() {
Ok(
Language::read_all(conn)?
Language::read_all_conn(conn)
.await?
.into_iter()
.map(|l| l.id)
.collect(),
@ -252,15 +286,18 @@ async fn convert_read_languages(
conn: &mut AsyncPgConnection,
language_ids: Vec<LanguageId>,
) -> Result<Vec<LanguageId>, Error> {
static ALL_LANGUAGES_COUNT: OnceCell<usize> = OnceCell::new();
let count = ALL_LANGUAGES_COUNT.get_or_init(|| {
use crate::schema::language::dsl::*;
let count: i64 = language
.select(count(id))
.first(conn)
.expect("read number of languages");
count as usize
});
static ALL_LANGUAGES_COUNT: OnceCell<usize> = OnceCell::const_new();
let count = ALL_LANGUAGES_COUNT
.get_or_init(|| async {
use crate::schema::language::dsl::*;
let count: i64 = language
.select(count(id))
.first(conn)
.await
.expect("read number of languages");
count as usize
})
.await;
if &language_ids.len() == count {
Ok(vec![])
@ -282,145 +319,159 @@ mod tests {
site::{Site, SiteInsertForm},
},
traits::Crud,
utils::establish_unpooled_connection,
utils::build_db_pool_for_tests,
};
use serial_test::serial;
async fn test_langs1(pool: &DbPool) -> Vec<LanguageId> {
vec![
Language::read_id_from_code(conn, "en").unwrap(),
Language::read_id_from_code(conn, "fr").unwrap(),
Language::read_id_from_code(conn, "ru").unwrap(),
Language::read_id_from_code(pool, "en").await.unwrap(),
Language::read_id_from_code(pool, "fr").await.unwrap(),
Language::read_id_from_code(pool, "ru").await.unwrap(),
]
}
async fn test_langs2(pool: &DbPool) -> Vec<LanguageId> {
vec![
Language::read_id_from_code(conn, "fi").unwrap(),
Language::read_id_from_code(conn, "se").unwrap(),
Language::read_id_from_code(pool, "fi").await.unwrap(),
Language::read_id_from_code(pool, "se").await.unwrap(),
]
}
async fn create_test_site(pool: &DbPool) -> (Site, Instance) {
let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
let site_form = SiteInsertForm::builder()
.name("test site".to_string())
.instance_id(inserted_instance.id)
.build();
let site = Site::create(conn, &site_form).unwrap();
let site = Site::create(pool, &site_form).await.unwrap();
// Create a local site, since this is necessary for local languages
let local_site_form = LocalSiteInsertForm::builder().site_id(site.id).build();
LocalSite::create(conn, &local_site_form).unwrap();
LocalSite::create(pool, &local_site_form).await.unwrap();
(site, inserted_instance)
}
#[test]
#[tokio::test]
#[serial]
async fn test_convert_update_languages() {
let conn = &mut establish_unpooled_connection();
let pool = &build_db_pool_for_tests().await;
// call with empty vec, returns all languages
let converted1 = convert_update_languages(conn, vec![]).unwrap();
let conn = &mut get_conn(pool).await.unwrap();
let converted1 = convert_update_languages(conn, vec![]).await.unwrap();
assert_eq!(184, converted1.len());
// call with nonempty vec, returns same vec
let test_langs = test_langs1(conn);
let converted2 = convert_update_languages(conn, test_langs.clone()).unwrap();
let test_langs = test_langs1(pool).await;
let converted2 = convert_update_languages(conn, test_langs.clone())
.await
.unwrap();
assert_eq!(test_langs, converted2);
}
#[test]
#[tokio::test]
#[serial]
async fn test_convert_read_languages() {
let conn = &mut establish_unpooled_connection();
let pool = &build_db_pool_for_tests().await;
// call with all languages, returns empty vec
use crate::schema::language::dsl::*;
let all_langs = language.select(id).get_results(conn).unwrap();
let converted1: Vec<LanguageId> = convert_read_languages(conn, all_langs).unwrap();
let conn = &mut get_conn(&pool).await.unwrap();
let all_langs = language.select(id).get_results(conn).await.unwrap();
let converted1: Vec<LanguageId> = convert_read_languages(conn, all_langs).await.unwrap();
assert_eq!(0, converted1.len());
// call with nonempty vec, returns same vec
let test_langs = test_langs1(conn);
let converted2 = convert_read_languages(conn, test_langs.clone()).unwrap();
let test_langs = test_langs1(pool).await;
let converted2 = convert_read_languages(conn, test_langs.clone())
.await
.unwrap();
assert_eq!(test_langs, converted2);
}
#[test]
#[tokio::test]
#[serial]
async fn test_site_languages() {
let conn = &mut establish_unpooled_connection();
let pool = &build_db_pool_for_tests().await;
let (site, instance) = create_test_site(conn);
let site_languages1 = SiteLanguage::read_local(conn).unwrap();
let (site, instance) = create_test_site(pool).await;
let site_languages1 = SiteLanguage::read_local(pool).await.unwrap();
// site is created with all languages
assert_eq!(184, site_languages1.len());
let test_langs = test_langs1(conn);
SiteLanguage::update(conn, test_langs.clone(), site.id).unwrap();
let test_langs = test_langs1(pool).await;
SiteLanguage::update(pool, test_langs.clone(), site.id)
.await
.unwrap();
let site_languages2 = SiteLanguage::read_local(conn).unwrap();
let site_languages2 = SiteLanguage::read_local(pool).await.unwrap();
// after update, site only has new languages
assert_eq!(test_langs, site_languages2);
Site::delete(conn, site.id).unwrap();
Instance::delete(conn, instance.id).unwrap();
LocalSite::delete(conn).unwrap();
Site::delete(pool, site.id).await.unwrap();
Instance::delete(pool, instance.id).await.unwrap();
LocalSite::delete(pool).await.unwrap();
}
#[test]
#[tokio::test]
#[serial]
async fn test_user_languages() {
let conn = &mut establish_unpooled_connection();
let pool = &build_db_pool_for_tests().await;
let (site, instance) = create_test_site(conn);
let test_langs = test_langs1(conn);
SiteLanguage::update(conn, test_langs.clone(), site.id).unwrap();
let (site, instance) = create_test_site(pool).await;
let test_langs = test_langs1(pool).await;
SiteLanguage::update(pool, test_langs.clone(), site.id)
.await
.unwrap();
let person_form = PersonInsertForm::builder()
.name("my test person".to_string())
.public_key("pubkey".to_string())
.instance_id(instance.id)
.build();
let person = Person::create(conn, &person_form).unwrap();
let person = Person::create(pool, &person_form).await.unwrap();
let local_user_form = LocalUserInsertForm::builder()
.person_id(person.id)
.password_encrypted("my_pw".to_string())
.build();
let local_user = LocalUser::create(conn, &local_user_form).unwrap();
let local_user_langs1 = LocalUserLanguage::read(conn, local_user.id).unwrap();
let local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
let local_user_langs1 = LocalUserLanguage::read(pool, local_user.id).await.unwrap();
// new user should be initialized with site languages
assert_eq!(test_langs, local_user_langs1);
// update user languages
let test_langs2 = test_langs2(conn);
LocalUserLanguage::update(conn, test_langs2, local_user.id).unwrap();
let local_user_langs2 = LocalUserLanguage::read(conn, local_user.id).unwrap();
let test_langs2 = test_langs2(pool).await;
LocalUserLanguage::update(pool, test_langs2, local_user.id)
.await
.unwrap();
let local_user_langs2 = LocalUserLanguage::read(pool, local_user.id).await.unwrap();
assert_eq!(2, local_user_langs2.len());
Person::delete(conn, person.id).unwrap();
LocalUser::delete(conn, local_user.id).unwrap();
Site::delete(conn, site.id).unwrap();
LocalSite::delete(conn).unwrap();
Instance::delete(conn, instance.id).unwrap();
Person::delete(pool, person.id).await.unwrap();
LocalUser::delete(pool, local_user.id).await.unwrap();
Site::delete(pool, site.id).await.unwrap();
LocalSite::delete(pool).await.unwrap();
Instance::delete(pool, instance.id).await.unwrap();
}
#[test]
#[tokio::test]
#[serial]
async fn test_community_languages() {
let conn = &mut establish_unpooled_connection();
let (site, instance) = create_test_site(conn);
let test_langs = test_langs1(conn);
SiteLanguage::update(conn, test_langs.clone(), site.id).unwrap();
let pool = &build_db_pool_for_tests().await;
let (site, instance) = create_test_site(pool).await;
let test_langs = test_langs1(pool).await;
SiteLanguage::update(pool, test_langs.clone(), site.id)
.await
.unwrap();
let read_site_langs = SiteLanguage::read(conn, site.id).unwrap();
let read_site_langs = SiteLanguage::read(pool, site.id).await.unwrap();
assert_eq!(test_langs, read_site_langs);
// Test the local ones are the same
let read_local_site_langs = SiteLanguage::read_local(conn).unwrap();
let read_local_site_langs = SiteLanguage::read_local(pool).await.unwrap();
assert_eq!(test_langs, read_local_site_langs);
let community_form = CommunityInsertForm::builder()
@ -429,45 +480,51 @@ mod tests {
.public_key("pubkey".to_string())
.instance_id(instance.id)
.build();
let community = Community::create(conn, &community_form).unwrap();
let community_langs1 = CommunityLanguage::read(conn, community.id).unwrap();
let community = Community::create(pool, &community_form).await.unwrap();
let community_langs1 = CommunityLanguage::read(pool, community.id).await.unwrap();
// community is initialized with site languages
assert_eq!(test_langs, community_langs1);
let allowed_lang1 =
CommunityLanguage::is_allowed_community_language(conn, Some(test_langs[0]), community.id);
CommunityLanguage::is_allowed_community_language(pool, Some(test_langs[0]), community.id)
.await;
assert!(allowed_lang1.is_ok());
let test_langs2 = test_langs2(conn);
let test_langs2 = test_langs2(pool).await;
let allowed_lang2 =
CommunityLanguage::is_allowed_community_language(conn, Some(test_langs2[0]), community.id);
CommunityLanguage::is_allowed_community_language(pool, Some(test_langs2[0]), community.id)
.await;
assert!(allowed_lang2.is_err());
// limit site languages to en, fi. after this, community languages should be updated to
// intersection of old languages (en, fr, ru) and (en, fi), which is only fi.
SiteLanguage::update(conn, vec![test_langs[0], test_langs2[0]], site.id).unwrap();
let community_langs2 = CommunityLanguage::read(conn, community.id).unwrap();
SiteLanguage::update(pool, vec![test_langs[0], test_langs2[0]], site.id)
.await
.unwrap();
let community_langs2 = CommunityLanguage::read(pool, community.id).await.unwrap();
assert_eq!(vec![test_langs[0]], community_langs2);
// update community languages to different ones
CommunityLanguage::update(conn, test_langs2.clone(), community.id).unwrap();
let community_langs3 = CommunityLanguage::read(conn, community.id).unwrap();
CommunityLanguage::update(pool, test_langs2.clone(), community.id)
.await
.unwrap();
let community_langs3 = CommunityLanguage::read(pool, community.id).await.unwrap();
assert_eq!(test_langs2, community_langs3);
Community::delete(conn, community.id).unwrap();
Site::delete(conn, site.id).unwrap();
LocalSite::delete(conn).unwrap();
Instance::delete(conn, instance.id).unwrap();
Community::delete(pool, community.id).await.unwrap();
Site::delete(pool, site.id).await.unwrap();
LocalSite::delete(pool).await.unwrap();
Instance::delete(pool, instance.id).await.unwrap();
}
#[test]
#[tokio::test]
#[serial]
async fn test_default_post_language() {
let conn = &mut establish_unpooled_connection();
let (site, instance) = create_test_site(conn);
let test_langs = test_langs1(conn);
let test_langs2 = test_langs2(conn);
let pool = &build_db_pool_for_tests().await;
let (site, instance) = create_test_site(pool).await;
let test_langs = test_langs1(pool).await;
let test_langs2 = test_langs2(pool).await;
let community_form = CommunityInsertForm::builder()
.name("test community".to_string())
@ -475,43 +532,53 @@ mod tests {
.public_key("pubkey".to_string())
.instance_id(instance.id)
.build();
let community = Community::create(conn, &community_form).unwrap();
CommunityLanguage::update(conn, test_langs, community.id).unwrap();
let community = Community::create(pool, &community_form).await.unwrap();
CommunityLanguage::update(pool, test_langs, community.id)
.await
.unwrap();
let person_form = PersonInsertForm::builder()
.name("my test person".to_string())
.public_key("pubkey".to_string())
.instance_id(instance.id)
.build();
let person = Person::create(conn, &person_form).unwrap();
let person = Person::create(pool, &person_form).await.unwrap();
let local_user_form = LocalUserInsertForm::builder()
.person_id(person.id)
.password_encrypted("my_pw".to_string())
.build();
let local_user = LocalUser::create(conn, &local_user_form).unwrap();
LocalUserLanguage::update(conn, test_langs2, local_user.id).unwrap();
let local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
LocalUserLanguage::update(pool, test_langs2, local_user.id)
.await
.unwrap();
// no overlap in user/community languages, so no default language for post
let def1 = default_post_language(conn, community.id, local_user.id).unwrap();
let def1 = default_post_language(pool, community.id, local_user.id)
.await
.unwrap();
assert_eq!(None, def1);
let ru = Language::read_id_from_code(conn, "ru").unwrap();
let ru = Language::read_id_from_code(pool, "ru").await.unwrap();
let test_langs3 = vec![
ru,
Language::read_id_from_code(conn, "fi").unwrap(),
Language::read_id_from_code(conn, "se").unwrap(),
Language::read_id_from_code(pool, "fi").await.unwrap(),
Language::read_id_from_code(pool, "se").await.unwrap(),
];
LocalUserLanguage::update(conn, test_langs3, local_user.id).unwrap();
LocalUserLanguage::update(pool, test_langs3, local_user.id)
.await
.unwrap();
// this time, both have ru as common lang
let def2 = default_post_language(conn, community.id, local_user.id).unwrap();
let def2 = default_post_language(pool, community.id, local_user.id)
.await
.unwrap();
assert_eq!(Some(ru), def2);
Person::delete(conn, person.id).unwrap();
Community::delete(conn, community.id).unwrap();
LocalUser::delete(conn, local_user.id).unwrap();
Site::delete(conn, site.id).unwrap();
LocalSite::delete(conn).unwrap();
Instance::delete(conn, instance.id).unwrap();
Person::delete(pool, person.id).await.unwrap();
Community::delete(pool, community.id).await.unwrap();
LocalUser::delete(pool, local_user.id).await.unwrap();
Site::delete(pool, site.id).await.unwrap();
LocalSite::delete(pool).await.unwrap();
Instance::delete(pool, instance.id).await.unwrap();
}
}

View file

@ -19,6 +19,7 @@ impl Instance {
.do_update()
.set(form)
.get_result::<Self>(conn)
.await
}
pub async fn create(pool: &DbPool, domain: &str) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;

View file

@ -6,11 +6,15 @@ use crate::{
utils::{get_conn, DbPool},
};
use diesel::{result::Error, QueryDsl};
use diesel_async::RunQueryDsl;
use diesel_async::{AsyncPgConnection, RunQueryDsl};
impl Language {
pub async fn read_all(pool: &DbPool) -> Result<Vec<Language>, Error> {
let conn = &mut get_conn(&pool).await?;
Self::read_all_conn(conn).await
}
pub async fn read_all_conn(conn: &mut AsyncPgConnection) -> Result<Vec<Language>, Error> {
language.load::<Self>(conn).await
}

View file

@ -129,16 +129,17 @@ impl Crud for LocalUser {
let local_user_ = insert_into(local_user)
.values(form_with_encrypted_password)
.get_result::<Self>(conn)
.await?;
.await
.expect("couldnt create local user");
let site_languages = SiteLanguage::read_local(conn).await;
let site_languages = SiteLanguage::read_local(pool).await;
if let Ok(langs) = site_languages {
// if site exists, init user with site languages
LocalUserLanguage::update(conn, langs, local_user_.id).await?;
LocalUserLanguage::update(pool, langs, local_user_.id).await?;
} else {
// otherwise, init with all languages (this only happens during tests and
// for first admin user, which is created before site)
LocalUserLanguage::update(conn, vec![], local_user_.id).await?;
LocalUserLanguage::update(pool, vec![], local_user_.id).await?;
}
Ok(local_user_)

View file

@ -93,12 +93,12 @@ mod tests {
};
use serial_test::serial;
#[test]
#[tokio::test]
#[serial]
fn test_crud() {
async fn test_crud() {
let pool = &build_db_pool_for_tests().await;
let inserted_instance = Instance::create(pool, "my_domain.tld").unwrap();
let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
let new_person = PersonInsertForm::builder()
.name("thommy prw".into())
@ -106,20 +106,22 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_person = Person::create(pool, &new_person).unwrap();
let inserted_person = Person::create(pool, &new_person).await.unwrap();
let new_local_user = LocalUserInsertForm::builder()
.person_id(inserted_person.id)
.password_encrypted("pass".to_string())
.build();
let inserted_local_user = LocalUser::create(pool, &new_local_user).unwrap();
let inserted_local_user = LocalUser::create(pool, &new_local_user).await.unwrap();
let token = "nope";
let token_encrypted_ = "ca3704aa0b06f5954c79ee837faa152d84d6b2d42838f0637a15eda8337dbdce";
let inserted_password_reset_request =
PasswordResetRequest::create_token(pool, inserted_local_user.id, token).unwrap();
PasswordResetRequest::create_token(pool, inserted_local_user.id, token)
.await
.unwrap();
let expected_password_reset_request = PasswordResetRequest {
id: inserted_password_reset_request.id,
@ -128,9 +130,11 @@ mod tests {
published: inserted_password_reset_request.published,
};
let read_password_reset_request = PasswordResetRequest::read_from_token(pool, token).unwrap();
let num_deleted = Person::delete(pool, inserted_person.id).unwrap();
Instance::delete(pool, inserted_instance.id).unwrap();
let read_password_reset_request = PasswordResetRequest::read_from_token(pool, token)
.await
.unwrap();
let num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
Instance::delete(pool, inserted_instance.id).await.unwrap();
assert_eq!(expected_password_reset_request, read_password_reset_request);
assert_eq!(

View file

@ -181,7 +181,6 @@ impl Post {
.filter(url.like(pictrs_search))
.load::<Self>(conn)
.await
.await
}
/// Sets the url and thumbnails fields to None
@ -203,7 +202,6 @@ impl Post {
))
.get_results::<Self>(conn)
.await
.await
}
}

View file

@ -5,7 +5,8 @@ use crate::{
traits::Crud,
utils::{get_conn, DbPool},
};
use diesel::{dsl::*, result::Error, *};
use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
use url::Url;
#[async_trait]
@ -30,7 +31,7 @@ impl Crud for Site {
.await?;
// initialize with all languages
SiteLanguage::update(conn, vec![], site_.id)?;
SiteLanguage::update(pool, vec![], site_.id).await?;
Ok(site_)
}

View file

@ -22,8 +22,9 @@ pub trait Crud {
async fn delete(_pool: &DbPool, _id: Self::IdType) -> Result<usize, Error>
where
Self: Sized,
Self::IdType: Send,
{
unimplemented!()
async { Err(Error::NotFound) }.await
}
}

View file

@ -1,4 +1,10 @@
use crate::{diesel_migrations::MigrationHarness, newtypes::DbUrl, CommentSortType, SortType};
use crate::{
diesel::Connection,
diesel_migrations::MigrationHarness,
newtypes::DbUrl,
CommentSortType,
SortType,
};
use activitypub_federation::{core::object_id::ObjectId, traits::ApubObject};
use bb8::PooledConnection;
use chrono::NaiveDateTime;
@ -9,7 +15,6 @@ use diesel::{
result::{Error as DieselError, Error::QueryBuilderError},
serialize::{Output, ToSql},
sql_types::Text,
Connection,
PgConnection,
};
use diesel_async::{
@ -31,6 +36,7 @@ pub type DbPool = Pool<AsyncPgConnection>;
pub async fn get_conn(
pool: &DbPool,
) -> Result<PooledConnection<AsyncDieselConnectionManager<AsyncPgConnection>>, DieselError> {
// TODO Maybe find a better diesel error for this
pool.get().await.map_err(|_| DieselError::NotInTransaction)
}
@ -125,18 +131,34 @@ pub fn diesel_option_overwrite_to_url_create(
}
}
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
async fn build_db_pool_settings_opt(settings: Option<&Settings>) -> DbPool {
let db_url = get_database_url(settings);
let pool_size = settings.map(|s| s.database.pool_size).unwrap_or(5);
let manager = AsyncDieselConnectionManager::<AsyncPgConnection>::new(&db_url);
Pool::builder()
let pool = Pool::builder()
.max_size(pool_size)
.min_idle(Some(1))
.build(manager)
.await
.unwrap_or_else(|_| panic!("Error connecting to {}", db_url))
.unwrap_or_else(|_| panic!("Error connecting to {}", db_url));
// If there's no settings, that means its a unit test, and migrations need to be run
if settings.is_none() {
run_migrations(&db_url);
}
pool
}
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
pub fn run_migrations(db_url: &str) {
// Needs to be a sync connection
let mut conn =
PgConnection::establish(&db_url).unwrap_or_else(|_| panic!("Error connecting to {}", db_url));
let _ = &mut conn
.run_pending_migrations(MIGRATIONS)
.unwrap_or_else(|_| panic!("Couldn't run DB Migrations"));
}
pub async fn build_db_pool(settings: &Settings) -> DbPool {

View file

@ -12,16 +12,18 @@ rust-version = "1.57"
doctest = false
[features]
full = ["lemmy_db_schema/full", "diesel", "tracing"]
full = ["lemmy_db_schema/full", "diesel", "diesel-async", "diesel_ltree", "tracing"]
[dependencies]
lemmy_db_schema = { version = "=0.16.5", path = "../db_schema" }
diesel = { version = "2.0.2", features = ["postgres","chrono","serde_json"], optional = true }
diesel-async = { version = "0.1.1", features = ["postgres", "bb8"], optional = true}
diesel_ltree = { version = "0.3.0", optional = true}
serde = { version = "1.0.147", features = ["derive"] }
tracing = { version = "0.1.37", optional = true }
diesel_ltree = "0.3.0"
typed-builder = "0.10.0"
url = { version = "2.3.1", features = ["serde"] }
[dev-dependencies]
serial_test = "0.9.0"
tokio = "1.21.2"

View file

@ -1,5 +1,14 @@
use crate::structs::CommentReportView;
use diesel::{dsl::*, result::Error, *};
use diesel::{
dsl::*,
result::Error,
BoolExpressionMethods,
ExpressionMethods,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
aggregates::structs::CommentAggregates,
newtypes::{CommentReportId, CommunityId, PersonId},
@ -22,7 +31,7 @@ use lemmy_db_schema::{
post::Post,
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
use typed_builder::TypedBuilder;
@ -43,11 +52,13 @@ impl CommentReportView {
/// returns the CommentReportView for the provided report_id
///
/// * `report_id` - the report id to obtain
pub fn read(
conn: &mut PgConnection,
pub async fn read(
pool: &DbPool,
report_id: CommentReportId,
my_person_id: PersonId,
) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
let (
@ -108,7 +119,8 @@ impl CommentReportView {
.fields(Person::safe_columns_tuple())
.nullable(),
))
.first::<CommentReportViewTuple>(conn)?;
.first::<CommentReportViewTuple>(conn)
.await?;
let my_vote = comment_like;
@ -127,14 +139,16 @@ impl CommentReportView {
}
/// Returns the current unresolved post report count for the communities you mod
pub fn get_report_count(
conn: &mut PgConnection,
pub async fn get_report_count(
pool: &DbPool,
my_person_id: PersonId,
admin: bool,
community_id: Option<CommunityId>,
) -> Result<i64, Error> {
use diesel::dsl::*;
let conn = &mut get_conn(&pool).await?;
let mut query = comment_report::table
.inner_join(comment::table)
.inner_join(post::table.on(comment::post_id.eq(post::id)))
@ -157,8 +171,12 @@ impl CommentReportView {
)
.select(count(comment_report::id))
.first::<i64>(conn)
.await
} else {
query.select(count(comment_report::id)).first::<i64>(conn)
query
.select(count(comment_report::id))
.first::<i64>(conn)
.await
}
}
}
@ -167,7 +185,7 @@ impl CommentReportView {
#[builder(field_defaults(default))]
pub struct CommentReportQuery<'a> {
#[builder(!default)]
conn: &'a mut PgConnection,
pool: &'a DbPool,
#[builder(!default)]
my_person_id: PersonId,
#[builder(!default)]
@ -179,7 +197,9 @@ pub struct CommentReportQuery<'a> {
}
impl<'a> CommentReportQuery<'a> {
pub fn list(self) -> Result<Vec<CommentReportView>, Error> {
pub async fn list(self) -> Result<Vec<CommentReportView>, Error> {
let conn = &mut get_conn(self.pool).await?;
let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
let mut query = comment_report::table
@ -255,9 +275,10 @@ impl<'a> CommentReportQuery<'a> {
.and(community_moderator::person_id.eq(self.my_person_id)),
),
)
.load::<CommentReportViewTuple>(self.conn)?
.load::<CommentReportViewTuple>(conn)
.await?
} else {
query.load::<CommentReportViewTuple>(self.conn)?
query.load::<CommentReportViewTuple>(conn).await?
};
Ok(CommentReportView::from_tuple_to_vec(res))
@ -292,16 +313,16 @@ mod tests {
aggregates::structs::CommentAggregates,
source::{comment::*, comment_report::*, community::*, instance::Instance, person::*, post::*},
traits::{Crud, Joinable, Reportable},
utils::establish_unpooled_connection,
utils::build_db_pool_for_tests,
};
use serial_test::serial;
#[test]
#[tokio::test]
#[serial]
fn test_crud() {
let conn = &mut establish_unpooled_connection();
async fn test_crud() {
let pool = &build_db_pool_for_tests().await;
let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
let new_person = PersonInsertForm::builder()
.name("timmy_crv".into())
@ -309,7 +330,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_timmy = Person::create(conn, &new_person).unwrap();
let inserted_timmy = Person::create(pool, &new_person).await.unwrap();
let new_person_2 = PersonInsertForm::builder()
.name("sara_crv".into())
@ -317,7 +338,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_sara = Person::create(conn, &new_person_2).unwrap();
let inserted_sara = Person::create(pool, &new_person_2).await.unwrap();
// Add a third person, since new ppl can only report something once.
let new_person_3 = PersonInsertForm::builder()
@ -326,7 +347,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_jessica = Person::create(conn, &new_person_3).unwrap();
let inserted_jessica = Person::create(pool, &new_person_3).await.unwrap();
let new_community = CommunityInsertForm::builder()
.name("test community crv".to_string())
@ -335,7 +356,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_community = Community::create(conn, &new_community).unwrap();
let inserted_community = Community::create(pool, &new_community).await.unwrap();
// Make timmy a mod
let timmy_moderator_form = CommunityModeratorForm {
@ -343,7 +364,9 @@ mod tests {
person_id: inserted_timmy.id,
};
let _inserted_moderator = CommunityModerator::join(conn, &timmy_moderator_form).unwrap();
let _inserted_moderator = CommunityModerator::join(pool, &timmy_moderator_form)
.await
.unwrap();
let new_post = PostInsertForm::builder()
.name("A test post crv".into())
@ -351,7 +374,7 @@ mod tests {
.community_id(inserted_community.id)
.build();
let inserted_post = Post::create(conn, &new_post).unwrap();
let inserted_post = Post::create(pool, &new_post).await.unwrap();
let comment_form = CommentInsertForm::builder()
.content("A test comment 32".into())
@ -359,7 +382,7 @@ mod tests {
.post_id(inserted_post.id)
.build();
let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
// sara reports
let sara_report_form = CommentReportForm {
@ -369,7 +392,9 @@ mod tests {
reason: "from sara".into(),
};
let inserted_sara_report = CommentReport::report(conn, &sara_report_form).unwrap();
let inserted_sara_report = CommentReport::report(pool, &sara_report_form)
.await
.unwrap();
// jessica reports
let jessica_report_form = CommentReportForm {
@ -379,12 +404,18 @@ mod tests {
reason: "from jessica".into(),
};
let inserted_jessica_report = CommentReport::report(conn, &jessica_report_form).unwrap();
let inserted_jessica_report = CommentReport::report(pool, &jessica_report_form)
.await
.unwrap();
let agg = CommentAggregates::read(conn, inserted_comment.id).unwrap();
let agg = CommentAggregates::read(pool, inserted_comment.id)
.await
.unwrap();
let read_jessica_report_view =
CommentReportView::read(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
CommentReportView::read(pool, inserted_jessica_report.id, inserted_timmy.id)
.await
.unwrap();
let expected_jessica_report_view = CommentReportView {
comment_report: inserted_jessica_report.to_owned(),
comment: inserted_comment.to_owned(),
@ -491,11 +522,12 @@ mod tests {
// Do a batch read of timmys reports
let reports = CommentReportQuery::builder()
.conn(conn)
.pool(pool)
.my_person_id(inserted_timmy.id)
.admin(false)
.build()
.list()
.await
.unwrap();
assert_eq!(
@ -507,14 +539,19 @@ mod tests {
);
// Make sure the counts are correct
let report_count =
CommentReportView::get_report_count(conn, inserted_timmy.id, false, None).unwrap();
let report_count = CommentReportView::get_report_count(pool, inserted_timmy.id, false, None)
.await
.unwrap();
assert_eq!(2, report_count);
// Try to resolve the report
CommentReport::resolve(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
CommentReport::resolve(pool, inserted_jessica_report.id, inserted_timmy.id)
.await
.unwrap();
let read_jessica_report_view_after_resolve =
CommentReportView::read(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
CommentReportView::read(pool, inserted_jessica_report.id, inserted_timmy.id)
.await
.unwrap();
let mut expected_jessica_report_view_after_resolve = expected_jessica_report_view;
expected_jessica_report_view_after_resolve
@ -558,24 +595,29 @@ mod tests {
// Do a batch read of timmys reports
// It should only show saras, which is unresolved
let reports_after_resolve = CommentReportQuery::builder()
.conn(conn)
.pool(pool)
.my_person_id(inserted_timmy.id)
.admin(false)
.build()
.list()
.await
.unwrap();
assert_eq!(reports_after_resolve[0], expected_sara_report_view);
assert_eq!(reports_after_resolve.len(), 1);
// Make sure the counts are correct
let report_count_after_resolved =
CommentReportView::get_report_count(conn, inserted_timmy.id, false, None).unwrap();
CommentReportView::get_report_count(pool, inserted_timmy.id, false, None)
.await
.unwrap();
assert_eq!(1, report_count_after_resolved);
Person::delete(conn, inserted_timmy.id).unwrap();
Person::delete(conn, inserted_sara.id).unwrap();
Person::delete(conn, inserted_jessica.id).unwrap();
Community::delete(conn, inserted_community.id).unwrap();
Instance::delete(conn, inserted_instance.id).unwrap();
Person::delete(pool, inserted_timmy.id).await.unwrap();
Person::delete(pool, inserted_sara.id).await.unwrap();
Person::delete(pool, inserted_jessica.id).await.unwrap();
Community::delete(pool, inserted_community.id)
.await
.unwrap();
Instance::delete(pool, inserted_instance.id).await.unwrap();
}
}

View file

@ -1,5 +1,15 @@
use crate::structs::CommentView;
use diesel::{dsl::*, result::Error, *};
use diesel::{
dsl::*,
result::Error,
BoolExpressionMethods,
ExpressionMethods,
JoinOnDsl,
NullableExpressionMethods,
PgTextExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use diesel_ltree::{nlevel, subpath, Ltree, LtreeExtensions};
use lemmy_db_schema::{
aggregates::structs::CommentAggregates,
@ -27,7 +37,7 @@ use lemmy_db_schema::{
post::Post,
},
traits::{ToSafe, ViewToVec},
utils::{functions::hot_rank, fuzzy_search, limit_and_offset_unlimited},
utils::{functions::hot_rank, fuzzy_search, get_conn, limit_and_offset_unlimited, DbPool},
CommentSortType,
ListingType,
};
@ -47,11 +57,13 @@ type CommentViewTuple = (
);
impl CommentView {
pub fn read(
conn: &mut PgConnection,
pub async fn read(
pool: &DbPool,
comment_id: CommentId,
my_person_id: Option<PersonId>,
) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
// The left join below will return None in this case
let person_id_join = my_person_id.unwrap_or(PersonId(-1));
@ -124,7 +136,8 @@ impl CommentView {
person_block::all_columns.nullable(),
comment_like::score.nullable(),
))
.first::<CommentViewTuple>(conn)?;
.first::<CommentViewTuple>(conn)
.await?;
// If a person is given, then my_vote, if None, should be 0, not null
// Necessary to differentiate between other person's votes
@ -153,7 +166,7 @@ impl CommentView {
#[builder(field_defaults(default))]
pub struct CommentQuery<'a> {
#[builder(!default)]
conn: &'a mut PgConnection,
pool: &'a DbPool,
listing_type: Option<ListingType>,
sort: Option<CommentSortType>,
community_id: Option<CommunityId>,
@ -171,8 +184,9 @@ pub struct CommentQuery<'a> {
}
impl<'a> CommentQuery<'a> {
pub fn list(self) -> Result<Vec<CommentView>, Error> {
pub async fn list(self) -> Result<Vec<CommentView>, Error> {
use diesel::dsl::*;
let conn = &mut get_conn(self.pool).await?;
// The left join below will return None in this case
let person_id_join = self.local_user.map(|l| l.person_id).unwrap_or(PersonId(-1));
@ -359,7 +373,8 @@ impl<'a> CommentQuery<'a> {
let res = query
.limit(limit)
.offset(offset)
.load::<CommentViewTuple>(self.conn)?;
.load::<CommentViewTuple>(conn)
.await?;
Ok(CommentView::from_tuple_to_vec(res))
}
@ -404,7 +419,7 @@ mod tests {
post::*,
},
traits::{Blockable, Crud, Likeable},
utils::establish_unpooled_connection,
utils::build_db_pool_for_tests,
SubscribedType,
};
use serial_test::serial;
@ -421,27 +436,27 @@ mod tests {
inserted_community: Community,
}
fn init_data(conn: &mut PgConnection) -> Data {
let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
async fn init_data(pool: &DbPool) -> Data {
let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
let new_person = PersonInsertForm::builder()
.name("timmy".into())
.public_key("pubkey".to_string())
.instance_id(inserted_instance.id)
.build();
let inserted_person = Person::create(conn, &new_person).unwrap();
let inserted_person = Person::create(pool, &new_person).await.unwrap();
let local_user_form = LocalUserInsertForm::builder()
.person_id(inserted_person.id)
.password_encrypted("".to_string())
.build();
let inserted_local_user = LocalUser::create(conn, &local_user_form).unwrap();
let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
let new_person_2 = PersonInsertForm::builder()
.name("sara".into())
.public_key("pubkey".to_string())
.instance_id(inserted_instance.id)
.build();
let inserted_person_2 = Person::create(conn, &new_person_2).unwrap();
let inserted_person_2 = Person::create(pool, &new_person_2).await.unwrap();
let new_community = CommunityInsertForm::builder()
.name("test community 5".to_string())
@ -450,7 +465,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_community = Community::create(conn, &new_community).unwrap();
let inserted_community = Community::create(pool, &new_community).await.unwrap();
let new_post = PostInsertForm::builder()
.name("A test post 2".into())
@ -458,7 +473,7 @@ mod tests {
.community_id(inserted_community.id)
.build();
let inserted_post = Post::create(conn, &new_post).unwrap();
let inserted_post = Post::create(pool, &new_post).await.unwrap();
// Create a comment tree with this hierarchy
// 0
@ -474,7 +489,7 @@ mod tests {
.post_id(inserted_post.id)
.build();
let inserted_comment_0 = Comment::create(conn, &comment_form_0, None).unwrap();
let inserted_comment_0 = Comment::create(pool, &comment_form_0, None).await.unwrap();
let comment_form_1 = CommentInsertForm::builder()
.content("Comment 1, A test blocked comment".into())
@ -482,10 +497,11 @@ mod tests {
.post_id(inserted_post.id)
.build();
let inserted_comment_1 =
Comment::create(conn, &comment_form_1, Some(&inserted_comment_0.path)).unwrap();
let inserted_comment_1 = Comment::create(pool, &comment_form_1, Some(&inserted_comment_0.path))
.await
.unwrap();
let finnish_id = Language::read_id_from_code(conn, "fi").unwrap();
let finnish_id = Language::read_id_from_code(pool, "fi").await.unwrap();
let comment_form_2 = CommentInsertForm::builder()
.content("Comment 2".into())
.creator_id(inserted_person.id)
@ -493,8 +509,9 @@ mod tests {
.language_id(Some(finnish_id))
.build();
let inserted_comment_2 =
Comment::create(conn, &comment_form_2, Some(&inserted_comment_0.path)).unwrap();
let inserted_comment_2 = Comment::create(pool, &comment_form_2, Some(&inserted_comment_0.path))
.await
.unwrap();
let comment_form_3 = CommentInsertForm::builder()
.content("Comment 3".into())
@ -503,9 +520,11 @@ mod tests {
.build();
let _inserted_comment_3 =
Comment::create(conn, &comment_form_3, Some(&inserted_comment_1.path)).unwrap();
Comment::create(pool, &comment_form_3, Some(&inserted_comment_1.path))
.await
.unwrap();
let polish_id = Language::read_id_from_code(conn, "pl").unwrap();
let polish_id = Language::read_id_from_code(pool, "pl").await.unwrap();
let comment_form_4 = CommentInsertForm::builder()
.content("Comment 4".into())
.creator_id(inserted_person.id)
@ -513,8 +532,9 @@ mod tests {
.language_id(Some(polish_id))
.build();
let inserted_comment_4 =
Comment::create(conn, &comment_form_4, Some(&inserted_comment_1.path)).unwrap();
let inserted_comment_4 = Comment::create(pool, &comment_form_4, Some(&inserted_comment_1.path))
.await
.unwrap();
let comment_form_5 = CommentInsertForm::builder()
.content("Comment 5".into())
@ -523,14 +543,18 @@ mod tests {
.build();
let _inserted_comment_5 =
Comment::create(conn, &comment_form_5, Some(&inserted_comment_4.path)).unwrap();
Comment::create(pool, &comment_form_5, Some(&inserted_comment_4.path))
.await
.unwrap();
let timmy_blocks_sara_form = PersonBlockForm {
person_id: inserted_person.id,
target_id: inserted_person_2.id,
};
let inserted_block = PersonBlock::block(conn, &timmy_blocks_sara_form).unwrap();
let inserted_block = PersonBlock::block(pool, &timmy_blocks_sara_form)
.await
.unwrap();
let expected_block = PersonBlock {
id: inserted_block.id,
@ -547,7 +571,7 @@ mod tests {
score: 1,
};
let _inserted_comment_like = CommentLike::like(conn, &comment_like_form).unwrap();
let _inserted_comment_like = CommentLike::like(pool, &comment_like_form).await.unwrap();
Data {
inserted_instance,
@ -562,22 +586,23 @@ mod tests {
}
}
#[test]
#[tokio::test]
#[serial]
fn test_crud() {
let conn = &mut establish_unpooled_connection();
let data = init_data(conn);
async fn test_crud() {
let pool = &build_db_pool_for_tests().await;
let data = init_data(pool).await;
let expected_comment_view_no_person = expected_comment_view(&data, conn);
let expected_comment_view_no_person = expected_comment_view(&data, pool).await;
let mut expected_comment_view_with_person = expected_comment_view_no_person.to_owned();
expected_comment_view_with_person.my_vote = Some(1);
let read_comment_views_no_person = CommentQuery::builder()
.conn(conn)
.pool(pool)
.post_id(Some(data.inserted_post.id))
.build()
.list()
.await
.unwrap();
assert_eq!(
@ -586,11 +611,12 @@ mod tests {
);
let read_comment_views_with_person = CommentQuery::builder()
.conn(conn)
.pool(pool)
.post_id(Some(data.inserted_post.id))
.local_user(Some(&data.inserted_local_user))
.build()
.list()
.await
.unwrap();
assert_eq!(
@ -602,40 +628,43 @@ mod tests {
assert_eq!(5, read_comment_views_with_person.len());
let read_comment_from_blocked_person = CommentView::read(
conn,
pool,
data.inserted_comment_1.id,
Some(data.inserted_person.id),
)
.await
.unwrap();
// Make sure block set the creator blocked
assert!(read_comment_from_blocked_person.creator_blocked);
cleanup(data, conn);
cleanup(data, pool).await;
}
#[test]
#[tokio::test]
#[serial]
fn test_comment_tree() {
let conn = &mut establish_unpooled_connection();
let data = init_data(conn);
async fn test_comment_tree() {
let pool = &build_db_pool_for_tests().await;
let data = init_data(pool).await;
let top_path = data.inserted_comment_0.path.clone();
let read_comment_views_top_path = CommentQuery::builder()
.conn(conn)
.pool(pool)
.post_id(Some(data.inserted_post.id))
.parent_path(Some(top_path))
.build()
.list()
.await
.unwrap();
let child_path = data.inserted_comment_1.path.clone();
let read_comment_views_child_path = CommentQuery::builder()
.conn(conn)
.pool(pool)
.post_id(Some(data.inserted_post.id))
.parent_path(Some(child_path))
.build()
.list()
.await
.unwrap();
// Make sure the comment parent-limited fetch is correct
@ -651,29 +680,31 @@ mod tests {
assert!(!child_comments.contains(&data.inserted_comment_2));
let read_comment_views_top_max_depth = CommentQuery::builder()
.conn(conn)
.pool(pool)
.post_id(Some(data.inserted_post.id))
.max_depth(Some(1))
.build()
.list()
.await
.unwrap();
// Make sure a depth limited one only has the top comment
assert_eq!(
expected_comment_view(&data, conn),
expected_comment_view(&data, pool).await,
read_comment_views_top_max_depth[0]
);
assert_eq!(1, read_comment_views_top_max_depth.len());
let child_path = data.inserted_comment_1.path.clone();
let read_comment_views_parent_max_depth = CommentQuery::builder()
.conn(conn)
.pool(pool)
.post_id(Some(data.inserted_post.id))
.parent_path(Some(child_path))
.max_depth(Some(1))
.sort(Some(CommentSortType::New))
.build()
.list()
.await
.unwrap();
// Make sure a depth limited one, and given child comment 1, has 3
@ -683,33 +714,37 @@ mod tests {
.eq("Comment 3"));
assert_eq!(3, read_comment_views_parent_max_depth.len());
cleanup(data, conn);
cleanup(data, pool).await;
}
#[test]
#[tokio::test]
#[serial]
fn test_languages() {
let conn = &mut establish_unpooled_connection();
let data = init_data(conn);
async fn test_languages() {
let pool = &build_db_pool_for_tests().await;
let data = init_data(pool).await;
// by default, user has all languages enabled and should see all comments
// (except from blocked user)
let all_languages = CommentQuery::builder()
.conn(conn)
.pool(pool)
.local_user(Some(&data.inserted_local_user))
.build()
.list()
.await
.unwrap();
assert_eq!(5, all_languages.len());
// change user lang to finnish, should only show single finnish comment
let finnish_id = Language::read_id_from_code(conn, "fi").unwrap();
LocalUserLanguage::update(conn, vec![finnish_id], data.inserted_local_user.id).unwrap();
let finnish_id = Language::read_id_from_code(pool, "fi").await.unwrap();
LocalUserLanguage::update(pool, vec![finnish_id], data.inserted_local_user.id)
.await
.unwrap();
let finnish_comment = CommentQuery::builder()
.conn(conn)
.pool(pool)
.local_user(Some(&data.inserted_local_user))
.build()
.list()
.await
.unwrap();
assert_eq!(1, finnish_comment.len());
assert_eq!(
@ -719,32 +754,49 @@ mod tests {
assert_eq!(finnish_id, finnish_comment[0].comment.language_id);
// now show all comments with undetermined language (which is the default value)
let undetermined_id = Language::read_id_from_code(conn, "und").unwrap();
LocalUserLanguage::update(conn, vec![undetermined_id], data.inserted_local_user.id).unwrap();
let undetermined_id = Language::read_id_from_code(pool, "und").await.unwrap();
LocalUserLanguage::update(pool, vec![undetermined_id], data.inserted_local_user.id)
.await
.unwrap();
let undetermined_comment = CommentQuery::builder()
.conn(conn)
.pool(pool)
.local_user(Some(&data.inserted_local_user))
.build()
.list()
.await
.unwrap();
assert_eq!(3, undetermined_comment.len());
cleanup(data, conn);
cleanup(data, pool).await;
}
fn cleanup(data: Data, conn: &mut PgConnection) {
CommentLike::remove(conn, data.inserted_person.id, data.inserted_comment_0.id).unwrap();
Comment::delete(conn, data.inserted_comment_0.id).unwrap();
Comment::delete(conn, data.inserted_comment_1.id).unwrap();
Post::delete(conn, data.inserted_post.id).unwrap();
Community::delete(conn, data.inserted_community.id).unwrap();
Person::delete(conn, data.inserted_person.id).unwrap();
Person::delete(conn, data.inserted_person_2.id).unwrap();
Instance::delete(conn, data.inserted_instance.id).unwrap();
async fn cleanup(data: Data, pool: &DbPool) {
CommentLike::remove(pool, data.inserted_person.id, data.inserted_comment_0.id)
.await
.unwrap();
Comment::delete(pool, data.inserted_comment_0.id)
.await
.unwrap();
Comment::delete(pool, data.inserted_comment_1.id)
.await
.unwrap();
Post::delete(pool, data.inserted_post.id).await.unwrap();
Community::delete(pool, data.inserted_community.id)
.await
.unwrap();
Person::delete(pool, data.inserted_person.id).await.unwrap();
Person::delete(pool, data.inserted_person_2.id)
.await
.unwrap();
Instance::delete(pool, data.inserted_instance.id)
.await
.unwrap();
}
fn expected_comment_view(data: &Data, conn: &mut PgConnection) -> CommentView {
let agg = CommentAggregates::read(conn, data.inserted_comment_0.id).unwrap();
async fn expected_comment_view(data: &Data, pool: &DbPool) -> CommentView {
let agg = CommentAggregates::read(pool, data.inserted_comment_0.id)
.await
.unwrap();
CommentView {
creator_banned_from_community: false,
my_vote: None,

View file

@ -1,5 +1,6 @@
use crate::structs::LocalUserDiscussionLanguageView;
use diesel::{result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
use diesel::{result::Error, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::LocalUserId,
schema::{language, local_user, local_user_language},
@ -8,15 +9,18 @@ use lemmy_db_schema::{
local_user::{LocalUser, LocalUserSettings},
},
traits::ToSafeSettings,
utils::{get_conn, DbPool},
};
type LocalUserDiscussionLanguageViewTuple = (LocalUserSettings, Language);
impl LocalUserDiscussionLanguageView {
pub fn read_languages(
conn: &mut PgConnection,
pub async fn read_languages(
pool: &DbPool,
local_user_id: LocalUserId,
) -> Result<Vec<Language>, Error> {
let conn = &mut get_conn(&pool).await?;
let res = local_user_language::table
.inner_join(local_user::table)
.inner_join(language::table)
@ -25,7 +29,8 @@ impl LocalUserDiscussionLanguageView {
language::all_columns,
))
.filter(local_user::id.eq(local_user_id))
.load::<LocalUserDiscussionLanguageViewTuple>(conn)?;
.load::<LocalUserDiscussionLanguageViewTuple>(conn)
.await?;
Ok(res.into_iter().map(|a| a.1).collect::<Vec<Language>>())
}

View file

@ -1,5 +1,6 @@
use crate::structs::{LocalUserSettingsView, LocalUserView};
use diesel::{result::Error, *};
use diesel::{result::Error, BoolExpressionMethods, ExpressionMethods, JoinOnDsl, QueryDsl};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
aggregates::structs::PersonAggregates,
newtypes::{LocalUserId, PersonId},
@ -9,13 +10,15 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ToSafeSettings, ViewToVec},
utils::functions::lower,
utils::{functions::lower, get_conn, DbPool},
};
type LocalUserViewTuple = (LocalUser, Person, PersonAggregates);
impl LocalUserView {
pub fn read(conn: &mut PgConnection, local_user_id: LocalUserId) -> Result<Self, Error> {
pub async fn read(pool: &DbPool, local_user_id: LocalUserId) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let (local_user, person, counts) = local_user::table
.find(local_user_id)
.inner_join(person::table)
@ -25,7 +28,8 @@ impl LocalUserView {
person::all_columns,
person_aggregates::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
.first::<LocalUserViewTuple>(conn)
.await?;
Ok(Self {
local_user,
person,
@ -33,7 +37,8 @@ impl LocalUserView {
})
}
pub fn read_person(conn: &mut PgConnection, person_id: PersonId) -> Result<Self, Error> {
pub async fn read_person(pool: &DbPool, person_id: PersonId) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let (local_user, person, counts) = local_user::table
.filter(person::id.eq(person_id))
.inner_join(person::table)
@ -43,7 +48,8 @@ impl LocalUserView {
person::all_columns,
person_aggregates::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
.first::<LocalUserViewTuple>(conn)
.await?;
Ok(Self {
local_user,
person,
@ -52,7 +58,8 @@ impl LocalUserView {
}
// TODO check where this is used
pub fn read_from_name(conn: &mut PgConnection, name: &str) -> Result<Self, Error> {
pub async fn read_from_name(pool: &DbPool, name: &str) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let (local_user, person, counts) = local_user::table
.filter(person::name.eq(name))
.inner_join(person::table)
@ -62,7 +69,8 @@ impl LocalUserView {
person::all_columns,
person_aggregates::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
.first::<LocalUserViewTuple>(conn)
.await?;
Ok(Self {
local_user,
person,
@ -70,10 +78,8 @@ impl LocalUserView {
})
}
pub fn find_by_email_or_name(
conn: &mut PgConnection,
name_or_email: &str,
) -> Result<Self, Error> {
pub async fn find_by_email_or_name(pool: &DbPool, name_or_email: &str) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
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)))
@ -87,7 +93,8 @@ impl LocalUserView {
person::all_columns,
person_aggregates::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
.first::<LocalUserViewTuple>(conn)
.await?;
Ok(Self {
local_user,
person,
@ -95,7 +102,8 @@ impl LocalUserView {
})
}
pub fn find_by_email(conn: &mut PgConnection, from_email: &str) -> Result<Self, Error> {
pub async fn find_by_email(pool: &DbPool, from_email: &str) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
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)))
@ -105,7 +113,8 @@ impl LocalUserView {
person::all_columns,
person_aggregates::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
.first::<LocalUserViewTuple>(conn)
.await?;
Ok(Self {
local_user,
person,
@ -117,7 +126,8 @@ impl LocalUserView {
type LocalUserSettingsViewTuple = (LocalUserSettings, PersonSafe, PersonAggregates);
impl LocalUserSettingsView {
pub fn read(conn: &mut PgConnection, local_user_id: LocalUserId) -> Result<Self, Error> {
pub async fn read(pool: &DbPool, local_user_id: LocalUserId) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let (local_user, person, counts) = local_user::table
.find(local_user_id)
.inner_join(person::table)
@ -127,7 +137,8 @@ impl LocalUserSettingsView {
Person::safe_columns_tuple(),
person_aggregates::all_columns,
))
.first::<LocalUserSettingsViewTuple>(conn)?;
.first::<LocalUserSettingsViewTuple>(conn)
.await?;
Ok(Self {
local_user,
person,
@ -135,7 +146,8 @@ impl LocalUserSettingsView {
})
}
pub fn list_admins_with_emails(conn: &mut PgConnection) -> Result<Vec<Self>, Error> {
pub async fn list_admins_with_emails(pool: &DbPool) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let res = local_user::table
.filter(person::admin.eq(true))
.filter(local_user::email.is_not_null())
@ -146,7 +158,8 @@ impl LocalUserSettingsView {
Person::safe_columns_tuple(),
person_aggregates::all_columns,
))
.load::<LocalUserSettingsViewTuple>(conn)?;
.load::<LocalUserSettingsViewTuple>(conn)
.await?;
Ok(LocalUserSettingsView::from_tuple_to_vec(res))
}

View file

@ -1,5 +1,14 @@
use crate::structs::PostReportView;
use diesel::{dsl::*, result::Error, *};
use diesel::{
dsl::*,
result::Error,
BoolExpressionMethods,
ExpressionMethods,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
aggregates::structs::PostAggregates,
newtypes::{CommunityId, PersonId, PostReportId},
@ -20,7 +29,7 @@ use lemmy_db_schema::{
post_report::PostReport,
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
use typed_builder::TypedBuilder;
@ -40,11 +49,12 @@ impl PostReportView {
/// returns the PostReportView for the provided report_id
///
/// * `report_id` - the report id to obtain
pub fn read(
conn: &mut PgConnection,
pub async fn read(
pool: &DbPool,
report_id: PostReportId,
my_person_id: PersonId,
) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
let (
@ -97,7 +107,8 @@ impl PostReportView {
post_aggregates::all_columns,
person_alias_2.fields(Person::safe_columns_tuple().nullable()),
))
.first::<PostReportViewTuple>(conn)?;
.first::<PostReportViewTuple>(conn)
.await?;
let my_vote = post_like;
@ -115,13 +126,14 @@ impl PostReportView {
}
/// returns the current unresolved post report count for the communities you mod
pub fn get_report_count(
conn: &mut PgConnection,
pub async fn get_report_count(
pool: &DbPool,
my_person_id: PersonId,
admin: bool,
community_id: Option<CommunityId>,
) -> Result<i64, Error> {
use diesel::dsl::*;
let conn = &mut get_conn(&pool).await?;
let mut query = post_report::table
.inner_join(post::table)
.filter(post_report::resolved.eq(false))
@ -143,8 +155,12 @@ impl PostReportView {
)
.select(count(post_report::id))
.first::<i64>(conn)
.await
} else {
query.select(count(post_report::id)).first::<i64>(conn)
query
.select(count(post_report::id))
.first::<i64>(conn)
.await
}
}
}
@ -153,7 +169,7 @@ impl PostReportView {
#[builder(field_defaults(default))]
pub struct PostReportQuery<'a> {
#[builder(!default)]
conn: &'a mut PgConnection,
pool: &'a DbPool,
#[builder(!default)]
my_person_id: PersonId,
#[builder(!default)]
@ -165,7 +181,8 @@ pub struct PostReportQuery<'a> {
}
impl<'a> PostReportQuery<'a> {
pub fn list(self) -> Result<Vec<PostReportView>, Error> {
pub async fn list(self) -> Result<Vec<PostReportView>, Error> {
let conn = &mut get_conn(self.pool).await?;
let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
let mut query = post_report::table
@ -236,9 +253,10 @@ impl<'a> PostReportQuery<'a> {
.and(community_moderator::person_id.eq(self.my_person_id)),
),
)
.load::<PostReportViewTuple>(self.conn)?
.load::<PostReportViewTuple>(conn)
.await?
} else {
query.load::<PostReportViewTuple>(self.conn)?
query.load::<PostReportViewTuple>(conn).await?
};
Ok(PostReportView::from_tuple_to_vec(res))
@ -278,16 +296,16 @@ mod tests {
post_report::{PostReport, PostReportForm},
},
traits::{Crud, Joinable, Reportable},
utils::establish_unpooled_connection,
utils::build_db_pool_for_tests,
};
use serial_test::serial;
#[test]
#[tokio::test]
#[serial]
fn test_crud() {
let conn = &mut establish_unpooled_connection();
async fn test_crud() {
let pool = &build_db_pool_for_tests().await;
let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
let new_person = PersonInsertForm::builder()
.name("timmy_prv".into())
@ -295,7 +313,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_timmy = Person::create(conn, &new_person).unwrap();
let inserted_timmy = Person::create(pool, &new_person).await.unwrap();
let new_person_2 = PersonInsertForm::builder()
.name("sara_prv".into())
@ -303,7 +321,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_sara = Person::create(conn, &new_person_2).unwrap();
let inserted_sara = Person::create(pool, &new_person_2).await.unwrap();
// Add a third person, since new ppl can only report something once.
let new_person_3 = PersonInsertForm::builder()
@ -312,7 +330,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_jessica = Person::create(conn, &new_person_3).unwrap();
let inserted_jessica = Person::create(pool, &new_person_3).await.unwrap();
let new_community = CommunityInsertForm::builder()
.name("test community prv".to_string())
@ -321,7 +339,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_community = Community::create(conn, &new_community).unwrap();
let inserted_community = Community::create(pool, &new_community).await.unwrap();
// Make timmy a mod
let timmy_moderator_form = CommunityModeratorForm {
@ -329,7 +347,9 @@ mod tests {
person_id: inserted_timmy.id,
};
let _inserted_moderator = CommunityModerator::join(conn, &timmy_moderator_form).unwrap();
let _inserted_moderator = CommunityModerator::join(pool, &timmy_moderator_form)
.await
.unwrap();
let new_post = PostInsertForm::builder()
.name("A test post crv".into())
@ -337,7 +357,7 @@ mod tests {
.community_id(inserted_community.id)
.build();
let inserted_post = Post::create(conn, &new_post).unwrap();
let inserted_post = Post::create(pool, &new_post).await.unwrap();
// sara reports
let sara_report_form = PostReportForm {
@ -349,7 +369,7 @@ mod tests {
reason: "from sara".into(),
};
let inserted_sara_report = PostReport::report(conn, &sara_report_form).unwrap();
let inserted_sara_report = PostReport::report(pool, &sara_report_form).await.unwrap();
// jessica reports
let jessica_report_form = PostReportForm {
@ -361,12 +381,16 @@ mod tests {
reason: "from jessica".into(),
};
let inserted_jessica_report = PostReport::report(conn, &jessica_report_form).unwrap();
let inserted_jessica_report = PostReport::report(pool, &jessica_report_form)
.await
.unwrap();
let agg = PostAggregates::read(conn, inserted_post.id).unwrap();
let agg = PostAggregates::read(pool, inserted_post.id).await.unwrap();
let read_jessica_report_view =
PostReportView::read(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
PostReportView::read(pool, inserted_jessica_report.id, inserted_timmy.id)
.await
.unwrap();
let expected_jessica_report_view = PostReportView {
post_report: inserted_jessica_report.to_owned(),
post: inserted_post.to_owned(),
@ -476,11 +500,12 @@ mod tests {
// Do a batch read of timmys reports
let reports = PostReportQuery::builder()
.conn(conn)
.pool(pool)
.my_person_id(inserted_timmy.id)
.admin(false)
.build()
.list()
.await
.unwrap();
assert_eq!(
@ -492,14 +517,19 @@ mod tests {
);
// Make sure the counts are correct
let report_count =
PostReportView::get_report_count(conn, inserted_timmy.id, false, None).unwrap();
let report_count = PostReportView::get_report_count(pool, inserted_timmy.id, false, None)
.await
.unwrap();
assert_eq!(2, report_count);
// Try to resolve the report
PostReport::resolve(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
PostReport::resolve(pool, inserted_jessica_report.id, inserted_timmy.id)
.await
.unwrap();
let read_jessica_report_view_after_resolve =
PostReportView::read(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
PostReportView::read(pool, inserted_jessica_report.id, inserted_timmy.id)
.await
.unwrap();
let mut expected_jessica_report_view_after_resolve = expected_jessica_report_view;
expected_jessica_report_view_after_resolve
@ -541,23 +571,28 @@ mod tests {
// Do a batch read of timmys reports
// It should only show saras, which is unresolved
let reports_after_resolve = PostReportQuery::builder()
.conn(conn)
.pool(pool)
.my_person_id(inserted_timmy.id)
.admin(false)
.build()
.list()
.await
.unwrap();
assert_eq!(reports_after_resolve[0], expected_sara_report_view);
// Make sure the counts are correct
let report_count_after_resolved =
PostReportView::get_report_count(conn, inserted_timmy.id, false, None).unwrap();
PostReportView::get_report_count(pool, inserted_timmy.id, false, None)
.await
.unwrap();
assert_eq!(1, report_count_after_resolved);
Person::delete(conn, inserted_timmy.id).unwrap();
Person::delete(conn, inserted_sara.id).unwrap();
Person::delete(conn, inserted_jessica.id).unwrap();
Community::delete(conn, inserted_community.id).unwrap();
Instance::delete(conn, inserted_instance.id).unwrap();
Person::delete(pool, inserted_timmy.id).await.unwrap();
Person::delete(pool, inserted_sara.id).await.unwrap();
Person::delete(pool, inserted_jessica.id).await.unwrap();
Community::delete(pool, inserted_community.id)
.await
.unwrap();
Instance::delete(pool, inserted_instance.id).await.unwrap();
}
}

View file

@ -1,5 +1,19 @@
use crate::structs::PostView;
use diesel::{dsl::*, pg::Pg, result::Error, *};
use diesel::{
debug_query,
dsl::*,
pg::Pg,
result::Error,
sql_function,
sql_types,
BoolExpressionMethods,
ExpressionMethods,
JoinOnDsl,
NullableExpressionMethods,
PgTextExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
aggregates::structs::PostAggregates,
newtypes::{CommunityId, DbUrl, LocalUserId, PersonId, PostId},
@ -26,7 +40,7 @@ use lemmy_db_schema::{
post::{Post, PostRead, PostSaved},
},
traits::{ToSafe, ViewToVec},
utils::{functions::hot_rank, fuzzy_search, limit_and_offset},
utils::{functions::hot_rank, fuzzy_search, get_conn, limit_and_offset, DbPool},
ListingType,
SortType,
};
@ -50,11 +64,13 @@ type PostViewTuple = (
sql_function!(fn coalesce(x: sql_types::Nullable<sql_types::BigInt>, y: sql_types::BigInt) -> sql_types::BigInt);
impl PostView {
pub fn read(
conn: &mut PgConnection,
pub async fn read(
pool: &DbPool,
post_id: PostId,
my_person_id: Option<PersonId>,
) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
// The left join below will return None in this case
let person_id_join = my_person_id.unwrap_or(PersonId(-1));
let (
@ -144,7 +160,8 @@ impl PostView {
post_aggregates::comments,
),
))
.first::<PostViewTuple>(conn)?;
.first::<PostViewTuple>(conn)
.await?;
// If a person is given, then my_vote, if None, should be 0, not null
// Necessary to differentiate between other person's votes
@ -174,7 +191,7 @@ impl PostView {
#[builder(field_defaults(default))]
pub struct PostQuery<'a> {
#[builder(!default)]
conn: &'a mut PgConnection,
pool: &'a DbPool,
listing_type: Option<ListingType>,
sort: Option<SortType>,
creator_id: Option<PersonId>,
@ -189,8 +206,9 @@ pub struct PostQuery<'a> {
}
impl<'a> PostQuery<'a> {
pub fn list(self) -> Result<Vec<PostView>, Error> {
pub async fn list(self) -> Result<Vec<PostView>, Error> {
use diesel::dsl::*;
let conn = &mut get_conn(self.pool).await?;
// The left join below will return None in this case
let person_id_join = self.local_user.map(|l| l.person_id).unwrap_or(PersonId(-1));
@ -418,7 +436,7 @@ impl<'a> PostQuery<'a> {
debug!("Post View Query: {:?}", debug_query::<Pg, _>(&query));
let res = query.load::<PostViewTuple>(self.conn)?;
let res = query.load::<PostViewTuple>(conn).await?;
Ok(PostView::from_tuple_to_vec(res))
}
@ -449,7 +467,6 @@ impl ViewToVec for PostView {
#[cfg(test)]
mod tests {
use crate::post_view::{PostQuery, PostView};
use diesel::PgConnection;
use lemmy_db_schema::{
aggregates::structs::PostAggregates,
newtypes::LanguageId,
@ -465,7 +482,7 @@ mod tests {
post::*,
},
traits::{Blockable, Crud, Likeable},
utils::establish_unpooled_connection,
utils::{build_db_pool_for_tests, DbPool},
SortType,
SubscribedType,
};
@ -481,8 +498,8 @@ mod tests {
inserted_post: Post,
}
fn init_data(conn: &mut PgConnection) -> Data {
let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
async fn init_data(pool: &DbPool) -> Data {
let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
let person_name = "tegan".to_string();
@ -492,13 +509,13 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_person = Person::create(conn, &new_person).unwrap();
let inserted_person = Person::create(pool, &new_person).await.unwrap();
let local_user_form = LocalUserInsertForm::builder()
.person_id(inserted_person.id)
.password_encrypted("".to_string())
.build();
let inserted_local_user = LocalUser::create(conn, &local_user_form).unwrap();
let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
let new_bot = PersonInsertForm::builder()
.name("mybot".to_string())
@ -507,7 +524,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_bot = Person::create(conn, &new_bot).unwrap();
let inserted_bot = Person::create(pool, &new_bot).await.unwrap();
let new_community = CommunityInsertForm::builder()
.name("test_community_3".to_string())
@ -516,7 +533,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_community = Community::create(conn, &new_community).unwrap();
let inserted_community = Community::create(pool, &new_community).await.unwrap();
// Test a person block, make sure the post query doesn't include their post
let blocked_person = PersonInsertForm::builder()
@ -525,7 +542,7 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_blocked_person = Person::create(conn, &blocked_person).unwrap();
let inserted_blocked_person = Person::create(pool, &blocked_person).await.unwrap();
let post_from_blocked_person = PostInsertForm::builder()
.name("blocked_person_post".to_string())
@ -534,7 +551,7 @@ mod tests {
.language_id(Some(LanguageId(1)))
.build();
Post::create(conn, &post_from_blocked_person).unwrap();
Post::create(pool, &post_from_blocked_person).await.unwrap();
// block that person
let person_block = PersonBlockForm {
@ -542,7 +559,7 @@ mod tests {
target_id: inserted_blocked_person.id,
};
PersonBlock::block(conn, &person_block).unwrap();
PersonBlock::block(pool, &person_block).await.unwrap();
// A sample post
let new_post = PostInsertForm::builder()
@ -552,7 +569,7 @@ mod tests {
.language_id(Some(LanguageId(47)))
.build();
let inserted_post = Post::create(conn, &new_post).unwrap();
let inserted_post = Post::create(pool, &new_post).await.unwrap();
let new_bot_post = PostInsertForm::builder()
.name("test bot post".to_string())
@ -560,7 +577,7 @@ mod tests {
.community_id(inserted_community.id)
.build();
let _inserted_bot_post = Post::create(conn, &new_bot_post).unwrap();
let _inserted_bot_post = Post::create(pool, &new_bot_post).await.unwrap();
Data {
inserted_instance,
@ -573,31 +590,36 @@ mod tests {
}
}
#[test]
#[tokio::test]
#[serial]
fn post_listing_with_person() {
let conn = &mut establish_unpooled_connection();
let data = init_data(conn);
async fn post_listing_with_person() {
let pool = &build_db_pool_for_tests().await;
let data = init_data(pool).await;
let local_user_form = LocalUserUpdateForm::builder()
.show_bot_accounts(Some(false))
.build();
let inserted_local_user =
LocalUser::update(conn, data.inserted_local_user.id, &local_user_form).unwrap();
LocalUser::update(pool, data.inserted_local_user.id, &local_user_form)
.await
.unwrap();
let read_post_listing = PostQuery::builder()
.conn(conn)
.pool(pool)
.sort(Some(SortType::New))
.community_id(Some(data.inserted_community.id))
.local_user(Some(&inserted_local_user))
.build()
.list()
.await
.unwrap();
let post_listing_single_with_person =
PostView::read(conn, data.inserted_post.id, Some(data.inserted_person.id)).unwrap();
PostView::read(pool, data.inserted_post.id, Some(data.inserted_person.id))
.await
.unwrap();
let mut expected_post_listing_with_user = expected_post_view(&data, conn);
let mut expected_post_listing_with_user = expected_post_view(&data, pool).await;
// Should be only one person, IE the bot post, and blocked should be missing
assert_eq!(1, read_post_listing.len());
@ -613,40 +635,45 @@ mod tests {
.show_bot_accounts(Some(true))
.build();
let inserted_local_user =
LocalUser::update(conn, data.inserted_local_user.id, &local_user_form).unwrap();
LocalUser::update(pool, data.inserted_local_user.id, &local_user_form)
.await
.unwrap();
let post_listings_with_bots = PostQuery::builder()
.conn(conn)
.pool(pool)
.sort(Some(SortType::New))
.community_id(Some(data.inserted_community.id))
.local_user(Some(&inserted_local_user))
.build()
.list()
.await
.unwrap();
// should include bot post which has "undetermined" language
assert_eq!(2, post_listings_with_bots.len());
cleanup(data, conn);
cleanup(data, pool).await;
}
#[test]
#[tokio::test]
#[serial]
fn post_listing_no_person() {
let conn = &mut establish_unpooled_connection();
let data = init_data(conn);
async fn post_listing_no_person() {
let pool = &build_db_pool_for_tests().await;
let data = init_data(pool).await;
let read_post_listing_multiple_no_person = PostQuery::builder()
.conn(conn)
.pool(pool)
.sort(Some(SortType::New))
.community_id(Some(data.inserted_community.id))
.build()
.list()
.await
.unwrap();
let read_post_listing_single_no_person =
PostView::read(conn, data.inserted_post.id, None).unwrap();
let read_post_listing_single_no_person = PostView::read(pool, data.inserted_post.id, None)
.await
.unwrap();
let expected_post_listing_no_person = expected_post_view(&data, conn);
let expected_post_listing_no_person = expected_post_view(&data, pool).await;
// Should be 2 posts, with the bot post, and the blocked
assert_eq!(3, read_post_listing_multiple_no_person.len());
@ -660,41 +687,44 @@ mod tests {
read_post_listing_single_no_person
);
cleanup(data, conn);
cleanup(data, pool).await;
}
#[test]
#[tokio::test]
#[serial]
fn post_listing_block_community() {
let conn = &mut establish_unpooled_connection();
let data = init_data(conn);
async fn post_listing_block_community() {
let pool = &build_db_pool_for_tests().await;
let data = init_data(pool).await;
let community_block = CommunityBlockForm {
person_id: data.inserted_person.id,
community_id: data.inserted_community.id,
};
CommunityBlock::block(conn, &community_block).unwrap();
CommunityBlock::block(pool, &community_block).await.unwrap();
let read_post_listings_with_person_after_block = PostQuery::builder()
.conn(conn)
.pool(pool)
.sort(Some(SortType::New))
.community_id(Some(data.inserted_community.id))
.local_user(Some(&data.inserted_local_user))
.build()
.list()
.await
.unwrap();
// Should be 0 posts after the community block
assert_eq!(0, read_post_listings_with_person_after_block.len());
CommunityBlock::unblock(conn, &community_block).unwrap();
cleanup(data, conn);
CommunityBlock::unblock(pool, &community_block)
.await
.unwrap();
cleanup(data, pool).await;
}
#[test]
#[tokio::test]
#[serial]
fn post_listing_like() {
let conn = &mut establish_unpooled_connection();
let data = init_data(conn);
async fn post_listing_like() {
let pool = &build_db_pool_for_tests().await;
let data = init_data(pool).await;
let post_like_form = PostLikeForm {
post_id: data.inserted_post.id,
@ -702,7 +732,7 @@ mod tests {
score: 1,
};
let inserted_post_like = PostLike::like(conn, &post_like_form).unwrap();
let inserted_post_like = PostLike::like(pool, &post_like_form).await.unwrap();
let expected_post_like = PostLike {
id: inserted_post_like.id,
@ -713,19 +743,20 @@ mod tests {
};
assert_eq!(expected_post_like, inserted_post_like);
let like_removed =
PostLike::remove(conn, data.inserted_person.id, data.inserted_post.id).unwrap();
let like_removed = PostLike::remove(pool, data.inserted_person.id, data.inserted_post.id)
.await
.unwrap();
assert_eq!(1, like_removed);
cleanup(data, conn);
cleanup(data, pool).await;
}
#[test]
#[tokio::test]
#[serial]
fn post_listing_person_language() {
let conn = &mut establish_unpooled_connection();
let data = init_data(conn);
async fn post_listing_person_language() {
let pool = &build_db_pool_for_tests().await;
let data = init_data(pool).await;
let spanish_id = Language::read_id_from_code(conn, "es").unwrap();
let spanish_id = Language::read_id_from_code(pool, "es").await.unwrap();
let post_spanish = PostInsertForm::builder()
.name("asffgdsc".to_string())
.creator_id(data.inserted_person.id)
@ -733,47 +764,53 @@ mod tests {
.language_id(Some(spanish_id))
.build();
Post::create(conn, &post_spanish).unwrap();
Post::create(pool, &post_spanish).await.unwrap();
let post_listings_all = PostQuery::builder()
.conn(conn)
.pool(pool)
.sort(Some(SortType::New))
.local_user(Some(&data.inserted_local_user))
.build()
.list()
.await
.unwrap();
// no language filters specified, all posts should be returned
assert_eq!(3, post_listings_all.len());
let french_id = Language::read_id_from_code(conn, "fr").unwrap();
LocalUserLanguage::update(conn, vec![french_id], data.inserted_local_user.id).unwrap();
let french_id = Language::read_id_from_code(pool, "fr").await.unwrap();
LocalUserLanguage::update(pool, vec![french_id], data.inserted_local_user.id)
.await
.unwrap();
let post_listing_french = PostQuery::builder()
.conn(conn)
.pool(pool)
.sort(Some(SortType::New))
.local_user(Some(&data.inserted_local_user))
.build()
.list()
.await
.unwrap();
// only one french language post should be returned
assert_eq!(1, post_listing_french.len());
assert_eq!(french_id, post_listing_french[0].post.language_id);
let undetermined_id = Language::read_id_from_code(conn, "und").unwrap();
let undetermined_id = Language::read_id_from_code(pool, "und").await.unwrap();
LocalUserLanguage::update(
conn,
pool,
vec![french_id, undetermined_id],
data.inserted_local_user.id,
)
.await
.unwrap();
let post_listings_french_und = PostQuery::builder()
.conn(conn)
.pool(pool)
.sort(Some(SortType::New))
.local_user(Some(&data.inserted_local_user))
.build()
.list()
.await
.unwrap();
// french post and undetermined language post should be returned
@ -784,26 +821,32 @@ mod tests {
);
assert_eq!(french_id, post_listings_french_und[1].post.language_id);
cleanup(data, conn);
cleanup(data, pool).await;
}
fn cleanup(data: Data, conn: &mut PgConnection) {
let num_deleted = Post::delete(conn, data.inserted_post.id).unwrap();
Community::delete(conn, data.inserted_community.id).unwrap();
Person::delete(conn, data.inserted_person.id).unwrap();
Person::delete(conn, data.inserted_bot.id).unwrap();
Person::delete(conn, data.inserted_blocked_person.id).unwrap();
Instance::delete(conn, data.inserted_instance.id).unwrap();
async fn cleanup(data: Data, pool: &DbPool) {
let num_deleted = Post::delete(pool, data.inserted_post.id).await.unwrap();
Community::delete(pool, data.inserted_community.id)
.await
.unwrap();
Person::delete(pool, data.inserted_person.id).await.unwrap();
Person::delete(pool, data.inserted_bot.id).await.unwrap();
Person::delete(pool, data.inserted_blocked_person.id)
.await
.unwrap();
Instance::delete(pool, data.inserted_instance.id)
.await
.unwrap();
assert_eq!(1, num_deleted);
}
fn expected_post_view(data: &Data, conn: &mut PgConnection) -> PostView {
async fn expected_post_view(data: &Data, pool: &DbPool) -> PostView {
let (inserted_person, inserted_community, inserted_post) = (
&data.inserted_person,
&data.inserted_community,
&data.inserted_post,
);
let agg = PostAggregates::read(conn, inserted_post.id).unwrap();
let agg = PostAggregates::read(pool, inserted_post.id).await.unwrap();
PostView {
post: Post {

View file

@ -1,5 +1,6 @@
use crate::structs::PrivateMessageReportView;
use diesel::{result::Error, *};
use diesel::{result::Error, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PrivateMessageReportId,
schema::{person, private_message, private_message_report},
@ -9,7 +10,7 @@ use lemmy_db_schema::{
private_message_report::PrivateMessageReport,
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
use typed_builder::TypedBuilder;
@ -25,7 +26,8 @@ impl PrivateMessageReportView {
/// returns the PrivateMessageReportView for the provided report_id
///
/// * `report_id` - the report id to obtain
pub fn read(conn: &mut PgConnection, report_id: PrivateMessageReportId) -> Result<Self, Error> {
pub async fn read(pool: &DbPool, report_id: PrivateMessageReportId) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
let (private_message_report, private_message, private_message_creator, creator, resolver) =
@ -51,7 +53,8 @@ impl PrivateMessageReportView {
.fields(Person::safe_columns_tuple())
.nullable(),
))
.first::<PrivateMessageReportViewTuple>(conn)?;
.first::<PrivateMessageReportViewTuple>(conn)
.await?;
Ok(Self {
private_message_report,
@ -63,8 +66,9 @@ impl PrivateMessageReportView {
}
/// Returns the current unresolved post report count for the communities you mod
pub fn get_report_count(conn: &mut PgConnection) -> Result<i64, Error> {
pub async fn get_report_count(pool: &DbPool) -> Result<i64, Error> {
use diesel::dsl::*;
let conn = &mut get_conn(&pool).await?;
private_message_report::table
.inner_join(private_message::table)
@ -72,6 +76,7 @@ impl PrivateMessageReportView {
.into_boxed()
.select(count(private_message_report::id))
.first::<i64>(conn)
.await
}
}
@ -79,14 +84,15 @@ impl PrivateMessageReportView {
#[builder(field_defaults(default))]
pub struct PrivateMessageReportQuery<'a> {
#[builder(!default)]
conn: &'a mut PgConnection,
pool: &'a DbPool,
page: Option<i64>,
limit: Option<i64>,
unresolved_only: Option<bool>,
}
impl<'a> PrivateMessageReportQuery<'a> {
pub fn list(self) -> Result<Vec<PrivateMessageReportView>, Error> {
pub async fn list(self) -> Result<Vec<PrivateMessageReportView>, Error> {
let conn = &mut get_conn(self.pool).await?;
let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
let mut query = private_message_report::table
@ -121,7 +127,7 @@ impl<'a> PrivateMessageReportQuery<'a> {
.limit(limit)
.offset(offset);
let res = query.load::<PrivateMessageReportViewTuple>(self.conn)?;
let res = query.load::<PrivateMessageReportViewTuple>(conn).await?;
Ok(PrivateMessageReportView::from_tuple_to_vec(res))
}
@ -154,30 +160,30 @@ mod tests {
private_message_report::{PrivateMessageReport, PrivateMessageReportForm},
},
traits::{Crud, Reportable},
utils::establish_unpooled_connection,
utils::build_db_pool_for_tests,
};
use serial_test::serial;
#[test]
#[tokio::test]
#[serial]
fn test_crud() {
let conn = &mut establish_unpooled_connection();
async fn test_crud() {
let pool = &build_db_pool_for_tests().await;
let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
let new_person_1 = PersonInsertForm::builder()
.name("timmy_mrv".into())
.public_key("pubkey".to_string())
.instance_id(inserted_instance.id)
.build();
let inserted_timmy = Person::create(conn, &new_person_1).unwrap();
let inserted_timmy = Person::create(pool, &new_person_1).await.unwrap();
let new_person_2 = PersonInsertForm::builder()
.name("jessica_mrv".into())
.public_key("pubkey".to_string())
.instance_id(inserted_instance.id)
.build();
let inserted_jessica = Person::create(conn, &new_person_2).unwrap();
let inserted_jessica = Person::create(pool, &new_person_2).await.unwrap();
// timmy sends private message to jessica
let pm_form = PrivateMessageInsertForm::builder()
@ -185,7 +191,7 @@ mod tests {
.recipient_id(inserted_jessica.id)
.content("something offensive".to_string())
.build();
let pm = PrivateMessage::create(conn, &pm_form).unwrap();
let pm = PrivateMessage::create(pool, &pm_form).await.unwrap();
// jessica reports private message
let pm_report_form = PrivateMessageReportForm {
@ -194,12 +200,15 @@ mod tests {
private_message_id: pm.id,
reason: "its offensive".to_string(),
};
let pm_report = PrivateMessageReport::report(conn, &pm_report_form).unwrap();
let pm_report = PrivateMessageReport::report(pool, &pm_report_form)
.await
.unwrap();
let reports = PrivateMessageReportQuery::builder()
.conn(conn)
.pool(pool)
.build()
.list()
.await
.unwrap();
assert_eq!(1, reports.len());
assert!(!reports[0].private_message_report.resolved);
@ -213,16 +222,19 @@ mod tests {
.public_key("pubkey".to_string())
.instance_id(inserted_instance.id)
.build();
let inserted_admin = Person::create(conn, &new_person_3).unwrap();
let inserted_admin = Person::create(pool, &new_person_3).await.unwrap();
// admin resolves the report (after taking appropriate action)
PrivateMessageReport::resolve(conn, pm_report.id, inserted_admin.id).unwrap();
PrivateMessageReport::resolve(pool, pm_report.id, inserted_admin.id)
.await
.unwrap();
let reports = PrivateMessageReportQuery::builder()
.conn(conn)
.pool(pool)
.unresolved_only(Some(false))
.build()
.list()
.await
.unwrap();
assert_eq!(1, reports.len());
assert!(reports[0].private_message_report.resolved);
@ -232,6 +244,6 @@ mod tests {
reports[0].resolver.as_ref().unwrap().name
);
Instance::delete(conn, inserted_instance.id).unwrap();
Instance::delete(pool, inserted_instance.id).await.unwrap();
}
}

View file

@ -1,5 +1,14 @@
use crate::structs::PrivateMessageView;
use diesel::{pg::Pg, result::Error, *};
use diesel::{
debug_query,
pg::Pg,
result::Error,
BoolExpressionMethods,
ExpressionMethods,
JoinOnDsl,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::{PersonId, PrivateMessageId},
schema::{person, private_message},
@ -8,7 +17,7 @@ use lemmy_db_schema::{
private_message::PrivateMessage,
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
use tracing::debug;
use typed_builder::TypedBuilder;
@ -16,10 +25,8 @@ use typed_builder::TypedBuilder;
type PrivateMessageViewTuple = (PrivateMessage, PersonSafe, PersonSafe);
impl PrivateMessageView {
pub fn read(
conn: &mut PgConnection,
private_message_id: PrivateMessageId,
) -> Result<Self, Error> {
pub async fn read(pool: &DbPool, private_message_id: PrivateMessageId) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let (private_message, creator, recipient) = private_message::table
@ -34,7 +41,8 @@ impl PrivateMessageView {
Person::safe_columns_tuple(),
person_alias_1.fields(Person::safe_columns_tuple()),
))
.first::<PrivateMessageViewTuple>(conn)?;
.first::<PrivateMessageViewTuple>(conn)
.await?;
Ok(PrivateMessageView {
private_message,
@ -44,17 +52,16 @@ impl PrivateMessageView {
}
/// Gets the number of unread messages
pub fn get_unread_messages(
conn: &mut PgConnection,
my_person_id: PersonId,
) -> Result<i64, Error> {
pub async fn get_unread_messages(pool: &DbPool, my_person_id: PersonId) -> Result<i64, Error> {
use diesel::dsl::*;
let conn = &mut get_conn(&pool).await?;
private_message::table
.filter(private_message::read.eq(false))
.filter(private_message::recipient_id.eq(my_person_id))
.filter(private_message::deleted.eq(false))
.select(count(private_message::id))
.first::<i64>(conn)
.await
}
}
@ -62,7 +69,7 @@ impl PrivateMessageView {
#[builder(field_defaults(default))]
pub struct PrivateMessageQuery<'a> {
#[builder(!default)]
conn: &'a mut PgConnection,
pool: &'a DbPool,
#[builder(!default)]
recipient_id: PersonId,
unread_only: Option<bool>,
@ -71,7 +78,8 @@ pub struct PrivateMessageQuery<'a> {
}
impl<'a> PrivateMessageQuery<'a> {
pub fn list(self) -> Result<Vec<PrivateMessageView>, Error> {
pub async fn list(self) -> Result<Vec<PrivateMessageView>, Error> {
let conn = &mut get_conn(self.pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let mut query = private_message::table
@ -114,7 +122,7 @@ impl<'a> PrivateMessageQuery<'a> {
debug_query::<Pg, _>(&query)
);
let res = query.load::<PrivateMessageViewTuple>(self.conn)?;
let res = query.load::<PrivateMessageViewTuple>(conn).await?;
Ok(PrivateMessageView::from_tuple_to_vec(res))
}

View file

@ -1,5 +1,13 @@
use crate::structs::RegistrationApplicationView;
use diesel::{dsl::count, result::Error, *};
use diesel::{
dsl::count,
result::Error,
ExpressionMethods,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
schema::{local_user, person, registration_application},
source::{
@ -8,7 +16,7 @@ use lemmy_db_schema::{
registration_application::RegistrationApplication,
},
traits::{ToSafe, ToSafeSettings, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
use typed_builder::TypedBuilder;
@ -20,7 +28,8 @@ type RegistrationApplicationViewTuple = (
);
impl RegistrationApplicationView {
pub fn read(conn: &mut PgConnection, registration_application_id: i32) -> Result<Self, Error> {
pub async fn read(pool: &DbPool, registration_application_id: i32) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let (registration_application, creator_local_user, creator, admin) =
@ -43,7 +52,8 @@ impl RegistrationApplicationView {
.fields(Person::safe_columns_tuple())
.nullable(),
))
.first::<RegistrationApplicationViewTuple>(conn)?;
.first::<RegistrationApplicationViewTuple>(conn)
.await?;
Ok(RegistrationApplicationView {
registration_application,
@ -54,10 +64,8 @@ impl RegistrationApplicationView {
}
/// Returns the current unread registration_application count
pub fn get_unread_count(
conn: &mut PgConnection,
verified_email_only: bool,
) -> Result<i64, Error> {
pub async fn get_unread_count(pool: &DbPool, verified_email_only: bool) -> Result<i64, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let mut query = registration_application::table
@ -77,6 +85,7 @@ impl RegistrationApplicationView {
query
.select(count(registration_application::id))
.first::<i64>(conn)
.await
}
}
@ -84,7 +93,7 @@ impl RegistrationApplicationView {
#[builder(field_defaults(default))]
pub struct RegistrationApplicationQuery<'a> {
#[builder(!default)]
conn: &'a mut PgConnection,
pool: &'a DbPool,
unread_only: Option<bool>,
verified_email_only: Option<bool>,
page: Option<i64>,
@ -92,7 +101,8 @@ pub struct RegistrationApplicationQuery<'a> {
}
impl<'a> RegistrationApplicationQuery<'a> {
pub fn list(self) -> Result<Vec<RegistrationApplicationView>, Error> {
pub async fn list(self) -> Result<Vec<RegistrationApplicationView>, Error> {
let conn = &mut get_conn(self.pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let mut query = registration_application::table
@ -128,7 +138,7 @@ impl<'a> RegistrationApplicationQuery<'a> {
.offset(offset)
.order_by(registration_application::published.desc());
let res = query.load::<RegistrationApplicationViewTuple>(self.conn)?;
let res = query.load::<RegistrationApplicationViewTuple>(conn).await?;
Ok(RegistrationApplicationView::from_tuple_to_vec(res))
}
@ -167,16 +177,16 @@ mod tests {
},
},
traits::Crud,
utils::establish_unpooled_connection,
utils::build_db_pool_for_tests,
};
use serial_test::serial;
#[test]
#[tokio::test]
#[serial]
fn test_crud() {
let conn = &mut establish_unpooled_connection();
async fn test_crud() {
let pool = &build_db_pool_for_tests().await;
let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
let timmy_person_form = PersonInsertForm::builder()
.name("timmy_rav".into())
@ -185,14 +195,16 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_timmy_person = Person::create(conn, &timmy_person_form).unwrap();
let inserted_timmy_person = Person::create(pool, &timmy_person_form).await.unwrap();
let timmy_local_user_form = LocalUserInsertForm::builder()
.person_id(inserted_timmy_person.id)
.password_encrypted("nada".to_string())
.build();
let _inserted_timmy_local_user = LocalUser::create(conn, &timmy_local_user_form).unwrap();
let _inserted_timmy_local_user = LocalUser::create(pool, &timmy_local_user_form)
.await
.unwrap();
let sara_person_form = PersonInsertForm::builder()
.name("sara_rav".into())
@ -200,14 +212,16 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_sara_person = Person::create(conn, &sara_person_form).unwrap();
let inserted_sara_person = Person::create(pool, &sara_person_form).await.unwrap();
let sara_local_user_form = LocalUserInsertForm::builder()
.person_id(inserted_sara_person.id)
.password_encrypted("nada".to_string())
.build();
let inserted_sara_local_user = LocalUser::create(conn, &sara_local_user_form).unwrap();
let inserted_sara_local_user = LocalUser::create(pool, &sara_local_user_form)
.await
.unwrap();
// Sara creates an application
let sara_app_form = RegistrationApplicationInsertForm {
@ -215,9 +229,13 @@ mod tests {
answer: "LET ME IIIIINN".to_string(),
};
let sara_app = RegistrationApplication::create(conn, &sara_app_form).unwrap();
let sara_app = RegistrationApplication::create(pool, &sara_app_form)
.await
.unwrap();
let read_sara_app_view = RegistrationApplicationView::read(conn, sara_app.id).unwrap();
let read_sara_app_view = RegistrationApplicationView::read(pool, sara_app.id)
.await
.unwrap();
let jess_person_form = PersonInsertForm::builder()
.name("jess_rav".into())
@ -225,14 +243,16 @@ mod tests {
.instance_id(inserted_instance.id)
.build();
let inserted_jess_person = Person::create(conn, &jess_person_form).unwrap();
let inserted_jess_person = Person::create(pool, &jess_person_form).await.unwrap();
let jess_local_user_form = LocalUserInsertForm::builder()
.person_id(inserted_jess_person.id)
.password_encrypted("nada".to_string())
.build();
let inserted_jess_local_user = LocalUser::create(conn, &jess_local_user_form).unwrap();
let inserted_jess_local_user = LocalUser::create(pool, &jess_local_user_form)
.await
.unwrap();
// Sara creates an application
let jess_app_form = RegistrationApplicationInsertForm {
@ -240,9 +260,13 @@ mod tests {
answer: "LET ME IIIIINN".to_string(),
};
let jess_app = RegistrationApplication::create(conn, &jess_app_form).unwrap();
let jess_app = RegistrationApplication::create(pool, &jess_app_form)
.await
.unwrap();
let read_jess_app_view = RegistrationApplicationView::read(conn, jess_app.id).unwrap();
let read_jess_app_view = RegistrationApplicationView::read(pool, jess_app.id)
.await
.unwrap();
let mut expected_sara_app_view = RegistrationApplicationView {
registration_application: sara_app.to_owned(),
@ -293,10 +317,11 @@ mod tests {
// Do a batch read of the applications
let apps = RegistrationApplicationQuery::builder()
.conn(conn)
.pool(pool)
.unread_only(Some(true))
.build()
.list()
.await
.unwrap();
assert_eq!(
@ -308,7 +333,9 @@ mod tests {
);
// Make sure the counts are correct
let unread_count = RegistrationApplicationView::get_unread_count(conn, false).unwrap();
let unread_count = RegistrationApplicationView::get_unread_count(pool, false)
.await
.unwrap();
assert_eq!(unread_count, 2);
// Approve the application
@ -317,17 +344,22 @@ mod tests {
deny_reason: None,
};
RegistrationApplication::update(conn, sara_app.id, &approve_form).unwrap();
RegistrationApplication::update(pool, sara_app.id, &approve_form)
.await
.unwrap();
// Update the local_user row
let approve_local_user_form = LocalUserUpdateForm::builder()
.accepted_application(Some(true))
.build();
LocalUser::update(conn, inserted_sara_local_user.id, &approve_local_user_form).unwrap();
LocalUser::update(pool, inserted_sara_local_user.id, &approve_local_user_form)
.await
.unwrap();
let read_sara_app_view_after_approve =
RegistrationApplicationView::read(conn, sara_app.id).unwrap();
let read_sara_app_view_after_approve = RegistrationApplicationView::read(pool, sara_app.id)
.await
.unwrap();
// Make sure the columns changed
expected_sara_app_view
@ -361,29 +393,34 @@ mod tests {
// Do a batch read of apps again
// It should show only jessicas which is unresolved
let apps_after_resolve = RegistrationApplicationQuery::builder()
.conn(conn)
.pool(pool)
.unread_only(Some(true))
.build()
.list()
.await
.unwrap();
assert_eq!(apps_after_resolve, vec![read_jess_app_view]);
// Make sure the counts are correct
let unread_count_after_approve =
RegistrationApplicationView::get_unread_count(conn, false).unwrap();
let unread_count_after_approve = RegistrationApplicationView::get_unread_count(pool, false)
.await
.unwrap();
assert_eq!(unread_count_after_approve, 1);
// Make sure the not undenied_only has all the apps
let all_apps = RegistrationApplicationQuery::builder()
.conn(conn)
.pool(pool)
.build()
.list()
.await
.unwrap();
assert_eq!(all_apps.len(), 2);
Person::delete(conn, inserted_timmy_person.id).unwrap();
Person::delete(conn, inserted_sara_person.id).unwrap();
Person::delete(conn, inserted_jess_person.id).unwrap();
Instance::delete(conn, inserted_instance.id).unwrap();
Person::delete(pool, inserted_timmy_person.id)
.await
.unwrap();
Person::delete(pool, inserted_sara_person.id).await.unwrap();
Person::delete(pool, inserted_jess_person.id).await.unwrap();
Instance::delete(pool, inserted_instance.id).await.unwrap();
}
}

View file

@ -1,13 +1,16 @@
use crate::structs::SiteView;
use diesel::{result::Error, *};
use diesel::{result::Error, ExpressionMethods, JoinOnDsl, QueryDsl};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
aggregates::structs::SiteAggregates,
schema::{local_site, local_site_rate_limit, site, site_aggregates},
source::{local_site::LocalSite, local_site_rate_limit::LocalSiteRateLimit, site::Site},
utils::{get_conn, DbPool},
};
impl SiteView {
pub fn read_local(conn: &mut PgConnection) -> Result<Self, Error> {
pub async fn read_local(pool: &DbPool) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let (mut site, local_site, local_site_rate_limit, counts) = site::table
.inner_join(local_site::table)
.inner_join(
@ -20,7 +23,8 @@ impl SiteView {
local_site_rate_limit::all_columns,
site_aggregates::all_columns,
))
.first::<(Site, LocalSite, LocalSiteRateLimit, SiteAggregates)>(conn)?;
.first::<(Site, LocalSite, LocalSiteRateLimit, SiteAggregates)>(conn)
.await?;
site.private_key = None;
Ok(SiteView {

View file

@ -12,11 +12,11 @@ rust-version = "1.57"
doctest = false
[features]
full = ["lemmy_db_schema/full", "diesel"]
full = ["lemmy_db_schema/full", "diesel", "diesel-async"]
[dependencies]
lemmy_db_schema = { version = "=0.16.5", path = "../db_schema" }
diesel = { version = "2.0.2", features = ["postgres","chrono","serde_json"], optional = true }
diesel-async = { version = "0.1.1", features = ["postgres", "bb8"] }
diesel-async = { version = "0.1.1", features = ["postgres", "bb8"], optional = true }
serde = { version = "1.0.147", features = ["derive"] }
typed-builder = "0.10.0"

View file

@ -1,5 +1,14 @@
use crate::structs::CommentReplyView;
use diesel::{dsl::*, result::Error, *};
use diesel::{
dsl::*,
result::Error,
BoolExpressionMethods,
ExpressionMethods,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
aggregates::structs::CommentAggregates,
newtypes::{CommentReplyId, PersonId},
@ -25,7 +34,7 @@ use lemmy_db_schema::{
post::Post,
},
traits::{ToSafe, ViewToVec},
utils::{functions::hot_rank, limit_and_offset},
utils::{functions::hot_rank, get_conn, limit_and_offset, DbPool},
CommentSortType,
};
use typed_builder::TypedBuilder;
@ -46,11 +55,12 @@ type CommentReplyViewTuple = (
);
impl CommentReplyView {
pub fn read(
conn: &mut PgConnection,
pub async fn read(
pool: &DbPool,
comment_reply_id: CommentReplyId,
my_person_id: Option<PersonId>,
) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
// The left join below will return None in this case
@ -131,7 +141,8 @@ impl CommentReplyView {
person_block::all_columns.nullable(),
comment_like::score.nullable(),
))
.first::<CommentReplyViewTuple>(conn)?;
.first::<CommentReplyViewTuple>(conn)
.await?;
Ok(CommentReplyView {
comment_reply,
@ -150,9 +161,11 @@ impl CommentReplyView {
}
/// Gets the number of unread replies
pub fn get_unread_replies(conn: &mut PgConnection, my_person_id: PersonId) -> Result<i64, Error> {
pub async fn get_unread_replies(pool: &DbPool, my_person_id: PersonId) -> Result<i64, Error> {
use diesel::dsl::*;
let conn = &mut get_conn(&pool).await?;
comment_reply::table
.inner_join(comment::table)
.filter(comment_reply::recipient_id.eq(my_person_id))
@ -161,6 +174,7 @@ impl CommentReplyView {
.filter(comment::removed.eq(false))
.select(count(comment_reply::id))
.first::<i64>(conn)
.await
}
}
@ -168,7 +182,7 @@ impl CommentReplyView {
#[builder(field_defaults(default))]
pub struct CommentReplyQuery<'a> {
#[builder(!default)]
conn: &'a mut PgConnection,
pool: &'a DbPool,
my_person_id: Option<PersonId>,
recipient_id: Option<PersonId>,
sort: Option<CommentSortType>,
@ -179,8 +193,9 @@ pub struct CommentReplyQuery<'a> {
}
impl<'a> CommentReplyQuery<'a> {
pub fn list(self) -> Result<Vec<CommentReplyView>, Error> {
pub async fn list(self) -> Result<Vec<CommentReplyView>, Error> {
use diesel::dsl::*;
let conn = &mut get_conn(self.pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
@ -276,7 +291,8 @@ impl<'a> CommentReplyQuery<'a> {
let res = query
.limit(limit)
.offset(offset)
.load::<CommentReplyViewTuple>(self.conn)?;
.load::<CommentReplyViewTuple>(conn)
.await?;
Ok(CommentReplyView::from_tuple_to_vec(res))
}

View file

@ -1,5 +1,6 @@
use crate::structs::CommunityBlockView;
use diesel::{result::Error, *};
use diesel::{result::Error, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{community, community_block, person},
@ -8,12 +9,14 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ViewToVec},
utils::{get_conn, DbPool},
};
type CommunityBlockViewTuple = (PersonSafe, CommunitySafe);
impl CommunityBlockView {
pub fn for_person(conn: &mut PgConnection, person_id: PersonId) -> Result<Vec<Self>, Error> {
pub async fn for_person(pool: &DbPool, person_id: PersonId) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let res = community_block::table
.inner_join(person::table)
.inner_join(community::table)
@ -25,7 +28,8 @@ impl CommunityBlockView {
.filter(community::deleted.eq(false))
.filter(community::removed.eq(false))
.order_by(community_block::published)
.load::<CommunityBlockViewTuple>(conn)?;
.load::<CommunityBlockViewTuple>(conn)
.await?;
Ok(Self::from_tuple_to_vec(res))
}

View file

@ -1,5 +1,6 @@
use crate::structs::CommunityFollowerView;
use diesel::{result::Error, *};
use diesel::{result::Error, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::{CommunityId, PersonId},
schema::{community, community_follower, person},
@ -8,15 +9,14 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ViewToVec},
utils::{get_conn, DbPool},
};
type CommunityFollowerViewTuple = (CommunitySafe, PersonSafe);
impl CommunityFollowerView {
pub fn for_community(
conn: &mut PgConnection,
community_id: CommunityId,
) -> Result<Vec<Self>, Error> {
pub async fn for_community(pool: &DbPool, community_id: CommunityId) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let res = community_follower::table
.inner_join(community::table)
.inner_join(person::table)
@ -26,12 +26,14 @@ impl CommunityFollowerView {
))
.filter(community_follower::community_id.eq(community_id))
.order_by(community::title)
.load::<CommunityFollowerViewTuple>(conn)?;
.load::<CommunityFollowerViewTuple>(conn)
.await?;
Ok(Self::from_tuple_to_vec(res))
}
pub fn for_person(conn: &mut PgConnection, person_id: PersonId) -> Result<Vec<Self>, Error> {
pub async fn for_person(pool: &DbPool, person_id: PersonId) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let res = community_follower::table
.inner_join(community::table)
.inner_join(person::table)
@ -43,7 +45,8 @@ impl CommunityFollowerView {
.filter(community::deleted.eq(false))
.filter(community::removed.eq(false))
.order_by(community::title)
.load::<CommunityFollowerViewTuple>(conn)?;
.load::<CommunityFollowerViewTuple>(conn)
.await?;
Ok(Self::from_tuple_to_vec(res))
}

View file

@ -1,5 +1,6 @@
use crate::structs::CommunityModeratorView;
use diesel::{result::Error, *};
use diesel::{result::Error, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::{CommunityId, PersonId},
schema::{community, community_moderator, person},
@ -8,15 +9,14 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ViewToVec},
utils::{get_conn, DbPool},
};
type CommunityModeratorViewTuple = (CommunitySafe, PersonSafe);
impl CommunityModeratorView {
pub fn for_community(
conn: &mut PgConnection,
community_id: CommunityId,
) -> Result<Vec<Self>, Error> {
pub async fn for_community(pool: &DbPool, community_id: CommunityId) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let res = community_moderator::table
.inner_join(community::table)
.inner_join(person::table)
@ -26,12 +26,14 @@ impl CommunityModeratorView {
))
.filter(community_moderator::community_id.eq(community_id))
.order_by(community_moderator::published)
.load::<CommunityModeratorViewTuple>(conn)?;
.load::<CommunityModeratorViewTuple>(conn)
.await?;
Ok(Self::from_tuple_to_vec(res))
}
pub fn for_person(conn: &mut PgConnection, person_id: PersonId) -> Result<Vec<Self>, Error> {
pub async fn for_person(pool: &DbPool, person_id: PersonId) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let res = community_moderator::table
.inner_join(community::table)
.inner_join(person::table)
@ -43,14 +45,16 @@ impl CommunityModeratorView {
.filter(community::deleted.eq(false))
.filter(community::removed.eq(false))
.order_by(community_moderator::published)
.load::<CommunityModeratorViewTuple>(conn)?;
.load::<CommunityModeratorViewTuple>(conn)
.await?;
Ok(Self::from_tuple_to_vec(res))
}
/// Finds all communities first mods / creators
/// Ideally this should be a group by, but diesel doesn't support it yet
pub fn get_community_first_mods(conn: &mut PgConnection) -> Result<Vec<Self>, Error> {
pub async fn get_community_first_mods(pool: &DbPool) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let res = community_moderator::table
.inner_join(community::table)
.inner_join(person::table)
@ -65,7 +69,8 @@ impl CommunityModeratorView {
community_moderator::community_id,
community_moderator::person_id,
))
.load::<CommunityModeratorViewTuple>(conn)?;
.load::<CommunityModeratorViewTuple>(conn)
.await?;
Ok(Self::from_tuple_to_vec(res))
}

View file

@ -1,5 +1,6 @@
use crate::structs::CommunityPersonBanView;
use diesel::{dsl::*, result::Error, *};
use diesel::{dsl::*, result::Error, BoolExpressionMethods, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::{CommunityId, PersonId},
schema::{community, community_person_ban, person},
@ -8,14 +9,16 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::ToSafe,
utils::{get_conn, DbPool},
};
impl CommunityPersonBanView {
pub fn get(
conn: &mut PgConnection,
pub async fn get(
pool: &DbPool,
from_person_id: PersonId,
from_community_id: CommunityId,
) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let (community, person) = community_person_ban::table
.inner_join(community::table)
.inner_join(person::table)
@ -31,7 +34,8 @@ impl CommunityPersonBanView {
.or(community_person_ban::expires.gt(now)),
)
.order_by(community_person_ban::published)
.first::<(CommunitySafe, PersonSafe)>(conn)?;
.first::<(CommunitySafe, PersonSafe)>(conn)
.await?;
Ok(CommunityPersonBanView { community, person })
}

View file

@ -1,5 +1,14 @@
use crate::structs::{CommunityModeratorView, CommunityView, PersonViewSafe};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
JoinOnDsl,
NullableExpressionMethods,
PgTextExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
aggregates::structs::CommunityAggregates,
newtypes::{CommunityId, PersonId},
@ -10,7 +19,7 @@ use lemmy_db_schema::{
local_user::LocalUser,
},
traits::{ToSafe, ViewToVec},
utils::{functions::hot_rank, fuzzy_search, limit_and_offset},
utils::{functions::hot_rank, fuzzy_search, get_conn, limit_and_offset, DbPool},
ListingType,
SortType,
};
@ -24,11 +33,12 @@ type CommunityViewTuple = (
);
impl CommunityView {
pub fn read(
conn: &mut PgConnection,
pub async fn read(
pool: &DbPool,
community_id: CommunityId,
my_person_id: Option<PersonId>,
) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
// The left join below will return None in this case
let person_id_join = my_person_id.unwrap_or(PersonId(-1));
@ -55,7 +65,8 @@ impl CommunityView {
community_follower::all_columns.nullable(),
community_block::all_columns.nullable(),
))
.first::<CommunityViewTuple>(conn)?;
.first::<CommunityViewTuple>(conn)
.await?;
Ok(CommunityView {
community,
@ -65,12 +76,13 @@ impl CommunityView {
})
}
pub fn is_mod_or_admin(
conn: &mut PgConnection,
pub async fn is_mod_or_admin(
pool: &DbPool,
person_id: PersonId,
community_id: CommunityId,
) -> bool {
let is_mod = CommunityModeratorView::for_community(conn, community_id)
) -> Result<bool, Error> {
let is_mod = CommunityModeratorView::for_community(pool, community_id)
.await
.map(|v| {
v.into_iter()
.map(|m| m.moderator.id)
@ -79,17 +91,19 @@ impl CommunityView {
.unwrap_or_default()
.contains(&person_id);
if is_mod {
return true;
return Ok(true);
}
PersonViewSafe::admins(conn)
let is_admin = PersonViewSafe::admins(pool)
.await
.map(|v| {
v.into_iter()
.map(|a| a.person.id)
.collect::<Vec<PersonId>>()
})
.unwrap_or_default()
.contains(&person_id)
.contains(&person_id);
Ok(is_admin)
}
}
@ -97,7 +111,7 @@ impl CommunityView {
#[builder(field_defaults(default))]
pub struct CommunityQuery<'a> {
#[builder(!default)]
conn: &'a mut PgConnection,
pool: &'a DbPool,
listing_type: Option<ListingType>,
sort: Option<SortType>,
local_user: Option<&'a LocalUser>,
@ -107,7 +121,9 @@ pub struct CommunityQuery<'a> {
}
impl<'a> CommunityQuery<'a> {
pub fn list(self) -> Result<Vec<CommunityView>, Error> {
pub async fn list(self) -> Result<Vec<CommunityView>, Error> {
let conn = &mut get_conn(self.pool).await?;
// The left join below will return None in this case
let person_id_join = self.local_user.map(|l| l.person_id).unwrap_or(PersonId(-1));
@ -203,7 +219,8 @@ impl<'a> CommunityQuery<'a> {
.offset(offset)
.filter(community::removed.eq(false))
.filter(community::deleted.eq(false))
.load::<CommunityViewTuple>(self.conn)?;
.load::<CommunityViewTuple>(conn)
.await?;
Ok(CommunityView::from_tuple_to_vec(res))
}

View file

@ -1,16 +1,19 @@
use crate::structs::PersonBlockView;
use diesel::{result::Error, *};
use diesel::{result::Error, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{person, person_block},
source::person::{Person, PersonSafe},
traits::{ToSafe, ViewToVec},
utils::{get_conn, DbPool},
};
type PersonBlockViewTuple = (PersonSafe, PersonSafe);
impl PersonBlockView {
pub fn for_person(conn: &mut PgConnection, person_id: PersonId) -> Result<Vec<Self>, Error> {
pub async fn for_person(pool: &DbPool, person_id: PersonId) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let res = person_block::table
@ -23,7 +26,8 @@ impl PersonBlockView {
.filter(person_block::person_id.eq(person_id))
.filter(person_alias_1.field(person::deleted).eq(false))
.order_by(person_block::published)
.load::<PersonBlockViewTuple>(conn)?;
.load::<PersonBlockViewTuple>(conn)
.await?;
Ok(Self::from_tuple_to_vec(res))
}

View file

@ -1,5 +1,14 @@
use crate::structs::PersonMentionView;
use diesel::{dsl::*, result::Error, *};
use diesel::{
dsl::*,
result::Error,
BoolExpressionMethods,
ExpressionMethods,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
aggregates::structs::CommentAggregates,
newtypes::{PersonId, PersonMentionId},
@ -25,7 +34,7 @@ use lemmy_db_schema::{
post::Post,
},
traits::{ToSafe, ViewToVec},
utils::{functions::hot_rank, limit_and_offset},
utils::{functions::hot_rank, get_conn, limit_and_offset, DbPool},
CommentSortType,
};
use typed_builder::TypedBuilder;
@ -46,11 +55,12 @@ type PersonMentionViewTuple = (
);
impl PersonMentionView {
pub fn read(
conn: &mut PgConnection,
pub async fn read(
pool: &DbPool,
person_mention_id: PersonMentionId,
my_person_id: Option<PersonId>,
) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
// The left join below will return None in this case
@ -131,7 +141,8 @@ impl PersonMentionView {
person_block::all_columns.nullable(),
comment_like::score.nullable(),
))
.first::<PersonMentionViewTuple>(conn)?;
.first::<PersonMentionViewTuple>(conn)
.await?;
Ok(PersonMentionView {
person_mention,
@ -150,11 +161,9 @@ impl PersonMentionView {
}
/// Gets the number of unread mentions
pub fn get_unread_mentions(
conn: &mut PgConnection,
my_person_id: PersonId,
) -> Result<i64, Error> {
pub async fn get_unread_mentions(pool: &DbPool, my_person_id: PersonId) -> Result<i64, Error> {
use diesel::dsl::*;
let conn = &mut get_conn(&pool).await?;
person_mention::table
.inner_join(comment::table)
@ -164,6 +173,7 @@ impl PersonMentionView {
.filter(comment::removed.eq(false))
.select(count(person_mention::id))
.first::<i64>(conn)
.await
}
}
@ -171,7 +181,7 @@ impl PersonMentionView {
#[builder(field_defaults(default))]
pub struct PersonMentionQuery<'a> {
#[builder(!default)]
conn: &'a mut PgConnection,
pool: &'a DbPool,
my_person_id: Option<PersonId>,
recipient_id: Option<PersonId>,
sort: Option<CommentSortType>,
@ -182,8 +192,9 @@ pub struct PersonMentionQuery<'a> {
}
impl<'a> PersonMentionQuery<'a> {
pub fn list(self) -> Result<Vec<PersonMentionView>, Error> {
pub async fn list(self) -> Result<Vec<PersonMentionView>, Error> {
use diesel::dsl::*;
let conn = &mut get_conn(self.pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
@ -279,7 +290,8 @@ impl<'a> PersonMentionQuery<'a> {
let res = query
.limit(limit)
.offset(offset)
.load::<PersonMentionViewTuple>(self.conn)?;
.load::<PersonMentionViewTuple>(conn)
.await?;
Ok(PersonMentionView::from_tuple_to_vec(res))
}

View file

@ -1,42 +1,55 @@
use crate::structs::PersonViewSafe;
use diesel::{dsl::*, result::Error, *};
use diesel::{
dsl::*,
result::Error,
BoolExpressionMethods,
ExpressionMethods,
PgTextExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
aggregates::structs::PersonAggregates,
newtypes::PersonId,
schema::{person, person_aggregates},
source::person::{Person, PersonSafe},
traits::{ToSafe, ViewToVec},
utils::{fuzzy_search, limit_and_offset, DbPool},
utils::{fuzzy_search, get_conn, limit_and_offset, DbPool},
SortType,
};
use std::iter::Iterator;
use typed_builder::TypedBuilder;
type PersonViewSafeTuple = (PersonSafe, PersonAggregates);
impl PersonViewSafe {
pub fn read(conn: &mut PgConnection, person_id: PersonId) -> Result<Self, Error> {
pub async fn read(pool: &DbPool, person_id: PersonId) -> Result<Self, Error> {
let conn = &mut get_conn(&pool).await?;
let (person, counts) = person::table
.find(person_id)
.inner_join(person_aggregates::table)
.select((Person::safe_columns_tuple(), person_aggregates::all_columns))
.first::<PersonViewSafeTuple>(conn)?;
.first::<PersonViewSafeTuple>(conn)
.await?;
Ok(Self { person, counts })
}
pub async fn admins(pool: &DbPool) -> Result<Vec<Self>, Error> {
let conn = pool.get().await?;
let conn = &mut get_conn(&pool).await?;
let admins = person::table
.inner_join(person_aggregates::table)
.select((Person::safe_columns_tuple(), person_aggregates::all_columns))
.filter(person::admin.eq(true))
.filter(person::deleted.eq(false))
.order_by(person::published)
.load::<PersonViewSafeTuple>(conn)?;
.load::<PersonViewSafeTuple>(conn)
.await?;
Ok(Self::from_tuple_to_vec(admins))
}
pub fn banned(conn: &mut PgConnection) -> Result<Vec<Self>, Error> {
pub async fn banned(pool: &DbPool) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let banned = person::table
.inner_join(person_aggregates::table)
.select((Person::safe_columns_tuple(), person_aggregates::all_columns))
@ -48,7 +61,8 @@ impl PersonViewSafe {
),
)
.filter(person::deleted.eq(false))
.load::<PersonViewSafeTuple>(conn)?;
.load::<PersonViewSafeTuple>(conn)
.await?;
Ok(Self::from_tuple_to_vec(banned))
}
@ -58,7 +72,7 @@ impl PersonViewSafe {
#[builder(field_defaults(default))]
pub struct PersonQuery<'a> {
#[builder(!default)]
conn: &'a mut PgConnection,
pool: &'a DbPool,
sort: Option<SortType>,
search_term: Option<String>,
page: Option<i64>,
@ -66,7 +80,8 @@ pub struct PersonQuery<'a> {
}
impl<'a> PersonQuery<'a> {
pub fn list(self) -> Result<Vec<PersonViewSafe>, Error> {
pub async fn list(self) -> Result<Vec<PersonViewSafe>, Error> {
let conn = &mut get_conn(self.pool).await?;
let mut query = person::table
.inner_join(person_aggregates::table)
.select((Person::safe_columns_tuple(), person_aggregates::all_columns))
@ -108,7 +123,7 @@ impl<'a> PersonQuery<'a> {
let (limit, offset) = limit_and_offset(self.page, self.limit)?;
query = query.limit(limit).offset(offset);
let res = query.load::<PersonViewSafeTuple>(self.conn)?;
let res = query.load::<PersonViewSafeTuple>(conn).await?;
Ok(PersonViewSafe::from_tuple_to_vec(res))
}

View file

@ -12,9 +12,10 @@ rust-version = "1.57"
doctest = false
[features]
full = ["lemmy_db_schema/full", "diesel"]
full = ["lemmy_db_schema/full", "diesel", "diesel-async"]
[dependencies]
lemmy_db_schema = { version = "=0.16.5", path = "../db_schema" }
diesel = { version = "2.0.2", features = ["postgres","chrono","serde_json"], optional = true }
diesel-async = { version = "0.1.1", features = ["postgres", "bb8"], optional = true }
serde = { version = "1.0.147", features = ["derive"] }

View file

@ -1,5 +1,14 @@
use crate::structs::{AdminPurgeCommentView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{admin_purge_comment, person, post},
@ -9,13 +18,14 @@ use lemmy_db_schema::{
post::Post,
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type AdminPurgeCommentViewTuple = (AdminPurgeComment, Option<PersonSafe>, Post);
impl AdminPurgeCommentView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
@ -44,7 +54,8 @@ impl AdminPurgeCommentView {
.limit(limit)
.offset(offset)
.order_by(admin_purge_comment::when_.desc())
.load::<AdminPurgeCommentViewTuple>(conn)?;
.load::<AdminPurgeCommentViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{AdminPurgeCommunityView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{admin_purge_community, person},
@ -8,13 +17,14 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type AdminPurgeCommunityViewTuple = (AdminPurgeCommunity, Option<PersonSafe>);
impl AdminPurgeCommunityView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
@ -41,7 +51,8 @@ impl AdminPurgeCommunityView {
.limit(limit)
.offset(offset)
.order_by(admin_purge_community::when_.desc())
.load::<AdminPurgeCommunityViewTuple>(conn)?;
.load::<AdminPurgeCommunityViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{AdminPurgePersonView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{admin_purge_person, person},
@ -8,13 +17,15 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type AdminPurgePersonViewTuple = (AdminPurgePerson, Option<PersonSafe>);
impl AdminPurgePersonView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
@ -40,7 +51,8 @@ impl AdminPurgePersonView {
.limit(limit)
.offset(offset)
.order_by(admin_purge_person::when_.desc())
.load::<AdminPurgePersonViewTuple>(conn)?;
.load::<AdminPurgePersonViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{AdminPurgePostView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{admin_purge_post, community, person},
@ -9,13 +18,15 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type AdminPurgePostViewTuple = (AdminPurgePost, Option<PersonSafe>, CommunitySafe);
impl AdminPurgePostView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
@ -43,7 +54,8 @@ impl AdminPurgePostView {
.limit(limit)
.offset(offset)
.order_by(admin_purge_post::when_.desc())
.load::<AdminPurgePostViewTuple>(conn)?;
.load::<AdminPurgePostViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{ModAddCommunityView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{community, mod_add_community, person},
@ -9,7 +18,7 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type ModAddCommunityViewTuple = (
@ -20,7 +29,8 @@ type ModAddCommunityViewTuple = (
);
impl ModAddCommunityView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
@ -61,7 +71,8 @@ impl ModAddCommunityView {
.limit(limit)
.offset(offset)
.order_by(mod_add_community::when_.desc())
.load::<ModAddCommunityViewTuple>(conn)?;
.load::<ModAddCommunityViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{ModAddView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{mod_add, person},
@ -8,13 +17,14 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type ModAddViewTuple = (ModAdd, Option<PersonSafe>, PersonSafe);
impl ModAddView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
@ -47,7 +57,8 @@ impl ModAddView {
.limit(limit)
.offset(offset)
.order_by(mod_add::when_.desc())
.load::<ModAddViewTuple>(conn)?;
.load::<ModAddViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{ModBanFromCommunityView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{community, mod_ban_from_community, person},
@ -9,7 +18,7 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type ModBanFromCommunityViewTuple = (
@ -20,7 +29,9 @@ type ModBanFromCommunityViewTuple = (
);
impl ModBanFromCommunityView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
@ -62,7 +73,8 @@ impl ModBanFromCommunityView {
.limit(limit)
.offset(offset)
.order_by(mod_ban_from_community::when_.desc())
.load::<ModBanFromCommunityViewTuple>(conn)?;
.load::<ModBanFromCommunityViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{ModBanView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{mod_ban, person},
@ -8,13 +17,14 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type ModBanViewTuple = (ModBan, Option<PersonSafe>, PersonSafe);
impl ModBanView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
@ -47,7 +57,8 @@ impl ModBanView {
.limit(limit)
.offset(offset)
.order_by(mod_ban::when_.desc())
.load::<ModBanViewTuple>(conn)?;
.load::<ModBanViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{ModHideCommunityView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{community, mod_hide_community, person},
@ -9,14 +18,16 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type ModHideCommunityViewTuple = (ModHideCommunity, Option<PersonSafe>, CommunitySafe);
impl ModHideCommunityView {
// Pass in mod_id as admin_id because only admins can do this action
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
@ -48,7 +59,8 @@ impl ModHideCommunityView {
.limit(limit)
.offset(offset)
.order_by(mod_hide_community::when_.desc())
.load::<ModHideCommunityViewTuple>(conn)?;
.load::<ModHideCommunityViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{ModLockPostView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{community, mod_lock_post, person, post},
@ -10,13 +19,15 @@ use lemmy_db_schema::{
post::Post,
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type ModLockPostViewTuple = (ModLockPost, Option<PersonSafe>, Post, CommunitySafe);
impl ModLockPostView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
@ -56,7 +67,8 @@ impl ModLockPostView {
.limit(limit)
.offset(offset)
.order_by(mod_lock_post::when_.desc())
.load::<ModLockPostViewTuple>(conn)?;
.load::<ModLockPostViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{ModRemoveCommentView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{comment, community, mod_remove_comment, person, post},
@ -11,7 +20,7 @@ use lemmy_db_schema::{
post::Post,
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type ModRemoveCommentViewTuple = (
@ -24,7 +33,8 @@ type ModRemoveCommentViewTuple = (
);
impl ModRemoveCommentView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(lemmy_db_schema::schema::person as person1);
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
@ -67,7 +77,8 @@ impl ModRemoveCommentView {
.limit(limit)
.offset(offset)
.order_by(mod_remove_comment::when_.desc())
.load::<ModRemoveCommentViewTuple>(conn)?;
.load::<ModRemoveCommentViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{ModRemoveCommunityView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{community, mod_remove_community, person},
@ -9,13 +18,14 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type ModRemoveCommunityTuple = (ModRemoveCommunity, Option<PersonSafe>, CommunitySafe);
impl ModRemoveCommunityView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
@ -43,7 +53,8 @@ impl ModRemoveCommunityView {
.limit(limit)
.offset(offset)
.order_by(mod_remove_community::when_.desc())
.load::<ModRemoveCommunityTuple>(conn)?;
.load::<ModRemoveCommunityTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{ModRemovePostView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{community, mod_remove_post, person, post},
@ -10,13 +19,15 @@ use lemmy_db_schema::{
post::Post,
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type ModRemovePostViewTuple = (ModRemovePost, Option<PersonSafe>, Post, CommunitySafe);
impl ModRemovePostView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
@ -56,7 +67,8 @@ impl ModRemovePostView {
.limit(limit)
.offset(offset)
.order_by(mod_remove_post::when_.desc())
.load::<ModRemovePostViewTuple>(conn)?;
.load::<ModRemovePostViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{ModStickyPostView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{community, mod_sticky_post, person, post},
@ -10,13 +19,14 @@ use lemmy_db_schema::{
post::Post,
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type ModStickyPostViewTuple = (ModStickyPost, Option<PersonSafe>, Post, CommunitySafe);
impl ModStickyPostView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
@ -56,7 +66,8 @@ impl ModStickyPostView {
.limit(limit)
.offset(offset)
.order_by(mod_sticky_post::when_.desc())
.load::<ModStickyPostViewTuple>(conn)?;
.load::<ModStickyPostViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)

View file

@ -1,5 +1,14 @@
use crate::structs::{ModTransferCommunityView, ModlogListParams};
use diesel::{result::Error, *};
use diesel::{
result::Error,
BoolExpressionMethods,
ExpressionMethods,
IntoSql,
JoinOnDsl,
NullableExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::PersonId,
schema::{community, mod_transfer_community, person},
@ -9,7 +18,7 @@ use lemmy_db_schema::{
person::{Person, PersonSafe},
},
traits::{ToSafe, ViewToVec},
utils::limit_and_offset,
utils::{get_conn, limit_and_offset, DbPool},
};
type ModTransferCommunityViewTuple = (
@ -20,7 +29,9 @@ type ModTransferCommunityViewTuple = (
);
impl ModTransferCommunityView {
pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(&pool).await?;
let person_alias_1 = diesel::alias!(person as person1);
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
let show_mod_names = !params.hide_modlog_names;
@ -62,7 +73,8 @@ impl ModTransferCommunityView {
.limit(limit)
.offset(offset)
.order_by(mod_transfer_community::when_.desc())
.load::<ModTransferCommunityViewTuple>(conn)?;
.load::<ModTransferCommunityViewTuple>(conn)
.await?;
let results = Self::from_tuple_to_vec(res);
Ok(results)