@@ -7,7 +7,6 @@ use crate::response::{Course, CourseDetails, Organization};
7
7
use crate :: { Language , RunResult , ValidationResult } ;
8
8
9
9
use oauth2:: basic:: BasicClient ;
10
- use oauth2:: prelude:: * ;
11
10
use oauth2:: {
12
11
AuthUrl , ClientId , ClientSecret , ResourceOwnerPassword , ResourceOwnerUsername , TokenUrl ,
13
12
} ;
@@ -18,7 +17,6 @@ use std::path::Path;
18
17
use std:: path:: PathBuf ;
19
18
use tempfile:: NamedTempFile ;
20
19
use tmc_langs_util:: task_executor;
21
- use url1:: Url as Url1 ;
22
20
23
21
pub type Token =
24
22
oauth2:: StandardTokenResponse < oauth2:: EmptyExtraTokenFields , oauth2:: basic:: BasicTokenType > ;
@@ -42,7 +40,10 @@ impl TmcCore {
42
40
///
43
41
/// # Examples
44
42
/// ```rust,no_run
45
- /// let core = TmcCore::new(Path::new("./config"), "https://tmc.mooc.fi".to_string()).unwrap();
43
+ /// use tmc_langs_core::TmcCore;
44
+ /// use std::path::PathBuf;
45
+ ///
46
+ /// let core = TmcCore::new(PathBuf::from("./config"), "https://tmc.mooc.fi".to_string()).unwrap();
46
47
/// ```
47
48
pub fn new ( config_dir : PathBuf , root_url : String ) -> Result < Self > {
48
49
// guarantee a trailing slash, otherwise join will drop the last component
@@ -70,6 +71,8 @@ impl TmcCore {
70
71
///
71
72
/// # Examples
72
73
/// ```rust,no_run
74
+ /// use tmc_langs_core::TmcCore;
75
+ ///
73
76
/// let core = TmcCore::new_in_config("https://tmc.mooc.fi".to_string()).unwrap();
74
77
/// ```
75
78
pub fn new_in_config ( root_url : String ) -> Result < Self > {
@@ -87,6 +90,8 @@ impl TmcCore {
87
90
///
88
91
/// # Examples
89
92
/// ```rust,no_run
93
+ /// use tmc_langs_core::TmcCore;
94
+ ///
90
95
/// let mut core = TmcCore::new_in_config("https://tmc.mooc.fi".to_string()).unwrap();
91
96
/// core.authenticate("client", "user".to_string(), "pass".to_string()).unwrap();
92
97
/// ```
@@ -96,6 +101,59 @@ impl TmcCore {
96
101
email : String ,
97
102
password : String ,
98
103
) -> Result < ( ) > {
104
+ // required until oauth 4.x.x
105
+ fn custom_client < ' a > (
106
+ client : & ' a Client ,
107
+ ) -> impl FnOnce ( oauth2:: HttpRequest ) -> Result < oauth2:: HttpResponse > + ' a {
108
+ move |req| {
109
+ // convert httprequest fields
110
+ let method = http:: method:: Method :: from_bytes ( req. method . as_str ( ) . as_bytes ( ) ) ?;
111
+ let mut headers = http:: HeaderMap :: new ( ) ;
112
+ let mut next_key = None ;
113
+ for ( key, val) in req. headers {
114
+ // if key is none, keep using previous next key
115
+ if key. is_some ( ) {
116
+ // update next key
117
+ next_key = key;
118
+ }
119
+ let header_name = if let Some ( name) = next_key. as_ref ( ) {
120
+ // use next key
121
+ name
122
+ } else {
123
+ log:: error!( "invalid header map, found None key first" ) ;
124
+ continue ;
125
+ } ;
126
+ let header_name =
127
+ http:: header:: HeaderName :: from_bytes ( header_name. as_str ( ) . as_bytes ( ) ) ?;
128
+ let header_value = http:: header:: HeaderValue :: from_bytes ( val. as_bytes ( ) ) ?;
129
+ headers. insert ( header_name, header_value) ;
130
+ }
131
+ let res = client
132
+ . request ( method, req. url )
133
+ . headers ( headers)
134
+ . body ( req. body )
135
+ . send ( ) ?;
136
+
137
+ // convert response to httpresponse
138
+ let status_code = http1:: StatusCode :: from_bytes ( res. status ( ) . as_str ( ) . as_bytes ( ) ) ?;
139
+ let mut headers = http1:: HeaderMap :: new ( ) ;
140
+ for ( key, val) in res. headers ( ) {
141
+ let header_name =
142
+ http1:: header:: HeaderName :: from_bytes ( key. as_str ( ) . as_bytes ( ) ) ?;
143
+ let header_value = http1:: header:: HeaderValue :: from_bytes ( val. as_bytes ( ) ) ?;
144
+ headers. insert ( header_name, header_value) ;
145
+ }
146
+ let body = res. bytes ( ) ?. to_vec ( ) ;
147
+ let res = oauth2:: HttpResponse {
148
+ status_code,
149
+ headers,
150
+ body,
151
+ } ;
152
+
153
+ Ok ( res)
154
+ }
155
+ }
156
+
99
157
if self . token . is_some ( ) {
100
158
return Err ( CoreError :: AlreadyAuthenticated ) ;
101
159
}
@@ -105,26 +163,20 @@ impl TmcCore {
105
163
. join ( & format ! ( "application/{}/credentials" , client_name) ) ?;
106
164
let credentials: Credentials = self . get_json_from_url ( url) ?;
107
165
108
- let auth_url = Url1 :: parse ( self . auth_url . as_str ( ) ) ?;
109
- log:: debug!( "authenticating at {}" , auth_url) ;
166
+ log:: debug!( "authenticating at {}" , self . auth_url) ;
110
167
let client = BasicClient :: new (
111
168
ClientId :: new ( credentials. application_id ) ,
112
169
Some ( ClientSecret :: new ( credentials. secret ) ) ,
113
- AuthUrl :: new ( auth_url. clone ( ) ) , // not used in the Resource Owner Password Credentials Grant
114
- Some ( TokenUrl :: new ( auth_url) ) ,
170
+ AuthUrl :: new ( self . auth_url . as_str ( ) . to_string ( ) ) ? , // not used in the Resource Owner Password Credentials Grant
171
+ Some ( TokenUrl :: new ( self . auth_url . as_str ( ) . to_string ( ) ) ? ) ,
115
172
) ;
116
173
117
174
let token = client
118
175
. exchange_password (
119
176
& ResourceOwnerUsername :: new ( email) ,
120
177
& ResourceOwnerPassword :: new ( password) ,
121
178
)
122
- . map_err ( |e| match e {
123
- oauth2:: RequestTokenError :: Parse ( e, msg) => {
124
- CoreError :: TokenParse ( e, String :: from_utf8_lossy ( & msg) . into_owned ( ) )
125
- }
126
- _ => CoreError :: Token ( e) ,
127
- } ) ?;
179
+ . request ( custom_client ( & self . client ) ) ?;
128
180
self . token = Some ( token) ;
129
181
log:: debug!( "authenticated" ) ;
130
182
Ok ( ( ) )
@@ -152,6 +204,9 @@ impl TmcCore {
152
204
///
153
205
/// # Examples
154
206
/// ```rust,no_run
207
+ /// use tmc_langs_core::TmcCore;
208
+ /// use std::path::Path;
209
+ ///
155
210
/// let core = TmcCore::new_in_config("https://tmc.mooc.fi".to_string()).unwrap();
156
211
/// // authenticate
157
212
/// core.download_or_update_exercises(vec![
@@ -274,10 +329,12 @@ impl TmcCore {
274
329
///
275
330
/// # Examples
276
331
/// ```rust,no_run
332
+ /// use tmc_langs_core::TmcCore;
333
+ ///
277
334
/// let core = TmcCore::new_in_config("https://tmc.mooc.fi".to_string()).unwrap();
278
335
/// // authenticate
279
336
/// let mut checksums = std::collections::HashMap::new();
280
- /// checksums.insert(1234, "exercisechecksum");
337
+ /// checksums.insert(1234, "exercisechecksum".to_string() );
281
338
/// let update_result = core.get_exercise_updates(600, checksums).unwrap();
282
339
/// ```
283
340
pub fn get_exercise_updates (
0 commit comments