commit 9511456ded780ae14fd9fca9dee672c8bfe3b0f8
parent 04b198a7e24674ecd211b89d0b03810e8d120cac
Author: Daniel GarcĂa <dani-garcia@users.noreply.github.com>
Date: Thu, 9 Aug 2018 01:44:16 +0200
Merge pull request #116 from krankur/beta
Implemented bulk cipher share (share selected) #100
Diffstat:
3 files changed, 68 insertions(+), 5 deletions(-)
diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs
@@ -87,6 +87,8 @@ fn get_cipher_details(uuid: String, headers: Headers, conn: DbConn) -> JsonResul
#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
struct CipherData {
+ // Id is optional as it is included only in bulk share
+ Id: Option<String>,
// Folder id is not included in import
FolderId: Option<String>,
// TODO: Some of these might appear all the time, no need for Option
@@ -332,6 +334,65 @@ struct ShareCipherData {
fn post_cipher_share(uuid: String, data: JsonUpcase<ShareCipherData>, headers: Headers, conn: DbConn) -> JsonResult {
let data: ShareCipherData = data.into_inner().data;
+ share_cipher_by_uuid(&uuid, data, &headers, &conn)
+}
+
+#[put("/ciphers/<uuid>/share", data = "<data>")]
+fn put_cipher_share(uuid: String, data: JsonUpcase<ShareCipherData>, headers: Headers, conn: DbConn) -> JsonResult {
+ let data: ShareCipherData = data.into_inner().data;
+
+ share_cipher_by_uuid(&uuid, data, &headers, &conn)
+}
+
+#[derive(Deserialize)]
+#[allow(non_snake_case)]
+struct ShareSelectedCipherData {
+ Ciphers: Vec<CipherData>,
+ CollectionIds: Vec<String>
+}
+
+#[put("/ciphers/share", data = "<data>")]
+fn put_cipher_share_seleted(data: JsonUpcase<ShareSelectedCipherData>, headers: Headers, conn: DbConn) -> EmptyResult {
+ let mut data: ShareSelectedCipherData = data.into_inner().data;
+ let mut cipher_ids: Vec<String> = Vec::new();
+
+ if data.Ciphers.len() == 0 {
+ err!("You must select at least one cipher.")
+ }
+
+ if data.CollectionIds.len() == 0 {
+ err!("You must select at least one collection.")
+ }
+
+ for cipher in data.Ciphers.iter() {
+ match cipher.Id {
+ Some(ref id) => cipher_ids.push(id.to_string()),
+ None => err!("Request missing ids field")
+ };
+ }
+
+ let attachments = Attachment::find_by_ciphers(cipher_ids, &conn);
+
+ if attachments.len() > 0 {
+ err!("Ciphers should not have any attachments.")
+ }
+
+ while let Some(cipher) = data.Ciphers.pop() {
+ let mut shared_cipher_data = ShareCipherData {
+ Cipher: cipher,
+ CollectionIds: data.CollectionIds.clone()
+ };
+
+ match shared_cipher_data.Cipher.Id.take() {
+ Some(id) => share_cipher_by_uuid(&id, shared_cipher_data , &headers, &conn)?,
+ None => err!("Request missing ids field")
+ };
+ }
+
+ Ok(())
+}
+
+fn share_cipher_by_uuid(uuid: &str, data: ShareCipherData, headers: &Headers, conn: &DbConn) -> JsonResult {
let mut cipher = match Cipher::find_by_uuid(&uuid, &conn) {
Some(cipher) => {
if cipher.is_write_accessible_to_user(&headers.user.uuid, &conn) {
@@ -365,11 +426,6 @@ fn post_cipher_share(uuid: String, data: JsonUpcase<ShareCipherData>, headers: H
}
}
-#[put("/ciphers/<uuid>/share", data = "<data>")]
-fn put_cipher_share(uuid: String, data: JsonUpcase<ShareCipherData>, headers: Headers, conn: DbConn) -> JsonResult {
- post_cipher_share(uuid, data, headers, conn)
-}
-
#[post("/ciphers/<uuid>/attachment", format = "multipart/form-data", data = "<data>")]
fn post_attachment(uuid: String, data: Data, content_type: &ContentType, headers: Headers, conn: DbConn) -> JsonResult {
let cipher = match Cipher::find_by_uuid(&uuid, &conn) {
diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs
@@ -42,6 +42,7 @@ pub fn routes() -> Vec<Route> {
post_cipher_admin,
post_cipher_share,
put_cipher_share,
+ put_cipher_share_seleted,
post_cipher,
put_cipher,
delete_cipher_post,
diff --git a/src/db/models/attachment.rs b/src/db/models/attachment.rs
@@ -111,4 +111,10 @@ impl Attachment {
.filter(attachments::cipher_uuid.eq(cipher_uuid))
.load::<Self>(&**conn).expect("Error loading attachments")
}
+
+ pub fn find_by_ciphers(cipher_uuids: Vec<String>, conn: &DbConn) -> Vec<Self> {
+ attachments::table
+ .filter(attachments::cipher_uuid.eq_any(cipher_uuids))
+ .load::<Self>(&**conn).expect("Error loading attachments")
+ }
}