use crate::addr::access_ctrl::serv::NetAccessCtrl;
use crate::addr::{AddrResult, Address};
use crate::prelude::*;
use crate::types::{ResourceDownloader, ResourceUploader, UpdateUnit};
use crate::update::{DownloadOptions, UploadOptions};
use log::error;
use orion_conf::YamlIO;
use std::path::{Path, PathBuf};
use super::git::GitAccessor;
use super::http::HttpAccessor;
use super::local::LocalAccessor;
#[derive(Debug, Clone, Default)]
pub struct UniversalConfig {
pub accs_ctrl: Option<NetAccessCtrl>,
}
impl UniversalConfig {
pub fn with_ctrl(mut self, ctrl: NetAccessCtrl) -> Self {
self.accs_ctrl = Some(ctrl);
self
}
pub fn with_ctrl_file(mut self, path: &Path) -> Self {
if path.exists() {
match NetAccessCtrl::load_yaml(path) {
Ok(redirect) => {
self.accs_ctrl = Some(redirect);
}
Err(e) => {
error!("load redirect conf failed!\npath:{} \n{e}", path.display());
}
}
}
self
}
pub fn with_file_opt(self, path_opt: &Option<PathBuf>) -> Self {
if let Some(path) = path_opt {
return self.with_ctrl_file(path.as_path());
}
self
}
}
#[cfg(test)]
mod config_tests {
use super::*;
#[test]
fn test_universal_config_builder_pattern() {
let net_ctrl = NetAccessCtrl::new(vec![], true);
let config = UniversalConfig::default().with_ctrl(net_ctrl);
assert!(config.accs_ctrl.is_some());
}
#[test]
fn test_universal_config_file_handling() {
let test_path = PathBuf::from("nonexistent_config.yml");
let none_path: Option<PathBuf> = None;
let config_with_none = UniversalConfig::default().with_file_opt(&none_path);
assert!(config_with_none.accs_ctrl.is_none());
let config_with_path = UniversalConfig::default().with_file_opt(&Some(test_path));
assert!(config_with_path.accs_ctrl.is_none());
}
}
#[derive(Debug, Default)]
pub struct UniversalAccessor {
git: GitAccessor,
http: HttpAccessor,
local: LocalAccessor,
config: UniversalConfig,
}
impl UniversalAccessor {
pub fn new(config: UniversalConfig) -> Self {
let git = GitAccessor::default().with_ctrl(config.accs_ctrl.clone());
let http = HttpAccessor::default().with_ctrl(config.accs_ctrl.clone());
let local = LocalAccessor::default();
Self {
git,
http,
local,
config,
}
}
pub fn config(&self) -> &UniversalConfig {
&self.config
}
pub fn config_mut(&mut self) -> &mut UniversalConfig {
&mut self.config
}
}
#[async_trait]
impl ResourceDownloader for UniversalAccessor {
async fn download_to_local(
&self,
addr: &Address,
path: &Path,
options: &DownloadOptions,
) -> AddrResult<UpdateUnit> {
match addr {
Address::Git(_) => self.git.download_to_local(addr, path, options).await,
Address::Http(_) => self.http.download_to_local(addr, path, options).await,
Address::Local(_) => self.local.download_to_local(addr, path, options).await,
}
}
}
#[async_trait]
impl ResourceUploader for UniversalAccessor {
async fn upload_from_local(
&self,
addr: &Address,
path: &Path,
options: &UploadOptions,
) -> AddrResult<UpdateUnit> {
match addr {
Address::Git(_) => self.git.upload_from_local(addr, path, options).await,
Address::Http(_) => self.http.upload_from_local(addr, path, options).await,
Address::Local(_) => self.local.upload_from_local(addr, path, options).await,
}
}
}
impl Clone for UniversalAccessor {
fn clone(&self) -> Self {
Self {
git: self.git.clone(),
http: self.http.clone(),
local: self.local.clone(),
config: self.config.clone(),
}
}
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use orion_error::TestAssert;
use super::*;
use crate::addr::{Address, GitRepository, LocalPath};
#[tokio::test]
async fn test_select_accessor() {
let config = UniversalConfig::default();
let accessor = UniversalAccessor::new(config);
let dest_path = PathBuf::from("./temp/hello-word.git");
if dest_path.exists() {
std::fs::remove_dir_all(&dest_path).assert();
}
let git_addr = Address::Git(GitRepository::from(
"https://github.com/galaxy-sec/hello-word.git",
));
accessor
.download_to_local(
&git_addr,
&PathBuf::from("./temp/"),
&DownloadOptions::default(),
)
.await
.assert();
}
#[test]
fn test_universal_accessor_config_accessors() {
let config = UniversalConfig::default();
let mut accessor = UniversalAccessor::new(config);
let config_ref = accessor.config();
assert_eq!(config_ref.accs_ctrl, None);
let net_ctrl = NetAccessCtrl::new(vec![], true);
accessor.config_mut().accs_ctrl = Some(net_ctrl);
let updated_config_ref = accessor.config();
assert!(updated_config_ref.accs_ctrl.is_some());
}
#[tokio::test]
async fn test_universal_accessor_upload_functionality() {
let config = UniversalConfig::default();
let accessor = UniversalAccessor::new(config);
let temp_dir = tempfile::tempdir().unwrap();
let temp_file = temp_dir.path().join("test_file.txt");
std::fs::write(&temp_file, "test content").unwrap();
let local_addr = Address::Local(LocalPath::from(
temp_file.clone().display().to_string().as_str(),
));
let upload_result = accessor
.upload_from_local(&local_addr, temp_dir.path(), &UploadOptions::default())
.await;
match upload_result {
Ok(_) => {} Err(e) => println!("Upload failed as expected: {e}"), }
}
}