}
}
+pub(crate) trait ToSafe {
+ type SafeColumns;
+ fn safe_columns_tuple() -> Self::SafeColumns;
+}
+
pub fn get_database_url_from_env() -> Result<String, VarError> {
env::var("LEMMY_DATABASE_URL")
}
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<String>,
+ pub avatar: Option<String>,
+ pub admin: bool,
+ pub banned: bool,
+ pub published: chrono::NaiveDateTime,
+ pub updated: Option<chrono::NaiveDateTime>,
+ pub matrix_user_id: Option<String>,
+ pub actor_id: String,
+ pub bio: Option<String>,
+ pub local: bool,
+ pub banner: Option<String>,
+ pub deleted: bool,
+}
+
#[derive(Insertable, AsChangeset, Clone)]
#[table_name = "user_"]
pub struct UserForm {
pub banner: Option<Option<String>>,
}
-/// 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<String>,
- pub avatar: Option<String>,
- pub admin: bool,
- pub banned: bool,
- pub published: chrono::NaiveDateTime,
- pub updated: Option<chrono::NaiveDateTime>,
- pub matrix_user_id: Option<String>,
- pub actor_id: String,
- pub bio: Option<String>,
- pub local: bool,
- pub banner: Option<String>,
- pub deleted: bool,
-}
-
impl Crud<UserForm> for User_ {
fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
user_
))
.get_result::<Self>(conn)
}
+}
+
+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,
+ );
- 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,
+ 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,
+ )
}
}
}
community::{Community, CommunityFollower},
schema::{category, community, community_aggregates, community_follower, user_},
user::{UserSafe, User_},
+ ToSafe,
};
use diesel::{result::Error, *};
use serde::Serialize;
.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,
schema::{site, user_},
site::Site,
user::{UserSafe, User_},
+ ToSafe,
};
use diesel::{result::Error, *};
use serde::Serialize;
pub fn read(conn: &PgConnection) -> Result<Self, Error> {
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 })
}
}
user::{UserSafe, User_},
MaybeOptional,
SortType,
+ ToSafe,
};
use diesel::{dsl::*, result::Error, *};
use serde::Serialize;
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<Vec<Self>, Error> {
let admins = user_::table
.inner_join(user_aggregates::table)
+ .select((User_::safe_columns_tuple(), user_aggregates::all_columns))
.filter(user_::admin.eq(true))
.order_by(user_::published)
- .load::<(User_, UserAggregates)>(conn)?;
+ .load::<(UserSafe, UserAggregates)>(conn)?;
- Ok(vec_to_user_view_safe(admins))
+ Ok(to_vec(admins))
}
pub fn banned(conn: &PgConnection) -> Result<Vec<Self>, Error> {
let banned = user_::table
.inner_join(user_aggregates::table)
+ .select((User_::safe_columns_tuple(), user_aggregates::all_columns))
.filter(user_::banned.eq(true))
- .load::<(User_, UserAggregates)>(conn)?;
+ .load::<(UserSafe, UserAggregates)>(conn)?;
- Ok(vec_to_user_view_safe(banned))
+ Ok(to_vec(banned))
}
}
pub(super) type BoxedUserJoin<'a> = BoxedSelectStatement<
'a,
(
+ // UserSafe column types
(
Integer,
Text,
Nullable<Text>,
- Text,
- Nullable<Text>,
Nullable<Text>,
- diesel::sql_types::Bool,
+ Bool,
Bool,
Timestamp,
Nullable<Timestamp>,
- Bool,
- Text,
- SmallInt,
- SmallInt,
- Text,
- Bool,
- Bool,
Nullable<Text>,
Text,
Nullable<Text>,
Bool,
Nullable<Text>,
- Nullable<Text>,
- Timestamp,
- Nullable<Text>,
Bool,
),
+ // UserAggregates column types
(Integer, Integer, BigInt, BigInt, BigInt, BigInt),
),
JoinOn<
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,
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<UserViewSafe> {
+fn to_vec(users: Vec<(UserSafe, UserAggregates)>) -> Vec<UserViewSafe> {
users
.iter()
.map(|a| UserViewSafe {
- user: a.0.to_safe(),
+ user: a.0.to_owned(),
counts: a.1.to_owned(),
})
.collect::<Vec<UserViewSafe>>()