openfga_client/lib.rs
1#![warn(
2 missing_debug_implementations,
3 rust_2018_idioms,
4 unreachable_pub,
5 clippy::pedantic
6)]
7#![forbid(unsafe_code)]
8
9//! # OpenFGA Rust Client
10//!
11//! [](https://crates.io/crates/openfga-client)
12//! [](https://opensource.org/licenses/Apache-2.0)
13//! [](https://github.com/vakamo-labs/openfga-client/actions/workflows/ci.yaml)
14//!
15//! OpenFGA Rust Client is a type-safe client for OpenFGA with optional Authorization Model management and Authentication (Bearer or Client Credentials).
16//!
17//! ## Features
18//!
19//! * No dependency on `protoc` - Rust files are pre-generated.
20//! * Type-safe client for OpenFGA (gRPC) build on `tonic`
21//! * (JSON) Serialization and deserialization for Authorization Models in addition go protobuf Messages
22//! * Optional Authorization Model management with Migration hooks if tuples need to be re-written. Ideal for stateless deployments. State is managed exclusively in OpenFGA. This enables fully automated model management by your Application without blindly re-writing of Authorization Models on startup!
23//! * Optional Authentication (Bearer or Client Credentials) via the [Middle Crate](https://crates.io/crates/middle). (Feature: `auth-middle`)
24//! * Convenience functions like `read_all_tuples` (handles pagination), `get_store_by_name` and more.
25//!
26//! # Usage
27//!
28//! ## Basic Usage
29//! ```no_run
30//! use openfga_client::client::OpenFgaServiceClient;
31//! use tonic::transport::Channel;
32//!
33//! #[tokio::main]
34//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
35//! let endpoint = "http://localhost:8080";
36//! let client = OpenFgaServiceClient::connect(endpoint).await?;
37//!
38//! // Use the client to interact with OpenFGA
39//! Ok(())
40//! }
41//! ```
42//!
43//! ## Bearer Token Authentication (API-Key)
44//! ```no_run
45//! use openfga_client::client::BasicOpenFgaServiceClient;
46//!
47//! fn main() -> Result<(), Box<dyn std::error::Error>> {
48//! let endpoint = "http://localhost:8080";
49//! let token = "your-bearer-token";
50//! let client = BasicOpenFgaServiceClient::new_with_basic_auth(endpoint, token)?;
51//!
52//! // Use the client to interact with OpenFGA
53//! Ok(())
54//! }
55//! ```
56//!
57//! ## Client Credential Authentication
58//! ```no_run
59//! use openfga_client::client::BasicOpenFgaServiceClient;
60//! use url::Url;
61//!
62//! #[tokio::main]
63//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
64//! let endpoint = "http://localhost:8080";
65//! let client_id = "your-client-id";
66//! let client_secret = "your-client-secret";
67//! let token_endpoint = Url::parse("http://localhost:8080/token")?;
68//! let client = BasicOpenFgaServiceClient::new_with_client_credentials(endpoint, client_id, client_secret, &token_endpoint).await?;
69//!
70//! // Use the client to interact with OpenFGA
71//! Ok(())
72//! }
73//! ```
74//!
75//! ## License
76//! This project is licensed under the Apache-2.0 License. See the LICENSE file for details.
77//!
78//! ## Contributing
79//! Contributions are welcome! Please open an issue or submit a pull request on GitHub.
80
81pub use prost_types;
82pub use tonic;
83pub mod error;
84pub mod migration;
85
86mod client_ext;
87mod conversions;
88
89mod generated {
90 #![allow(clippy::all)]
91 #![allow(clippy::pedantic)]
92
93 include!("gen/openfga.v1.rs");
94}
95
96pub mod client {
97 pub use open_fga_service_client::OpenFgaServiceClient;
98
99 #[cfg(feature = "auth-middle")]
100 pub use super::client_ext::BasicOpenFgaServiceClient;
101 pub use super::generated::*;
102}
103
104#[cfg(test)]
105mod test_json_serde {
106 use super::client::*;
107
108 fn test_authorization_model_serde(schema: &str) {
109 let schema_json: serde_json::Value = schema.parse().unwrap();
110 let schema: AuthorizationModel = serde_json::from_value(schema_json.clone()).unwrap();
111 let value = serde_json::to_value(&schema).unwrap();
112 assert_eq!(schema_json, value);
113 }
114 #[test]
115 fn test_serde_custom_roles() {
116 test_authorization_model_serde(include_str!(
117 "../tests/sample-store/custom-roles/schema.json"
118 ));
119 }
120
121 #[test]
122 fn test_serde_entitlements() {
123 test_authorization_model_serde(include_str!(
124 "../tests/sample-store/entitlements/schema.json"
125 ));
126 }
127
128 #[test]
129 fn test_serde_expenses() {
130 test_authorization_model_serde(include_str!("../tests/sample-store/expenses/schema.json"));
131 }
132
133 // gdrive, github, iot, issue-tracker, modular, slack
134 #[test]
135 fn test_serde_gdrive() {
136 test_authorization_model_serde(include_str!("../tests/sample-store/gdrive/schema.json"));
137 }
138
139 #[test]
140 fn test_serde_github() {
141 test_authorization_model_serde(include_str!("../tests/sample-store/github/schema.json"));
142 }
143
144 #[test]
145 fn test_serde_iot() {
146 test_authorization_model_serde(include_str!("../tests/sample-store/iot/schema.json"));
147 }
148
149 #[test]
150 fn test_serde_modular() {
151 test_authorization_model_serde(include_str!("../tests/sample-store/modular/schema.json"));
152 }
153
154 #[test]
155 fn test_serde_slack() {
156 test_authorization_model_serde(include_str!("../tests/sample-store/slack/schema.json"));
157 }
158}