1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
pub mod auth; pub mod collections; pub mod delete; pub mod download; pub mod search; pub mod upload; pub mod users; pub use auth::{Code, CodeProvider, Token}; use crate::{ client::{ collections::{CollectionsQuery, CollectionsResult}, download::Download, search::{Search, SearchResult}, upload::Upload, users::{UsersQuery, UsersResult}, }, errors::{Error, ErrorKind, Result}, CenterDevice, ClientCredentials, WithProgress, }; use failure::Fail; use reqwest::{self, blocking::Response, IntoUrl, StatusCode}; pub struct UnauthorizedClient<'a> { pub(crate) base_url: &'a str, pub(crate) client_credentials: ClientCredentials<'a>, pub(crate) http_client: reqwest::blocking::Client, } impl<'a, 'b: 'a> UnauthorizedClient<'b> { pub fn authorize_with_code_flow<T: IntoUrl + ToString + Clone, S: CodeProvider>( self, redirect_uri: T, code_provider: &S, ) -> Result<AuthorizedClient<'a>> { let redirect_url = redirect_uri .clone() .into_url() .map_err(|e| e.context(ErrorKind::FailedToPrepareHttpRequest(redirect_uri.to_string())))?; let token = auth::authorization_code_flow(&self.client_credentials, self.base_url, &redirect_url, code_provider)?; let authorized_client = AuthorizedClient { base_url: self.base_url, client_credentials: self.client_credentials, token, http_client: self.http_client, }; Ok(authorized_client) } } pub struct AuthorizedClient<'a> { pub(crate) base_url: &'a str, pub(crate) client_credentials: ClientCredentials<'a>, pub(crate) token: Token, pub(crate) http_client: reqwest::blocking::Client, } impl<'a> AuthorizedClient<'a> { pub fn token(&self) -> &Token { &self.token } } impl<'a> CenterDevice for AuthorizedClient<'a> { fn refresh_access_token(&self) -> Result<Token> { auth::refresh_access_token(self) } fn search_documents(&self, search: Search) -> Result<SearchResult> { search::search_documents(self, search) } fn upload_file(&self, upload: Upload) -> Result<ID> { upload::upload_file(&self, upload) } fn download_file(&self, download: Download) -> Result<u64> { download::download_file(self, download) } fn download_file_with_progress<T: WithProgress>(&self, download: Download, progress: &mut T) -> Result<u64> { download::download_file_with_progress(self, download, progress) } fn delete_documents(&self, document_ids: &[&str]) -> Result<()> { delete::delete_documents(self, document_ids) } fn search_users(&self, users_query: UsersQuery) -> Result<UsersResult> { users::search_users(self, users_query) } fn search_collections(&self, collections_query: CollectionsQuery) -> Result<CollectionsResult> { collections::search_collections(self, collections_query) } } pub type ID = String; pub(crate) trait GeneralErrHandler { type T: std::marker::Sized; fn general_err_handler(self, expected_states: &[StatusCode]) -> Result<Self::T>; } impl GeneralErrHandler for Response { type T = Response; fn general_err_handler(self, expected_states: &[StatusCode]) -> Result<Self> { match self.status() { code if expected_states.contains(&code) => Ok(self), code @ StatusCode::UNAUTHORIZED => Err(Error::from(ErrorKind::ApiCallFailedInvalidToken(code))), code @ StatusCode::TOO_MANY_REQUESTS => Err(Error::from(ErrorKind::ApiCallFailedTooManyRequests(code))), _ => Err(handle_error(self)), } } } fn handle_error(response: Response) -> Error { let status_code = response.status(); match response.text() { Ok(body) => Error::from(ErrorKind::ApiCallFailed(status_code, body)), Err(e) => { e.context(ErrorKind::FailedToProcessHttpResponse( status_code, "reading body".to_string(), )) .into() } } }