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

Update the crate description for identity-credential #873

Merged
merged 22 commits into from
Jun 13, 2022
Merged
Show file tree
Hide file tree
Changes from 15 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
28 changes: 14 additions & 14 deletions bindings/wasm/docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ publishing to the Tangle.
**Kind**: global class

* [Account](#Account)
* [.detachMethodRelationships(options)](#Account+detachMethodRelationships) ⇒ <code>Promise.&lt;void&gt;</code>
* [.did()](#Account+did) ⇒ [<code>DID</code>](#DID)
* [.autopublish()](#Account+autopublish) ⇒ <code>boolean</code>
* [.autosave()](#Account+autosave) ⇒ [<code>AutoSave</code>](#AutoSave)
Expand All @@ -224,7 +225,17 @@ publishing to the Tangle.
* [.createService(options)](#Account+createService) ⇒ <code>Promise.&lt;void&gt;</code>
* [.attachMethodRelationships(options)](#Account+attachMethodRelationships) ⇒ <code>Promise.&lt;void&gt;</code>
* [.createMethod(options)](#Account+createMethod) ⇒ <code>Promise.&lt;void&gt;</code>
* [.detachMethodRelationships(options)](#Account+detachMethodRelationships) ⇒ <code>Promise.&lt;void&gt;</code>

<a name="Account+detachMethodRelationships"></a>

### account.detachMethodRelationships(options) ⇒ <code>Promise.&lt;void&gt;</code>
Detaches the given relationship from the given method, if the method exists.

**Kind**: instance method of [<code>Account</code>](#Account)

| Param | Type |
| --- | --- |
| options | <code>DetachMethodRelationshipOptions</code> |

<a name="Account+did"></a>

Expand Down Expand Up @@ -471,17 +482,6 @@ Adds a new verification method to the DID document.
| --- | --- |
| options | <code>CreateMethodOptions</code> |

<a name="Account+detachMethodRelationships"></a>

### account.detachMethodRelationships(options) ⇒ <code>Promise.&lt;void&gt;</code>
Detaches the given relationship from the given method, if the method exists.

**Kind**: instance method of [<code>Account</code>](#Account)

| Param | Type |
| --- | --- |
| options | <code>DetachMethodRelationshipOptions</code> |

<a name="AccountBuilder"></a>

## AccountBuilder
Expand Down Expand Up @@ -929,7 +929,7 @@ Returns a copy of the JSON-LD context(s) applicable to the `Credential`.
<a name="Credential+id"></a>

### credential.id() ⇒ <code>string</code> \| <code>undefined</code>
Returns a copy of the unique `URI` referencing the subject of the `Credential`.
Returns a copy of the unique `URI` identifying the `Credential` .

**Kind**: instance method of [<code>Credential</code>](#Credential)
<a name="Credential+type"></a>
Expand Down Expand Up @@ -3330,7 +3330,7 @@ Returns a copy of the JSON-LD context(s) applicable to the `Presentation`.
<a name="Presentation+id"></a>

### presentation.id() ⇒ <code>string</code> \| <code>undefined</code>
Returns a copy of the unique `URI` of the `Presentation`.
Returns a copy of the unique `URI` identifying the `Presentation`.

**Kind**: instance method of [<code>Presentation</code>](#Presentation)
<a name="Presentation+type"></a>
Expand Down
2 changes: 1 addition & 1 deletion bindings/wasm/src/credential/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl WasmCredential {
.map(|value| value.unchecked_into::<ArrayContext>())
}

/// Returns a copy of the unique `URI` referencing the subject of the `Credential`.
/// Returns a copy of the unique `URI` identifying the `Credential` .
#[wasm_bindgen]
pub fn id(&self) -> Option<String> {
self.0.id.as_ref().map(|url| url.to_string())
Expand Down
2 changes: 1 addition & 1 deletion bindings/wasm/src/credential/credential_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ struct ICredentialHelper {
/// The JSON-LD context(s) applicable to the `Credential`.
#[typescript(type = "string | Record<string, any> | Array<string | Record<string, any>>")]
context: Option<OneOrMany<Context>>,
/// A unique URI referencing the subject of the `Credential`.
/// A unique URI that may be used to identify the `Credential`.
#[typescript(type = "string")]
id: Option<String>,
/// One or more URIs defining the type of the `Credential`. Contains the base context by default.
Expand Down
2 changes: 1 addition & 1 deletion bindings/wasm/src/credential/presentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl WasmPresentation {
.map(|value| value.unchecked_into::<ArrayContext>())
}

/// Returns a copy of the unique `URI` of the `Presentation`.
/// Returns a copy of the unique `URI` identifying the `Presentation`.
#[wasm_bindgen]
pub fn id(&self) -> Option<String> {
self.0.id.as_ref().map(|url| url.to_string())
Expand Down
2 changes: 1 addition & 1 deletion bindings/wasm/src/credential/presentation_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ struct IPresentationHelper {
/// The JSON-LD context(s) applicable to the `Presentation`.
#[typescript(type = "string | Record<string, any> | Array<string | Record<string, any>>")]
context: Option<OneOrMany<Context>>,
/// A unique URI of the `Presentation`.
/// A unique URI that may be used to identify the `Presentation`.
#[typescript(type = "string")]
id: Option<String>,
/// One or more URIs defining the type of the `Presentation`. Contains the base context by default.
Expand Down
1 change: 0 additions & 1 deletion identity-credential/README.md

This file was deleted.

161 changes: 161 additions & 0 deletions identity-credential/src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
IOTA Identity - Credentials
===

This crate contains types representing verifiable credentials and verifiable presentations as defined in the [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/).

The [IOTA Identity Framework Wiki](https://wiki.iota.org/identity.rs/concepts/verifiable_credentials/overview) provides an overview of verifiable credentials and demonstrates how they may be constructed using the building blocks from this crate.

## Construction
This crate follows the [builder pattern](https://rust-unofficial.github.io/patterns/patterns/creational/builder.html) for the creation of [`Credentials`](crate::credential::Credential) and [`Presentations`](crate::presentation::Presentation).

### Example - Credential
Constructing a [`Credential`](crate::credential::Credential) using the [`CredentialBuilder`](crate::credential::CredentialBuilder).

```rust
use identity_credential::credential::Credential;
use identity_credential::credential::CredentialBuilder;
use identity_credential::credential::Subject;
use identity_credential::credential::Issuer;
use identity_core::common::Url;
use identity_core::common::Timestamp;
use serde_json::json;
use serde_json::Value;


// Construct a `Subject` from json
let json_subject: Value = json!({
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"degree": {
"type": "BachelorDegree",
"name": "Bachelor of Science and Arts"
}
});
let subject: Subject = serde_json::from_value(json_subject).unwrap();

// Construct an `Issuer` from json
let json_issuer: Value = json!({
"id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
"name": "Example University"
});

let issuer: Issuer = serde_json::from_value(json_issuer).unwrap();

let credential: Credential = CredentialBuilder::default()
.context(Url::parse("https://www.w3.org/2018/credentials/examples/v1").unwrap())
.id(Url::parse("http://example.edu/credentials/3732").unwrap())
.type_("UniversityDegreeCredential")
.subject(subject)
.issuer(issuer)
.issuance_date(Timestamp::parse("2010-01-01T00:00:00Z").unwrap())
.build()
.unwrap();

```
#### Important

The generated `Credential` is not verifiable until it has been signed by the issuer's DID Document. See [this example](https://github.com/iotaledger/identity.rs/blob/support/v0.5/examples/account/create_vc.rs) for a full demonstration of issuing and signing a verifiable credential.

### Example - Presentation
Constructing a [`Presentation`](crate::presentation::Presentation) using the [`PresentationBuilder`](crate::presentation::PresentationBuilder).

```rust
use identity_credential::credential::Credential;
use identity_credential::presentation::Presentation;
use identity_credential::presentation::PresentationBuilder;
use identity_core::common::Url;

// Build a presentation for the given holder and iterator of credentials
fn build_presentation(credentials: impl Iterator<Item = Credential>, holder: Url) -> Presentation {
let presentation_builder: PresentationBuilder = PresentationBuilder::default();
credentials
.fold(
presentation_builder,
|builder: PresentationBuilder, credential: Credential| builder.credential(credential),
)
.holder(holder)
.build()
.unwrap()
}
```
#### Important
A `Presentation` is not verifiable until signed by the holder's DID Document. All `Credentials` contained in the presentation must also be signed by their respective issuers. See [this example](https://github.com/iotaledger/identity.rs/blob/support/v0.5/examples/account/create_vp.rs) for a full demonstration of constructing and validating a verifiable presentation.

## JSON Serialization
The `Credential` and `Presentation` types both implement the [`Serialize`](https://docs.serde.rs/serde/trait.Serialize.html) and [`Deserialize`](https://docs.serde.rs/serde/trait.Deserialize.html) traits from the [`serde` crate](https://crates.io/crates/serde). Hence one can use the [`serde_json` crate](https://crates.io/crates/serde_json) to obtain `Credential`s and `Presentation`s from JSON.

### Example
Deserializing a `Presentation` from JSON.

```rust
use identity_credential::presentation::Presentation;
use serde_json;

let presentation_json: &'static str = r#"{
"@context": "https://www.w3.org/2018/credentials/v1",
"id": "http://example.org/credentials/3732",
"type": "VerifiablePresentation",
"verifiableCredential": [
{
"@context": "https://www.w3.org/2018/credentials/v1",
"id": "https://example.edu/credentials/3732",
"type": [
"VerifiableCredential",
"UniversityDegreeCredential"
],
"credentialSubject": {
"id": "did:iota:4LCrrVYFQkYYn9VPejhebmMhNnCq24pYPao8yvVLwVje",
"GPA": "4.0",
"degree": {
"name": "Bachelor of Science and Arts",
"type": "BachelorDegree"
},
"name": "Alice"
},
"issuer": "did:iota:H3PBNPtLYkVaPpMQVz1R3LeT5zW1Hd6BXQmdtFptaGLR",
"issuanceDate": "2019-01-01T00:00:00Z",
"expirationDate": "2024-01-01T00:00:00Z",
"nonTransferable": true,
"proof": {
"type": "JcsEd25519Signature2020",
"verificationMethod": "did:iota:H3PBNPtLYkVaPpMQVz1R3LeT5zW1Hd6BXQmdtFptaGLR#sign-0",
"signatureValue": "5H2TSAG3cHnVEt7HZgg6aeYqmzKRQr9BTaP6mgHSE9uH9iLy7pK7TC2A5NHaiiFMGGaY3hJS5WUhfqCW3APxFhSP"
}
},
{
"@context": "https://www.w3.org/2018/credentials/v1",
"id": "https://example.edu/credentials/3732",
"type": [
"VerifiableCredential",
"UniversityDegreeCredential"
],
"credentialSubject": {
"id": "did:iota:b5DtNBzvJfz8jrX1FYYxgvHqvsoFofy1hxzPRMM5iH1",
"GPA": "4.0",
"degree": {
"name": "Bachelor of Science and Arts",
"type": "BachelorDegree"
},
"name": "Alice"
},
"issuer": "did:iota:7RD6LT5aSNuKMLJJYorGzhktpTG2TrxGSLmHnWW1Dbb",
"issuanceDate": "2020-01-01T00:00:00Z",
"expirationDate": "2023-01-01T00:00:00Z",
"proof": {
"type": "JcsEd25519Signature2020",
"verificationMethod": "did:iota:7RD6LT5aSNuKMLJJYorGzhktpTG2TrxGSLmHnWW1Dbb#sign-0",
"signatureValue": "4QYkkDLDCZxfa6mymhGTGvG4NRgzdx5Txst7dM6jtfDpBV3Mif8hWH93RzR2MoVCtMgZf3ed7qoZsqepWkp4x9oU"
}
}
],
"holder": "did:iota:4LCrrVYFQkYYn9VPejhebmMhNnCq24pYPao8yvVLwVje",
"proof": {
"type": "JcsEd25519Signature2020",
"verificationMethod": "did:iota:4LCrrVYFQkYYn9VPejhebmMhNnCq24pYPao8yvVLwVje#sign-0",
"signatureValue": "47YLi81cr8atfiyydTe4o989V8GBWZk6rVtvE5bAydhbd8HCK5c3wrNXRbBDAF8PDUBGGGqn8ZjA3jxGDFpQwGAW",
"challenge": "475a7984-1bb5-4c4c-a56f-822bccd46440"
}
}
"#;

let presentation: Presentation = serde_json::from_str(presentation_json).unwrap();
```
2 changes: 1 addition & 1 deletion identity-credential/src/credential/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub struct Credential<T = Object> {
/// The JSON-LD context(s) applicable to the `Credential`.
#[serde(rename = "@context")]
pub context: OneOrMany<Context>,
/// A unique `URI` referencing the subject of the `Credential`.
/// A unique `URI` that may be used to identify the `Credential`.
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<Url>,
/// One or more URIs defining the type of the `Credential`.
Expand Down
4 changes: 1 addition & 3 deletions identity-credential/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]
#![cfg_attr(docsrs, feature(doc_cfg, extended_key_value_attributes))]
#![cfg_attr(docsrs, cfg_attr(docsrs, doc = include_str!("../README.md")))]
#![cfg_attr(not(docsrs), doc = "")]
#![doc = include_str!("README.md")]
#![allow(clippy::upper_case_acronyms)]
#![warn(
rust_2018_idioms,
Expand Down
2 changes: 1 addition & 1 deletion identity-credential/src/presentation/presentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub struct Presentation<T = Object, U = Object> {
/// The JSON-LD context(s) applicable to the `Presentation`.
#[serde(rename = "@context")]
pub context: OneOrMany<Context>,
/// A unique `URI` referencing the subject of the `Presentation`.
/// A unique `URI` that may be used to identify the `Presentation`.
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<Url>,
/// One or more URIs defining the type of the `Presentation`.
Expand Down