Last active
August 4, 2017 21:49
-
-
Save sethlopezme/ea921ab51ef2c94d8de4fe8f9e7dd548 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate reqwest; | |
extern crate serde; | |
#[macro_use] | |
extern crate serde_derive; | |
extern crate serde_urlencoded; | |
use std::collections::HashSet; | |
use std::fmt; | |
use serde::Serializer; | |
#[derive(Debug)] | |
pub struct Client; | |
impl Client { | |
pub fn code_authorization_url_builder() -> AuthorizationUrlBuilder { | |
AuthorizationUrlBuilder { | |
client_id: None, | |
compact: false, | |
origin: None, | |
duration: None, | |
redirect_uri: None, | |
response_type: AuthorizationResponseType::Code, | |
scope: None, | |
state: None, | |
} | |
} | |
} | |
#[derive(Debug)] | |
pub struct AuthorizationUrlBuilder { | |
client_id: Option<String>, | |
compact: bool, | |
duration: Option<AuthorizationDuration>, | |
origin: Option<String>, | |
redirect_uri: Option<String>, | |
response_type: AuthorizationResponseType, | |
scope: Option<HashSet<Scope>>, | |
state: Option<String>, | |
} | |
impl AuthorizationUrlBuilder { | |
pub fn client_id(&mut self, client_id: String) -> &mut Self { | |
self.client_id = Some(client_id); | |
self | |
} | |
pub fn compact(&mut self, compact: bool) -> &mut Self { | |
self.compact = compact; | |
self | |
} | |
pub fn duration(&mut self, duration: AuthorizationDuration) -> &mut Self { | |
self.duration = Some(duration); | |
self | |
} | |
pub fn origin(&mut self, origin: String) -> &mut Self { | |
self.origin = Some(origin); | |
self | |
} | |
pub fn redirect_uri(&mut self, redirect_uri: String) -> &mut Self { | |
self.redirect_uri = Some(redirect_uri); | |
self | |
} | |
pub fn scope(&mut self, scope: HashSet<Scope>) -> &mut Self { | |
self.scope = Some(scope); | |
self | |
} | |
pub fn state(&mut self, state: String) -> &mut Self { | |
self.state = Some(state); | |
self | |
} | |
pub fn build(&self) -> Result<String, String> { | |
let client_id = Clone::clone(self.client_id.as_ref().ok_or(String::from( | |
"client_id must be initialized", | |
))?); | |
let compact = if self.compact { ".compact" } else { "" }; | |
let duration = match self.response_type { | |
AuthorizationResponseType::Code => { | |
Clone::clone(&self.duration).or(Some(AuthorizationDuration::Temporary)) | |
} | |
_ => None, | |
}; | |
let origin = Clone::clone(self.origin.as_ref().unwrap_or( | |
&String::from("localhost"), | |
)); | |
let redirect_uri = Clone::clone(self.redirect_uri.as_ref().ok_or(String::from( | |
"redirect_uri must be initialized", | |
))?); | |
let response_type = Clone::clone(&self.response_type); | |
let scope = Clone::clone(self.scope.as_ref().unwrap_or( | |
&[Scope::Identity].iter().cloned().collect(), | |
)); | |
let state = Clone::clone(self.state.as_ref().ok_or( | |
String::from("state must be initialized"), | |
)?); | |
let query_parameters = serde_urlencoded::to_string(AuthorizationUrlQueryParameters { | |
client_id: client_id, | |
duration: duration, | |
redirect_uri: redirect_uri, | |
response_type: response_type, | |
scope: scope, | |
state: state, | |
}).unwrap(); | |
Ok(format!( | |
"{}/api/v1/authorize{}?{}", | |
origin, | |
compact, | |
query_parameters | |
)) | |
} | |
} | |
// ... | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
#[test] | |
fn builds_valid_code_authorization_urls() { | |
let mut builder = Client::code_authorization_url_builder() | |
.client_id(String::from("abc123")) | |
.redirect_uri(String::from("localhost")) | |
.scope( | |
[Scope::Identity, Scope::Subscribe] | |
.iter() | |
.cloned() | |
.collect::<HashSet<Scope>>(), | |
) | |
.state(String::from("random_state_123")); | |
let expected = Ok(String::from( | |
"https://localhost/api/v1/authorize\ | |
?client_id=abc123\ | |
&duration=temporary\ | |
&redirect_uri=localhost\ | |
&response_type=code\ | |
&scope=*\ | |
&state=random_state_123", | |
)); | |
let actual = builder.build(); | |
assert_eq!(expected, actual); | |
// changes to the builder values and more asserts here | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've included the error below. I've removed irrelevant code, so the line numbers are different. Line 256 in the error is line 128 in the gist above.