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_},
9 use lemmy_utils::settings::Settings;
13 use lemmy_db_schema::{schema::user_::columns::*, source::user::User_};
32 impl ToSafe for User_ {
33 type SafeColumns = Columns;
34 fn safe_columns_tuple() -> Self::SafeColumns {
55 mod safe_type_alias_1 {
57 use lemmy_db_schema::{schema::user_alias_1::columns::*, source::user::UserAlias1};
76 impl ToSafe for UserAlias1 {
77 type SafeColumns = Columns;
78 fn safe_columns_tuple() -> Self::SafeColumns {
99 mod safe_type_alias_2 {
101 use lemmy_db_schema::{schema::user_alias_2::columns::*, source::user::UserAlias2};
120 impl ToSafe for UserAlias2 {
121 type SafeColumns = Columns;
122 fn safe_columns_tuple() -> Self::SafeColumns {
143 mod safe_settings_type {
144 use crate::ToSafeSettings;
145 use lemmy_db_schema::{schema::user_::columns::*, source::user::User_};
160 default_listing_type,
163 send_notifications_to_email,
173 impl ToSafeSettings for User_ {
174 type SafeSettingsColumns = Columns;
175 fn safe_settings_columns_tuple() -> Self::SafeSettingsColumns {
189 default_listing_type,
192 send_notifications_to_email,
205 pub trait UserSafeSettings_ {
206 fn read(conn: &PgConnection, user_id: i32) -> Result<UserSafeSettings, Error>;
209 impl UserSafeSettings_ for UserSafeSettings {
210 fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
212 .select(User_::safe_settings_columns_tuple())
213 .filter(deleted.eq(false))
219 impl Crud<UserForm> for User_ {
220 fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
222 .filter(deleted.eq(false))
226 fn delete(conn: &PgConnection, user_id: i32) -> Result<usize, Error> {
227 diesel::delete(user_.find(user_id)).execute(conn)
229 fn create(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
230 insert_into(user_).values(form).get_result::<Self>(conn)
232 fn update(conn: &PgConnection, user_id: i32, form: &UserForm) -> Result<Self, Error> {
233 diesel::update(user_.find(user_id))
235 .get_result::<Self>(conn)
239 impl ApubObject<UserForm> for User_ {
240 fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result<Self, Error> {
241 use lemmy_db_schema::schema::user_::dsl::*;
243 .filter(deleted.eq(false))
244 .filter(actor_id.eq(object_id))
248 fn upsert(conn: &PgConnection, user_form: &UserForm) -> Result<User_, Error> {
251 .on_conflict(actor_id)
254 .get_result::<Self>(conn)
259 fn register(conn: &PgConnection, form: &UserForm) -> Result<User_, Error>;
260 fn update_password(conn: &PgConnection, user_id: i32, new_password: &str)
261 -> Result<User_, Error>;
262 fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result<User_, Error>;
263 fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result<User_, Error>;
264 fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<User_, Error>;
265 fn find_by_email_or_username(
267 username_or_email: &str,
268 ) -> Result<User_, Error>;
269 fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error>;
270 fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<User_, Error>;
271 fn get_profile_url(&self, hostname: &str) -> String;
272 fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
273 fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
276 impl User for User_ {
277 fn register(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
278 let mut edited_user = form.clone();
280 hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
281 edited_user.password_encrypted = password_hash;
283 Self::create(&conn, &edited_user)
286 // TODO do more individual updates like these
287 fn update_password(conn: &PgConnection, user_id: i32, new_password: &str) -> Result<Self, Error> {
288 let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password");
290 diesel::update(user_.find(user_id))
292 password_encrypted.eq(password_hash),
293 updated.eq(naive_now()),
295 .get_result::<Self>(conn)
298 fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result<Self, Error> {
300 .filter(local.eq(true))
301 .filter(deleted.eq(false))
302 .filter(name.eq(from_user_name))
306 fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result<Self, Error> {
307 diesel::update(user_.find(user_id))
308 .set(admin.eq(added))
309 .get_result::<Self>(conn)
312 fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<Self, Error> {
313 diesel::update(user_.find(user_id))
315 .get_result::<Self>(conn)
318 fn find_by_email_or_username(
320 username_or_email: &str,
321 ) -> Result<Self, Error> {
322 if is_email_regex(username_or_email) {
323 Self::find_by_email(conn, username_or_email)
325 Self::find_by_username(conn, username_or_email)
329 fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error> {
331 .filter(deleted.eq(false))
332 .filter(local.eq(true))
333 .filter(name.ilike(username))
334 .first::<User_>(conn)
337 fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<User_, Error> {
339 .filter(deleted.eq(false))
340 .filter(local.eq(true))
341 .filter(email.eq(from_email))
342 .first::<User_>(conn)
345 fn get_profile_url(&self, hostname: &str) -> String {
348 Settings::get().get_protocol_string(),
354 fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
355 diesel::update(user_.find(user_id))
356 .set((last_refreshed_at.eq(naive_now()),))
357 .get_result::<Self>(conn)
360 fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
361 diesel::update(user_.find(user_id))
363 preferred_username.eq::<Option<String>>(None),
364 email.eq::<Option<String>>(None),
365 matrix_user_id.eq::<Option<String>>(None),
366 bio.eq::<Option<String>>(None),
368 updated.eq(naive_now()),
370 .get_result::<Self>(conn)
376 use crate::{establish_unpooled_connection, source::user::*, ListingType, SortType};
380 let conn = establish_unpooled_connection();
382 let new_user = UserForm {
383 name: "thommy".into(),
384 preferred_username: None,
385 password_encrypted: "nope".into(),
387 matrix_user_id: None,
395 theme: "browser".into(),
396 default_sort_type: SortType::Hot as i16,
397 default_listing_type: ListingType::Subscribed as i16,
398 lang: "browser".into(),
400 send_notifications_to_email: false,
406 last_refreshed_at: None,
409 let inserted_user = User_::create(&conn, &new_user).unwrap();
411 let expected_user = User_ {
412 id: inserted_user.id,
413 name: "thommy".into(),
414 preferred_username: None,
415 password_encrypted: "nope".into(),
417 matrix_user_id: None,
422 published: inserted_user.published,
425 theme: "browser".into(),
426 default_sort_type: SortType::Hot as i16,
427 default_listing_type: ListingType::Subscribed as i16,
428 lang: "browser".into(),
430 send_notifications_to_email: false,
431 actor_id: inserted_user.actor_id.to_owned(),
436 last_refreshed_at: inserted_user.published,
440 let read_user = User_::read(&conn, inserted_user.id).unwrap();
441 let updated_user = User_::update(&conn, inserted_user.id, &new_user).unwrap();
442 let num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
444 assert_eq!(expected_user, read_user);
445 assert_eq!(expected_user, inserted_user);
446 assert_eq!(expected_user, updated_user);
447 assert_eq!(1, num_deleted);