2 use crate::schema::user_;
3 use crate::schema::user_::dsl::*;
4 use crate::{is_email_regex, Settings};
5 use bcrypt::{hash, DEFAULT_COST};
6 use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, TokenData, Validation};
8 #[derive(Queryable, Identifiable, PartialEq, Debug)]
9 #[table_name = "user_"]
13 pub fedi_name: String,
14 pub preferred_username: Option<String>,
15 pub password_encrypted: String,
16 pub email: Option<String>,
17 pub avatar: Option<String>,
20 pub published: chrono::NaiveDateTime,
21 pub updated: Option<chrono::NaiveDateTime>,
24 pub default_sort_type: i16,
25 pub default_listing_type: i16,
27 pub show_avatars: bool,
28 pub send_notifications_to_email: bool,
29 pub matrix_user_id: Option<String>,
32 #[derive(Insertable, AsChangeset, Clone)]
33 #[table_name = "user_"]
36 pub fedi_name: String,
37 pub preferred_username: Option<String>,
38 pub password_encrypted: String,
41 pub email: Option<String>,
42 pub avatar: Option<String>,
43 pub updated: Option<chrono::NaiveDateTime>,
46 pub default_sort_type: i16,
47 pub default_listing_type: i16,
49 pub show_avatars: bool,
50 pub send_notifications_to_email: bool,
51 pub matrix_user_id: Option<String>,
54 impl Crud<UserForm> for User_ {
55 fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
56 user_.find(user_id).first::<Self>(conn)
58 fn delete(conn: &PgConnection, user_id: i32) -> Result<usize, Error> {
59 diesel::delete(user_.find(user_id)).execute(conn)
61 fn create(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
62 insert_into(user_).values(form).get_result::<Self>(conn)
64 fn update(conn: &PgConnection, user_id: i32, form: &UserForm) -> Result<Self, Error> {
65 diesel::update(user_.find(user_id))
67 .get_result::<Self>(conn)
72 pub fn register(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
73 let mut edited_user = form.clone();
75 hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
76 edited_user.password_encrypted = password_hash;
78 Self::create(&conn, &edited_user)
81 pub fn update_password(
85 ) -> Result<Self, Error> {
86 let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password");
88 diesel::update(user_.find(user_id))
89 .set(password_encrypted.eq(password_hash))
90 .get_result::<Self>(conn)
93 pub fn read_from_name(conn: &PgConnection, from_user_name: String) -> Result<Self, Error> {
94 user_.filter(name.eq(from_user_name)).first::<Self>(conn)
98 #[derive(Debug, Serialize, Deserialize)]
101 pub username: String,
105 pub default_sort_type: i16,
106 pub default_listing_type: i16,
108 pub avatar: Option<String>,
109 pub show_avatars: bool,
113 pub fn decode(jwt: &str) -> Result<TokenData<Claims>, jsonwebtoken::errors::Error> {
116 ..Validation::default()
120 &DecodingKey::from_secret(Settings::get().jwt_secret.as_ref()),
128 pub fn jwt(&self) -> Jwt {
129 let my_claims = Claims {
131 username: self.name.to_owned(),
132 iss: self.fedi_name.to_owned(),
133 show_nsfw: self.show_nsfw,
134 theme: self.theme.to_owned(),
135 default_sort_type: self.default_sort_type,
136 default_listing_type: self.default_listing_type,
137 lang: self.lang.to_owned(),
138 avatar: self.avatar.to_owned(),
139 show_avatars: self.show_avatars.to_owned(),
144 &EncodingKey::from_secret(Settings::get().jwt_secret.as_ref()),
149 pub fn find_by_username(conn: &PgConnection, username: &str) -> Result<Self, Error> {
150 user_.filter(name.eq(username)).first::<User_>(conn)
153 pub fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<Self, Error> {
154 user_.filter(email.eq(from_email)).first::<User_>(conn)
157 pub fn find_by_email_or_username(
159 username_or_email: &str,
160 ) -> Result<Self, Error> {
161 if is_email_regex(username_or_email) {
162 User_::find_by_email(conn, username_or_email)
164 User_::find_by_username(conn, username_or_email)
168 pub fn get_profile_url(&self) -> String {
169 format!("https://{}/u/{}", Settings::get().hostname, self.name)
172 pub fn find_by_jwt(conn: &PgConnection, jwt: &str) -> Result<Self, Error> {
173 let claims: Claims = Claims::decode(&jwt).expect("Invalid token").claims;
174 Self::read(&conn, claims.id)
185 let conn = establish_unpooled_connection();
187 let new_user = UserForm {
188 name: "thommy".into(),
189 fedi_name: "rrf".into(),
190 preferred_username: None,
191 password_encrypted: "nope".into(),
193 matrix_user_id: None,
199 theme: "darkly".into(),
200 default_sort_type: SortType::Hot as i16,
201 default_listing_type: ListingType::Subscribed as i16,
202 lang: "browser".into(),
204 send_notifications_to_email: false,
207 let inserted_user = User_::create(&conn, &new_user).unwrap();
209 let expected_user = User_ {
210 id: inserted_user.id,
211 name: "thommy".into(),
212 fedi_name: "rrf".into(),
213 preferred_username: None,
214 password_encrypted: "nope".into(),
216 matrix_user_id: None,
220 published: inserted_user.published,
223 theme: "darkly".into(),
224 default_sort_type: SortType::Hot as i16,
225 default_listing_type: ListingType::Subscribed as i16,
226 lang: "browser".into(),
228 send_notifications_to_email: false,
231 let read_user = User_::read(&conn, inserted_user.id).unwrap();
232 let updated_user = User_::update(&conn, inserted_user.id, &new_user).unwrap();
233 let num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
235 assert_eq!(expected_user, read_user);
236 assert_eq!(expected_user, inserted_user);
237 assert_eq!(expected_user, updated_user);
238 assert_eq!(1, num_deleted);