Compare commits
6 Commits
a35c7b20d8
...
c6cf8a9730
Author | SHA1 | Date | |
---|---|---|---|
|
c6cf8a9730 | ||
|
f6db6992a0 | ||
|
908ead5b11 | ||
|
9ea1d01c27 | ||
|
07f6405b26 | ||
|
dadf00f4a5 |
22
Cargo.lock
generated
22
Cargo.lock
generated
@ -641,6 +641,7 @@ dependencies = [
|
|||||||
"md5",
|
"md5",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
"rpassword",
|
||||||
"rust-crypto",
|
"rust-crypto",
|
||||||
"textwrap 0.13.4",
|
"textwrap 0.13.4",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -915,6 +916,27 @@ dependencies = [
|
|||||||
"winreg",
|
"winreg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rpassword"
|
||||||
|
version = "7.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6678cf63ab3491898c0d021b493c94c9b221d91295294a2a5746eacbe5928322"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rtoolbox",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rtoolbox"
|
||||||
|
version = "0.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "034e22c514f5c0cb8a10ff341b9b048b5ceb21591f31c8f44c43b960f9b3524a"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust-crypto"
|
name = "rust-crypto"
|
||||||
version = "0.2.36"
|
version = "0.2.36"
|
||||||
|
@ -21,6 +21,7 @@ chrono = "0.4.26"
|
|||||||
indicatif = "0.17.5"
|
indicatif = "0.17.5"
|
||||||
md5 = "0.7.0"
|
md5 = "0.7.0"
|
||||||
futures-util = "0.3.28"
|
futures-util = "0.3.28"
|
||||||
|
rpassword = "7.2"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = true
|
debug = true
|
||||||
|
@ -13,13 +13,12 @@ This should work pretty much like git with some adaptations to be more debuggabl
|
|||||||
- [x] Pushing updates (new, deleted, modified)
|
- [x] Pushing updates (new, deleted, modified)
|
||||||
- [x] Using a .nextsyncignore to ignore files
|
- [x] Using a .nextsyncignore to ignore files
|
||||||
- [ ] Pulling changes
|
- [ ] Pulling changes
|
||||||
- [ ] Auth without using env variables
|
- [x] Auth with a token
|
||||||
|
- [ ] Remember token
|
||||||
- [ ] Various optimisation
|
- [ ] Various optimisation
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
For the authentification, I use env variables (USERNAME and PASSWORD), this is temporary.
|
|
||||||
|
|
||||||
```
|
```
|
||||||
USAGE:
|
USAGE:
|
||||||
nextsync [SUBCOMMAND]
|
nextsync [SUBCOMMAND]
|
||||||
|
@ -10,6 +10,7 @@ use crate::utils::path::path_buf_to_string;
|
|||||||
use crate::utils::remote::{enumerate_remote, EnumerateOptions};
|
use crate::utils::remote::{enumerate_remote, EnumerateOptions};
|
||||||
use crate::global::global::{DIR_PATH, set_dir_path};
|
use crate::global::global::{DIR_PATH, set_dir_path};
|
||||||
use crate::services::api::ApiError;
|
use crate::services::api::ApiError;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
use crate::services::req_props::{ReqProps, ObjProps};
|
use crate::services::req_props::{ReqProps, ObjProps};
|
||||||
use crate::store::object::{tree, blob::Blob};
|
use crate::store::object::{tree, blob::Blob};
|
||||||
use crate::commands::config;
|
use crate::commands::config;
|
||||||
|
@ -2,6 +2,7 @@ use std::path::PathBuf;
|
|||||||
use std::io;
|
use std::io;
|
||||||
use crate::services::api::ApiError;
|
use crate::services::api::ApiError;
|
||||||
use crate::services::r#copy::Copy;
|
use crate::services::r#copy::Copy;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
use crate::services::req_props::ReqProps;
|
use crate::services::req_props::ReqProps;
|
||||||
use crate::commands::status::LocalObj;
|
use crate::commands::status::LocalObj;
|
||||||
use crate::commands::push::push_factory::{PushState, PushChange, PushFlowState};
|
use crate::commands::push::push_factory::{PushState, PushChange, PushFlowState};
|
||||||
@ -26,10 +27,10 @@ impl PushChange for Copied {
|
|||||||
fn push(&self) -> io::Result<()> {
|
fn push(&self) -> io::Result<()> {
|
||||||
let obj = &self.obj;
|
let obj = &self.obj;
|
||||||
let res = Copy::new()
|
let res = Copy::new()
|
||||||
.set_url(
|
.set_url_copy(
|
||||||
&path_buf_to_string(obj.path_from.clone().unwrap()),
|
&path_buf_to_string(obj.path_from.clone().unwrap()),
|
||||||
obj.path.to_str().unwrap())
|
obj.path.to_str().unwrap())
|
||||||
.send_with_err();
|
.send();
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Err(ApiError::IncorrectRequest(err)) => {
|
Err(ApiError::IncorrectRequest(err)) => {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::io;
|
use std::io;
|
||||||
use crate::services::api::ApiError;
|
use crate::services::api::ApiError;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
use crate::services::delete_path::DeletePath;
|
use crate::services::delete_path::DeletePath;
|
||||||
use crate::store::index;
|
use crate::store::index;
|
||||||
use crate::store::object::blob::Blob;
|
use crate::store::object::blob::Blob;
|
||||||
@ -26,7 +27,7 @@ impl PushChange for Deleted {
|
|||||||
let obj = &self.obj;
|
let obj = &self.obj;
|
||||||
let res = DeletePath::new()
|
let res = DeletePath::new()
|
||||||
.set_url(obj.path.to_str().unwrap())
|
.set_url(obj.path.to_str().unwrap())
|
||||||
.send_with_err();
|
.send();
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Err(ApiError::IncorrectRequest(err)) => {
|
Err(ApiError::IncorrectRequest(err)) => {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::io;
|
use std::io;
|
||||||
use crate::services::api::ApiError;
|
use crate::services::api::ApiError;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
use crate::services::req_props::ReqProps;
|
use crate::services::req_props::ReqProps;
|
||||||
use crate::services::upload_file::UploadFile;
|
use crate::services::upload_file::UploadFile;
|
||||||
use crate::commands::status::LocalObj;
|
use crate::commands::status::LocalObj;
|
||||||
@ -27,7 +28,7 @@ impl PushChange for Modified {
|
|||||||
let res = UploadFile::new()
|
let res = UploadFile::new()
|
||||||
.set_url(obj.path.to_str().unwrap())
|
.set_url(obj.path.to_str().unwrap())
|
||||||
.set_file(obj.path.clone())
|
.set_file(obj.path.clone())
|
||||||
.send_with_err();
|
.send();
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Err(ApiError::IncorrectRequest(err)) => {
|
Err(ApiError::IncorrectRequest(err)) => {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::io;
|
use std::io;
|
||||||
use crate::services::api::ApiError;
|
use crate::services::api::ApiError;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
use crate::services::r#move::Move;
|
use crate::services::r#move::Move;
|
||||||
use crate::services::req_props::ReqProps;
|
use crate::services::req_props::ReqProps;
|
||||||
use crate::commands::status::LocalObj;
|
use crate::commands::status::LocalObj;
|
||||||
@ -26,10 +27,10 @@ impl PushChange for Moved {
|
|||||||
fn push(&self) -> io::Result<()> {
|
fn push(&self) -> io::Result<()> {
|
||||||
let obj = &self.obj;
|
let obj = &self.obj;
|
||||||
let res = Move::new()
|
let res = Move::new()
|
||||||
.set_url(
|
.set_url_move(
|
||||||
&path_buf_to_string(obj.path_from.clone().unwrap()),
|
&path_buf_to_string(obj.path_from.clone().unwrap()),
|
||||||
obj.path.to_str().unwrap())
|
obj.path.to_str().unwrap())
|
||||||
.send_with_err();
|
.send();
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Err(ApiError::IncorrectRequest(err)) => {
|
Err(ApiError::IncorrectRequest(err)) => {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::io;
|
use std::io;
|
||||||
use crate::services::api::ApiError;
|
use crate::services::api::ApiError;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
use crate::services::req_props::ReqProps;
|
use crate::services::req_props::ReqProps;
|
||||||
use crate::services::upload_file::UploadFile;
|
use crate::services::upload_file::UploadFile;
|
||||||
use crate::store::object::blob::Blob;
|
use crate::store::object::blob::Blob;
|
||||||
@ -27,7 +28,7 @@ impl PushChange for New {
|
|||||||
let res = UploadFile::new()
|
let res = UploadFile::new()
|
||||||
.set_url(obj.path.to_str().unwrap())
|
.set_url(obj.path.to_str().unwrap())
|
||||||
.set_file(obj.path.clone())
|
.set_file(obj.path.clone())
|
||||||
.send_with_err();
|
.send();
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Err(ApiError::IncorrectRequest(err)) => {
|
Err(ApiError::IncorrectRequest(err)) => {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::io;
|
use std::io;
|
||||||
use crate::services::api::ApiError;
|
use crate::services::api::ApiError;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
use crate::services::req_props::ReqProps;
|
use crate::services::req_props::ReqProps;
|
||||||
use crate::services::create_folder::CreateFolder;
|
use crate::services::create_folder::CreateFolder;
|
||||||
use crate::store::index;
|
use crate::store::index;
|
||||||
@ -33,7 +34,7 @@ impl PushChange for NewDir {
|
|||||||
let obj = &self.obj;
|
let obj = &self.obj;
|
||||||
let res = CreateFolder::new()
|
let res = CreateFolder::new()
|
||||||
.set_url(obj.path.to_str().unwrap())
|
.set_url(obj.path.to_str().unwrap())
|
||||||
.send_with_err();
|
.send();
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Err(ApiError::IncorrectRequest(err)) => {
|
Err(ApiError::IncorrectRequest(err)) => {
|
||||||
|
@ -2,6 +2,7 @@ use std::path::PathBuf;
|
|||||||
use std::io;
|
use std::io;
|
||||||
use crate::commands::status::{State, LocalObj};
|
use crate::commands::status::{State, LocalObj};
|
||||||
use crate::services::api::ApiError;
|
use crate::services::api::ApiError;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
use crate::services::req_props::ReqProps;
|
use crate::services::req_props::ReqProps;
|
||||||
use crate::commands::push::new::New;
|
use crate::commands::push::new::New;
|
||||||
use crate::commands::push::new_dir::NewDir;
|
use crate::commands::push::new_dir::NewDir;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::io;
|
use std::io;
|
||||||
use crate::services::api::ApiError;
|
use crate::services::api::ApiError;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
use crate::services::delete_path::DeletePath;
|
use crate::services::delete_path::DeletePath;
|
||||||
use crate::store::index;
|
use crate::store::index;
|
||||||
use crate::store::object::tree;
|
use crate::store::object::tree;
|
||||||
@ -32,7 +33,7 @@ impl PushChange for RmDir {
|
|||||||
let obj = &self.obj;
|
let obj = &self.obj;
|
||||||
let res = DeletePath::new()
|
let res = DeletePath::new()
|
||||||
.set_url(obj.path.to_str().unwrap())
|
.set_url(obj.path.to_str().unwrap())
|
||||||
.send_with_err();
|
.send();
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Err(ApiError::IncorrectRequest(err)) => {
|
Err(ApiError::IncorrectRequest(err)) => {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::services::api::ApiError;
|
use crate::services::api::ApiError;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
use crate::services::req_props::{ReqProps, ObjProps};
|
use crate::services::req_props::{ReqProps, ObjProps};
|
||||||
use crate::store::object::Object;
|
use crate::store::object::Object;
|
||||||
use crate::utils::api::{ApiProps, get_api_props};
|
use crate::utils::api::{ApiProps, get_api_props};
|
||||||
|
@ -7,4 +7,8 @@ pub mod delete_path;
|
|||||||
pub mod downloader;
|
pub mod downloader;
|
||||||
pub mod r#move;
|
pub mod r#move;
|
||||||
pub mod r#copy;
|
pub mod r#copy;
|
||||||
|
pub mod login;
|
||||||
|
pub mod request_manager;
|
||||||
|
pub mod api_call;
|
||||||
|
//pub mod auth;
|
||||||
//pub mod bulk_upload;
|
//pub mod bulk_upload;
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use std::path::PathBuf;
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use reqwest::RequestBuilder;
|
use reqwest::RequestBuilder;
|
||||||
@ -8,6 +11,11 @@ use reqwest::header::{HeaderValue, CONTENT_TYPE, HeaderMap, IntoHeaderName};
|
|||||||
use crate::utils::api::ApiProps;
|
use crate::utils::api::ApiProps;
|
||||||
use crate::commands::config;
|
use crate::commands::config;
|
||||||
use crate::commands::clone::get_url_props;
|
use crate::commands::clone::get_url_props;
|
||||||
|
use crate::services::request_manager::get_request_manager;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref HTTP_TOKEN: Mutex<String> = Mutex::new(String::new());
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ApiError {
|
pub enum ApiError {
|
||||||
@ -20,7 +28,9 @@ pub enum ApiError {
|
|||||||
pub struct ApiBuilder {
|
pub struct ApiBuilder {
|
||||||
client: Client,
|
client: Client,
|
||||||
request: Option<RequestBuilder>,
|
request: Option<RequestBuilder>,
|
||||||
headers: Option<HeaderMap>
|
headers: Option<HeaderMap>,
|
||||||
|
auth_set: bool,
|
||||||
|
host: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApiBuilder {
|
impl ApiBuilder {
|
||||||
@ -29,24 +39,14 @@ impl ApiBuilder {
|
|||||||
client: Client::new(),
|
client: Client::new(),
|
||||||
request: None,
|
request: None,
|
||||||
headers: None,
|
headers: None,
|
||||||
|
auth_set: false,
|
||||||
|
host: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_url(&mut self, method: Method, url: &str) -> &mut ApiBuilder {
|
pub fn set_url(&mut self, method: Method, url: &str) -> &mut ApiBuilder {
|
||||||
let remote = match config::get("remote") {
|
self.request = Some(self.client.request(method, url));
|
||||||
Some(r) => r,
|
|
||||||
None => {
|
|
||||||
eprintln!("fatal: unable to find a remote");
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let (host, _, _) = get_url_props(&remote);
|
|
||||||
let mut u = String::from(host);
|
|
||||||
u.push_str(url);
|
|
||||||
self.request = Some(self.client.request(method, u));
|
|
||||||
self
|
self
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_request(&mut self, method: Method, path: &str) -> &mut ApiBuilder {
|
pub fn build_request(&mut self, method: Method, path: &str) -> &mut ApiBuilder {
|
||||||
@ -58,6 +58,7 @@ impl ApiBuilder {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let (host, username, root) = get_url_props(&remote);
|
let (host, username, root) = get_url_props(&remote);
|
||||||
|
self.host = Some(host.clone());
|
||||||
let mut url = String::from(host);
|
let mut url = String::from(host);
|
||||||
url.push_str("/remote.php/dav/files/");
|
url.push_str("/remote.php/dav/files/");
|
||||||
url.push_str(username.unwrap());
|
url.push_str(username.unwrap());
|
||||||
@ -71,6 +72,7 @@ impl ApiBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_req(&mut self, meth: Method, p: &str, api_props: &ApiProps) -> &mut ApiBuilder {
|
pub fn set_req(&mut self, meth: Method, p: &str, api_props: &ApiProps) -> &mut ApiBuilder {
|
||||||
|
self.host = Some(api_props.clone().host.clone());
|
||||||
let mut url = String::from(&api_props.host);
|
let mut url = String::from(&api_props.host);
|
||||||
url.push_str("/remote.php/dav/files/");
|
url.push_str("/remote.php/dav/files/");
|
||||||
url.push_str("/");
|
url.push_str("/");
|
||||||
@ -84,23 +86,33 @@ impl ApiBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_auth(&mut self) -> &mut ApiBuilder {
|
pub fn set_basic_auth(&mut self, login: String, pwd: String) -> &mut ApiBuilder {
|
||||||
// todo if not exist
|
|
||||||
dotenv().ok();
|
|
||||||
let password = env::var("PASSWORD").unwrap();
|
|
||||||
let username = env::var("USERNAME").unwrap();
|
|
||||||
match self.request.take() {
|
match self.request.take() {
|
||||||
None => {
|
None => {
|
||||||
eprintln!("fatal: incorrect request");
|
eprintln!("fatal: incorrect request");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
},
|
},
|
||||||
Some(req) => {
|
Some(req) => {
|
||||||
self.request = Some(req.basic_auth(username, Some(password)));
|
self.request = Some(req.basic_auth(login, Some(pwd)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.auth_set = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_token(&mut self, token: String) {
|
||||||
|
match self.request.take() {
|
||||||
|
None => {
|
||||||
|
eprintln!("fatal: incorrect request");
|
||||||
|
std::process::exit(1);
|
||||||
|
},
|
||||||
|
Some(req) => {
|
||||||
|
self.request = Some(req.bearer_auth(token));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.auth_set = true;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_xml(&mut self, xml_payload: String) -> &mut ApiBuilder {
|
pub fn set_xml(&mut self, xml_payload: String) -> &mut ApiBuilder {
|
||||||
match self.request.take() {
|
match self.request.take() {
|
||||||
None => {
|
None => {
|
||||||
@ -148,8 +160,71 @@ impl ApiBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&mut self) -> Result<Response, Error> {
|
fn set_request_manager(&mut self) {
|
||||||
self.set_auth();
|
let mut request_manager = get_request_manager().lock().unwrap();
|
||||||
|
let request_manager = request_manager.as_mut().unwrap();
|
||||||
|
|
||||||
|
if !self.host.is_none()
|
||||||
|
{
|
||||||
|
request_manager.set_host(self.host.clone().unwrap().replace("https://", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.auth_set {
|
||||||
|
self.set_token(request_manager.get_token());
|
||||||
|
//self.set_auth();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send(&mut self, need_text: bool) -> Result<Option<String>, ApiError> {
|
||||||
|
if !self.host.is_none() || !self.auth_set {
|
||||||
|
self.set_request_manager();
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||||
|
match self.request.take() {
|
||||||
|
None => {
|
||||||
|
eprintln!("fatal: incorrect request");
|
||||||
|
std::process::exit(1);
|
||||||
|
},
|
||||||
|
Some(req) => {
|
||||||
|
if let Some(headers) = &self.headers {
|
||||||
|
req.headers(headers.clone())
|
||||||
|
.send().await
|
||||||
|
} else {
|
||||||
|
req.send().await
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}).map_err(ApiError::RequestError)?;
|
||||||
|
|
||||||
|
if res.status().is_success() {
|
||||||
|
if need_text {
|
||||||
|
let body = tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||||
|
res.text().await
|
||||||
|
}).map_err(|err| ApiError::EmptyError(err))?;
|
||||||
|
Ok(Some(body))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(ApiError::IncorrectRequest(res))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn old_send(&mut self) -> Result<Response, Error> {
|
||||||
|
let mut request_manager = get_request_manager().lock().unwrap();
|
||||||
|
let request_manager = request_manager.as_mut().unwrap();
|
||||||
|
if !self.host.is_none()
|
||||||
|
{
|
||||||
|
request_manager.set_host(self.host.clone().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.auth_set {
|
||||||
|
//self.set_auth();
|
||||||
|
self.set_token(request_manager.get_token());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
match self.request.take() {
|
match self.request.take() {
|
||||||
None => {
|
None => {
|
||||||
eprintln!("fatal: incorrect request");
|
eprintln!("fatal: incorrect request");
|
||||||
|
13
src/services/api_call.rs
Normal file
13
src/services/api_call.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
use crate::services::api::ApiError;
|
||||||
|
|
||||||
|
pub trait ApiCall {
|
||||||
|
fn new() -> Self where Self: Sized {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
fn set_url(&mut self, url: &str) -> &mut Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
fn send(&mut self) -> Result<Option<String>, ApiError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
@ -1,2 +0,0 @@
|
|||||||
|
|
||||||
|
|
@ -1,20 +1,27 @@
|
|||||||
use reqwest::{Method, Response, Error, header::HeaderValue};
|
use reqwest::{Method, header::HeaderValue};
|
||||||
use crate::services::api::{ApiBuilder, ApiError};
|
use crate::services::api::{ApiBuilder, ApiError};
|
||||||
use crate::clone::get_url_props;
|
use crate::clone::get_url_props;
|
||||||
use crate::commands::config;
|
use crate::commands::config;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
|
|
||||||
pub struct Copy {
|
pub struct Copy {
|
||||||
api_builder: ApiBuilder,
|
api_builder: ApiBuilder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Copy {
|
impl ApiCall for Copy {
|
||||||
pub fn new() -> Self {
|
fn new() -> Self {
|
||||||
Copy {
|
Copy {
|
||||||
api_builder: ApiBuilder::new(),
|
api_builder: ApiBuilder::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_url(&mut self, url: &str, destination: &str) -> &mut Copy {
|
fn send(&mut self) -> Result<Option<String>, ApiError> {
|
||||||
|
self.api_builder.send(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Copy {
|
||||||
|
pub fn set_url_copy(&mut self, url: &str, destination: &str) -> &mut Copy {
|
||||||
self.api_builder.build_request(Method::from_bytes(b"COPY").unwrap(), url);
|
self.api_builder.build_request(Method::from_bytes(b"COPY").unwrap(), url);
|
||||||
|
|
||||||
let remote = match config::get("remote") {
|
let remote = match config::get("remote") {
|
||||||
@ -37,25 +44,10 @@ impl Copy {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&mut self) -> Result<Response, Error> {
|
|
||||||
self.api_builder.send().await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _overwrite(&mut self, overwrite: bool) -> &mut Copy {
|
pub fn _overwrite(&mut self, overwrite: bool) -> &mut Copy {
|
||||||
self.api_builder.set_header("Overwrite", HeaderValue::from_str({
|
self.api_builder.set_header("Overwrite", HeaderValue::from_str({
|
||||||
if overwrite { "T" } else { "F" }
|
if overwrite { "T" } else { "F" }
|
||||||
}).unwrap());
|
}).unwrap());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_with_err(&mut self) -> Result<(), ApiError> {
|
|
||||||
let res = tokio::runtime::Runtime::new().unwrap().block_on(async {
|
|
||||||
self.send().await
|
|
||||||
}).map_err(ApiError::RequestError)?;
|
|
||||||
if res.status().is_success() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(ApiError::IncorrectRequest(res))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,24 @@
|
|||||||
use reqwest::{Method, Response, Error};
|
use reqwest::Method;
|
||||||
use crate::services::api::{ApiBuilder, ApiError};
|
use crate::services::api::{ApiBuilder, ApiError};
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
|
|
||||||
pub struct CreateFolder {
|
pub struct CreateFolder {
|
||||||
api_builder: ApiBuilder,
|
api_builder: ApiBuilder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateFolder {
|
impl ApiCall for CreateFolder {
|
||||||
pub fn new() -> Self {
|
fn new() -> Self {
|
||||||
CreateFolder {
|
CreateFolder {
|
||||||
api_builder: ApiBuilder::new(),
|
api_builder: ApiBuilder::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_url(&mut self, url: &str) -> &mut CreateFolder {
|
fn set_url(&mut self, url: &str) -> &mut CreateFolder {
|
||||||
self.api_builder.build_request(Method::from_bytes(b"MKCOL").unwrap(), url);
|
self.api_builder.build_request(Method::from_bytes(b"MKCOL").unwrap(), url);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&mut self) -> Result<Response, Error> {
|
fn send(&mut self) -> Result<Option<String>, ApiError> {
|
||||||
self.api_builder.send().await
|
self.api_builder.send(false)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_with_err(&mut self) -> Result<(), ApiError> {
|
|
||||||
let res = tokio::runtime::Runtime::new().unwrap().block_on(async {
|
|
||||||
self.send().await
|
|
||||||
}).map_err(ApiError::RequestError)?;
|
|
||||||
if res.status().is_success() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(ApiError::IncorrectRequest(res))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,38 +1,24 @@
|
|||||||
use reqwest::{Method, Response, Error};
|
use reqwest::Method;
|
||||||
use crate::services::api::{ApiBuilder, ApiError};
|
use crate::services::api::{ApiBuilder, ApiError};
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
|
|
||||||
pub struct DeletePath {
|
pub struct DeletePath {
|
||||||
api_builder: ApiBuilder,
|
api_builder: ApiBuilder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeletePath {
|
impl ApiCall for DeletePath {
|
||||||
pub fn new() -> Self {
|
fn new() -> Self {
|
||||||
DeletePath {
|
DeletePath {
|
||||||
api_builder: ApiBuilder::new(),
|
api_builder: ApiBuilder::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_url(&mut self, url: &str) -> &mut DeletePath {
|
fn set_url(&mut self, url: &str) -> &mut DeletePath {
|
||||||
self.api_builder.build_request(Method::DELETE, url);
|
self.api_builder.build_request(Method::DELETE, url);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&mut self) -> Result<Response, Error> {
|
fn send(&mut self) -> Result<Option<String>, ApiError> {
|
||||||
self.api_builder.send().await
|
self.api_builder.send(true)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_with_err(&mut self) -> Result<String, ApiError> {
|
|
||||||
let res = tokio::runtime::Runtime::new().unwrap().block_on(async {
|
|
||||||
self.send().await
|
|
||||||
}).map_err(ApiError::RequestError)?;
|
|
||||||
|
|
||||||
if res.status().is_success() {
|
|
||||||
let body = tokio::runtime::Runtime::new().unwrap().block_on(async {
|
|
||||||
res.text().await
|
|
||||||
}).map_err(ApiError::EmptyError)?;
|
|
||||||
Ok(body)
|
|
||||||
} else {
|
|
||||||
Err(ApiError::IncorrectRequest(res))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,38 +6,32 @@ use std::io::{self, Write};
|
|||||||
use reqwest::{Method, Response, Error};
|
use reqwest::{Method, Response, Error};
|
||||||
use crate::utils::api::ApiProps;
|
use crate::utils::api::ApiProps;
|
||||||
use crate::services::api::{ApiBuilder, ApiError};
|
use crate::services::api::{ApiBuilder, ApiError};
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
|
|
||||||
pub struct DownloadFiles {
|
pub struct DownloadFiles {
|
||||||
api_builder: ApiBuilder,
|
api_builder: ApiBuilder,
|
||||||
relative_ps: String,
|
relative_ps: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DownloadFiles {
|
impl ApiCall for DownloadFiles {
|
||||||
pub fn new() -> Self {
|
fn new() -> Self {
|
||||||
DownloadFiles {
|
DownloadFiles {
|
||||||
api_builder: ApiBuilder::new(),
|
api_builder: ApiBuilder::new(),
|
||||||
relative_ps: String::new(),
|
relative_ps: String::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_url(&mut self, relative_ps: &str, api_props: &ApiProps) -> &mut DownloadFiles {
|
impl DownloadFiles {
|
||||||
|
// todo make it beautiful
|
||||||
|
pub fn set_url_download(&mut self, relative_ps: &str, api_props: &ApiProps) -> &mut DownloadFiles {
|
||||||
self.relative_ps = relative_ps.to_string();
|
self.relative_ps = relative_ps.to_string();
|
||||||
self.api_builder.set_req(Method::GET, relative_ps, api_props);
|
self.api_builder.set_req(Method::GET, relative_ps, api_props);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&mut self) -> Result<Response, Error> {
|
pub async fn send_download(&mut self) -> Result<Response, Error> {
|
||||||
self.api_builder.send().await
|
self.api_builder.old_send().await
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn _send_with_err(mut self) -> Result<Vec<u8>, ApiError> {
|
|
||||||
let res = self.send().await.map_err(ApiError::RequestError)?;
|
|
||||||
if res.status().is_success() {
|
|
||||||
let body = res.bytes().await.map_err(ApiError::EmptyError)?;
|
|
||||||
Ok(body.to_vec())
|
|
||||||
} else {
|
|
||||||
Err(ApiError::IncorrectRequest(res))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_stream(&mut self, ref_p: PathBuf, callback: Option<impl Fn(u64)>) -> Result<(), ApiError> {
|
pub fn save_stream(&mut self, ref_p: PathBuf, callback: Option<impl Fn(u64)>) -> Result<(), ApiError> {
|
||||||
@ -45,7 +39,7 @@ impl DownloadFiles {
|
|||||||
let mut file = File::create(abs_p).unwrap();
|
let mut file = File::create(abs_p).unwrap();
|
||||||
|
|
||||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||||
let res = self.send().await.map_err(ApiError::RequestError)?;
|
let res = self.send_download().await.map_err(ApiError::RequestError)?;
|
||||||
if res.status().is_success() {
|
if res.status().is_success() {
|
||||||
let mut stream = res.bytes_stream();
|
let mut stream = res.bytes_stream();
|
||||||
|
|
||||||
@ -70,7 +64,7 @@ impl DownloadFiles {
|
|||||||
pub fn save(&mut self, ref_p: PathBuf) -> Result<(), ApiError> {
|
pub fn save(&mut self, ref_p: PathBuf) -> Result<(), ApiError> {
|
||||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||||
let p = ref_p.join(PathBuf::from(self.relative_ps.clone()));
|
let p = ref_p.join(PathBuf::from(self.relative_ps.clone()));
|
||||||
let res = self.send().await.map_err(ApiError::RequestError)?;
|
let res = self.send_download().await.map_err(ApiError::RequestError)?;
|
||||||
if res.status().is_success() {
|
if res.status().is_success() {
|
||||||
let body = res.bytes().await.map_err(ApiError::EmptyError)?;
|
let body = res.bytes().await.map_err(ApiError::EmptyError)?;
|
||||||
match Self::write_file(p, &body.to_vec()) {
|
match Self::write_file(p, &body.to_vec()) {
|
||||||
|
@ -2,6 +2,7 @@ use std::path::PathBuf;
|
|||||||
use indicatif::{ProgressBar, MultiProgress, ProgressStyle, HumanBytes};
|
use indicatif::{ProgressBar, MultiProgress, ProgressStyle, HumanBytes};
|
||||||
|
|
||||||
use crate::utils::api::ApiProps;
|
use crate::utils::api::ApiProps;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
use crate::services::api::ApiError;
|
use crate::services::api::ApiError;
|
||||||
use crate::services::download_files::DownloadFiles;
|
use crate::services::download_files::DownloadFiles;
|
||||||
use crate::services::req_props::ObjProps;
|
use crate::services::req_props::ObjProps;
|
||||||
@ -106,7 +107,7 @@ impl Downloader {
|
|||||||
for file in self.files.clone() {
|
for file in self.files.clone() {
|
||||||
let relative_s = &file.clone().relative_s.unwrap();
|
let relative_s = &file.clone().relative_s.unwrap();
|
||||||
let mut download = DownloadFiles::new();
|
let mut download = DownloadFiles::new();
|
||||||
download.set_url(&relative_s, &self.api_props.clone().unwrap());
|
download.set_url_download(&relative_s, &self.api_props.clone().unwrap());
|
||||||
|
|
||||||
let should_use_stream = {
|
let should_use_stream = {
|
||||||
if let Some(size) = file.contentlength {
|
if let Some(size) = file.contentlength {
|
||||||
|
102
src/services/login.rs
Normal file
102
src/services/login.rs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
use std::io;
|
||||||
|
use std::io::Cursor;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use xml::reader::{EventReader, XmlEvent};
|
||||||
|
use reqwest::{header::HeaderValue, Method};
|
||||||
|
use rpassword;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
|
use crate::services::api::{ApiBuilder, ApiError};
|
||||||
|
|
||||||
|
pub struct Login {
|
||||||
|
api_builder: ApiBuilder,
|
||||||
|
login: String,
|
||||||
|
password: String,
|
||||||
|
host: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApiCall for Login {
|
||||||
|
fn new() -> Self {
|
||||||
|
Login {
|
||||||
|
api_builder: ApiBuilder::new(),
|
||||||
|
login: String::new(),
|
||||||
|
password: String::new(),
|
||||||
|
host: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send(&mut self) -> Result<Option<String>, ApiError> {
|
||||||
|
|
||||||
|
let url = match self.host.clone() {
|
||||||
|
Some(h) => {
|
||||||
|
let mut u = String::from("https://");
|
||||||
|
u.push_str(&h);
|
||||||
|
u.push_str("/ocs/v2.php/core/getapppassword");
|
||||||
|
u
|
||||||
|
},
|
||||||
|
None => "/ocs/v2.php/core/getapppassword".to_owned(),
|
||||||
|
};
|
||||||
|
dbg!(url.clone());
|
||||||
|
self.api_builder.set_url(Method::GET, &url);
|
||||||
|
self.api_builder.set_header("OCS-APIRequest", HeaderValue::from_str("true").unwrap());
|
||||||
|
self.api_builder.set_basic_auth(self.login.clone(), self.password.clone());
|
||||||
|
self.api_builder.send(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Login {
|
||||||
|
pub fn ask_auth(&mut self) -> &mut Login {
|
||||||
|
println!("Please enter your username/email: ");
|
||||||
|
let stdin = io::stdin();
|
||||||
|
self.login = stdin.lock().lines().next().unwrap().unwrap();
|
||||||
|
println!("Please enter your password: ");
|
||||||
|
self.password = rpassword::read_password().unwrap();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_host(&mut self, host: Option<String>) -> &mut Login {
|
||||||
|
self.host = host;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_login(&mut self) -> Result<String, ApiError> {
|
||||||
|
match self.send() {
|
||||||
|
Ok(Some(body)) => Ok(self.parse(body)),
|
||||||
|
Ok(None) => Err(ApiError::Unexpected(String::from("Empty after tested"))),
|
||||||
|
Err(err) => Err(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(&self, xml: String) -> String {
|
||||||
|
let cursor = Cursor::new(xml);
|
||||||
|
let parser = EventReader::new(cursor);
|
||||||
|
|
||||||
|
let mut should_get = false;
|
||||||
|
|
||||||
|
for event in parser {
|
||||||
|
match event {
|
||||||
|
Ok(XmlEvent::StartElement { name, .. }) => {
|
||||||
|
should_get = {
|
||||||
|
if &name.local_name == "apppassword" {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(XmlEvent::Characters(text)) => {
|
||||||
|
if !text.trim().is_empty() && should_get {
|
||||||
|
return text.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(XmlEvent::EndElement { name, .. }) => {
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("err: parsing xml: {}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +1,28 @@
|
|||||||
use reqwest::{Method, Response, Error, header::HeaderValue};
|
use reqwest::{Method, header::HeaderValue};
|
||||||
use crate::services::api::{ApiBuilder, ApiError};
|
use crate::services::api::{ApiBuilder, ApiError};
|
||||||
use crate::clone::get_url_props;
|
use crate::clone::get_url_props;
|
||||||
use crate::commands::config;
|
use crate::commands::config;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
|
|
||||||
pub struct Move {
|
pub struct Move {
|
||||||
api_builder: ApiBuilder,
|
api_builder: ApiBuilder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Move {
|
impl ApiCall for Move {
|
||||||
pub fn new() -> Self {
|
fn new() -> Self {
|
||||||
Move {
|
Move {
|
||||||
api_builder: ApiBuilder::new(),
|
api_builder: ApiBuilder::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_url(&mut self, url: &str, destination: &str) -> &mut Move {
|
|
||||||
|
fn send(&mut self) -> Result<Option<String>, ApiError> {
|
||||||
|
self.api_builder.send(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Move {
|
||||||
|
pub fn set_url_move(&mut self, url: &str, destination: &str) -> &mut Move {
|
||||||
self.api_builder.build_request(Method::from_bytes(b"MOVE").unwrap(), url);
|
self.api_builder.build_request(Method::from_bytes(b"MOVE").unwrap(), url);
|
||||||
|
|
||||||
let remote = match config::get("remote") {
|
let remote = match config::get("remote") {
|
||||||
@ -37,25 +45,10 @@ impl Move {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&mut self) -> Result<Response, Error> {
|
|
||||||
self.api_builder.send().await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _overwrite(&mut self, overwrite: bool) -> &mut Move {
|
pub fn _overwrite(&mut self, overwrite: bool) -> &mut Move {
|
||||||
self.api_builder.set_header("Overwrite", HeaderValue::from_str({
|
self.api_builder.set_header("Overwrite", HeaderValue::from_str({
|
||||||
if overwrite { "T" } else { "F" }
|
if overwrite { "T" } else { "F" }
|
||||||
}).unwrap());
|
}).unwrap());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_with_err(&mut self) -> Result<(), ApiError> {
|
|
||||||
let res = tokio::runtime::Runtime::new().unwrap().block_on(async {
|
|
||||||
self.send().await
|
|
||||||
}).map_err(ApiError::RequestError)?;
|
|
||||||
if res.status().is_success() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(ApiError::IncorrectRequest(res))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use chrono::{Utc, DateTime};
|
use chrono::{Utc, DateTime};
|
||||||
use reqwest::{Method, Response, Error};
|
use reqwest::Method;
|
||||||
use xml::reader::{EventReader, XmlEvent};
|
use xml::reader::{EventReader, XmlEvent};
|
||||||
use reqwest::header::HeaderValue;
|
use reqwest::header::HeaderValue;
|
||||||
use crate::commands::clone::get_url_props;
|
use crate::commands::clone::get_url_props;
|
||||||
@ -8,6 +8,7 @@ use crate::commands::config;
|
|||||||
use crate::utils::time::parse_timestamp;
|
use crate::utils::time::parse_timestamp;
|
||||||
use crate::utils::api::{get_relative_s, ApiProps};
|
use crate::utils::api::{get_relative_s, ApiProps};
|
||||||
use crate::services::api::{ApiBuilder, ApiError};
|
use crate::services::api::{ApiBuilder, ApiError};
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ObjProps {
|
pub struct ObjProps {
|
||||||
@ -55,8 +56,8 @@ pub struct ReqProps {
|
|||||||
api_props: Option<ApiProps>
|
api_props: Option<ApiProps>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReqProps {
|
impl ApiCall for ReqProps {
|
||||||
pub fn new() -> Self {
|
fn new() -> Self {
|
||||||
ReqProps {
|
ReqProps {
|
||||||
api_builder: ApiBuilder::new(),
|
api_builder: ApiBuilder::new(),
|
||||||
xml_balises: vec![],
|
xml_balises: vec![],
|
||||||
@ -65,7 +66,7 @@ impl ReqProps {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_url(&mut self, url: &str) -> &mut ReqProps {
|
fn set_url(&mut self, url: &str) -> &mut ReqProps {
|
||||||
let remote = match config::get("remote") {
|
let remote = match config::get("remote") {
|
||||||
Some(r) => r,
|
Some(r) => r,
|
||||||
None => {
|
None => {
|
||||||
@ -83,6 +84,13 @@ impl ReqProps {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send(&mut self) -> Result<Option<String>, ApiError> {
|
||||||
|
self.validate_xml();
|
||||||
|
self.api_builder.send(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReqProps {
|
||||||
pub fn set_request(&mut self, p: &str, api_props: &ApiProps) -> &mut ReqProps {
|
pub fn set_request(&mut self, p: &str, api_props: &ApiProps) -> &mut ReqProps {
|
||||||
self.api_props = Some(api_props.clone());
|
self.api_props = Some(api_props.clone());
|
||||||
self.api_builder.set_req(Method::from_bytes(b"PROPFIND").unwrap(), p, api_props);
|
self.api_builder.set_req(Method::from_bytes(b"PROPFIND").unwrap(), p, api_props);
|
||||||
@ -145,32 +153,10 @@ impl ReqProps {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&mut self) -> Result<Response, Error> {
|
|
||||||
self.validate_xml();
|
|
||||||
self.api_builder.send().await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_with_err(&mut self) -> Result<String, ApiError> {
|
|
||||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
|
||||||
match self.send().await {
|
|
||||||
Err(res) => Err(ApiError::RequestError(res)),
|
|
||||||
Ok(res) if res.status().is_success() => {
|
|
||||||
let body = res
|
|
||||||
.text()
|
|
||||||
.await
|
|
||||||
.map_err(|err| ApiError::EmptyError(err))?;
|
|
||||||
Ok(body)
|
|
||||||
},
|
|
||||||
Ok(res) => {
|
|
||||||
Err(ApiError::IncorrectRequest(res))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_req_multiple(&mut self) -> Result<Vec<ObjProps>, ApiError> {
|
pub fn send_req_multiple(&mut self) -> Result<Vec<ObjProps>, ApiError> {
|
||||||
match self.send_with_err() {
|
match self.send() {
|
||||||
Ok(body) => Ok(self.parse(body, true)),
|
Ok(Some(body)) => Ok(self.parse(body, true)),
|
||||||
|
Ok(None) => Err(ApiError::Unexpected(String::from("Empty after tested"))),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,12 +164,13 @@ impl ReqProps {
|
|||||||
pub fn send_req_single(&mut self) -> Result<ObjProps, ApiError> {
|
pub fn send_req_single(&mut self) -> Result<ObjProps, ApiError> {
|
||||||
// set depth to 0 as we only need one element
|
// set depth to 0 as we only need one element
|
||||||
self.set_depth("0");
|
self.set_depth("0");
|
||||||
match self.send_with_err() {
|
match self.send() {
|
||||||
Ok(body) => {
|
Ok(Some(body)) => {
|
||||||
let objs = self.parse(body, false);
|
let objs = self.parse(body, false);
|
||||||
let obj = objs[0].clone();
|
let obj = objs[0].clone();
|
||||||
Ok(obj)
|
Ok(obj)
|
||||||
},
|
},
|
||||||
|
Ok(None) => Err(ApiError::Unexpected(String::from("Empty after tested"))),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
73
src/services/request_manager.rs
Normal file
73
src/services/request_manager.rs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
use lazy_static::lazy_static;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use crate::services::login::Login;
|
||||||
|
use crate::commands::config;
|
||||||
|
use crate::commands::clone::get_url_props;
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref REQUEST_MANAGER: Mutex<Option<RequestManager>> = Mutex::new(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_request_manager() -> &'static Mutex<Option<RequestManager>> {
|
||||||
|
if REQUEST_MANAGER.lock().unwrap().is_none() {
|
||||||
|
*REQUEST_MANAGER.lock().unwrap() = Some(RequestManager::new());
|
||||||
|
}
|
||||||
|
&REQUEST_MANAGER
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RequestManager {
|
||||||
|
token: Option<String>,
|
||||||
|
host: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RequestManager {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
RequestManager {
|
||||||
|
token: None,
|
||||||
|
host: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_host(&mut self, host: String) {
|
||||||
|
self.host = Some(host);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_host(&mut self) -> String
|
||||||
|
{
|
||||||
|
if self.host.is_none()
|
||||||
|
{
|
||||||
|
let remote = match config::get("remote") {
|
||||||
|
Some(r) => r,
|
||||||
|
None => {
|
||||||
|
// todo ask user instead
|
||||||
|
eprintln!("fatal: unable to find a remote");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let (host, _, _) = get_url_props(&remote);
|
||||||
|
self.host = Some(host.clone());
|
||||||
|
// todo ask user
|
||||||
|
}
|
||||||
|
self.host.clone().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_token(&mut self) -> String {
|
||||||
|
if self.token.is_none() {
|
||||||
|
// todo check in config
|
||||||
|
let get_token = Login::new()
|
||||||
|
.ask_auth()
|
||||||
|
.set_host(Some(self.get_host()))
|
||||||
|
.send_login();
|
||||||
|
// todo deal with error cases
|
||||||
|
self.token = Some(get_token.unwrap());
|
||||||
|
}
|
||||||
|
self.token.clone().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_request()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +1,32 @@
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use reqwest::{Method, Response, Error};
|
use reqwest::Method;
|
||||||
use crate::services::api::{ApiBuilder, ApiError};
|
use crate::services::api::{ApiBuilder, ApiError};
|
||||||
|
use crate::services::api_call::ApiCall;
|
||||||
|
|
||||||
pub struct UploadFile {
|
pub struct UploadFile {
|
||||||
api_builder: ApiBuilder,
|
api_builder: ApiBuilder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UploadFile {
|
impl ApiCall for UploadFile {
|
||||||
pub fn new() -> Self {
|
fn new() -> Self {
|
||||||
UploadFile {
|
UploadFile {
|
||||||
api_builder: ApiBuilder::new(),
|
api_builder: ApiBuilder::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_url(&mut self, url: &str) -> &mut UploadFile {
|
fn set_url(&mut self, url: &str) -> &mut UploadFile {
|
||||||
self.api_builder.build_request(Method::PUT, url);
|
self.api_builder.build_request(Method::PUT, url);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send(&mut self) -> Result<Option<String>, ApiError> {
|
||||||
|
self.api_builder.send(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UploadFile {
|
||||||
pub fn set_file(&mut self, path: PathBuf) -> &mut UploadFile {
|
pub fn set_file(&mut self, path: PathBuf) -> &mut UploadFile {
|
||||||
// todo large file
|
// todo large file
|
||||||
// todo small files
|
// todo small files
|
||||||
@ -29,23 +36,4 @@ impl UploadFile {
|
|||||||
self.api_builder.set_body(buffer);
|
self.api_builder.set_body(buffer);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&mut self) -> Result<Response, Error> {
|
|
||||||
self.api_builder.send().await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_with_err(&mut self) -> Result<String, ApiError> {
|
|
||||||
let res = tokio::runtime::Runtime::new().unwrap().block_on(async {
|
|
||||||
self.send().await
|
|
||||||
}).map_err(ApiError::RequestError)?;
|
|
||||||
|
|
||||||
if res.status().is_success() {
|
|
||||||
let body = tokio::runtime::Runtime::new().unwrap().block_on(async {
|
|
||||||
res.text().await
|
|
||||||
}).map_err(ApiError::EmptyError)?;
|
|
||||||
Ok(body)
|
|
||||||
} else {
|
|
||||||
Err(ApiError::IncorrectRequest(res))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user