Skip to content

Commit b37fcb7

Browse files
committed
fix(rust/signed-doc): add missing metadata aditional fields
1 parent fbf4584 commit b37fcb7

File tree

1 file changed

+180
-16
lines changed

1 file changed

+180
-16
lines changed

rust/signed_doc/src/metadata/additional_fields.rs

Lines changed: 180 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
//! Catalyst Signed Document Additional Fields.
22
33
use anyhow::anyhow;
4+
use coset::{cbor::Value, Label, ProtectedHeader};
45

5-
use super::{cose_protected_header_find, DocumentRef};
6+
use super::{cose_protected_header_find, DocumentRef, UuidV4};
67

78
/// Additional Metadata Fields.
89
///
910
/// These values are extracted from the COSE Sign protected header labels.
1011
#[derive(Default, Debug, serde::Serialize, serde::Deserialize)]
11-
pub(super) struct AdditionalFields {
12+
pub struct AdditionalFields {
1213
/// Reference to the latest document.
1314
#[serde(rename = "ref")]
1415
pub(super) doc_ref: Option<DocumentRef>,
@@ -18,18 +19,90 @@ pub(super) struct AdditionalFields {
1819
pub(super) reply: Option<DocumentRef>,
1920
/// Reference to the document section.
2021
pub(super) section: Option<String>,
22+
/// Reference to the document collaborators. Collaborator type is TBD.
23+
pub(super) collabs: Option<Vec<String>>,
24+
/// Unique identifier for the brand that is running the voting.
25+
pub(super) brand_id: Option<UuidV4>,
26+
/// Unique identifier for the campaign of voting.
27+
pub(super) campaign_id: Option<UuidV4>,
28+
/// Unique identifier for the election.
29+
pub(super) election_id: Option<UuidV4>,
30+
/// Unique identifier for the voting category as a collection of proposals.
31+
pub(super) category_id: Option<UuidV4>,
2132
}
2233

23-
impl TryFrom<&coset::ProtectedHeader> for AdditionalFields {
34+
impl From<&AdditionalFields> for Vec<(Label, Value)> {
35+
fn from(fields: &AdditionalFields) -> Self {
36+
let mut vec = Vec::new();
37+
38+
if let Some(doc_ref) = &fields.doc_ref {
39+
vec.push((Label::Text("ref".to_string()), doc_ref.into()));
40+
}
41+
42+
if let Some(template) = &fields.template {
43+
vec.push((Label::Text("template".to_string()), template.into()));
44+
}
45+
46+
if let Some(reply) = &fields.reply {
47+
vec.push((Label::Text("reply".to_string()), reply.into()));
48+
}
49+
50+
if let Some(section) = &fields.section {
51+
vec.push((
52+
Label::Text("section".to_string()),
53+
Value::Text(section.clone()),
54+
));
55+
}
56+
57+
if let Some(collabs) = &fields.collabs {
58+
if !collabs.is_empty() {
59+
vec.push((
60+
Label::Text("collabs".to_string()),
61+
Value::Array(collabs.iter().cloned().map(Value::Text).collect()),
62+
));
63+
}
64+
}
65+
66+
if let Some(brand_id) = &fields.brand_id {
67+
vec.push((Label::Text("brand_id".to_string()), Value::from(*brand_id)));
68+
}
69+
70+
if let Some(campaign_id) = &fields.campaign_id {
71+
vec.push((
72+
Label::Text("campaign_id".to_string()),
73+
Value::from(*campaign_id),
74+
));
75+
}
76+
77+
if let Some(election_id) = &fields.election_id {
78+
vec.push((
79+
Label::Text("election_id".to_string()),
80+
Value::from(*election_id),
81+
));
82+
}
83+
84+
if let Some(category_id) = &fields.category_id {
85+
vec.push((
86+
Label::Text("category_id".to_string()),
87+
Value::from(*category_id),
88+
));
89+
}
90+
91+
vec
92+
}
93+
}
94+
95+
impl TryFrom<&ProtectedHeader> for AdditionalFields {
2496
type Error = Vec<anyhow::Error>;
2597

26-
fn try_from(protected: &coset::ProtectedHeader) -> Result<Self, Self::Error> {
98+
#[allow(clippy::too_many_lines)]
99+
fn try_from(protected: &ProtectedHeader) -> Result<Self, Self::Error> {
27100
let mut extra = AdditionalFields::default();
28101
let mut errors = Vec::new();
29102

30-
if let Some(cbor_doc_ref) = cose_protected_header_find(protected, |key| {
31-
key == &coset::Label::Text("ref".to_string())
32-
}) {
103+
if let Some(cbor_doc_ref) =
104+
cose_protected_header_find(protected, |key| key == &Label::Text("ref".to_string()))
105+
{
33106
match DocumentRef::try_from(cbor_doc_ref) {
34107
Ok(doc_ref) => {
35108
extra.doc_ref = Some(doc_ref);
@@ -42,9 +115,9 @@ impl TryFrom<&coset::ProtectedHeader> for AdditionalFields {
42115
}
43116
}
44117

45-
if let Some(cbor_doc_template) = cose_protected_header_find(protected, |key| {
46-
key == &coset::Label::Text("template".to_string())
47-
}) {
118+
if let Some(cbor_doc_template) =
119+
cose_protected_header_find(protected, |key| key == &Label::Text("template".to_string()))
120+
{
48121
match DocumentRef::try_from(cbor_doc_template) {
49122
Ok(doc_template) => {
50123
extra.template = Some(doc_template);
@@ -57,9 +130,9 @@ impl TryFrom<&coset::ProtectedHeader> for AdditionalFields {
57130
}
58131
}
59132

60-
if let Some(cbor_doc_reply) = cose_protected_header_find(protected, |key| {
61-
key == &coset::Label::Text("reply".to_string())
62-
}) {
133+
if let Some(cbor_doc_reply) =
134+
cose_protected_header_find(protected, |key| key == &Label::Text("reply".to_string()))
135+
{
63136
match DocumentRef::try_from(cbor_doc_reply) {
64137
Ok(doc_reply) => {
65138
extra.reply = Some(doc_reply);
@@ -72,9 +145,9 @@ impl TryFrom<&coset::ProtectedHeader> for AdditionalFields {
72145
}
73146
}
74147

75-
if let Some(cbor_doc_section) = cose_protected_header_find(protected, |key| {
76-
key == &coset::Label::Text("section".to_string())
77-
}) {
148+
if let Some(cbor_doc_section) =
149+
cose_protected_header_find(protected, |key| key == &Label::Text("section".to_string()))
150+
{
78151
match cbor_doc_section.clone().into_text() {
79152
Ok(doc_section) => {
80153
extra.section = Some(doc_section);
@@ -87,6 +160,97 @@ impl TryFrom<&coset::ProtectedHeader> for AdditionalFields {
87160
}
88161
}
89162

163+
if let Some(cbor_doc_collabs) =
164+
cose_protected_header_find(protected, |key| key == &Label::Text("collabs".to_string()))
165+
{
166+
match cbor_doc_collabs.clone().into_array() {
167+
Ok(collabs) => {
168+
let mut c = Vec::new();
169+
for (ids, collaborator) in collabs.iter().cloned().enumerate() {
170+
match collaborator.into_text() {
171+
Ok(collaborator) => {
172+
c.push(collaborator);
173+
},
174+
Err(e) => {
175+
errors.push(anyhow!(
176+
"Invalid Collaborator at index {ids} of COSE protected header `collabs` field, err: {e:?}"
177+
));
178+
},
179+
}
180+
}
181+
182+
if !c.is_empty() {
183+
extra.collabs = Some(c);
184+
}
185+
},
186+
Err(e) => {
187+
errors.push(anyhow!(
188+
"Invalid COSE protected header `collabs` field, err: {e:?}"
189+
));
190+
},
191+
}
192+
}
193+
194+
if let Some(cbor_doc_brand_id) =
195+
cose_protected_header_find(protected, |key| key == &Label::Text("brand_id".to_string()))
196+
{
197+
match UuidV4::try_from(cbor_doc_brand_id) {
198+
Ok(brand_id) => {
199+
extra.brand_id = Some(brand_id);
200+
},
201+
Err(e) => {
202+
errors.push(anyhow!(
203+
"Invalid COSE protected header `brand_id` field, err: {e}"
204+
));
205+
},
206+
}
207+
}
208+
209+
if let Some(cbor_doc_campaign_id) = cose_protected_header_find(protected, |key| {
210+
key == &Label::Text("campaign_id".to_string())
211+
}) {
212+
match UuidV4::try_from(cbor_doc_campaign_id) {
213+
Ok(campaign_id) => {
214+
extra.campaign_id = Some(campaign_id);
215+
},
216+
Err(e) => {
217+
errors.push(anyhow!(
218+
"Invalid COSE protected header `campaign_id` field, err: {e}"
219+
));
220+
},
221+
}
222+
}
223+
224+
if let Some(cbor_doc_election_id) = cose_protected_header_find(protected, |key| {
225+
key == &Label::Text("election_id".to_string())
226+
}) {
227+
match UuidV4::try_from(cbor_doc_election_id) {
228+
Ok(election_id) => {
229+
extra.election_id = Some(election_id);
230+
},
231+
Err(e) => {
232+
errors.push(anyhow!(
233+
"Invalid COSE protected header `election_id` field, err: {e}"
234+
));
235+
},
236+
}
237+
}
238+
239+
if let Some(cbor_doc_category_id) = cose_protected_header_find(protected, |key| {
240+
key == &Label::Text("category_id".to_string())
241+
}) {
242+
match UuidV4::try_from(cbor_doc_category_id) {
243+
Ok(category_id) => {
244+
extra.category_id = Some(category_id);
245+
},
246+
Err(e) => {
247+
errors.push(anyhow!(
248+
"Invalid COSE protected header `category_id` field, err: {e}"
249+
));
250+
},
251+
}
252+
}
253+
90254
if errors.is_empty() {
91255
Ok(extra)
92256
} else {

0 commit comments

Comments
 (0)