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_};
35 impl ToSafe for User_ {
36 type SafeColumns = Columns;
37 fn safe_columns_tuple() -> Self::SafeColumns {
60 mod safe_type_alias_1 {
62 use lemmy_db_schema::{schema::user_alias_1::columns::*, source::user::UserAlias1};
81 impl ToSafe for UserAlias1 {
82 type SafeColumns = Columns;
83 fn safe_columns_tuple() -> Self::SafeColumns {
104 mod safe_type_alias_2 {
106 use lemmy_db_schema::{schema::user_alias_2::columns::*, source::user::UserAlias2};
125 impl ToSafe for UserAlias2 {
126 type SafeColumns = Columns;
127 fn safe_columns_tuple() -> Self::SafeColumns {
148 mod safe_settings_type {
149 use crate::ToSafeSettings;
150 use lemmy_db_schema::{schema::user_::columns::*, source::user::User_};
165 default_listing_type,
168 send_notifications_to_email,
178 impl ToSafeSettings for User_ {
179 type SafeSettingsColumns = Columns;
180 fn safe_settings_columns_tuple() -> Self::SafeSettingsColumns {
194 default_listing_type,
197 send_notifications_to_email,
210 pub trait UserSafeSettings_ {
211 fn read(conn: &PgConnection, user_id: i32) -> Result<UserSafeSettings, Error>;
214 impl UserSafeSettings_ for UserSafeSettings {
215 fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
217 .select(User_::safe_settings_columns_tuple())
218 .filter(deleted.eq(false))
224 impl Crud<UserForm> for User_ {
225 fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
227 .filter(deleted.eq(false))
231 fn delete(conn: &PgConnection, user_id: i32) -> Result<usize, Error> {
232 diesel::delete(user_.find(user_id)).execute(conn)
234 fn create(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
235 insert_into(user_).values(form).get_result::<Self>(conn)
237 fn update(conn: &PgConnection, user_id: i32, form: &UserForm) -> Result<Self, Error> {
238 diesel::update(user_.find(user_id))
240 .get_result::<Self>(conn)
244 impl ApubObject<UserForm> for User_ {
245 fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error> {
246 use lemmy_db_schema::schema::user_::dsl::*;
248 .filter(deleted.eq(false))
249 .filter(actor_id.eq(object_id))
253 fn upsert(conn: &PgConnection, user_form: &UserForm) -> Result<User_, Error> {
256 .on_conflict(actor_id)
259 .get_result::<Self>(conn)
264 fn register(conn: &PgConnection, form: &UserForm) -> Result<User_, Error>;
265 fn update_password(conn: &PgConnection, user_id: i32, new_password: &str)
266 -> Result<User_, Error>;
267 fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result<User_, Error>;
268 fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result<User_, Error>;
269 fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<User_, Error>;
270 fn find_by_email_or_username(
272 username_or_email: &str,
273 ) -> Result<User_, Error>;
274 fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error>;
275 fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<User_, Error>;
276 fn get_profile_url(&self, hostname: &str) -> String;
277 fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
278 fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
281 impl User for User_ {
282 fn register(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
283 let mut edited_user = form.clone();
285 hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
286 edited_user.password_encrypted = password_hash;
288 Self::create(&conn, &edited_user)
291 // TODO do more individual updates like these
292 fn update_password(conn: &PgConnection, user_id: i32, new_password: &str) -> Result<Self, Error> {
293 let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password");
295 diesel::update(user_.find(user_id))
297 password_encrypted.eq(password_hash),
298 updated.eq(naive_now()),
300 .get_result::<Self>(conn)
303 fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result<Self, Error> {
305 .filter(local.eq(true))
306 .filter(deleted.eq(false))
307 .filter(name.eq(from_user_name))
311 fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result<Self, Error> {
312 diesel::update(user_.find(user_id))
313 .set(admin.eq(added))
314 .get_result::<Self>(conn)
317 fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<Self, Error> {
318 diesel::update(user_.find(user_id))
320 .get_result::<Self>(conn)
323 fn find_by_email_or_username(
325 username_or_email: &str,
326 ) -> Result<Self, Error> {
327 if is_email_regex(username_or_email) {
328 Self::find_by_email(conn, username_or_email)
330 Self::find_by_username(conn, username_or_email)
334 fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error> {
336 .filter(deleted.eq(false))
337 .filter(local.eq(true))
338 .filter(name.ilike(username))
339 .first::<User_>(conn)
342 fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<User_, Error> {
344 .filter(deleted.eq(false))
345 .filter(local.eq(true))
346 .filter(email.eq(from_email))
347 .first::<User_>(conn)
350 fn get_profile_url(&self, hostname: &str) -> String {
353 Settings::get().get_protocol_string(),
359 fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
360 diesel::update(user_.find(user_id))
361 .set((last_refreshed_at.eq(naive_now()),))
362 .get_result::<Self>(conn)
365 fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
366 diesel::update(user_.find(user_id))
368 preferred_username.eq::<Option<String>>(None),
369 email.eq::<Option<String>>(None),
370 matrix_user_id.eq::<Option<String>>(None),
371 bio.eq::<Option<String>>(None),
373 updated.eq(naive_now()),
375 .get_result::<Self>(conn)
381 use crate::{establish_unpooled_connection, source::user::*, ListingType, SortType};
382 use serial_test::serial;
387 let conn = establish_unpooled_connection();
389 let new_user = UserForm {
390 name: "thommy".into(),
391 preferred_username: None,
392 password_encrypted: "nope".into(),
394 matrix_user_id: None,
402 theme: "browser".into(),
403 default_sort_type: SortType::Hot as i16,
404 default_listing_type: ListingType::Subscribed as i16,
405 lang: "browser".into(),
407 send_notifications_to_email: false,
413 last_refreshed_at: None,
415 shared_inbox_url: None,
418 let inserted_user = User_::create(&conn, &new_user).unwrap();
420 let expected_user = User_ {
421 id: inserted_user.id,
422 name: "thommy".into(),
423 preferred_username: None,
424 password_encrypted: "nope".into(),
426 matrix_user_id: None,
431 published: inserted_user.published,
434 theme: "browser".into(),
435 default_sort_type: SortType::Hot as i16,
436 default_listing_type: ListingType::Subscribed as i16,
437 lang: "browser".into(),
439 send_notifications_to_email: false,
440 actor_id: inserted_user.actor_id.to_owned(),
445 last_refreshed_at: inserted_user.published,
447 inbox_url: inserted_user.inbox_url.to_owned(),
448 shared_inbox_url: None,
451 let read_user = User_::read(&conn, inserted_user.id).unwrap();
452 let updated_user = User_::update(&conn, inserted_user.id, &new_user).unwrap();
453 let num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
455 assert_eq!(expected_user, read_user);
456 assert_eq!(expected_user, inserted_user);
457 assert_eq!(expected_user, updated_user);
458 assert_eq!(1, num_deleted);