2022-06-29 13:39:54 +00:00
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::sync::{Arc, Weak};
|
|
|
|
|
2022-06-29 11:16:58 +00:00
|
|
|
use anyhow::Result;
|
2022-06-29 13:39:54 +00:00
|
|
|
use lazy_static::lazy_static;
|
2022-06-29 11:16:58 +00:00
|
|
|
|
|
|
|
use k2v_client::K2vClient;
|
|
|
|
use rusoto_s3::S3Client;
|
|
|
|
|
2022-06-29 13:39:54 +00:00
|
|
|
use crate::login::{Credentials, StorageCredentials};
|
2022-06-29 11:16:58 +00:00
|
|
|
use crate::mail::mailbox::Mailbox;
|
2022-06-29 13:52:09 +00:00
|
|
|
use crate::mail::unique_ident::UniqueIdent;
|
2022-06-29 11:16:58 +00:00
|
|
|
|
|
|
|
pub struct User {
|
|
|
|
pub username: String,
|
|
|
|
pub creds: Credentials,
|
|
|
|
pub s3_client: S3Client,
|
|
|
|
pub k2v_client: K2vClient,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl User {
|
|
|
|
pub fn new(username: String, creds: Credentials) -> Result<Self> {
|
|
|
|
let s3_client = creds.s3_client()?;
|
|
|
|
let k2v_client = creds.k2v_client()?;
|
|
|
|
Ok(Self {
|
|
|
|
username,
|
|
|
|
creds,
|
|
|
|
s3_client,
|
|
|
|
k2v_client,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-06-29 11:41:05 +00:00
|
|
|
/// Lists user's available mailboxes
|
|
|
|
pub fn list_mailboxes(&self) -> Result<Vec<String>> {
|
|
|
|
unimplemented!()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Opens an existing mailbox given its IMAP name.
|
2022-06-29 13:39:54 +00:00
|
|
|
pub async fn open_mailbox(&self, name: &str) -> Result<Option<Arc<Mailbox>>> {
|
2022-06-29 13:52:09 +00:00
|
|
|
// TODO: handle mailbox names, mappings, renaming, etc
|
|
|
|
let id = match name {
|
|
|
|
"INBOX" => UniqueIdent([0u8; 24]),
|
|
|
|
_ => panic!("Only INBOX exists for now"),
|
|
|
|
};
|
|
|
|
|
|
|
|
let cache_key = (self.creds.storage.clone(), id);
|
|
|
|
|
2022-06-29 13:39:54 +00:00
|
|
|
{
|
|
|
|
let cache = MAILBOX_CACHE.cache.lock().unwrap();
|
2022-06-29 13:52:09 +00:00
|
|
|
if let Some(mb) = cache.get(&cache_key).and_then(Weak::upgrade) {
|
2022-06-29 13:39:54 +00:00
|
|
|
return Ok(Some(mb));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-29 13:52:09 +00:00
|
|
|
let mb = Arc::new(Mailbox::open(&self.creds, id).await?);
|
2022-06-29 13:39:54 +00:00
|
|
|
|
|
|
|
let mut cache = MAILBOX_CACHE.cache.lock().unwrap();
|
2022-06-29 13:52:09 +00:00
|
|
|
if let Some(concurrent_mb) = cache.get(&cache_key).and_then(Weak::upgrade) {
|
|
|
|
drop(mb); // we worked for nothing but at least we didn't starve someone else
|
2022-06-29 13:39:54 +00:00
|
|
|
Ok(Some(concurrent_mb))
|
|
|
|
} else {
|
2022-06-29 13:52:09 +00:00
|
|
|
cache.insert(cache_key, Arc::downgrade(&mb));
|
2022-06-29 13:39:54 +00:00
|
|
|
Ok(Some(mb))
|
|
|
|
}
|
2022-06-29 11:41:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates a new mailbox in the user's IMAP namespace.
|
2022-06-29 14:05:34 +00:00
|
|
|
pub fn create_mailbox(&self, _name: &str) -> Result<()> {
|
2022-06-29 11:41:05 +00:00
|
|
|
unimplemented!()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Deletes a mailbox in the user's IMAP namespace.
|
2022-06-29 14:05:34 +00:00
|
|
|
pub fn delete_mailbox(&self, _name: &str) -> Result<()> {
|
2022-06-29 11:41:05 +00:00
|
|
|
unimplemented!()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Renames a mailbox in the user's IMAP namespace.
|
2022-06-29 14:05:34 +00:00
|
|
|
pub fn rename_mailbox(&self, _old_name: &str, _new_name: &str) -> Result<()> {
|
2022-06-29 11:41:05 +00:00
|
|
|
unimplemented!()
|
2022-06-29 11:16:58 +00:00
|
|
|
}
|
|
|
|
}
|
2022-06-29 13:39:54 +00:00
|
|
|
|
|
|
|
// ---- Mailbox cache ----
|
|
|
|
|
|
|
|
struct MailboxCache {
|
2022-06-29 13:52:09 +00:00
|
|
|
cache: std::sync::Mutex<HashMap<(StorageCredentials, UniqueIdent), Weak<Mailbox>>>,
|
2022-06-29 13:39:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl MailboxCache {
|
|
|
|
fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
cache: std::sync::Mutex::new(HashMap::new()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lazy_static! {
|
|
|
|
static ref MAILBOX_CACHE: MailboxCache = MailboxCache::new();
|
|
|
|
}
|