summaryrefslogtreecommitdiff
path: root/src/client.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/client.rs')
-rw-r--r--src/client.rs54
1 files changed, 43 insertions, 11 deletions
diff --git a/src/client.rs b/src/client.rs
index b58f89c..5b13cb7 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -1,6 +1,8 @@
//! Client to the Obnam server HTTP API.
-use crate::chunk::{DataChunk, GenerationChunk, GenerationChunkError};
+use crate::chunk::{
+ ClientTrust, ClientTrustError, DataChunk, GenerationChunk, GenerationChunkError,
+};
use crate::chunkid::ChunkId;
use crate::chunkmeta::ChunkMeta;
use crate::cipher::{CipherEngine, CipherError};
@@ -54,6 +56,10 @@ pub enum ClientError {
#[error(transparent)]
GenerationChunkError(#[from] GenerationChunkError),
+ /// An error regarding client trust.
+ #[error(transparent)]
+ ClientTrust(#[from] ClientTrustError),
+
/// An error using a backup's local metadata.
#[error(transparent)]
LocalGenerationError(#[from] LocalGenerationError),
@@ -147,7 +153,7 @@ impl BackupClient {
Ok(has)
}
- /// Upload a data chunk to the srver.
+ /// Upload a data chunk to the server.
pub async fn upload_chunk(&self, chunk: DataChunk) -> Result<ChunkId, ClientError> {
let enc = self.cipher.encrypt_chunk(&chunk)?;
let res = self
@@ -170,18 +176,44 @@ impl BackupClient {
Ok(chunk_id)
}
- /// List backup generations known by the server.
- pub async fn list_generations(&self) -> Result<GenerationList, ClientError> {
- let (_, body) = self.get("", &[("generation", "true")]).await?;
+ /// Get current client trust chunk from repository, if there is one.
+ pub async fn get_client_trust(&self) -> Result<Option<ClientTrust>, ClientError> {
+ let ids = self.find_client_trusts().await?;
+ let mut latest: Option<ClientTrust> = None;
+ for id in ids {
+ let chunk = self.fetch_chunk(&id).await?;
+ let new = ClientTrust::from_data_chunk(&chunk)?;
+ if let Some(t) = &latest {
+ if new.timestamp() > t.timestamp() {
+ latest = Some(new);
+ }
+ } else {
+ latest = Some(new);
+ }
+ }
+ Ok(latest)
+ }
+
+ async fn find_client_trusts(&self) -> Result<Vec<ChunkId>, ClientError> {
+ let body = match self.get("", &[("label", "client-trust")]).await {
+ Ok((_, body)) => body,
+ Err(err) => return Err(err),
+ };
- let map: HashMap<String, ChunkMeta> =
- serde_yaml::from_slice(&body).map_err(ClientError::YamlParse)?;
- debug!("list_generations: map={:?}", map);
- let finished = map
+ let hits: HashMap<String, ChunkMeta> =
+ serde_json::from_slice(&body).map_err(ClientError::JsonParse)?;
+ let ids = hits.iter().map(|(id, _)| id.into()).collect();
+ Ok(ids)
+ }
+
+ /// List backup generations known by the server.
+ pub fn list_generations(&self, trust: &ClientTrust) -> GenerationList {
+ let finished = trust
+ .backups()
.iter()
- .map(|(id, meta)| FinishedGeneration::new(id, meta.ended().map_or("", |s| s)))
+ .map(|id| FinishedGeneration::new(&format!("{}", id), ""))
.collect();
- Ok(GenerationList::new(finished))
+ GenerationList::new(finished)
}
/// Fetch a data chunk from the server, given the chunk identifier.