Skip to content

Commit

Permalink
remove mock feature to avoid constraining the API prematurely
Browse files Browse the repository at this point in the history
  • Loading branch information
Lur1an committed Jul 19, 2024
1 parent 4173cf9 commit a80d978
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 127 deletions.
86 changes: 1 addition & 85 deletions Cargo.lock

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

4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "spicedb-rust"
version = "0.2.2"
version = "0.3.0"
edition = "2021"
description = "A client for spicedb"
license = "MIT"
Expand All @@ -15,15 +15,13 @@ uuid = "1.6.1"
tonic-reflection = "0.10.2"
anyhow = "1.0.86"
futures = "0.3.30"
mockall = { version = "0.12.1", optional = true }
strum = { version = "0.26.3", features = ["derive", "strum_macros"] }

[build-dependencies]
tonic-build = "0.10.2"

[features]
default = []
mock = ["dep:mockall"]

[dev-dependencies]
uuid = { version = "1.10.0", features = ["v4", "v7"] }
Expand Down
43 changes: 19 additions & 24 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,20 @@ pub struct SpiceDBClient {
permission_service_client: SpiceDBPermissionClient,
}

#[cfg_attr(feature = "mock", mockall::automock)]
impl SpiceDBClient {
/// Reads the following env variables:
/// - `ZED_TOKEN`
/// - `ZED_ENDPOINT`
pub async fn from_env() -> anyhow::Result<Self> {
let token = std::env::var("ZED_TOKEN")?;
let addr = std::env::var("ZED_ENDPOINT")?;
let token = std::env::var("SPICEDB_TOKEN")?;
let addr = std::env::var("SPICEDB_ENDPOINT")?;
Self::new(addr, &token).await
}

pub async fn new(addr: String, token: &str) -> anyhow::Result<Self> {
let token = format!("Bearer {}", token).parse()?;
pub async fn new(addr: impl Into<String>, token: impl AsRef<str>) -> anyhow::Result<Self> {
let token = format!("Bearer {}", token.as_ref()).parse()?;
let interceptor = BearerTokenInterceptor::new(token);
let channel = tonic::transport::Channel::from_shared(addr)?
let channel = tonic::transport::Channel::from_shared(addr.into())?
.connect()
.await?;
Ok(SpiceDBClient {
Expand Down Expand Up @@ -138,13 +137,12 @@ impl SpiceDBClient {

/// Shortcut for the most common use case of looking up resources, to quickly collect all ID's
/// returned in one call.
pub async fn lookup_resources<A, R>(
pub async fn lookup_resources<R>(
&self,
actor: &A,
actor: &impl Actor,
permission: R::Permissions,
) -> GrpcResult<Vec<R::Id>>
where
A: Actor,
R: Resource,
{
let mut request = self.lookup_resources_request::<R>();
Expand All @@ -153,14 +151,13 @@ impl SpiceDBClient {
request.send_collect_ids().await
}

pub async fn lookup_resources_at<A, R>(
pub async fn lookup_resources_at<R>(
&self,
actor: &A,
actor: &impl Actor,
permission: R::Permissions,
token: spicedb::ZedToken,
) -> GrpcResult<Vec<R::Id>>
where
A: Actor,
R: Resource,
{
let mut request = self.lookup_resources_request::<R>();
Expand All @@ -172,7 +169,7 @@ impl SpiceDBClient {

pub async fn lookup_subjects<S, R>(
&self,
id: R::Id,
id: impl Into<R::Id>,
permission: R::Permissions,
) -> GrpcResult<Vec<S::Id>>
where
Expand All @@ -186,7 +183,7 @@ impl SpiceDBClient {

pub async fn lookup_subjects_at<S, R>(
&self,
id: R::Id,
id: impl Into<R::Id>,
permission: R::Permissions,
token: spicedb::ZedToken,
) -> GrpcResult<Vec<S::Id>>
Expand All @@ -202,39 +199,37 @@ impl SpiceDBClient {

/// Shortcut for the most common use case of checking a permission for an actor in the system
/// on a specific resource `R` with default consistency.
pub async fn check_permission<A, R>(
pub async fn check_permission<R>(
&self,
actor: &A,
resource_id: R::Id,
actor: &impl Actor,
resource_id: impl Into<R::Id>,
permission: R::Permissions,
) -> GrpcResult<bool>
where
A: Actor,
R: Resource,
{
let mut request = self.check_permission_request::<R>();
request.subject(actor.to_subject());
request.resource(object_reference::<R>(resource_id));
request.resource(object_reference::<R>(resource_id.into()));
request.permission(permission);
let resp = request.send().await?;
Ok(resp.permissionship
== spicedb::check_permission_response::Permissionship::HasPermission as i32)
}

pub async fn check_permission_at<A, R>(
pub async fn check_permission_at<R>(
&self,
actor: &A,
resource_id: R::Id,
actor: &impl Actor,
resource_id: impl Into<R::Id>,
permission: R::Permissions,
token: spicedb::ZedToken,
) -> GrpcResult<bool>
where
A: Actor,
R: Resource,
{
let mut request = self.check_permission_request::<R>();
request.subject(actor.to_subject());
request.resource(object_reference::<R>(resource_id));
request.resource(object_reference::<R>(resource_id.into()));
request.permission(permission);
request.consistency(Consistency::AtLeastAsFresh(token));
let resp = request.send().await?;
Expand Down
6 changes: 5 additions & 1 deletion src/permission/check_permission.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::grpc::GrpcResult;
use crate::permission::SpiceDBPermissionClient;
use crate::spicedb::wrappers::Consistency;
use crate::{spicedb, Permission, Resource};
use crate::{spicedb, Actor, Permission, Resource};

#[derive(Debug)]
pub struct CheckPermissionRequest<R> {
Expand Down Expand Up @@ -45,6 +45,10 @@ where
self
}

pub fn actor(&mut self, actor: &impl Actor) -> &mut Self {
self.subject(actor.to_subject())
}

pub fn resource(&mut self, resource: spicedb::ObjectReference) -> &mut Self {
self.request.resource = Some(resource);
self
Expand Down
4 changes: 2 additions & 2 deletions src/permission/lookup_subjects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ where
self
}

pub fn resource(&mut self, id: R::Id, permission: R::Permissions) -> &mut Self
pub fn resource(&mut self, id: impl Into<R::Id>, permission: R::Permissions) -> &mut Self
where
R: Resource,
{
self.request.resource = Some(object_reference::<R>(id));
self.request.resource = Some(object_reference::<R>(id.into()));
self.request.permission = permission.name().into();
self
}
Expand Down
20 changes: 8 additions & 12 deletions tests/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ async fn example() {

let actor = User::new(user_id);
let authorized = client
.check_permission_at::<_, Document>(
.check_permission_at::<Document>(
&actor,
"homework".to_owned(),
"homework",
DocumentPermission::Write,
token.clone(),
)
Expand All @@ -103,9 +103,9 @@ async fn example() {

let random_user_actor = User::new(Uuid::now_v7());
let authorized = client
.check_permission_at::<_, Document>(
.check_permission_at::<Document>(
&random_user_actor,
"manga".to_owned(),
"manga",
DocumentPermission::Read,
token.clone(),
)
Expand All @@ -117,7 +117,7 @@ async fn example() {
);

let mut resource_ids = client
.lookup_resources_at::<_, Document>(&actor, DocumentPermission::Read, token.clone())
.lookup_resources_at::<Document>(&actor, DocumentPermission::Read, token.clone())
.await
.unwrap();
let mut expected = vec!["homework", "manga"];
Expand All @@ -129,11 +129,7 @@ async fn example() {
);

let subject_ids = client
.lookup_subjects_at::<User, Document>(
"homework".to_owned(),
DocumentPermission::Write,
token.clone(),
)
.lookup_subjects_at::<User, Document>("homework", DocumentPermission::Write, token.clone())
.await
.unwrap();
assert_eq!(subject_ids, vec![user_id]);
Expand All @@ -144,9 +140,9 @@ async fn example() {
.unwrap();

let authorized = client
.check_permission_at::<_, Document>(
.check_permission_at::<Document>(
&random_user_actor,
"manga".to_owned(),
"manga",
DocumentPermission::Read,
new_token,
)
Expand Down

0 comments on commit a80d978

Please sign in to comment.