mirror of
https://github.com/pimalaya/himalaya.git
synced 2026-06-19 23:25:14 +08:00
fix wizard serialization issues
This commit is contained in:
@@ -45,10 +45,10 @@ pub struct TomlAccountConfig {
|
||||
pub flag: Option<FlagConfig>,
|
||||
pub message: Option<MessageConfig>,
|
||||
|
||||
#[cfg(feature = "maildir")]
|
||||
pub maildir: Option<MaildirConfig>,
|
||||
#[cfg(feature = "imap")]
|
||||
pub imap: Option<ImapConfig>,
|
||||
#[cfg(feature = "maildir")]
|
||||
pub maildir: Option<MaildirConfig>,
|
||||
#[cfg(feature = "notmuch")]
|
||||
pub notmuch: Option<NotmuchConfig>,
|
||||
#[cfg(feature = "smtp")]
|
||||
|
||||
+359
-10
@@ -94,16 +94,21 @@ pub(crate) async fn configure(path: PathBuf) -> Result<TomlConfig> {
|
||||
let path = expand::path(path);
|
||||
|
||||
println!("Writing the configuration to {path:?}…");
|
||||
let toml = pretty_serialize(&config)?;
|
||||
fs::create_dir_all(path.parent().unwrap_or(&path))?;
|
||||
fs::write(path, toml)?;
|
||||
|
||||
let mut doc = toml::to_string(&config)?.parse::<Document>()?;
|
||||
println!("Exiting the wizard…");
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
fn pretty_serialize(config: &TomlConfig) -> Result<String> {
|
||||
let mut doc: Document = toml::to_string(&config)?.parse()?;
|
||||
|
||||
doc.iter_mut().for_each(|(_, item)| {
|
||||
set_table_dotted(item, "folder-aliases");
|
||||
set_table_dotted(item, "sync-folders-strategy");
|
||||
|
||||
set_table_dotted(item, "folder");
|
||||
if let Some(item) = get_table_mut(item, "folder") {
|
||||
set_tables_dotted(item, ["add", "list", "expunge", "purge", "delete"]);
|
||||
set_tables_dotted(item, ["alias", "add", "list", "expunge", "purge", "delete"]);
|
||||
}
|
||||
|
||||
set_table_dotted(item, "envelope");
|
||||
@@ -124,7 +129,9 @@ pub(crate) async fn configure(path: PathBuf) -> Result<TomlConfig> {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "maildir")]
|
||||
set_table_dotted(item, "maildir");
|
||||
|
||||
#[cfg(feature = "imap")]
|
||||
{
|
||||
set_table_dotted(item, "imap");
|
||||
@@ -132,9 +139,10 @@ pub(crate) async fn configure(path: PathBuf) -> Result<TomlConfig> {
|
||||
set_tables_dotted(item, ["passwd", "oauth2"]);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "notmuch")]
|
||||
set_table_dotted(item, "notmuch");
|
||||
set_table_dotted(item, "sendmail");
|
||||
|
||||
#[cfg(feature = "smtp")]
|
||||
{
|
||||
set_table_dotted(item, "smtp");
|
||||
@@ -143,14 +151,22 @@ pub(crate) async fn configure(path: PathBuf) -> Result<TomlConfig> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sendmail")]
|
||||
set_table_dotted(item, "sendmail");
|
||||
|
||||
#[cfg(feature = "account-sync")]
|
||||
{
|
||||
set_table_dotted(item, "sync");
|
||||
if let Some(item) = get_table_mut(item, "sync") {
|
||||
set_tables_dotted(item, ["strategy"]);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "pgp")]
|
||||
set_table_dotted(item, "pgp");
|
||||
});
|
||||
|
||||
fs::create_dir_all(path.parent().unwrap_or(&path))?;
|
||||
fs::write(path, doc.to_string())?;
|
||||
|
||||
Ok(config)
|
||||
Ok(doc.to_string())
|
||||
}
|
||||
|
||||
fn get_table_mut<'a>(item: &'a mut Item, key: &'a str) -> Option<&'a mut Item> {
|
||||
@@ -168,3 +184,336 @@ fn set_tables_dotted<'a>(item: &'a mut Item, keys: impl IntoIterator<Item = &'a
|
||||
set_table_dotted(item, key)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{account::config::TomlAccountConfig, config::TomlConfig};
|
||||
|
||||
fn assert_eq(config: TomlAccountConfig, expected_toml: &str) {
|
||||
let config = TomlConfig {
|
||||
accounts: HashMap::from_iter([("test".into(), config)]),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let toml = super::pretty_serialize(&config).expect("serialize error");
|
||||
assert_eq!(toml, expected_toml);
|
||||
|
||||
let expected_config = toml::from_str(&toml).expect("deserialize error");
|
||||
assert_eq!(config, expected_config);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pretty_serialize_default() {
|
||||
assert_eq(
|
||||
TomlAccountConfig {
|
||||
email: "test@localhost".into(),
|
||||
..Default::default()
|
||||
},
|
||||
r#"[test]
|
||||
email = "test@localhost"
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "account-sync")]
|
||||
#[test]
|
||||
fn pretty_serialize_sync_all() {
|
||||
use email::{account::sync::config::SyncConfig, folder::sync::FolderSyncStrategy};
|
||||
|
||||
assert_eq(
|
||||
TomlAccountConfig {
|
||||
email: "test@localhost".into(),
|
||||
sync: Some(SyncConfig {
|
||||
enable: Some(false),
|
||||
dir: Some("/tmp/test".into()),
|
||||
strategy: Some(FolderSyncStrategy::All),
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
r#"[test]
|
||||
email = "test@localhost"
|
||||
sync.enable = false
|
||||
sync.dir = "/tmp/test"
|
||||
sync.strategy = "all"
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "account-sync")]
|
||||
#[test]
|
||||
fn pretty_serialize_sync_include() {
|
||||
use std::collections::HashSet;
|
||||
|
||||
use email::{account::sync::config::SyncConfig, folder::sync::FolderSyncStrategy};
|
||||
|
||||
assert_eq(
|
||||
TomlAccountConfig {
|
||||
email: "test@localhost".into(),
|
||||
sync: Some(SyncConfig {
|
||||
enable: Some(true),
|
||||
dir: Some("/tmp/test".into()),
|
||||
strategy: Some(FolderSyncStrategy::Include(HashSet::from_iter([
|
||||
"test".into()
|
||||
]))),
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
r#"[test]
|
||||
email = "test@localhost"
|
||||
sync.enable = true
|
||||
sync.dir = "/tmp/test"
|
||||
sync.strategy.include = ["test"]
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "imap")]
|
||||
#[test]
|
||||
fn pretty_serialize_imap_passwd_cmd() {
|
||||
use email::{
|
||||
account::config::passwd::PasswdConfig,
|
||||
imap::config::{ImapAuthConfig, ImapConfig},
|
||||
};
|
||||
use secret::Secret;
|
||||
|
||||
assert_eq(
|
||||
TomlAccountConfig {
|
||||
email: "test@localhost".into(),
|
||||
imap: Some(ImapConfig {
|
||||
host: "localhost".into(),
|
||||
port: 143,
|
||||
login: "test@localhost".into(),
|
||||
auth: ImapAuthConfig::Passwd(PasswdConfig(Secret::new_cmd("pass show test"))),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
r#"[test]
|
||||
email = "test@localhost"
|
||||
imap.host = "localhost"
|
||||
imap.port = 143
|
||||
imap.login = "test@localhost"
|
||||
imap.passwd.cmd = "pass show test"
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "imap")]
|
||||
#[test]
|
||||
fn pretty_serialize_imap_passwd_cmds() {
|
||||
use email::{
|
||||
account::config::passwd::PasswdConfig,
|
||||
imap::config::{ImapAuthConfig, ImapConfig},
|
||||
};
|
||||
use secret::Secret;
|
||||
|
||||
assert_eq(
|
||||
TomlAccountConfig {
|
||||
email: "test@localhost".into(),
|
||||
imap: Some(ImapConfig {
|
||||
host: "localhost".into(),
|
||||
port: 143,
|
||||
login: "test@localhost".into(),
|
||||
auth: ImapAuthConfig::Passwd(PasswdConfig(Secret::new_cmd(vec![
|
||||
"pass show test",
|
||||
"tr -d '[:blank:]'",
|
||||
]))),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
r#"[test]
|
||||
email = "test@localhost"
|
||||
imap.host = "localhost"
|
||||
imap.port = 143
|
||||
imap.login = "test@localhost"
|
||||
imap.passwd.cmd = ["pass show test", "tr -d '[:blank:]'"]
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "imap")]
|
||||
#[test]
|
||||
fn pretty_serialize_imap_oauth2() {
|
||||
use email::{
|
||||
account::config::oauth2::OAuth2Config,
|
||||
imap::config::{ImapAuthConfig, ImapConfig},
|
||||
};
|
||||
|
||||
assert_eq(
|
||||
TomlAccountConfig {
|
||||
email: "test@localhost".into(),
|
||||
imap: Some(ImapConfig {
|
||||
host: "localhost".into(),
|
||||
port: 143,
|
||||
login: "test@localhost".into(),
|
||||
auth: ImapAuthConfig::OAuth2(OAuth2Config {
|
||||
client_id: "client-id".into(),
|
||||
auth_url: "auth-url".into(),
|
||||
token_url: "token-url".into(),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
r#"[test]
|
||||
email = "test@localhost"
|
||||
imap.host = "localhost"
|
||||
imap.port = 143
|
||||
imap.login = "test@localhost"
|
||||
imap.oauth2.method = "xoauth2"
|
||||
imap.oauth2.client-id = "client-id"
|
||||
imap.oauth2.auth-url = "auth-url"
|
||||
imap.oauth2.token-url = "token-url"
|
||||
imap.oauth2.pkce = false
|
||||
imap.oauth2.scopes = []
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "maildir")]
|
||||
#[test]
|
||||
fn pretty_serialize_maildir() {
|
||||
use email::maildir::config::MaildirConfig;
|
||||
|
||||
assert_eq(
|
||||
TomlAccountConfig {
|
||||
email: "test@localhost".into(),
|
||||
maildir: Some(MaildirConfig {
|
||||
root_dir: "/tmp/test".into(),
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
r#"[test]
|
||||
email = "test@localhost"
|
||||
maildir.root-dir = "/tmp/test"
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "smtp")]
|
||||
#[test]
|
||||
fn pretty_serialize_smtp_passwd_cmd() {
|
||||
use email::{
|
||||
account::config::passwd::PasswdConfig,
|
||||
smtp::config::{SmtpAuthConfig, SmtpConfig},
|
||||
};
|
||||
use secret::Secret;
|
||||
|
||||
assert_eq(
|
||||
TomlAccountConfig {
|
||||
email: "test@localhost".into(),
|
||||
smtp: Some(SmtpConfig {
|
||||
host: "localhost".into(),
|
||||
port: 143,
|
||||
login: "test@localhost".into(),
|
||||
auth: SmtpAuthConfig::Passwd(PasswdConfig(Secret::new_cmd("pass show test"))),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
r#"[test]
|
||||
email = "test@localhost"
|
||||
smtp.host = "localhost"
|
||||
smtp.port = 143
|
||||
smtp.login = "test@localhost"
|
||||
smtp.passwd.cmd = "pass show test"
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "smtp")]
|
||||
#[test]
|
||||
fn pretty_serialize_smtp_passwd_cmds() {
|
||||
use email::{
|
||||
account::config::passwd::PasswdConfig,
|
||||
smtp::config::{SmtpAuthConfig, SmtpConfig},
|
||||
};
|
||||
use secret::Secret;
|
||||
|
||||
assert_eq(
|
||||
TomlAccountConfig {
|
||||
email: "test@localhost".into(),
|
||||
smtp: Some(SmtpConfig {
|
||||
host: "localhost".into(),
|
||||
port: 143,
|
||||
login: "test@localhost".into(),
|
||||
auth: SmtpAuthConfig::Passwd(PasswdConfig(Secret::new_cmd(vec![
|
||||
"pass show test",
|
||||
"tr -d '[:blank:]'",
|
||||
]))),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
r#"[test]
|
||||
email = "test@localhost"
|
||||
smtp.host = "localhost"
|
||||
smtp.port = 143
|
||||
smtp.login = "test@localhost"
|
||||
smtp.passwd.cmd = ["pass show test", "tr -d '[:blank:]'"]
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "smtp")]
|
||||
#[test]
|
||||
fn pretty_serialize_smtp_oauth2() {
|
||||
use email::{
|
||||
account::config::oauth2::OAuth2Config,
|
||||
smtp::config::{SmtpAuthConfig, SmtpConfig},
|
||||
};
|
||||
|
||||
assert_eq(
|
||||
TomlAccountConfig {
|
||||
email: "test@localhost".into(),
|
||||
smtp: Some(SmtpConfig {
|
||||
host: "localhost".into(),
|
||||
port: 143,
|
||||
login: "test@localhost".into(),
|
||||
auth: SmtpAuthConfig::OAuth2(OAuth2Config {
|
||||
client_id: "client-id".into(),
|
||||
auth_url: "auth-url".into(),
|
||||
token_url: "token-url".into(),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
r#"[test]
|
||||
email = "test@localhost"
|
||||
smtp.host = "localhost"
|
||||
smtp.port = 143
|
||||
smtp.login = "test@localhost"
|
||||
smtp.oauth2.method = "xoauth2"
|
||||
smtp.oauth2.client-id = "client-id"
|
||||
smtp.oauth2.auth-url = "auth-url"
|
||||
smtp.oauth2.token-url = "token-url"
|
||||
smtp.oauth2.pkce = false
|
||||
smtp.oauth2.scopes = []
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "pgp")]
|
||||
#[test]
|
||||
fn pretty_serialize_pgp_cmds() {
|
||||
use email::account::config::pgp::PgpConfig;
|
||||
|
||||
assert_eq(
|
||||
TomlAccountConfig {
|
||||
email: "test@localhost".into(),
|
||||
pgp: Some(PgpConfig::Cmds(Default::default())),
|
||||
..Default::default()
|
||||
},
|
||||
r#"[test]
|
||||
email = "test@localhost"
|
||||
pgp.backend = "cmds"
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-5
@@ -135,6 +135,8 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
|
||||
|
||||
let auth = if oauth2_enabled {
|
||||
let mut config = OAuth2Config::default();
|
||||
let redirect_host = OAuth2Config::LOCALHOST.to_owned();
|
||||
let redirect_port = OAuth2Config::get_first_available_port()?;
|
||||
|
||||
let method_idx = Select::with_theme(&*THEME)
|
||||
.with_prompt("IMAP OAuth 2.0 mechanism")
|
||||
@@ -245,13 +247,13 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
|
||||
config.auth_url.clone(),
|
||||
config.token_url.clone(),
|
||||
)?
|
||||
.with_redirect_host(config.redirect_host.clone())
|
||||
.with_redirect_port(config.redirect_port)
|
||||
.with_redirect_host(redirect_host.to_owned())
|
||||
.with_redirect_port(redirect_port)
|
||||
.build()?;
|
||||
|
||||
let mut auth_code_grant = AuthorizationCodeGrant::new()
|
||||
.with_redirect_host(config.redirect_host.clone())
|
||||
.with_redirect_port(config.redirect_port);
|
||||
.with_redirect_host(redirect_host.to_owned())
|
||||
.with_redirect_port(redirect_port);
|
||||
|
||||
if config.pkce {
|
||||
auth_code_grant = auth_code_grant.with_pkce();
|
||||
@@ -312,7 +314,7 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
|
||||
_ => Default::default(),
|
||||
};
|
||||
|
||||
ImapAuthConfig::Passwd(PasswdConfig { passwd: secret })
|
||||
ImapAuthConfig::Passwd(PasswdConfig(secret))
|
||||
};
|
||||
|
||||
let config = ImapConfig {
|
||||
|
||||
+7
-5
@@ -135,6 +135,8 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
|
||||
|
||||
let auth = if oauth2_enabled {
|
||||
let mut config = OAuth2Config::default();
|
||||
let redirect_host = OAuth2Config::LOCALHOST;
|
||||
let redirect_port = OAuth2Config::get_first_available_port()?;
|
||||
|
||||
let method_idx = Select::with_theme(&*THEME)
|
||||
.with_prompt("SMTP OAuth 2.0 mechanism")
|
||||
@@ -245,13 +247,13 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
|
||||
config.auth_url.clone(),
|
||||
config.token_url.clone(),
|
||||
)?
|
||||
.with_redirect_host(config.redirect_host.clone())
|
||||
.with_redirect_port(config.redirect_port)
|
||||
.with_redirect_host(redirect_host.to_owned())
|
||||
.with_redirect_port(redirect_port)
|
||||
.build()?;
|
||||
|
||||
let mut auth_code_grant = AuthorizationCodeGrant::new()
|
||||
.with_redirect_host(config.redirect_host.clone())
|
||||
.with_redirect_port(config.redirect_port);
|
||||
.with_redirect_host(redirect_host.to_owned())
|
||||
.with_redirect_port(redirect_port);
|
||||
|
||||
if config.pkce {
|
||||
auth_code_grant = auth_code_grant.with_pkce();
|
||||
@@ -312,7 +314,7 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
|
||||
_ => Default::default(),
|
||||
};
|
||||
|
||||
SmtpAuthConfig::Passwd(PasswdConfig { passwd: secret })
|
||||
SmtpAuthConfig::Passwd(PasswdConfig(secret))
|
||||
};
|
||||
|
||||
let config = SmtpConfig {
|
||||
|
||||
Reference in New Issue
Block a user