Implement imap-flow #34
15 changed files with 75 additions and 4 deletions
|
@ -26,6 +26,7 @@ pub struct ProviderConfig {
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
#[serde(tag = "user_driver")]
|
#[serde(tag = "user_driver")]
|
||||||
pub enum UserManagement {
|
pub enum UserManagement {
|
||||||
|
Demo,
|
||||||
Static(LoginStaticConfig),
|
Static(LoginStaticConfig),
|
||||||
Ldap(LoginLdapConfig),
|
Ldap(LoginLdapConfig),
|
||||||
}
|
}
|
||||||
|
|
48
src/login/demo_provider.rs
Normal file
48
src/login/demo_provider.rs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
use crate::login::*;
|
||||||
|
use crate::storage::*;
|
||||||
|
|
||||||
|
pub struct DemoLoginProvider{
|
||||||
|
keys: CryptoKeys,
|
||||||
|
in_memory_store: in_memory::MemDb,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DemoLoginProvider {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
keys: CryptoKeys::init(),
|
||||||
|
in_memory_store: in_memory::MemDb::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl LoginProvider for DemoLoginProvider {
|
||||||
|
async fn login(&self, username: &str, password: &str) -> Result<Credentials> {
|
||||||
|
tracing::debug!(user=%username, "login");
|
||||||
|
|
||||||
|
if username != "alice" {
|
||||||
|
bail!("user does not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
if password != "hunter2" {
|
||||||
|
bail!("wrong password");
|
||||||
|
}
|
||||||
|
|
||||||
|
let storage = self.in_memory_store.builder("alice").await;
|
||||||
|
let keys = self.keys.clone();
|
||||||
|
|
||||||
|
Ok(Credentials { storage, keys })
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn public_login(&self, email: &str) -> Result<PublicCredentials> {
|
||||||
|
tracing::debug!(user=%email, "public_login");
|
||||||
|
if email != "alice@example.tld" {
|
||||||
|
bail!("invalid email address");
|
||||||
|
}
|
||||||
|
|
||||||
|
let storage = self.in_memory_store.builder("alice").await;
|
||||||
|
let public_key = self.keys.public.clone();
|
||||||
|
|
||||||
|
Ok(PublicCredentials { storage, public_key })
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod ldap_provider;
|
pub mod ldap_provider;
|
||||||
pub mod static_provider;
|
pub mod static_provider;
|
||||||
|
pub mod demo_provider;
|
||||||
|
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
26
src/main.rs
26
src/main.rs
|
@ -29,7 +29,12 @@ struct Args {
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
command: Command,
|
command: Command,
|
||||||
|
|
||||||
|
/// A special mode dedicated to developers, NOT INTENDED FOR PRODUCTION
|
||||||
|
#[clap(long)]
|
||||||
|
dev: bool,
|
||||||
|
|
||||||
#[clap(short, long, env = "CONFIG_FILE", default_value = "aerogramme.toml")]
|
#[clap(short, long, env = "CONFIG_FILE", default_value = "aerogramme.toml")]
|
||||||
|
/// Path to the main Aerogramme configuration file
|
||||||
config_file: PathBuf,
|
config_file: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +163,22 @@ async fn main() -> Result<()> {
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
let any_config = read_config(args.config_file)?;
|
let any_config = if args.dev {
|
||||||
|
use std::net::*;
|
||||||
|
AnyConfig::Provider(ProviderConfig {
|
||||||
|
pid: None,
|
||||||
|
imap: ImapConfig {
|
||||||
|
bind_addr: SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 1143),
|
||||||
|
},
|
||||||
|
lmtp: LmtpConfig {
|
||||||
|
bind_addr: SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 1025),
|
||||||
|
hostname: "example.tld".to_string(),
|
||||||
|
},
|
||||||
|
users: UserManagement::Demo,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
read_config(args.config_file)?
|
||||||
|
};
|
||||||
|
|
||||||
match (&args.command, any_config) {
|
match (&args.command, any_config) {
|
||||||
(Command::Companion(subcommand), AnyConfig::Companion(config)) => match subcommand {
|
(Command::Companion(subcommand), AnyConfig::Companion(config)) => match subcommand {
|
||||||
|
@ -184,8 +204,8 @@ async fn main() -> Result<()> {
|
||||||
ProviderCommand::Account(cmd) => {
|
ProviderCommand::Account(cmd) => {
|
||||||
let user_file = match config.users {
|
let user_file = match config.users {
|
||||||
UserManagement::Static(conf) => conf.user_list,
|
UserManagement::Static(conf) => conf.user_list,
|
||||||
UserManagement::Ldap(_) => {
|
_ => {
|
||||||
panic!("LDAP account management is not supported from Aerogramme.")
|
panic!("Only static account management is supported from Aerogramme.")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
account_management(&args.command, cmd, user_file)?;
|
account_management(&args.command, cmd, user_file)?;
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::config::*;
|
||||||
use crate::imap;
|
use crate::imap;
|
||||||
use crate::lmtp::*;
|
use crate::lmtp::*;
|
||||||
use crate::login::ArcLoginProvider;
|
use crate::login::ArcLoginProvider;
|
||||||
use crate::login::{ldap_provider::*, static_provider::*};
|
use crate::login::{ldap_provider::*, static_provider::*, demo_provider::*};
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
lmtp_server: Option<Arc<LmtpServer>>,
|
lmtp_server: Option<Arc<LmtpServer>>,
|
||||||
|
@ -36,6 +36,7 @@ impl Server {
|
||||||
pub async fn from_provider_config(config: ProviderConfig) -> Result<Self> {
|
pub async fn from_provider_config(config: ProviderConfig) -> Result<Self> {
|
||||||
tracing::info!("Init as provider");
|
tracing::info!("Init as provider");
|
||||||
let login: ArcLoginProvider = match config.users {
|
let login: ArcLoginProvider = match config.users {
|
||||||
|
UserManagement::Demo => Arc::new(DemoLoginProvider::new()),
|
||||||
UserManagement::Static(x) => Arc::new(StaticLoginProvider::new(x).await?),
|
UserManagement::Static(x) => Arc::new(StaticLoginProvider::new(x).await?),
|
||||||
UserManagement::Ldap(x) => Arc::new(LdapLoginProvider::new(x)?),
|
UserManagement::Ldap(x) => Arc::new(LdapLoginProvider::new(x)?),
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue