]> Untitled Git - lemmy.git/blob - server/src/websocket/server.rs
Reorganizing files before splitting out API
[lemmy.git] / server / src / websocket / server.rs
1 //! `ChatServer` is an actor. It maintains list of connection client session.
2 //! And manages available rooms. Peers send messages to other peers in same
3 //! room through `ChatServer`.
4
5 use actix::prelude::*;
6 use rand::{rngs::ThreadRng, Rng};
7 use std::collections::{HashMap, HashSet};
8 use serde::{Deserialize, Serialize};
9 use serde_json::{Value};
10 use bcrypt::{verify};
11 use std::str::FromStr;
12 use diesel::PgConnection;
13 use failure::Error;
14 use std::time::{SystemTime};
15
16 use {Crud, Joinable, Likeable, Followable, Bannable, Saveable, establish_connection, naive_now, naive_from_unix, SortType, SearchType, has_slurs, remove_slurs, Settings};
17 use db::community::*;
18 use db::user::*;
19 use db::post::*;
20 use db::comment::*;
21 use db::post_view::*;
22 use db::comment_view::*;
23 use db::category::*;
24 use db::community_view::*;
25 use db::user_view::*;
26 use db::moderator_views::*;
27 use db::moderator::*;
28
29 const RATE_LIMIT_MESSAGES: i32 = 30;
30 const RATE_LIMIT_PER_SECOND: i32 = 60;
31 const RATE_LIMIT_REGISTER_MESSAGES: i32 = 1;
32 const RATE_LIMIT_REGISTER_PER_SECOND: i32 = 60;
33
34 #[derive(EnumString,ToString,Debug)]
35 pub enum UserOperation {
36   Login, Register, CreateCommunity, CreatePost, ListCommunities, ListCategories, GetPost, GetCommunity, CreateComment, EditComment, SaveComment, CreateCommentLike, GetPosts, CreatePostLike, EditPost, SavePost, EditCommunity, FollowCommunity, GetFollowedCommunities, GetUserDetails, GetReplies, GetModlog, BanFromCommunity, AddModToCommunity, CreateSite, EditSite, GetSite, AddAdmin, BanUser, Search, MarkAllAsRead
37 }
38
39 #[derive(Fail, Debug)]
40 #[fail(display = "{{\"op\":\"{}\", \"error\":\"{}\"}}", op, message)]
41 pub struct ErrorMessage {
42   op: String,
43   message: String
44 }
45
46 /// Chat server sends this messages to session
47 #[derive(Message)]
48 pub struct WSMessage(pub String);
49
50 /// Message for chat server communications
51
52 /// New chat session is created
53 #[derive(Message)]
54 #[rtype(usize)]
55 pub struct Connect {
56   pub addr: Recipient<WSMessage>,
57   pub ip: String,
58 }
59
60 /// Session is disconnected
61 #[derive(Message)]
62 pub struct Disconnect {
63   pub id: usize,
64   pub ip: String,
65 }
66
67 /// Send message to specific room
68 #[derive(Message)]
69 pub struct ClientMessage {
70   /// Id of the client session
71   pub id: usize,
72   /// Peer message
73   pub msg: String,
74   /// Room name
75   pub room: String,
76 }
77
78 #[derive(Serialize, Deserialize)]
79 pub struct StandardMessage {
80   /// Id of the client session
81   pub id: usize,
82   /// Peer message
83   pub msg: String,
84 }
85
86 impl actix::Message for StandardMessage {
87   type Result = String;
88 }
89
90 #[derive(Serialize, Deserialize)]
91 pub struct Login {
92   pub username_or_email: String,
93   pub password: String
94 }
95
96 #[derive(Serialize, Deserialize)]
97 pub struct Register {
98   username: String,
99   email: Option<String>,
100   password: String,
101   password_verify: String,
102   admin: bool,
103   spam_timeri: i64,
104 }
105
106 #[derive(Serialize, Deserialize)]
107 pub struct LoginResponse {
108   op: String,
109   jwt: String
110 }
111
112 #[derive(Serialize, Deserialize)]
113 pub struct CreateCommunity {
114   name: String,
115   title: String,
116   description: Option<String>,
117   category_id: i32 ,
118   auth: String
119 }
120
121 #[derive(Serialize, Deserialize)]
122 pub struct CommunityResponse {
123   op: String,
124   community: CommunityView
125 }
126
127 #[derive(Serialize, Deserialize)]
128 pub struct ListCommunities {
129   sort: String,
130   page: Option<i64>,
131   limit: Option<i64>,
132   auth: Option<String>
133 }
134
135 #[derive(Serialize, Deserialize)]
136 pub struct ListCommunitiesResponse {
137   op: String,
138   communities: Vec<CommunityView>
139 }
140
141 #[derive(Serialize, Deserialize)]
142 pub struct ListCategories;
143
144 #[derive(Serialize, Deserialize)]
145 pub struct ListCategoriesResponse {
146   op: String,
147   categories: Vec<Category>
148 }
149
150 #[derive(Serialize, Deserialize)]
151 pub struct CreatePost {
152   name: String,
153   url: Option<String>,
154   body: Option<String>,
155   community_id: i32,
156   auth: String
157 }
158
159 #[derive(Serialize, Deserialize)]
160 pub struct PostResponse {
161   op: String,
162   post: PostView
163 }
164
165
166 #[derive(Serialize, Deserialize)]
167 pub struct GetPost {
168   id: i32,
169   auth: Option<String>
170 }
171
172 #[derive(Serialize, Deserialize)]
173 pub struct GetPostResponse {
174   op: String,
175   post: PostView,
176   comments: Vec<CommentView>,
177   community: CommunityView,
178   moderators: Vec<CommunityModeratorView>,
179   admins: Vec<UserView>,
180 }
181
182 #[derive(Serialize, Deserialize)]
183 pub struct GetPosts {
184   type_: String,
185   sort: String,
186   page: Option<i64>,
187   limit: Option<i64>,
188   community_id: Option<i32>,
189   auth: Option<String>
190 }
191
192 #[derive(Serialize, Deserialize)]
193 pub struct GetPostsResponse {
194   op: String,
195   posts: Vec<PostView>,
196 }
197
198 #[derive(Serialize, Deserialize)]
199 pub struct GetCommunity {
200   id: Option<i32>,
201   name: Option<String>,
202   auth: Option<String>
203 }
204
205 #[derive(Serialize, Deserialize)]
206 pub struct GetCommunityResponse {
207   op: String,
208   community: CommunityView,
209   moderators: Vec<CommunityModeratorView>,
210   admins: Vec<UserView>,
211 }
212
213 #[derive(Serialize, Deserialize)]
214 pub struct CreateComment {
215   content: String,
216   parent_id: Option<i32>,
217   edit_id: Option<i32>,
218   post_id: i32,
219   auth: String
220 }
221
222 #[derive(Serialize, Deserialize)]
223 pub struct EditComment {
224   content: String,
225   parent_id: Option<i32>,
226   edit_id: i32,
227   creator_id: i32,
228   post_id: i32,
229   removed: Option<bool>,
230   deleted: Option<bool>,
231   reason: Option<String>,
232   read: Option<bool>,
233   auth: String
234 }
235
236 #[derive(Serialize, Deserialize)]
237 pub struct SaveComment {
238   comment_id: i32,
239   save: bool,
240   auth: String
241 }
242
243 #[derive(Serialize, Deserialize)]
244 pub struct CommentResponse {
245   op: String,
246   comment: CommentView
247 }
248
249 #[derive(Serialize, Deserialize)]
250 pub struct CreateCommentLike {
251   comment_id: i32,
252   post_id: i32,
253   score: i16,
254   auth: String
255 }
256
257 #[derive(Serialize, Deserialize)]
258 pub struct CreatePostLike {
259   post_id: i32,
260   score: i16,
261   auth: String
262 }
263
264 #[derive(Serialize, Deserialize)]
265 pub struct CreatePostLikeResponse {
266   op: String,
267   post: PostView
268 }
269
270
271 #[derive(Serialize, Deserialize)]
272 pub struct EditPost {
273   edit_id: i32,
274   creator_id: i32,
275   community_id: i32,
276   name: String,
277   url: Option<String>,
278   body: Option<String>,
279   removed: Option<bool>,
280   deleted: Option<bool>,
281   locked: Option<bool>,
282   reason: Option<String>,
283   auth: String
284 }
285
286 #[derive(Serialize, Deserialize)]
287 pub struct SavePost {
288   post_id: i32,
289   save: bool,
290   auth: String
291 }
292
293 #[derive(Serialize, Deserialize)]
294 pub struct EditCommunity {
295   edit_id: i32,
296   name: String,
297   title: String,
298   description: Option<String>,
299   category_id: i32,
300   removed: Option<bool>,
301   deleted: Option<bool>,
302   reason: Option<String>,
303   expires: Option<i64>,
304   auth: String
305 }
306
307 #[derive(Serialize, Deserialize)]
308 pub struct FollowCommunity {
309   community_id: i32,
310   follow: bool,
311   auth: String
312 }
313
314 #[derive(Serialize, Deserialize)]
315 pub struct GetFollowedCommunities {
316   auth: String
317 }
318
319 #[derive(Serialize, Deserialize)]
320 pub struct GetFollowedCommunitiesResponse {
321   op: String,
322   communities: Vec<CommunityFollowerView>
323 }
324
325 #[derive(Serialize, Deserialize)]
326 pub struct GetUserDetails {
327   user_id: Option<i32>,
328   username: Option<String>,
329   sort: String,
330   page: Option<i64>,
331   limit: Option<i64>,
332   community_id: Option<i32>,
333   saved_only: bool,
334   auth: Option<String>,
335 }
336
337 #[derive(Serialize, Deserialize)]
338 pub struct GetUserDetailsResponse {
339   op: String,
340   user: UserView,
341   follows: Vec<CommunityFollowerView>,
342   moderates: Vec<CommunityModeratorView>,
343   comments: Vec<CommentView>,
344   posts: Vec<PostView>,
345 }
346
347 #[derive(Serialize, Deserialize)]
348 pub struct GetModlog {
349   mod_user_id: Option<i32>,
350   community_id: Option<i32>,
351   page: Option<i64>,
352   limit: Option<i64>,
353 }
354
355 #[derive(Serialize, Deserialize)]
356 pub struct GetModlogResponse {
357   op: String,
358   removed_posts: Vec<ModRemovePostView>,
359   locked_posts: Vec<ModLockPostView>,
360   removed_comments: Vec<ModRemoveCommentView>,
361   removed_communities: Vec<ModRemoveCommunityView>,
362   banned_from_community: Vec<ModBanFromCommunityView>,
363   banned: Vec<ModBanView>,
364   added_to_community: Vec<ModAddCommunityView>,
365   added: Vec<ModAddView>,
366 }
367
368 #[derive(Serialize, Deserialize)]
369 pub struct BanFromCommunity {
370   community_id: i32,
371   user_id: i32,
372   ban: bool,
373   reason: Option<String>,
374   expires: Option<i64>,
375   auth: String
376 }
377
378 #[derive(Serialize, Deserialize)]
379 pub struct BanFromCommunityResponse {
380   op: String,
381   user: UserView,
382   banned: bool,
383 }
384
385
386 #[derive(Serialize, Deserialize)]
387 pub struct AddModToCommunity {
388   community_id: i32,
389   user_id: i32,
390   added: bool,
391   auth: String
392 }
393
394 #[derive(Serialize, Deserialize)]
395 pub struct AddModToCommunityResponse {
396   op: String,
397   moderators: Vec<CommunityModeratorView>,
398 }
399
400 #[derive(Serialize, Deserialize)]
401 pub struct CreateSite {
402   name: String,
403   description: Option<String>,
404   auth: String
405 }
406
407 #[derive(Serialize, Deserialize)]
408 pub struct EditSite {
409   name: String,
410   description: Option<String>,
411   auth: String
412 }
413
414 #[derive(Serialize, Deserialize)]
415 pub struct GetSite {
416 }
417
418 #[derive(Serialize, Deserialize)]
419 pub struct SiteResponse {
420   op: String,
421   site: SiteView,
422 }
423
424 #[derive(Serialize, Deserialize)]
425 pub struct GetSiteResponse {
426   op: String,
427   site: Option<SiteView>,
428   admins: Vec<UserView>,
429   banned: Vec<UserView>,
430 }
431
432 #[derive(Serialize, Deserialize)]
433 pub struct AddAdmin {
434   user_id: i32,
435   added: bool,
436   auth: String
437 }
438
439 #[derive(Serialize, Deserialize)]
440 pub struct AddAdminResponse {
441   op: String,
442   admins: Vec<UserView>,
443 }
444
445 #[derive(Serialize, Deserialize)]
446 pub struct BanUser {
447   user_id: i32,
448   ban: bool,
449   reason: Option<String>,
450   expires: Option<i64>,
451   auth: String
452 }
453
454 #[derive(Serialize, Deserialize)]
455 pub struct BanUserResponse {
456   op: String,
457   user: UserView,
458   banned: bool,
459 }
460
461 #[derive(Serialize, Deserialize)]
462 pub struct GetReplies {
463   sort: String,
464   page: Option<i64>,
465   limit: Option<i64>,
466   unread_only: bool,
467   auth: String
468 }
469
470 #[derive(Serialize, Deserialize)]
471 pub struct GetRepliesResponse {
472   op: String,
473   replies: Vec<ReplyView>,
474 }
475
476 #[derive(Serialize, Deserialize)]
477 pub struct Search {
478   q: String,
479   type_: String,
480   community_id: Option<i32>,
481   sort: String,
482   page: Option<i64>,
483   limit: Option<i64>,
484 }
485
486 #[derive(Serialize, Deserialize)]
487 pub struct SearchResponse {
488   op: String,
489   comments: Vec<CommentView>,
490   posts: Vec<PostView>,
491 }
492
493 #[derive(Serialize, Deserialize)]
494 pub struct MarkAllAsRead {
495   auth: String
496 }
497
498 #[derive(Debug)]
499 pub struct RateLimitBucket {
500   last_checked: SystemTime,
501   allowance: f64
502 }
503
504 pub struct SessionInfo {
505   pub addr: Recipient<WSMessage>,
506   pub ip: String,
507 }
508
509 /// `ChatServer` manages chat rooms and responsible for coordinating chat
510 /// session. implementation is super primitive
511 pub struct ChatServer {
512   sessions: HashMap<usize, SessionInfo>, // A map from generated random ID to session addr
513   rate_limits: HashMap<String, RateLimitBucket>,
514   rooms: HashMap<i32, HashSet<usize>>, // A map from room / post name to set of connectionIDs
515   rng: ThreadRng,
516 }
517
518 impl Default for ChatServer {
519   fn default() -> ChatServer {
520     // default room
521     let rooms = HashMap::new();
522
523     ChatServer {
524       sessions: HashMap::new(),
525       rate_limits: HashMap::new(),
526       rooms: rooms,
527       rng: rand::thread_rng(),
528     }
529   }
530 }
531
532 impl ChatServer {
533   /// Send message to all users in the room
534   fn send_room_message(&self, room: i32, message: &str, skip_id: usize) {
535     if let Some(sessions) = self.rooms.get(&room) {
536       for id in sessions {
537         if *id != skip_id {
538           if let Some(info) = self.sessions.get(id) {
539             let _ = info.addr.do_send(WSMessage(message.to_owned()));
540           }
541         }
542       }
543     }
544   }
545
546   fn send_community_message(&self, conn: &PgConnection, community_id: i32, message: &str, skip_id: usize) -> Result<(), Error> {
547     let posts = PostView::list(conn,
548                                PostListingType::Community, 
549                                &SortType::New, 
550                                Some(community_id), 
551                                None,
552                                None, 
553                                None,
554                                false,
555                                false,
556                                None,
557                                Some(9999))?;
558     for post in posts {
559       self.send_room_message(post.id, message, skip_id);
560     }
561
562     Ok(())
563   }
564
565   fn check_rate_limit_register(&mut self, addr: usize) -> Result<(), Error> {
566     self.check_rate_limit_full(addr, RATE_LIMIT_REGISTER_MESSAGES, RATE_LIMIT_REGISTER_PER_SECOND)
567   }
568
569   fn check_rate_limit(&mut self, addr: usize) -> Result<(), Error> {
570     self.check_rate_limit_full(addr, RATE_LIMIT_MESSAGES, RATE_LIMIT_PER_SECOND)
571   }
572
573   fn check_rate_limit_full(&mut self, addr: usize, rate: i32, per: i32) -> Result<(), Error> {
574     if let Some(info) = self.sessions.get(&addr) {
575       if let Some(rate_limit) = self.rate_limits.get_mut(&info.ip) {
576         // The initial value
577         if rate_limit.allowance == -2f64 {
578           rate_limit.allowance = rate as f64;
579         };
580
581         let current = SystemTime::now();
582         let time_passed = current.duration_since(rate_limit.last_checked)?.as_secs() as f64;
583         rate_limit.last_checked = current;
584         rate_limit.allowance += time_passed * (rate as f64 / per as f64);
585         if rate_limit.allowance > rate as f64 {
586           rate_limit.allowance = rate as f64;
587         }
588
589         if rate_limit.allowance < 1.0 {
590           println!("Rate limited IP: {}, time_passed: {}, allowance: {}", &info.ip, time_passed, rate_limit.allowance);
591           Err(ErrorMessage {
592             op: "Rate Limit".to_string(), 
593             message: format!("Too many requests. {} per {} seconds", rate, per),
594           })?
595         } else {
596           rate_limit.allowance -= 1.0;
597           Ok(())
598         }
599       } else {
600         Ok(())
601       }
602     } else {
603       Ok(())
604     }
605   }
606 }
607
608
609 /// Make actor from `ChatServer`
610 impl Actor for ChatServer {
611   /// We are going to use simple Context, we just need ability to communicate
612   /// with other actors.
613   type Context = Context<Self>;
614 }
615
616 /// Handler for Connect message.
617 ///
618 /// Register new session and assign unique id to this session
619 impl Handler<Connect> for ChatServer {
620   type Result = usize;
621
622   fn handle(&mut self, msg: Connect, _ctx: &mut Context<Self>) -> Self::Result {
623
624     // notify all users in same room
625     // self.send_room_message(&"Main".to_owned(), "Someone joined", 0);
626
627     // register session with random id
628     let id = self.rng.gen::<usize>();
629     println!("{} joined", &msg.ip);
630
631     self.sessions.insert(id, SessionInfo {
632       addr: msg.addr,
633       ip: msg.ip.to_owned(),
634     });
635
636     if self.rate_limits.get(&msg.ip).is_none() {
637       self.rate_limits.insert(msg.ip, RateLimitBucket {
638         last_checked: SystemTime::now(),
639         allowance: -2f64,
640       });
641     }
642
643     // for (k,v) in &self.rate_limits {
644     //   println!("{}: {:?}", k,v);
645     // }
646
647     // auto join session to Main room
648     // self.rooms.get_mut(&"Main".to_owned()).unwrap().insert(id);
649
650     // send id back
651     id
652   }
653 }
654
655
656 /// Handler for Disconnect message.
657 impl Handler<Disconnect> for ChatServer {
658   type Result = ();
659
660   fn handle(&mut self, msg: Disconnect, _: &mut Context<Self>) {
661
662     // let mut rooms: Vec<i32> = Vec::new();
663
664     // remove address
665     if self.sessions.remove(&msg.id).is_some() {
666       // remove session from all rooms
667       for (_id, sessions) in &mut self.rooms {
668         if sessions.remove(&msg.id) {
669           // rooms.push(*id);
670         }
671       }
672     }
673   }
674 }
675
676 /// Handler for Message message.
677 impl Handler<StandardMessage> for ChatServer {
678   type Result = MessageResult<StandardMessage>;
679
680
681   fn handle(&mut self, msg: StandardMessage, _: &mut Context<Self>) -> Self::Result {
682
683     let msg_out = match parse_json_message(self, msg) {
684       Ok(m) => m,
685       Err(e) => e.to_string()
686     };
687
688     MessageResult(msg_out)
689   }
690 }
691
692 fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<String, Error> {
693
694   let json: Value = serde_json::from_str(&msg.msg)?;
695   let data = &json["data"].to_string();
696   let op = &json["op"].as_str().unwrap();
697
698   let user_operation: UserOperation = UserOperation::from_str(&op)?;
699
700   match user_operation {
701     UserOperation::Login => {
702       let login: Login = serde_json::from_str(data)?;
703       login.perform(chat, msg.id)
704     },
705     UserOperation::Register => {
706       let register: Register = serde_json::from_str(data)?;
707       register.perform(chat, msg.id)
708     },
709     UserOperation::CreateCommunity => {
710       let create_community: CreateCommunity = serde_json::from_str(data)?;
711       create_community.perform(chat, msg.id)
712     },
713     UserOperation::ListCommunities => {
714       let list_communities: ListCommunities = serde_json::from_str(data)?;
715       list_communities.perform(chat, msg.id)
716     },
717     UserOperation::ListCategories => {
718       let list_categories: ListCategories = ListCategories;
719       list_categories.perform(chat, msg.id)
720     },
721     UserOperation::CreatePost => {
722       let create_post: CreatePost = serde_json::from_str(data)?;
723       create_post.perform(chat, msg.id)
724     },
725     UserOperation::GetPost => {
726       let get_post: GetPost = serde_json::from_str(data)?;
727       get_post.perform(chat, msg.id)
728     },
729     UserOperation::GetCommunity => {
730       let get_community: GetCommunity = serde_json::from_str(data)?;
731       get_community.perform(chat, msg.id)
732     },
733     UserOperation::CreateComment => {
734       let create_comment: CreateComment = serde_json::from_str(data)?;
735       create_comment.perform(chat, msg.id)
736     },
737     UserOperation::EditComment => {
738       let edit_comment: EditComment = serde_json::from_str(data)?;
739       edit_comment.perform(chat, msg.id)
740     },
741     UserOperation::SaveComment => {
742       let save_post: SaveComment = serde_json::from_str(data)?;
743       save_post.perform(chat, msg.id)
744     },
745     UserOperation::CreateCommentLike => {
746       let create_comment_like: CreateCommentLike = serde_json::from_str(data)?;
747       create_comment_like.perform(chat, msg.id)
748     },
749     UserOperation::GetPosts => {
750       let get_posts: GetPosts = serde_json::from_str(data)?;
751       get_posts.perform(chat, msg.id)
752     },
753     UserOperation::CreatePostLike => {
754       let create_post_like: CreatePostLike = serde_json::from_str(data)?;
755       create_post_like.perform(chat, msg.id)
756     },
757     UserOperation::EditPost => {
758       let edit_post: EditPost = serde_json::from_str(data)?;
759       edit_post.perform(chat, msg.id)
760     },
761     UserOperation::SavePost => {
762       let save_post: SavePost = serde_json::from_str(data)?;
763       save_post.perform(chat, msg.id)
764     },
765     UserOperation::EditCommunity => {
766       let edit_community: EditCommunity = serde_json::from_str(data)?;
767       edit_community.perform(chat, msg.id)
768     },
769     UserOperation::FollowCommunity => {
770       let follow_community: FollowCommunity = serde_json::from_str(data)?;
771       follow_community.perform(chat, msg.id)
772     },
773     UserOperation::GetFollowedCommunities => {
774       let followed_communities: GetFollowedCommunities = serde_json::from_str(data)?;
775       followed_communities.perform(chat, msg.id)
776     },
777     UserOperation::GetUserDetails => {
778       let get_user_details: GetUserDetails = serde_json::from_str(data)?;
779       get_user_details.perform(chat, msg.id)
780     },
781     UserOperation::GetModlog => {
782       let get_modlog: GetModlog = serde_json::from_str(data)?;
783       get_modlog.perform(chat, msg.id)
784     },
785     UserOperation::BanFromCommunity => {
786       let ban_from_community: BanFromCommunity = serde_json::from_str(data)?;
787       ban_from_community.perform(chat, msg.id)
788     },
789     UserOperation::AddModToCommunity => {
790       let mod_add_to_community: AddModToCommunity = serde_json::from_str(data)?;
791       mod_add_to_community.perform(chat, msg.id)
792     },
793     UserOperation::CreateSite => {
794       let create_site: CreateSite = serde_json::from_str(data)?;
795       create_site.perform(chat, msg.id)
796     },
797     UserOperation::EditSite => {
798       let edit_site: EditSite = serde_json::from_str(data)?;
799       edit_site.perform(chat, msg.id)
800     },
801     UserOperation::GetSite => {
802       let get_site: GetSite = serde_json::from_str(data)?;
803       get_site.perform(chat, msg.id)
804     },
805     UserOperation::AddAdmin => {
806       let add_admin: AddAdmin = serde_json::from_str(data)?;
807       add_admin.perform(chat, msg.id)
808     },
809     UserOperation::BanUser => {
810       let ban_user: BanUser = serde_json::from_str(data)?;
811       ban_user.perform(chat, msg.id)
812     },
813     UserOperation::GetReplies => {
814       let get_replies: GetReplies = serde_json::from_str(data)?;
815       get_replies.perform(chat, msg.id)
816     },
817     UserOperation::Search => {
818       let search: Search = serde_json::from_str(data)?;
819       search.perform(chat, msg.id)
820     },
821     UserOperation::MarkAllAsRead => {
822       let mark_all_as_read: MarkAllAsRead = serde_json::from_str(data)?;
823       mark_all_as_read.perform(chat, msg.id)
824     },
825   }
826 }
827
828 pub trait Perform {
829   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error>;
830   fn op_type(&self) -> UserOperation;
831   fn error(&self, error_msg: &str) -> ErrorMessage {
832     ErrorMessage {
833       op: self.op_type().to_string(), 
834       message: error_msg.to_string()
835     }
836   }
837 }
838
839 impl Perform for Login {
840
841   fn op_type(&self) -> UserOperation {
842     UserOperation::Login
843   }
844
845   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
846
847     let conn = establish_connection();
848
849     // Fetch that username / email
850     let user: User_ = match User_::find_by_email_or_username(&conn, &self.username_or_email) {
851       Ok(user) => user,
852       Err(_e) => return Err(self.error("Couldn't find that username or email"))?
853     };
854
855     // Verify the password
856     let valid: bool = verify(&self.password, &user.password_encrypted).unwrap_or(false);
857     if !valid {
858       return Err(self.error("Password incorrect"))?
859     }
860
861     // Return the jwt
862     Ok(
863       serde_json::to_string(
864         &LoginResponse {
865           op: self.op_type().to_string(),
866           jwt: user.jwt()
867         }
868         )?
869       )
870   }
871
872 }
873
874 impl Perform for Register {
875   fn op_type(&self) -> UserOperation {
876     UserOperation::Register
877   }
878   fn perform(&self, chat: &mut ChatServer, addr: usize) -> Result<String, Error> {
879
880     let conn = establish_connection();
881
882     chat.check_rate_limit_register(addr)?;
883
884     // Make sure passwords match
885     if &self.password != &self.password_verify {
886       return Err(self.error("Passwords do not match."))?
887     }
888
889     if self.spam_timeri < 1142 {
890       return Err(self.error("Too fast"))?
891     }
892
893     if has_slurs(&self.username) {
894       return Err(self.error("No slurs"))?
895     }
896
897     // Make sure there are no admins
898     if self.admin && UserView::admins(&conn)?.len() > 0 {
899       return Err(self.error("Sorry, there's already an admin."))?
900     }
901
902     // Register the new user
903     let user_form = UserForm {
904       name: self.username.to_owned(),
905       fedi_name: Settings::get().hostname.into(),
906       email: self.email.to_owned(),
907       password_encrypted: self.password.to_owned(),
908       preferred_username: None,
909       updated: None,
910       admin: self.admin,
911       banned: false,
912     };
913
914     // Create the user
915     let inserted_user = match User_::register(&conn, &user_form) {
916       Ok(user) => user,
917       Err(_e) => {
918         return Err(self.error("User already exists."))?
919       }
920     };
921
922     // Sign them up for main community no matter what
923     let community_follower_form = CommunityFollowerForm {
924       community_id: 1,
925       user_id: inserted_user.id,
926     };
927
928     let _inserted_community_follower = match CommunityFollower::follow(&conn, &community_follower_form) {
929       Ok(user) => user,
930       Err(_e) => {
931         return Err(self.error("Community follower already exists."))?
932       }
933     };
934
935     // If its an admin, add them as a mod and follower to main
936     if self.admin {
937       let community_moderator_form = CommunityModeratorForm {
938         community_id: 1,
939         user_id: inserted_user.id,
940       };
941
942       let _inserted_community_moderator = match CommunityModerator::join(&conn, &community_moderator_form) {
943         Ok(user) => user,
944         Err(_e) => {
945           return Err(self.error("Community moderator already exists."))?
946         }
947       };
948
949     }
950
951
952     // Return the jwt
953     Ok(
954       serde_json::to_string(
955         &LoginResponse {
956           op: self.op_type().to_string(), 
957           jwt: inserted_user.jwt()
958         }
959         )?
960       )
961
962   }
963 }
964
965 impl Perform for CreateCommunity {
966   fn op_type(&self) -> UserOperation {
967     UserOperation::CreateCommunity
968   }
969
970   fn perform(&self, chat: &mut ChatServer, addr: usize) -> Result<String, Error> {
971
972     let conn = establish_connection();
973
974     chat.check_rate_limit_register(addr)?;
975
976     let claims = match Claims::decode(&self.auth) {
977       Ok(claims) => claims.claims,
978       Err(_e) => {
979         return Err(self.error("Not logged in."))?
980       }
981     };
982
983     if has_slurs(&self.name) || 
984       has_slurs(&self.title) || 
985         (self.description.is_some() && has_slurs(&self.description.to_owned().unwrap())) {
986           return Err(self.error("No slurs"))?
987         }
988
989     let user_id = claims.id;
990
991     // Check for a site ban
992     if UserView::read(&conn, user_id)?.banned {
993       return Err(self.error("You have been banned from the site"))?
994     }
995
996     // When you create a community, make sure the user becomes a moderator and a follower
997     let community_form = CommunityForm {
998       name: self.name.to_owned(),
999       title: self.title.to_owned(),
1000       description: self.description.to_owned(),
1001       category_id: self.category_id,
1002       creator_id: user_id,
1003       removed: None,
1004       deleted: None,
1005       updated: None,
1006     };
1007
1008     let inserted_community = match Community::create(&conn, &community_form) {
1009       Ok(community) => community,
1010       Err(_e) => {
1011         return Err(self.error("Community already exists."))?
1012       }
1013     };
1014
1015     let community_moderator_form = CommunityModeratorForm {
1016       community_id: inserted_community.id,
1017       user_id: user_id
1018     };
1019
1020     let _inserted_community_moderator = match CommunityModerator::join(&conn, &community_moderator_form) {
1021       Ok(user) => user,
1022       Err(_e) => {
1023         return Err(self.error("Community moderator already exists."))?
1024       }
1025     };
1026
1027     let community_follower_form = CommunityFollowerForm {
1028       community_id: inserted_community.id,
1029       user_id: user_id
1030     };
1031
1032     let _inserted_community_follower = match CommunityFollower::follow(&conn, &community_follower_form) {
1033       Ok(user) => user,
1034       Err(_e) => {
1035         return Err(self.error("Community follower already exists."))?
1036       }
1037     };
1038
1039     let community_view = CommunityView::read(&conn, inserted_community.id, Some(user_id))?;
1040
1041     Ok(
1042       serde_json::to_string(
1043         &CommunityResponse {
1044           op: self.op_type().to_string(), 
1045           community: community_view
1046         }
1047         )?
1048       )
1049   }
1050 }
1051
1052 impl Perform for ListCommunities {
1053   fn op_type(&self) -> UserOperation {
1054     UserOperation::ListCommunities
1055   }
1056
1057   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
1058
1059     let conn = establish_connection();
1060
1061     let user_id: Option<i32> = match &self.auth {
1062       Some(auth) => {
1063         match Claims::decode(&auth) {
1064           Ok(claims) => {
1065             let user_id = claims.claims.id;
1066             Some(user_id)
1067           }
1068           Err(_e) => None
1069         }
1070       }
1071       None => None
1072     };
1073
1074     let sort = SortType::from_str(&self.sort)?;
1075
1076     let communities: Vec<CommunityView> = CommunityView::list(&conn, user_id, sort, self.page, self.limit)?;
1077
1078     // Return the jwt
1079     Ok(
1080       serde_json::to_string(
1081         &ListCommunitiesResponse {
1082           op: self.op_type().to_string(),
1083           communities: communities
1084         }
1085         )?
1086       )
1087   }
1088 }
1089
1090 impl Perform for ListCategories {
1091   fn op_type(&self) -> UserOperation {
1092     UserOperation::ListCategories
1093   }
1094
1095   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
1096
1097     let conn = establish_connection();
1098
1099     let categories: Vec<Category> = Category::list_all(&conn)?;
1100
1101     // Return the jwt
1102     Ok(
1103       serde_json::to_string(
1104         &ListCategoriesResponse {
1105           op: self.op_type().to_string(),
1106           categories: categories
1107         }
1108         )?
1109       )
1110   }
1111 }
1112
1113 impl Perform for CreatePost {
1114   fn op_type(&self) -> UserOperation {
1115     UserOperation::CreatePost
1116   }
1117
1118   fn perform(&self, chat: &mut ChatServer, addr: usize) -> Result<String, Error> {
1119
1120     let conn = establish_connection();
1121
1122     chat.check_rate_limit_register(addr)?;
1123
1124     let claims = match Claims::decode(&self.auth) {
1125       Ok(claims) => claims.claims,
1126       Err(_e) => {
1127         return Err(self.error("Not logged in."))?
1128       }
1129     };
1130
1131     if has_slurs(&self.name) || 
1132       (self.body.is_some() && has_slurs(&self.body.to_owned().unwrap())) {
1133         return Err(self.error("No slurs"))?
1134       }
1135
1136     let user_id = claims.id;
1137
1138     // Check for a community ban
1139     if CommunityUserBanView::get(&conn, user_id, self.community_id).is_ok() {
1140       return Err(self.error("You have been banned from this community"))?
1141     }
1142
1143     // Check for a site ban
1144     if UserView::read(&conn, user_id)?.banned {
1145       return Err(self.error("You have been banned from the site"))?
1146     }
1147
1148     let post_form = PostForm {
1149       name: self.name.to_owned(),
1150       url: self.url.to_owned(),
1151       body: self.body.to_owned(),
1152       community_id: self.community_id,
1153       creator_id: user_id,
1154       removed: None,
1155       deleted: None,
1156       locked: None,
1157       updated: None
1158     };
1159
1160     let inserted_post = match Post::create(&conn, &post_form) {
1161       Ok(post) => post,
1162       Err(_e) => {
1163         return Err(self.error("Couldn't create Post"))?
1164       }
1165     };
1166
1167     // They like their own post by default
1168     let like_form = PostLikeForm {
1169       post_id: inserted_post.id,
1170       user_id: user_id,
1171       score: 1
1172     };
1173
1174     // Only add the like if the score isnt 0
1175     let _inserted_like = match PostLike::like(&conn, &like_form) {
1176       Ok(like) => like,
1177       Err(_e) => {
1178         return Err(self.error("Couldn't like post."))?
1179       }
1180     };
1181
1182     // Refetch the view
1183     let post_view = match PostView::read(&conn, inserted_post.id, Some(user_id)) {
1184       Ok(post) => post,
1185       Err(_e) => {
1186         return Err(self.error("Couldn't find Post"))?
1187       }
1188     };
1189
1190     Ok(
1191       serde_json::to_string(
1192         &PostResponse {
1193           op: self.op_type().to_string(), 
1194           post: post_view
1195         }
1196         )?
1197       )
1198   }
1199 }
1200
1201
1202 impl Perform for GetPost {
1203   fn op_type(&self) -> UserOperation {
1204     UserOperation::GetPost
1205   }
1206
1207   fn perform(&self, chat: &mut ChatServer, addr: usize) -> Result<String, Error> {
1208
1209     let conn = establish_connection();
1210
1211     let user_id: Option<i32> = match &self.auth {
1212       Some(auth) => {
1213         match Claims::decode(&auth) {
1214           Ok(claims) => {
1215             let user_id = claims.claims.id;
1216             Some(user_id)
1217           }
1218           Err(_e) => None
1219         }
1220       }
1221       None => None
1222     };
1223
1224     let post_view = match PostView::read(&conn, self.id, user_id) {
1225       Ok(post) => post,
1226       Err(_e) => {
1227         return Err(self.error("Couldn't find Post"))?
1228       }
1229     };
1230
1231     // remove session from all rooms
1232     for (_n, sessions) in &mut chat.rooms {
1233       sessions.remove(&addr);
1234     }
1235
1236     if chat.rooms.get_mut(&self.id).is_none() {
1237       chat.rooms.insert(self.id, HashSet::new());
1238     }
1239
1240     chat.rooms.get_mut(&self.id).unwrap().insert(addr);
1241
1242     let comments = CommentView::list(&conn, &SortType::New, Some(self.id), None, None, user_id, false, None, Some(9999))?;
1243
1244     let community = CommunityView::read(&conn, post_view.community_id, user_id)?;
1245
1246     let moderators = CommunityModeratorView::for_community(&conn, post_view.community_id)?;
1247
1248     let admins = UserView::admins(&conn)?;
1249
1250     // Return the jwt
1251     Ok(
1252       serde_json::to_string(
1253         &GetPostResponse {
1254           op: self.op_type().to_string(),
1255           post: post_view,
1256           comments: comments,
1257           community: community,
1258           moderators: moderators,
1259           admins: admins,
1260         }
1261         )?
1262       )
1263   }
1264 }
1265
1266 impl Perform for GetCommunity {
1267   fn op_type(&self) -> UserOperation {
1268     UserOperation::GetCommunity
1269   }
1270
1271   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
1272
1273     let conn = establish_connection();
1274
1275     let user_id: Option<i32> = match &self.auth {
1276       Some(auth) => {
1277         match Claims::decode(&auth) {
1278           Ok(claims) => {
1279             let user_id = claims.claims.id;
1280             Some(user_id)
1281           }
1282           Err(_e) => None
1283         }
1284       }
1285       None => None
1286     };
1287
1288     let community_id = match self.id {
1289       Some(id) => id,
1290       None => Community::read_from_name(&conn, self.name.to_owned().unwrap_or("main".to_string()))?.id
1291     };
1292
1293     let community_view = match CommunityView::read(&conn, community_id, user_id) {
1294       Ok(community) => community,
1295       Err(_e) => {
1296         return Err(self.error("Couldn't find Community"))?
1297       }
1298     };
1299
1300     let moderators = match CommunityModeratorView::for_community(&conn, community_id) {
1301       Ok(moderators) => moderators,
1302       Err(_e) => {
1303         return Err(self.error("Couldn't find Community"))?
1304       }
1305     };
1306
1307     let admins = UserView::admins(&conn)?;
1308
1309     // Return the jwt
1310     Ok(
1311       serde_json::to_string(
1312         &GetCommunityResponse {
1313           op: self.op_type().to_string(),
1314           community: community_view,
1315           moderators: moderators,
1316           admins: admins,
1317         }
1318         )?
1319       )
1320   }
1321 }
1322
1323 impl Perform for CreateComment {
1324   fn op_type(&self) -> UserOperation {
1325     UserOperation::CreateComment
1326   }
1327
1328   fn perform(&self, chat: &mut ChatServer, addr: usize) -> Result<String, Error> {
1329
1330     let conn = establish_connection();
1331
1332     chat.check_rate_limit(addr)?;
1333
1334     let claims = match Claims::decode(&self.auth) {
1335       Ok(claims) => claims.claims,
1336       Err(_e) => {
1337         return Err(self.error("Not logged in."))?
1338       }
1339     };
1340
1341     let user_id = claims.id;
1342
1343     // Check for a community ban
1344     let post = Post::read(&conn, self.post_id)?;
1345     if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
1346       return Err(self.error("You have been banned from this community"))?
1347     }
1348
1349     // Check for a site ban
1350     if UserView::read(&conn, user_id)?.banned {
1351       return Err(self.error("You have been banned from the site"))?
1352     }
1353
1354     let content_slurs_removed = remove_slurs(&self.content.to_owned());
1355
1356     let comment_form = CommentForm {
1357       content: content_slurs_removed,
1358       parent_id: self.parent_id.to_owned(),
1359       post_id: self.post_id,
1360       creator_id: user_id,
1361       removed: None,
1362       deleted: None,
1363       read: None,
1364       updated: None
1365     };
1366
1367     let inserted_comment = match Comment::create(&conn, &comment_form) {
1368       Ok(comment) => comment,
1369       Err(_e) => {
1370         return Err(self.error("Couldn't create Comment"))?
1371       }
1372     };
1373
1374     // You like your own comment by default
1375     let like_form = CommentLikeForm {
1376       comment_id: inserted_comment.id,
1377       post_id: self.post_id,
1378       user_id: user_id,
1379       score: 1
1380     };
1381
1382     let _inserted_like = match CommentLike::like(&conn, &like_form) {
1383       Ok(like) => like,
1384       Err(_e) => {
1385         return Err(self.error("Couldn't like comment."))?
1386       }
1387     };
1388
1389     let comment_view = CommentView::read(&conn, inserted_comment.id, Some(user_id))?;
1390
1391     let mut comment_sent = comment_view.clone();
1392     comment_sent.my_vote = None;
1393     comment_sent.user_id = None;
1394
1395     let comment_out = serde_json::to_string(
1396       &CommentResponse {
1397         op: self.op_type().to_string(), 
1398         comment: comment_view
1399       }
1400       )?;
1401
1402     let comment_sent_out = serde_json::to_string(
1403       &CommentResponse {
1404         op: self.op_type().to_string(), 
1405         comment: comment_sent
1406       }
1407       )?;
1408
1409     chat.send_room_message(self.post_id, &comment_sent_out, addr);
1410
1411     Ok(comment_out)
1412   }
1413 }
1414
1415 impl Perform for EditComment {
1416   fn op_type(&self) -> UserOperation {
1417     UserOperation::EditComment
1418   }
1419
1420   fn perform(&self, chat: &mut ChatServer, addr: usize) -> Result<String, Error> {
1421
1422     let conn = establish_connection();
1423
1424     let claims = match Claims::decode(&self.auth) {
1425       Ok(claims) => claims.claims,
1426       Err(_e) => {
1427         return Err(self.error("Not logged in."))?
1428       }
1429     };
1430
1431     let user_id = claims.id;
1432
1433     let orig_comment = CommentView::read(&conn, self.edit_id, None)?;
1434
1435     // You are allowed to mark the comment as read even if you're banned.
1436     if self.read.is_none() {
1437
1438       // Verify its the creator or a mod, or an admin
1439       let mut editors: Vec<i32> = vec![self.creator_id];
1440       editors.append(
1441         &mut CommunityModeratorView::for_community(&conn, orig_comment.community_id)
1442         ?
1443         .into_iter()
1444         .map(|m| m.user_id)
1445         .collect()
1446         );
1447       editors.append(
1448         &mut UserView::admins(&conn)
1449         ?
1450         .into_iter()
1451         .map(|a| a.id)
1452         .collect()
1453         );
1454
1455       if !editors.contains(&user_id) {
1456         return Err(self.error("Not allowed to edit comment."))?
1457       }
1458
1459       // Check for a community ban
1460       if CommunityUserBanView::get(&conn, user_id, orig_comment.community_id).is_ok() {
1461         return Err(self.error("You have been banned from this community"))?
1462       }
1463
1464       // Check for a site ban
1465       if UserView::read(&conn, user_id)?.banned {
1466         return Err(self.error("You have been banned from the site"))?
1467       }
1468
1469     }
1470
1471     let content_slurs_removed = remove_slurs(&self.content.to_owned());
1472
1473     let comment_form = CommentForm {
1474       content: content_slurs_removed,
1475       parent_id: self.parent_id,
1476       post_id: self.post_id,
1477       creator_id: self.creator_id,
1478       removed: self.removed.to_owned(),
1479       deleted: self.deleted.to_owned(),
1480       read: self.read.to_owned(),
1481       updated: if self.read.is_some() { orig_comment.updated } else {Some(naive_now())}
1482     };
1483
1484     let _updated_comment = match Comment::update(&conn, self.edit_id, &comment_form) {
1485       Ok(comment) => comment,
1486       Err(_e) => {
1487         return Err(self.error("Couldn't update Comment"))?
1488       }
1489     };
1490
1491     // Mod tables
1492     if let Some(removed) = self.removed.to_owned() {
1493       let form = ModRemoveCommentForm {
1494         mod_user_id: user_id,
1495         comment_id: self.edit_id,
1496         removed: Some(removed),
1497         reason: self.reason.to_owned(),
1498       };
1499       ModRemoveComment::create(&conn, &form)?;
1500     }
1501
1502
1503     let comment_view = CommentView::read(&conn, self.edit_id, Some(user_id))?;
1504
1505     let mut comment_sent = comment_view.clone();
1506     comment_sent.my_vote = None;
1507     comment_sent.user_id = None;
1508
1509     let comment_out = serde_json::to_string(
1510       &CommentResponse {
1511         op: self.op_type().to_string(), 
1512         comment: comment_view
1513       }
1514       )?;
1515
1516     let comment_sent_out = serde_json::to_string(
1517       &CommentResponse {
1518         op: self.op_type().to_string(), 
1519         comment: comment_sent
1520       }
1521       )?;
1522
1523     chat.send_room_message(self.post_id, &comment_sent_out, addr);
1524
1525     Ok(comment_out)
1526   }
1527 }
1528
1529 impl Perform for SaveComment {
1530   fn op_type(&self) -> UserOperation {
1531     UserOperation::SaveComment
1532   }
1533
1534   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
1535
1536     let conn = establish_connection();
1537
1538     let claims = match Claims::decode(&self.auth) {
1539       Ok(claims) => claims.claims,
1540       Err(_e) => {
1541         return Err(self.error("Not logged in."))?
1542       }
1543     };
1544
1545     let user_id = claims.id;
1546
1547     let comment_saved_form = CommentSavedForm {
1548       comment_id: self.comment_id,
1549       user_id: user_id,
1550     };
1551
1552     if self.save {
1553       match CommentSaved::save(&conn, &comment_saved_form) {
1554         Ok(comment) => comment,
1555         Err(_e) => {
1556           return Err(self.error("Couldnt do comment save"))?
1557         }
1558       };
1559     } else {
1560       match CommentSaved::unsave(&conn, &comment_saved_form) {
1561         Ok(comment) => comment,
1562         Err(_e) => {
1563           return Err(self.error("Couldnt do comment save"))?
1564         }
1565       };
1566     }
1567
1568     let comment_view = CommentView::read(&conn, self.comment_id, Some(user_id))?;
1569
1570     let comment_out = serde_json::to_string(
1571       &CommentResponse {
1572         op: self.op_type().to_string(), 
1573         comment: comment_view
1574       }
1575       )
1576       ?;
1577
1578     Ok(comment_out)
1579   }
1580 }
1581
1582
1583 impl Perform for CreateCommentLike {
1584   fn op_type(&self) -> UserOperation {
1585     UserOperation::CreateCommentLike
1586   }
1587
1588   fn perform(&self, chat: &mut ChatServer, addr: usize) -> Result<String, Error> {
1589
1590     let conn = establish_connection();
1591
1592     chat.check_rate_limit(addr)?;
1593
1594     let claims = match Claims::decode(&self.auth) {
1595       Ok(claims) => claims.claims,
1596       Err(_e) => {
1597         return Err(self.error("Not logged in."))?
1598       }
1599     };
1600
1601     let user_id = claims.id;
1602
1603     // Check for a community ban
1604     let post = Post::read(&conn, self.post_id)?;
1605     if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
1606       return Err(self.error("You have been banned from this community"))?
1607     }
1608
1609     // Check for a site ban
1610     if UserView::read(&conn, user_id)?.banned {
1611       return Err(self.error("You have been banned from the site"))?
1612     }
1613
1614     let like_form = CommentLikeForm {
1615       comment_id: self.comment_id,
1616       post_id: self.post_id,
1617       user_id: user_id,
1618       score: self.score
1619     };
1620
1621     // Remove any likes first
1622     CommentLike::remove(&conn, &like_form)?;
1623
1624     // Only add the like if the score isnt 0
1625     if &like_form.score != &0 {
1626       let _inserted_like = match CommentLike::like(&conn, &like_form) {
1627         Ok(like) => like,
1628         Err(_e) => {
1629           return Err(self.error("Couldn't like comment."))?
1630         }
1631       };
1632     }
1633
1634     // Have to refetch the comment to get the current state
1635     let liked_comment = CommentView::read(&conn, self.comment_id, Some(user_id))?;
1636
1637     let mut liked_comment_sent = liked_comment.clone();
1638     liked_comment_sent.my_vote = None;
1639     liked_comment_sent.user_id = None;
1640
1641     let like_out = serde_json::to_string(
1642       &CommentResponse {
1643         op: self.op_type().to_string(), 
1644         comment: liked_comment
1645       }
1646       )?;
1647
1648     let like_sent_out = serde_json::to_string(
1649       &CommentResponse {
1650         op: self.op_type().to_string(), 
1651         comment: liked_comment_sent
1652       }
1653       )?;
1654
1655     chat.send_room_message(self.post_id, &like_sent_out, addr);
1656
1657     Ok(like_out)
1658   }
1659 }
1660
1661
1662 impl Perform for GetPosts {
1663   fn op_type(&self) -> UserOperation {
1664     UserOperation::GetPosts
1665   }
1666
1667   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
1668
1669     let conn = establish_connection();
1670
1671     let user_id: Option<i32> = match &self.auth {
1672       Some(auth) => {
1673         match Claims::decode(&auth) {
1674           Ok(claims) => {
1675             let user_id = claims.claims.id;
1676             Some(user_id)
1677           }
1678           Err(_e) => None
1679         }
1680       }
1681       None => None
1682     };
1683
1684     let type_ = PostListingType::from_str(&self.type_)?;
1685     let sort = SortType::from_str(&self.sort)?;
1686
1687     let posts = match PostView::list(&conn, 
1688                                      type_, 
1689                                      &sort, 
1690                                      self.community_id, 
1691                                      None,
1692                                      None,
1693                                      user_id, 
1694                                      false, 
1695                                      false, 
1696                                      self.page, 
1697                                      self.limit) {
1698       Ok(posts) => posts,
1699       Err(_e) => {
1700         return Err(self.error("Couldn't get posts"))?
1701       }
1702     };
1703
1704     // Return the jwt
1705     Ok(
1706       serde_json::to_string(
1707         &GetPostsResponse {
1708           op: self.op_type().to_string(),
1709           posts: posts
1710         }
1711         )?
1712       )
1713   }
1714 }
1715
1716
1717 impl Perform for CreatePostLike {
1718   fn op_type(&self) -> UserOperation {
1719     UserOperation::CreatePostLike
1720   }
1721
1722   fn perform(&self, chat: &mut ChatServer, addr: usize) -> Result<String, Error> {
1723
1724     let conn = establish_connection();
1725
1726     chat.check_rate_limit(addr)?;
1727
1728     let claims = match Claims::decode(&self.auth) {
1729       Ok(claims) => claims.claims,
1730       Err(_e) => {
1731         return Err(self.error("Not logged in."))?
1732       }
1733     };
1734
1735     let user_id = claims.id;
1736
1737     // Check for a community ban
1738     let post = Post::read(&conn, self.post_id)?;
1739     if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
1740       return Err(self.error("You have been banned from this community"))?
1741     }
1742
1743     // Check for a site ban
1744     if UserView::read(&conn, user_id)?.banned {
1745       return Err(self.error("You have been banned from the site"))?
1746     }
1747
1748     let like_form = PostLikeForm {
1749       post_id: self.post_id,
1750       user_id: user_id,
1751       score: self.score
1752     };
1753
1754     // Remove any likes first
1755     PostLike::remove(&conn, &like_form)?;
1756
1757     // Only add the like if the score isnt 0
1758     if &like_form.score != &0 {
1759       let _inserted_like = match PostLike::like(&conn, &like_form) {
1760         Ok(like) => like,
1761         Err(_e) => {
1762           return Err(self.error("Couldn't like post."))?
1763         }
1764       };
1765     }
1766
1767     let post_view = match PostView::read(&conn, self.post_id, Some(user_id)) {
1768       Ok(post) => post,
1769       Err(_e) => {
1770         return Err(self.error("Couldn't find Post"))?
1771       }
1772     };
1773
1774     // just output the score
1775
1776     let like_out = serde_json::to_string(
1777       &CreatePostLikeResponse {
1778         op: self.op_type().to_string(), 
1779         post: post_view
1780       }
1781       )?;
1782
1783     Ok(like_out)
1784   }
1785 }
1786
1787 impl Perform for EditPost {
1788   fn op_type(&self) -> UserOperation {
1789     UserOperation::EditPost
1790   }
1791
1792   fn perform(&self, chat: &mut ChatServer, addr: usize) -> Result<String, Error> {
1793
1794     if has_slurs(&self.name) || 
1795       (self.body.is_some() && has_slurs(&self.body.to_owned().unwrap())) {
1796         return Err(self.error("No slurs"))?
1797       }
1798
1799     let conn = establish_connection();
1800
1801     let claims = match Claims::decode(&self.auth) {
1802       Ok(claims) => claims.claims,
1803       Err(_e) => {
1804         return Err(self.error("Not logged in."))?
1805       }
1806     };
1807
1808     let user_id = claims.id;
1809
1810     // Verify its the creator or a mod or admin
1811     let mut editors: Vec<i32> = vec![self.creator_id];
1812     editors.append(
1813       &mut CommunityModeratorView::for_community(&conn, self.community_id)
1814       ?
1815       .into_iter()
1816       .map(|m| m.user_id)
1817       .collect()
1818       );
1819     editors.append(
1820       &mut UserView::admins(&conn)
1821       ?
1822       .into_iter()
1823       .map(|a| a.id)
1824       .collect()
1825       );
1826     if !editors.contains(&user_id) {
1827       return Err(self.error("Not allowed to edit post."))?
1828     }
1829
1830     // Check for a community ban
1831     if CommunityUserBanView::get(&conn, user_id, self.community_id).is_ok() {
1832       return Err(self.error("You have been banned from this community"))?
1833     }
1834
1835     // Check for a site ban
1836     if UserView::read(&conn, user_id)?.banned {
1837       return Err(self.error("You have been banned from the site"))?
1838     }
1839
1840     let post_form = PostForm {
1841       name: self.name.to_owned(),
1842       url: self.url.to_owned(),
1843       body: self.body.to_owned(),
1844       creator_id: self.creator_id.to_owned(),
1845       community_id: self.community_id,
1846       removed: self.removed.to_owned(),
1847       deleted: self.deleted.to_owned(),
1848       locked: self.locked.to_owned(),
1849       updated: Some(naive_now())
1850     };
1851
1852     let _updated_post = match Post::update(&conn, self.edit_id, &post_form) {
1853       Ok(post) => post,
1854       Err(_e) => {
1855         return Err(self.error("Couldn't update Post"))?
1856       }
1857     };
1858
1859     // Mod tables
1860     if let Some(removed) = self.removed.to_owned() {
1861       let form = ModRemovePostForm {
1862         mod_user_id: user_id,
1863         post_id: self.edit_id,
1864         removed: Some(removed),
1865         reason: self.reason.to_owned(),
1866       };
1867       ModRemovePost::create(&conn, &form)?;
1868     }
1869
1870     if let Some(locked) = self.locked.to_owned() {
1871       let form = ModLockPostForm {
1872         mod_user_id: user_id,
1873         post_id: self.edit_id,
1874         locked: Some(locked),
1875       };
1876       ModLockPost::create(&conn, &form)?;
1877     }
1878
1879     let post_view = PostView::read(&conn, self.edit_id, Some(user_id))?;
1880
1881     let mut post_sent = post_view.clone();
1882     post_sent.my_vote = None;
1883
1884     let post_out = serde_json::to_string(
1885       &PostResponse {
1886         op: self.op_type().to_string(), 
1887         post: post_view
1888       }
1889       )
1890       ?;
1891
1892     let post_sent_out = serde_json::to_string(
1893       &PostResponse {
1894         op: self.op_type().to_string(), 
1895         post: post_sent
1896       }
1897       )
1898       ?;
1899
1900     chat.send_room_message(self.edit_id, &post_sent_out, addr);
1901
1902     Ok(post_out)
1903   }
1904 }
1905
1906 impl Perform for SavePost {
1907   fn op_type(&self) -> UserOperation {
1908     UserOperation::SavePost
1909   }
1910
1911   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
1912
1913     let conn = establish_connection();
1914
1915     let claims = match Claims::decode(&self.auth) {
1916       Ok(claims) => claims.claims,
1917       Err(_e) => {
1918         return Err(self.error("Not logged in."))?
1919       }
1920     };
1921
1922     let user_id = claims.id;
1923
1924     let post_saved_form = PostSavedForm {
1925       post_id: self.post_id,
1926       user_id: user_id,
1927     };
1928
1929     if self.save {
1930       match PostSaved::save(&conn, &post_saved_form) {
1931         Ok(post) => post,
1932         Err(_e) => {
1933           return Err(self.error("Couldnt do post save"))?
1934         }
1935       };
1936     } else {
1937       match PostSaved::unsave(&conn, &post_saved_form) {
1938         Ok(post) => post,
1939         Err(_e) => {
1940           return Err(self.error("Couldnt do post save"))?
1941         }
1942       };
1943     }
1944
1945     let post_view = PostView::read(&conn, self.post_id, Some(user_id))?;
1946
1947     let post_out = serde_json::to_string(
1948       &PostResponse {
1949         op: self.op_type().to_string(), 
1950         post: post_view
1951       }
1952       )
1953       ?;
1954
1955     Ok(post_out)
1956   }
1957 }
1958
1959 impl Perform for EditCommunity {
1960   fn op_type(&self) -> UserOperation {
1961     UserOperation::EditCommunity
1962   }
1963
1964   fn perform(&self, chat: &mut ChatServer, addr: usize) -> Result<String, Error> {
1965
1966     if has_slurs(&self.name) || has_slurs(&self.title) {
1967       return Err(self.error("No slurs"))?
1968     }
1969
1970     let conn = establish_connection();
1971
1972     let claims = match Claims::decode(&self.auth) {
1973       Ok(claims) => claims.claims,
1974       Err(_e) => {
1975         return Err(self.error("Not logged in."))?
1976       }
1977     };
1978
1979     let user_id = claims.id;
1980
1981     // Check for a site ban
1982     if UserView::read(&conn, user_id)?.banned {
1983       return Err(self.error("You have been banned from the site"))?
1984     }
1985
1986     // Verify its a mod
1987     let mut editors: Vec<i32> = Vec::new();
1988     editors.append(
1989       &mut CommunityModeratorView::for_community(&conn, self.edit_id)
1990       ?
1991       .into_iter()
1992       .map(|m| m.user_id)
1993       .collect()
1994       );
1995     editors.append(
1996       &mut UserView::admins(&conn)
1997       ?
1998       .into_iter()
1999       .map(|a| a.id)
2000       .collect()
2001       );
2002     if !editors.contains(&user_id) {
2003       return Err(self.error("Not allowed to edit community"))?
2004     }
2005
2006     let community_form = CommunityForm {
2007       name: self.name.to_owned(),
2008       title: self.title.to_owned(),
2009       description: self.description.to_owned(),
2010       category_id: self.category_id.to_owned(),
2011       creator_id: user_id,
2012       removed: self.removed.to_owned(),
2013       deleted: self.deleted.to_owned(),
2014       updated: Some(naive_now())
2015     };
2016
2017     let _updated_community = match Community::update(&conn, self.edit_id, &community_form) {
2018       Ok(community) => community,
2019       Err(_e) => {
2020         return Err(self.error("Couldn't update Community"))?
2021       }
2022     };
2023
2024     // Mod tables
2025     if let Some(removed) = self.removed.to_owned() {
2026       let expires = match self.expires {
2027         Some(time) => Some(naive_from_unix(time)),
2028         None => None
2029       };
2030       let form = ModRemoveCommunityForm {
2031         mod_user_id: user_id,
2032         community_id: self.edit_id,
2033         removed: Some(removed),
2034         reason: self.reason.to_owned(),
2035         expires: expires
2036       };
2037       ModRemoveCommunity::create(&conn, &form)?;
2038     }
2039
2040     let community_view = CommunityView::read(&conn, self.edit_id, Some(user_id))?;
2041
2042     let community_out = serde_json::to_string(
2043       &CommunityResponse {
2044         op: self.op_type().to_string(), 
2045         community: community_view
2046       }
2047       )
2048       ?;
2049
2050     let community_view_sent = CommunityView::read(&conn, self.edit_id, None)?;
2051
2052     let community_sent = serde_json::to_string(
2053       &CommunityResponse {
2054         op: self.op_type().to_string(), 
2055         community: community_view_sent
2056       }
2057       )
2058       ?;
2059
2060     chat.send_community_message(&conn, self.edit_id, &community_sent, addr)?;
2061
2062     Ok(community_out)
2063   }
2064 }
2065
2066
2067 impl Perform for FollowCommunity {
2068   fn op_type(&self) -> UserOperation {
2069     UserOperation::FollowCommunity
2070   }
2071
2072   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
2073
2074     let conn = establish_connection();
2075
2076     let claims = match Claims::decode(&self.auth) {
2077       Ok(claims) => claims.claims,
2078       Err(_e) => {
2079         return Err(self.error("Not logged in."))?
2080       }
2081     };
2082
2083     let user_id = claims.id;
2084
2085     let community_follower_form = CommunityFollowerForm {
2086       community_id: self.community_id,
2087       user_id: user_id
2088     };
2089
2090     if self.follow {
2091
2092       match CommunityFollower::follow(&conn, &community_follower_form) {
2093         Ok(user) => user,
2094         Err(_e) => {
2095           return Err(self.error("Community follower already exists."))?
2096         }
2097       };
2098     } else {
2099       match CommunityFollower::ignore(&conn, &community_follower_form) {
2100         Ok(user) => user,
2101         Err(_e) => {
2102           return Err(self.error("Community follower already exists."))?
2103         }
2104       };
2105     }
2106
2107     let community_view = CommunityView::read(&conn, self.community_id, Some(user_id))?;
2108
2109     Ok(
2110       serde_json::to_string(
2111         &CommunityResponse {
2112           op: self.op_type().to_string(), 
2113           community: community_view
2114         }
2115         )?
2116       )
2117   }
2118 }
2119
2120 impl Perform for GetFollowedCommunities {
2121   fn op_type(&self) -> UserOperation {
2122     UserOperation::GetFollowedCommunities
2123   }
2124
2125   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
2126
2127     let conn = establish_connection();
2128
2129     let claims = match Claims::decode(&self.auth) {
2130       Ok(claims) => claims.claims,
2131       Err(_e) => {
2132         return Err(self.error("Not logged in."))?
2133       }
2134     };
2135
2136     let user_id = claims.id;
2137
2138     let communities: Vec<CommunityFollowerView> = match CommunityFollowerView::for_user(&conn, user_id) {
2139       Ok(communities) => communities,
2140       Err(_e) => {
2141         return Err(self.error("System error, try logging out and back in."))?
2142       }
2143     };
2144
2145     // Return the jwt
2146     Ok(
2147       serde_json::to_string(
2148         &GetFollowedCommunitiesResponse {
2149           op: self.op_type().to_string(),
2150           communities: communities
2151         }
2152         )?
2153       )
2154   }
2155 }
2156
2157 impl Perform for GetUserDetails {
2158   fn op_type(&self) -> UserOperation {
2159     UserOperation::GetUserDetails
2160   }
2161
2162   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
2163
2164     let conn = establish_connection();
2165
2166     let user_id: Option<i32> = match &self.auth {
2167       Some(auth) => {
2168         match Claims::decode(&auth) {
2169           Ok(claims) => {
2170             let user_id = claims.claims.id;
2171             Some(user_id)
2172           }
2173           Err(_e) => None
2174         }
2175       }
2176       None => None
2177     };
2178
2179     //TODO add save
2180     let sort = SortType::from_str(&self.sort)?;
2181
2182     let user_details_id = match self.user_id {
2183       Some(id) => id,
2184       None => User_::read_from_name(&conn, self.username.to_owned().unwrap_or("admin".to_string()))?.id
2185     };
2186
2187     let user_view = UserView::read(&conn, user_details_id)?;
2188
2189     // If its saved only, you don't care what creator it was
2190     let posts = if self.saved_only {
2191       PostView::list(&conn, 
2192                      PostListingType::All, 
2193                      &sort, 
2194                      self.community_id, 
2195                      None, 
2196                      None,
2197                      Some(user_details_id), 
2198                      self.saved_only, 
2199                      false, 
2200                      self.page, 
2201                      self.limit)?
2202     } else {
2203       PostView::list(&conn, 
2204                      PostListingType::All, 
2205                      &sort, 
2206                      self.community_id, 
2207                      Some(user_details_id), 
2208                      None, 
2209                      user_id, 
2210                      self.saved_only, 
2211                      false, 
2212                      self.page, 
2213                      self.limit)?
2214     };
2215     let comments = if self.saved_only {
2216       CommentView::list(&conn, 
2217                         &sort, 
2218                         None, 
2219                         None, 
2220                         None, 
2221                         Some(user_details_id), 
2222                         self.saved_only, 
2223                         self.page, 
2224                         self.limit)?
2225     } else {
2226       CommentView::list(&conn, 
2227                         &sort, 
2228                         None, 
2229                         Some(user_details_id), 
2230                         None, 
2231                         user_id, 
2232                         self.saved_only, 
2233                         self.page, 
2234                         self.limit)?
2235     };
2236
2237     let follows = CommunityFollowerView::for_user(&conn, user_details_id)?;
2238     let moderates = CommunityModeratorView::for_user(&conn, user_details_id)?;
2239
2240     // Return the jwt
2241     Ok(
2242       serde_json::to_string(
2243         &GetUserDetailsResponse {
2244           op: self.op_type().to_string(),
2245           user: user_view,
2246           follows: follows,
2247           moderates: moderates, 
2248           comments: comments,
2249           posts: posts,
2250         }
2251         )?
2252       )
2253   }
2254 }
2255
2256 impl Perform for GetModlog {
2257   fn op_type(&self) -> UserOperation {
2258     UserOperation::GetModlog
2259   }
2260
2261   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
2262
2263     let conn = establish_connection();
2264
2265     let removed_posts = ModRemovePostView::list(&conn, self.community_id, self.mod_user_id, self.page, self.limit)?;
2266     let locked_posts = ModLockPostView::list(&conn, self.community_id, self.mod_user_id, self.page, self.limit)?;
2267     let removed_comments = ModRemoveCommentView::list(&conn, self.community_id, self.mod_user_id, self.page, self.limit)?;
2268     let banned_from_community = ModBanFromCommunityView::list(&conn, self.community_id, self.mod_user_id, self.page, self.limit)?;
2269     let added_to_community = ModAddCommunityView::list(&conn, self.community_id, self.mod_user_id, self.page, self.limit)?;
2270
2271     // These arrays are only for the full modlog, when a community isn't given
2272     let mut removed_communities = Vec::new();
2273     let mut banned = Vec::new();
2274     let mut added = Vec::new();
2275
2276     if self.community_id.is_none() {
2277       removed_communities = ModRemoveCommunityView::list(&conn, self.mod_user_id, self.page, self.limit)?;
2278       banned = ModBanView::list(&conn, self.mod_user_id, self.page, self.limit)?;
2279       added = ModAddView::list(&conn, self.mod_user_id, self.page, self.limit)?;
2280     }
2281
2282     // Return the jwt
2283     Ok(
2284       serde_json::to_string(
2285         &GetModlogResponse {
2286           op: self.op_type().to_string(),
2287           removed_posts: removed_posts,
2288           locked_posts: locked_posts,
2289           removed_comments: removed_comments,
2290           removed_communities: removed_communities,
2291           banned_from_community: banned_from_community,
2292           banned: banned,
2293           added_to_community: added_to_community,
2294           added: added,
2295         }
2296         )?
2297       )
2298   }
2299 }
2300
2301 impl Perform for GetReplies {
2302   fn op_type(&self) -> UserOperation {
2303     UserOperation::GetReplies
2304   }
2305
2306   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
2307
2308     let conn = establish_connection();
2309
2310     let claims = match Claims::decode(&self.auth) {
2311       Ok(claims) => claims.claims,
2312       Err(_e) => {
2313         return Err(self.error("Not logged in."))?
2314       }
2315     };
2316
2317     let user_id = claims.id;
2318
2319     let sort = SortType::from_str(&self.sort)?;
2320
2321     let replies = ReplyView::get_replies(&conn, user_id, &sort, self.unread_only, self.page, self.limit)?;
2322
2323     // Return the jwt
2324     Ok(
2325       serde_json::to_string(
2326         &GetRepliesResponse {
2327           op: self.op_type().to_string(),
2328           replies: replies,
2329         }
2330         )?
2331       )
2332   }
2333 }
2334
2335 impl Perform for BanFromCommunity {
2336   fn op_type(&self) -> UserOperation {
2337     UserOperation::BanFromCommunity
2338   }
2339
2340   fn perform(&self, chat: &mut ChatServer, addr: usize) -> Result<String, Error> {
2341
2342     let conn = establish_connection();
2343
2344     let claims = match Claims::decode(&self.auth) {
2345       Ok(claims) => claims.claims,
2346       Err(_e) => {
2347         return Err(self.error("Not logged in."))?
2348       }
2349     };
2350
2351     let user_id = claims.id;
2352
2353     let community_user_ban_form = CommunityUserBanForm {
2354       community_id: self.community_id,
2355       user_id: self.user_id,
2356     };
2357
2358     if self.ban {
2359       match CommunityUserBan::ban(&conn, &community_user_ban_form) {
2360         Ok(user) => user,
2361         Err(_e) => {
2362           return Err(self.error("Community user ban already exists"))?
2363         }
2364       };
2365     } else {
2366       match CommunityUserBan::unban(&conn, &community_user_ban_form) {
2367         Ok(user) => user,
2368         Err(_e) => {
2369           return Err(self.error("Community user ban already exists"))?
2370         }
2371       };
2372     }
2373
2374     // Mod tables
2375     let expires = match self.expires {
2376       Some(time) => Some(naive_from_unix(time)),
2377       None => None
2378     };
2379
2380     let form = ModBanFromCommunityForm {
2381       mod_user_id: user_id,
2382       other_user_id: self.user_id,
2383       community_id: self.community_id,
2384       reason: self.reason.to_owned(),
2385       banned: Some(self.ban),
2386       expires: expires,
2387     };
2388     ModBanFromCommunity::create(&conn, &form)?;
2389
2390     let user_view = UserView::read(&conn, self.user_id)?;
2391
2392     let res = serde_json::to_string(
2393       &BanFromCommunityResponse {
2394         op: self.op_type().to_string(), 
2395         user: user_view,
2396         banned: self.ban
2397       }
2398       )
2399       ?;
2400
2401
2402     chat.send_community_message(&conn, self.community_id, &res, addr)?;
2403
2404     Ok(res)
2405   }
2406 }
2407
2408 impl Perform for AddModToCommunity {
2409   fn op_type(&self) -> UserOperation {
2410     UserOperation::AddModToCommunity
2411   }
2412
2413   fn perform(&self, chat: &mut ChatServer, addr: usize) -> Result<String, Error> {
2414
2415     let conn = establish_connection();
2416
2417     let claims = match Claims::decode(&self.auth) {
2418       Ok(claims) => claims.claims,
2419       Err(_e) => {
2420         return Err(self.error("Not logged in."))?
2421       }
2422     };
2423
2424     let user_id = claims.id;
2425
2426     let community_moderator_form = CommunityModeratorForm {
2427       community_id: self.community_id,
2428       user_id: self.user_id
2429     };
2430
2431     if self.added {
2432       match CommunityModerator::join(&conn, &community_moderator_form) {
2433         Ok(user) => user,
2434         Err(_e) => {
2435           return Err(self.error("Community moderator already exists."))?
2436         }
2437       };
2438     } else {
2439       match CommunityModerator::leave(&conn, &community_moderator_form) {
2440         Ok(user) => user,
2441         Err(_e) => {
2442           return Err(self.error("Community moderator already exists."))?
2443         }
2444       };
2445     }
2446
2447     // Mod tables
2448     let form = ModAddCommunityForm {
2449       mod_user_id: user_id,
2450       other_user_id: self.user_id,
2451       community_id: self.community_id,
2452       removed: Some(!self.added),
2453     };
2454     ModAddCommunity::create(&conn, &form)?;
2455
2456     let moderators = CommunityModeratorView::for_community(&conn, self.community_id)?;
2457
2458     let res = serde_json::to_string(
2459       &AddModToCommunityResponse {
2460         op: self.op_type().to_string(), 
2461         moderators: moderators,
2462       }
2463       )
2464       ?;
2465
2466
2467     chat.send_community_message(&conn, self.community_id, &res, addr)?;
2468
2469     Ok(res)
2470
2471   }
2472 }
2473
2474 impl Perform for CreateSite {
2475   fn op_type(&self) -> UserOperation {
2476     UserOperation::CreateSite
2477   }
2478
2479   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
2480
2481     let conn = establish_connection();
2482
2483     let claims = match Claims::decode(&self.auth) {
2484       Ok(claims) => claims.claims,
2485       Err(_e) => {
2486         return Err(self.error("Not logged in."))?
2487       }
2488     };
2489
2490     if has_slurs(&self.name) || 
2491       (self.description.is_some() && has_slurs(&self.description.to_owned().unwrap())) {
2492         return Err(self.error("No slurs"))?
2493       }
2494
2495     let user_id = claims.id;
2496
2497     // Make sure user is an admin
2498     if !UserView::read(&conn, user_id)?.admin {
2499       return Err(self.error("Not an admin."))?
2500     }
2501
2502     let site_form = SiteForm {
2503       name: self.name.to_owned(),
2504       description: self.description.to_owned(),
2505       creator_id: user_id,
2506       updated: None,
2507     };
2508
2509     match Site::create(&conn, &site_form) {
2510       Ok(site) => site,
2511       Err(_e) => {
2512         return Err(self.error("Site exists already"))?
2513       }
2514     };
2515
2516     let site_view = SiteView::read(&conn)?;
2517
2518     Ok(
2519       serde_json::to_string(
2520         &SiteResponse {
2521           op: self.op_type().to_string(), 
2522           site: site_view,
2523         }
2524         )?
2525       )
2526   }
2527 }
2528
2529 impl Perform for EditSite {
2530   fn op_type(&self) -> UserOperation {
2531     UserOperation::EditSite
2532   }
2533
2534   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
2535
2536     let conn = establish_connection();
2537
2538     let claims = match Claims::decode(&self.auth) {
2539       Ok(claims) => claims.claims,
2540       Err(_e) => {
2541         return Err(self.error("Not logged in."))?
2542       }
2543     };
2544
2545     if has_slurs(&self.name) || 
2546       (self.description.is_some() && has_slurs(&self.description.to_owned().unwrap())) {
2547         return Err(self.error("No slurs"))?
2548       }
2549
2550     let user_id = claims.id;
2551
2552     // Make sure user is an admin
2553     if UserView::read(&conn, user_id)?.admin == false {
2554       return Err(self.error("Not an admin."))?
2555     }
2556
2557     let found_site = Site::read(&conn, 1)?;
2558
2559     let site_form = SiteForm {
2560       name: self.name.to_owned(),
2561       description: self.description.to_owned(),
2562       creator_id: found_site.creator_id,
2563       updated: Some(naive_now()),
2564     };
2565
2566     match Site::update(&conn, 1, &site_form) {
2567       Ok(site) => site,
2568       Err(_e) => {
2569         return Err(self.error("Couldn't update site."))?
2570       }
2571     };
2572
2573     let site_view = SiteView::read(&conn)?;
2574
2575     Ok(
2576       serde_json::to_string(
2577         &SiteResponse {
2578           op: self.op_type().to_string(), 
2579           site: site_view,
2580         }
2581         )?
2582       )
2583   }
2584 }
2585
2586 impl Perform for GetSite {
2587   fn op_type(&self) -> UserOperation {
2588     UserOperation::GetSite
2589   }
2590
2591   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
2592
2593     let conn = establish_connection();
2594
2595     // It can return a null site in order to redirect
2596     let site_view = match Site::read(&conn, 1) {
2597       Ok(_site) => Some(SiteView::read(&conn)?),
2598       Err(_e) => None
2599     };
2600
2601     let admins = UserView::admins(&conn)?;
2602     let banned = UserView::banned(&conn)?;
2603
2604     Ok(
2605       serde_json::to_string(
2606         &GetSiteResponse {
2607           op: self.op_type().to_string(), 
2608           site: site_view,
2609           admins: admins,
2610           banned: banned,
2611         }
2612         )?    
2613       )
2614   }
2615 }
2616
2617 impl Perform for AddAdmin {
2618   fn op_type(&self) -> UserOperation {
2619     UserOperation::AddAdmin
2620   }
2621
2622   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
2623
2624     let conn = establish_connection();
2625
2626     let claims = match Claims::decode(&self.auth) {
2627       Ok(claims) => claims.claims,
2628       Err(_e) => {
2629         return Err(self.error("Not logged in."))?
2630       }
2631     };
2632
2633     let user_id = claims.id;
2634
2635     // Make sure user is an admin
2636     if UserView::read(&conn, user_id)?.admin == false {
2637       return Err(self.error("Not an admin."))?
2638     }
2639
2640     let read_user = User_::read(&conn, self.user_id)?;
2641
2642     let user_form = UserForm {
2643       name: read_user.name,
2644       fedi_name: read_user.fedi_name,
2645       email: read_user.email,
2646       password_encrypted: read_user.password_encrypted,
2647       preferred_username: read_user.preferred_username,
2648       updated: Some(naive_now()),
2649       admin: self.added,
2650       banned: read_user.banned,
2651     };
2652
2653     match User_::update(&conn, self.user_id, &user_form) {
2654       Ok(user) => user,
2655       Err(_e) => {
2656         return Err(self.error("Couldn't update user"))?
2657       }
2658     };
2659
2660     // Mod tables
2661     let form = ModAddForm {
2662       mod_user_id: user_id,
2663       other_user_id: self.user_id,
2664       removed: Some(!self.added),
2665     };
2666
2667     ModAdd::create(&conn, &form)?;
2668
2669     let admins = UserView::admins(&conn)?;
2670
2671     let res = serde_json::to_string(
2672       &AddAdminResponse {
2673         op: self.op_type().to_string(), 
2674         admins: admins,
2675       }
2676       )
2677       ?;
2678
2679
2680     Ok(res)
2681
2682   }
2683 }
2684
2685 impl Perform for BanUser {
2686   fn op_type(&self) -> UserOperation {
2687     UserOperation::BanUser
2688   }
2689
2690   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
2691
2692     let conn = establish_connection();
2693
2694     let claims = match Claims::decode(&self.auth) {
2695       Ok(claims) => claims.claims,
2696       Err(_e) => {
2697         return Err(self.error("Not logged in."))?
2698       }
2699     };
2700
2701     let user_id = claims.id;
2702
2703     // Make sure user is an admin
2704     if UserView::read(&conn, user_id)?.admin == false {
2705       return Err(self.error("Not an admin."))?
2706     }
2707
2708     let read_user = User_::read(&conn, self.user_id)?;
2709
2710     let user_form = UserForm {
2711       name: read_user.name,
2712       fedi_name: read_user.fedi_name,
2713       email: read_user.email,
2714       password_encrypted: read_user.password_encrypted,
2715       preferred_username: read_user.preferred_username,
2716       updated: Some(naive_now()),
2717       admin: read_user.admin,
2718       banned: self.ban,
2719     };
2720
2721     match User_::update(&conn, self.user_id, &user_form) {
2722       Ok(user) => user,
2723       Err(_e) => {
2724         return Err(self.error("Couldn't update user"))?
2725       }
2726     };
2727
2728     // Mod tables
2729     let expires = match self.expires {
2730       Some(time) => Some(naive_from_unix(time)),
2731       None => None
2732     };
2733
2734     let form = ModBanForm {
2735       mod_user_id: user_id,
2736       other_user_id: self.user_id,
2737       reason: self.reason.to_owned(),
2738       banned: Some(self.ban),
2739       expires: expires,
2740     };
2741
2742     ModBan::create(&conn, &form)?;
2743
2744     let user_view = UserView::read(&conn, self.user_id)?;
2745
2746     let res = serde_json::to_string(
2747       &BanUserResponse {
2748         op: self.op_type().to_string(), 
2749         user: user_view,
2750         banned: self.ban
2751       }
2752       )
2753       ?;
2754
2755     Ok(res)
2756
2757   }
2758 }
2759
2760 impl Perform for Search {
2761   fn op_type(&self) -> UserOperation {
2762     UserOperation::Search
2763   }
2764
2765   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
2766
2767     let conn = establish_connection();
2768
2769     let sort = SortType::from_str(&self.sort)?;
2770     let type_ = SearchType::from_str(&self.type_)?;
2771
2772     let mut posts = Vec::new();
2773     let mut comments = Vec::new();
2774
2775     match type_ {
2776       SearchType::Posts => {
2777         posts = PostView::list(&conn, 
2778                                PostListingType::All, 
2779                                &sort, 
2780                                self.community_id, 
2781                                None,
2782                                Some(self.q.to_owned()),
2783                                None, 
2784                                false, 
2785                                false, 
2786                                self.page, 
2787                                self.limit)?;
2788       },
2789       SearchType::Comments => {
2790         comments = CommentView::list(&conn, 
2791                                      &sort, 
2792                                      None, 
2793                                      None, 
2794                                      Some(self.q.to_owned()),
2795                                      None,
2796                                      false, 
2797                                      self.page,
2798                                      self.limit)?;
2799       }, 
2800       SearchType::Both => {
2801         posts = PostView::list(&conn, 
2802                                PostListingType::All, 
2803                                &sort, 
2804                                self.community_id, 
2805                                None,
2806                                Some(self.q.to_owned()),
2807                                None, 
2808                                false, 
2809                                false, 
2810                                self.page, 
2811                                self.limit)?;
2812         comments = CommentView::list(&conn, 
2813                                      &sort, 
2814                                      None, 
2815                                      None, 
2816                                      Some(self.q.to_owned()),
2817                                      None,
2818                                      false, 
2819                                      self.page,
2820                                      self.limit)?;
2821       }
2822     };
2823
2824
2825     // Return the jwt
2826     Ok(
2827       serde_json::to_string(
2828         &SearchResponse {
2829           op: self.op_type().to_string(),
2830           comments: comments,
2831           posts: posts,
2832         }
2833         )?
2834       )
2835   }
2836 }
2837
2838
2839 impl Perform for MarkAllAsRead {
2840   fn op_type(&self) -> UserOperation {
2841     UserOperation::MarkAllAsRead
2842   }
2843
2844   fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> {
2845
2846     let conn = establish_connection();
2847
2848     let claims = match Claims::decode(&self.auth) {
2849       Ok(claims) => claims.claims,
2850       Err(_e) => {
2851         return Err(self.error("Not logged in."))?
2852       }
2853     };
2854
2855     let user_id = claims.id;
2856
2857     let replies = ReplyView::get_replies(&conn, user_id, &SortType::New, true, Some(1), Some(999))?;
2858
2859     for reply in &replies {
2860       let comment_form = CommentForm {
2861         content: reply.to_owned().content,
2862         parent_id: reply.to_owned().parent_id,
2863         post_id: reply.to_owned().post_id,
2864         creator_id: reply.to_owned().creator_id,
2865         removed: None,
2866         deleted: None,
2867         read: Some(true),
2868         updated: reply.to_owned().updated 
2869       };
2870
2871       let _updated_comment = match Comment::update(&conn, reply.id, &comment_form) {
2872         Ok(comment) => comment,
2873         Err(_e) => {
2874           return Err(self.error("Couldn't update Comment"))?
2875         }
2876       };
2877     }
2878
2879     let replies = ReplyView::get_replies(&conn, user_id, &SortType::New, true, Some(1), Some(999))?;
2880
2881     Ok(
2882       serde_json::to_string(
2883         &GetRepliesResponse {
2884           op: self.op_type().to_string(),
2885           replies: replies,
2886         }
2887         )?
2888       )
2889   }
2890 }