Skip to main content

pickcat_api_collection/
auth.rs

1//! 鉴权与入站考试:会话、注册、邮箱验证、考试流程。
2//!
3//! 参见 <https://pickcat-docs.xiaole6324.fun/auth.html>。
4
5use crate::{Error, PickcatAccound};
6
7use crate::dto::auth::{
8    CurrentQuestionDTO, ExamStatusDTO, RegistrationDTO, SendRegistrationDTO, SendVerifyEmailDTO,
9    SessionDTO, StartExamDTO, SubmitExamAnswerDTO, SubmitExamAnswerResponseDTO, VerifyEmailDTO,
10};
11
12pub trait UserBehavior {
13    fn get_current_user_session(
14        &self,
15    ) -> impl std::future::Future<Output = Result<SessionDTO, Error>> + Send;
16    fn post_registration(
17        &self,
18        username: &str,
19        email: &str,
20        captcha: &str,
21    ) -> impl std::future::Future<Output = Result<RegistrationDTO, Error>> + Send;
22    fn verify_email(
23        &self,
24        id: &str,
25        code: &str,
26        password: &str,
27    ) -> impl Future<Output = Result<VerifyEmailDTO, Error>> + Send;
28    fn get_exam_status(&self) -> impl Future<Output = Result<ExamStatusDTO, Error>> + Send;
29    fn start_exam(&self) -> impl Future<Output = Result<StartExamDTO, Error>> + Send;
30    fn get_current_question(
31        &self,
32        id: &str,
33    ) -> impl Future<Output = Result<CurrentQuestionDTO, Error>> + Send;
34    fn submit_answer(
35        &self,
36        exam_id: &str,
37        question_id: &str,
38        token: &str,
39        selected_option_ids: Vec<String>,
40    ) -> impl Future<Output = Result<SubmitExamAnswerResponseDTO, Error>> + Send;
41}
42
43impl UserBehavior for PickcatAccound {
44    async fn get_current_user_session(&self) -> Result<SessionDTO, Error> {
45        Ok(self
46            .client
47            .get(format!("{}/api/v1/session", self.base_url))
48            .send()
49            .await?
50            .json::<SessionDTO>()
51            .await?)
52    }
53
54    async fn post_registration(
55        &self,
56        username: &str,
57        email: &str,
58        captcha: &str,
59    ) -> Result<RegistrationDTO, Error> {
60        let dto = SendRegistrationDTO {
61            username: username.to_string(),
62            email: email.to_string(),
63            captcha_verify_param: captcha.to_string(),
64        };
65        Ok(self
66            .client
67            .post(format!("{}/api/v1/registrations", self.base_url))
68            .json(&dto)
69            .send()
70            .await?
71            .json::<RegistrationDTO>()
72            .await?)
73    }
74
75    async fn verify_email(
76        &self,
77        code: &str,
78        password: &str,
79        id: &str,
80    ) -> Result<VerifyEmailDTO, Error> {
81        let dto = SendVerifyEmailDTO {
82            code: code.to_string(),
83            password: password.to_string(),
84        };
85        Ok(self
86            .client
87            .patch(format!("{}/api/v1/registrations/{}", self.base_url, id))
88            .json(&dto)
89            .send()
90            .await?
91            .json::<VerifyEmailDTO>()
92            .await?)
93    }
94
95    async fn get_exam_status(&self) -> Result<ExamStatusDTO, Error> {
96        Ok(self
97            .client
98            .get(format!("{}/api/v1/entrance-exam", self.base_url))
99            .send()
100            .await?
101            .json::<ExamStatusDTO>()
102            .await?)
103    }
104
105    async fn start_exam(&self) -> Result<StartExamDTO, Error> {
106        Ok(self
107            .client
108            .post(format!("{}/api/v1/entrance-exam/attempts", self.base_url))
109            .send()
110            .await?
111            .json::<StartExamDTO>()
112            .await?)
113    }
114
115    async fn get_current_question(&self, id: &str) -> Result<CurrentQuestionDTO, Error> {
116        Ok(self
117            .client
118            .get(format!(
119                "{}/api/v1/entrance-exam/attempts/{}/current-question",
120                self.base_url, id
121            ))
122            .send()
123            .await?
124            .json::<CurrentQuestionDTO>()
125            .await?)
126    }
127
128    async fn submit_answer(
129        &self,
130        exam_id: &str,
131        question_id: &str,
132        token: &str,
133        selected_option_ids: Vec<String>,
134    ) -> Result<SubmitExamAnswerResponseDTO, Error> {
135        let dto = SubmitExamAnswerDTO {
136            question_id: question_id.to_string(),
137            delivery_token: token.to_string(),
138            selected_option_ids: selected_option_ids,
139        };
140        Ok(self
141            .client
142            .patch(format!(
143                "{}/api/v1/entrance-exam/attempts/{}/current-question",
144                self.base_url, exam_id
145            ))
146            .json(&dto)
147            .send()
148            .await?
149            .json::<SubmitExamAnswerResponseDTO>()
150            .await?)
151    }
152}