The package rpms/rust-yup-oauth2.git has added or updated architecture specific content in
its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/rust-yup-oauth2.git/commit/?id=d6....
Change:
+ExclusiveArch: %{rust_arches}
Thanks.
Full change:
============
commit d65b4f05199c1f5834d924a2b2b2f27def84f298
Author: Igor Gnatenko <ignatenkobrain(a)fedoraproject.org>
Date: Fri Jul 27 00:26:35 2018 +0200
initial import
Signed-off-by: Igor Gnatenko <ignatenkobrain(a)fedoraproject.org>
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..00851d1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/yup-oauth2-1.0.7.crate
diff --git a/0001-deps-update-chrono-to-0.4.patch b/0001-deps-update-chrono-to-0.4.patch
new file mode 100644
index 0000000..2d1853a
--- /dev/null
+++ b/0001-deps-update-chrono-to-0.4.patch
@@ -0,0 +1,166 @@
+From e634d3f139dd314afa96d9f0365d981a6bb01a8d Mon Sep 17 00:00:00 2001
+From: Igor Gnatenko <i.gnatenko.brain(a)gmail.com>
+Date: Wed, 25 Jul 2018 22:44:32 +0200
+Subject: [PATCH 1/4] deps: update chrono to 0.4
+
+Signed-off-by: Igor Gnatenko <i.gnatenko.brain(a)gmail.com>
+---
+ src/authenticator_delegate.rs | 8 ++++----
+ src/device.rs | 6 +++---
+ src/refresh.rs | 4 ++--
+ src/service_account.rs | 4 ++--
+ src/types.rs | 10 +++++-----
+ 5 files changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/src/authenticator_delegate.rs b/src/authenticator_delegate.rs
+index 381ec15..e46c5c0 100644
+--- a/src/authenticator_delegate.rs
++++ b/src/authenticator_delegate.rs
+@@ -7,7 +7,7 @@ use std::error::Error;
+ use authenticator::Retry;
+ use types::RequestError;
+
+-use chrono::{DateTime, Local, UTC};
++use chrono::{DateTime, Local, Utc};
+ use std::time::Duration;
+
+ /// Contains state of pending authentication requests
+@@ -20,7 +20,7 @@ pub struct PollInformation {
+
+ /// The `user_code` expires at the given time
+ /// It's the time the user has left to authenticate your application
+- pub expires_at: DateTime<UTC>,
++ pub expires_at: DateTime<Utc>,
+ /// The interval in which we may poll for a status change
+ /// The server responds with errors of we poll too fast.
+ pub interval: Duration,
+@@ -38,7 +38,7 @@ pub enum PollError {
+ /// Connection failure - retry if you think it's worth it
+ HttpError(hyper::Error),
+ /// indicates we are expired, including the expiration date
+- Expired(DateTime<UTC>),
++ Expired(DateTime<Utc>),
+ /// Indicates that the user declined access. String is server response
+ AccessDenied,
+ }
+@@ -83,7 +83,7 @@ pub trait AuthenticatorDelegate {
+ /// Called if the request code is expired. You will have to start over in this
case.
+ /// This will be the last call the delegate receives.
+ /// Given `DateTime` is the expiration date
+- fn expired(&mut self, &DateTime<UTC>) {}
++ fn expired(&mut self, &DateTime<Utc>) {}
+
+ /// Called if the user denied access. You would have to start over.
+ /// This will be the last call the delegate receives.
+diff --git a/src/device.rs b/src/device.rs
+index c89cd47..f61ca50 100644
+--- a/src/device.rs
++++ b/src/device.rs
+@@ -7,7 +7,7 @@ use hyper::header::ContentType;
+ use url::form_urlencoded;
+ use itertools::Itertools;
+ use serde_json as json;
+-use chrono::{self, UTC};
++use chrono::{self, Utc};
+ use std::borrow::BorrowMut;
+ use std::io::Read;
+ use std::i64;
+@@ -133,7 +133,7 @@ impl<C> DeviceFlow<C>
+ let pi = PollInformation {
+ user_code: decoded.user_code,
+ verification_url: decoded.verification_url,
+- expires_at: UTC::now() +
chrono::Duration::seconds(decoded.expires_in),
++ expires_at: Utc::now() +
chrono::Duration::seconds(decoded.expires_in),
+ interval: Duration::from_secs(i64::abs(decoded.interval) as u64),
+ };
+ self.state = Some(DeviceFlowState::Pending(pi.clone()));
+@@ -175,7 +175,7 @@ impl<C> DeviceFlow<C>
+ _ => panic!("You have to call request_code() beforehand"),
+ };
+
+- if pi.expires_at <= UTC::now() {
++ if pi.expires_at <= Utc::now() {
+ self.error = Some(PollError::Expired(pi.expires_at));
+ self.state = Some(DeviceFlowState::Error);
+ return Err(&self.error.as_ref().unwrap());
+diff --git a/src/refresh.rs b/src/refresh.rs
+index b980021..f68dd54 100644
+--- a/src/refresh.rs
++++ b/src/refresh.rs
+@@ -1,6 +1,6 @@
+ use types::{ApplicationSecret, FlowType, JsonError};
+
+-use chrono::UTC;
++use chrono::Utc;
+ use hyper;
+ use hyper::header::ContentType;
+ use serde_json as json;
+@@ -107,7 +107,7 @@ impl<C> RefreshFlow<C>
+ token_type: t.token_type,
+ refresh_token: refresh_token.to_string(),
+ expires_in: None,
+- expires_in_timestamp: Some(UTC::now().timestamp() + t.expires_in),
++ expires_in_timestamp: Some(Utc::now().timestamp() + t.expires_in),
+ });
+
+ &self.result
+diff --git a/src/service_account.rs b/src/service_account.rs
+index 082b58d..80a5bf3 100644
+--- a/src/service_account.rs
++++ b/src/service_account.rs
+@@ -133,7 +133,7 @@ fn init_claims_from_key<'a, I, T>(key:
&ServiceAccountKey, scopes: I) -> Claims
+ where T: AsRef<str> + 'a,
+ I: IntoIterator<Item = &'a T>
+ {
+- let iat = chrono::UTC::now().timestamp();
++ let iat = chrono::Utc::now().timestamp();
+ let expiry = iat + 3600 - 5; // Max validity is 1h.
+
+ let mut scopes_string = scopes.into_iter().fold(String::new(), |mut acc, sc| {
+@@ -179,7 +179,7 @@ struct TokenResponse {
+
+ impl TokenResponse {
+ fn to_oauth_token(self) -> Token {
+- let expires_ts = chrono::UTC::now().timestamp() + self.expires_in.unwrap_or(0);
++ let expires_ts = chrono::Utc::now().timestamp() + self.expires_in.unwrap_or(0);
+
+ Token {
+ access_token: self.access_token.unwrap(),
+diff --git a/src/types.rs b/src/types.rs
+index e924d69..0f905f4 100644
+--- a/src/types.rs
++++ b/src/types.rs
+@@ -1,4 +1,4 @@
+-use chrono::{DateTime, UTC, TimeZone};
++use chrono::{DateTime, Utc, TimeZone};
+ use std::error::Error;
+ use std::fmt;
+ use std::str::FromStr;
+@@ -203,12 +203,12 @@ impl Token {
+ if self.access_token.len() == 0 {
+ panic!("called expired() on unset token");
+ }
+- self.expiry_date() <= UTC::now()
++ self.expiry_date() <= Utc::now()
+ }
+
+ /// Returns a DateTime object representing our expiry date.
+- pub fn expiry_date(&self) -> DateTime<UTC> {
+- UTC.timestamp(self.expires_in_timestamp
++ pub fn expiry_date(&self) -> DateTime<Utc> {
++ Utc.timestamp(self.expires_in_timestamp
+ .expect("Tokens without an absolute expiry are
invalid"),
+ 0)
+ }
+@@ -220,7 +220,7 @@ impl Token {
+ return self;
+ }
+
+- self.expires_in_timestamp = Some(UTC::now().timestamp() +
self.expires_in.unwrap());
++ self.expires_in_timestamp = Some(Utc::now().timestamp() +
self.expires_in.unwrap());
+ self.expires_in = None;
+ self
+ }
+--
+2.18.0
+
diff --git a/0001-docs-update-the-example-to-use-the-hyper-tls-connect.patch
b/0001-docs-update-the-example-to-use-the-hyper-tls-connect.patch
new file mode 100644
index 0000000..814709b
--- /dev/null
+++ b/0001-docs-update-the-example-to-use-the-hyper-tls-connect.patch
@@ -0,0 +1,43 @@
+From f529404ccb097ca0678519e4ef3abd8532ad44d9 Mon Sep 17 00:00:00 2001
+From: Mark Catley <mark(a)catley.net.nz>
+Date: Mon, 7 May 2018 12:09:47 +1200
+Subject: [PATCH] docs: update the example to use the hyper tls connector
+
+This is required to use tls apis hyper 0.10. The example uses a tls api, so this is
required.
+
+Closes #52
+---
+ src/lib.rs | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/src/lib.rs b/src/lib.rs
+index 2222c56..9b53009 100644
+--- a/src/lib.rs
++++ b/src/lib.rs
+@@ -39,6 +39,7 @@
+ //! extern crate serde_derive;
+ //!
+ //! extern crate hyper;
++//! extern crate hyper_rustls;
+ //! extern crate yup_oauth2 as oauth2;
+ //! extern crate serde;
+ //! extern crate serde_json;
+@@ -46,12 +47,14 @@
+ //! use oauth2::{Authenticator, DefaultAuthenticatorDelegate, PollInformation,
ConsoleApplicationSecret, MemoryStorage, GetToken};
+ //! use serde_json as json;
+ //! use std::default::Default;
++//! use hyper::{Client, net::HttpsConnector};
++//! use hyper_rustls::TlsClient;
+ //! # const SECRET: &'static str =
"{\"installed\":{\"auth_uri\":\"https://accounts.google.com/o/oauth2/auth\",\"client_secret\":\"UqkDJd5RFwnHoiG5x5Rub8SI\",\"token_uri\":\"https://accounts.google.com/o/oauth2/token\",\"client_email\":\"\",\"redirect_uris\":[\"urn:ietf:wg:oauth:2.0:oob\",\"oob\"],\"client_x509_cert_url\":\"\",\"client_id\":\"14070749909-vgip2f1okm7bkvajhi9jugan6126io9v.apps.googleusercontent.com\",\"auth_provider_x509_cert_url\":\"https://www.googleapis.com/oauth2/v1/certs\"}}";
+ //!
+ //! # #[test] fn device() {
+ //! let secret =
json::from_str::<ConsoleApplicationSecret>(SECRET).unwrap().installed.unwrap();
+ //! let res = Authenticator::new(&secret, DefaultAuthenticatorDelegate,
+-//! hyper::Client::new(),
++//!
Client::with_connector(HttpsConnector::new(TlsClient::new())),
+ //! <MemoryStorage as Default>::default(), None)
+ //!
.token(&["https://www.googleapis.com/auth/youtube.upload"]);
+ //! match res {
+--
+2.18.0
+
diff --git a/0002-deps-update-url-to-1.patch b/0002-deps-update-url-to-1.patch
new file mode 100644
index 0000000..e19d626
--- /dev/null
+++ b/0002-deps-update-url-to-1.patch
@@ -0,0 +1,134 @@
+From 78cefeab474bb5ab503d6c10c697394e98032ebe Mon Sep 17 00:00:00 2001
+From: Igor Gnatenko <i.gnatenko.brain(a)gmail.com>
+Date: Wed, 25 Jul 2018 22:50:45 +0200
+Subject: [PATCH 2/4] deps: update url to 1
+
+Signed-off-by: Igor Gnatenko <i.gnatenko.brain(a)gmail.com>
+---
+ src/device.rs | 26 ++++++++++++++------------
+ src/installed.rs | 17 ++++++++---------
+ src/refresh.rs | 10 ++++++----
+ src/service_account.rs | 7 ++++---
+ 4 files changed, 32 insertions(+), 28 deletions(-)
+
+diff --git a/src/device.rs b/src/device.rs
+index f61ca50..da5090f 100644
+--- a/src/device.rs
++++ b/src/device.rs
+@@ -87,13 +87,14 @@ impl<C> DeviceFlow<C>
+
+ // note: cloned() shouldn't be needed, see issue
+ //
https://github.com/servo/rust-url/issues/81
+- let req = form_urlencoded::serialize(&[("client_id",
&self.application_secret.client_id),
+- ("scope",
+- &scopes.into_iter()
+- .map(|s| s.as_ref())
+- .intersperse(" ")
+- .collect::<String>()
+- )]);
++ let req = form_urlencoded::Serializer::new(String::new())
++ .extend_pairs(&[("client_id",
&self.application_secret.client_id),
++ ("scope", &scopes
++ .into_iter()
++ .map(|s| s.as_ref())
++ .intersperse(" ")
++ .collect::<String>())])
++ .finish();
+
+ // note: works around bug in rustlang
+ //
https://github.com/rust-lang/rust/issues/22252
+@@ -182,11 +183,12 @@ impl<C> DeviceFlow<C>
+ }
+
+ // We should be ready for a new request
+- let req = form_urlencoded::serialize(&[("client_id",
&self.application_secret.client_id[..]),
+- ("client_secret",
&self.application_secret.client_secret),
+- ("code",
&self.device_code),
+- ("grant_type",
+-
"http://oauth.net/grant_type/device/1.0")]);
++ let req = form_urlencoded::Serializer::new(String::new())
++ .extend_pairs(&[("client_id",
&self.application_secret.client_id[..]),
++ ("client_secret",
&self.application_secret.client_secret),
++ ("code", &self.device_code),
++ ("grant_type",
"http://oauth.net/grant_type/device/1.0")])
++ .finish();
+
+ let json_str: String = match self.client
+ .borrow_mut()
+diff --git a/src/installed.rs b/src/installed.rs
+index 300f84e..c3b6f3c 100644
+--- a/src/installed.rs
++++ b/src/installed.rs
+@@ -52,7 +52,7 @@ fn build_authentication_request_url<'a, T, I>(auth_uri:
&str,
+ format!("&client_id={}", client_id)]
+ .into_iter()
+ .fold(url, |mut u, param| {
+- u.push_str(&percent_encode(param.as_ref(), QUERY_ENCODE_SET));
++ u.push_str(&percent_encode(param.as_ref(),
QUERY_ENCODE_SET).to_string());
+ u
+ })
+ }
+@@ -221,14 +221,13 @@ impl<C> InstalledFlow<C>
+ Some(p) => redirect_uri = format!("http://localhost:{}", p),
+ }
+
+- let body = form_urlencoded::serialize(vec![("code".to_string(),
authcode.to_string()),
+- ("client_id".to_string(),
+- appsecret.client_id.clone()),
+-
("client_secret".to_string(),
+- appsecret.client_secret.clone()),
+-
("redirect_uri".to_string(), redirect_uri),
+- ("grant_type".to_string(),
+-
"authorization_code".to_string())]);
++ let body = form_urlencoded::Serializer::new(String::new())
++ .extend_pairs(vec![("code".to_string(), authcode.to_string()),
++ ("client_id".to_string(),
appsecret.client_id.clone()),
++ ("client_secret".to_string(),
appsecret.client_secret.clone()),
++ ("redirect_uri".to_string(), redirect_uri),
++ ("grant_type".to_string(),
"authorization_code".to_string())])
++ .finish();
+
+ let result: Result<client::Response, hyper::Error> = self.client
+ .borrow_mut()
+diff --git a/src/refresh.rs b/src/refresh.rs
+index f68dd54..883a59b 100644
+--- a/src/refresh.rs
++++ b/src/refresh.rs
+@@ -64,10 +64,12 @@ impl<C> RefreshFlow<C>
+ return &self.result;
+ }
+
+- let req = form_urlencoded::serialize(&[("client_id",
client_secret.client_id.as_ref()),
+- ("client_secret",
client_secret.client_secret.as_ref()),
+- ("refresh_token",
refresh_token),
+- ("grant_type",
"refresh_token")]);
++ let req = form_urlencoded::Serializer::new(String::new())
++ .extend_pairs(&[("client_id",
client_secret.client_id.as_ref()),
++ ("client_secret",
client_secret.client_secret.as_ref()),
++ ("refresh_token", refresh_token),
++ ("grant_type", "refresh_token")])
++ .finish();
+
+ let json_str: String = match self.client
+ .borrow_mut()
+diff --git a/src/service_account.rs b/src/service_account.rs
+index 80a5bf3..6fc0c10 100644
+--- a/src/service_account.rs
++++ b/src/service_account.rs
+@@ -220,9 +220,10 @@ impl<'a, C> ServiceAccountAccess<C>
+ let signed = try!(JWT::new(claims)
+ .sign(self.key.private_key.as_ref().unwrap()));
+
+- let body = form_urlencoded::serialize(vec![("grant_type".to_string(),
+- GRANT_TYPE.to_string()),
+- ("assertion".to_string(),
signed)]);
++ let body = form_urlencoded::Serializer::new(String::new())
++ .extend_pairs(vec![("grant_type".to_string(),
GRANT_TYPE.to_string()),
++ ("assertion".to_string(), signed)])
++ .finish();
+
+ let mut response = String::new();
+ let mut result = try!(self.client
+--
+2.18.0
+
diff --git a/0003-deps-hyper-rustls-hyper-native-tls.patch
b/0003-deps-hyper-rustls-hyper-native-tls.patch
new file mode 100644
index 0000000..045affb
--- /dev/null
+++ b/0003-deps-hyper-rustls-hyper-native-tls.patch
@@ -0,0 +1,78 @@
+From 9b5bbf5459625f410cba65387ba81c1d8e93883b Mon Sep 17 00:00:00 2001
+From: Igor Gnatenko <i.gnatenko.brain(a)gmail.com>
+Date: Wed, 25 Jul 2018 22:51:37 +0200
+Subject: [PATCH 3/4] =?UTF-8?q?deps:=20hyper-rustls=20=E2=86=92=20hyper-na?=
+ =?UTF-8?q?tive-tls?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Igor Gnatenko <i.gnatenko.brain(a)gmail.com>
+---
+ src/lib.rs | 8 ++++----
+ src/service_account.rs | 4 ++--
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/src/lib.rs b/src/lib.rs
+index 9b53009..c668199 100644
+--- a/src/lib.rs
++++ b/src/lib.rs
+@@ -39,7 +39,7 @@
+ //! extern crate serde_derive;
+ //!
+ //! extern crate hyper;
+-//! extern crate hyper_rustls;
++//! extern crate hyper_native_tls;
+ //! extern crate yup_oauth2 as oauth2;
+ //! extern crate serde;
+ //! extern crate serde_json;
+@@ -48,13 +48,13 @@
+ //! use serde_json as json;
+ //! use std::default::Default;
+ //! use hyper::{Client, net::HttpsConnector};
+-//! use hyper_rustls::TlsClient;
++//! use hyper_native_tls::NativeTlsClient;
+ //! # const SECRET: &'static str =
"{\"installed\":{\"auth_uri\":\"https://accounts.google.com/o/oauth2/auth\",\"client_secret\":\"UqkDJd5RFwnHoiG5x5Rub8SI\",\"token_uri\":\"https://accounts.google.com/o/oauth2/token\",\"client_email\":\"\",\"redirect_uris\":[\"urn:ietf:wg:oauth:2.0:oob\",\"oob\"],\"client_x509_cert_url\":\"\",\"client_id\":\"14070749909-vgip2f1okm7bkvajhi9jugan6126io9v.apps.googleusercontent.com\",\"auth_provider_x509_cert_url\":\"https://www.googleapis.com/oauth2/v1/certs\"}}";
+ //!
+ //! # #[test] fn device() {
+ //! let secret =
json::from_str::<ConsoleApplicationSecret>(SECRET).unwrap().installed.unwrap();
+ //! let res = Authenticator::new(&secret, DefaultAuthenticatorDelegate,
+-//!
Client::with_connector(HttpsConnector::new(TlsClient::new())),
++//!
Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap())),
+ //! <MemoryStorage as Default>::default(), None)
+ //!
.token(&["https://www.googleapis.com/auth/youtube.upload"]);
+ //! match res {
+@@ -77,7 +77,7 @@ extern crate serde_json;
+ extern crate base64;
+ extern crate chrono;
+ extern crate hyper;
+-extern crate hyper_rustls;
++extern crate hyper_native_tls;
+ extern crate rustls;
+
+ #[cfg(test)]
+diff --git a/src/service_account.rs b/src/service_account.rs
+index 6fc0c10..3b71b7b 100644
+--- a/src/service_account.rs
++++ b/src/service_account.rs
+@@ -283,7 +283,7 @@ mod tests {
+ use helper::service_account_key_from_file;
+ use hyper;
+ use hyper::net::HttpsConnector;
+- use hyper_rustls;
++ use hyper_native_tls::NativeTlsClient;
+ use authenticator::GetToken;
+
+ // This is a valid but deactivated key.
+@@ -294,7 +294,7 @@ mod tests {
+ #[allow(dead_code)]
+ fn test_service_account_e2e() {
+ let key =
service_account_key_from_file(&TEST_PRIVATE_KEY_PATH.to_string()).unwrap();
+- let client =
hyper::Client::with_connector(HttpsConnector::new(hyper_rustls::TlsClient::new()));
++ let client =
hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
+ let mut acc = ServiceAccountAccess::new(key, client);
+ println!("{:?}",
+
acc.token(vec![&"https://www.googleapis.com/auth/pubsub"])....);
+--
+2.18.0
+
diff --git a/0004-deps-rustls-openssl.patch b/0004-deps-rustls-openssl.patch
new file mode 100644
index 0000000..0f647cd
--- /dev/null
+++ b/0004-deps-rustls-openssl.patch
@@ -0,0 +1,97 @@
+From 3163be984d9a926f54900dd16b6fa3af5dbdfc6e Mon Sep 17 00:00:00 2001
+From: Igor Gnatenko <i.gnatenko.brain(a)gmail.com>
+Date: Wed, 25 Jul 2018 22:51:51 +0200
+Subject: [PATCH 4/4] =?UTF-8?q?deps:=20rustls=20=E2=86=92=20openssl?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Igor Gnatenko <i.gnatenko.brain(a)gmail.com>
+---
+ src/lib.rs | 2 +-
+ src/service_account.rs | 34 +++++++++++-----------------------
+ 2 files changed, 12 insertions(+), 24 deletions(-)
+
+diff --git a/src/lib.rs b/src/lib.rs
+index c668199..d542e25 100644
+--- a/src/lib.rs
++++ b/src/lib.rs
+@@ -78,7 +78,7 @@ extern crate base64;
+ extern crate chrono;
+ extern crate hyper;
+ extern crate hyper_native_tls;
+-extern crate rustls;
++extern crate openssl;
+
+ #[cfg(test)]
+ extern crate log;
+diff --git a/src/service_account.rs b/src/service_account.rs
+index 3b71b7b..21f1286 100644
+--- a/src/service_account.rs
++++ b/src/service_account.rs
+@@ -14,7 +14,7 @@
+ use std::borrow::BorrowMut;
+ use std::default::Default;
+ use std::error;
+-use std::io::{self, Read};
++use std::io::Read;
+ use std::result;
+ use std::str;
+
+@@ -25,9 +25,10 @@ use types::{StringError, Token};
+ use hyper::header;
+ use url::form_urlencoded;
+
+-use rustls::{self, PrivateKey};
+-use rustls::sign::{self, Signer};
+-use rustls::internal::pemfile;
++use openssl::sign::Signer;
++use openssl::hash::MessageDigest;
++use openssl::pkey::{PKey, Private};
++use openssl::rsa::Padding;
+
+ use base64;
+ use chrono;
+@@ -42,21 +43,9 @@ fn encode_base64<T: AsRef<[u8]>>(s: T) -> String {
+ base64::encode_config(s.as_ref(), base64::URL_SAFE)
+ }
+
+-fn decode_rsa_key(pem_pkcs8: &str) -> Result<PrivateKey,
Box<error::Error>> {
++fn decode_rsa_key(pem_pkcs8: &str) -> Result<PKey<Private>,
Box<error::Error>> {
+ let private = pem_pkcs8.to_string().replace("\\n",
"\n").into_bytes();
+- let mut private_reader: &[u8] = private.as_ref();
+- let private_keys = pemfile::pkcs8_private_keys(&mut private_reader);
+-
+- if let Ok(pk) = private_keys {
+- if pk.len() > 0 {
+- Ok(pk[0].clone())
+- } else {
+- Err(Box::new(io::Error::new(io::ErrorKind::InvalidInput,
+- "Not enough private keys in PEM")))
+- }
+- } else {
+- Err(Box::new(io::Error::new(io::ErrorKind::InvalidInput, "Error reading key
from PEM")))
+- }
++ Ok(try!(PKey::private_key_from_pem(&private)))
+ }
+
+ /// JSON schema of secret service account key. You can obtain the key from
+@@ -115,11 +104,10 @@ impl JWT {
+ fn sign(&self, private_key: &str) -> Result<String,
Box<error::Error>> {
+ let mut jwt_head = self.encode_claims();
+ let key = try!(decode_rsa_key(private_key));
+- let signer = try!(sign::RSASigner::new(&key)
+- .map_err(|_| io::Error::new(io::ErrorKind::Other, "Couldn't
initialize signer")));
+- let signature = try!(signer.sign(rustls::SignatureScheme::RSA_PKCS1_SHA256,
+- jwt_head.as_bytes())
+- .map_err(|_| io::Error::new(io::ErrorKind::Other, "Couldn't sign
claims")));
++ let mut signer = try!(Signer::new(MessageDigest::sha256(), &key));
++ try!(signer.set_rsa_padding(Padding::PKCS1));
++ try!(signer.update(jwt_head.as_bytes()));
++ let signature = try!(signer.sign_to_vec());
+ let signature_b64 = encode_base64(signature);
+
+ jwt_head.push_str(".");
+--
+2.18.0
+
diff --git a/rust-yup-oauth2.spec b/rust-yup-oauth2.spec
new file mode 100644
index 0000000..5e2b2d9
--- /dev/null
+++ b/rust-yup-oauth2.spec
@@ -0,0 +1,87 @@
+# Generated by rust2rpm
+# Not all deps are packaged
+%bcond_with check
+%global debug_package %{nil}
+
+%global crate yup-oauth2
+
+Name: rust-%{crate}
+Version: 1.0.7
+Release: 1%{?dist}
+Summary: Oauth2 implementation
+
+License: MIT or ASL 2.0
+URL:
https://crates.io/crates/yup-oauth2
+Source0:
https://crates.io/api/v1/crates/%{crate}/%{version}/download#/%{crate}-%{...
+# Initial patched metadata
+# * Bump deps to modern versions
+# * Switch to hyper-native-tls + openssl
+#
https://github.com/dermesser/yup-oauth2/pull/72
+Patch0: yup-oauth2-1.0.7-fix-metadata.diff
+#
https://github.com/dermesser/yup-oauth2/commit/f529404ccb097ca0678519e4ef...
+Patch0001: 0001-docs-update-the-example-to-use-the-hyper-tls-connect.patch
+Patch1001: 0001-deps-update-chrono-to-0.4.patch
+Patch1002: 0002-deps-update-url-to-1.patch
+Patch1003: 0003-deps-hyper-rustls-hyper-native-tls.patch
+Patch1004: 0004-deps-rustls-openssl.patch
+
+ExclusiveArch: %{rust_arches}
+
+BuildRequires: rust-packaging
+# [dependencies]
+BuildRequires: (crate(base64) >= 0.9.0 with crate(base64) < 0.10.0)
+BuildRequires: (crate(chrono) >= 0.4.0 with crate(chrono) < 0.5.0)
+BuildRequires: (crate(hyper) >= 0.10.2 with crate(hyper) < 0.11.0)
+BuildRequires: (crate(hyper-native-tls) >= 0.2.0 with crate(hyper-native-tls) <
0.3.0)
+BuildRequires: (crate(itertools) >= 0.7.0 with crate(itertools) < 0.8.0)
+BuildRequires: (crate(log) >= 0.3.0 with crate(log) < 0.4.0)
+BuildRequires: (crate(openssl) >= 0.10.0 with crate(openssl) < 0.11.0)
+BuildRequires: (crate(serde) >= 1.0.0 with crate(serde) < 2.0.0)
+BuildRequires: (crate(serde_derive) >= 1.0.0 with crate(serde_derive) < 2.0.0)
+BuildRequires: (crate(serde_json) >= 1.0.0 with crate(serde_json) < 2.0.0)
+BuildRequires: (crate(url) >= 1.0.0 with crate(url) < 2.0.0)
+%if %{with check}
+# [dev-dependencies]
+BuildRequires: (crate(getopts) >= 0.2.0 with crate(getopts) < 0.3.0)
+BuildRequires: (crate(open) >= 1.1.0 with crate(open) < 2.0.0)
+BuildRequires: (crate(yup-hyper-mock) >= 2.0.0 with crate(yup-hyper-mock) <
3.0.0)
+%endif
+
+%description
+%{summary}.
+
+%package devel
+Summary: %{summary}
+BuildArch: noarch
+
+%description devel
+An oauth2 implementation, providing the 'device', 'service account' and
+'installed' authorization flows.
+
+This package contains library source intended for building other packages
+which use %{crate} from crates.io.
+
+%prep
+%autosetup -n %{crate}-%{version} -p1
+%cargo_prep
+
+%build
+%cargo_build
+
+%install
+%cargo_install
+
+%if %{with check}
+%check
+%cargo_test
+%endif
+
+%files devel
+%license LICENSE-MIT LICENSE-APACHE
+%doc README.md changelog.md
+%{cargo_registry}/%{crate}-%{version}/
+%exclude %{cargo_registry}/%{crate}-%{version}/etc
+
+%changelog
+* Wed Jul 25 2018 Igor Gnatenko <i.gnatenko.brain(a)gmail.com> - 1.0.7-1
+- Initial package
diff --git a/sources b/sources
new file mode 100644
index 0000000..cf3eb8d
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+SHA512 (yup-oauth2-1.0.7.crate) =
042001b4f9b0eccd5c593160f7e78761d2b5e577d3bc1281b3fc37e9e311c4f029edfe20b90b81732acab90e593e7459320376176e8fadd3df8a39b182194525
diff --git a/yup-oauth2-1.0.7-fix-metadata.diff b/yup-oauth2-1.0.7-fix-metadata.diff
new file mode 100644
index 0000000..a58df6b
--- /dev/null
+++ b/yup-oauth2-1.0.7-fix-metadata.diff
@@ -0,0 +1,44 @@
+--- yup-oauth2-1.0.7/Cargo.toml 1970-01-01T01:00:00+01:00
++++ yup-oauth2-1.0.7/Cargo.toml 2018-07-25T23:00:37.371101+02:00
+@@ -20,25 +20,25 @@
+ license = "MIT OR Apache-2.0"
+ repository = "https://github.com/dermesser/yup-oauth2"
+ [dependencies.base64]
+-version = "0.5.2"
++version = "0.9"
+
+ [dependencies.chrono]
+-version = "0.2"
++version = "0.4"
+
+ [dependencies.hyper]
+ version = "0.10.2"
+
+-[dependencies.hyper-rustls]
+-version = "0.6.1"
++[dependencies.hyper-native-tls]
++version = "0.2"
+
+ [dependencies.itertools]
+-version = "0.4"
++version = "0.7"
+
+ [dependencies.log]
+ version = "0.3"
+
+-[dependencies.rustls]
+-version = "0.9.0"
++[dependencies.openssl]
++version = "0.10"
+
+ [dependencies.serde]
+ version = "1.0"
+@@ -50,7 +50,7 @@
+ version = "1.0"
+
+ [dependencies.url]
+-version = "0.5"
++version = "1"
+ [dev-dependencies.getopts]
+ version = "0.2"
+