pass_it_on/
notifications.rs1use crate::{Error, KEY_CONTEXT};
4use blake3::Hash;
5use serde::{Deserialize, Serialize};
6use serde_json::StreamDeserializer;
7use std::collections::HashSet;
8use std::time::{SystemTime, UNIX_EPOCH};
9
10#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Hash, Clone)]
12pub struct Message {
13 text: String,
14 time: u128,
15}
16
17#[derive(Debug, PartialEq, Eq, Hash, Clone)]
19pub struct ClientReadyMessage {
20 message: Message,
21 notification_name: String,
22}
23
24#[derive(Debug, PartialEq, Eq, Hash, Clone)]
26pub struct ValidatedNotification {
27 message: Message,
28 sub_name: String,
29}
30
31#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Hash, Clone)]
33pub struct Notification {
34 message: Message,
35 key: String,
36}
37
38#[derive(Debug, PartialEq, Eq, Hash, Clone)]
43pub struct Key {
44 hash: Hash,
45}
46
47impl Notification {
48 pub fn new(message: Message, notification_key: &Key) -> Notification {
50 let key = message.create_key(notification_key).to_hex();
51 Notification { message, key }
52 }
53
54 pub fn from_json<S: AsRef<str>>(input: S) -> Result<Notification, Error> {
56 Ok(serde_json::from_str(input.as_ref())?)
57 }
58
59 pub fn from_json_multi<S: AsRef<str>>(input: S) -> Vec<Result<Notification, Error>> {
61 let mut notifications = Vec::new();
62 let stream: StreamDeserializer<_, Notification> =
63 serde_json::Deserializer::from_str(input.as_ref()).into_iter();
64
65 for item in stream {
66 match item {
67 Err(e) => notifications.push(Err(Error::SerdeJsonError(e))),
68 Ok(n) => notifications.push(Ok(n)),
69 };
70 }
71 notifications
72 }
73
74 pub fn to_json(&self) -> Result<String, Error> {
76 Ok(serde_json::to_string(self)?)
77 }
78
79 pub(crate) fn validate(&self, hash_key: &Key) -> bool {
81 let new_key = self.message.create_key(hash_key);
82 self.key == new_key.to_hex()
83 }
84
85 pub(crate) fn validate_set(&self, hash_keys: &HashSet<Key>) -> bool {
87 for hash_key in hash_keys {
88 match self.validate(hash_key) {
89 true => return true,
90 false => (),
91 }
92 }
93 false
94 }
95
96 pub fn message(&self) -> Message {
98 self.message.clone()
99 }
100
101 pub fn key(&self) -> &str {
103 &self.key
104 }
105}
106
107impl Message {
108 pub fn new<S: AsRef<str>>(text: S) -> Message {
110 let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_nanos();
111 let body = String::from(text.as_ref());
112 Self { text: body, time }
113 }
114
115 pub fn text(&self) -> &str {
117 &self.text
118 }
119
120 pub fn time(&self) -> u128 {
122 self.time
123 }
124
125 fn create_key(&self, notification_key: &Key) -> Key {
127 let hash_string = format!("{}{}", self.text, self.time);
128 Key::generate(hash_string.as_str(), notification_key)
129 }
130
131 pub fn to_client_ready_message<S: AsRef<str>>(self, notification_name: S) -> ClientReadyMessage {
133 ClientReadyMessage::new(notification_name, self)
134 }
135}
136
137impl ClientReadyMessage {
138 pub(crate) fn new<S: AsRef<str>>(notification_name: S, message: Message) -> Self {
140 Self { notification_name: notification_name.as_ref().into(), message }
141 }
142
143 pub fn to_notification(self, client_key: &Key) -> Notification {
145 let key = Key::generate(self.notification_name(), client_key);
146 let message = self.message;
147 Notification::new(message, &key)
148 }
149
150 pub fn message(&self) -> &Message {
152 &self.message
153 }
154
155 pub fn notification_name(&self) -> &str {
157 &self.notification_name
158 }
159}
160
161impl ValidatedNotification {
162 pub fn new<S: AsRef<str>>(name_id: S, message: Message) -> ValidatedNotification {
164 Self { sub_name: name_id.as_ref().into(), message }
165 }
166
167 pub fn message(&self) -> &Message {
169 &self.message
170 }
171
172 pub fn sub_name(&self) -> &str {
174 &self.sub_name
175 }
176}
177
178impl Key {
179 pub fn generate<S: AsRef<str>>(name: S, hash_key: &Key) -> Key {
181 let mut hasher = blake3::Hasher::new_keyed(hash_key.as_bytes());
182 hasher.update(name.as_ref().as_bytes());
183 Self { hash: hasher.finalize() }
184 }
185
186 pub fn derive_shared_key<S: AsRef<str>>(key_string: S) -> Key {
188 Self::from_bytes(&blake3::derive_key(KEY_CONTEXT, key_string.as_ref().as_bytes()))
189 }
190
191 pub fn from_bytes(key: &[u8; 32]) -> Key {
193 let hash = Hash::from(*key);
194 Self { hash }
195 }
196
197 pub fn from_hex<S: AsRef<str>>(key: S) -> Key {
199 let hash = Hash::from_hex(key.as_ref()).expect("Unable to create Key from hex");
200 Self { hash }
201 }
202
203 pub fn to_hex(&self) -> String {
205 self.hash.to_hex().to_string()
206 }
207
208 pub fn as_bytes(&self) -> &[u8; 32] {
210 self.hash.as_bytes()
211 }
212}