1use tap::Pipe;
2use tracing::{debug, trace};
3
4use crate::{
5 ApiError, Error, Qbit, Result,
6 client::{CheckError, Method, StatusCode},
7 ext::*,
8};
9
10impl Qbit {
11 pub async fn get_cookie(&self) -> Option<String> {
13 self.state
14 .lock()
15 .unwrap()
16 .as_header()
17 .1
18 .map(ToOwned::to_owned)
19 }
20
21 pub async fn logout(&self) -> Result<()> {
23 self.get("auth/logout").await?.end()
24 }
25
26 pub async fn login(&self, force: bool) -> Result<()> {
31 let re_login = force || { self.state().as_header().1.is_none() };
32 if re_login {
33 let credential = match self.state().as_credential() {
34 Some(credential) => credential.clone(),
35 None => {
36 trace!("API key or cookie auth in use, skipping login");
37 return Ok(());
38 }
39 };
40 debug!("Cookie not found, logging in");
41 self.client
42 .request(Method::POST, self.url("auth/login"))
43 .check()?
44 .pipe(|req| req.form(&credential))
45 .check()?
46 .send()
47 .await?
48 .map_status(|code| match code as _ {
49 StatusCode::FORBIDDEN => Some(Error::ApiError(ApiError::IpBanned)),
50 StatusCode::UNAUTHORIZED => Some(Error::ApiError(ApiError::BadCredentials)),
51 _ => None,
52 })?
53 .extract::<Cookie>()?
54 .pipe(|Cookie(cookie)| self.state.lock().unwrap().add_cookie(cookie));
55
56 debug!("Log in success");
57 } else {
58 trace!("Already logged in, skipping");
59 }
60
61 Ok(())
62 }
63}