pub struct SpiceDbRepository { /* private fields */ }Expand description
Main SpiceDB client for performing authorization checks.
SpiceDbRepository provides a high-level interface to interact with SpiceDB,
a Google Zanzibar-inspired authorization system. It handles connection management,
authentication, and permission checking operations.
§Architecture
The repository maintains a gRPC connection to a SpiceDB server and provides methods to check whether a subject (e.g., a user) has a specific permission on a resource (e.g., a channel or server).
§Examples
use authz::{SpiceDbRepository, SpiceDbConfig, SpiceDbObject, Permissions};
let config = SpiceDbConfig {
endpoint: "localhost:50051".to_string(),
token: Some("your-token".to_string()),
};
let repo = SpiceDbRepository::new(config).await?;
// Check if user can view a channel
let result = repo.check_permissions(
SpiceDbObject::Channel("channel-123".to_string()),
Permissions::ViewChannels,
SpiceDbObject::User("user-456".to_string()),
).await;
if result.has_permissions() {
println!("Access granted!");
}Implementations§
Source§impl SpiceDbRepository
impl SpiceDbRepository
Sourcepub async fn new(config: SpiceDbConfig) -> Result<Self, AuthorizationError>
pub async fn new(config: SpiceDbConfig) -> Result<Self, AuthorizationError>
Creates a new SpiceDB client with the given configuration.
This establishes a gRPC connection to the SpiceDB server and sets up authentication using the provided token.
§Arguments
config- Configuration containing the endpoint URL and optional authentication token
§Returns
Returns Ok(SpiceDbRepository) on successful connection, or an
AuthorizationError::ConnectionError if the connection fails.
§Examples
use authz::{SpiceDbRepository, SpiceDbConfig};
let config = SpiceDbConfig {
endpoint: "localhost:50051".to_string(),
token: Some("somerandomkey".to_string()),
};
let repo = SpiceDbRepository::new(config).await?;§Errors
This function will return an error if:
- The endpoint URL is invalid
- The connection to SpiceDB cannot be established
- Network issues prevent communication with the server
Sourcepub async fn check_permissions(
&self,
resource: impl Into<SpiceDbObject>,
permission: Permissions,
subject: impl Into<SpiceDbObject>,
) -> AuthorizationResult
pub async fn check_permissions( &self, resource: impl Into<SpiceDbObject>, permission: Permissions, subject: impl Into<SpiceDbObject>, ) -> AuthorizationResult
Checks if a subject has a specific permission on a resource.
This is the primary method for performing authorization checks in your application. It evaluates whether the given subject (e.g., a user) has the specified permission on the target resource (e.g., a channel, server, or other object).
§How It Works
The method performs the following steps:
- Converts the resource and subject into SpiceDB object references
- Sends a gRPC
CheckPermissionrequest to SpiceDB - SpiceDB evaluates the permission based on defined relationships and rules
- Returns an
AuthorizationResultindicating whether access is granted
§Arguments
resource- The resource being accessed (e.g.,SpiceDbObject::Channel("123"))permission- The permission being checked (e.g.,Permissions::ViewChannels)subject- The entity requesting access (e.g.,SpiceDbObject::User("456"))
§Returns
Returns an AuthorizationResult which can be queried with:
has_permissions()- Returnstrueif access is grantedresult()- ReturnsOk(())if granted, orErr(AuthorizationError)if denied
§Examples
§Basic permission check
use authz::{SpiceDbRepository, SpiceDbObject, Permissions};
let result = repo.check_permissions(
SpiceDbObject::Channel("general".to_string()),
Permissions::SendMessages,
SpiceDbObject::User("alice".to_string()),
).await;
if result.has_permissions() {
// Allow user to send message
println!("User can send messages");
} else {
// Deny access
println!("User cannot send messages");
}§Using result() for error handling
use authz::{SpiceDbRepository, SpiceDbObject, Permissions, AuthorizationError};
let result = repo.check_permissions(
SpiceDbObject::Server("server-1".to_string()),
Permissions::ManageRoles,
SpiceDbObject::User("bob".to_string()),
).await;
// Returns error if permission denied
result.result()?;
// Continue with authorized action
println!("User is authorized to manage roles");§Checking administrative access
use authz::{SpiceDbRepository, SpiceDbObject, Permissions};
let is_admin = repo.check_permissions(
SpiceDbObject::Server("my-server".to_string()),
Permissions::Administrator,
SpiceDbObject::User("charlie".to_string()),
).await.has_permissions();
if is_admin {
// Grant full access
}§Performance Considerations
Each call to this method makes a network request to SpiceDB. For high-performance scenarios, consider:
- Caching authorization results when appropriate
- Batching multiple checks when possible
- Using SpiceDB’s consistency guarantees to balance freshness vs. performance
§See Also
check_permissions_raw- Lower-level API with more controlPermissions- Available permission typesSpiceDbObject- Resource and subject types
Sourcepub async fn check_permissions_raw(
&self,
resource: impl Into<ObjectReference>,
permission: impl Into<String>,
subject: impl Into<ObjectReference>,
) -> Result<Permissionship, AuthorizationError>
pub async fn check_permissions_raw( &self, resource: impl Into<ObjectReference>, permission: impl Into<String>, subject: impl Into<ObjectReference>, ) -> Result<Permissionship, AuthorizationError>
Performs a raw permission check using SpiceDB object references and string permissions.
This is a lower-level API that provides more flexibility than check_permissions.
It allows you to specify permissions as strings and use custom object references directly,
which can be useful for:
- Custom permission types not defined in the
Permissionsenum - Dynamic permission names determined at runtime
- Direct integration with SpiceDB’s native types
§Arguments
resource- The resource object reference (must implementInto<ObjectReference>)permission- The permission name as a string (e.g., “view”, “edit”, “admin”)subject- The subject object reference (must implementInto<ObjectReference>)
§Returns
Returns a Result containing:
Ok(Permissionship)- The permission status from SpiceDB:Permissionship::HasPermission- Access is grantedPermissionship::NoPermission- Access is deniedPermissionship::ConditionalPermission- Access depends on additional context
Err(AuthorizationError::Unauthorized)- The check failed or was denied
§Examples
§Custom permission check
use authz::{SpiceDbRepository, authzed::api::v1::ObjectReference};
let resource = ObjectReference {
object_type: "document".to_string(),
object_id: "doc-123".to_string(),
};
let subject = ObjectReference {
object_type: "user".to_string(),
object_id: "user-456".to_string(),
};
let permissionship = repo.check_permissions_raw(
resource,
"edit",
subject,
).await?;
match permissionship {
authz::authzed::api::v1::check_permission_response::Permissionship::HasPermission => {
println!("Permission granted");
}
_ => {
println!("Permission denied");
}
}§Dynamic permission names
use authz::{SpiceDbRepository, SpiceDbObject};
let permission_name = format!("can_{}", action);
let result = repo.check_permissions_raw(
SpiceDbObject::Channel(resource_id.to_string()),
permission_name,
SpiceDbObject::User(user_id.to_string()),
).await?;
Ok(result.has_permissions())§Errors
This function will return an error if:
- The gRPC connection to SpiceDB fails
- The request times out
- The permission check is denied (returns
AuthorizationError::Unauthorized)
§See Also
check_permissions- Higher-level, type-safe API- SpiceDB CheckPermission API
Trait Implementations§
Source§impl Clone for SpiceDbRepository
impl Clone for SpiceDbRepository
Source§fn clone(&self) -> SpiceDbRepository
fn clone(&self) -> SpiceDbRepository
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for SpiceDbRepository
impl !RefUnwindSafe for SpiceDbRepository
impl Send for SpiceDbRepository
impl Sync for SpiceDbRepository
impl Unpin for SpiceDbRepository
impl !UnwindSafe for SpiceDbRepository
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request