refactor imap oauth2 and password config using sub crates from lib

This commit is contained in:
Clément DOUIN 2023-05-06 15:04:55 +02:00
parent 9dfdebb396
commit b478c545ad
No known key found for this signature in database
GPG key ID: 353E4A18EE0FAB72
5 changed files with 117 additions and 32 deletions

35
Cargo.lock generated
View file

@ -1147,6 +1147,9 @@ dependencies = [
"log", "log",
"once_cell", "once_cell",
"pimalaya-email", "pimalaya-email",
"pimalaya-keyring",
"pimalaya-process",
"pimalaya-secret",
"serde", "serde",
"serde_json", "serde_json",
"shellexpand", "shellexpand",
@ -2098,7 +2101,6 @@ dependencies = [
[[package]] [[package]]
name = "pimalaya-email" name = "pimalaya-email"
version = "0.7.1" version = "0.7.1"
source = "git+https://git.sr.ht/~soywod/pimalaya#22db3ec886536897c54b72d4ab7d20beff0ffecc"
dependencies = [ dependencies = [
"ammonia", "ammonia",
"chrono", "chrono",
@ -2107,7 +2109,6 @@ dependencies = [
"html-escape", "html-escape",
"imap", "imap",
"imap-proto", "imap-proto",
"keyring",
"lettre", "lettre",
"log", "log",
"mail-parser", "mail-parser",
@ -2120,6 +2121,7 @@ dependencies = [
"once_cell", "once_cell",
"ouroboros", "ouroboros",
"pimalaya-oauth2", "pimalaya-oauth2",
"pimalaya-secret",
"proc-lock", "proc-lock",
"rayon", "rayon",
"regex", "regex",
@ -2136,10 +2138,18 @@ dependencies = [
"webpki-roots", "webpki-roots",
] ]
[[package]]
name = "pimalaya-keyring"
version = "0.0.1"
dependencies = [
"keyring",
"log",
"thiserror",
]
[[package]] [[package]]
name = "pimalaya-oauth2" name = "pimalaya-oauth2"
version = "0.0.1" version = "0.0.1"
source = "git+https://git.sr.ht/~soywod/pimalaya#22db3ec886536897c54b72d4ab7d20beff0ffecc"
dependencies = [ dependencies = [
"log", "log",
"oauth2", "oauth2",
@ -2148,6 +2158,25 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "pimalaya-process"
version = "0.0.1"
dependencies = [
"log",
"thiserror",
]
[[package]]
name = "pimalaya-secret"
version = "0.0.1"
dependencies = [
"log",
"pimalaya-keyring",
"pimalaya-oauth2",
"pimalaya-process",
"thiserror",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.9" version = "0.2.9"

View file

@ -43,15 +43,19 @@ clap = "4.0"
clap_complete = "4.0" clap_complete = "4.0"
clap_mangen = "0.2" clap_mangen = "0.2"
console = "0.15.2" console = "0.15.2"
dirs = "4.0.0"
dialoguer = "0.10.2" dialoguer = "0.10.2"
dirs = "4.0.0"
email_address = "0.2.4" email_address = "0.2.4"
env_logger = "0.8" env_logger = "0.8"
erased-serde = "0.3" erased-serde = "0.3"
pimalaya-email = { git = "https://git.sr.ht/~soywod/pimalaya" }
indicatif = "0.17" indicatif = "0.17"
log = "0.4" log = "0.4"
once_cell = "1.16.0" once_cell = "1.16.0"
# pimalaya-email = { git = "https://git.sr.ht/~soywod/pimalaya" }
pimalaya-email = { path = "/home/soywod/sourcehut/pimalaya/email" }
pimalaya-keyring = { path = "/home/soywod/sourcehut/pimalaya/keyring" }
pimalaya-process = { path = "/home/soywod/sourcehut/pimalaya/process" }
pimalaya-secret = { path = "/home/soywod/sourcehut/pimalaya/secret" }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
shellexpand = "2.1" shellexpand = "2.1"

View file

@ -1,8 +1,11 @@
use pimalaya_email::{ use pimalaya_email::{
folder::sync::Strategy as SyncFoldersStrategy, EmailHooks, EmailSender, EmailTextPlainFormat, folder::sync::Strategy as SyncFoldersStrategy, EmailHooks, EmailSender, EmailTextPlainFormat,
ImapAuthConfig, MaildirConfig, OAuth2ClientSecret, OAuth2Config, OAuth2Method, OAuth2Scopes, ImapAuthConfig, MaildirConfig, OAuth2Config, OAuth2Method, OAuth2Scopes, SendmailConfig,
SendmailConfig, SmtpConfig, SmtpConfig,
}; };
use pimalaya_keyring::Entry;
use pimalaya_process::Cmd;
use pimalaya_secret::Secret;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{collections::HashSet, path::PathBuf}; use std::{collections::HashSet, path::PathBuf};
@ -12,6 +15,14 @@ use pimalaya_email::ImapConfig;
#[cfg(feature = "notmuch-backend")] #[cfg(feature = "notmuch-backend")]
use pimalaya_email::NotmuchConfig; use pimalaya_email::NotmuchConfig;
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Cmd", from = "String")]
pub struct CmdDef;
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Entry", from = "String")]
pub struct EntryDef;
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "SmtpConfig")] #[serde(remote = "SmtpConfig")]
struct SmtpConfigDef { struct SmtpConfigDef {
@ -47,7 +58,7 @@ pub struct ImapConfigDef {
pub insecure: Option<bool>, pub insecure: Option<bool>,
#[serde(rename = "imap-login")] #[serde(rename = "imap-login")]
pub login: String, pub login: String,
#[serde(rename = "imap-auth", with = "ImapAuthConfigDef")] #[serde(flatten, with = "ImapAuthConfigDef")]
pub auth: ImapAuthConfig, pub auth: ImapAuthConfig,
#[serde(rename = "imap-notify-cmd")] #[serde(rename = "imap-notify-cmd")]
pub notify_cmd: Option<String>, pub notify_cmd: Option<String>,
@ -58,26 +69,44 @@ pub struct ImapConfigDef {
} }
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "ImapAuthConfig", rename_all = "kebab-case")] #[serde(remote = "ImapAuthConfig", tag = "imap-auth", rename_all = "lowercase")]
pub enum ImapAuthConfigDef { pub enum ImapAuthConfigDef {
#[serde(skip)] #[serde(skip)]
None, None,
RawPasswd(String), #[serde(with = "PasswdDef")]
PasswdCmd(String), Passwd(Secret),
#[serde(with = "OAuth2ConfigDef", rename = "oauth2")] #[serde(with = "OAuth2ConfigDef")]
OAuth2(OAuth2Config), OAuth2(OAuth2Config),
} }
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Secret", rename_all = "kebab-case")]
pub enum PasswdDef {
#[serde(rename = "imap-passwd")]
Raw(String),
#[serde(rename = "imap-passwd-cmd", with = "CmdDef")]
Cmd(Cmd),
#[serde(rename = "imap-passwd-keyring", with = "EntryDef")]
Keyring(Entry),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "OAuth2Config", rename_all = "kebab-case")] #[serde(remote = "OAuth2Config", rename_all = "kebab-case")]
pub struct OAuth2ConfigDef { pub struct OAuth2ConfigDef {
#[serde(with = "OAuth2MethodDef")] #[serde(rename = "imap-oauth2-method", with = "OAuth2MethodDef")]
pub method: OAuth2Method, pub method: OAuth2Method,
#[serde(rename = "imap-oauth2-client-id")]
pub client_id: String, pub client_id: String,
#[serde(with = "OAuth2ClientSecretDef")] #[serde(flatten, with = "ClientSecretDef")]
pub client_secret: OAuth2ClientSecret, pub client_secret: Secret,
#[serde(rename = "imap-oauth2-auth-url")]
pub auth_url: String, pub auth_url: String,
#[serde(rename = "imap-oauth2-token-url")]
pub token_url: String, pub token_url: String,
#[serde(flatten, with = "AccessTokenDef")]
pub access_token: Secret,
#[serde(flatten, with = "RefreshTokenDef")]
pub refresh_token: Secret,
#[serde(flatten, with = "OAuth2ScopesDef")] #[serde(flatten, with = "OAuth2ScopesDef")]
pub scopes: OAuth2Scopes, pub scopes: OAuth2Scopes,
#[serde(default)] #[serde(default)]
@ -85,24 +114,53 @@ pub struct OAuth2ConfigDef {
} }
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "OAuth2ClientSecret", rename_all = "kebab-case")] #[serde(remote = "Secret", rename_all = "kebab-case")]
pub enum OAuth2ClientSecretDef { pub enum ClientSecretDef {
#[serde(rename = "imap-oauth2-client-secret")]
Raw(String), Raw(String),
Cmd(String), #[serde(rename = "imap-oauth2-client-secret-cmd", with = "CmdDef")]
Keyring, Cmd(Cmd),
#[serde(rename = "imap-oauth2-client-secret-keyring", with = "EntryDef")]
Keyring(Entry),
} }
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "OAuth2Method", rename_all = "lowercase")] #[serde(remote = "Secret", rename_all = "kebab-case")]
pub enum AccessTokenDef {
#[serde(rename = "imap-oauth2-access-token")]
Raw(String),
#[serde(rename = "imap-oauth2-access-token-cmd", with = "CmdDef")]
Cmd(Cmd),
#[serde(rename = "imap-oauth2-access-token-keyring", with = "EntryDef")]
Keyring(Entry),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Secret", rename_all = "kebab-case")]
pub enum RefreshTokenDef {
#[serde(rename = "imap-oauth2-refresh-token")]
Raw(String),
#[serde(rename = "imap-oauth2-refresh-token-cmd", with = "CmdDef")]
Cmd(Cmd),
#[serde(rename = "imap-oauth2-refresh-token-keyring", with = "EntryDef")]
Keyring(Entry),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "OAuth2Method")]
pub enum OAuth2MethodDef { pub enum OAuth2MethodDef {
#[serde(rename = "xoauth2", alias = "XOAUTH2")]
XOAuth2, XOAuth2,
#[serde(rename = "oauthbearer", alias = "OAUTHBEARER")]
OAuthBearer, OAuthBearer,
} }
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "OAuth2Scopes", rename_all = "kebab-case")] #[serde(remote = "OAuth2Scopes", rename_all = "kebab-case")]
pub enum OAuth2ScopesDef { pub enum OAuth2ScopesDef {
#[serde(rename = "imap-oauth2-scope")]
Scope(String), Scope(String),
#[serde(rename = "imap-oauth2-scopes")]
Scopes(Vec<String>), Scopes(Vec<String>),
} }

View file

@ -17,27 +17,21 @@ use crate::{
}; };
/// Configure the current selected account /// Configure the current selected account
pub fn configure( pub fn configure(backend_config: &BackendConfig, reset: bool) -> Result<()> {
account_config: &AccountConfig,
backend_config: &BackendConfig,
reset: bool,
) -> Result<()> {
info!("entering the configure account handler"); info!("entering the configure account handler");
match backend_config { match backend_config {
BackendConfig::None => (), BackendConfig::None => (),
BackendConfig::Maildir(_) => (), BackendConfig::Maildir(_) => (),
#[cfg(feature = "imap-backend")] #[cfg(feature = "imap-backend")]
BackendConfig::Imap(imap_config) => { BackendConfig::Imap(imap_config) => {
imap_config.auth.configure( imap_config
&account_config.name, .auth
reset, .configure(reset, configure_oauth2_client_secret)?;
configure_oauth2_client_secret,
)?;
} }
#[cfg(feature = "notmuch-backend")] #[cfg(feature = "notmuch-backend")]
BackendConfig::Notmuch(config) => (), BackendConfig::Notmuch(config) => (),
}; };
println!("Account {} configured!", account_config.name); println!("Account successfully configured!");
Ok(()) Ok(())
} }

View file

@ -138,7 +138,7 @@ fn main() -> Result<()> {
return Ok(()); return Ok(());
} }
Some(account::args::Cmd::Configure(reset)) => { Some(account::args::Cmd::Configure(reset)) => {
return account::handlers::configure(&account_config, &backend_config, reset); return account::handlers::configure(&backend_config, reset);
} }
_ => (), _ => (),
} }