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,
179 impl ToSafeSettings for User_ {
180 type SafeSettingsColumns = Columns;
181 fn safe_settings_columns_tuple() -> Self::SafeSettingsColumns {
195 default_listing_type,
198 send_notifications_to_email,
212 pub trait UserSafeSettings_ {
213 fn read(conn: &PgConnection, user_id: i32) -> Result<UserSafeSettings, Error>;
216 impl UserSafeSettings_ for UserSafeSettings {
217 fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
219 .select(User_::safe_settings_columns_tuple())
220 .filter(deleted.eq(false))
226 impl Crud<UserForm> for User_ {
227 fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
229 .filter(deleted.eq(false))
233 fn delete(conn: &PgConnection, user_id: i32) -> Result<usize, Error> {
234 diesel::delete(user_.find(user_id)).execute(conn)
236 fn create(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
237 insert_into(user_).values(form).get_result::<Self>(conn)
239 fn update(conn: &PgConnection, user_id: i32, form: &UserForm) -> Result<Self, Error> {
240 diesel::update(user_.find(user_id))
242 .get_result::<Self>(conn)
246 impl ApubObject<UserForm> for User_ {
247 fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error> {
248 use lemmy_db_schema::schema::user_::dsl::*;
250 .filter(deleted.eq(false))
251 .filter(actor_id.eq(object_id))
255 fn upsert(conn: &PgConnection, user_form: &UserForm) -> Result<User_, Error> {
258 .on_conflict(actor_id)
261 .get_result::<Self>(conn)
266 fn register(conn: &PgConnection, form: &UserForm) -> Result<User_, Error>;
267 fn update_password(conn: &PgConnection, user_id: i32, new_password: &str)
268 -> Result<User_, Error>;
269 fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result<User_, Error>;
270 fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result<User_, Error>;
271 fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<User_, Error>;
272 fn find_by_email_or_username(
274 username_or_email: &str,
275 ) -> Result<User_, Error>;
276 fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error>;
277 fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<User_, Error>;
278 fn get_profile_url(&self, hostname: &str) -> String;
279 fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
280 fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
283 impl User for User_ {
284 fn register(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
285 let mut edited_user = form.clone();
287 hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
288 edited_user.password_encrypted = password_hash;
290 Self::create(&conn, &edited_user)
293 // TODO do more individual updates like these
294 fn update_password(conn: &PgConnection, user_id: i32, new_password: &str) -> Result<Self, Error> {
295 let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password");
297 diesel::update(user_.find(user_id))
299 password_encrypted.eq(password_hash),
300 updated.eq(naive_now()),
301 validator_time.eq(naive_now()),
303 .get_result::<Self>(conn)
306 fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result<Self, Error> {
308 .filter(local.eq(true))
309 .filter(deleted.eq(false))
310 .filter(name.eq(from_user_name))
314 fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result<Self, Error> {
315 diesel::update(user_.find(user_id))
316 .set(admin.eq(added))
317 .get_result::<Self>(conn)
320 fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<Self, Error> {
321 diesel::update(user_.find(user_id))
323 .get_result::<Self>(conn)
326 fn find_by_email_or_username(
328 username_or_email: &str,
329 ) -> Result<Self, Error> {
330 if is_email_regex(username_or_email) {
331 Self::find_by_email(conn, username_or_email)
333 Self::find_by_username(conn, username_or_email)
337 fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error> {
339 .filter(deleted.eq(false))
340 .filter(local.eq(true))
341 .filter(name.ilike(username))
342 .first::<User_>(conn)
345 fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<User_, Error> {
347 .filter(deleted.eq(false))
348 .filter(local.eq(true))
349 .filter(email.eq(from_email))
350 .first::<User_>(conn)
353 fn get_profile_url(&self, hostname: &str) -> String {
356 Settings::get().get_protocol_string(),
362 fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
363 diesel::update(user_.find(user_id))
364 .set((last_refreshed_at.eq(naive_now()),))
365 .get_result::<Self>(conn)
368 fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
369 diesel::update(user_.find(user_id))
371 preferred_username.eq::<Option<String>>(None),
372 email.eq::<Option<String>>(None),
373 matrix_user_id.eq::<Option<String>>(None),
374 bio.eq::<Option<String>>(None),
376 updated.eq(naive_now()),
378 .get_result::<Self>(conn)
384 use crate::{establish_unpooled_connection, source::user::*, ListingType, SortType};
385 use serial_test::serial;
390 let conn = establish_unpooled_connection();
392 let new_user = UserForm {
393 name: "thommy".into(),
394 preferred_username: None,
395 password_encrypted: "nope".into(),
397 matrix_user_id: None,
405 theme: "browser".into(),
406 default_sort_type: SortType::Hot as i16,
407 default_listing_type: ListingType::Subscribed as i16,
408 lang: "browser".into(),
410 send_notifications_to_email: false,
416 last_refreshed_at: None,
418 shared_inbox_url: None,
421 let inserted_user = User_::create(&conn, &new_user).unwrap();
423 let expected_user = User_ {
424 id: inserted_user.id,
425 name: "thommy".into(),
426 preferred_username: None,
427 password_encrypted: "nope".into(),
429 matrix_user_id: None,
434 published: inserted_user.published,
437 theme: "browser".into(),
438 default_sort_type: SortType::Hot as i16,
439 default_listing_type: ListingType::Subscribed as i16,
440 lang: "browser".into(),
442 send_notifications_to_email: false,
443 actor_id: inserted_user.actor_id.to_owned(),
448 last_refreshed_at: inserted_user.published,
450 inbox_url: inserted_user.inbox_url.to_owned(),
451 shared_inbox_url: None,
452 validator_time: inserted_user.published,
455 let read_user = User_::read(&conn, inserted_user.id).unwrap();
456 let updated_user = User_::update(&conn, inserted_user.id, &new_user).unwrap();
457 let num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
459 assert_eq!(expected_user, read_user);
460 assert_eq!(expected_user, inserted_user);
461 assert_eq!(expected_user, updated_user);
462 assert_eq!(1, num_deleted);