]> Untitled Git - lemmy.git/blob - server/src/api/site.rs
Adding emoji support
[lemmy.git] / server / src / api / site.rs
1 use super::*;
2 use std::str::FromStr;
3
4 #[derive(Serialize, Deserialize)]
5 pub struct ListCategories;
6
7 #[derive(Serialize, Deserialize)]
8 pub struct ListCategoriesResponse {
9   op: String,
10   categories: Vec<Category>
11 }
12
13 #[derive(Serialize, Deserialize)]
14 pub struct Search {
15   q: String,
16   type_: String,
17   community_id: Option<i32>,
18   sort: String,
19   page: Option<i64>,
20   limit: Option<i64>,
21 }
22
23 #[derive(Serialize, Deserialize)]
24 pub struct SearchResponse {
25   op: String,
26   comments: Vec<CommentView>,
27   posts: Vec<PostView>,
28 }
29
30 #[derive(Serialize, Deserialize)]
31 pub struct GetModlog {
32   mod_user_id: Option<i32>,
33   community_id: Option<i32>,
34   page: Option<i64>,
35   limit: Option<i64>,
36 }
37
38 #[derive(Serialize, Deserialize)]
39 pub struct GetModlogResponse {
40   op: String,
41   removed_posts: Vec<ModRemovePostView>,
42   locked_posts: Vec<ModLockPostView>,
43   removed_comments: Vec<ModRemoveCommentView>,
44   removed_communities: Vec<ModRemoveCommunityView>,
45   banned_from_community: Vec<ModBanFromCommunityView>,
46   banned: Vec<ModBanView>,
47   added_to_community: Vec<ModAddCommunityView>,
48   added: Vec<ModAddView>,
49 }
50
51
52 #[derive(Serialize, Deserialize)]
53 pub struct CreateSite {
54   name: String,
55   description: Option<String>,
56   auth: String
57 }
58
59 #[derive(Serialize, Deserialize)]
60 pub struct EditSite {
61   name: String,
62   description: Option<String>,
63   auth: String
64 }
65
66 #[derive(Serialize, Deserialize)]
67 pub struct GetSite {
68 }
69
70 #[derive(Serialize, Deserialize)]
71 pub struct SiteResponse {
72   op: String,
73   site: SiteView,
74 }
75
76 #[derive(Serialize, Deserialize)]
77 pub struct GetSiteResponse {
78   op: String,
79   site: Option<SiteView>,
80   admins: Vec<UserView>,
81   banned: Vec<UserView>,
82 }
83
84 impl Perform<ListCategoriesResponse> for Oper<ListCategories> {
85   fn perform(&self) -> Result<ListCategoriesResponse, Error> {
86     let _data: &ListCategories = &self.data;
87     let conn = establish_connection();
88
89     let categories: Vec<Category> = Category::list_all(&conn)?;
90
91     // Return the jwt
92     Ok(
93       ListCategoriesResponse {
94         op: self.op.to_string(),
95         categories: categories
96       }
97       )
98   }
99 }
100
101 impl Perform<GetModlogResponse> for Oper<GetModlog> {
102   fn perform(&self) -> Result<GetModlogResponse, Error> {
103     let data: &GetModlog = &self.data;
104     let conn = establish_connection();
105
106     let removed_posts = ModRemovePostView::list(&conn, data.community_id, data.mod_user_id, data.page, data.limit)?;
107     let locked_posts = ModLockPostView::list(&conn, data.community_id, data.mod_user_id, data.page, data.limit)?;
108     let removed_comments = ModRemoveCommentView::list(&conn, data.community_id, data.mod_user_id, data.page, data.limit)?;
109     let banned_from_community = ModBanFromCommunityView::list(&conn, data.community_id, data.mod_user_id, data.page, data.limit)?;
110     let added_to_community = ModAddCommunityView::list(&conn, data.community_id, data.mod_user_id, data.page, data.limit)?;
111
112     // These arrays are only for the full modlog, when a community isn't given
113     let mut removed_communities = Vec::new();
114     let mut banned = Vec::new();
115     let mut added = Vec::new();
116
117     if data.community_id.is_none() {
118       removed_communities = ModRemoveCommunityView::list(&conn, data.mod_user_id, data.page, data.limit)?;
119       banned = ModBanView::list(&conn, data.mod_user_id, data.page, data.limit)?;
120       added = ModAddView::list(&conn, data.mod_user_id, data.page, data.limit)?;
121     }
122
123     // Return the jwt
124     Ok(
125       GetModlogResponse {
126         op: self.op.to_string(),
127         removed_posts: removed_posts,
128         locked_posts: locked_posts,
129         removed_comments: removed_comments,
130         removed_communities: removed_communities,
131         banned_from_community: banned_from_community,
132         banned: banned,
133         added_to_community: added_to_community,
134         added: added,
135       }
136       )
137   }
138 }
139
140 impl Perform<SiteResponse> for Oper<CreateSite> {
141   fn perform(&self) -> Result<SiteResponse, Error> {
142     let data: &CreateSite = &self.data;
143     let conn = establish_connection();
144
145     let claims = match Claims::decode(&data.auth) {
146       Ok(claims) => claims.claims,
147       Err(_e) => {
148         return Err(APIError::err(&self.op, "Not logged in."))?
149       }
150     };
151
152     if has_slurs(&data.name) || 
153       (data.description.is_some() && has_slurs(&data.description.to_owned().unwrap())) {
154         return Err(APIError::err(&self.op, "No slurs"))?
155       }
156
157     let user_id = claims.id;
158
159     // Make sure user is an admin
160     if !UserView::read(&conn, user_id)?.admin {
161       return Err(APIError::err(&self.op, "Not an admin."))?
162     }
163
164     let site_form = SiteForm {
165       name: data.name.to_owned(),
166       description: data.description.to_owned(),
167       creator_id: user_id,
168       updated: None,
169     };
170
171     match Site::create(&conn, &site_form) {
172       Ok(site) => site,
173       Err(_e) => {
174         return Err(APIError::err(&self.op, "Site exists already"))?
175       }
176     };
177
178     let site_view = SiteView::read(&conn)?;
179
180     Ok(
181       SiteResponse {
182         op: self.op.to_string(), 
183         site: site_view,
184       }
185       )
186   }
187 }
188
189
190 impl Perform<SiteResponse> for Oper<EditSite> {
191   fn perform(&self) -> Result<SiteResponse, Error> {
192     let data: &EditSite = &self.data;
193     let conn = establish_connection();
194
195     let claims = match Claims::decode(&data.auth) {
196       Ok(claims) => claims.claims,
197       Err(_e) => {
198         return Err(APIError::err(&self.op, "Not logged in."))?
199       }
200     };
201
202     if has_slurs(&data.name) || 
203       (data.description.is_some() && has_slurs(&data.description.to_owned().unwrap())) {
204         return Err(APIError::err(&self.op, "No slurs"))?
205       }
206
207     let user_id = claims.id;
208
209     // Make sure user is an admin
210     if UserView::read(&conn, user_id)?.admin == false {
211       return Err(APIError::err(&self.op, "Not an admin."))?
212     }
213
214     let found_site = Site::read(&conn, 1)?;
215
216     let site_form = SiteForm {
217       name: data.name.to_owned(),
218       description: data.description.to_owned(),
219       creator_id: found_site.creator_id,
220       updated: Some(naive_now()),
221     };
222
223     match Site::update(&conn, 1, &site_form) {
224       Ok(site) => site,
225       Err(_e) => {
226         return Err(APIError::err(&self.op, "Couldn't update site."))?
227       }
228     };
229
230     let site_view = SiteView::read(&conn)?;
231
232     Ok(
233       SiteResponse {
234         op: self.op.to_string(), 
235         site: site_view,
236       }
237       )
238   }
239 }
240
241 impl Perform<GetSiteResponse> for Oper<GetSite> {
242   fn perform(&self) -> Result<GetSiteResponse, Error> {
243     let _data: &GetSite = &self.data;
244     let conn = establish_connection();
245
246     // It can return a null site in order to redirect
247     let site_view = match Site::read(&conn, 1) {
248       Ok(_site) => Some(SiteView::read(&conn)?),
249       Err(_e) => None
250     };
251
252     let admins = UserView::admins(&conn)?;
253     let banned = UserView::banned(&conn)?;
254
255     Ok(
256       GetSiteResponse {
257         op: self.op.to_string(), 
258         site: site_view,
259         admins: admins,
260         banned: banned,
261       }
262       )
263   }
264 }
265
266 impl Perform<SearchResponse> for Oper<Search> {
267   fn perform(&self) -> Result<SearchResponse, Error> {
268     let data: &Search = &self.data;
269     let conn = establish_connection();
270
271     let sort = SortType::from_str(&data.sort)?;
272     let type_ = SearchType::from_str(&data.type_)?;
273
274     let mut posts = Vec::new();
275     let mut comments = Vec::new();
276
277     match type_ {
278       SearchType::Posts => {
279         posts = PostView::list(&conn, 
280                                PostListingType::All, 
281                                &sort, 
282                                data.community_id, 
283                                None,
284                                Some(data.q.to_owned()),
285                                None, 
286                                false, 
287                                false, 
288                                data.page, 
289                                data.limit)?;
290       },
291       SearchType::Comments => {
292         comments = CommentView::list(&conn, 
293                                      &sort, 
294                                      None, 
295                                      None, 
296                                      Some(data.q.to_owned()),
297                                      None,
298                                      false, 
299                                      data.page,
300                                      data.limit)?;
301       }, 
302       SearchType::Both => {
303         posts = PostView::list(&conn, 
304                                PostListingType::All, 
305                                &sort, 
306                                data.community_id, 
307                                None,
308                                Some(data.q.to_owned()),
309                                None, 
310                                false, 
311                                false, 
312                                data.page, 
313                                data.limit)?;
314         comments = CommentView::list(&conn, 
315                                      &sort, 
316                                      None, 
317                                      None, 
318                                      Some(data.q.to_owned()),
319                                      None,
320                                      false, 
321                                      data.page,
322                                      data.limit)?;
323       }
324     };
325
326
327     // Return the jwt
328     Ok(
329       SearchResponse {
330         op: self.op.to_string(),
331         comments: comments,
332         posts: posts,
333       }
334       )
335   }
336 }