Merge branch 'syntex' into next

This commit is contained in:
Sebastian Thiel
2015-06-18 18:11:48 +02:00
10 changed files with 158 additions and 67 deletions

View File

@@ -1,6 +1,7 @@
language: rust
sudo: required
rust:
- stable
- nightly
before_script:
- pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH

View File

@@ -8,6 +8,7 @@ description = "A partial oauth2 implementation, providing the 'device' authoriza
documentation = "http://byron.github.io/yup-oauth2"
keywords = ["google", "oauth", "v2"]
license = "MIT"
build = "build.rs"
[dependencies]
chrono = "*"
@@ -18,7 +19,16 @@ url = "*"
hyper = ">= 0.5.0"
itertools = "*"
serde = "*"
serde_macros = "*"
serde_macros = { version = "*", optional = true }
[features]
default = ["with_syntex"]
nightly = ["serde_macros"]
with_syntex = ["serde_codegen", "syntex"]
[build-dependencies]
syntex = { version = "*", optional = true }
serde_codegen = { version = "*", optional = true }
[dev-dependencies]
getopts = "*"

11
Makefile Normal file
View File

@@ -0,0 +1,11 @@
.PHONY = nightly
help:
$(info -- Targets -- )
$(info )
$(info nightly - run cargo with nightly configuration, set ARGS to something like 'build'. rustc must be set to nightly)
$(info _____________Note that for using stable, you can use cargo directly)
$(info )
nightly:
cargo $(ARGS) --no-default-features --features=nightly

28
build.rs Normal file
View File

@@ -0,0 +1,28 @@
#[cfg(feature = "with_syntex")]
mod inner {
extern crate syntex;
extern crate serde_codegen;
use std::env;
use std::path::Path;
pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let src = Path::new("src/lib.rs.in");
let dst = Path::new(&out_dir).join("lib.rs");
let mut registry = syntex::Registry::new();
serde_codegen::register(&mut registry);
registry.expand("yup-oauth2", &src, &dst).unwrap();
}
}
#[cfg(not(feature = "with_syntex"))]
mod inner {
pub fn main() {}
}
pub fn main() {
inner::main()
}

View File

@@ -1,5 +1,3 @@
#![feature(collections, exit_status)]
#![allow(deprecated)]
extern crate yup_oauth2 as oauth2;
extern crate yup_hyper_mock as mock;
extern crate hyper;
@@ -17,15 +15,17 @@ use time::Duration;
use std::thread::sleep_ms;
fn usage(program: &str, opts: &Options, err: Option<Fail>) {
fn usage(program: &str, opts: &Options, err: Option<Fail>) -> ! {
if err.is_some() {
println!("{}", err.unwrap());
env::set_exit_status(1);
std::process::exit(1);
}
println!("{}", opts.short_usage(program) + " SCOPE [SCOPE ...]");
println!("{}", opts.usage("A program to authenticate against oauthv2 services.\n\
See https://developers.google.com/youtube/registering_an_application\n\
and https://developers.google.com/youtube/v3/guides/authentication#devices"));
std::process::exit(0);
}
fn main() {
@@ -36,18 +36,16 @@ fn main() {
opts.opt("c", "id", "oauthv2 ID of your application", "CLIENT_ID", HasArg::Yes, Occur::Req)
.opt("s", "secret", "oauthv2 secret of your application", "CLIENT_SECRET", HasArg::Yes, Occur::Req);
let m = match opts.parse(args.tail()) {
let m = match opts.parse(&args[1..]) {
Ok(m) => m,
Err(e) => {
usage(&prog, &opts, Some(e));
return
}
};
if m.free.len() == 0 {
let msg = Fail::ArgumentMissing("you must provide one or more authorization scopes as free options".to_string());
usage(&prog, &opts, Some(msg));
return
}
let secret = oauth2::ApplicationSecret {
@@ -93,7 +91,7 @@ fn main() {
},
Err(err) => {
println!("Access token wasn't obtained: {}", err);
env::set_exit_status(10);
std::process::exit(10);
}
}
}

View File

@@ -339,9 +339,14 @@ pub mod tests {
use std::default::Default;
use time::Duration;
use hyper;
use yup_hyper_mock::{SequentialConnector, MockStream};
mock_connector_in_order!(MockGoogleAuth {
"HTTP/1.1 200 OK\r\n\
pub struct MockGoogleAuth(SequentialConnector);
impl Default for MockGoogleAuth {
fn default() -> MockGoogleAuth {
let mut c = MockGoogleAuth(Default::default());
c.0.content.push("HTTP/1.1 200 OK\r\n\
Server: BOGUS\r\n\
\r\n\
{\r\n\
@@ -350,23 +355,38 @@ pub mod tests {
\"verification_url\" : \"http://www.google.com/device\",\r\n\
\"expires_in\" : 1800,\r\n\
\"interval\" : 0\r\n\
}"
"HTTP/1.1 200 OK\r\n\
Server: BOGUS\r\n\
\r\n\
{\r\n\
\"error\" : \"authorization_pending\"\r\n\
}"
"HTTP/1.1 200 OK\r\n\
Server: BOGUS\r\n\
\r\n\
{\r\n\
\"access_token\":\"1/fFAGRNJru1FTz70BzhT3Zg\",\r\n\
\"expires_in\":3920,\r\n\
\"token_type\":\"Bearer\",\r\n\
\"refresh_token\":\"1/6BMfW9j53gdGImsixUH6kU5RsR4zwI9lUVX-tqf8JXQ\"\r\n\
}"
});
}".to_string());
c.0.content.push("HTTP/1.1 200 OK\r\n\
Server: BOGUS\r\n\
\r\n\
{\r\n\
\"error\" : \"authorization_pending\"\r\n\
}".to_string());
c.0.content.push("HTTP/1.1 200 OK\r\n\
Server: BOGUS\r\n\
\r\n\
{\r\n\
\"access_token\":\"1/fFAGRNJru1FTz70BzhT3Zg\",\r\n\
\"expires_in\":3920,\r\n\
\"token_type\":\"Bearer\",\r\n\
\"refresh_token\":\"1/6BMfW9j53gdGImsixUH6kU5RsR4zwI9lUVX-tqf8JXQ\"\r\n\
}".to_string());
c
}
}
impl hyper::net::NetworkConnector for MockGoogleAuth {
type Stream = MockStream;
fn connect(&self, host: &str, port: u16, scheme: &str) -> ::hyper::Result<MockStream> {
self.0.connect(host, port, scheme)
}
fn set_ssl_verifier(&mut self, _: hyper::net::ContextVerifier) {}
}
#[test]
fn working_flow() {

View File

@@ -446,8 +446,8 @@ pub trait AuthenticatorDelegate {
/// * Will be called exactly once, provided we didn't abort during `request_code` phase.
/// * Will only be called if the Authenticator's flow_type is `FlowType::Device`.
fn present_user_code(&mut self, pi: &PollInformation) {
println!{"Please enter {} at {} and grant access to this application",
pi.user_code, pi.verification_url}
println!("Please enter {} at {} and grant access to this application",
pi.user_code, pi.verification_url);
println!("Do not close this application until you either denied or granted access.");
println!("You have time until {}.", pi.expires_at.with_timezone(&Local));
}

View File

@@ -13,8 +13,8 @@
//! The returned `Token` should be stored permanently to authorize future API requests.
//!
//! ```test_harness,no_run
//! #![feature(custom_derive, plugin)]
//! #![plugin(serde_macros)]
//! #![cfg_attr(feature = "nightly", feature(custom_derive, custom_attribute, plugin))]
//! #![cfg_attr(feature = "nightly", plugin(serde_macros))]
//! extern crate hyper;
//! extern crate yup_oauth2 as oauth2;
//! extern crate serde;
@@ -60,30 +60,11 @@
//! };
//! # }
//! ```
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate chrono;
#![cfg_attr(feature = "nightly", feature(custom_derive, custom_attribute, plugin))]
#![cfg_attr(feature = "nightly", plugin(serde_macros))]
#[macro_use]
extern crate hyper;
#[macro_use]
extern crate log;
#[cfg(test)] #[macro_use]
extern crate yup_hyper_mock as hyper_mock;
extern crate mime;
extern crate url;
extern crate time;
extern crate itertools;
extern crate serde;
#[cfg(feature = "nightly")]
include!("lib.rs.in");
mod device;
mod refresh;
mod common;
mod helper;
pub use device::{DeviceFlow, PollInformation, PollError};
pub use refresh::{RefreshFlow, RefreshResult};
pub use common::{Token, FlowType, ApplicationSecret, ConsoleApplicationSecret, Scheme, TokenType};
pub use helper::{TokenStorage, NullStorage, MemoryStorage, Authenticator,
AuthenticatorDelegate, Retry, DefaultAuthenticatorDelegate, GetToken};
#[cfg(feature = "with_syntex")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));

24
src/lib.rs.in Normal file
View File

@@ -0,0 +1,24 @@
extern crate serde;
extern crate chrono;
extern crate hyper;
#[macro_use] #[cfg(test)]
extern crate log;
#[macro_use] #[cfg(test)]
extern crate yup_hyper_mock;
extern crate mime;
extern crate url;
extern crate time;
extern crate itertools;
mod device;
mod refresh;
mod common;
mod helper;
pub use device::{DeviceFlow, PollInformation, PollError};
pub use refresh::{RefreshFlow, RefreshResult};
pub use common::{Token, FlowType, ApplicationSecret, ConsoleApplicationSecret, Scheme, TokenType};
pub use helper::{TokenStorage, NullStorage, MemoryStorage, Authenticator,
AuthenticatorDelegate, Retry, DefaultAuthenticatorDelegate, GetToken};

View File

@@ -123,17 +123,35 @@ mod tests {
use std::default::Default;
use super::*;
use super::super::FlowType;
use yup_hyper_mock::{MockStream, SequentialConnector};
mock_connector_in_order!(MockGoogleRefresh {
"HTTP/1.1 200 OK\r\n\
Server: BOGUS\r\n\
\r\n\
{\r\n\
\"access_token\":\"1/fFAGRNJru1FTz70BzhT3Zg\",\r\n\
\"expires_in\":3920,\r\n\
\"token_type\":\"Bearer\"\r\n\
}"
});
struct MockGoogleRefresh(SequentialConnector);
impl Default for MockGoogleRefresh {
fn default() -> MockGoogleRefresh {
let mut c = MockGoogleRefresh(Default::default());
c.0.content.push("HTTP/1.1 200 OK\r\n\
Server: BOGUS\r\n\
\r\n\
{\r\n\
\"access_token\":\"1/fFAGRNJru1FTz70BzhT3Zg\",\r\n\
\"expires_in\":3920,\r\n\
\"token_type\":\"Bearer\"\r\n\
}".to_string());
c
}
}
impl hyper::net::NetworkConnector for MockGoogleRefresh {
type Stream = MockStream;
fn connect(&self, host: &str, port: u16, scheme: &str) -> ::hyper::Result<MockStream> {
self.0.connect(host, port, scheme)
}
fn set_ssl_verifier(&mut self, _: hyper::net::ContextVerifier) {}
}
#[test]
fn refresh_flow() {