1use crate::{
4 Account, Agent, AgentId, CIString, DataError, Fingerprint, Group, GroupId, MyEmailAddress,
5 Validate, ValidationError, emit_error, fingerprint::fingerprint_it,
6};
7use core::fmt;
8use iri_string::types::UriStr;
9use serde::{
10 Deserialize, Serialize,
11 de::{self, Error},
12};
13use serde_json::{Map, Value};
14use std::{hash::Hasher, str::FromStr};
15use tracing::{debug, error};
16
17#[derive(Clone, Debug, PartialEq, Serialize)]
24#[serde(untagged)]
25pub enum Actor {
26 Agent(Agent),
28 Group(Group),
30}
31
32#[derive(Debug, Serialize)]
33#[serde(untagged)]
34pub(crate) enum ActorId {
35 Agent(AgentId),
36 Group(GroupId),
37}
38
39impl From<Actor> for ActorId {
40 fn from(value: Actor) -> Self {
41 match value {
42 Actor::Agent(agent) => ActorId::Agent(AgentId::from(agent)),
43 Actor::Group(group) => ActorId::Group(GroupId::from(group)),
44 }
45 }
46}
47
48impl From<ActorId> for Actor {
49 fn from(value: ActorId) -> Self {
50 match value {
51 ActorId::Agent(x) => Actor::Agent(Agent::from(x)),
52 ActorId::Group(x) => Actor::Group(Group::from(x)),
53 }
54 }
55}
56
57impl Actor {
58 pub fn from_json_obj(map: Map<String, Value>) -> Result<Self, DataError> {
60 match map.get("objectType") {
61 Some(x) => {
62 if x == &serde_json::json!("Agent") {
63 Ok(Actor::Agent(Agent::from_json_obj(map)?))
64 } else if x == &serde_json::json!("Group") {
65 Ok(Actor::Group(Group::from_json_obj(map)?))
66 } else {
67 emit_error!(DataError::Validation(ValidationError::ConstraintViolation(
68 format!("Unknown objectType ({x})").into()
69 )))
70 }
71 }
72 None => {
73 debug!("Missing 'objectType'. Assume Agent + continue...");
74 Ok(Actor::Agent(Agent::from_json_obj(map)?))
75 }
76 }
77 }
78
79 pub fn from_agent(actor: Agent) -> Self {
81 Actor::Agent(actor)
82 }
83
84 pub fn from_group(actor: Group) -> Self {
86 Actor::Group(actor)
87 }
88
89 pub fn is_agent(&self) -> bool {
91 matches!(self, Actor::Agent(_))
92 }
93
94 pub fn is_group(&self) -> bool {
96 matches!(self, Actor::Group(_))
97 }
98
99 pub fn as_agent(&self) -> Result<Agent, DataError> {
102 match self {
103 Actor::Agent(x) => Ok(x.to_owned()),
104 _ => emit_error!(DataError::Validation(ValidationError::ConstraintViolation(
105 format!("This ({self}) is NOT an Agent").into()
106 ))),
107 }
108 }
109
110 pub fn as_group(&self) -> Result<Group, DataError> {
113 match self {
114 Actor::Group(x) => Ok(x.to_owned()),
115 _ => emit_error!(DataError::Validation(ValidationError::ConstraintViolation(
116 format!("This ({self}) is NOT a Group").into()
117 ))),
118 }
119 }
120
121 pub fn name(&self) -> Option<&CIString> {
125 match self {
126 Actor::Agent(x) => x.name(),
127 Actor::Group(x) => x.name(),
128 }
129 }
130
131 pub fn name_as_str(&self) -> Option<&str> {
133 match self {
134 Actor::Agent(x) => x.name_as_str(),
135 Actor::Group(x) => x.name_as_str(),
136 }
137 }
138
139 pub fn mbox(&self) -> Option<&MyEmailAddress> {
141 match self {
142 Actor::Agent(x) => x.mbox(),
143 Actor::Group(x) => x.mbox(),
144 }
145 }
146
147 pub fn mbox_sha1sum(&self) -> Option<&str> {
150 match self {
151 Actor::Agent(x) => x.mbox_sha1sum(),
152 Actor::Group(x) => x.mbox_sha1sum(),
153 }
154 }
155
156 pub fn openid(&self) -> Option<&UriStr> {
159 match self {
160 Actor::Agent(x) => x.openid(),
161 Actor::Group(x) => x.openid(),
162 }
163 }
164
165 pub fn account(&self) -> Option<&Account> {
168 match self {
169 Actor::Agent(x) => x.account(),
170 Actor::Group(x) => x.account(),
171 }
172 }
173
174 pub fn uid(&self) -> u64 {
176 fingerprint_it(self)
177 }
178
179 pub fn equivalent(&self, that: &Actor) -> bool {
181 self.uid() == that.uid()
182 }
183}
184
185impl<'de> Deserialize<'de> for Actor {
186 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
187 where
188 D: serde::Deserializer<'de>,
189 {
190 let val = serde_json::Value::deserialize(deserializer)?;
191 match Map::deserialize(val.clone()) {
192 Ok(x) => {
193 if x.contains_key("objectType") {
194 if let Ok(x) = Agent::deserialize(val.clone())
195 && x.check_object_type()
196 {
197 return Ok(Actor::Agent(x));
198 }
199 match Group::deserialize(val) {
200 Ok(x) => Ok(Actor::Group(x)),
201 _ => Err(D::Error::unknown_variant("actor", &["Agent", "Group"])),
202 }
203 } else {
204 match Agent::deserialize(val.clone()) {
207 Ok(x) => Ok(Actor::Agent(x)),
208 _ => {
209 error!("Alleged Actor has no 'objectType' and is NOT an Agent");
210 Err(D::Error::unknown_field("actor", &["Agent", "Group"]))
211 }
212 }
213 }
214 }
215 Err(x) => {
216 error!("Failed deserializing '{}' as Actor: {}", val, x);
217 Err(de::Error::unknown_field("actor", &["Agent", "Group"]))
218 }
219 }
220 }
221}
222
223impl fmt::Display for Actor {
224 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
225 match self {
226 Actor::Agent(x) => write!(f, "{x}"),
227 Actor::Group(x) => write!(f, "{x}"),
228 }
229 }
230}
231
232impl Fingerprint for Actor {
233 fn fingerprint<H: Hasher>(&self, state: &mut H) {
234 match self {
235 Actor::Agent(x) => x.fingerprint(state),
236 Actor::Group(x) => x.fingerprint(state),
237 }
238 }
239}
240
241impl Validate for Actor {
242 fn validate(&self) -> Vec<ValidationError> {
243 match self {
244 Actor::Agent(x) => x.validate(),
245 Actor::Group(x) => x.validate(),
246 }
247 }
248}
249
250impl FromStr for Actor {
251 type Err = DataError;
252
253 fn from_str(s: &str) -> Result<Self, Self::Err> {
254 let map = serde_json::from_str::<Map<String, Value>>(s)?;
255 Self::from_json_obj(map)
256 }
257}
258
259#[cfg(test)]
260mod tests {
261 use super::*;
262 use tracing_test::traced_test;
263
264 #[test]
265 fn test_serde_actor_agent() -> Result<(), DataError> {
266 const JSON: &str =
267 r#"{"objectType":"Agent","name":"Z User","mbox":"mailto:zuser@somewhere.net"}"#;
268 let a1 = Agent::builder()
269 .with_object_type()
270 .name("Z User")?
271 .mbox("zuser@somewhere.net")?
272 .build()?;
273 let actor = Actor::Agent(a1);
274 let se_result = serde_json::to_string(&actor);
275 assert!(se_result.is_ok());
276 let json = se_result.unwrap();
277 assert_eq!(json, JSON);
278
279 let de_result = serde_json::from_str::<Actor>(JSON);
280 assert!(de_result.is_ok());
281 if let Ok(Actor::Agent(a2)) = de_result {
282 assert_eq!(a2.name().unwrap(), "Z User");
283 }
284
285 Ok(())
286 }
287
288 #[test]
289 fn test_de_actor_agent() {
290 const JSON: &str = r#"{
291 "objectType":"Agent",
292 "name":"Z User",
293 "mbox":"mailto:zuser@somewhere.net"
294 }"#;
295
296 let de_result = serde_json::from_str::<Actor>(JSON);
297 assert!(de_result.is_ok());
298 }
299
300 #[traced_test]
301 #[test]
302 fn test_actor_bad() {
303 const IN1: &str = r#"{ "objectType": "Foo", "foo": 42 }"#;
304 const IN2: &str = r#"{ "foo": 42 }"#;
305
306 let r1 = serde_json::from_str::<Actor>(IN1);
307 assert!(r1.is_err()); assert!(r1.err().unwrap().is_data());
309
310 let r2 = serde_json::from_str::<Actor>(IN2);
311 assert!(r2.is_err()); assert!(r2.err().unwrap().is_data());
313 }
314}