mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Aws s3 support
This commit is contained in:
@@ -25,31 +25,57 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use crate::filetransfer::params::{AwsS3Params, GenericProtocolParams, ProtocolParams};
|
||||
use crate::filetransfer::{FileTransferParams, FileTransferProtocol};
|
||||
|
||||
use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Deserialize, Serialize, std::fmt::Debug)]
|
||||
/// ## UserHosts
|
||||
///
|
||||
/// UserHosts contains all the hosts saved by the user in the data storage
|
||||
/// It contains both `Bookmark`
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct UserHosts {
|
||||
pub bookmarks: HashMap<String, Bookmark>,
|
||||
pub recents: HashMap<String, Bookmark>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, std::fmt::Debug, PartialEq)]
|
||||
/// ## Bookmark
|
||||
///
|
||||
/// Bookmark describes a single bookmark entry in the user hosts storage
|
||||
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq)]
|
||||
pub struct Bookmark {
|
||||
pub address: String,
|
||||
pub port: u16,
|
||||
pub protocol: String,
|
||||
pub username: String,
|
||||
pub password: Option<String>, // Password is optional; base64, aes-128 encrypted password
|
||||
#[serde(
|
||||
deserialize_with = "deserialize_protocol",
|
||||
serialize_with = "serialize_protocol"
|
||||
)]
|
||||
pub protocol: FileTransferProtocol,
|
||||
/// Address for generic parameters
|
||||
pub address: Option<String>,
|
||||
/// Port number for generic parameters
|
||||
pub port: Option<u16>,
|
||||
/// Username for generic parameters
|
||||
pub username: Option<String>,
|
||||
/// Password is optional; base64, aes-128 encrypted password
|
||||
pub password: Option<String>,
|
||||
/// S3 params; optional. When used other fields are empty for sure
|
||||
pub s3: Option<S3Params>,
|
||||
}
|
||||
|
||||
/// ## S3Params
|
||||
///
|
||||
/// Connection parameters for Aws s3 protocol
|
||||
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Default)]
|
||||
pub struct S3Params {
|
||||
pub bucket: String,
|
||||
pub region: String,
|
||||
pub profile: Option<String>,
|
||||
}
|
||||
|
||||
// -- impls
|
||||
|
||||
impl Default for UserHosts {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
@@ -59,6 +85,87 @@ impl Default for UserHosts {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FileTransferParams> for Bookmark {
|
||||
fn from(params: FileTransferParams) -> Self {
|
||||
let protocol: FileTransferProtocol = params.protocol;
|
||||
// Create generic or others
|
||||
match params.params {
|
||||
ProtocolParams::Generic(params) => Self {
|
||||
protocol,
|
||||
address: Some(params.address),
|
||||
port: Some(params.port),
|
||||
username: params.username,
|
||||
password: params.password,
|
||||
s3: None,
|
||||
},
|
||||
ProtocolParams::AwsS3(params) => Self {
|
||||
protocol,
|
||||
address: None,
|
||||
port: None,
|
||||
username: None,
|
||||
password: None,
|
||||
s3: Some(S3Params::from(params)),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Bookmark> for FileTransferParams {
|
||||
fn from(bookmark: Bookmark) -> Self {
|
||||
// Create generic or others based on protocol
|
||||
match bookmark.protocol {
|
||||
FileTransferProtocol::AwsS3 => {
|
||||
let params = bookmark.s3.unwrap_or_default();
|
||||
let params = AwsS3Params::from(params);
|
||||
Self::new(FileTransferProtocol::AwsS3, ProtocolParams::AwsS3(params))
|
||||
}
|
||||
protocol => {
|
||||
let params = GenericProtocolParams::default()
|
||||
.address(bookmark.address.unwrap_or_default())
|
||||
.port(bookmark.port.unwrap_or(22))
|
||||
.username(bookmark.username)
|
||||
.password(bookmark.password);
|
||||
Self::new(protocol, ProtocolParams::Generic(params))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AwsS3Params> for S3Params {
|
||||
fn from(params: AwsS3Params) -> Self {
|
||||
S3Params {
|
||||
bucket: params.bucket_name,
|
||||
region: params.region,
|
||||
profile: params.profile,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<S3Params> for AwsS3Params {
|
||||
fn from(params: S3Params) -> Self {
|
||||
AwsS3Params::new(params.bucket, params.region, params.profile)
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_protocol<'de, D>(deserializer: D) -> Result<FileTransferProtocol, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s: &str = Deserialize::deserialize(deserializer)?;
|
||||
// Parse color
|
||||
match FileTransferProtocol::from_str(s) {
|
||||
Err(err) => Err(DeError::custom(err)),
|
||||
Ok(protocol) => Ok(protocol),
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_protocol<S>(protocol: &FileTransferProtocol, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(protocol.to_string().as_str())
|
||||
}
|
||||
|
||||
// Tests
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -77,48 +184,117 @@ mod tests {
|
||||
#[test]
|
||||
fn test_bookmarks_bookmark_new() {
|
||||
let bookmark: Bookmark = Bookmark {
|
||||
address: String::from("192.168.1.1"),
|
||||
port: 22,
|
||||
protocol: String::from("SFTP"),
|
||||
username: String::from("root"),
|
||||
address: Some(String::from("192.168.1.1")),
|
||||
port: Some(22),
|
||||
protocol: FileTransferProtocol::Sftp,
|
||||
username: Some(String::from("root")),
|
||||
password: Some(String::from("password")),
|
||||
s3: None,
|
||||
};
|
||||
let recent: Bookmark = Bookmark {
|
||||
address: String::from("192.168.1.2"),
|
||||
port: 22,
|
||||
protocol: String::from("SCP"),
|
||||
username: String::from("admin"),
|
||||
address: Some(String::from("192.168.1.2")),
|
||||
port: Some(22),
|
||||
protocol: FileTransferProtocol::Scp,
|
||||
username: Some(String::from("admin")),
|
||||
password: Some(String::from("password")),
|
||||
s3: None,
|
||||
};
|
||||
let mut bookmarks: HashMap<String, Bookmark> = HashMap::with_capacity(1);
|
||||
bookmarks.insert(String::from("test"), bookmark);
|
||||
let mut recents: HashMap<String, Bookmark> = HashMap::with_capacity(1);
|
||||
recents.insert(String::from("ISO20201218T181432"), recent);
|
||||
let hosts: UserHosts = UserHosts {
|
||||
bookmarks: bookmarks,
|
||||
recents: recents,
|
||||
};
|
||||
let hosts: UserHosts = UserHosts { bookmarks, recents };
|
||||
// Verify
|
||||
let bookmark: &Bookmark = hosts.bookmarks.get(&String::from("test")).unwrap();
|
||||
assert_eq!(bookmark.address, String::from("192.168.1.1"));
|
||||
assert_eq!(bookmark.port, 22);
|
||||
assert_eq!(bookmark.protocol, String::from("SFTP"));
|
||||
assert_eq!(bookmark.username, String::from("root"));
|
||||
assert_eq!(
|
||||
*bookmark.password.as_ref().unwrap(),
|
||||
String::from("password")
|
||||
);
|
||||
assert_eq!(bookmark.address.as_deref().unwrap(), "192.168.1.1");
|
||||
assert_eq!(bookmark.port.unwrap(), 22);
|
||||
assert_eq!(bookmark.protocol, FileTransferProtocol::Sftp);
|
||||
assert_eq!(bookmark.username.as_deref().unwrap(), "root");
|
||||
assert_eq!(bookmark.password.as_deref().unwrap(), "password");
|
||||
let bookmark: &Bookmark = hosts
|
||||
.recents
|
||||
.get(&String::from("ISO20201218T181432"))
|
||||
.unwrap();
|
||||
assert_eq!(bookmark.address, String::from("192.168.1.2"));
|
||||
assert_eq!(bookmark.port, 22);
|
||||
assert_eq!(bookmark.protocol, String::from("SCP"));
|
||||
assert_eq!(bookmark.username, String::from("admin"));
|
||||
assert_eq!(
|
||||
*bookmark.password.as_ref().unwrap(),
|
||||
String::from("password")
|
||||
);
|
||||
assert_eq!(bookmark.address.as_deref().unwrap(), "192.168.1.2");
|
||||
assert_eq!(bookmark.port.unwrap(), 22);
|
||||
assert_eq!(bookmark.protocol, FileTransferProtocol::Scp);
|
||||
assert_eq!(bookmark.username.as_deref().unwrap(), "admin");
|
||||
assert_eq!(bookmark.password.as_deref().unwrap(), "password");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bookmark_from_generic_ftparams() {
|
||||
let params = ProtocolParams::Generic(GenericProtocolParams {
|
||||
address: "127.0.0.1".to_string(),
|
||||
port: 10222,
|
||||
username: Some(String::from("root")),
|
||||
password: Some(String::from("omar")),
|
||||
});
|
||||
let params: FileTransferParams = FileTransferParams::new(FileTransferProtocol::Scp, params);
|
||||
let bookmark = Bookmark::from(params);
|
||||
assert_eq!(bookmark.protocol, FileTransferProtocol::Scp);
|
||||
assert_eq!(bookmark.address.as_deref().unwrap(), "127.0.0.1");
|
||||
assert_eq!(bookmark.port.unwrap(), 10222);
|
||||
assert_eq!(bookmark.username.as_deref().unwrap(), "root");
|
||||
assert_eq!(bookmark.password.as_deref().unwrap(), "omar");
|
||||
assert!(bookmark.s3.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bookmark_from_s3_ftparams() {
|
||||
let params = ProtocolParams::AwsS3(AwsS3Params::new("omar", "eu-west-1", Some("test")));
|
||||
let params: FileTransferParams =
|
||||
FileTransferParams::new(FileTransferProtocol::AwsS3, params);
|
||||
let bookmark = Bookmark::from(params);
|
||||
assert_eq!(bookmark.protocol, FileTransferProtocol::AwsS3);
|
||||
assert!(bookmark.address.is_none());
|
||||
assert!(bookmark.port.is_none());
|
||||
assert!(bookmark.username.is_none());
|
||||
assert!(bookmark.password.is_none());
|
||||
let s3: &S3Params = bookmark.s3.as_ref().unwrap();
|
||||
assert_eq!(s3.bucket.as_str(), "omar");
|
||||
assert_eq!(s3.region.as_str(), "eu-west-1");
|
||||
assert_eq!(s3.profile.as_deref().unwrap(), "test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ftparams_from_generic_bookmark() {
|
||||
let bookmark: Bookmark = Bookmark {
|
||||
address: Some(String::from("192.168.1.1")),
|
||||
port: Some(22),
|
||||
protocol: FileTransferProtocol::Sftp,
|
||||
username: Some(String::from("root")),
|
||||
password: Some(String::from("password")),
|
||||
s3: None,
|
||||
};
|
||||
let params = FileTransferParams::from(bookmark);
|
||||
assert_eq!(params.protocol, FileTransferProtocol::Sftp);
|
||||
let gparams = params.params.generic_params().unwrap();
|
||||
assert_eq!(gparams.address.as_str(), "192.168.1.1");
|
||||
assert_eq!(gparams.port, 22);
|
||||
assert_eq!(gparams.username.as_deref().unwrap(), "root");
|
||||
assert_eq!(gparams.password.as_deref().unwrap(), "password");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ftparams_from_s3_bookmark() {
|
||||
let bookmark: Bookmark = Bookmark {
|
||||
protocol: FileTransferProtocol::AwsS3,
|
||||
address: None,
|
||||
port: None,
|
||||
username: None,
|
||||
password: None,
|
||||
s3: Some(S3Params {
|
||||
bucket: String::from("veeso"),
|
||||
region: String::from("eu-west-1"),
|
||||
profile: None,
|
||||
}),
|
||||
};
|
||||
let params = FileTransferParams::from(bookmark);
|
||||
assert_eq!(params.protocol, FileTransferProtocol::AwsS3);
|
||||
let gparams = params.params.s3_params().unwrap();
|
||||
assert_eq!(gparams.bucket_name.as_str(), "veeso");
|
||||
assert_eq!(gparams.region.as_str(), "eu-west-1");
|
||||
assert_eq!(gparams.profile, None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,17 +141,19 @@ where
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
use crate::config::bookmarks::{Bookmark, S3Params, UserHosts};
|
||||
use crate::config::params::UserConfig;
|
||||
use crate::config::themes::Theme;
|
||||
use crate::filetransfer::FileTransferProtocol;
|
||||
use crate::utils::test_helpers::create_file_ioers;
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::collections::HashMap;
|
||||
use std::io::{Seek, SeekFrom};
|
||||
use std::path::PathBuf;
|
||||
use tuirealm::tui::style::Color;
|
||||
|
||||
use crate::config::bookmarks::{Bookmark, UserHosts};
|
||||
use crate::config::params::UserConfig;
|
||||
use crate::config::themes::Theme;
|
||||
use crate::utils::test_helpers::create_file_ioers;
|
||||
|
||||
#[test]
|
||||
fn test_config_serialization_errors() {
|
||||
let error: SerializerError = SerializerError::new(SerializerErrorKind::Syntax);
|
||||
@@ -373,31 +375,42 @@ mod tests {
|
||||
// Verify recents
|
||||
assert_eq!(hosts.recents.len(), 1);
|
||||
let host: &Bookmark = hosts.recents.get("ISO20201215T094000Z").unwrap();
|
||||
assert_eq!(host.address, String::from("172.16.104.10"));
|
||||
assert_eq!(host.port, 22);
|
||||
assert_eq!(host.protocol, String::from("SCP"));
|
||||
assert_eq!(host.username, String::from("root"));
|
||||
assert_eq!(host.address.as_deref().unwrap(), "172.16.104.10");
|
||||
assert_eq!(host.port.unwrap(), 22);
|
||||
assert_eq!(host.protocol, FileTransferProtocol::Scp);
|
||||
assert_eq!(host.username.as_deref().unwrap(), "root");
|
||||
assert_eq!(host.password, None);
|
||||
// Verify bookmarks
|
||||
assert_eq!(hosts.bookmarks.len(), 3);
|
||||
assert_eq!(hosts.bookmarks.len(), 4);
|
||||
let host: &Bookmark = hosts.bookmarks.get("raspberrypi2").unwrap();
|
||||
assert_eq!(host.address, String::from("192.168.1.31"));
|
||||
assert_eq!(host.port, 22);
|
||||
assert_eq!(host.protocol, String::from("SFTP"));
|
||||
assert_eq!(host.username, String::from("root"));
|
||||
assert_eq!(*host.password.as_ref().unwrap(), String::from("mypassword"));
|
||||
assert_eq!(host.address.as_deref().unwrap(), "192.168.1.31");
|
||||
assert_eq!(host.port.unwrap(), 22);
|
||||
assert_eq!(host.protocol, FileTransferProtocol::Sftp);
|
||||
assert_eq!(host.username.as_deref().unwrap(), "root");
|
||||
assert_eq!(host.password.as_deref().unwrap(), "mypassword");
|
||||
let host: &Bookmark = hosts.bookmarks.get("msi-estrem").unwrap();
|
||||
assert_eq!(host.address, String::from("192.168.1.30"));
|
||||
assert_eq!(host.port, 22);
|
||||
assert_eq!(host.protocol, String::from("SFTP"));
|
||||
assert_eq!(host.username, String::from("cvisintin"));
|
||||
assert_eq!(*host.password.as_ref().unwrap(), String::from("mysecret"));
|
||||
assert_eq!(host.address.as_deref().unwrap(), "192.168.1.30");
|
||||
assert_eq!(host.port.unwrap(), 22);
|
||||
assert_eq!(host.protocol, FileTransferProtocol::Sftp);
|
||||
assert_eq!(host.username.as_deref().unwrap(), "cvisintin");
|
||||
assert_eq!(host.password.as_deref().unwrap(), "mysecret");
|
||||
let host: &Bookmark = hosts.bookmarks.get("aws-server-prod1").unwrap();
|
||||
assert_eq!(host.address, String::from("51.23.67.12"));
|
||||
assert_eq!(host.port, 21);
|
||||
assert_eq!(host.protocol, String::from("FTPS"));
|
||||
assert_eq!(host.username, String::from("aws001"));
|
||||
assert_eq!(host.address.as_deref().unwrap(), "51.23.67.12");
|
||||
assert_eq!(host.port.unwrap(), 21);
|
||||
assert_eq!(host.protocol, FileTransferProtocol::Ftp(true));
|
||||
assert_eq!(host.username.as_deref().unwrap(), "aws001");
|
||||
assert_eq!(host.password, None);
|
||||
// Aws s3 bucket
|
||||
let host: &Bookmark = hosts.bookmarks.get("my-bucket").unwrap();
|
||||
assert_eq!(host.address, None);
|
||||
assert_eq!(host.port, None);
|
||||
assert_eq!(host.username, None);
|
||||
assert_eq!(host.password, None);
|
||||
assert_eq!(host.protocol, FileTransferProtocol::AwsS3);
|
||||
let s3 = host.s3.as_ref().unwrap();
|
||||
assert_eq!(s3.bucket.as_str(), "veeso");
|
||||
assert_eq!(s3.region.as_str(), "eu-west-1");
|
||||
assert_eq!(s3.profile.as_deref().unwrap(), "default");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -416,32 +429,50 @@ mod tests {
|
||||
bookmarks.insert(
|
||||
String::from("raspberrypi2"),
|
||||
Bookmark {
|
||||
address: String::from("192.168.1.31"),
|
||||
port: 22,
|
||||
protocol: String::from("SFTP"),
|
||||
username: String::from("root"),
|
||||
address: Some(String::from("192.168.1.31")),
|
||||
port: Some(22),
|
||||
protocol: FileTransferProtocol::Sftp,
|
||||
username: Some(String::from("root")),
|
||||
password: None,
|
||||
s3: None,
|
||||
},
|
||||
);
|
||||
bookmarks.insert(
|
||||
String::from("msi-estrem"),
|
||||
Bookmark {
|
||||
address: String::from("192.168.1.30"),
|
||||
port: 4022,
|
||||
protocol: String::from("SFTP"),
|
||||
username: String::from("cvisintin"),
|
||||
address: Some(String::from("192.168.1.30")),
|
||||
port: Some(4022),
|
||||
protocol: FileTransferProtocol::Sftp,
|
||||
username: Some(String::from("cvisintin")),
|
||||
password: Some(String::from("password")),
|
||||
s3: None,
|
||||
},
|
||||
);
|
||||
bookmarks.insert(
|
||||
String::from("my-bucket"),
|
||||
Bookmark {
|
||||
address: None,
|
||||
port: None,
|
||||
protocol: FileTransferProtocol::AwsS3,
|
||||
username: None,
|
||||
password: None,
|
||||
s3: Some(S3Params {
|
||||
bucket: "veeso".to_string(),
|
||||
region: "eu-west-1".to_string(),
|
||||
profile: None,
|
||||
}),
|
||||
},
|
||||
);
|
||||
let mut recents: HashMap<String, Bookmark> = HashMap::with_capacity(1);
|
||||
recents.insert(
|
||||
String::from("ISO20201215T094000Z"),
|
||||
Bookmark {
|
||||
address: String::from("192.168.1.254"),
|
||||
port: 3022,
|
||||
protocol: String::from("SCP"),
|
||||
username: String::from("omar"),
|
||||
address: Some(String::from("192.168.1.254")),
|
||||
port: Some(3022),
|
||||
protocol: FileTransferProtocol::Scp,
|
||||
username: Some(String::from("omar")),
|
||||
password: Some(String::from("aaa")),
|
||||
s3: None,
|
||||
},
|
||||
);
|
||||
let tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap();
|
||||
@@ -482,6 +513,14 @@ mod tests {
|
||||
raspberrypi2 = { address = "192.168.1.31", port = 22, protocol = "SFTP", username = "root", password = "mypassword" }
|
||||
msi-estrem = { address = "192.168.1.30", port = 22, protocol = "SFTP", username = "cvisintin", password = "mysecret" }
|
||||
aws-server-prod1 = { address = "51.23.67.12", port = 21, protocol = "FTPS", username = "aws001" }
|
||||
|
||||
[bookmarks.my-bucket]
|
||||
protocol = "S3"
|
||||
|
||||
[bookmarks.my-bucket.s3]
|
||||
bucket = "veeso"
|
||||
region = "eu-west-1"
|
||||
profile = "default"
|
||||
|
||||
[recents]
|
||||
ISO20201215T094000Z = { address = "172.16.104.10", port = 22, protocol = "SCP", username = "root" }
|
||||
@@ -497,7 +536,7 @@ mod tests {
|
||||
let file_content: &str = r#"
|
||||
[bookmarks]
|
||||
raspberrypi2 = { address = "192.168.1.31", port = 22, protocol = "SFTP", username = "root"}
|
||||
msi-estrem = { address = "192.168.1.30", port = 22, protocol = "SFTP" }
|
||||
msi-estrem = { address = "192.168.1.30", port = 22 }
|
||||
aws-server-prod1 = { address = "51.23.67.12", port = 21, protocol = "FTPS", username = "aws001" }
|
||||
|
||||
[recents]
|
||||
|
||||
Reference in New Issue
Block a user