From 028d1d0efc78451c0002a009b73fd7e1174886d2 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 4 Dec 2020 23:18:30 -0500 Subject: [PATCH] Userview safe updated. --- lemmy_db/src/lib.rs | 5 ++ lemmy_db/src/user.rs | 94 +++++++++++++++++----------- lemmy_db/src/views/community_view.rs | 11 +++- lemmy_db/src/views/site_view.rs | 9 ++- lemmy_db/src/views/user_view.rs | 48 +++++++------- 5 files changed, 98 insertions(+), 69 deletions(-) diff --git a/lemmy_db/src/lib.rs b/lemmy_db/src/lib.rs index 61a2120d1..4f2e85cd4 100644 --- a/lemmy_db/src/lib.rs +++ b/lemmy_db/src/lib.rs @@ -140,6 +140,11 @@ impl MaybeOptional for Option { } } +pub(crate) trait ToSafe { + type SafeColumns; + fn safe_columns_tuple() -> Self::SafeColumns; +} + pub fn get_database_url_from_env() -> Result { env::var("LEMMY_DATABASE_URL") } diff --git a/lemmy_db/src/user.rs b/lemmy_db/src/user.rs index 96483c1d7..389554263 100644 --- a/lemmy_db/src/user.rs +++ b/lemmy_db/src/user.rs @@ -40,6 +40,26 @@ pub struct User_ { pub deleted: bool, } +/// A safe representation of user, without the sensitive info +#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] +#[table_name = "user_"] +pub struct UserSafe { + pub id: i32, + pub name: String, + pub preferred_username: Option, + pub avatar: Option, + pub admin: bool, + pub banned: bool, + pub published: chrono::NaiveDateTime, + pub updated: Option, + pub matrix_user_id: Option, + pub actor_id: String, + pub bio: Option, + pub local: bool, + pub banner: Option, + pub deleted: bool, +} + #[derive(Insertable, AsChangeset, Clone)] #[table_name = "user_"] pub struct UserForm { @@ -69,25 +89,6 @@ pub struct UserForm { pub banner: Option>, } -/// A safe representation of user, without the sensitive info -#[derive(Clone, Debug, Serialize)] -pub struct UserSafe { - pub id: i32, - pub name: String, - pub preferred_username: Option, - pub avatar: Option, - pub admin: bool, - pub banned: bool, - pub published: chrono::NaiveDateTime, - pub updated: Option, - pub matrix_user_id: Option, - pub actor_id: String, - pub bio: Option, - pub local: bool, - pub banner: Option, - pub deleted: bool, -} - impl Crud for User_ { fn read(conn: &PgConnection, user_id: i32) -> Result { user_ @@ -219,23 +220,46 @@ impl User_ { )) .get_result::(conn) } +} - pub fn to_safe(&self) -> UserSafe { - UserSafe { - id: self.id, - name: self.name.to_owned(), - preferred_username: self.preferred_username.to_owned(), - avatar: self.avatar.to_owned(), - admin: self.admin, - banned: self.banned, - published: self.published, - updated: self.updated, - matrix_user_id: self.matrix_user_id.to_owned(), - actor_id: self.actor_id.to_owned(), - bio: self.bio.to_owned(), - local: self.local, - banner: self.banner.to_owned(), - deleted: self.deleted, +mod safe_type { + use crate::{schema::user_::columns::*, user::User_, ToSafe}; + type Columns = ( + id, + name, + preferred_username, + avatar, + admin, + banned, + published, + updated, + matrix_user_id, + actor_id, + bio, + local, + banner, + deleted, + ); + + impl ToSafe for User_ { + type SafeColumns = Columns; + fn safe_columns_tuple() -> Self::SafeColumns { + ( + id, + name, + preferred_username, + avatar, + admin, + banned, + published, + updated, + matrix_user_id, + actor_id, + bio, + local, + banner, + deleted, + ) } } } diff --git a/lemmy_db/src/views/community_view.rs b/lemmy_db/src/views/community_view.rs index 4e0b58821..2972b1fe5 100644 --- a/lemmy_db/src/views/community_view.rs +++ b/lemmy_db/src/views/community_view.rs @@ -4,6 +4,7 @@ use crate::{ community::{Community, CommunityFollower}, schema::{category, community, community_aggregates, community_follower, user_}, user::{UserSafe, User_}, + ToSafe, }; use diesel::{result::Error, *}; use serde::Serialize; @@ -39,11 +40,17 @@ impl CommunityView { .inner_join(user_::table) .inner_join(category::table) .inner_join(community_aggregates::table) - .first::<(Community, User_, Category, CommunityAggregates)>(conn)?; + .select(( + community::all_columns, + User_::safe_columns_tuple(), + category::all_columns, + community_aggregates::all_columns, + )) + .first::<(Community, UserSafe, Category, CommunityAggregates)>(conn)?; Ok(CommunityView { community, - creator: creator.to_safe(), + creator, category, subscribed, counts, diff --git a/lemmy_db/src/views/site_view.rs b/lemmy_db/src/views/site_view.rs index 547c13b4b..c00b83789 100644 --- a/lemmy_db/src/views/site_view.rs +++ b/lemmy_db/src/views/site_view.rs @@ -2,6 +2,7 @@ use crate::{ schema::{site, user_}, site::Site, user::{UserSafe, User_}, + ToSafe, }; use diesel::{result::Error, *}; use serde::Serialize; @@ -16,11 +17,9 @@ impl SiteView { pub fn read(conn: &PgConnection) -> Result { let (site, creator) = site::table .inner_join(user_::table) - .first::<(Site, User_)>(conn)?; + .select((site::all_columns, User_::safe_columns_tuple())) + .first::<(Site, UserSafe)>(conn)?; - Ok(SiteView { - site, - creator: creator.to_safe(), - }) + Ok(SiteView { site, creator }) } } diff --git a/lemmy_db/src/views/user_view.rs b/lemmy_db/src/views/user_view.rs index be80179b2..76bc3c3d3 100644 --- a/lemmy_db/src/views/user_view.rs +++ b/lemmy_db/src/views/user_view.rs @@ -6,6 +6,7 @@ use crate::{ user::{UserSafe, User_}, MaybeOptional, SortType, + ToSafe, }; use diesel::{dsl::*, result::Error, *}; use serde::Serialize; @@ -37,30 +38,30 @@ impl UserViewSafe { let (user, counts) = user_::table .find(id) .inner_join(user_aggregates::table) - .first::<(User_, UserAggregates)>(conn)?; - Ok(Self { - user: user.to_safe(), - counts, - }) + .select((User_::safe_columns_tuple(), user_aggregates::all_columns)) + .first::<(UserSafe, UserAggregates)>(conn)?; + Ok(Self { user, counts }) } pub fn admins(conn: &PgConnection) -> Result, Error> { let admins = user_::table .inner_join(user_aggregates::table) + .select((User_::safe_columns_tuple(), user_aggregates::all_columns)) .filter(user_::admin.eq(true)) .order_by(user_::published) - .load::<(User_, UserAggregates)>(conn)?; + .load::<(UserSafe, UserAggregates)>(conn)?; - Ok(vec_to_user_view_safe(admins)) + Ok(to_vec(admins)) } pub fn banned(conn: &PgConnection) -> Result, Error> { let banned = user_::table .inner_join(user_aggregates::table) + .select((User_::safe_columns_tuple(), user_aggregates::all_columns)) .filter(user_::banned.eq(true)) - .load::<(User_, UserAggregates)>(conn)?; + .load::<(UserSafe, UserAggregates)>(conn)?; - Ok(vec_to_user_view_safe(banned)) + Ok(to_vec(banned)) } } @@ -77,34 +78,24 @@ mod join_types { pub(super) type BoxedUserJoin<'a> = BoxedSelectStatement< 'a, ( + // UserSafe column types ( Integer, Text, Nullable, - Text, Nullable, - Nullable, - diesel::sql_types::Bool, + Bool, Bool, Timestamp, Nullable, - Bool, - Text, - SmallInt, - SmallInt, - Text, - Bool, - Bool, Nullable, Text, Nullable, Bool, Nullable, - Nullable, - Timestamp, - Nullable, Bool, ), + // UserAggregates column types (Integer, Integer, BigInt, BigInt, BigInt, BigInt), ), JoinOn< @@ -128,7 +119,10 @@ pub struct UserQueryBuilder<'a> { impl<'a> UserQueryBuilder<'a> { pub fn create(conn: &'a PgConnection) -> Self { - let query = user_::table.inner_join(user_aggregates::table).into_boxed(); + let query = user_::table + .inner_join(user_aggregates::table) + .select((User_::safe_columns_tuple(), user_aggregates::all_columns)) + .into_boxed(); UserQueryBuilder { conn, @@ -192,17 +186,17 @@ impl<'a> UserQueryBuilder<'a> { let (limit, offset) = limit_and_offset(self.page, self.limit); query = query.limit(limit).offset(offset); - let res = query.load::<(User_, UserAggregates)>(self.conn)?; + let res = query.load::<(UserSafe, UserAggregates)>(self.conn)?; - Ok(vec_to_user_view_safe(res)) + Ok(to_vec(res)) } } -fn vec_to_user_view_safe(users: Vec<(User_, UserAggregates)>) -> Vec { +fn to_vec(users: Vec<(UserSafe, UserAggregates)>) -> Vec { users .iter() .map(|a| UserViewSafe { - user: a.0.to_safe(), + user: a.0.to_owned(), counts: a.1.to_owned(), }) .collect::>()