Jelajahi Sumber

bin/tau: setting access types as read-write and read-only(default)

dasman 2 tahun lalu
induk
melakukan
d47eac66a4

+ 27 - 1
bin/tau/taud/src/jsonrpc.rs

@@ -46,7 +46,7 @@ use taud::{
     error::{to_json_result, TaudError, TaudResult},
     month_tasks::MonthTasks,
     task_info::{Comment, TaskInfo},
-    util::set_event,
+    util::{check_write_access, set_event},
 };
 
 pub struct JsonRpcInterface {
@@ -55,6 +55,8 @@ pub struct JsonRpcInterface {
     nickname: String,
     workspace: Mutex<String>,
     workspaces: Arc<HashMap<String, ChaChaBox>>,
+    write: Option<String>,
+    password: Option<String>,
     p2p: net::P2pPtr,
     event_graph: EventGraphPtr,
     dnet_sub: JsonSubscriber,
@@ -114,6 +116,8 @@ impl JsonRpcInterface {
         notify_queue_sender: smol::channel::Sender<TaskInfo>,
         nickname: String,
         workspaces: Arc<HashMap<String, ChaChaBox>>,
+        write: Option<String>,
+        password: Option<String>,
         p2p: net::P2pPtr,
         event_graph: EventGraphPtr,
         dnet_sub: JsonSubscriber,
@@ -126,6 +130,8 @@ impl JsonRpcInterface {
             workspace,
             workspaces,
             notify_queue_sender,
+            write,
+            password,
             p2p,
             event_graph,
             rpc_connections: Mutex::new(HashSet::new()),
@@ -316,6 +322,10 @@ impl JsonRpcInterface {
             _ => return Err(TaudError::InvalidData("Invalid parameter \"created_at\"".to_string())),
         };
 
+        if !check_write_access(self.write.clone(), self.password.clone())? {
+            return Ok(JsonValue::Boolean(false))
+        }
+
         let mut new_task: TaskInfo = TaskInfo::new(
             self.workspace.lock().await.clone(),
             params["title"].get::<String>().unwrap(),
@@ -389,6 +399,10 @@ impl JsonRpcInterface {
             return Err(TaudError::InvalidData("len of params should be 2".into()))
         }
 
+        if !check_write_access(self.write.clone(), self.password.clone())? {
+            return Ok(JsonValue::Boolean(false))
+        }
+
         let ws = self.workspace.lock().await.clone();
 
         let task = self.check_params_for_modify(
@@ -417,6 +431,10 @@ impl JsonRpcInterface {
             return Err(TaudError::InvalidData("len of params should be 2".into()))
         }
 
+        if !check_write_access(self.write.clone(), self.password.clone())? {
+            return Ok(JsonValue::Boolean(false))
+        }
+
         let state = params[1].get::<String>().unwrap();
         let ws = self.workspace.lock().await.clone();
 
@@ -445,6 +463,10 @@ impl JsonRpcInterface {
             return Err(TaudError::InvalidData("len of params should be 2".into()))
         }
 
+        if !check_write_access(self.write.clone(), self.password.clone())? {
+            return Ok(JsonValue::Boolean(false))
+        }
+
         let ref_id = params[0].get::<String>().unwrap();
         let comment_content = params[1].get::<String>().unwrap();
 
@@ -630,6 +652,10 @@ impl JsonRpcInterface {
             return Err(TaudError::InvalidData("Invalid path".into()))
         }
 
+        if !check_write_access(self.write.clone(), self.password.clone())? {
+            return Ok(JsonValue::Boolean(false))
+        }
+
         let path = params[0].get::<String>().unwrap();
         let path = expand_path(path)?.join("exported_tasks");
         let ws = self.workspace.lock().await.clone();

+ 2 - 0
bin/tau/taud/src/main.rs

@@ -516,6 +516,8 @@ async fn realmain(settings: Args, executor: Arc<smol::Executor<'static>>) -> Res
         broadcast_snd,
         nickname.unwrap(),
         workspaces.clone(),
+        settings.write,
+        settings.password,
         p2p.clone(),
         event_graph.clone(),
         json_sub,

+ 8 - 0
bin/tau/taud/src/settings.rs

@@ -57,6 +57,14 @@ pub struct Args {
     #[structopt(long)]
     pub workspaces: Vec<String>,
 
+    /// Write access key
+    #[structopt(long)]
+    pub write: Option<String>,
+
+    /// Password
+    #[structopt(long)]
+    pub password: Option<String>,
+
     ///  Clean all the local data in datastore path
     /// (BE CAREFUL) Check the datastore path in the config file before running this
     #[structopt(long)]

+ 52 - 2
bin/tau/taud/src/util.rs

@@ -22,12 +22,16 @@ use std::{
     path::Path,
 };
 
-use log::debug;
+use crypto_box::aead::Aead;
+use log::{debug, error};
 
 use darkfi::{Error, Result};
 use rand::{distributions::Alphanumeric, rngs::OsRng, Rng};
 
-use crate::task_info::{TaskEvent, TaskInfo};
+use crate::{
+    error::{TaudError, TaudResult},
+    task_info::{TaskEvent, TaskInfo},
+};
 
 pub fn set_event(task_info: &mut TaskInfo, action: &str, author: &str, content: &str) {
     debug!(target: "tau", "TaskInfo::set_event()");
@@ -43,3 +47,49 @@ pub fn pipe_write<P: AsRef<Path>>(path: P) -> Result<File> {
 pub fn gen_id(len: usize) -> String {
     OsRng.sample_iter(&Alphanumeric).take(len).map(char::from).collect()
 }
+
+pub fn check_write_access(write: Option<String>, password: Option<String>) -> TaudResult<bool> {
+    let secret = if write.is_some() {
+        let scrt = write.clone().unwrap();
+        let bytes: [u8; 32] = bs58::decode(scrt)
+            .into_vec()
+            .map_err(|_| {
+                Error::ParseFailed("Parse secret key failed, couldn't decode into vector of bytes")
+            })?
+            .try_into()
+            .map_err(|_| Error::ParseFailed("Parse secret key failed"))?;
+        crypto_box::SecretKey::from(bytes)
+    } else {
+        crypto_box::SecretKey::generate(&mut OsRng)
+    };
+
+    let public = secret.public_key();
+    let chacha_box = crypto_box::ChaChaBox::new(&public, &secret);
+
+    if password.is_some() {
+        let bytes = match bs58::decode(password.clone().unwrap()).into_vec() {
+            Ok(v) => v,
+            Err(_) => return Err(TaudError::DecryptionError("Error decoding payload".to_string())),
+        };
+
+        if bytes.len() < 25 {
+            return Err(TaudError::DecryptionError("Invalid bytes length".to_string()))
+        }
+
+        // Try extracting the nonce
+        let nonce = bytes[0..24].into();
+
+        // Take the remaining ciphertext
+        let pswd = &bytes[24..];
+
+        if chacha_box.decrypt(nonce, pswd).is_err() {
+            error!(target: "taud", "You don't have write access");
+            return Ok(false);
+        };
+    } else {
+        error!(target: "taud", "You don't have write access");
+        return Ok(false);
+    };
+
+    Ok(true)
+}