melib: Add FolderPermissions
permissions() method on BackendFolder and SetPermissions in FolderOperation enum.sql
parent
97e20b22a8
commit
5761f854e2
|
@ -173,6 +173,7 @@ pub enum FolderOperation {
|
|||
Subscribe,
|
||||
Unsubscribe,
|
||||
Rename(NewFolderName),
|
||||
SetPermissions(FolderPermissions),
|
||||
}
|
||||
|
||||
type NewFolderName = String;
|
||||
|
@ -309,6 +310,8 @@ pub trait BackendFolder: Debug {
|
|||
fn clone(&self) -> Folder;
|
||||
fn children(&self) -> &Vec<FolderHash>;
|
||||
fn parent(&self) -> Option<FolderHash>;
|
||||
|
||||
fn permissions(&self) -> FolderPermissions;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -342,6 +345,10 @@ impl BackendFolder for DummyFolder {
|
|||
fn parent(&self) -> Option<FolderHash> {
|
||||
None
|
||||
}
|
||||
|
||||
fn permissions(&self) -> FolderPermissions {
|
||||
FolderPermissions::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn folder_default() -> Folder {
|
||||
|
@ -364,3 +371,30 @@ impl Default for Folder {
|
|||
folder_default()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
pub struct FolderPermissions {
|
||||
pub create_messages: bool,
|
||||
pub remove_messages: bool,
|
||||
pub set_flags: bool,
|
||||
pub create_child: bool,
|
||||
pub rename_messages: bool,
|
||||
pub delete_messages: bool,
|
||||
pub delete_mailbox: bool,
|
||||
pub change_permissions: bool,
|
||||
}
|
||||
|
||||
impl Default for FolderPermissions {
|
||||
fn default() -> Self {
|
||||
FolderPermissions {
|
||||
create_messages: false,
|
||||
remove_messages: false,
|
||||
set_flags: false,
|
||||
create_child: false,
|
||||
rename_messages: false,
|
||||
delete_messages: false,
|
||||
delete_mailbox: false,
|
||||
change_permissions: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,7 +123,10 @@ impl MailBackend for ImapType {
|
|||
let uid_store = self.uid_store.clone();
|
||||
let folder_path = folder.path().to_string();
|
||||
let folder_hash = folder.hash();
|
||||
let folder_exists = self.folders.lock().unwrap()[&folder_hash].exists.clone();
|
||||
let (permissions, folder_exists) = {
|
||||
let f = &self.folders.lock().unwrap()[&folder_hash];
|
||||
(f.permissions.clone(), f.exists.clone())
|
||||
};
|
||||
let connection = self.connection.clone();
|
||||
let closure = move |_work_context| {
|
||||
let connection = connection.clone();
|
||||
|
@ -134,13 +137,19 @@ impl MailBackend for ImapType {
|
|||
let mut conn = conn.unwrap();
|
||||
debug!("locked for get {}", folder_path);
|
||||
|
||||
/* first SELECT the mailbox to get READ/WRITE permissions (because EXAMINE only
|
||||
* returns READ-ONLY for both cases) */
|
||||
exit_on_error!(&tx,
|
||||
conn.send_command(format!("EXAMINE {}", folder_path).as_bytes())
|
||||
conn.send_command(format!("SELECT {}", folder_path).as_bytes())
|
||||
conn.read_response(&mut response)
|
||||
);
|
||||
let examine_response = protocol_parser::select_response(&response);
|
||||
exit_on_error!(&tx, examine_response);
|
||||
let examine_response = examine_response.unwrap();
|
||||
debug!(
|
||||
"folder: {} examine_response: {:?}",
|
||||
folder_path, examine_response
|
||||
);
|
||||
let mut exists: usize = examine_response.uidnext - 1;
|
||||
{
|
||||
let mut uidvalidities = uid_store.uidvalidity.lock().unwrap();
|
||||
|
@ -149,11 +158,22 @@ impl MailBackend for ImapType {
|
|||
.entry(folder_hash)
|
||||
.or_insert(examine_response.uidvalidity);
|
||||
*v = examine_response.uidvalidity;
|
||||
}
|
||||
{
|
||||
|
||||
let mut permissions = permissions.lock().unwrap();
|
||||
permissions.create_messages = !examine_response.read_only;
|
||||
permissions.remove_messages = !examine_response.read_only;
|
||||
permissions.set_flags = !examine_response.read_only;
|
||||
permissions.rename_messages = !examine_response.read_only;
|
||||
permissions.delete_messages = !examine_response.read_only;
|
||||
permissions.delete_messages = !examine_response.read_only;
|
||||
let mut folder_exists = folder_exists.lock().unwrap();
|
||||
*folder_exists = exists;
|
||||
}
|
||||
/* reselecting the same mailbox with EXAMINE prevents expunging it */
|
||||
exit_on_error!(&tx,
|
||||
conn.send_command(format!("EXAMINE {}", folder_path).as_bytes())
|
||||
conn.read_response(&mut response)
|
||||
);
|
||||
|
||||
while exists > 1 {
|
||||
let mut envelopes = vec![];
|
||||
|
@ -285,11 +305,23 @@ impl MailBackend for ImapType {
|
|||
let path = {
|
||||
let folders = self.folders.lock().unwrap();
|
||||
|
||||
folders
|
||||
.values()
|
||||
.find(|v| v.name == folder)
|
||||
let f_result = folders.values().find(|v| v.name == folder);
|
||||
if f_result
|
||||
.map(|f| !f.permissions.lock().unwrap().create_messages)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return Err(MeliError::new(format!(
|
||||
"You are not allowed to create messages in folder {}",
|
||||
folder
|
||||
)));
|
||||
}
|
||||
|
||||
f_result
|
||||
.map(|v| v.path().to_string())
|
||||
.ok_or(MeliError::new(""))?
|
||||
.ok_or(MeliError::new(format!(
|
||||
"Folder with name {} not found.",
|
||||
folder
|
||||
)))?
|
||||
};
|
||||
let mut response = String::with_capacity(8 * 1024);
|
||||
let mut conn = self.connection.lock().unwrap();
|
||||
|
@ -365,6 +397,9 @@ impl MailBackend for ImapType {
|
|||
conn.send_command(format!("UNSUBSCRIBE \"{}\"", path,).as_bytes())?;
|
||||
conn.read_response(&mut response)?;
|
||||
}
|
||||
SetPermissions(_new_val) => {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
use crate::backends::{BackendFolder, Folder, FolderHash};
|
||||
use crate::backends::{BackendFolder, Folder, FolderHash, FolderPermissions};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
|
@ -29,6 +29,7 @@ pub struct ImapFolder {
|
|||
pub(super) parent: Option<FolderHash>,
|
||||
pub(super) children: Vec<FolderHash>,
|
||||
|
||||
pub permissions: Arc<Mutex<FolderPermissions>>,
|
||||
pub exists: Arc<Mutex<usize>>,
|
||||
}
|
||||
|
||||
|
@ -60,6 +61,7 @@ impl BackendFolder for ImapFolder {
|
|||
name: self.name.clone(),
|
||||
parent: self.parent,
|
||||
children: self.children.clone(),
|
||||
permissions: self.permissions.clone(),
|
||||
exists: self.exists.clone(),
|
||||
})
|
||||
}
|
||||
|
@ -67,4 +69,8 @@ impl BackendFolder for ImapFolder {
|
|||
fn parent(&self) -> Option<FolderHash> {
|
||||
self.parent
|
||||
}
|
||||
|
||||
fn permissions(&self) -> FolderPermissions {
|
||||
*self.permissions.lock().unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -287,6 +287,7 @@ pub struct SelectResponse {
|
|||
pub uidvalidity: usize,
|
||||
pub uidnext: usize,
|
||||
pub permanentflags: Flag,
|
||||
pub read_only: bool,
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -337,6 +338,10 @@ pub fn select_response(input: &str) -> Result<SelectResponse> {
|
|||
flags(&l["* OK [PERMANENTFLAGS (".len()..l.find(')').unwrap()])
|
||||
.to_full_result()
|
||||
.unwrap();
|
||||
} else if l.contains("OK [READ-WRITE]") {
|
||||
ret.read_only = false;
|
||||
} else if l.contains("OK [READ-ONLY]") {
|
||||
ret.read_only = true;
|
||||
} else if !l.is_empty() {
|
||||
debug!("select response: {}", l);
|
||||
}
|
||||
|
|
|
@ -182,6 +182,7 @@ pub struct MaildirFolder {
|
|||
path: PathBuf,
|
||||
parent: Option<FolderHash>,
|
||||
children: Vec<FolderHash>,
|
||||
permissions: FolderPermissions,
|
||||
}
|
||||
|
||||
impl MaildirFolder {
|
||||
|
@ -229,6 +230,12 @@ impl MaildirFolder {
|
|||
None
|
||||
};
|
||||
|
||||
let read_only = if let Ok(metadata) = std::fs::metadata(&pathbuf) {
|
||||
metadata.permissions().readonly()
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
let ret = MaildirFolder {
|
||||
hash: h.finish(),
|
||||
name: file_name,
|
||||
|
@ -236,6 +243,16 @@ impl MaildirFolder {
|
|||
fs_path: pathbuf,
|
||||
parent,
|
||||
children,
|
||||
permissions: FolderPermissions {
|
||||
create_messages: !read_only,
|
||||
remove_messages: !read_only,
|
||||
set_flags: !read_only,
|
||||
create_child: !read_only,
|
||||
rename_messages: !read_only,
|
||||
delete_messages: !read_only,
|
||||
delete_mailbox: !read_only,
|
||||
change_permissions: false,
|
||||
},
|
||||
};
|
||||
ret.is_valid()?;
|
||||
Ok(ret)
|
||||
|
@ -290,10 +307,15 @@ impl BackendFolder for MaildirFolder {
|
|||
path: self.path.clone(),
|
||||
children: self.children.clone(),
|
||||
parent: self.parent,
|
||||
permissions: self.permissions,
|
||||
})
|
||||
}
|
||||
|
||||
fn parent(&self) -> Option<FolderHash> {
|
||||
self.parent
|
||||
}
|
||||
|
||||
fn permissions(&self) -> FolderPermissions {
|
||||
self.permissions
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,8 @@ use crate::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext};
|
|||
use crate::backends::BackendOp;
|
||||
use crate::backends::FolderHash;
|
||||
use crate::backends::{
|
||||
BackendFolder, Folder, MailBackend, RefreshEvent, RefreshEventConsumer, RefreshEventKind,
|
||||
BackendFolder, Folder, FolderPermissions, MailBackend, RefreshEvent, RefreshEventConsumer,
|
||||
RefreshEventKind,
|
||||
};
|
||||
use crate::conf::AccountSettings;
|
||||
use crate::email::parser::BytesExt;
|
||||
|
@ -86,6 +87,7 @@ struct MboxFolder {
|
|||
content: Vec<u8>,
|
||||
children: Vec<FolderHash>,
|
||||
parent: Option<FolderHash>,
|
||||
permissions: FolderPermissions,
|
||||
}
|
||||
|
||||
impl BackendFolder for MboxFolder {
|
||||
|
@ -114,6 +116,7 @@ impl BackendFolder for MboxFolder {
|
|||
content: self.content.clone(),
|
||||
children: self.children.clone(),
|
||||
parent: self.parent,
|
||||
permissions: self.permissions,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -124,6 +127,10 @@ impl BackendFolder for MboxFolder {
|
|||
fn parent(&self) -> Option<FolderHash> {
|
||||
self.parent
|
||||
}
|
||||
|
||||
fn permissions(&self) -> FolderPermissions {
|
||||
self.permissions
|
||||
}
|
||||
}
|
||||
|
||||
/// `BackendOp` implementor for Mbox
|
||||
|
@ -574,6 +581,13 @@ impl MboxType {
|
|||
.map(|f| f.to_string_lossy().into())
|
||||
.unwrap_or(String::new());
|
||||
let hash = get_path_hash!(&ret.path);
|
||||
|
||||
let read_only = if let Ok(metadata) = std::fs::metadata(&ret.path) {
|
||||
metadata.permissions().readonly()
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
ret.folders.lock().unwrap().insert(
|
||||
hash,
|
||||
MboxFolder {
|
||||
|
@ -583,6 +597,16 @@ impl MboxType {
|
|||
content: Vec::new(),
|
||||
children: Vec::new(),
|
||||
parent: None,
|
||||
permissions: FolderPermissions {
|
||||
create_messages: !read_only,
|
||||
remove_messages: !read_only,
|
||||
set_flags: !read_only,
|
||||
create_child: !read_only,
|
||||
rename_messages: !read_only,
|
||||
delete_messages: !read_only,
|
||||
delete_mailbox: !read_only,
|
||||
change_permissions: false,
|
||||
},
|
||||
},
|
||||
);
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue