Skip to content

Commit

Permalink
Merge pull request #279 from adorsys/107-improve-code-documentation-f…
Browse files Browse the repository at this point in the history
…or-the-project

Improve code documentation for the project
  • Loading branch information
chendiblessing authored Dec 11, 2024
2 parents 67393f1 + 11235cf commit 7e2f492
Show file tree
Hide file tree
Showing 44 changed files with 927 additions and 712 deletions.
64 changes: 64 additions & 0 deletions crates/database/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Database crate

A lightweight library for managing MongoDB operations. This library provides an interface, the `Repository` trait with default implementations for interacting with MongoDB collections. It is used by the plugins in the workspace that require database access.
This crate is part of the [DIDComm mediator](https://github.com/adorsys/didcomm-mediator-rs) project.

## Usage

### Requirements

* [MongoDB](https://www.mongodb.com) server instance
* Environment variables:
* `MONGO_URI`: MongoDB connection string
* `MONGO_DBN`: Database name

### Example

* Define an entity

```rust
use database::Repository;

#[derive(Debug, Clone, Serialize, Deserialize)]
struct MyEntity {
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
id: Option<ObjectId>,
name: String,
}

impl Identifiable for MyEntity {
fn id(&self) -> Option<ObjectId> {
self.id.clone()
}

fn set_id(&mut self, id: ObjectId) {
self.id = Some(id);
}
}
```

* Implement the `Repository` trait(the only required method is `get_collection`)

```rust
struct MyEntityRepository {
collection: Arc<RwLock<Collection<MyEntity>>>,
}

#[async_trait]
impl Repository<MyEntity> for MyEntityRepository {
fn get_collection(&self) -> Arc<RwLock<Collection<MyEntity>>> {
self.collection.clone()
}
}
```

* Use the repository

```rust
let db = get_or_init_database();
let repo = MyEntityRepository {
collection: Arc::new(RwLock::new(db.read().await.collection("my_entities"))),
};
let entity = MyEntity { id: None, name: "example".to_string() };
repo.store(entity).await?;
```
10 changes: 9 additions & 1 deletion crates/database/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,10 @@ where
Entity: Identifiable + Unpin,
Entity: Serialize + for<'de> Deserialize<'de>,
{
/// Get a handle to a collection.
fn get_collection(&self) -> Arc<RwLock<Collection<Entity>>>;

/// Retrieve all entities from the database.
async fn find_all(&self) -> Result<Vec<Entity>, RepositoryError> {
let mut entities = Vec::new();
let collection = self.get_collection();
Expand All @@ -83,7 +85,7 @@ where
Ok(entities)
}

/// Counts all entities by filter.
/// Gets the number of documents matching `filter`.
async fn count_by(&self, filter: BsonDocument) -> Result<usize, RepositoryError> {
let collection = self.get_collection();
// Lock the Mutex and get the Collection
Expand All @@ -95,10 +97,12 @@ where
.map_err(|_| RepositoryError::Generic("count overflow".to_owned()))?)
}

/// Find an entity by `id`.
async fn find_one(&self, id: ObjectId) -> Result<Option<Entity>, RepositoryError> {
self.find_one_by(doc! {"_id": id}).await
}

/// Find an entity matching `filter`.
async fn find_one_by(&self, filter: BsonDocument) -> Result<Option<Entity>, RepositoryError> {
let collection = self.get_collection();

Expand All @@ -125,6 +129,8 @@ where
Ok(entity)
}

/// Find all entities matching `filter`.
/// If `limit` is set, only the first `limit` entities are returned.
async fn find_all_by(
&self,
filter: BsonDocument,
Expand All @@ -146,6 +152,7 @@ where
Ok(entities)
}

/// Deletes an entity by `id`.
async fn delete_one(&self, id: ObjectId) -> Result<(), RepositoryError> {
let collection = self.get_collection();

Expand All @@ -158,6 +165,7 @@ where
Ok(())
}

/// Updates an entity.
async fn update(&self, entity: Entity) -> Result<Entity, RepositoryError> {
if entity.id().is_none() {
return Err(RepositoryError::MissingIdentifier);
Expand Down
40 changes: 40 additions & 0 deletions crates/keystore/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Keystore Crate

The `keystore` crate is a utility library for managing cryptographic secrets. It is used in the [Didcomm Mediator](https://github.com/adorsys/didcomm-mediator-rs/) to store and retrieve cryptographic keys for DIDcomm interactions.

## Usage

This crate is internal to the [Didcomm Mediator](https://github.com/adorsys/didcomm-mediator-rs/). Below is an example of interacting with the keystore:

```rust
use keystore::{KeyStore, Secrets};
use mongodb::bson::{doc, Bson, Document};
use did_utils::jwk::Jwk;

// Initialize the keystore
let keystore = KeyStore::get();

let jwk: Jwk = serde_json::from_str(
r#"{
"kty": "OKP",
"crv": "X25519",
"x": "SHSUZ6V3x355FqCzIUfgoPzrZB0BQs0JKyag4UfMqHQ",
"d": "0A8SSFkGHg3N9gmVDRnl63ih5fcwtEvnQu9912SVplY"
}"#,
)
.unwrap();

// Store a secret
let secret = Secrets {
id: Some(ObjectId::new()),
kid: "key-1".to_string(),
secret_material: jwk,
};
keystore.store(secret).await?;

// Retrieve a secret by ID
let secret = keystore.find_one(doc! {"kid": "key-1"}).await?;

// Delete a secret by ID
keystore.delete_one(secret.id.unwrap()).await?;
```
2 changes: 2 additions & 0 deletions crates/keystore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use tokio::sync::RwLock;

static SECRETS_COLLECTION: OnceCell<Collection<Secrets>> = OnceCell::new();

/// Represents a cryptographic secret stored in the keystore.
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Secrets {
#[serde(rename = "_id")]
Expand All @@ -30,6 +31,7 @@ impl Identifiable for Secrets {
}
}

/// A keystore for managing cryptographic secrets.
#[derive(Debug, Clone)]
pub struct KeyStore<T>
where
Expand Down
6 changes: 3 additions & 3 deletions crates/plugin-api/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Server plugin API

The server used for this project provides a system for building versatile applications by integrating functionalities offered by configurable plugins via the plugin API.
An interface that can be used by a generic server to build versatile applications by integrating functionalities offered by configurable plugins via the plugin API. It is part of the [Didcomm Mediator](https://github.com/adorsys/didcomm-mediator-rs/) project.

## Features

Expand Down Expand Up @@ -51,9 +51,9 @@ impl Plugin for MyPlugin {
Ok(())
}

fn routes(&self) -> Router {
fn routes(&self) -> Result<Router, PluginError> {
// Define and return routes here
Router::new().route("/myplugin", get(my_plugin_handler))
Router::new().route("/myplugin", get(my_plugin_handler))?
}
}

Expand Down
33 changes: 18 additions & 15 deletions crates/web-plugins/did-endpoint/README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
# did-endpoint

The `did-endpoint` crate provides tools and functionalities for generating and managing Decentralized Identifiers (DIDs) and web-based interactions.
The `did-endpoint` plugin crate provides a set of tools for generating and validating a DID document. It is a part of the [Didcomm Mediator](https://github.com/adorsys/didcomm-mediator-rs/) project.

## Features

- **Generates keys and forward them for DID generation:**
- **Builds and persists DID document:**
- **Validates the integrity of the persisted DID document**

## Usage

To use `did-endpoint` in your project, add the following to your **Cargo.toml**:

```toml
did-endpoint = "0.1.0"
```

### Example

Here’s a simple example of how you can generate and validate a DID document:

```rust
use did_endpoint::{didgen, validate_diddoc};
use filesystem::{FileSystem, StdFileSystem};
use keystore::KeyStore;

let storage_dirpath = std::env::var("STORAGE_DIRPATH").unwrap(),
let server_public_domain = std::env::var("SERVER_PUBLIC_DOMAIN").unwrap();

let mut filesystem = filesystem::StdFileSystem;
let keystore = keystore::KeyStore::get();

let (storage_dirpath, server_public_domain) = ("target/storage", "https://example.com");
// Generate and persist a new DID document
didgen::didgen(
storage_dirpath,
server_public_domain,
&keystore,
&mut filesystem,
)?;

// generate and persist a did document
didgen(&storage_dirpath, &server_public_domain)?;
// validate the generated did document
assert!(validate_diddoc(&storage_dirpath).is_ok());
// Validate the integrity of the persisted DID document
didgen::validate_diddoc(storage_dirpath, &keystore, &mut filesystem)?;
```
97 changes: 97 additions & 0 deletions crates/web-plugins/didcomm-messaging/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# didcomm-messaging

The `didcomm-messaging` plugin is a web plugin of the [DIDComm mediator](https://github.com/adorsys/didcomm-mediator-rs/) project. It provides implementations of various DIDComm messaging protocols as plugins and features, so protocols can be added and deleted with minimal effort as well as being dynamically loaded.

See the repository [README](https://github.com/adorsys/didcomm-mediator-rs/blob/main/README.md) for the list of currently supported protocols.

## Usage

**Implementing a new protocol:**

* Define handler(s) for the protocol

```rust
use async_trait::async_trait;
use axum::response::{IntoResponse, Response};
use didcomm::Message;
use message_api::{MessageHandler, MessagePlugin, MessageRouter};
use shared::state::AppState;
use std::sync::Arc;

pub struct MockProtocol;

struct ExampleProtocolHandler1;
struct ExampleProtocolHandler2;

#[async_trait]
impl MessageHandler for ExampleProtocolHandler1 {
async fn handle(
&self,
_state: Arc<AppState>,
message: Message,
) -> Result<Option<Message>, Response> {
// do something with the message
Ok(None)
}
}

#[async_trait]
impl MessageHandler for ExampleProtocolHandler2 {
async fn handle(
&self,
_state: Arc<AppState>,
message: Message,
) -> Result<Option<Message>, Response> {
// do something with the message
Ok(None)
}
}

impl MessagePlugin for MockProtocol {
fn name(&self) -> &'static str {
"mock_protocol"
}

fn didcomm_routes(&self) -> MessageRouter {
MessageRouter::new()
.register("message-type-1", ExampleProtocolHandler1)
.register("message-type-2", ExampleProtocolHandler2)
}
}
```

* Add the protocol to the `DIDCOMM_PLUGINS` array in `crates/web-plugins/didcomm-messaging/src/protocols.rs`:

```rust
pub(crate) static DIDCOMM_PLUGINS: Lazy<Vec<Arc<dyn MessagePlugin>>> = Lazy::new(|| {
vec![
#[cfg(feature = "mock-protocol")]
Arc::new(MockProtocol),
// other plugins
]
});
```

* Add the plugin as a feature in `didcomm-messaging` `Cargo.toml`:

```toml
[dependencies]
mock-protocol = { workspace = true, optional = true }

[features]
mock-protocol = ["mock-protocol", ...]

default = ["mock-protocol", ...]
```

* Adjust the workspace `Cargo.toml`:

```toml
[workspace.dependencies]
mock-protocol = { path = "./crates/web-plugins/didcomm-messaging/protocols/mock-protocol", version = "0.1.0" }

[features]
mock-protocol = ["plugin-didcomm_messaging", "didcomm-messaging/mock-protocol"]
```

The plugin manager will automatically handle routing based on the added protocol's routes.
20 changes: 6 additions & 14 deletions crates/web-plugins/didcomm-messaging/did-utils/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ A Rust library for implementing reusable utility code for DID-based applications

## Installation

```rust
cargo install did-utils
Add this to your `Cargo.toml`:

```toml
[dependencies]
did-utils = "0.1"
```

## Usage
Expand Down Expand Up @@ -39,20 +42,9 @@ let encrypted_did_document = did_document.encrypt(&my_public_key);
let decrypted_did_document = encrypted_did_document.decrypt(&my_private_key);
```

## Dependencies

* serde
* sha2
* x25519-dalek

## Documentation

The documentation for the library is available here: https://docs.rs/did-utils/

## Contributors

* Bard
* [Your name]
The documentation for the library is available [here](https://docs.rs/did-utils)

## License

Expand Down
Loading

0 comments on commit 7e2f492

Please sign in to comment.