1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use crate::*;

const LOGIN_PAGE_URL: &str = "https://wsdmoodle.waseda.jp/auth/saml2/login.php?wants=https%3A%2F%2Fwsdmoodle.waseda.jp%2F&idp=fcc52c5d2e034b1803ea1932ae2678b0&passive=off";
pub struct Session {
    pub client: reqwest::Client,
    pub session_key: String,
}
impl Session {
    pub async fn login(login_id: &str, password: &str) -> Result<Session> {
        let client = reqwest::ClientBuilder::new()
            .cookie_store(true)
            .use_rustls_tls()
            .build()
            .context(ErrorKind::InvalidResponse(Some(
                "cannot create http client".to_owned(),
            )))?;
        let login_page =
            LoginPage::extract_from_str(&client.get(LOGIN_PAGE_URL).send().await?.text().await?)?;
        let login_response = LoginResponse::extract_from_str(
            &client
                .post(
                    reqwest::Url::parse("https://iaidp.ia.waseda.jp/")
                        .unwrap()
                        .join(&login_page.login_info_post_url)
                        .unwrap(),
                )
                .form(&[
                    ("j_username", login_id),
                    ("j_password", password),
                    ("_eventId_proceed", "Login"),
                ])
                .send()
                .await?
                .text()
                .await?,
        )?;
        let moodle_top = MoodleTop::extract_from_str(
            &client
                .post(&login_response.login_continue_url)
                .form(&[
                    ("RelayState", &login_response.relay_state),
                    ("SAMLResponse", &login_response.saml_response),
                ])
                .send()
                .await?
                .text()
                .await?,
        )?;

        Ok(Session {
            client,
            session_key: moodle_top.session_key,
        })
    }
}

html_extractor! {
    #[derive(Debug)]
    LoginPage {
        login_info_post_url: String = (attr["action"] of "#login"),
    }
    #[derive(Debug)]
    LoginResponse {
        login_continue_url: String = (attr["action"] of "form"),
        relay_state: String = (attr["value"] of r#"input[name="RelayState"]"#),
        saml_response: String = (attr["value"] of r#"input[name="SAMLResponse"]"#),
    }
    #[derive(Debug)]
    MoodleTop {
        (session_key: String,) = (attr["href"] of r#"[data-title="logout,moodle"]"#, capture with r#"sesskey=(.*)$"#)
    }
}