1pub mod common;
2pub mod error;
3
4use crate::common::*;
5use futures_util::SinkExt;
6use netsblox_api_common::{
7 CreateGroupData, CreateMagicLinkData, ServiceHostScope, UpdateGroupData, UpdateUserData,
8};
9use reqwest::{self, Method, RequestBuilder, Response};
10use serde::{Deserialize, Serialize};
11pub use serde_json;
12use serde_json::{json, Value};
13use tokio::net::TcpStream;
14use tokio_tungstenite::tungstenite::Message;
15use tokio_tungstenite::{connect_async, MaybeTlsStream, WebSocketStream};
16
17#[derive(Serialize, Deserialize, Debug, Clone)]
18pub struct Config {
19 pub app_id: Option<AppId>,
20 pub url: String,
21 pub token: Option<String>,
22 pub username: Option<String>,
23}
24
25impl Default for Config {
26 fn default() -> Self {
27 Self {
28 app_id: None,
29 username: None,
30 token: None,
31 url: "https://cloud.netsblox.org".to_owned(),
32 }
33 }
34}
35
36async fn check_response(response: Response) -> Result<Response, error::Error> {
37 let status_code = response.status().as_u16();
38 let is_error = status_code > 399;
39 if is_error {
40 let msg = response.text().await.map_err(error::Error::RequestError)?;
41
42 match status_code {
43 400 => Err(error::Error::BadRequestError(msg)),
44 401 => Err(error::Error::LoginRequiredError),
45 403 => Err(error::Error::PermissionsError(msg)),
46 404 => Err(error::Error::NotFoundError(msg)),
47 500 => Err(error::Error::InternalServerError),
48 _ => panic!("Unknown status code: {:?}", status_code), }
50 } else {
51 Ok(response)
52 }
53}
54
55pub type Token = String;
56pub async fn login(mut cfg: Config, credentials: &LoginRequest) -> Result<Config, error::Error> {
57 let client = reqwest::Client::new();
58 let response = client
59 .post(format!("{}/users/login", cfg.url))
60 .json(&credentials)
61 .send()
62 .await
63 .map_err(error::Error::RequestError)?;
64
65 let response = check_response(response).await?;
66 let cookie = response
67 .cookies()
68 .find(|cookie| cookie.name() == "netsblox")
69 .ok_or("No cookie received.")
70 .unwrap();
71
72 let token = cookie.value().to_owned();
73
74 let user = response.json::<User>().await.unwrap();
75 cfg.username = Some(user.username);
76 cfg.token = Some(token);
77 Ok(cfg)
78}
79
80#[derive(Serialize)]
81struct UserData<'a> {
82 username: &'a str,
83 email: &'a str,
84 role: &'a UserRole,
85 group_id: Option<&'a GroupId>,
86 password: Option<&'a str>,
87}
88
89#[derive(Clone)]
90pub struct Client {
91 cfg: Config,
92}
93
94impl Client {
95 pub fn new(cfg: Config) -> Self {
96 Client { cfg }
97 }
98
99 fn request(&self, method: Method, path: &str) -> RequestBuilder {
100 let client = reqwest::Client::new();
101 let empty = "".to_owned();
102 let token = self.cfg.token.as_ref().unwrap_or(&empty);
103 client
104 .request(method, format!("{}{}", self.cfg.url, path))
105 .header("Cookie", format!("netsblox={}", token))
106 }
107
108 pub async fn create_user(
110 &self,
111 name: &str,
112 email: &str,
113 password: Option<&str>, group_id: Option<&GroupId>,
115 role: UserRole,
116 ) -> Result<(), error::Error> {
117 let user_data = NewUser {
118 username: name.to_owned(),
119 email: email.to_owned(),
120 role: Some(role),
121 group_id: group_id.map(|id| id.to_owned()),
122 password: password.map(|pwd| pwd.to_owned()),
123 };
124
125 let response = self
126 .request(Method::POST, "/users/create")
127 .json(&user_data)
128 .send()
129 .await
130 .map_err(error::Error::RequestError)?;
131
132 println!(
133 "status {} {}",
134 response.status(),
135 response.text().await.unwrap()
136 );
137 Ok(())
138 }
139
140 pub async fn list_users(&self) -> Result<Vec<User>, error::Error> {
141 let response = self
142 .request(Method::GET, "/users/")
143 .send()
144 .await
145 .map_err(error::Error::RequestError)?;
146
147 let response = check_response(response).await?;
148 Ok(response.json::<Vec<User>>().await.unwrap())
149 }
150
151 pub async fn forgot_username(&self, email: &str) -> Result<(), error::Error> {
154 let response = self
155 .request(Method::POST, "/users/forgot-username")
156 .json(&email)
157 .send()
158 .await
159 .map_err(error::Error::RequestError)?;
160
161 check_response(response).await?;
162 Ok(())
163 }
164
165 pub async fn delete_user(&self, username: &str) -> Result<(), error::Error> {
166 let response = self
167 .request(Method::POST, &format!("/users/{}/delete", username))
168 .send()
169 .await
170 .map_err(error::Error::RequestError)?;
171
172 check_response(response).await?;
173 Ok(())
174 }
175
176 pub async fn view_user(&self, username: &str) -> Result<User, error::Error> {
177 let response = self
178 .request(Method::GET, &format!("/users/{}", username))
179 .send()
180 .await
181 .map_err(error::Error::RequestError)?;
182
183 let response = check_response(response).await?;
184 Ok(response.json::<User>().await.unwrap())
185 }
186
187 pub async fn update_user(
188 &self,
189 username: &str,
190 update: &UpdateUserData,
191 ) -> Result<User, error::Error> {
192 let path = format!("/users/{}", username);
193 let response = self
194 .request(Method::PATCH, &path)
195 .json(&update)
196 .send()
197 .await
198 .map_err(error::Error::RequestError)?;
199
200 let response = check_response(response).await?;
201 Ok(response.json::<User>().await.unwrap())
202 }
203
204 pub async fn set_password(&self, username: &str, password: &str) -> Result<(), error::Error> {
205 let path = format!("/users/{}/password", username);
206 let response = self
207 .request(Method::PATCH, &path)
208 .json(&password)
209 .send()
210 .await
211 .map_err(error::Error::RequestError)?;
212
213 check_response(response).await?;
214 Ok(())
215 }
216
217 pub async fn link_account(
218 &self,
219 username: &str,
220 credentials: &Credentials,
221 ) -> Result<(), error::Error> {
222 let response = self
223 .request(Method::POST, &format!("/users/{}/link/", username))
224 .json(&credentials)
225 .send()
226 .await
227 .map_err(error::Error::RequestError)?;
228
229 check_response(response).await?;
230 Ok(())
231 }
232
233 pub async fn unlink_account(
234 &self,
235 username: &str,
236 account: &LinkedAccount,
237 ) -> Result<(), error::Error> {
238 let response = self
239 .request(Method::POST, &format!("/users/{}/unlink", username))
240 .json(&account)
241 .send()
242 .await
243 .map_err(error::Error::RequestError)?;
244
245 check_response(response).await?;
246 Ok(())
247 }
248
249 pub async fn ban_user(&self, username: &str) -> Result<BannedAccount, error::Error> {
250 let response = self
251 .request(Method::POST, &format!("/users/{}/ban", username))
252 .send()
253 .await
254 .map_err(error::Error::RequestError)?;
255
256 let response = check_response(response).await?;
257 Ok(response.json::<BannedAccount>().await.unwrap())
258 }
259
260 pub async fn unban_user(&self, username: &str) -> Result<BannedAccount, error::Error> {
261 let response = self
262 .request(Method::POST, &format!("/users/{}/unban", username))
263 .send()
264 .await
265 .map_err(error::Error::RequestError)?;
266
267 let response = check_response(response).await?;
268 Ok(response.json::<BannedAccount>().await.unwrap())
269 }
270
271 pub async fn send_magic_link(&self, data: &CreateMagicLinkData) -> Result<(), error::Error> {
274 let response = self
275 .request(Method::POST, "/magic-links/")
276 .json(data)
277 .send()
278 .await
279 .map_err(error::Error::RequestError)?;
280
281 check_response(response).await?;
282 Ok(())
283 }
284
285 pub async fn create_project(
287 &self,
288 data: &CreateProjectData,
289 ) -> Result<ProjectMetadata, error::Error> {
290 let response = self
292 .request(Method::POST, "/projects/")
293 .json(data)
294 .send()
295 .await
296 .map_err(error::Error::RequestError)?;
297
298 let response = check_response(response).await?;
299 Ok(response.json::<ProjectMetadata>().await.unwrap())
300 }
301
302 pub async fn list_projects(&self, owner: &str) -> Result<Vec<ProjectMetadata>, error::Error> {
303 let response = self
304 .request(Method::GET, &format!("/projects/user/{}", &owner))
305 .send()
306 .await
307 .map_err(error::Error::RequestError)?;
308
309 let response = check_response(response).await?;
310
311 Ok(response.json::<Vec<ProjectMetadata>>().await.unwrap())
312 }
313
314 pub async fn list_shared_projects(
315 &self,
316 owner: &str,
317 ) -> Result<Vec<ProjectMetadata>, error::Error> {
318 let response = self
319 .request(Method::GET, &format!("/projects/shared/{}", &owner))
320 .send()
321 .await
322 .map_err(error::Error::RequestError)?;
323
324 let response = check_response(response).await?;
325
326 Ok(response.json::<Vec<ProjectMetadata>>().await.unwrap())
327 }
328
329 pub async fn get_project_metadata(
330 &self,
331 owner: &str,
332 name: &str,
333 ) -> Result<ProjectMetadata, error::Error> {
334 let response = self
335 .request(
336 Method::GET,
337 &format!("/projects/user/{}/{}/metadata", &owner, name),
338 )
339 .send()
340 .await
341 .map_err(error::Error::RequestError)?;
342
343 let response = check_response(response).await?;
344
345 Ok(response.json::<ProjectMetadata>().await.unwrap())
346 }
347
348 pub async fn rename_project(&self, id: &ProjectId, name: &str) -> Result<(), error::Error> {
349 let response = self
350 .request(Method::PATCH, &format!("/projects/id/{}", &id))
351 .json(&UpdateProjectData {
352 name: name.to_owned(),
353 client_id: None,
354 })
355 .send()
356 .await
357 .map_err(error::Error::RequestError)?;
358
359 check_response(response).await?;
360
361 Ok(())
362 }
363
364 pub async fn rename_role(
365 &self,
366 id: &ProjectId,
367 role_id: &RoleId,
368 name: &str,
369 ) -> Result<(), error::Error> {
370 let response = self
371 .request(Method::PATCH, &format!("/projects/id/{}/{}", &id, &role_id))
372 .json(&UpdateRoleData {
373 name: name.to_owned(),
374 client_id: None,
375 })
376 .send()
377 .await
378 .map_err(error::Error::RequestError)?;
379
380 check_response(response).await?;
381
382 Ok(())
383 }
384
385 pub async fn delete_project(&self, id: &ProjectId) -> Result<(), error::Error> {
386 let response = self
387 .request(Method::DELETE, &format!("/projects/id/{}", id))
388 .send()
389 .await
390 .map_err(error::Error::RequestError)?;
391
392 check_response(response).await?;
393
394 Ok(())
395 }
396
397 pub async fn delete_role(&self, id: &ProjectId, role_id: &RoleId) -> Result<(), error::Error> {
398 let response = self
399 .request(Method::DELETE, &format!("/projects/id/{}/{}", id, role_id))
400 .send()
401 .await
402 .map_err(error::Error::RequestError)?;
403
404 check_response(response).await?;
405
406 Ok(())
407 }
408
409 pub async fn publish_project(&self, id: &ProjectId) -> Result<PublishState, error::Error> {
410 let response = self
411 .request(Method::POST, &format!("/projects/id/{}/publish", id))
412 .send()
413 .await
414 .map_err(error::Error::RequestError)?;
415
416 let response = check_response(response).await?;
417
418 Ok(response.json::<PublishState>().await.unwrap())
419 }
420
421 pub async fn unpublish_project(&self, id: &ProjectId) -> Result<(), error::Error> {
422 let response = self
423 .request(Method::POST, &format!("/projects/id/{}/unpublish", id))
424 .send()
425 .await
426 .map_err(error::Error::RequestError)?;
427
428 check_response(response).await?;
429
430 Ok(())
431 }
432
433 pub async fn get_project(
434 &self,
435 id: &ProjectId,
436 latest: &bool,
437 ) -> Result<Project, error::Error> {
438 let path = if *latest {
439 format!("/projects/id/{}/latest", id)
440 } else {
441 format!("/projects/id/{}", id)
442 };
443 let response = self
444 .request(Method::GET, &path)
445 .send()
446 .await
447 .map_err(error::Error::RequestError)?;
448
449 let response = check_response(response).await?;
450
451 Ok(response.json::<Project>().await.unwrap())
452 }
453
454 pub async fn get_role(
455 &self,
456 id: &ProjectId,
457 role_id: &RoleId,
458 latest: &bool,
459 ) -> Result<RoleData, error::Error> {
460 let path = if *latest {
461 format!("/projects/id/{}/{}/latest", id, role_id)
462 } else {
463 format!("/projects/id/{}/{}", id, role_id)
464 };
465 let response = self
466 .request(Method::GET, &path)
467 .send()
468 .await
469 .map_err(error::Error::RequestError)?;
470
471 let response = check_response(response).await?;
472
473 Ok(response.json::<RoleData>().await.unwrap())
474 }
475
476 pub async fn list_collaborators(&self, project_id: &str) -> Result<Vec<String>, error::Error> {
478 let response = self
479 .request(Method::GET, &format!("/id/{}/collaborators/", project_id))
480 .send()
481 .await
482 .map_err(error::Error::RequestError)?;
483
484 let response = check_response(response).await?;
485
486 Ok(response.json::<Vec<String>>().await.unwrap())
487 }
488
489 pub async fn remove_collaborator(
490 &self,
491 project_id: &ProjectId,
492 username: &str,
493 ) -> Result<(), error::Error> {
494 let response = self
495 .request(
496 Method::DELETE,
497 &format!("/projects/id/{}/collaborators/{}", project_id, username),
498 )
499 .send()
500 .await
501 .map_err(error::Error::RequestError)?;
502
503 check_response(response).await?;
504
505 Ok(())
506 }
507
508 pub async fn list_collaboration_invites(
509 &self,
510 username: &str,
511 ) -> Result<Vec<CollaborationInvite>, error::Error> {
512 let response = self
513 .request(
514 Method::GET,
515 &format!("/collaboration-invites/user/{}/", username),
516 )
517 .send()
518 .await
519 .map_err(error::Error::RequestError)?;
520
521 let response = check_response(response).await?;
522
523 Ok(response.json::<Vec<CollaborationInvite>>().await.unwrap())
524 }
525
526 pub async fn invite_collaborator(
527 &self,
528 id: &ProjectId,
529 username: &str,
530 ) -> Result<(), error::Error> {
531 let response = self
532 .request(
533 Method::POST,
534 &format!("/collaboration-invites/{}/invite/{}", id, username),
535 )
536 .send()
537 .await
538 .map_err(error::Error::RequestError)?;
539
540 check_response(response).await?;
541 Ok(())
542 }
543
544 pub async fn respond_to_collaboration_invite(
545 &self,
546 id: &InvitationId,
547 state: &InvitationState,
548 ) -> Result<(), error::Error> {
549 let response = self
550 .request(Method::POST, &format!("/collaboration-invites/id/{}", id))
551 .json(state)
552 .send()
553 .await
554 .map_err(error::Error::RequestError)?;
555
556 check_response(response).await?;
557 Ok(())
558 }
559
560 pub async fn list_friends(&self, username: &str) -> Result<Vec<String>, error::Error> {
562 let path = &format!("/friends/{}/", username);
563 let response = self
564 .request(Method::GET, path)
565 .send()
566 .await
567 .map_err(error::Error::RequestError)?;
568
569 let response = check_response(response).await?;
570 Ok(response.json::<Vec<String>>().await.unwrap())
571 }
572
573 pub async fn list_online_friends(&self, username: &str) -> Result<Vec<String>, error::Error> {
574 let path = &format!("/friends/{}/online", username);
575 let response = self
576 .request(Method::GET, path)
577 .send()
578 .await
579 .map_err(error::Error::RequestError)?;
580
581 let response = check_response(response).await?;
582 Ok(response.json::<Vec<String>>().await.unwrap())
583 }
584
585 pub async fn list_friend_invites(
586 &self,
587 username: &str,
588 ) -> Result<Vec<FriendInvite>, error::Error> {
589 let path = &format!("/friends/{}/invites/", username);
590 let response = self
591 .request(Method::GET, path)
592 .send()
593 .await
594 .map_err(error::Error::RequestError)?;
595
596 let response = check_response(response).await?;
597 Ok(response.json::<Vec<FriendInvite>>().await.unwrap())
598 }
599
600 pub async fn send_friend_invite(
601 &self,
602 username: &str,
603 recipient: &str,
604 ) -> Result<(), error::Error> {
605 let path = &format!("/friends/{}/invite/", username);
606 let response = self
607 .request(Method::POST, path)
608 .json(recipient)
609 .send()
610 .await
611 .map_err(error::Error::RequestError)?;
612
613 check_response(response).await?;
614 Ok(())
615 }
616
617 pub async fn respond_to_friend_invite(
618 &self,
619 recipient: &str,
620 sender: &str,
621 state: FriendLinkState,
622 ) -> Result<(), error::Error> {
623 let path = format!("/friends/{}/invites/{}", recipient, sender);
624 let response = self
625 .request(Method::POST, &path)
626 .json(&state)
627 .send()
628 .await
629 .map_err(error::Error::RequestError)?;
630
631 check_response(response).await?;
632 Ok(())
633 }
634
635 pub async fn unfriend(&self, username: &str, friend: &str) -> Result<(), error::Error> {
636 let path = format!("/friends/{}/unfriend/{}", username, friend);
637 let response = self
638 .request(Method::POST, &path)
639 .send()
640 .await
641 .map_err(error::Error::RequestError)?;
642
643 check_response(response).await?;
644 Ok(())
645 }
646
647 pub async fn block_user(&self, username: &str, other_user: &str) -> Result<(), error::Error> {
648 let path = format!("/friends/{}/block/{}", username, other_user);
649 let response = self
650 .request(Method::POST, &path)
651 .send()
652 .await
653 .map_err(error::Error::RequestError)?;
654
655 check_response(response).await?;
656 Ok(())
657 }
658
659 pub async fn unblock_user(&self, username: &str, other_user: &str) -> Result<(), error::Error> {
660 let path = format!("/friends/{}/unblock/{}", username, other_user);
661 let response = self
662 .request(Method::POST, &path)
663 .send()
664 .await
665 .map_err(error::Error::RequestError)?;
666
667 check_response(response).await?;
668 Ok(())
669 }
670
671 pub async fn get_libraries(
673 &self,
674 username: &str,
675 ) -> Result<Vec<LibraryMetadata>, error::Error> {
676 let path = format!("/libraries/user/{}/", username);
677 let response = self
678 .request(Method::GET, &path)
679 .send()
680 .await
681 .map_err(error::Error::RequestError)?;
682
683 let response = check_response(response).await?;
684 Ok(response.json::<Vec<LibraryMetadata>>().await.unwrap())
685 }
686
687 pub async fn get_submitted_libraries(&self) -> Result<Vec<LibraryMetadata>, error::Error> {
688 let response = self
689 .request(Method::GET, "/libraries/mod/pending")
690 .send()
691 .await
692 .map_err(error::Error::RequestError)?;
693
694 let response = check_response(response).await?;
695
696 Ok(response.json::<Vec<LibraryMetadata>>().await.unwrap())
697 }
698
699 pub async fn get_public_libraries(&self) -> Result<Vec<LibraryMetadata>, error::Error> {
700 let response = self
701 .request(Method::GET, "/libraries/community/")
702 .send()
703 .await
704 .map_err(error::Error::RequestError)?;
705
706 let response = check_response(response).await?;
707
708 Ok(response.json::<Vec<LibraryMetadata>>().await.unwrap())
709 }
710
711 pub async fn get_library(&self, username: &str, name: &str) -> Result<String, error::Error> {
712 let path = format!("/libraries/user/{}/{}", username, name); let response = self
714 .request(Method::GET, &path)
715 .send()
716 .await
717 .map_err(error::Error::RequestError)?;
718
719 let response = check_response(response).await?;
720
721 Ok(response.text().await.unwrap())
722 }
723
724 pub async fn save_library(
725 &self,
726 username: &str,
727 name: &str,
728 blocks: &str,
729 notes: &str,
730 ) -> Result<(), error::Error> {
731 let path = format!("/libraries/user/{}/", username);
732 let response = self
733 .request(Method::POST, &path)
734 .json(&CreateLibraryData {
735 name: name.to_owned(),
736 blocks: blocks.to_owned(),
737 notes: notes.to_owned(),
738 })
739 .send()
740 .await
741 .map_err(error::Error::RequestError)?;
742
743 check_response(response).await?;
744 Ok(())
745 }
746
747 pub async fn delete_library(&self, username: &str, library: &str) -> Result<(), error::Error> {
748 let path = format!("/libraries/user/{}/{}", username, library);
749 let response = self
750 .request(Method::DELETE, &path)
751 .send()
752 .await
753 .map_err(error::Error::RequestError)?;
754
755 check_response(response).await?;
756 Ok(())
757 }
758
759 pub async fn publish_library(&self, username: &str, library: &str) -> Result<(), error::Error> {
760 let path = format!("/libraries/user/{}/{}/publish", username, library);
761 let response = self
762 .request(Method::POST, &path)
763 .send()
764 .await
765 .map_err(error::Error::RequestError)?;
766
767 check_response(response).await?;
768 Ok(())
769 }
770
771 pub async fn unpublish_library(
772 &self,
773 username: &str,
774 library: &str,
775 ) -> Result<(), error::Error> {
776 let path = format!("/libraries/user/{}/{}/unpublish", username, library);
777 let response = self
778 .request(Method::POST, &path)
779 .send()
780 .await
781 .map_err(error::Error::RequestError)?;
782
783 check_response(response).await?;
784 Ok(())
785 }
786
787 pub async fn approve_library(
788 &self,
789 username: &str,
790 library: &str,
791 state: &PublishState,
792 ) -> Result<(), error::Error> {
793 let path = format!("/libraries/mod/{}/{}", username, library);
794 let response = self
795 .request(Method::POST, &path)
796 .json(&state)
797 .send()
798 .await
799 .map_err(error::Error::RequestError)?;
800
801 check_response(response).await?;
802 Ok(())
803 }
804
805 pub async fn list_groups(&self, username: &str) -> Result<Vec<Group>, error::Error> {
807 let path = format!("/groups/user/{}/", username);
808 let response = self
809 .request(Method::GET, &path)
810 .send()
811 .await
812 .map_err(error::Error::RequestError)?;
813
814 let response = check_response(response).await?;
815
816 Ok(response.json::<Vec<Group>>().await.unwrap())
817 }
818
819 pub async fn create_group(&self, owner: &str, name: &str) -> Result<(), error::Error> {
820 let path = format!("/groups/user/{}/", owner);
821 let group = CreateGroupData {
822 name: name.to_owned(),
823 services_hosts: None,
824 };
825 let response = self
826 .request(Method::POST, &path)
827 .json(&group)
828 .send()
829 .await
830 .map_err(error::Error::RequestError)?;
831
832 check_response(response).await?;
833 Ok(())
834 }
835
836 pub async fn delete_group(&self, id: &GroupId) -> Result<(), error::Error> {
837 let path = format!("/groups/id/{}", id);
838 let response = self
839 .request(Method::DELETE, &path)
840 .send()
841 .await
842 .map_err(error::Error::RequestError)?;
843
844 check_response(response).await?;
845 Ok(())
846 }
847
848 pub async fn list_members(&self, id: &GroupId) -> Result<Vec<User>, error::Error> {
849 let path = format!("/groups/id/{}/members", id);
850 let response = self
851 .request(Method::GET, &path)
852 .send()
853 .await
854 .map_err(error::Error::RequestError)?;
855
856 let response = check_response(response).await?;
857 Ok(response.json::<Vec<User>>().await.unwrap())
858 }
859
860 pub async fn rename_group(&self, id: &GroupId, name: &str) -> Result<(), error::Error> {
861 let path = format!("/groups/id/{}", id);
862 let response = self
863 .request(Method::PATCH, &path)
864 .json(&UpdateGroupData {
865 name: name.to_owned(),
866 })
867 .send()
868 .await
869 .map_err(error::Error::RequestError)?;
870
871 check_response(response).await?;
872 Ok(())
873 }
874
875 pub async fn view_group(&self, id: &GroupId) -> Result<Group, error::Error> {
876 let path = format!("/groups/id/{}", id);
877 let response = self
878 .request(Method::GET, &path)
879 .send()
880 .await
881 .map_err(error::Error::RequestError)?;
882
883 let response = check_response(response).await?;
884
885 Ok(response.json::<Group>().await.unwrap())
886 }
887
888 pub async fn list_user_hosts(&self, username: &str) -> Result<Vec<ServiceHost>, error::Error> {
890 let response = self
891 .request(Method::GET, &format!("/services/hosts/user/{}", username))
892 .send()
893 .await
894 .map_err(error::Error::RequestError)?;
895
896 let response = check_response(response).await?;
897
898 Ok(response.json::<Vec<ServiceHost>>().await.unwrap())
899 }
900
901 pub async fn list_group_hosts(
902 &self,
903 group_id: &GroupId,
904 ) -> Result<Vec<ServiceHost>, error::Error> {
905 let response = self
906 .request(Method::GET, &format!("/services/hosts/group/{}", group_id))
907 .send()
908 .await
909 .map_err(error::Error::RequestError)?;
910
911 let response = check_response(response).await?;
912
913 Ok(response.json::<Vec<ServiceHost>>().await.unwrap())
914 }
915
916 pub async fn list_hosts(&self, username: &str) -> Result<Vec<ServiceHost>, error::Error> {
917 let response = self
918 .request(Method::GET, &format!("/services/hosts/all/{}", username))
919 .send()
920 .await
921 .map_err(error::Error::RequestError)?;
922
923 let response = check_response(response).await?;
924
925 Ok(response.json::<Vec<ServiceHost>>().await.unwrap())
926 }
927
928 pub async fn set_user_hosts(
929 &self,
930 username: &str,
931 hosts: Vec<ServiceHost>,
932 ) -> Result<(), error::Error> {
933 let response = self
934 .request(Method::POST, &format!("/services/hosts/user/{}", username))
935 .json(&hosts)
936 .send()
937 .await
938 .map_err(error::Error::RequestError)?;
939
940 check_response(response).await?;
941 Ok(())
942 }
943
944 pub async fn set_group_hosts(
945 &self,
946 group_id: &GroupId,
947 hosts: Vec<ServiceHost>,
948 ) -> Result<(), error::Error> {
949 let response = self
950 .request(Method::POST, &format!("/services/hosts/group/{}", group_id))
951 .json(&hosts)
952 .send()
953 .await
954 .map_err(error::Error::RequestError)?;
955
956 check_response(response).await?;
957 Ok(())
958 }
959
960 pub async fn authorize_host(
961 &self,
962 url: &str,
963 id: &str,
964 visibility: ServiceHostScope,
965 ) -> Result<String, error::Error> {
966 let host = AuthorizedServiceHost {
967 url: url.to_owned(),
968 id: id.to_owned(),
969 visibility,
970 };
971 let response = self
972 .request(Method::POST, "/services/hosts/authorized/")
973 .json(&host)
974 .send()
975 .await
976 .map_err(error::Error::RequestError)?;
977
978 let response = check_response(response).await?;
979 Ok(response.json::<String>().await.unwrap())
980 }
981
982 pub async fn unauthorize_host(&self, id: &str) -> Result<(), error::Error> {
983 let response = self
984 .request(
985 Method::DELETE,
986 &format!("/services/hosts/authorized/{}", id),
987 )
988 .send()
989 .await
990 .map_err(error::Error::RequestError)?;
991
992 check_response(response).await?;
993 Ok(())
994 }
995
996 pub async fn list_authorized_hosts(&self) -> Result<Vec<AuthorizedServiceHost>, error::Error> {
997 let response = self
998 .request(Method::GET, "/services/hosts/authorized/")
999 .send()
1000 .await
1001 .map_err(error::Error::RequestError)?;
1002
1003 let response = check_response(response).await?;
1004 Ok(response.json::<Vec<AuthorizedServiceHost>>().await.unwrap())
1005 }
1006
1007 pub async fn list_group_settings(
1009 &self,
1010 group_id: &GroupId,
1011 ) -> Result<Vec<String>, error::Error> {
1012 let response = self
1013 .request(
1014 Method::GET,
1015 &format!("/services/settings/group/{}/", group_id),
1016 )
1017 .send()
1018 .await
1019 .map_err(error::Error::RequestError)?;
1020
1021 let response = check_response(response).await?;
1022 Ok(response.json::<Vec<String>>().await.unwrap())
1023 }
1024
1025 pub async fn list_user_settings(&self, username: &str) -> Result<Vec<String>, error::Error> {
1026 let response = self
1027 .request(
1028 Method::GET,
1029 &format!("/services/settings/user/{}/", username),
1030 )
1031 .send()
1032 .await
1033 .map_err(error::Error::RequestError)?;
1034
1035 let response = check_response(response).await?;
1036 Ok(response.json::<Vec<String>>().await.unwrap())
1037 }
1038
1039 pub async fn get_all_settings(
1040 &self,
1041 username: &str,
1042 service_id: &str,
1043 ) -> Result<ServiceSettings, error::Error> {
1044 let response = self
1045 .request(
1046 Method::GET,
1047 &format!("/services/settings/user/{}/{}/all", username, service_id),
1048 )
1049 .send()
1050 .await
1051 .map_err(error::Error::RequestError)?;
1052
1053 let response = check_response(response).await?;
1054 Ok(response.json::<ServiceSettings>().await.unwrap())
1055 }
1056
1057 pub async fn get_group_settings(
1058 &self,
1059 group_id: &GroupId,
1060 service_id: &str,
1061 ) -> Result<String, error::Error> {
1062 let response = self
1063 .request(
1064 Method::GET,
1065 &format!("/services/settings/group/{}/{}", group_id, service_id),
1066 )
1067 .send()
1068 .await
1069 .map_err(error::Error::RequestError)?;
1070
1071 let response = check_response(response).await?;
1072 Ok(response.text().await.unwrap())
1073 }
1074
1075 pub async fn get_user_settings(
1076 &self,
1077 username: &str,
1078 service_id: &str,
1079 ) -> Result<String, error::Error> {
1080 let response = self
1081 .request(
1082 Method::GET,
1083 &format!("/services/settings/user/{}/{}", username, service_id),
1084 )
1085 .send()
1086 .await
1087 .map_err(error::Error::RequestError)?;
1088
1089 let response = check_response(response).await?;
1090 Ok(response.text().await.unwrap())
1091 }
1092
1093 pub async fn set_user_settings(
1094 &self,
1095 username: &str,
1096 service_id: &str,
1097 settings: String,
1098 ) -> Result<String, error::Error> {
1099 let response = self
1100 .request(
1101 Method::POST,
1102 &format!("/services/settings/user/{}/{}", username, service_id),
1103 )
1104 .body(settings)
1105 .send()
1106 .await
1107 .map_err(error::Error::RequestError)?;
1108
1109 let response = check_response(response).await?;
1110 Ok(response.text().await.unwrap())
1111 }
1112
1113 pub async fn set_group_settings(
1114 &self,
1115 group_id: &GroupId,
1116 service_id: &str,
1117 settings: String,
1118 ) -> Result<String, error::Error> {
1119 let response = self
1120 .request(
1121 Method::POST,
1122 &format!("/services/settings/group/{}/{}", group_id, service_id),
1123 )
1124 .body(settings)
1125 .send()
1126 .await
1127 .map_err(error::Error::RequestError)?;
1128
1129 let response = check_response(response).await?;
1130 Ok(response.text().await.unwrap())
1131 }
1132
1133 pub async fn delete_user_settings(
1134 &self,
1135 username: &str,
1136 service_id: &str,
1137 ) -> Result<String, error::Error> {
1138 let response = self
1139 .request(
1140 Method::DELETE,
1141 &format!("/services/settings/user/{}/{}", username, service_id),
1142 )
1143 .send()
1144 .await
1145 .map_err(error::Error::RequestError)?;
1146
1147 let response = check_response(response).await?;
1148 Ok(response.text().await.unwrap())
1149 }
1150
1151 pub async fn delete_group_settings(
1152 &self,
1153 group_id: &GroupId,
1154 service_id: &str,
1155 ) -> Result<String, error::Error> {
1156 let response = self
1157 .request(
1158 Method::DELETE,
1159 &format!("/services/settings/group/{}/{}", group_id, service_id),
1160 )
1161 .send()
1162 .await
1163 .map_err(error::Error::RequestError)?;
1164
1165 let response = check_response(response).await?;
1166 Ok(response.text().await.unwrap())
1167 }
1168 pub async fn list_external_clients(&self) -> Result<Vec<ExternalClient>, error::Error> {
1170 let response = self
1171 .request(Method::GET, "/network/external")
1172 .send()
1173 .await
1174 .map_err(error::Error::RequestError)?;
1175
1176 let response = check_response(response).await?;
1177
1178 Ok(response.json::<Vec<ExternalClient>>().await.unwrap())
1179 }
1180
1181 pub async fn list_networks(&self) -> Result<Vec<ProjectId>, error::Error> {
1182 let response = self
1183 .request(Method::GET, "/network/")
1184 .send()
1185 .await
1186 .map_err(error::Error::RequestError)?;
1187
1188 let response = check_response(response).await?;
1189
1190 Ok(response.json::<Vec<ProjectId>>().await.unwrap())
1191 }
1192
1193 pub async fn get_room_state(&self, id: &ProjectId) -> Result<RoomState, error::Error> {
1194 let response = self
1195 .request(Method::GET, &format!("/network/id/{}", id))
1196 .send()
1197 .await
1198 .map_err(error::Error::RequestError)?;
1199
1200 let response = check_response(response).await?;
1201
1202 Ok(response.json::<RoomState>().await.unwrap())
1203 }
1204
1205 pub async fn get_client_state(&self, client_id: &ClientId) -> Result<ClientInfo, error::Error> {
1206 let response = self
1207 .request(
1208 Method::GET,
1209 &format!("/network/{}/state", client_id.as_str()),
1210 )
1211 .send()
1212 .await
1213 .map_err(error::Error::RequestError)?;
1214
1215 let response = check_response(response).await?;
1216
1217 Ok(response.json::<ClientInfo>().await.unwrap())
1218 }
1219
1220 pub async fn evict_occupant(&self, client_id: &ClientId) -> Result<(), error::Error> {
1221 let response = self
1222 .request(
1223 Method::POST,
1224 &format!("/network/clients/{}/evict", client_id.as_str()),
1225 )
1226 .send()
1227 .await
1228 .map_err(error::Error::RequestError)?;
1229
1230 check_response(response).await?;
1231 Ok(())
1232 }
1233
1234 pub async fn connect(&self, address: &str) -> Result<MessageChannel, error::Error> {
1235 let response = self
1236 .request(Method::GET, "/configuration")
1237 .send()
1238 .await
1239 .map_err(error::Error::RequestError)?;
1240
1241 let response = check_response(response).await?;
1242
1243 let config = response.json::<ClientConfig>().await.unwrap();
1244
1245 let url = format!(
1246 "{}/network/{}/connect",
1247 self.cfg.url.replace("http", "ws"),
1248 config.client_id
1249 );
1250 let (ws_stream, _) = connect_async(&url).await.unwrap();
1251
1252 let state = ClientStateData {
1253 state: ClientState::External(ExternalClientState {
1254 address: address.to_owned(),
1255 app_id: self.cfg.app_id.as_ref().unwrap().clone(),
1256 }),
1257 };
1258
1259 let response = self
1260 .request(
1261 Method::POST,
1262 &format!("/network/{}/state", config.client_id),
1263 )
1264 .json(&state)
1265 .send()
1266 .await
1267 .map_err(error::Error::RequestError)?;
1268
1269 check_response(response).await?;
1270
1271 Ok(MessageChannel {
1272 id: config.client_id,
1273 stream: ws_stream,
1274 })
1275 }
1276
1277 pub async fn add_oauth_client(
1279 &self,
1280 client: &oauth::CreateClientData,
1281 ) -> Result<oauth::CreatedClientData, error::Error> {
1282 let response = self
1283 .request(Method::POST, "/oauth/clients/")
1284 .json(&client)
1285 .send()
1286 .await
1287 .map_err(error::Error::RequestError)?;
1288
1289 let response = check_response(response).await?;
1290
1291 Ok(response.json::<oauth::CreatedClientData>().await.unwrap())
1292 }
1293
1294 pub async fn remove_oauth_client(&self, id: &oauth::ClientId) -> Result<(), error::Error> {
1295 let response = self
1296 .request(Method::DELETE, &format!("/oauth/clients/{}", id))
1297 .send()
1298 .await
1299 .map_err(error::Error::RequestError)?;
1300
1301 check_response(response).await?;
1302 Ok(())
1303 }
1304
1305 pub async fn list_oauth_clients(&self) -> Result<Vec<oauth::Client>, error::Error> {
1306 let response = self
1307 .request(Method::GET, "/oauth/clients/")
1308 .send()
1309 .await
1310 .map_err(error::Error::RequestError)?;
1311
1312 let response = check_response(response).await?;
1313
1314 Ok(response.json::<Vec<oauth::Client>>().await.unwrap())
1315 }
1316}
1317
1318pub struct MessageChannel {
1319 pub id: String,
1320 pub stream: WebSocketStream<MaybeTlsStream<TcpStream>>,
1321}
1322
1323impl MessageChannel {
1324 pub async fn send_json(
1327 &mut self,
1328 addr: &str,
1329 r#type: &str,
1330 data: &Value,
1331 ) -> Result<(), error::Error> {
1332 let msg = json!({
1333 "type": "message",
1334 "dstId": addr,
1335 "msgType": r#type,
1336 "content": data
1337 });
1338 let msg_text = serde_json::to_string(&msg).unwrap();
1339 self.stream
1340 .send(Message::Text(msg_text))
1341 .await
1342 .map_err(error::Error::WebSocketSendError)?;
1343
1344 Ok(())
1345 }
1346}
1347
1348#[cfg(test)]
1349mod tests {
1350
1351 #[test]
1352 fn it_works() {
1353 let result = 2 + 2;
1354 assert_eq!(result, 4);
1355 }
1356}