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