mirror of
https://github.com/chatmail/core.git
synced 2026-04-02 05:22:14 +03:00
first pass at resolving CR
This commit is contained in:
38
src/chat.rs
38
src/chat.rs
@@ -635,44 +635,6 @@ impl Chat {
|
||||
&self.name
|
||||
}
|
||||
|
||||
fn parent_query(fields: &str) -> String {
|
||||
// Check for server_uid guarantees that we don't
|
||||
// select a draft or undelivered message.
|
||||
format!(
|
||||
"SELECT {} \
|
||||
FROM msgs WHERE chat_id=?1 AND server_uid!=0 \
|
||||
ORDER BY timestamp DESC, id DESC \
|
||||
LIMIT 1;",
|
||||
fields
|
||||
)
|
||||
}
|
||||
|
||||
async fn get_parent_mime_headers(&self, context: &Context) -> Option<(String, String, String)> {
|
||||
let collect = |row: &rusqlite::Row| Ok((row.get(0)?, row.get(1)?, row.get(2)?));
|
||||
let params = paramsv![self.id];
|
||||
let sql = &context.sql;
|
||||
|
||||
let query = Self::parent_query("rfc724_mid, mime_in_reply_to, mime_references");
|
||||
|
||||
sql.query_row(&query, params, collect).await.ok()
|
||||
}
|
||||
|
||||
async fn parent_is_encrypted(&self, context: &Context) -> Result<bool, Error> {
|
||||
let sql = &context.sql;
|
||||
let params = paramsv![self.id];
|
||||
let query = Self::parent_query("param");
|
||||
|
||||
let packed: Option<String> = sql.query_get_value_result(&query, params).await?;
|
||||
|
||||
if let Some(ref packed) = packed {
|
||||
let param = packed.parse::<Params>()?;
|
||||
Ok(param.exists(Param::GuaranteeE2ee))
|
||||
} else {
|
||||
// No messages
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_profile_image(&self, context: &Context) -> Option<PathBuf> {
|
||||
if let Some(image_rel) = self.param.get(Param::ProfileImage) {
|
||||
if !image_rel.is_empty() {
|
||||
|
||||
@@ -44,11 +44,11 @@ impl Context {
|
||||
|
||||
ensure!(
|
||||
!self.scheduler.read().await.is_running(),
|
||||
"Can not configure, already running"
|
||||
"cannot configure, already running"
|
||||
);
|
||||
ensure!(
|
||||
self.sql.is_open().await,
|
||||
"Cannot configure, database not opened."
|
||||
"cannot configure, database not opened."
|
||||
);
|
||||
let cancel_channel = self.alloc_ongoing().await?;
|
||||
|
||||
|
||||
@@ -52,6 +52,8 @@ pub struct InnerContext {
|
||||
pub(crate) running_state: RwLock<RunningState>,
|
||||
/// Mutex to avoid generating the key for the user more than once.
|
||||
pub(crate) generating_key_mutex: Mutex<()>,
|
||||
/// Mutex to enforce only a single running oauth2 is running.
|
||||
pub(crate) oauth2_mutex: Mutex<()>,
|
||||
pub(crate) translated_stockstrings: RwLock<HashMap<usize, String>>,
|
||||
pub(crate) logs: (SyncSender<Event>, SyncReceiver<Event>),
|
||||
|
||||
@@ -117,6 +119,7 @@ impl Context {
|
||||
bob: RwLock::new(Default::default()),
|
||||
last_smeared_timestamp: RwLock::new(0),
|
||||
generating_key_mutex: Mutex::new(()),
|
||||
oauth2_mutex: Mutex::new(()),
|
||||
translated_stockstrings: RwLock::new(HashMap::new()),
|
||||
logs: unbounded(),
|
||||
scheduler: RwLock::new(Scheduler::Stopped),
|
||||
|
||||
@@ -1227,6 +1227,14 @@ impl Imap {
|
||||
return;
|
||||
}
|
||||
|
||||
if !self
|
||||
.add_flag_finalized_with_set(context, SELECT_ALL, "\\Deleted")
|
||||
.await
|
||||
{
|
||||
error!(context, "Cannot mark messages for deletion {}", folder);
|
||||
return;
|
||||
}
|
||||
|
||||
// we now trigger expunge to actually delete messages
|
||||
self.config.selected_folder_needs_expunge = true;
|
||||
match self.select_folder::<String>(context, None).await {
|
||||
|
||||
@@ -47,6 +47,7 @@ impl Imap {
|
||||
}
|
||||
self.config.selected_folder = None;
|
||||
self.config.selected_folder_needs_expunge = false;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -77,26 +78,7 @@ impl Imap {
|
||||
// deselect existing folder, if needed (it's also done implicitly by SELECT, however, without EXPUNGE then)
|
||||
let needs_expunge = { self.config.selected_folder_needs_expunge };
|
||||
if needs_expunge {
|
||||
if let Some(ref folder) = self.config.selected_folder {
|
||||
info!(context, "Expunge messages in \"{}\".", folder);
|
||||
|
||||
// A CLOSE-SELECT is considerably faster than an EXPUNGE-SELECT, see
|
||||
// https://tools.ietf.org/html/rfc3501#section-6.4.2
|
||||
if let Some(ref mut session) = &mut self.session {
|
||||
match session.close().await {
|
||||
Ok(_) => {
|
||||
info!(context, "close/expunge succeeded");
|
||||
}
|
||||
Err(err) => {
|
||||
self.trigger_reconnect();
|
||||
return Err(Error::CloseExpungeFailed(err));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(Error::NoSession);
|
||||
}
|
||||
}
|
||||
self.config.selected_folder_needs_expunge = false;
|
||||
self.close_folder(context).await?;
|
||||
}
|
||||
|
||||
// select new folder
|
||||
|
||||
39
src/job.rs
39
src/job.rs
@@ -810,45 +810,6 @@ pub enum Connection<'a> {
|
||||
Smtp(&'a mut Smtp),
|
||||
}
|
||||
|
||||
async fn add_imap_deletion_jobs(context: &Context) -> sql::Result<()> {
|
||||
if let Some(delete_server_after) = context.get_config_delete_server_after().await {
|
||||
let threshold_timestamp = time() - delete_server_after;
|
||||
|
||||
// Select all expired messages which don't have a
|
||||
// corresponding message deletion job yet.
|
||||
let msg_ids = context
|
||||
.sql
|
||||
.query_map(
|
||||
"SELECT id FROM msgs \
|
||||
WHERE timestamp < ? \
|
||||
AND server_uid != 0 \
|
||||
AND NOT EXISTS (SELECT 1 FROM jobs WHERE foreign_id = msgs.id \
|
||||
AND action = ?)",
|
||||
paramsv![threshold_timestamp, Action::DeleteMsgOnImap],
|
||||
|row| row.get::<_, MsgId>(0),
|
||||
|ids| {
|
||||
ids.collect::<std::result::Result<Vec<_>, _>>()
|
||||
.map_err(Into::into)
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Schedule IMAP deletion for expired messages.
|
||||
for msg_id in msg_ids {
|
||||
add(
|
||||
context,
|
||||
Action::DeleteMsgOnImap,
|
||||
msg_id.to_u32() as i32,
|
||||
Params::new(),
|
||||
0,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn load_imap_deletion_msgid(context: &Context) -> sql::Result<Option<MsgId>> {
|
||||
if let Some(delete_server_after) = context.get_config_delete_server_after().await {
|
||||
let threshold_timestamp = time() - delete_server_after;
|
||||
|
||||
@@ -75,8 +75,6 @@ pub async fn dc_get_oauth2_url(
|
||||
}
|
||||
}
|
||||
|
||||
// The following function may block due http-requests;
|
||||
// must not be called from the main thread or by the ui!
|
||||
pub async fn dc_get_oauth2_access_token(
|
||||
context: &Context,
|
||||
addr: impl AsRef<str>,
|
||||
@@ -84,9 +82,7 @@ pub async fn dc_get_oauth2_access_token(
|
||||
regenerate: bool,
|
||||
) -> Option<String> {
|
||||
if let Some(oauth2) = Oauth2::from_address(addr) {
|
||||
// TODO: FIXME
|
||||
// let lock = context.oauth2_critical.clone();
|
||||
// let _l = lock.lock().await;
|
||||
let lock = context.oauth2_mutex.lock().await;
|
||||
|
||||
// read generated token
|
||||
if !regenerate && !is_expired(context).await {
|
||||
@@ -243,6 +239,8 @@ pub async fn dc_get_oauth2_access_token(
|
||||
warn!(context, "Failed to find OAuth2 access token");
|
||||
}
|
||||
|
||||
drop(lock);
|
||||
|
||||
response.access_token
|
||||
} else {
|
||||
warn!(context, "Internal OAuth2 error: 2");
|
||||
|
||||
Reference in New Issue
Block a user