Support dynamic providers

This commit is contained in:
Matthew Scheirer 2017-08-18 18:55:13 -04:00
parent 2d524faf92
commit 179532e061
3 changed files with 31 additions and 29 deletions

View File

@ -5,8 +5,6 @@ mod error;
pub mod response; pub mod response;
pub use self::error::ClientError; pub use self::error::ClientError;
use std::marker::PhantomData;
use hyper::{self, header, mime}; use hyper::{self, header, mime};
use serde_json::{self, Value}; use serde_json::{self, Value};
use url::Url; use url::Url;
@ -29,7 +27,7 @@ pub struct Client<P: Provider> {
/// Redirect URI. /// Redirect URI.
pub redirect_uri: Option<String>, pub redirect_uri: Option<String>,
provider: PhantomData<P>, provider: P,
} }
impl<P: Provider> Client<P> { impl<P: Provider> Client<P> {
@ -52,7 +50,7 @@ impl<P: Provider> Client<P> {
client_id: client_id, client_id: client_id,
client_secret: client_secret, client_secret: client_secret,
redirect_uri: redirect_uri, redirect_uri: redirect_uri,
provider: PhantomData, provider: P::default(),
} }
} }
@ -79,7 +77,7 @@ impl<P: Provider> Client<P> {
/// ``` /// ```
pub fn auth_uri(&self, scope: Option<&str>, state: Option<&str>) -> Result<Url, ClientError> pub fn auth_uri(&self, scope: Option<&str>, state: Option<&str>) -> Result<Url, ClientError>
{ {
let mut uri = Url::parse(P::auth_uri())?; let mut uri = Url::parse(self.provider.auth_uri())?;
{ {
let mut query = uri.query_pairs_mut(); let mut query = uri.query_pairs_mut();
@ -122,7 +120,7 @@ impl<P: Provider> Client<P> {
]); ]);
let body = body.finish(); let body = body.finish();
let request = http_client.post(P::token_uri()) let request = http_client.post(self.provider.token_uri())
.header(auth_header) .header(auth_header)
.header(accept_header) .header(accept_header)
.header(header::ContentType::form_url_encoded()) .header(header::ContentType::form_url_encoded())
@ -201,12 +199,13 @@ mod tests {
use provider::Provider; use provider::Provider;
use super::Client; use super::Client;
#[derive(Default)]
struct Test; struct Test;
impl Provider for Test { impl Provider for Test {
type Lifetime = Static; type Lifetime = Static;
type Token = Bearer<Static>; type Token = Bearer<Static>;
fn auth_uri() -> &'static str { "http://example.com/oauth2/auth" } fn auth_uri(&self) -> &'static str { "http://example.com/oauth2/auth" }
fn token_uri() -> &'static str { "http://example.com/oauth2/token" } fn token_uri(&self) -> &'static str { "http://example.com/oauth2/token" }
} }
#[test] #[test]

View File

@ -3,7 +3,7 @@
use token::{Token, Lifetime, Bearer, Static, Refresh}; use token::{Token, Lifetime, Bearer, Static, Refresh};
/// OAuth 2.0 providers. /// OAuth 2.0 providers.
pub trait Provider { pub trait Provider: Default {
/// The lifetime of tokens issued by the provider. /// The lifetime of tokens issued by the provider.
type Lifetime: Lifetime; type Lifetime: Lifetime;
@ -15,14 +15,14 @@ pub trait Provider {
/// See [RFC 6749, section 3.1](http://tools.ietf.org/html/rfc6749#section-3.1). /// See [RFC 6749, section 3.1](http://tools.ietf.org/html/rfc6749#section-3.1).
/// ///
/// Note: likely to become an associated constant. /// Note: likely to become an associated constant.
fn auth_uri() -> &'static str; fn auth_uri(&self) -> &str;
/// The token endpoint URI. /// The token endpoint URI.
/// ///
/// See [RFC 6749, section 3.2](http://tools.ietf.org/html/rfc6749#section-3.2). /// See [RFC 6749, section 3.2](http://tools.ietf.org/html/rfc6749#section-3.2).
/// ///
/// Note: likely to become an associated constant. /// Note: likely to become an associated constant.
fn token_uri() -> &'static str; fn token_uri(&self) -> &str;
/// Provider requires credentials via request body. /// Provider requires credentials via request body.
/// ///
@ -62,49 +62,49 @@ pub mod google {
/// ///
/// See [Using OAuth 2.0 for Web Server /// See [Using OAuth 2.0 for Web Server
/// Applications](https://developers.google.com/identity/protocols/OAuth2WebServer). /// Applications](https://developers.google.com/identity/protocols/OAuth2WebServer).
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub struct Web; pub struct Web;
impl Provider for Web { impl Provider for Web {
type Lifetime = Expiring; type Lifetime = Expiring;
type Token = Bearer<Expiring>; type Token = Bearer<Expiring>;
fn auth_uri() -> &'static str { "https://accounts.google.com/o/oauth2/v2/auth" } fn auth_uri(&self) -> &'static str { "https://accounts.google.com/o/oauth2/v2/auth" }
fn token_uri() -> &'static str { "https://www.googleapis.com/oauth2/v4/token" } fn token_uri(&self) -> &'static str { "https://www.googleapis.com/oauth2/v4/token" }
} }
/// Google OAuth 2.0 provider for installed applications. /// Google OAuth 2.0 provider for installed applications.
/// ///
/// See [Using OAuth 2.0 for Installed /// See [Using OAuth 2.0 for Installed
/// Applications](https://developers.google.com/identity/protocols/OAuth2InstalledApp). /// Applications](https://developers.google.com/identity/protocols/OAuth2InstalledApp).
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub struct Installed; pub struct Installed;
impl Provider for Installed { impl Provider for Installed {
type Lifetime = Refresh; type Lifetime = Refresh;
type Token = Bearer<Refresh>; type Token = Bearer<Refresh>;
fn auth_uri() -> &'static str { "https://accounts.google.com/o/oauth2/v2/auth" } fn auth_uri(&self) -> &'static str { "https://accounts.google.com/o/oauth2/v2/auth" }
fn token_uri() -> &'static str { "https://www.googleapis.com/oauth2/v4/token" } fn token_uri(&self) -> &'static str { "https://www.googleapis.com/oauth2/v4/token" }
} }
} }
/// GitHub OAuth 2.0 provider. /// GitHub OAuth 2.0 provider.
/// ///
/// See [OAuth, GitHub Developer Guide](https://developer.github.com/v3/oauth/). /// See [OAuth, GitHub Developer Guide](https://developer.github.com/v3/oauth/).
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub struct GitHub; pub struct GitHub;
impl Provider for GitHub { impl Provider for GitHub {
type Lifetime = Static; type Lifetime = Static;
type Token = Bearer<Static>; type Token = Bearer<Static>;
fn auth_uri() -> &'static str { "https://github.com/login/oauth/authorize" } fn auth_uri(&self) -> &'static str { "https://github.com/login/oauth/authorize" }
fn token_uri() -> &'static str { "https://github.com/login/oauth/access_token" } fn token_uri(&self) -> &'static str { "https://github.com/login/oauth/access_token" }
} }
/// Imgur OAuth 2.0 provider. /// Imgur OAuth 2.0 provider.
/// ///
/// See [OAuth 2.0, Imgur](https://api.imgur.com/oauth2). /// See [OAuth 2.0, Imgur](https://api.imgur.com/oauth2).
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub struct Imgur; pub struct Imgur;
impl Provider for Imgur { impl Provider for Imgur {
type Lifetime = Refresh; type Lifetime = Refresh;
type Token = Bearer<Refresh>; type Token = Bearer<Refresh>;
fn auth_uri() -> &'static str { "https://api.imgur.com/oauth2/authorize" } fn auth_uri(&self) -> &'static str { "https://api.imgur.com/oauth2/authorize" }
fn token_uri() -> &'static str { "https://api.imgur.com/oauth2/token" } fn token_uri(&self) -> &'static str { "https://api.imgur.com/oauth2/token" }
} }

View File

@ -12,28 +12,31 @@ mod provider {
use inth_oauth2::token::{Bearer, Static, Expiring, Refresh}; use inth_oauth2::token::{Bearer, Static, Expiring, Refresh};
use inth_oauth2::provider::Provider; use inth_oauth2::provider::Provider;
#[derive(Default)]
pub struct BearerStatic; pub struct BearerStatic;
impl Provider for BearerStatic { impl Provider for BearerStatic {
type Lifetime = Static; type Lifetime = Static;
type Token = Bearer<Static>; type Token = Bearer<Static>;
fn auth_uri() -> &'static str { "https://example.com/oauth/auth" } fn auth_uri(&self) -> &'static str { "https://example.com/oauth/auth" }
fn token_uri() -> &'static str { "https://example.com/oauth/token" } fn token_uri(&self) -> &'static str { "https://example.com/oauth/token" }
} }
#[derive(Default)]
pub struct BearerExpiring; pub struct BearerExpiring;
impl Provider for BearerExpiring { impl Provider for BearerExpiring {
type Lifetime = Expiring; type Lifetime = Expiring;
type Token = Bearer<Expiring>; type Token = Bearer<Expiring>;
fn auth_uri() -> &'static str { "https://example.com/oauth/auth" } fn auth_uri(&self) -> &'static str { "https://example.com/oauth/auth" }
fn token_uri() -> &'static str { "https://example.com/oauth/token" } fn token_uri(&self) -> &'static str { "https://example.com/oauth/token" }
} }
#[derive(Default)]
pub struct BearerRefresh; pub struct BearerRefresh;
impl Provider for BearerRefresh { impl Provider for BearerRefresh {
type Lifetime = Refresh; type Lifetime = Refresh;
type Token = Bearer<Refresh>; type Token = Bearer<Refresh>;
fn auth_uri() -> &'static str { "https://example.com/oauth/auth" } fn auth_uri(&self) -> &'static str { "https://example.com/oauth/auth" }
fn token_uri() -> &'static str { "https://example.com/oauth/token" } fn token_uri(&self) -> &'static str { "https://example.com/oauth/token" }
} }
} }