Skip to main content

p2panda_store/key_secrets/
sqlite.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use p2panda_core::cbor::{decode_cbor, encode_cbor};
4use p2panda_encryption::key_manager::PreKeyBundlesState;
5use sqlx::{query, query_scalar};
6
7use crate::key_secrets::traits::KeySecretsStore;
8use crate::{SqliteError, SqliteStore};
9
10// Constant identifier used to provide a primary key for the database table.
11// This makes it possible to use INSERT OR REPLACE to update the prekey secrets state.
12const DEFAULT_PRE_KEY_BUNDLES_STATE: &str = "default";
13
14impl KeySecretsStore for SqliteStore {
15    type Error = SqliteError;
16
17    async fn get_prekey_secrets(&self) -> Result<Option<PreKeyBundlesState>, SqliteError> {
18        let state_bytes: Option<Vec<u8>> = self
19            .execute(async |pool| {
20                query_scalar(
21                    "
22                    SELECT
23                        state
24                    FROM
25                        key_secrets_v1
26                    WHERE
27                        id = ?
28                    ",
29                )
30                .bind(DEFAULT_PRE_KEY_BUNDLES_STATE)
31                .fetch_optional(pool)
32                .await
33                .map_err(SqliteError::Sqlite)
34            })
35            .await?;
36
37        if let Some(bytes) = state_bytes {
38            let state = decode_cbor(&bytes[..])
39                .map_err(|err| SqliteError::Decode("state".into(), err.into()))?;
40
41            Ok(Some(state))
42        } else {
43            Ok(None)
44        }
45    }
46
47    async fn set_prekey_secrets(&self, state: &PreKeyBundlesState) -> Result<(), SqliteError> {
48        self.tx(async |tx| {
49            query(
50                "
51                INSERT OR REPLACE
52                    INTO
53                        key_secrets_v1(id, state)
54                    VALUES
55                        (?, ?)
56                ",
57            )
58            .bind(DEFAULT_PRE_KEY_BUNDLES_STATE)
59            .bind(encode_cbor(&state).map_err(|err| SqliteError::Encode("state".to_string(), err))?)
60            .execute(&mut **tx)
61            .await
62            .map_err(SqliteError::Sqlite)
63        })
64        .await?;
65
66        Ok(())
67    }
68}