X-Git-Url: http://these/git/?a=blobdiff_plain;f=crates%2Fdb_views_actor%2Fsrc%2Fperson_view.rs;h=dd4edcaf0c5dec24ab318e15115a594e50428909;hb=9a5a13c734a1792511e1bfef7b9ac4121e0e7371;hp=55a64819953f35979a93c5a5c2da18b4b167896f;hpb=ee416543943a82e552177c9f4ca67d8b1fb15dc2;p=lemmy.git diff --git a/crates/db_views_actor/src/person_view.rs b/crates/db_views_actor/src/person_view.rs index 55a64819..dd4edcaf 100644 --- a/crates/db_views_actor/src/person_view.rs +++ b/crates/db_views_actor/src/person_view.rs @@ -1,127 +1,139 @@ -use crate::structs::PersonViewSafe; -use diesel::{dsl::*, result::Error, *}; +use crate::structs::PersonView; +use diesel::{ + dsl::now, + pg::Pg, + result::Error, + BoolExpressionMethods, + ExpressionMethods, + PgTextExpressionMethods, + QueryDsl, +}; +use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aggregates::structs::PersonAggregates, newtypes::PersonId, + schema, schema::{person, person_aggregates}, - source::person::{Person, PersonSafe}, - traits::{ToSafe, ViewToVec}, - utils::{fuzzy_search, limit_and_offset}, - SortType, + source::person::Person, + traits::JoinView, + utils::{fuzzy_search, get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, + PersonSortType, }; -use typed_builder::TypedBuilder; -type PersonViewSafeTuple = (PersonSafe, PersonAggregates); +type PersonViewTuple = (Person, PersonAggregates); -impl PersonViewSafe { - pub fn read(conn: &mut PgConnection, person_id: PersonId) -> Result { - let (person, counts) = person::table - .find(person_id) - .inner_join(person_aggregates::table) - .select((Person::safe_columns_tuple(), person_aggregates::all_columns)) - .first::(conn)?; - Ok(Self { person, counts }) - } +enum ListMode { + Admins, + Banned, + Query(PersonQuery), +} - pub fn admins(conn: &mut PgConnection) -> Result, Error> { - let admins = person::table +fn queries<'a>( +) -> Queries, impl ListFn<'a, PersonView, ListMode>> { + let all_joins = |query: person::BoxedQuery<'a, Pg>| { + query .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::(conn)?; + .select((person::all_columns, person_aggregates::all_columns)) + }; - Ok(Self::from_tuple_to_vec(admins)) - } + let read = move |mut conn: DbConn<'a>, person_id: PersonId| async move { + all_joins(person::table.find(person_id).into_boxed()) + .first::(&mut conn) + .await + }; - pub fn banned(conn: &mut PgConnection) -> Result, Error> { - let banned = person::table - .inner_join(person_aggregates::table) - .select((Person::safe_columns_tuple(), person_aggregates::all_columns)) - .filter( - person::banned.eq(true).and( - person::ban_expires - .is_null() - .or(person::ban_expires.gt(now)), - ), - ) - .filter(person::deleted.eq(false)) - .load::(conn)?; + let list = move |mut conn: DbConn<'a>, mode: ListMode| async move { + let mut query = all_joins(person::table.into_boxed()); + match mode { + ListMode::Admins => { + query = query + .filter(person::admin.eq(true)) + .filter(person::deleted.eq(false)) + .order_by(person::published); + } + ListMode::Banned => { + query = query + .filter( + person::banned.eq(true).and( + person::ban_expires + .is_null() + .or(person::ban_expires.gt(now)), + ), + ) + .filter(person::deleted.eq(false)); + } + ListMode::Query(options) => { + if let Some(search_term) = options.search_term { + let searcher = fuzzy_search(&search_term); + query = query + .filter(person::name.ilike(searcher.clone())) + .or_filter(person::display_name.ilike(searcher)); + } - Ok(Self::from_tuple_to_vec(banned)) - } -} + query = match options.sort.unwrap_or(PersonSortType::CommentScore) { + PersonSortType::New => query.order_by(person::published.desc()), + PersonSortType::Old => query.order_by(person::published.asc()), + PersonSortType::MostComments => query.order_by(person_aggregates::comment_count.desc()), + PersonSortType::CommentScore => query.order_by(person_aggregates::comment_score.desc()), + PersonSortType::PostScore => query.order_by(person_aggregates::post_score.desc()), + PersonSortType::PostCount => query.order_by(person_aggregates::post_count.desc()), + }; -#[derive(TypedBuilder)] -#[builder(field_defaults(default))] -pub struct PersonQuery<'a> { - #[builder(!default)] - conn: &'a mut PgConnection, - sort: Option, - search_term: Option, - page: Option, - limit: Option, + let (limit, offset) = limit_and_offset(options.page, options.limit)?; + query = query.limit(limit).offset(offset); + } + } + query.load::(&mut conn).await + }; + + Queries::new(read, list) } -impl<'a> PersonQuery<'a> { - pub fn list(self) -> Result, Error> { - let mut query = person::table - .inner_join(person_aggregates::table) - .select((Person::safe_columns_tuple(), person_aggregates::all_columns)) - .into_boxed(); +impl PersonView { + pub async fn read(pool: &mut DbPool<'_>, person_id: PersonId) -> Result { + queries().read(pool, person_id).await + } - if let Some(search_term) = self.search_term { - let searcher = fuzzy_search(&search_term); - query = query - .filter(person::name.ilike(searcher.to_owned())) - .or_filter(person::display_name.ilike(searcher)); - } + pub async fn is_admin(pool: &mut DbPool<'_>, person_id: PersonId) -> Result { + use schema::person::dsl::{admin, id, person}; + let conn = &mut get_conn(pool).await?; + let is_admin = person + .filter(id.eq(person_id)) + .select(admin) + .first::(conn) + .await?; + Ok(is_admin) + } - query = match self.sort.unwrap_or(SortType::Hot) { - SortType::Hot => query - .order_by(person_aggregates::comment_score.desc()) - .then_order_by(person::published.desc()), - SortType::Active => query - .order_by(person_aggregates::comment_score.desc()) - .then_order_by(person::published.desc()), - SortType::New | SortType::MostComments | SortType::NewComments => { - query.order_by(person::published.desc()) - } - SortType::Old => query.order_by(person::published.asc()), - SortType::TopAll => query.order_by(person_aggregates::comment_score.desc()), - SortType::TopYear => query - .filter(person::published.gt(now - 1.years())) - .order_by(person_aggregates::comment_score.desc()), - SortType::TopMonth => query - .filter(person::published.gt(now - 1.months())) - .order_by(person_aggregates::comment_score.desc()), - SortType::TopWeek => query - .filter(person::published.gt(now - 1.weeks())) - .order_by(person_aggregates::comment_score.desc()), - SortType::TopDay => query - .filter(person::published.gt(now - 1.days())) - .order_by(person_aggregates::comment_score.desc()), - }; + pub async fn admins(pool: &mut DbPool<'_>) -> Result, Error> { + queries().list(pool, ListMode::Admins).await + } - let (limit, offset) = limit_and_offset(self.page, self.limit)?; - query = query.limit(limit).offset(offset); + pub async fn banned(pool: &mut DbPool<'_>) -> Result, Error> { + queries().list(pool, ListMode::Banned).await + } +} - let res = query.load::(self.conn)?; +#[derive(Default)] +pub struct PersonQuery { + pub sort: Option, + pub search_term: Option, + pub page: Option, + pub limit: Option, +} - Ok(PersonViewSafe::from_tuple_to_vec(res)) +impl PersonQuery { + pub async fn list(self, pool: &mut DbPool<'_>) -> Result, Error> { + queries().list(pool, ListMode::Query(self)).await } } -impl ViewToVec for PersonViewSafe { - type DbTuple = PersonViewSafeTuple; - fn from_tuple_to_vec(items: Vec) -> Vec { - items - .into_iter() - .map(|a| Self { - person: a.0, - counts: a.1, - }) - .collect::>() +impl JoinView for PersonView { + type JoinTuple = PersonViewTuple; + fn from_tuple(a: Self::JoinTuple) -> Self { + Self { + person: a.0, + counts: a.1, + } } }