1 use crate::{is_email_regex, ApubObject, Crud, ToSafeSettings};
2 use bcrypt::{hash, DEFAULT_COST};
3 use diesel::{dsl::*, result::Error, *};
7 source::user::{UserForm, UserSafeSettings, User_},
10 use lemmy_utils::settings::Settings;
14 use lemmy_db_schema::{schema::user_::columns::*, source::user::User_};
33 impl ToSafe for User_ {
34 type SafeColumns = Columns;
35 fn safe_columns_tuple() -> Self::SafeColumns {
56 mod safe_type_alias_1 {
58 use lemmy_db_schema::{schema::user_alias_1::columns::*, source::user::UserAlias1};
77 impl ToSafe for UserAlias1 {
78 type SafeColumns = Columns;
79 fn safe_columns_tuple() -> Self::SafeColumns {
100 mod safe_type_alias_2 {
102 use lemmy_db_schema::{schema::user_alias_2::columns::*, source::user::UserAlias2};
121 impl ToSafe for UserAlias2 {
122 type SafeColumns = Columns;
123 fn safe_columns_tuple() -> Self::SafeColumns {
144 mod safe_settings_type {
145 use crate::ToSafeSettings;
146 use lemmy_db_schema::{schema::user_::columns::*, source::user::User_};
161 default_listing_type,
164 send_notifications_to_email,
174 impl ToSafeSettings for User_ {
175 type SafeSettingsColumns = Columns;
176 fn safe_settings_columns_tuple() -> Self::SafeSettingsColumns {
190 default_listing_type,
193 send_notifications_to_email,
206 pub trait UserSafeSettings_ {
207 fn read(conn: &PgConnection, user_id: i32) -> Result<UserSafeSettings, Error>;
210 impl UserSafeSettings_ for UserSafeSettings {
211 fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
213 .select(User_::safe_settings_columns_tuple())
214 .filter(deleted.eq(false))
220 impl Crud<UserForm> for User_ {
221 fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
223 .filter(deleted.eq(false))
227 fn delete(conn: &PgConnection, user_id: i32) -> Result<usize, Error> {
228 diesel::delete(user_.find(user_id)).execute(conn)
230 fn create(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
231 insert_into(user_).values(form).get_result::<Self>(conn)
233 fn update(conn: &PgConnection, user_id: i32, form: &UserForm) -> Result<Self, Error> {
234 diesel::update(user_.find(user_id))
236 .get_result::<Self>(conn)
240 impl ApubObject<UserForm> for User_ {
241 fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error> {
242 use lemmy_db_schema::schema::user_::dsl::*;
244 .filter(deleted.eq(false))
245 .filter(actor_id.eq(object_id))
249 fn upsert(conn: &PgConnection, user_form: &UserForm) -> Result<User_, Error> {
252 .on_conflict(actor_id)
255 .get_result::<Self>(conn)
260 fn register(conn: &PgConnection, form: &UserForm) -> Result<User_, Error>;
261 fn update_password(conn: &PgConnection, user_id: i32, new_password: &str)
262 -> Result<User_, Error>;
263 fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result<User_, Error>;
264 fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result<User_, Error>;
265 fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<User_, Error>;
266 fn find_by_email_or_username(
268 username_or_email: &str,
269 ) -> Result<User_, Error>;
270 fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error>;
271 fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<User_, Error>;
272 fn get_profile_url(&self, hostname: &str) -> String;
273 fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
274 fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
277 impl User for User_ {
278 fn register(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
279 let mut edited_user = form.clone();
281 hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
282 edited_user.password_encrypted = password_hash;
284 Self::create(&conn, &edited_user)
287 // TODO do more individual updates like these
288 fn update_password(conn: &PgConnection, user_id: i32, new_password: &str) -> Result<Self, Error> {
289 let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password");
291 diesel::update(user_.find(user_id))
293 password_encrypted.eq(password_hash),
294 updated.eq(naive_now()),
296 .get_result::<Self>(conn)
299 fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result<Self, Error> {
301 .filter(local.eq(true))
302 .filter(deleted.eq(false))
303 .filter(name.eq(from_user_name))
307 fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result<Self, Error> {
308 diesel::update(user_.find(user_id))
309 .set(admin.eq(added))
310 .get_result::<Self>(conn)
313 fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<Self, Error> {
314 diesel::update(user_.find(user_id))
316 .get_result::<Self>(conn)
319 fn find_by_email_or_username(
321 username_or_email: &str,
322 ) -> Result<Self, Error> {
323 if is_email_regex(username_or_email) {
324 Self::find_by_email(conn, username_or_email)
326 Self::find_by_username(conn, username_or_email)
330 fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error> {
332 .filter(deleted.eq(false))
333 .filter(local.eq(true))
334 .filter(name.ilike(username))
335 .first::<User_>(conn)
338 fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<User_, Error> {
340 .filter(deleted.eq(false))
341 .filter(local.eq(true))
342 .filter(email.eq(from_email))
343 .first::<User_>(conn)
346 fn get_profile_url(&self, hostname: &str) -> String {
349 Settings::get().get_protocol_string(),
355 fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
356 diesel::update(user_.find(user_id))
357 .set((last_refreshed_at.eq(naive_now()),))
358 .get_result::<Self>(conn)
361 fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
362 diesel::update(user_.find(user_id))
364 preferred_username.eq::<Option<String>>(None),
365 email.eq::<Option<String>>(None),
366 matrix_user_id.eq::<Option<String>>(None),
367 bio.eq::<Option<String>>(None),
369 updated.eq(naive_now()),
371 .get_result::<Self>(conn)
377 use crate::{establish_unpooled_connection, source::user::*, ListingType, SortType};
381 let conn = establish_unpooled_connection();
383 let new_user = UserForm {
384 name: "thommy".into(),
385 preferred_username: None,
386 password_encrypted: "nope".into(),
388 matrix_user_id: None,
396 theme: "browser".into(),
397 default_sort_type: SortType::Hot as i16,
398 default_listing_type: ListingType::Subscribed as i16,
399 lang: "browser".into(),
401 send_notifications_to_email: false,
407 last_refreshed_at: None,
410 let inserted_user = User_::create(&conn, &new_user).unwrap();
412 let expected_user = User_ {
413 id: inserted_user.id,
414 name: "thommy".into(),
415 preferred_username: None,
416 password_encrypted: "nope".into(),
418 matrix_user_id: None,
423 published: inserted_user.published,
426 theme: "browser".into(),
427 default_sort_type: SortType::Hot as i16,
428 default_listing_type: ListingType::Subscribed as i16,
429 lang: "browser".into(),
431 send_notifications_to_email: false,
432 actor_id: inserted_user.actor_id.to_owned(),
437 last_refreshed_at: inserted_user.published,
441 let read_user = User_::read(&conn, inserted_user.id).unwrap();
442 let updated_user = User_::update(&conn, inserted_user.id, &new_user).unwrap();
443 let num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
445 assert_eq!(expected_user, read_user);
446 assert_eq!(expected_user, inserted_user);
447 assert_eq!(expected_user, updated_user);
448 assert_eq!(1, num_deleted);