Tweak MailStore and MultiDomain traits to add Error types

This commit is contained in:
Nathan Fisher 2023-05-29 00:56:15 -04:00
parent 4f2f151173
commit 179b8ad100
3 changed files with 50 additions and 21 deletions

View file

@ -1,11 +1,11 @@
use super::*; use super::*;
use std::{fs, io, os::unix::fs::DirBuilderExt, path::PathBuf}; use std::{fs::{self, File}, io::{self, Write}, os::unix::fs::DirBuilderExt, path::PathBuf};
pub trait MultiDomain: MailStore { pub trait MultiDomain: MailStore {
type Error; type Error;
fn domains(&self) -> Result<Vec<String>, Self::Error>; fn domains(&self) -> Result<Vec<String>, <Self as filesystem::MultiDomain>::Error>;
fn add_domain(&mut self, domain: &str) -> Result<(), Self::Error>; fn add_domain(&mut self, domain: &str) -> Result<(), <Self as filesystem::MultiDomain>::Error>;
fn remove_domain(&mut self, domain: &str) -> Result<(), Self::Error>; fn remove_domain(&mut self, domain: &str) -> Result<(), <Self as filesystem::MultiDomain>::Error>;
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -15,6 +15,8 @@ pub struct Filesystem {
} }
impl MailStore for Filesystem { impl MailStore for Filesystem {
type Error = io::Error;
fn users(&self) -> Vec<Mailuser> { fn users(&self) -> Vec<Mailuser> {
todo!() todo!()
} }
@ -48,7 +50,10 @@ impl MailStore for Filesystem {
let Ok(dir) = fs::read_dir(path) else { let Ok(dir) = fs::read_dir(path) else {
return None; return None;
}; };
let mut folder = Folder { name: folder.to_string(), messages: HashMap::new() }; let mut folder = Folder {
name: folder.to_string(),
messages: HashMap::new(),
};
dir.filter(|x| x.is_ok()).map(|x| x.unwrap()).for_each(|e| { dir.filter(|x| x.is_ok()).map(|x| x.unwrap()).for_each(|e| {
if let Ok(contents) = fs::read_to_string(e.path()) { if let Ok(contents) = fs::read_to_string(e.path()) {
if let Ok(message) = contents.parse::<Message>() { if let Ok(message) = contents.parse::<Message>() {
@ -60,14 +65,28 @@ impl MailStore for Filesystem {
} }
fn get_message(&self, user: &str, folder: &str, title: &str) -> Option<Message> { fn get_message(&self, user: &str, folder: &str, title: &str) -> Option<Message> {
todo!() self.get_folder(user, folder).and_then(|f| {
f.messages
.values()
.find(|m| m.title.as_ref().map(|x| x.as_str()) == Some(title))
.cloned()
})
} }
fn add_message(&mut self, user: &str, folder: &str, message: Message) { fn add_message(&mut self, user: &str, folder: &str, message: Message) -> Result<(), Self::Error> {
todo!() let Some((user, host)) = user.rsplit_once('@') else {
return Err(io::Error::new(io::ErrorKind::Other, "Invalid username"));
};
let mut path = self.path.clone();
path.push(host);
path.push(user);
path.push(folder);
path.push(&message.id);
let mut fd = File::create(path)?;
write!(fd, "{message}")
} }
fn delete_message(&mut self, user: &str, folder: &str, key: &str) -> bool { fn delete_message(&mut self, user: &str, folder: &str, key: &str) -> Result<(), Self::Error> {
todo!() todo!()
} }
@ -87,7 +106,7 @@ impl MailStore for Filesystem {
impl MultiDomain for Filesystem { impl MultiDomain for Filesystem {
type Error = io::Error; type Error = io::Error;
fn domains(&self) -> Result<Vec<String>, Self::Error> { fn domains(&self) -> Result<Vec<String>, io::Error> {
Ok(self Ok(self
.path .path
.read_dir()? .read_dir()?
@ -103,7 +122,7 @@ impl MultiDomain for Filesystem {
.collect::<Vec<String>>()) .collect::<Vec<String>>())
} }
fn add_domain(&mut self, domain: &str) -> Result<(), Self::Error> { fn add_domain(&mut self, domain: &str) -> Result<(), io::Error> {
let mut path = self.path.clone(); let mut path = self.path.clone();
path.push(domain); path.push(domain);
if !path.exists() { if !path.exists() {
@ -115,7 +134,7 @@ impl MultiDomain for Filesystem {
Ok(()) Ok(())
} }
fn remove_domain(&mut self, domain: &str) -> Result<(), Self::Error> { fn remove_domain(&mut self, domain: &str) -> Result<(), io::Error> {
let mut path = self.path.clone(); let mut path = self.path.clone();
path.push(domain); path.push(domain);
if path.exists() { if path.exists() {

View file

@ -1,5 +1,6 @@
#![allow(unused_variables)]
use crate::prelude::{Host, Mailbox, Mailuser, Message, ParseMailboxError}; use crate::prelude::{Host, Mailbox, Mailuser, Message, ParseMailboxError};
use std::{collections::HashMap, str::FromStr}; use std::{collections::HashMap, str::FromStr, convert::Infallible};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -7,6 +8,8 @@ use serde::{Deserialize, Serialize};
pub mod filesystem; pub mod filesystem;
pub trait MailStore { pub trait MailStore {
type Error;
/// Retreives a list of all valid mailusers on this server /// Retreives a list of all valid mailusers on this server
fn users(&self) -> Vec<Mailuser>; fn users(&self) -> Vec<Mailuser>;
/// Checks whether this server services that domain /// Checks whether this server services that domain
@ -19,11 +22,11 @@ pub trait MailStore {
/// returns the message /// returns the message
fn get_message(&self, user: &str, folder: &str, title: &str) -> Option<Message>; fn get_message(&self, user: &str, folder: &str, title: &str) -> Option<Message>;
/// Move a message to a new folder /// Move a message to a new folder
fn move_message(&mut self, user: &str, title: &str, folder: &str); fn move_message(&mut self, user: &str, id: &str, folder: &str);
/// Deletes a message it it exists /// Deletes a message it it exists
fn delete_message(&mut self, user: &str, folder: &str, key: &str) -> bool; fn delete_message(&mut self, user: &str, folder: &str, id: &str) -> Result<(), Self::Error>;
/// Adds a message /// Adds a message
fn add_message(&mut self, user: &str, folder: &str, message: Message); fn add_message(&mut self, user: &str, folder: &str, message: Message) -> Result<(), Self::Error>;
/// Adds a new mailuser to the given domain /// Adds a new mailuser to the given domain
fn add_user(&mut self, user: &str) -> Result<(), ParseMailboxError>; fn add_user(&mut self, user: &str) -> Result<(), ParseMailboxError>;
/// Removes the given user if the account exists /// Removes the given user if the account exists
@ -58,6 +61,8 @@ pub struct MultiDomain {
} }
impl MailStore for Domain { impl MailStore for Domain {
type Error = Infallible;
fn users(&self) -> Vec<Mailuser> { fn users(&self) -> Vec<Mailuser> {
self.users self.users
.values() .values()
@ -96,7 +101,7 @@ impl MailStore for Domain {
.cloned() .cloned()
} }
fn move_message(&mut self, user: &str, title: &str, folder: &str) { fn move_message(&mut self, user: &str, id: &str, folder: &str) {
todo!() todo!()
} }
@ -118,11 +123,11 @@ impl MailStore for Domain {
self.users.remove(user).is_some() self.users.remove(user).is_some()
} }
fn add_message(&mut self, user: &str, folder: &str, message: Message) { fn add_message(&mut self, user: &str, folder: &str, message: Message) -> Result<(), Self::Error> {
todo!() todo!()
} }
fn delete_message(&mut self, user: &str, folder: &str, key: &str) -> bool { fn delete_message(&mut self, user: &str, folder: &str, id: &str) -> Result<(), Self::Error> {
todo!() todo!()
} }
} }

View file

@ -105,7 +105,12 @@ where
S: CertificateStore + 'static + Clone, S: CertificateStore + 'static + Clone,
C: ClientCertificateStore + Clone, C: ClientCertificateStore + Clone,
{ {
pub fn new(sender: &str, recipients: &[&str], store: S, client_store: C) -> Result<Self, Error> { pub fn new(
sender: &str,
recipients: &[&str],
store: S,
client_store: C,
) -> Result<Self, Error> {
let mut rec = vec![]; let mut rec = vec![];
for r in recipients { for r in recipients {
let r = r.parse()?; let r = r.parse()?;
@ -115,7 +120,7 @@ where
sender: sender.parse()?, sender: sender.parse()?,
recipients: rec, recipients: rec,
store, store,
client_store client_store,
}) })
} }