1use std::borrow::Borrow;
4use std::marker::PhantomData;
5use std::str::FromStr;
6
7use p2panda_auth::group::GroupCrdtState;
8use p2panda_auth::traits::{Conditions, Operation as AuthOperation};
9use p2panda_core::cbor::{decode_cbor, encode_cbor};
10use p2panda_core::{Extensions, Hash, Operation, VerifyingKey};
11use p2panda_encryption::key_manager::PreKeyBundlesState;
12use p2panda_encryption::key_registry::KeyRegistryState;
13use serde::{Deserialize, Serialize};
14use sqlx::{query, query_as};
15
16use crate::groups::GroupsStore;
17use crate::key_registry::KeyRegistryStore;
18use crate::key_secrets::KeySecretsStore;
19use crate::operations::OperationStore;
20use crate::spaces::traits::SpacesMessageStore;
21use crate::spaces::{SpacesMessage, SpacesStore};
22use crate::sqlite::TransactionPermit;
23use crate::{SqliteError, SqliteStore};
24
25#[derive(Clone)]
26pub struct SqliteSpacesStore<E> {
27 store: SqliteStore,
28 _phantom: PhantomData<E>,
29}
30
31impl<E> SqliteSpacesStore<E> {
32 pub fn new(store: SqliteStore) -> Self {
33 Self {
34 store,
35 _phantom: PhantomData,
36 }
37 }
38}
39
40impl<ARG, E> SpacesMessageStore<ARG> for SqliteSpacesStore<E>
41where
42 ARG: Clone,
43 E: Extensions + Borrow<ARG>,
44{
45 type Error = SqliteError;
46
47 async fn get_spaces_message(
48 &self,
49 id: &Hash,
50 ) -> Result<Option<SpacesMessage<ARG>>, Self::Error> {
51 match <SqliteStore as OperationStore<Operation<E>, Hash>>::get_operation(&self.store, id)
52 .await?
53 {
54 Some(operation) => {
55 let args = operation.header().extensions.borrow().clone();
56 let message = SpacesMessage {
57 id: operation.hash,
58 author: operation.header().verifying_key,
59 args,
60 };
61 Ok(Some(message))
62 }
63 None => Ok(None),
64 }
65 }
66}
67
68impl<S, E> SpacesStore<S> for SqliteSpacesStore<E>
69where
70 S: for<'a> Deserialize<'a> + Serialize,
71{
72 type Error = SqliteError;
73
74 async fn get_space_state_tx(&self, id: &Hash) -> Result<Option<S>, Self::Error> {
75 let row = self
76 .store
77 .tx(async |tx| {
78 query_as::<_, (Vec<u8>,)>(
79 "
80 SELECT
81 state
82 FROM
83 spaces_v1
84 WHERE
85 id = ?
86 ",
87 )
88 .bind(id.to_hex())
89 .fetch_optional(&mut **tx)
90 .await
91 .map_err(SqliteError::Sqlite)
92 })
93 .await?;
94
95 let Some((state_bytes,)) = row else {
96 return Ok(None);
97 };
98
99 let state = decode_cbor(&state_bytes[..])
100 .map_err(|err| SqliteError::Decode("state".into(), err.into()))?;
101
102 Ok(Some(state))
103 }
104
105 async fn set_space_state_tx(&self, id: &Hash, state: &S) -> Result<(), Self::Error> {
106 self.store
107 .tx(async |tx| {
108 query(
109 "
110 INSERT OR REPLACE
111 INTO
112 spaces_v1 (
113 id,
114 state
115 )
116 VALUES
117 (?, ?)
118 ",
119 )
120 .bind(id.to_hex())
121 .bind(
122 encode_cbor(&state)
123 .map_err(|err| SqliteError::Encode("state".to_string(), err))?,
124 )
125 .execute(&mut **tx)
126 .await
127 .map_err(SqliteError::Sqlite)
128 })
129 .await?;
130
131 Ok(())
132 }
133
134 async fn has_space(&self, id: &Hash) -> Result<bool, Self::Error> {
135 let result = self
136 .store
137 .execute(async |pool| {
138 query_as::<_, (Vec<u8>,)>(
139 "
140 SELECT
141 id
142 FROM
143 spaces_v1
144 WHERE
145 id = ?
146 ",
147 )
148 .bind(id.to_hex())
149 .fetch_optional(pool)
150 .await
151 .map_err(SqliteError::Sqlite)
152 })
153 .await?;
154
155 Ok(result.is_some())
156 }
157
158 async fn space_ids(&self) -> Result<Vec<Hash>, Self::Error> {
159 let result = self
160 .store
161 .execute(async |pool| {
162 query_as::<_, (String,)>(
163 "
164 SELECT
165 id
166 FROM
167 spaces_v1
168 ",
169 )
170 .fetch_all(pool)
171 .await
172 .map_err(SqliteError::Sqlite)
173 })
174 .await?;
175
176 let result: Result<Vec<Hash>, _> = result
177 .iter()
178 .map(|(id_str,)| Hash::from_str(id_str))
179 .collect();
180
181 result.map_err(|err| SqliteError::Decode("state".into(), err.into()))
182 }
183}
184
185impl<E> KeyRegistryStore for SqliteSpacesStore<E> {
186 type Error = SqliteError;
187
188 async fn get_key_registry(
189 &self,
190 ) -> Result<Option<KeyRegistryState<VerifyingKey>>, Self::Error> {
191 self.store.get_key_registry().await
192 }
193
194 async fn set_key_registry(
195 &self,
196 state: &KeyRegistryState<VerifyingKey>,
197 ) -> Result<(), Self::Error> {
198 self.store.set_key_registry(state).await
199 }
200}
201
202impl<E> KeySecretsStore for SqliteSpacesStore<E> {
203 type Error = SqliteError;
204
205 async fn get_prekey_secrets(&self) -> Result<Option<PreKeyBundlesState>, Self::Error> {
206 self.store.get_prekey_secrets().await
207 }
208
209 async fn set_prekey_secrets(&self, state: &PreKeyBundlesState) -> Result<(), Self::Error> {
210 self.store.set_prekey_secrets(state).await
211 }
212}
213
214impl<E, M, C> GroupsStore<M, C> for SqliteSpacesStore<E>
215where
216 C: Conditions + Serialize + for<'a> Deserialize<'a>,
217 M: AuthOperation<VerifyingKey, Hash, C> + Serialize + for<'a> Deserialize<'a>,
218{
219 type Error = SqliteError;
220
221 async fn set_groups_state_tx(
222 &self,
223 id: Hash,
224 state: &GroupCrdtState<VerifyingKey, Hash, M, C>,
225 ) -> Result<(), SqliteError> {
226 self.store.set_groups_state_tx(id, state).await
227 }
228
229 async fn get_groups_state_tx(
230 &self,
231 id: Hash,
232 ) -> Result<Option<GroupCrdtState<VerifyingKey, Hash, M, C>>, SqliteError> {
233 self.store.get_groups_state_tx(id).await
234 }
235}
236
237impl<E> crate::traits::Transaction for SqliteSpacesStore<E> {
238 type Error = SqliteError;
239
240 type Permit = TransactionPermit;
241
242 async fn begin(&self) -> Result<TransactionPermit, SqliteError> {
243 self.store.begin().await
244 }
245
246 async fn rollback(&self, permit: TransactionPermit) -> Result<(), SqliteError> {
247 self.store.rollback(permit).await
248 }
249
250 async fn commit(&self, permit: TransactionPermit) -> Result<(), SqliteError> {
251 self.store.commit(permit).await
252 }
253}