11use http:: status:: StatusCode ;
22use isahc:: { auth:: Authentication , prelude:: * , HttpClient , Request } ;
3+ use rpassword:: read_password;
34use serde_json:: json;
45use serde_json:: { Map , Value } ;
6+ use std:: env;
57use std:: fmt;
8+ use std:: io:: { Read , Write } ;
9+ use std:: process:: { Command , Stdio } ;
610use url:: Url ;
11+ use users:: get_current_username;
712
813pub struct API {
914 token : Option < String > ,
@@ -28,7 +33,9 @@ impl fmt::Display for APIError {
2833
2934impl API {
3035 pub fn new ( ) -> API {
31- return API { token : None } ;
36+ let mut api = API { token : None } ;
37+ api. get_token ( ) ;
38+ return api;
3239 }
3340 pub fn drop ( self : & mut API , machine : String , slot : u8 ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
3441 let token = self . get_token ( ) ?;
@@ -64,7 +71,10 @@ impl API {
6471 . body ( ( ) ) ?. send ( ) ?;
6572 let location = match response. headers ( ) . get ( "Location" ) {
6673 Some ( location) => location,
67- None => return Err ( Box :: new ( APIError :: Unauthorized ) ) ,
74+ None => {
75+ API :: login ( ) ;
76+ return self . get_token ( ) ;
77+ }
6878 } ;
6979 let url = Url :: parse ( & location. to_str ( ) ?. replace ( "#" , "?" ) ) ?;
7080
@@ -80,20 +90,63 @@ impl API {
8090 } ;
8191 }
8292
93+ fn login ( ) {
94+ // Get credentials
95+ let username: Option < String > = std:: env:: var ( "CLINK_USERNAME" )
96+ . map ( |it| Some ( it) )
97+ . unwrap_or_else ( |_| get_current_username ( ) . and_then ( |it| it. into_string ( ) . ok ( ) ) ) ;
98+
99+ let username: String = username. unwrap ( ) ;
100+
101+ // Start kinit, ready to get password from pipe
102+ let mut process = Command :: new ( "kinit" )
103+ . arg ( format ! ( "{}@CSH.RIT.EDU" , username) )
104+ . stdin ( Stdio :: piped ( ) )
105+ . stdout ( Stdio :: null ( ) )
106+ . spawn ( )
107+ . unwrap ( ) ;
108+
109+ // Get password
110+ println ! ( "Please enter password for {}: " , username) ;
111+ let password = read_password ( ) . unwrap ( ) ;
112+
113+ // Pipe password into the prompt that "comes up"
114+ process
115+ . stdin
116+ . as_ref ( )
117+ . unwrap ( )
118+ . write_all ( password. as_bytes ( ) )
119+ . unwrap ( ) ;
120+
121+ // Wait for login to be complete before continuting
122+ process. wait ( ) . unwrap ( ) ;
123+
124+ println ! ( "...\n \n " ) ;
125+ }
126+
83127 pub fn get_credits ( self : & mut API ) -> Result < u64 , Box < dyn std:: error:: Error > > {
84128 //let token = self.get_token()?;
85129 let client = HttpClient :: new ( ) ?;
86130 // Can also be used to get other user information
87- let request = Request :: get ( "https://sso.csh.rit.edu/auth/realms/csh/protocol/openid-connect/userinfo" )
131+ let request =
132+ Request :: get ( "https://sso.csh.rit.edu/auth/realms/csh/protocol/openid-connect/userinfo" )
88133 . header ( "Authorization" , self . get_token ( ) ?)
89134 . body ( ( ) ) ?;
90135 let response: Value = client. send ( request) ?. json ( ) ?;
91136 let uid = response[ "preferred_username" ] . as_str ( ) . unwrap ( ) . to_string ( ) ;
92- let credit_request = Request :: get ( format ! ( "https://drink.csh.rit.edu/users/credits?uid={}" , uid) )
93- . header ( "Authorization" , self . get_token ( ) ?)
94- . body ( ( ) ) ?;
137+ let credit_request = Request :: get ( format ! (
138+ "https://drink.csh.rit.edu/users/credits?uid={}" ,
139+ uid
140+ ) )
141+ . header ( "Authorization" , self . get_token ( ) ?)
142+ . body ( ( ) ) ?;
95143 let credit_response: Value = client. send ( credit_request) ?. json ( ) ?;
96- Ok ( credit_response[ "user" ] [ "drinkBalance" ] . as_str ( ) . unwrap ( ) . parse :: < u64 > ( ) ?) // Coffee
144+ Ok (
145+ credit_response[ "user" ] [ "drinkBalance" ]
146+ . as_str ( )
147+ . unwrap ( )
148+ . parse :: < u64 > ( ) ?,
149+ ) // Coffee
97150 }
98151
99152 pub fn get_machine_status ( self : & mut API ) -> Result < Value , Box < dyn std:: error:: Error > > {
0 commit comments