diff options
author | Paul Woolcock <paul@woolcock.us> | 2018-08-24 23:39:27 -0400 |
---|---|---|
committer | Paul Woolcock <paul@woolcock.us> | 2018-08-25 09:13:34 -0400 |
commit | 1436c28e424bccdd8d2ae647c07d551cc858ebb6 (patch) | |
tree | c647d116965e89a0cd4bf321dbbebba565631b23 | |
parent | ae4d5dffe55564d4a93c9b7b9df2e5da052a1c9f (diff) |
duplicate the AppBuilder api in Registration
Closes #13
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | examples/register.rs | 25 | ||||
-rw-r--r-- | src/apps.rs | 22 | ||||
-rw-r--r-- | src/http_send.rs | 3 | ||||
-rw-r--r-- | src/lib.rs | 7 | ||||
-rw-r--r-- | src/registration.rs | 114 |
6 files changed, 106 insertions, 71 deletions
@@ -56,11 +56,9 @@ fn main() -> Result<(), Box<Error>> { } fn register() -> Result<Mastodon, Box<Error>> { - let mut app = App::builder(); - app.client_name("elefren-examples"); - let registration = Registration::new("https://mastodon.social") - .register(app)?; + .client_name("elefren-examples") + .register()?; let url = registration.authorize_url()?; println!("Click this link to authorize on Mastodon: {}", url); diff --git a/examples/register.rs b/examples/register.rs index 052cf71..82f6344 100644 --- a/examples/register.rs +++ b/examples/register.rs @@ -2,16 +2,11 @@ #![cfg_attr(not(feature = "toml"), allow(unused_imports))] extern crate elefren; -pub use self::elefren::{Data, MastodonClient}; +pub use self::elefren::prelude::*; +pub use self::elefren::apps::prelude::*; use std::{error::Error, io}; -use self::elefren::{ - apps::{App, Scopes}, - Mastodon, - Registration, -}; - #[cfg(feature = "toml")] use self::elefren::data::toml; @@ -34,20 +29,18 @@ pub fn get_mastodon_data() -> Result<Mastodon, Box<Error>> { #[cfg(feature = "toml")] pub fn register() -> Result<Mastodon, Box<Error>> { - let mut app = App::builder(); - app.client_name("elefren-examples") - .scopes(Scopes::All) - .website("https://github.com/pwoolcoc/elefren"); - let website = read_line("Please enter your mastodon instance url:")?; - let registration = Registration::new(website.trim()); - let registered = registration.register(app)?; - let url = registered.authorize_url()?; + let registration = Registration::new(website.trim()) + .client_name("elefren-examples") + .scopes(Scopes::All) + .website("https://github.com/pwoolcoc/elefren") + .register()?; + let url = registration.authorize_url()?; println!("Click this link to authorize on Mastodon: {}", url); let code = read_line("Paste the returned authorization code: ")?; - let mastodon = registered.complete(code)?; + let mastodon = registration.complete(code)?; // Save app data for using on the next run. toml::to_file(&*mastodon, "mastodon-data.toml")?; diff --git a/src/apps.rs b/src/apps.rs index cc70bc0..23dad7e 100644 --- a/src/apps.rs +++ b/src/apps.rs @@ -1,7 +1,5 @@ use std::{borrow::Cow, fmt}; -use try_from::TryInto; - use errors::{Error, Result}; /// Provides the necessary types for registering an App and getting the @@ -43,7 +41,7 @@ impl App { /// # Ok(()) /// # } /// ``` -#[derive(Debug, Default, Serialize)] +#[derive(Clone, Debug, Default, PartialEq, Serialize)] pub struct AppBuilder<'a> { client_name: Option<Cow<'a, str>>, redirect_uris: Option<Cow<'a, str>>, @@ -106,26 +104,10 @@ impl<'a> AppBuilder<'a> { } } -impl TryInto<App> for App { - type Err = Error; - - fn try_into(self) -> Result<App> { - Ok(self) - } -} - -impl<'a> TryInto<App> for AppBuilder<'a> { - type Err = Error; - - fn try_into(self) -> Result<App> { - Ok(self.build()?) - } -} - /// Permission scope of the application. /// [Details on what each permission provides][1] /// [1]: https://github.com/tootsuite/documentation/blob/master/Using-the-API/OAuth-details.md) -#[derive(Debug, Clone, Copy, Serialize)] +#[derive(Debug, Clone, Copy, PartialEq, Serialize)] pub enum Scopes { /// All Permissions, equivalent to `read write follow` #[serde(rename = "read write follow")] diff --git a/src/http_send.rs b/src/http_send.rs index fed76c6..56c69ef 100644 --- a/src/http_send.rs +++ b/src/http_send.rs @@ -1,7 +1,7 @@ use reqwest::{Client, Request, RequestBuilder, Response}; use Result; -pub trait HttpSend { +pub trait HttpSend: Clone { fn execute(&self, client: &Client, request: Request) -> Result<Response>; fn send(&self, client: &Client, builder: &mut RequestBuilder) -> Result<Response> { let request = builder.build()?; @@ -9,6 +9,7 @@ pub trait HttpSend { } } +#[derive(Clone)] pub struct HttpSender; impl HttpSend for HttpSender { @@ -11,10 +11,9 @@ //! # fn try() -> elefren::Result<()> { //! use elefren::{apps::prelude::*, prelude::*}; //! -//! let mut app = App::builder(); -//! app.client_name("elefren_test"); -//! -//! let registration = Registration::new("https://mastodon.social").register(app)?; +//! let registration = Registration::new("https://mastodon.social") +//! .client_name("elefren_test") +//! .register()?; //! let url = registration.authorize_url()?; //! // Here you now need to open the url in the browser //! // And handle a the redirect url coming back with the code. diff --git a/src/registration.rs b/src/registration.rs index 1a1249f..6a6ab2b 100644 --- a/src/registration.rs +++ b/src/registration.rs @@ -1,19 +1,17 @@ +use std::borrow::Cow; + use reqwest::{Client, RequestBuilder, Response}; -use try_from::TryInto; -use apps::{App, Scopes}; +use apps::{App, AppBuilder, Scopes}; use http_send::{HttpSend, HttpSender}; -use Data; -use Error; -use Mastodon; -use MastodonBuilder; -use Result; +use {Data, Mastodon, MastodonBuilder, Result}; /// Handles registering your mastodon app to your instance. It is recommended /// you cache your data struct to avoid registering on every run. -pub struct Registration<H: HttpSend> { +pub struct Registration<'a, H: HttpSend> { base: String, client: Client, + app_builder: AppBuilder<'a>, http_sender: H, } @@ -34,7 +32,7 @@ struct AccessToken { access_token: String, } -impl Registration<HttpSender> { +impl<'a> Registration<'a, HttpSender> { /// Construct a new registration process to the instance of the `base` url. /// ``` /// use elefren::apps::prelude::*; @@ -45,21 +43,43 @@ impl Registration<HttpSender> { Registration { base: base.into(), client: Client::new(), + app_builder: AppBuilder::new(), http_sender: HttpSender, } } } -impl<H: HttpSend> Registration<H> { +impl<'a, H: HttpSend> Registration<'a, H> { #[allow(dead_code)] pub(crate) fn with_sender<I: Into<String>>(base: I, http_sender: H) -> Self { Registration { base: base.into(), client: Client::new(), + app_builder: AppBuilder::new(), http_sender, } } + pub fn client_name<I: Into<Cow<'a, str>>>(&mut self, name: I) -> &mut Self { + self.app_builder.client_name(name.into()); + self + } + + pub fn redirect_uris<I: Into<Cow<'a, str>>>(&mut self, uris: I) -> &mut Self { + self.app_builder.redirect_uris(uris); + self + } + + pub fn scopes(&mut self, scopes: Scopes) -> &mut Self { + self.app_builder.scopes(scopes); + self + } + + pub fn website<I: Into<Cow<'a, str>>>(&mut self, website: I) -> &mut Self { + self.app_builder.website(website); + self + } + fn send(&self, req: &mut RequestBuilder) -> Result<Response> { Ok(self.http_sender.send(&self.client, req)?) } @@ -71,38 +91,32 @@ impl<H: HttpSend> Registration<H> { /// # fn main () -> elefren::Result<()> { /// use elefren::{apps::prelude::*, prelude::*}; /// - /// let mut builder = App::builder(); - /// builder.client_name("elefren_test"); - /// let app = builder.build()?; - /// - /// let registration = Registration::new("https://mastodon.social"); - /// let registered = registration.register(app)?; - /// let url = registered.authorize_url()?; + /// let registration = Registration::new("https://mastodon.social") + /// .client_name("elefren_test") + /// .register()?; + /// let url = registration.authorize_url()?; /// // Here you now need to open the url in the browser /// // And handle a the redirect url coming back with the code. /// let code = String::from("RETURNED_FROM_BROWSER"); - /// let mastodon = registered.complete(code)?; + /// let mastodon = registration.complete(code)?; /// /// println!("{:?}", mastodon.get_home_timeline()?.initial_items); /// # Ok(()) /// # } /// ``` - pub fn register<I: TryInto<App>>(self, app: I) -> Result<Registered<H>> - where - Error: From<<I as TryInto<App>>::Err>, - { - let app = app.try_into()?; + pub fn register(&mut self) -> Result<Registered<H>> { + let app: App = self.app_builder.clone().build()?; let url = format!("{}/api/v1/apps", self.base); let oauth: OAuth = self.send(self.client.post(&url).form(&app))?.json()?; Ok(Registered { - base: self.base, - client: self.client, + base: self.base.clone(), + client: self.client.clone(), client_id: oauth.client_id, client_secret: oauth.client_secret, redirect: oauth.redirect_uri, scopes: app.scopes(), - http_sender: self.http_sender, + http_sender: self.http_sender.clone(), }) } } @@ -160,3 +174,51 @@ pub struct Registered<H: HttpSend> { scopes: Scopes, http_sender: H, } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_registration_new() { + let r = Registration::new("https://example.com"); + assert_eq!(r.base, "https://example.com".to_string()); + assert_eq!(r.app_builder, AppBuilder::new()); + } + + #[test] + fn test_set_client_name() { + let mut r = Registration::new("https://example.com"); + r.client_name("foo-test"); + + assert_eq!(r.base, "https://example.com".to_string()); + assert_eq!(&mut r.app_builder, AppBuilder::new().client_name("foo-test")); + } + + #[test] + fn test_set_redirect_uris() { + let mut r = Registration::new("https://example.com"); + r.redirect_uris("https://foo.com"); + + assert_eq!(r.base, "https://example.com".to_string()); + assert_eq!(&mut r.app_builder, AppBuilder::new().redirect_uris("https://foo.com")); + } + + #[test] + fn test_set_scopes() { + let mut r = Registration::new("https://example.com"); + r.scopes(Scopes::All); + + assert_eq!(r.base, "https://example.com".to_string()); + assert_eq!(&mut r.app_builder, AppBuilder::new().scopes(Scopes::All)); + } + + #[test] + fn test_set_website() { + let mut r = Registration::new("https://example.com"); + r.website("https://website.example.com"); + + assert_eq!(r.base, "https://example.com".to_string()); + assert_eq!(&mut r.app_builder, AppBuilder::new().website("https://website.example.com")); + } +} |