X-Git-Url: http://these/git/?a=blobdiff_plain;f=crates%2Fdb_views_actor%2Fsrc%2Fperson_view.rs;h=dd4edcaf0c5dec24ab318e15115a594e50428909;hb=9a5a13c734a1792511e1bfef7b9ac4121e0e7371;hp=861d333fe83272475f58df9fbba9611a0dff3bd0;hpb=f8cd6fd445daf9040e4283313c81bdf614d89746;p=lemmy.git diff --git a/crates/db_views_actor/src/person_view.rs b/crates/db_views_actor/src/person_view.rs index 861d333f..dd4edcaf 100644 --- a/crates/db_views_actor/src/person_view.rs +++ b/crates/db_views_actor/src/person_view.rs @@ -1,152 +1,139 @@ -use diesel::{dsl::*, result::Error, *}; -use lemmy_db_queries::{ - aggregates::person_aggregates::PersonAggregates, - fuzzy_search, - limit_and_offset, - MaybeOptional, - SortType, - ToSafe, - ViewToVec, +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}, - PersonId, + source::person::Person, + traits::JoinView, + utils::{fuzzy_search, get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, + PersonSortType, }; -use serde::Serialize; -#[derive(Debug, Serialize, Clone)] -pub struct PersonViewSafe { - pub person: PersonSafe, - pub counts: PersonAggregates, -} - -type PersonViewSafeTuple = (PersonSafe, PersonAggregates); - -impl PersonViewSafe { - pub fn read(conn: &PgConnection, 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 }) - } - - pub fn admins(conn: &PgConnection) -> Result, Error> { - let admins = person::table - .inner_join(person_aggregates::table) - .select((Person::safe_columns_tuple(), person_aggregates::all_columns)) - .filter(person::admin.eq(true)) - .order_by(person::published) - .load::(conn)?; +type PersonViewTuple = (Person, PersonAggregates); - Ok(Self::from_tuple_to_vec(admins)) - } +enum ListMode { + Admins, + Banned, + Query(PersonQuery), +} - pub fn banned(conn: &PgConnection) -> Result, Error> { - let banned = 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::banned.eq(true)) - .load::(conn)?; - - Ok(Self::from_tuple_to_vec(banned)) - } -} + .select((person::all_columns, person_aggregates::all_columns)) + }; + + 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 + }; + + 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)); + } + + 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()), + }; + + let (limit, offset) = limit_and_offset(options.page, options.limit)?; + query = query.limit(limit).offset(offset); + } + } + query.load::(&mut conn).await + }; -pub struct PersonQueryBuilder<'a> { - conn: &'a PgConnection, - sort: Option, - search_term: Option, - page: Option, - limit: Option, + Queries::new(read, list) } -impl<'a> PersonQueryBuilder<'a> { - pub fn create(conn: &'a PgConnection) -> Self { - PersonQueryBuilder { - conn, - search_term: None, - sort: None, - page: None, - limit: None, - } - } - - pub fn sort>(mut self, sort: T) -> Self { - self.sort = sort.get_optional(); - self +impl PersonView { + pub async fn read(pool: &mut DbPool<'_>, person_id: PersonId) -> Result { + queries().read(pool, person_id).await } - pub fn search_term>(mut self, search_term: T) -> Self { - self.search_term = search_term.get_optional(); - self + 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) } - pub fn page>(mut self, page: T) -> Self { - self.page = page.get_optional(); - self + pub async fn admins(pool: &mut DbPool<'_>) -> Result, Error> { + queries().list(pool, ListMode::Admins).await } - pub fn limit>(mut self, limit: T) -> Self { - self.limit = limit.get_optional(); - self + pub async fn banned(pool: &mut DbPool<'_>) -> Result, Error> { + queries().list(pool, ListMode::Banned).await } +} - 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(); - - if let Some(search_term) = self.search_term { - query = query.filter(person::name.ilike(fuzzy_search(&search_term))); - } - - 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::TopAll => query.order_by(person_aggregates::comment_score.desc()), - SortType::TopYear => query - .filter(person::published.gt(now - 1.years())) - .order_by(person_aggregates::comment_score.desc()), - SortType::TopMonth => query - .filter(person::published.gt(now - 1.months())) - .order_by(person_aggregates::comment_score.desc()), - SortType::TopWeek => query - .filter(person::published.gt(now - 1.weeks())) - .order_by(person_aggregates::comment_score.desc()), - SortType::TopDay => query - .filter(person::published.gt(now - 1.days())) - .order_by(person_aggregates::comment_score.desc()), - }; - - let (limit, offset) = limit_and_offset(self.page, self.limit); - query = query.limit(limit).offset(offset); - - let res = query.load::(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 - .iter() - .map(|a| Self { - person: a.0.to_owned(), - counts: a.1.to_owned(), - }) - .collect::>() +impl JoinView for PersonView { + type JoinTuple = PersonViewTuple; + fn from_tuple(a: Self::JoinTuple) -> Self { + Self { + person: a.0, + counts: a.1, + } } }