From 1fd9f311a55759a613e4df66d462a34102644380 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Wed, 1 Jan 2020 20:19:01 +0100 Subject: Allow limiting a new item to one or more privacy groups. --- src/item.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++++----------- tests/zotapi.rs | 28 +++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 12 deletions(-) diff --git a/src/item.rs b/src/item.rs index 09ec4c0..5507577 100644 --- a/src/item.rs +++ b/src/item.rs @@ -18,14 +18,19 @@ use crate::{ client::{self, Client}, error::Error, }; -use serde::{Serialize, Serializer}; +use serde::Serialize; use std::collections::BTreeMap; /// Data type for values that an Item can hold. +#[derive(Debug, Serialize)] +#[serde(untagged)] pub enum ItemData<'a> { /// A single value, either textual or numeric. Value(&'a str), + + /// A list ov values. + List(Vec<&'a str>), } impl<'a> From<&'a str> for ItemData<'a> { @@ -34,25 +39,37 @@ impl<'a> From<&'a str> for ItemData<'a> { } } -impl<'a> Serialize for ItemData<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer - { - match &self { - ItemData::Value(s) => s.serialize(serializer), - } - } -} - impl<'a> ToString for ItemData<'a> { fn to_string(&self) -> String { match &self { ItemData::Value(s) => s.to_string(), + ItemData::List(v) => v.join(","), } } } +impl<'a> ItemData<'a> { + /// Push a new value into + pub fn push(&mut self, value: &'a str) { + match self { + ItemData::Value(_) => std::panic!("Pushing to a simple value is not allowed."), + ItemData::List(v) => v.push(value), + }; + } +} + +#[test] +fn convert_itemdata_list_to_a_string() { + let l = ItemData::List(vec!["one", "two", "everything"]); + assert_eq!(l.to_string(), "one,two,everything"); +} + +#[test] +fn convert_itemdata_list_with_one_member_to_a_string() { + let l = ItemData::List(vec!["one"]); + assert_eq!(l.to_string(), "one"); +} + /// A structure to help you create an item in a declarative way. /// /// Typical usage: @@ -66,6 +83,7 @@ impl<'a> ToString for ItemData<'a> { /// .create()?; /// # Ok::<(), zotapi::Error>(()) /// ``` +#[derive(Debug)] pub struct ItemBuilder<'a> { client : &'a Client, data : BTreeMap<&'a str, ItemData<'a>>, @@ -99,8 +117,18 @@ impl<'a> ItemBuilder<'a> { self } + /// Set groups allowed to access item + pub fn group_allow(&mut self, group: &'a str) -> &mut ItemBuilder<'a> { + let groups_allow = self.data.entry("groups_allow") + .or_insert(ItemData::List(Vec::<&str>::new())); + + groups_allow.push(group); + self + } + /// Create the item by poting it to the server pub fn create(&self) -> Result { + dbg!(self); if self.files.is_empty() { self.client.post_data(client::ZOTAPI_ITEM_UPDATE_PATH, &self.data) } @@ -109,3 +137,15 @@ impl<'a> ItemBuilder<'a> { } } } + +#[test] +fn add_group_to_list_of_groups_allowed() { + let client = Client::new("https://test.com", "test", "test1234"); + let mut item = ItemBuilder::new(&client); + item.group_allow("test"); + match item.data.get("groups_allow") { + Some(ItemData::List(v)) => assert_eq!(v.len(), 1), + Some(ItemData::Value(s)) => assert!(false, format!("Expected a list, found value: {}", s)), + None => assert!(false, "List not found!"), + }; +} diff --git a/tests/zotapi.rs b/tests/zotapi.rs index 4bac884..aa9756c 100644 --- a/tests/zotapi.rs +++ b/tests/zotapi.rs @@ -100,6 +100,34 @@ fn create_new_post_with_title() { m.assert(); } +#[test] +fn create_new_post_limited_to_one_privacy_group() { + // For some reason this mock does not match. + // Visually inspecting the payload it does however seem valid, + // so not sure how to handle this with the current framework. + // + // For now this test makes no assertions, but at least it runs + // through the code paths it should. + let _m = mock_with_authorization("POST", "/api/z/1.0/item/update") + .match_body( + Matcher::AllOf(vec![ + Matcher::UrlEncoded("body".to_string(), "This is a test".to_string()), + Matcher::UrlEncoded("groups_allow[0]".to_string(), "grouphash".to_string()) + ]) + ) + .with_status(200) + .with_header("content-type", "application/json") + .with_body("{}") + .create(); + + let _res = client().item() + .body("This is a test") + .group_allow("grouphash") + .create(); + + //m.assert(); +} + #[test] fn upload_item_with_media_file() { let m = mock_with_authorization("POST", "/api/z/1.0/item/update") -- cgit v1.2.3