]> Untitled Git - lemmy.git/blob - server/src/api/user.rs
Spanish translations
[lemmy.git] / server / src / api / user.rs
1 use super::*;
2 use bcrypt::verify;
3 use std::str::FromStr;
4
5 #[derive(Serialize, Deserialize, Debug)]
6 pub struct Login {
7   username_or_email: String,
8   password: String,
9 }
10
11 #[derive(Serialize, Deserialize)]
12 pub struct Register {
13   username: String,
14   email: Option<String>,
15   password: String,
16   password_verify: String,
17   admin: bool,
18   show_nsfw: bool,
19 }
20
21 #[derive(Serialize, Deserialize)]
22 pub struct SaveUserSettings {
23   show_nsfw: bool,
24   theme: String,
25   auth: String,
26 }
27
28 #[derive(Serialize, Deserialize)]
29 pub struct LoginResponse {
30   op: String,
31   jwt: String,
32 }
33
34 #[derive(Serialize, Deserialize)]
35 pub struct GetUserDetails {
36   user_id: Option<i32>,
37   username: Option<String>,
38   sort: String,
39   page: Option<i64>,
40   limit: Option<i64>,
41   community_id: Option<i32>,
42   saved_only: bool,
43   auth: Option<String>,
44 }
45
46 #[derive(Serialize, Deserialize)]
47 pub struct GetUserDetailsResponse {
48   op: String,
49   user: UserView,
50   follows: Vec<CommunityFollowerView>,
51   moderates: Vec<CommunityModeratorView>,
52   comments: Vec<CommentView>,
53   posts: Vec<PostView>,
54   admins: Vec<UserView>,
55 }
56
57 #[derive(Serialize, Deserialize)]
58 pub struct GetRepliesResponse {
59   op: String,
60   replies: Vec<ReplyView>,
61 }
62
63 #[derive(Serialize, Deserialize)]
64 pub struct MarkAllAsRead {
65   auth: String,
66 }
67
68 #[derive(Serialize, Deserialize)]
69 pub struct AddAdmin {
70   user_id: i32,
71   added: bool,
72   auth: String,
73 }
74
75 #[derive(Serialize, Deserialize)]
76 pub struct AddAdminResponse {
77   op: String,
78   admins: Vec<UserView>,
79 }
80
81 #[derive(Serialize, Deserialize)]
82 pub struct BanUser {
83   user_id: i32,
84   ban: bool,
85   reason: Option<String>,
86   expires: Option<i64>,
87   auth: String,
88 }
89
90 #[derive(Serialize, Deserialize)]
91 pub struct BanUserResponse {
92   op: String,
93   user: UserView,
94   banned: bool,
95 }
96
97 #[derive(Serialize, Deserialize)]
98 pub struct GetReplies {
99   sort: String,
100   page: Option<i64>,
101   limit: Option<i64>,
102   unread_only: bool,
103   auth: String,
104 }
105
106 #[derive(Serialize, Deserialize)]
107 pub struct DeleteAccount {
108   auth: String,
109 }
110
111 impl Perform<LoginResponse> for Oper<Login> {
112   fn perform(&self) -> Result<LoginResponse, Error> {
113     let data: &Login = &self.data;
114     let conn = establish_connection();
115
116     // Fetch that username / email
117     let user: User_ = match User_::find_by_email_or_username(&conn, &data.username_or_email) {
118       Ok(user) => user,
119       Err(_e) => {
120         return Err(APIError::err(
121           &self.op,
122           "couldnt_find_that_username_or_email",
123         ))?
124       }
125     };
126
127     // Verify the password
128     let valid: bool = verify(&data.password, &user.password_encrypted).unwrap_or(false);
129     if !valid {
130       return Err(APIError::err(&self.op, "password_incorrect"))?;
131     }
132
133     // Return the jwt
134     Ok(LoginResponse {
135       op: self.op.to_string(),
136       jwt: user.jwt(),
137     })
138   }
139 }
140
141 impl Perform<LoginResponse> for Oper<Register> {
142   fn perform(&self) -> Result<LoginResponse, Error> {
143     let data: &Register = &self.data;
144     let conn = establish_connection();
145
146     // Make sure passwords match
147     if &data.password != &data.password_verify {
148       return Err(APIError::err(&self.op, "passwords_dont_match"))?;
149     }
150
151     if has_slurs(&data.username) {
152       return Err(APIError::err(&self.op, "no_slurs"))?;
153     }
154
155     // Make sure there are no admins
156     if data.admin && UserView::admins(&conn)?.len() > 0 {
157       return Err(APIError::err(&self.op, "admin_already_created"))?;
158     }
159
160     // Register the new user
161     let user_form = UserForm {
162       name: data.username.to_owned(),
163       fedi_name: Settings::get().hostname.into(),
164       email: data.email.to_owned(),
165       password_encrypted: data.password.to_owned(),
166       preferred_username: None,
167       updated: None,
168       admin: data.admin,
169       banned: false,
170       show_nsfw: data.show_nsfw,
171       theme: "darkly".into(),
172     };
173
174     // Create the user
175     let inserted_user = match User_::register(&conn, &user_form) {
176       Ok(user) => user,
177       Err(_e) => return Err(APIError::err(&self.op, "user_already_exists"))?,
178     };
179
180     // Create the main community if it doesn't exist
181     let main_community: Community = match Community::read(&conn, 2) {
182       Ok(c) => c,
183       Err(_e) => {
184         let community_form = CommunityForm {
185           name: "main".to_string(),
186           title: "The Default Community".to_string(),
187           description: Some("The Default Community".to_string()),
188           category_id: 1,
189           nsfw: false,
190           creator_id: inserted_user.id,
191           removed: None,
192           deleted: None,
193           updated: None,
194         };
195         Community::create(&conn, &community_form).unwrap()
196       }
197     };
198
199     // Sign them up for main community no matter what
200     let community_follower_form = CommunityFollowerForm {
201       community_id: main_community.id,
202       user_id: inserted_user.id,
203     };
204
205     let _inserted_community_follower =
206       match CommunityFollower::follow(&conn, &community_follower_form) {
207         Ok(user) => user,
208         Err(_e) => return Err(APIError::err(&self.op, "community_follower_already_exists"))?,
209       };
210
211     // If its an admin, add them as a mod and follower to main
212     if data.admin {
213       let community_moderator_form = CommunityModeratorForm {
214         community_id: main_community.id,
215         user_id: inserted_user.id,
216       };
217
218       let _inserted_community_moderator =
219         match CommunityModerator::join(&conn, &community_moderator_form) {
220           Ok(user) => user,
221           Err(_e) => {
222             return Err(APIError::err(
223               &self.op,
224               "community_moderator_already_exists",
225             ))?
226           }
227         };
228     }
229
230     // Return the jwt
231     Ok(LoginResponse {
232       op: self.op.to_string(),
233       jwt: inserted_user.jwt(),
234     })
235   }
236 }
237
238 impl Perform<LoginResponse> for Oper<SaveUserSettings> {
239   fn perform(&self) -> Result<LoginResponse, Error> {
240     let data: &SaveUserSettings = &self.data;
241     let conn = establish_connection();
242
243     let claims = match Claims::decode(&data.auth) {
244       Ok(claims) => claims.claims,
245       Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
246     };
247
248     let user_id = claims.id;
249
250     let read_user = User_::read(&conn, user_id)?;
251
252     let user_form = UserForm {
253       name: read_user.name,
254       fedi_name: read_user.fedi_name,
255       email: read_user.email,
256       password_encrypted: read_user.password_encrypted,
257       preferred_username: read_user.preferred_username,
258       updated: Some(naive_now()),
259       admin: read_user.admin,
260       banned: read_user.banned,
261       show_nsfw: data.show_nsfw,
262       theme: data.theme.to_owned(),
263     };
264
265     let updated_user = match User_::update(&conn, user_id, &user_form) {
266       Ok(user) => user,
267       Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_user"))?,
268     };
269
270     // Return the jwt
271     Ok(LoginResponse {
272       op: self.op.to_string(),
273       jwt: updated_user.jwt(),
274     })
275   }
276 }
277
278 impl Perform<GetUserDetailsResponse> for Oper<GetUserDetails> {
279   fn perform(&self) -> Result<GetUserDetailsResponse, Error> {
280     let data: &GetUserDetails = &self.data;
281     let conn = establish_connection();
282
283     let user_claims: Option<Claims> = match &data.auth {
284       Some(auth) => match Claims::decode(&auth) {
285         Ok(claims) => Some(claims.claims),
286         Err(_e) => None,
287       },
288       None => None,
289     };
290
291     let user_id = match &user_claims {
292       Some(claims) => Some(claims.id),
293       None => None,
294     };
295
296     let show_nsfw = match &user_claims {
297       Some(claims) => claims.show_nsfw,
298       None => false,
299     };
300
301     //TODO add save
302     let sort = SortType::from_str(&data.sort)?;
303
304     let user_details_id = match data.user_id {
305       Some(id) => id,
306       None => {
307         User_::read_from_name(
308           &conn,
309           data.username.to_owned().unwrap_or("admin".to_string()),
310         )?
311         .id
312       }
313     };
314
315     let user_view = UserView::read(&conn, user_details_id)?;
316
317     // If its saved only, you don't care what creator it was
318     let posts = if data.saved_only {
319       PostView::list(
320         &conn,
321         PostListingType::All,
322         &sort,
323         data.community_id,
324         None,
325         None,
326         None,
327         Some(user_details_id),
328         show_nsfw,
329         data.saved_only,
330         false,
331         data.page,
332         data.limit,
333       )?
334     } else {
335       PostView::list(
336         &conn,
337         PostListingType::All,
338         &sort,
339         data.community_id,
340         Some(user_details_id),
341         None,
342         None,
343         user_id,
344         show_nsfw,
345         data.saved_only,
346         false,
347         data.page,
348         data.limit,
349       )?
350     };
351     let comments = if data.saved_only {
352       CommentView::list(
353         &conn,
354         &sort,
355         None,
356         None,
357         None,
358         Some(user_details_id),
359         data.saved_only,
360         data.page,
361         data.limit,
362       )?
363     } else {
364       CommentView::list(
365         &conn,
366         &sort,
367         None,
368         Some(user_details_id),
369         None,
370         user_id,
371         data.saved_only,
372         data.page,
373         data.limit,
374       )?
375     };
376
377     let follows = CommunityFollowerView::for_user(&conn, user_details_id)?;
378     let moderates = CommunityModeratorView::for_user(&conn, user_details_id)?;
379     let site_creator_id = Site::read(&conn, 1)?.creator_id;
380     let mut admins = UserView::admins(&conn)?;
381     let creator_index = admins.iter().position(|r| r.id == site_creator_id).unwrap();
382     let creator_user = admins.remove(creator_index);
383     admins.insert(0, creator_user);
384
385     // Return the jwt
386     Ok(GetUserDetailsResponse {
387       op: self.op.to_string(),
388       user: user_view,
389       follows: follows,
390       moderates: moderates,
391       comments: comments,
392       posts: posts,
393       admins: admins,
394     })
395   }
396 }
397
398 impl Perform<AddAdminResponse> for Oper<AddAdmin> {
399   fn perform(&self) -> Result<AddAdminResponse, Error> {
400     let data: &AddAdmin = &self.data;
401     let conn = establish_connection();
402
403     let claims = match Claims::decode(&data.auth) {
404       Ok(claims) => claims.claims,
405       Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
406     };
407
408     let user_id = claims.id;
409
410     // Make sure user is an admin
411     if UserView::read(&conn, user_id)?.admin == false {
412       return Err(APIError::err(&self.op, "not_an_admin"))?;
413     }
414
415     let read_user = User_::read(&conn, data.user_id)?;
416
417     let user_form = UserForm {
418       name: read_user.name,
419       fedi_name: read_user.fedi_name,
420       email: read_user.email,
421       password_encrypted: read_user.password_encrypted,
422       preferred_username: read_user.preferred_username,
423       updated: Some(naive_now()),
424       admin: data.added,
425       banned: read_user.banned,
426       show_nsfw: read_user.show_nsfw,
427       theme: read_user.theme,
428     };
429
430     match User_::update(&conn, data.user_id, &user_form) {
431       Ok(user) => user,
432       Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_user"))?,
433     };
434
435     // Mod tables
436     let form = ModAddForm {
437       mod_user_id: user_id,
438       other_user_id: data.user_id,
439       removed: Some(!data.added),
440     };
441
442     ModAdd::create(&conn, &form)?;
443
444     let site_creator_id = Site::read(&conn, 1)?.creator_id;
445     let mut admins = UserView::admins(&conn)?;
446     let creator_index = admins.iter().position(|r| r.id == site_creator_id).unwrap();
447     let creator_user = admins.remove(creator_index);
448     admins.insert(0, creator_user);
449
450     Ok(AddAdminResponse {
451       op: self.op.to_string(),
452       admins: admins,
453     })
454   }
455 }
456
457 impl Perform<BanUserResponse> for Oper<BanUser> {
458   fn perform(&self) -> Result<BanUserResponse, Error> {
459     let data: &BanUser = &self.data;
460     let conn = establish_connection();
461
462     let claims = match Claims::decode(&data.auth) {
463       Ok(claims) => claims.claims,
464       Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
465     };
466
467     let user_id = claims.id;
468
469     // Make sure user is an admin
470     if UserView::read(&conn, user_id)?.admin == false {
471       return Err(APIError::err(&self.op, "not_an_admin"))?;
472     }
473
474     let read_user = User_::read(&conn, data.user_id)?;
475
476     let user_form = UserForm {
477       name: read_user.name,
478       fedi_name: read_user.fedi_name,
479       email: read_user.email,
480       password_encrypted: read_user.password_encrypted,
481       preferred_username: read_user.preferred_username,
482       updated: Some(naive_now()),
483       admin: read_user.admin,
484       banned: data.ban,
485       show_nsfw: read_user.show_nsfw,
486       theme: read_user.theme,
487     };
488
489     match User_::update(&conn, data.user_id, &user_form) {
490       Ok(user) => user,
491       Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_user"))?,
492     };
493
494     // Mod tables
495     let expires = match data.expires {
496       Some(time) => Some(naive_from_unix(time)),
497       None => None,
498     };
499
500     let form = ModBanForm {
501       mod_user_id: user_id,
502       other_user_id: data.user_id,
503       reason: data.reason.to_owned(),
504       banned: Some(data.ban),
505       expires: expires,
506     };
507
508     ModBan::create(&conn, &form)?;
509
510     let user_view = UserView::read(&conn, data.user_id)?;
511
512     Ok(BanUserResponse {
513       op: self.op.to_string(),
514       user: user_view,
515       banned: data.ban,
516     })
517   }
518 }
519
520 impl Perform<GetRepliesResponse> for Oper<GetReplies> {
521   fn perform(&self) -> Result<GetRepliesResponse, Error> {
522     let data: &GetReplies = &self.data;
523     let conn = establish_connection();
524
525     let claims = match Claims::decode(&data.auth) {
526       Ok(claims) => claims.claims,
527       Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
528     };
529
530     let user_id = claims.id;
531
532     let sort = SortType::from_str(&data.sort)?;
533
534     let replies = ReplyView::get_replies(
535       &conn,
536       user_id,
537       &sort,
538       data.unread_only,
539       data.page,
540       data.limit,
541     )?;
542
543     // Return the jwt
544     Ok(GetRepliesResponse {
545       op: self.op.to_string(),
546       replies: replies,
547     })
548   }
549 }
550
551 impl Perform<GetRepliesResponse> for Oper<MarkAllAsRead> {
552   fn perform(&self) -> Result<GetRepliesResponse, Error> {
553     let data: &MarkAllAsRead = &self.data;
554     let conn = establish_connection();
555
556     let claims = match Claims::decode(&data.auth) {
557       Ok(claims) => claims.claims,
558       Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
559     };
560
561     let user_id = claims.id;
562
563     let replies = ReplyView::get_replies(&conn, user_id, &SortType::New, true, Some(1), Some(999))?;
564
565     for reply in &replies {
566       let comment_form = CommentForm {
567         content: reply.to_owned().content,
568         parent_id: reply.to_owned().parent_id,
569         post_id: reply.to_owned().post_id,
570         creator_id: reply.to_owned().creator_id,
571         removed: None,
572         deleted: None,
573         read: Some(true),
574         updated: reply.to_owned().updated,
575       };
576
577       let _updated_comment = match Comment::update(&conn, reply.id, &comment_form) {
578         Ok(comment) => comment,
579         Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_comment"))?,
580       };
581     }
582
583     let replies = ReplyView::get_replies(&conn, user_id, &SortType::New, true, Some(1), Some(999))?;
584
585     Ok(GetRepliesResponse {
586       op: self.op.to_string(),
587       replies: replies,
588     })
589   }
590 }
591
592 impl Perform<LoginResponse> for Oper<DeleteAccount> {
593   fn perform(&self) -> Result<LoginResponse, Error> {
594     let data: &DeleteAccount = &self.data;
595     let conn = establish_connection();
596
597     let claims = match Claims::decode(&data.auth) {
598       Ok(claims) => claims.claims,
599       Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
600     };
601
602     let user_id = claims.id;
603
604     // Comments
605     let comments = CommentView::list(
606       &conn,
607       &SortType::New,
608       None,
609       Some(user_id),
610       None,
611       None,
612       false,
613       None,
614       Some(std::i64::MAX),
615     )?;
616
617     for comment in &comments {
618       let comment_form = CommentForm {
619         content: "*Permananently Deleted*".to_string(),
620         parent_id: comment.to_owned().parent_id,
621         post_id: comment.to_owned().post_id,
622         creator_id: comment.to_owned().creator_id,
623         removed: None,
624         deleted: Some(true),
625         read: None,
626         updated: Some(naive_now()),
627       };
628
629       let _updated_comment = match Comment::update(&conn, comment.id, &comment_form) {
630         Ok(comment) => comment,
631         Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_comment"))?,
632       };
633     }
634
635     // Posts
636     let posts = PostView::list(
637       &conn,
638       PostListingType::All,
639       &SortType::New,
640       None,
641       Some(user_id),
642       None,
643       None,
644       None,
645       true,
646       false,
647       false,
648       None,
649       Some(std::i64::MAX),
650     )?;
651
652     for post in &posts {
653       let post_form = PostForm {
654         name: "*Permananently Deleted*".to_string(),
655         url: Some("https://deleted.com".to_string()),
656         body: Some("*Permananently Deleted*".to_string()),
657         creator_id: post.to_owned().creator_id,
658         community_id: post.to_owned().community_id,
659         removed: None,
660         deleted: Some(true),
661         nsfw: post.to_owned().nsfw,
662         locked: None,
663         stickied: None,
664         updated: Some(naive_now()),
665       };
666
667       let _updated_post = match Post::update(&conn, post.id, &post_form) {
668         Ok(post) => post,
669         Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_post"))?,
670       };
671     }
672
673     Ok(LoginResponse {
674       op: self.op.to_string(),
675       jwt: data.auth.to_owned(),
676     })
677   }
678 }