identity_credential/credential/
subject.rs

1// Copyright 2020-2021 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use serde::Deserialize;
5use serde::Serialize;
6
7use identity_core::common::Object;
8use identity_core::common::Url;
9
10/// An entity who is the target of a set of claims.
11///
12/// [More Info](https://www.w3.org/TR/vc-data-model/#credential-subject)
13#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
14pub struct Subject {
15  /// A URI identifying the credential subject.
16  #[serde(skip_serializing_if = "Option::is_none")]
17  pub id: Option<Url>,
18  /// Additional properties of the credential subject.
19  #[serde(flatten)]
20  pub properties: Object,
21}
22
23impl Subject {
24  /// Creates a new `Subject`.
25  pub fn new() -> Self {
26    Self::with_properties(Object::new())
27  }
28
29  /// Creates a new `Subject` with the given `id`.
30  pub fn with_id(id: Url) -> Self {
31    Self::with_id_and_properties(id, Object::new())
32  }
33
34  /// Creates a new `Subject` with the given `properties`.
35  pub fn with_properties(properties: Object) -> Self {
36    Self { id: None, properties }
37  }
38
39  /// Creates a new `Subject` with the given `id` and `properties`.
40  pub fn with_id_and_properties(id: Url, properties: Object) -> Self {
41    Self {
42      id: Some(id),
43      properties,
44    }
45  }
46}
47
48#[cfg(test)]
49mod tests {
50  use identity_core::convert::FromJson;
51
52  use crate::credential::Subject;
53
54  const JSON1: &str = include_str!("../../tests/fixtures/subject-1.json");
55  const JSON2: &str = include_str!("../../tests/fixtures/subject-2.json");
56  const JSON3: &str = include_str!("../../tests/fixtures/subject-3.json");
57  const JSON4: &str = include_str!("../../tests/fixtures/subject-4.json");
58  const JSON5: &str = include_str!("../../tests/fixtures/subject-5.json");
59  const JSON6: &str = include_str!("../../tests/fixtures/subject-6.json");
60  const JSON7: &str = include_str!("../../tests/fixtures/subject-7.json");
61  const JSON8: &str = include_str!("../../tests/fixtures/subject-8.json");
62  const JSON9: &str = include_str!("../../tests/fixtures/subject-9.json");
63  const JSON10: &str = include_str!("../../tests/fixtures/subject-10.json");
64
65  #[test]
66  fn test_from_json() {
67    let subject: Subject = Subject::from_json(JSON1).unwrap();
68    assert_eq!(subject.id.unwrap(), "did:example:ebfeb1f712ebc6f1c276e12ec21");
69    assert_eq!(
70      subject.properties["alumniOf"]["id"],
71      "did:example:c276e12ec21ebfeb1f712ebc6f1"
72    );
73    assert_eq!(subject.properties["alumniOf"]["name"][0]["value"], "Example University");
74    assert_eq!(subject.properties["alumniOf"]["name"][0]["lang"], "en");
75    assert_eq!(
76      subject.properties["alumniOf"]["name"][1]["value"],
77      "Exemple d'Université"
78    );
79    assert_eq!(subject.properties["alumniOf"]["name"][1]["lang"], "fr");
80
81    let subject: Subject = Subject::from_json(JSON2).unwrap();
82    assert_eq!(subject.id.unwrap(), "did:example:ebfeb1f712ebc6f1c276e12ec21");
83    assert_eq!(subject.properties["degree"]["type"], "BachelorDegree");
84    assert_eq!(subject.properties["degree"]["name"], "Bachelor of Science and Arts");
85
86    let subject: Subject = Subject::from_json(JSON3).unwrap();
87    assert_eq!(subject.id.unwrap(), "did:example:abcdef1234567");
88    assert_eq!(subject.properties["name"], "Jane Doe");
89
90    let subject: Subject = Subject::from_json(JSON4).unwrap();
91    assert_eq!(subject.id.unwrap(), "did:example:abcdef1234567");
92    assert_eq!(subject.properties["name"], "Jane Doe");
93    assert_eq!(subject.properties["favoriteFood"], "Papaya");
94
95    let subject: Subject = Subject::from_json(JSON5).unwrap();
96    assert_eq!(subject.properties["givenName"], "Jane");
97    assert_eq!(subject.properties["familyName"], "Doe");
98    assert_eq!(subject.properties["degree"]["type"], "BachelorDegree");
99    assert_eq!(subject.properties["degree"]["name"], "Bachelor of Science and Arts");
100    assert_eq!(subject.properties["degree"]["college"], "College of Engineering");
101
102    let subject: Subject = Subject::from_json(JSON6).unwrap();
103    assert_eq!(subject.properties["degreeType"], "BachelorDegree");
104    assert_eq!(subject.properties["degreeSchool"], "College of Engineering");
105
106    let subject: Subject = Subject::from_json(JSON7).unwrap();
107    assert_eq!(subject.id.unwrap(), "http://example.com/credentials/245");
108    assert_eq!(subject.properties["currentStatus"], "Disputed");
109    assert_eq!(subject.properties["statusReason"]["value"], "Address is out of date.");
110    assert_eq!(subject.properties["statusReason"]["lang"], "en");
111
112    let subject: Subject = Subject::from_json(JSON8).unwrap();
113    assert_eq!(subject.properties["degree"]["type"], "BachelorDegree");
114    assert_eq!(subject.properties["degree"]["name"], "Bachelor of Science and Arts");
115
116    let subject: Subject = Subject::from_json(JSON9).unwrap();
117    assert_eq!(subject.id.unwrap(), "did:example:ebfeb1f712ebc6f1c276e12ec21");
118    assert_eq!(subject.properties["image"], "https://example.edu/images/58473");
119    assert_eq!(
120      subject.properties["alumniOf"]["id"],
121      "did:example:c276e12ec21ebfeb1f712ebc6f1"
122    );
123    assert_eq!(subject.properties["alumniOf"]["name"][0]["value"], "Example University");
124    assert_eq!(subject.properties["alumniOf"]["name"][0]["lang"], "en");
125    assert_eq!(
126      subject.properties["alumniOf"]["name"][1]["value"],
127      "Exemple d'Université"
128    );
129    assert_eq!(subject.properties["alumniOf"]["name"][1]["lang"], "fr");
130
131    let subject: Subject = Subject::from_json(JSON10).unwrap();
132    assert_eq!(subject.id.unwrap(), "did:example:ebfeb1f712ebc6f1c276e12ec21");
133    assert_eq!(
134      subject.properties["image"],
135      "ipfs:/ipfs/QmXfrS3pHerg44zzK6QKQj6JDk8H6cMtQS7pdXbohwNQfK/image"
136    );
137    assert_eq!(
138      subject.properties["alumniOf"]["id"],
139      "did:example:c276e12ec21ebfeb1f712ebc6f1"
140    );
141    assert_eq!(subject.properties["alumniOf"]["name"][0]["value"], "Example University");
142    assert_eq!(subject.properties["alumniOf"]["name"][0]["lang"], "en");
143    assert_eq!(
144      subject.properties["alumniOf"]["name"][1]["value"],
145      "Exemple d'Université"
146    );
147    assert_eq!(subject.properties["alumniOf"]["name"][1]["lang"], "fr");
148  }
149}