Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove spacetimedb-core as a dep of cli #2244

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[workspace]
members = [
"crates/auth",
"crates/bench",
"crates/bindings-sys",
"crates/bindings",
Expand Down Expand Up @@ -93,6 +94,7 @@ rust-version = "1.84.0"

[workspace.dependencies]
spacetimedb = { path = "crates/bindings", version = "1.0.0" }
spacetimedb-auth = { path = "crates/auth", version = "1.0.0" }
spacetimedb-bindings-macro = { path = "crates/bindings-macro", version = "1.0.0" }
spacetimedb-bindings-sys = { path = "crates/bindings-sys", version = "1.0.0" }
spacetimedb-cli = { path = "crates/cli", version = "1.0.0" }
Expand Down Expand Up @@ -186,6 +188,7 @@ itertools = "0.12"
itoa = "1"
jsonwebtoken = { package = "spacetimedb-jsonwebtoken", version = "9.3.0" }
junction = "1"
jwks = { package = "spacetimedb-jwks", version = "0.1.3" }
lazy_static = "1.4.0"
log = "0.4.17"
memchr = "2"
Expand Down
13 changes: 13 additions & 0 deletions crates/auth/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "spacetimedb-auth"
version.workspace = true
edition.workspace = true
rust-version.workspace = true

[dependencies]
spacetimedb-lib.workspace = true

anyhow.workspace = true
serde.workspace = true
serde_with.workspace = true
jsonwebtoken.workspace = true
28 changes: 10 additions & 18 deletions crates/core/src/auth/identity.rs → crates/auth/src/identity.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use crate::identity::Identity;
pub use jsonwebtoken::errors::Error as JwtError;
pub use jsonwebtoken::errors::ErrorKind as JwtErrorKind;
pub use jsonwebtoken::{DecodingKey, EncodingKey};
use serde::{Deserialize, Serialize};
use spacetimedb_lib::Identity;
use std::time::SystemTime;

use super::token_validation::TokenValidationError;

// These are the claims that can be attached to a request/connection.
#[serde_with::serde_as]
#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -49,39 +47,33 @@ pub struct IncomingClaims {
}

impl TryInto<SpacetimeIdentityClaims> for IncomingClaims {
type Error = TokenValidationError;
type Error = anyhow::Error;

fn try_into(self) -> Result<SpacetimeIdentityClaims, TokenValidationError> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was removed the TokenValidationError?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method never actually returned anything other than its Other(anyhow::Error) variant, so it's easier to just return anyhow::Error.

fn try_into(self) -> anyhow::Result<SpacetimeIdentityClaims> {
// The issuer and subject must be less than 128 bytes.
if self.issuer.len() > 128 {
return Err(TokenValidationError::Other(anyhow::anyhow!(
"Issuer too long: {:?}",
self.issuer
)));
return Err(anyhow::anyhow!("Issuer too long: {:?}", self.issuer));
}
if self.subject.len() > 128 {
return Err(TokenValidationError::Other(anyhow::anyhow!(
"Subject too long: {:?}",
self.subject
)));
return Err(anyhow::anyhow!("Subject too long: {:?}", self.subject));
}
// The issuer and subject must be non-empty.
if self.issuer.is_empty() {
return Err(TokenValidationError::Other(anyhow::anyhow!("Issuer empty")));
return Err(anyhow::anyhow!("Issuer empty"));
}
if self.subject.is_empty() {
return Err(TokenValidationError::Other(anyhow::anyhow!("Subject empty")));
return Err(anyhow::anyhow!("Subject empty"));
}

let computed_identity = Identity::from_claims(&self.issuer, &self.subject);
// If an identity is provided, it must match the computed identity.
if let Some(token_identity) = self.identity {
if token_identity != computed_identity {
return Err(TokenValidationError::Other(anyhow::anyhow!(
return Err(anyhow::anyhow!(
"Identity mismatch: token identity {:?} does not match computed identity {:?}",
token_identity,
computed_identity
)));
computed_identity,
));
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/auth/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod identity;
4 changes: 2 additions & 2 deletions crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ bench = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
spacetimedb-auth.workspace = true
spacetimedb-client-api-messages.workspace = true
spacetimedb-core.workspace = true
spacetimedb-data-structures.workspace = true
spacetimedb-data-structures = { workspace = true, features = ["serde"] }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is the feature newly needed here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was being enabled by core, but now core isn't in the build graph.

spacetimedb-fs-utils.workspace = true
spacetimedb-lib.workspace = true
spacetimedb-paths.workspace = true
Expand Down
48 changes: 47 additions & 1 deletion crates/cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::errors::CliError;
use crate::util::{contains_protocol, host_or_url_to_host_and_protocol};
use anyhow::Context;
use jsonwebtoken::DecodingKey;
use spacetimedb::config::{set_opt_value, set_table_opt_value};
use spacetimedb_fs_utils::atomic_write;
use spacetimedb_paths::cli::CliTomlPath;
use std::collections::HashMap;
Expand Down Expand Up @@ -822,6 +821,53 @@ Update the server's fingerprint with:
}
}

/// Update the value of a key in a `TOML` document, preserving the formatting and comments of the original value.
///
/// ie:
///
/// ```toml;no_run
/// # Moving key = value to key = new_value
/// old = "value" # Comment
/// new = "new_value" # Comment
/// ```
fn copy_value_with_decor(old_value: Option<&toml_edit::Item>, new_value: &str) -> toml_edit::Item {
match old_value {
Some(toml_edit::Item::Value(toml_edit::Value::String(old_value))) => {
// Creates a new `toml_edit::Value` with the same formatting as the old value.
let mut new = toml_edit::Value::String(toml_edit::Formatted::new(new_value.to_string()));
let decor = new.decor_mut();
// Copy the comments and formatting from the old value.
*decor = old_value.decor().clone();
new.into()
}
_ => new_value.into(),
}
}

/// Set the value of a key in a `TOML` document, removing the key if the value is `None`.
///
/// **NOTE**: This function will preserve the formatting and comments of the original value.
pub fn set_opt_value(doc: &mut toml_edit::DocumentMut, key: &str, value: Option<&str>) {
let old_value = doc.get(key);
if let Some(new) = value {
doc[key] = copy_value_with_decor(old_value, new);
} else {
doc.remove(key);
}
}

/// Set the value of a key in a `TOML` table, removing the key if the value is `None`.
///
/// **NOTE**: This function will preserve the formatting and comments of the original value.
pub fn set_table_opt_value(table: &mut toml_edit::Table, key: &str, value: Option<&str>) {
let old_value = table.get(key);
if let Some(new) = value {
table[key] = copy_value_with_decor(old_value, new);
} else {
table.remove(key);
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
3 changes: 1 addition & 2 deletions crates/cli/src/subcommands/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ use anyhow::{bail, Context, Error};
use clap::{Arg, ArgMatches};
use convert_case::{Case, Casing};
use itertools::Itertools;
use spacetimedb::Identity;
use spacetimedb_lib::sats::{self, AlgebraicType, Typespace};
use spacetimedb_lib::ProductTypeElement;
use spacetimedb_lib::{Identity, ProductTypeElement};
use spacetimedb_schema::def::{ModuleDef, ReducerDef};
use std::fmt::Write;

Expand Down
29 changes: 20 additions & 9 deletions crates/cli/src/subcommands/generate/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#![warn(clippy::uninlined_format_args)]

use anyhow::Context;
use clap::parser::ValueSource;
use clap::Arg;
use clap::ArgAction::Set;
use core::mem;
use fs_err as fs;
use spacetimedb::host::wasmtime::{Mem, MemView, WasmPointee as _};
use spacetimedb_lib::de::serde::DeserializeWrapper;
use spacetimedb_lib::{bsatn, RawModuleDefV8};
use spacetimedb_lib::{RawModuleDef, MODULE_ABI_MAJOR_VERSION};
Expand Down Expand Up @@ -298,13 +298,13 @@ fn extract_descriptions_from_module(module: wasmtime::Module) -> anyhow::Result<
message_ptr: u32,
message_len: u32| {
let (mem, _) = WasmCtx::mem_env(&mut caller);
let slice = mem.deref_slice(message_ptr, message_len).unwrap();
let slice = deref_slice(mem, message_ptr, message_len).unwrap();
println!("from wasm: {}", String::from_utf8_lossy(slice));
},
)?;
linker.func_wrap(module_name, "bytes_sink_write", WasmCtx::bytes_sink_write)?;
let instance = linker.instantiate(&mut store, &module)?;
let memory = Mem::extract(&instance, &mut store)?;
let memory = instance.get_memory(&mut store, "memory").context("no memory export")?;
store.data_mut().mem = Some(memory);

let mut preinits = instance
Expand All @@ -329,19 +329,30 @@ fn extract_descriptions_from_module(module: wasmtime::Module) -> anyhow::Result<
}

struct WasmCtx {
mem: Option<Mem>,
mem: Option<wasmtime::Memory>,
sink: Vec<u8>,
}

fn deref_slice(mem: &[u8], offset: u32, len: u32) -> anyhow::Result<&[u8]> {
anyhow::ensure!(offset != 0, "ptr is null");
mem.get(offset as usize..)
.and_then(|s| s.get(..len as usize))
.context("pointer out of bounds")
}

fn read_u32(mem: &[u8], offset: u32) -> anyhow::Result<u32> {
Ok(u32::from_le_bytes(deref_slice(mem, offset, 4)?.try_into().unwrap()))
}

impl WasmCtx {
pub fn get_mem(&self) -> Mem {
pub fn get_mem(&self) -> wasmtime::Memory {
self.mem.expect("Initialized memory")
}

fn mem_env<'a>(ctx: impl Into<StoreContextMut<'a, Self>>) -> (&'a mut MemView, &'a mut Self) {
fn mem_env<'a>(ctx: impl Into<StoreContextMut<'a, Self>>) -> (&'a mut [u8], &'a mut Self) {
let ctx = ctx.into();
let mem = ctx.data().get_mem();
mem.view_and_store_mut(ctx)
mem.data_and_store_mut(ctx)
}

pub fn bytes_sink_write(
Expand All @@ -357,9 +368,9 @@ impl WasmCtx {
let (mem, env) = Self::mem_env(&mut caller);

// Read `buffer_len`, i.e., the capacity of `buffer` pointed to by `buffer_ptr`.
let buffer_len = u32::read_from(mem, buffer_len_ptr)?;
let buffer_len = read_u32(mem, buffer_len_ptr)?;
// Write `buffer` to `sink`.
let buffer = mem.deref_slice(buffer_ptr, buffer_len)?;
let buffer = deref_slice(mem, buffer_ptr, buffer_len)?;
env.sink.extend(buffer);

Ok(0)
Expand Down
2 changes: 1 addition & 1 deletion crates/cli/src/subcommands/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::Config;
use anyhow::Context;
use clap::{ArgMatches, Command};
use serde::Deserialize;
use spacetimedb::Identity;
use spacetimedb_lib::Identity;
use tabled::{
settings::{object::Columns, Alignment, Modify, Style},
Table, Tabled,
Expand Down
2 changes: 1 addition & 1 deletion crates/cli/src/util.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::Context;
use base64::{engine::general_purpose::STANDARD_NO_PAD as BASE_64_STD_NO_PAD, Engine as _};
use reqwest::{RequestBuilder, Url};
use spacetimedb::auth::identity::{IncomingClaims, SpacetimeIdentityClaims};
use spacetimedb_auth::identity::{IncomingClaims, SpacetimeIdentityClaims};
use spacetimedb_client_api_messages::name::GetNamesResponse;
use spacetimedb_lib::Identity;
use std::io::Write;
Expand Down
4 changes: 2 additions & 2 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ path = "src/lib.rs" # The source file of the target.
bench = false

[dependencies]
spacetimedb-auth.workspace = true
spacetimedb-data-structures.workspace = true
spacetimedb-lib = { workspace = true, features = ["serde", "metrics_impls"] }
spacetimedb-client-api-messages.workspace = true
Expand Down Expand Up @@ -95,7 +96,6 @@ tokio-util.workspace = true
tokio.workspace = true
tokio-stream = "0.1"
toml.workspace = true
toml_edit.workspace = true
tracing-appender.workspace = true
tracing-core.workspace = true
tracing-flame.workspace = true
Expand All @@ -107,7 +107,7 @@ url.workspace = true
urlencoding.workspace = true
uuid.workspace = true
wasmtime.workspace = true
jwks = { package = "spacetimedb-jwks", version = "0.1.3" }
jwks.workspace = true
async_cache = "0.3.1"
faststr = "0.2.23"

Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/auth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use spacetimedb_paths::cli::{PrivKeyPath, PubKeyPath};

use crate::config::CertificateAuthority;

pub mod identity;
pub use spacetimedb_auth::identity;
pub mod token_validation;

/// JWT verification and signing keys.
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/auth/token_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ impl TokenValidator for DecodingKey {

let data = decode::<IncomingClaims>(token, self, &validation)?;
let claims = data.claims;
claims.try_into()
claims.try_into().map_err(TokenValidationError::Other)
}
}

Expand Down
Loading
Loading