diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2019-05-24 14:01:28 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-05-24 16:20:49 +0200 |
commit | e97befc021e3e66b554cdd698a37ca80d9d88e44 (patch) | |
tree | 8b6dd1ca81d956a5b3f5900af65f62a0e9fa7b8f | |
parent | 6502a9ef8e4d2247f5149efcd72f5ba10332ffe5 (diff) |
store-rusqlite: Provide wrapper for TPK.
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | store-rusqlite/Cargo.toml | 1 | ||||
-rw-r--r-- | store-rusqlite/src/lib.rs | 47 | ||||
-rw-r--r-- | store/src/backend/mod.rs | 37 |
4 files changed, 66 insertions, 20 deletions
@@ -1684,6 +1684,7 @@ name = "sequoia-store-rusqlite" version = "0.7.0" dependencies = [ "rusqlite 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sequoia-openpgp 0.7.0", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/store-rusqlite/Cargo.toml b/store-rusqlite/Cargo.toml index 0d52c5fd..2f214c3e 100644 --- a/store-rusqlite/Cargo.toml +++ b/store-rusqlite/Cargo.toml @@ -21,5 +21,6 @@ default = ["background-services"] background-services = [] [dependencies] +sequoia-openpgp = { path = "../openpgp", version = "0.7" } rusqlite = "0.14" time = "0.1.38" diff --git a/store-rusqlite/src/lib.rs b/store-rusqlite/src/lib.rs index c260e364..39b3a50b 100644 --- a/store-rusqlite/src/lib.rs +++ b/store-rusqlite/src/lib.rs @@ -1,5 +1,8 @@ //! Data types for working with `rusqlite`. +extern crate sequoia_openpgp as openpgp; +use openpgp::{parse::Parse, serialize::Serialize}; + extern crate rusqlite; use rusqlite::types::{ToSql, ToSqlOutput, FromSql, FromSqlResult, ValueRef}; use std::fmt; @@ -94,3 +97,47 @@ impl Sub<Timestamp> for Timestamp { self.0 - other.0 } } + +/// Represents a TPK. +#[derive(Clone, PartialEq)] +pub struct TPK(openpgp::TPK); + +impl fmt::Display for TPK { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl From<openpgp::TPK> for TPK { + fn from(tpk: openpgp::TPK) -> Self { + TPK(tpk) + } +} + +impl From<TPK> for openpgp::TPK { + fn from(tpk: TPK) -> Self { + tpk.0 + } +} + +impl ToSql for TPK { + fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { + use rusqlite::Error; + + let mut buf = Vec::new(); + self.0.serialize(&mut buf) + .map_err(|e| Error::ToSqlConversionFailure(Box::new(e.compat())))?; + + Ok(buf.into()) + } +} + +impl FromSql for TPK { + fn column_result(value: ValueRef) -> FromSqlResult<Self> { + use rusqlite::types::FromSqlError; + + Ok(openpgp::TPK::from_bytes(value.as_blob()?) + .map_err(|e| FromSqlError::Other(Box::new(e.compat())))? + .into()) + } +} diff --git a/store/src/backend/mod.rs b/store/src/backend/mod.rs index d04ac296..4ee445cd 100644 --- a/store/src/backend/mod.rs +++ b/store/src/backend/mod.rs @@ -547,23 +547,20 @@ impl node::binding::Server for BindingServer { // Check in the database for the current key. let key_id = sry!(self.key_id()); - let (fingerprint, key): (String, Option<Vec<u8>>) + let (fingerprint, current): (String, Option<TPK>) = sry!(self.c.query_row( "SELECT fingerprint, key FROM keys WHERE id = ?1", &[&key_id], - |row| (row.get(0), row.get_checked(1).ok()))); + |row| (row.get(0), row.get_checked::<_, store_rusqlite::TPK>(1) + .map(|t| TPK::from(t)).ok()))); - // If we found one, convert it to TPK. - let current = if let Some(current) = key { - let current = sry!(TPK::from_bytes(¤t)); + // If we found one, check consistency. + if let Some(current) = current.as_ref() { if current.fingerprint().to_hex() != fingerprint { // Inconsistent database. fail!(node::Error::SystemError); } - Some(current) - } else { - None - }; + } // Check for conflicts. if new.fingerprint().to_hex() != fingerprint { @@ -754,20 +751,19 @@ impl KeyServer { /// Merges other into this key updating the database. /// /// Returnes the merged key as blob. - fn merge(&self, other: TPK) -> Result<Vec<u8>> { + fn merge(&self, other: TPK) -> Result<TPK> { let mut new = other; // Get the current key from the database. - let (fingerprint, key): (String, Option<Vec<u8>>) + let (fingerprint, key): (String, Option<TPK>) = self.c.query_row( "SELECT fingerprint, key FROM keys WHERE id = ?1", &[&self.id], - |row| (row.get(0), row.get_checked(1).ok()))?; + |row| (row.get(0), row.get_checked::<_, store_rusqlite::TPK>(1) + .map(|t| t.into()).ok()))?; // If there was a key stored there, merge it. if let Some(current) = key { - let current = TPK::from_bytes(¤t)?; - if current.fingerprint().to_hex() != fingerprint { // Inconsistent database. return Err(node::Error::SystemError.into()); @@ -781,14 +777,13 @@ impl KeyServer { } // Write key back to the database. - let mut blob = vec![]; - new.serialize(&mut blob)?; - + let new = store_rusqlite::TPK::from(new); self.c.execute("UPDATE keys SET key = ?1 WHERE id = ?2", - &[&blob, &self.id])?; + &[&new, &self.id])?; + let new = new.into(); KeyServer::reindex_subkeys(&self.c, self.id, &new)?; - Ok(blob) + Ok(new) } /// Keeps the mapping of (sub)KeyIDs to keys up-to-date. @@ -1030,7 +1025,9 @@ impl node::key::Server for KeyServer { -> Promise<(), capnp::Error> { bind_results!(results); let new = sry!(TPK::from_bytes(&pry!(pry!(params.get()).get_key()))); - let blob = sry!(self.merge(new)); + let tpk = sry!(self.merge(new)); + let mut blob = Vec::new(); + sry!(tpk.serialize(&mut blob)); pry!(pry!(results.get().get_result()).set_ok(&blob[..])); Promise::ok(()) } |