From 570a7e94d0f71287e4960c5306e07ce4cd85d125 Mon Sep 17 00:00:00 2001 From: Phoebe Goldman Date: Mon, 17 Jul 2023 10:03:00 -0400 Subject: [PATCH 1/2] [SDK] Functions for saving and loading `Credentials` to/from disk --- Cargo.lock | 10 ++++++++ crates/sdk/Cargo.toml | 1 + crates/sdk/src/identity.rs | 47 +++++++++++++++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 0a3903b86a..4a07f7b04b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1753,6 +1753,15 @@ dependencies = [ "digest", ] +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "hostname" version = "0.3.1" @@ -4137,6 +4146,7 @@ dependencies = [ "base64 0.21.2", "futures", "futures-channel", + "home", "http", "im", "log", diff --git a/crates/sdk/Cargo.toml b/crates/sdk/Cargo.toml index c7f03d6ba1..d137434727 100644 --- a/crates/sdk/Cargo.toml +++ b/crates/sdk/Cargo.toml @@ -22,3 +22,4 @@ futures-channel = "0.3" anymap = "0.12" im = "15.1" base64 = "0.21" +home = "0.5" diff --git a/crates/sdk/src/identity.rs b/crates/sdk/src/identity.rs index 21a68cf8f4..7577063ef9 100644 --- a/crates/sdk/src/identity.rs +++ b/crates/sdk/src/identity.rs @@ -1,6 +1,7 @@ use crate::callbacks::CallbackId; use crate::global_connection::try_with_credential_store; -use anyhow::{anyhow, Result}; +use crate::sats::bsatn; +use anyhow::{anyhow, Context, Result}; use spacetimedb_lib::de::Deserialize; use spacetimedb_lib::ser::Serialize; // TODO: impl ser/de for `Identity`, `Token`, `Credentials` so that clients can stash them @@ -167,3 +168,47 @@ pub fn credentials() -> Result { try_with_credential_store(|cred_store| cred_store.credentials().ok_or(anyhow!("Credentials not yet received"))) .and_then(|inner| inner) } + +const CREDS_FILE: &str = "credentials"; + +/// Load a saved `Credentials` from a file within `~/dirname`, if one exists. +/// +/// `dirname` is treated as a directory in the user's home directory. +/// If it contains a file named `credentials`, +/// that file is treated as a BSATN-encoded `Credentials`, deserialized and returned. +/// +/// Returns `Ok(None)` if the directory or the credentials file does not exist. +/// Returns `Err` when IO or deserialization fails. +pub fn load_credentials(dirname: &str) -> Result> { + let mut path = home::home_dir().with_context(|| "Determining user home directory to compute credentials path")?; + path.push(dirname); + path.push(CREDS_FILE); + + match std::fs::read(&path) { + Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(None), + Err(e) => Err(e).with_context(|| "Reading BSATN-encoded credentials from file")?, + Ok(file_contents) => bsatn::from_slice::(&file_contents) + .with_context(|| "Deserializing credentials") + .map(Some), + } +} + +/// Stores a `Credentials` to a file within `~/dirname`, to be later loaded with [`load_credentials`]. +/// +/// `dirname` is treated as a directory in the user's home directory. +/// The directory is created if it does not already exists. +/// A file within it named `credentials` is created or replaced, +/// containing `creds` encoded as BSATN. +/// +/// Returns `Err` when IO or serialization fails. +pub fn save_credentials(dirname: &str, creds: &Credentials) -> Result<()> { + let creds_bytes = bsatn::to_vec(creds).with_context(|| "Serializing credentials")?; + + let mut path = home::home_dir().with_context(|| "Determining user home directory to compute credentials path")?; + path.push(dirname); + + std::fs::create_dir_all(&path).with_context(|| "Creating credentials directory")?; + + path.push(CREDS_FILE); + std::fs::write(&path, creds_bytes).with_context(|| "Writing credentials to file") +} From cb5ad1269fb0b597d3d02090e7c9d5bb0bb37de3 Mon Sep 17 00:00:00 2001 From: Boppy Date: Mon, 17 Jul 2023 14:51:38 -0500 Subject: [PATCH 2/2] Added import --- crates/sdk/src/identity.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/sdk/src/identity.rs b/crates/sdk/src/identity.rs index b16529214d..fe000639c3 100644 --- a/crates/sdk/src/identity.rs +++ b/crates/sdk/src/identity.rs @@ -3,6 +3,7 @@ use crate::global_connection::with_credential_store; use anyhow::{anyhow, Context, Result}; use spacetimedb_lib::de::Deserialize; use spacetimedb_lib::ser::Serialize; +use spacetimedb_sats::bsatn; // TODO: impl ser/de for `Identity`, `Token`, `Credentials` so that clients can stash them // to disk and use them to re-connect.