arminius_lib_model/
event.rs1use arminius_lib_db::{DatabaseError, ResultExt as _};
8use arminius_lib_events::{
9 KnownRoomVersionId, PartsVerified, RoomEvent, VerificationMetadata, Verified,
10};
11use ruma::{Int, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, UInt};
12use sqlx::types::chrono::{DateTime, Utc};
13
14pub type EventJson = String;
18
19#[derive(Debug, Clone)]
21pub struct EventRow {
22 pub event_id: OwnedEventId,
24 pub room_id: OwnedRoomId,
26 pub depth: i64,
28 pub event_json: EventJson,
30 pub received_ts: i64,
32}
33
34impl EventRow {
35 #[must_use]
39 pub fn to_value(&self) -> serde_json::Value {
40 serde_json::from_str(&self.event_json).unwrap_or(serde_json::Value::Null)
41 }
42}
43
44#[derive(Debug)]
46pub struct EventVerifiedRow {
47 pub event_json: Box<sqlx::types::JsonRawValue>,
49 pub room_version: String,
52 pub attempted_at: DateTime<Utc>,
54 pub signature_verification: DbPartsVerified,
56 pub soft_failed: bool,
58}
59
60impl EventVerifiedRow {
61 pub fn try_into_event(self) -> Result<RoomEvent<Verified>, DatabaseError> {
63 let metadata = VerificationMetadata {
64 attempted_at: MilliSecondsSinceUnixEpoch(
65 UInt::try_from(self.attempted_at.timestamp_millis())
66 .invalid_data("Unrepresentable timestamp")?,
67 ),
68 signature_verification: self.signature_verification.into(),
69 room_version: self.room_version.parse().invalid_data("Unknown room version")?,
70 soft_failed: self.soft_failed,
71 };
72 let verified = RoomEvent::verified_from_pdu(&self.event_json, metadata)
73 .invalid_data("Could not load event from database")?;
74 Ok(verified)
75 }
76}
77
78#[derive(Debug, sqlx::Type, Eq, PartialEq, Clone, Copy)]
81#[sqlx(type_name = "PARTS_VERIFIED", rename_all = "snake_case")]
82pub enum DbPartsVerified {
83 CompleteEvent,
86 OnlySignatures,
89}
90
91impl From<PartsVerified> for DbPartsVerified {
92 fn from(value: PartsVerified) -> Self {
93 match value {
94 PartsVerified::CompleteEvent => DbPartsVerified::CompleteEvent,
95 PartsVerified::OnlySignatures => DbPartsVerified::OnlySignatures,
96 }
97 }
98}
99
100impl From<DbPartsVerified> for PartsVerified {
101 fn from(value: DbPartsVerified) -> Self {
102 match value {
103 DbPartsVerified::CompleteEvent => PartsVerified::CompleteEvent,
104 DbPartsVerified::OnlySignatures => PartsVerified::OnlySignatures,
105 }
106 }
107}
108
109#[derive(Debug, Clone)]
111pub struct DbVerificationMetadata {
112 pub attempted_at: DateTime<Utc>,
114 pub signature_verification: DbPartsVerified,
116 pub soft_failed: bool,
118}
119
120impl DbVerificationMetadata {
121 pub fn try_into_domain(
123 self,
124 room_version: KnownRoomVersionId,
125 ) -> Result<VerificationMetadata, DatabaseError> {
126 Ok(VerificationMetadata {
127 attempted_at: MilliSecondsSinceUnixEpoch(
128 UInt::try_from(self.attempted_at.timestamp_millis())
129 .invalid_data("Unrepresentable timestamp")?,
130 ),
131 signature_verification: self.signature_verification.into(),
132 room_version,
133 soft_failed: self.soft_failed,
134 })
135 }
136}
137
138impl TryFrom<VerificationMetadata> for DbVerificationMetadata {
139 type Error = DatabaseError;
140
141 fn try_from(from: VerificationMetadata) -> Result<DbVerificationMetadata, DatabaseError> {
142 Ok(DbVerificationMetadata {
143 attempted_at: DateTime::from_timestamp_millis(i64::from(Int::from(
144 from.attempted_at.get(),
145 )))
146 .ok_or(DatabaseError::InvalidData("Unrepresentable timestamp".to_owned()))?,
147 signature_verification: from.signature_verification.into(),
148 soft_failed: from.soft_failed,
149 })
150 }
151}