git ssb

0+

Spruce git-ssb bridge / ssi



Commit a2068150831314d79784575a37370aaf50ed64f4

Add DIDMethodError

- Don't use anyhow in did module
- Use Map for DID method options, for simpler checking
Charles E. Lehner committed on 3/1/2022, 3:47:03 PM
Parent: dcb203fcb92d527f2c3813be8892c9fb0890e18b

Files changed

did-ion/src/sidetree.rschanged
src/did.rschanged
did-ion/src/sidetree.rsView
@@ -5,10 +5,11 @@
55 use reqwest::{header, Client, StatusCode};
66 use serde::{de::DeserializeOwned, Deserialize, Serialize};
77 use serde_json::Value;
88 use ssi::did::{
9- DIDCreate, DIDDeactivate, DIDDocumentOperation, DIDMethod, DIDMethodTransaction, DIDRecover,
10- DIDUpdate, Document, Service, ServiceEndpoint, VerificationRelationship,
9 + DIDCreate, DIDDeactivate, DIDDocumentOperation, DIDMethod, DIDMethodError,
10 + DIDMethodTransaction, DIDRecover, DIDUpdate, Document, Service, ServiceEndpoint,
11 + VerificationRelationship,
1112 };
1213 use ssi::did_resolve::{
1314 DIDResolver, DocumentMetadata, HTTPDIDResolver, ResolutionInputMetadata, ResolutionMetadata,
1415 ERROR_INVALID_DID,
@@ -1482,26 +1483,32 @@
14821483 None => &NoOpResolver,
14831484 }
14841485 }
14851486
1486- fn create(&self, create: DIDCreate) -> Result<DIDMethodTransaction> {
1487 + fn create(&self, create: DIDCreate) -> Result<DIDMethodTransaction, DIDMethodError> {
14871488 let DIDCreate {
14881489 recovery_key,
14891490 update_key,
14901491 verification_key,
14911492 options,
14921493 } = create;
1493- ensure!(is_empty(&options), "Create options not supported");
1494 + for opt in options.keys() {
1495 + return Err(DIDMethodError::OptionNotSupported {
1496 + operation: "create",
1497 + option: opt.clone(),
1498 + });
1499 + }
14941500 let (update_pk, recovery_pk, patches) =
14951501 new_did_state::<S>(update_key, recovery_key, verification_key)
14961502 .context("Prepare keys for DID creation")?;
14971503 let operation = S::create_existing(&update_pk, &recovery_pk, patches)
14981504 .context("Construct Create operation")?;
1499- Self::op_to_transaction(operation).context("Construct create transaction")
1505 + let tx = Self::op_to_transaction(operation).context("Construct create transaction")?;
1506 + Ok(tx)
15001507 }
15011508
15021509 /// <https://identity.foundation/sidetree/api/#sidetree-operations>
1503- async fn submit_transaction(&self, tx: DIDMethodTransaction) -> Result<Value> {
1510 + async fn submit_transaction(&self, tx: DIDMethodTransaction) -> Result<Value, DIDMethodError> {
15041511 let op = Self::op_from_transaction(tx)
15051512 .context("Convert DID method transaction to Sidetree operation")?;
15061513 let endpoint = self
15071514 .endpoint
@@ -1521,9 +1528,9 @@
15211528 let err: SidetreeError = resp
15221529 .json()
15231530 .await
15241531 .context("Transaction submit failed. Unable to read HTTP response JSON")?;
1525- bail!("Transaction submit failed: {}: {}", e, err);
1532 + return Err(anyhow!("Transaction submit failed: {}: {}", e, err).into());
15261533 }
15271534 if resp.content_length() == Some(0) {
15281535 // Update operation may return empty body with 200 OK.
15291536 return Ok(Value::Null);
@@ -1535,9 +1542,9 @@
15351542 ))?;
15361543 Ok(resp_json)
15371544 }
15381545
1539- fn did_from_transaction(&self, tx: DIDMethodTransaction) -> Result<String> {
1546 + fn did_from_transaction(&self, tx: DIDMethodTransaction) -> Result<String, DIDMethodError> {
15401547 let op = Self::op_from_transaction(tx)
15411548 .context("Convert DID method transaction to Sidetree operation")?;
15421549 let did = match op {
15431550 Operation::Create(create_op) => SidetreeDID::<S>::from_create_operation(&create_op)
@@ -1554,18 +1561,23 @@
15541561 };
15551562 Ok(did.to_string())
15561563 }
15571564
1558- fn update(&self, update: DIDUpdate) -> Result<DIDMethodTransaction> {
1565 + fn update(&self, update: DIDUpdate) -> Result<DIDMethodTransaction, DIDMethodError> {
15591566 let DIDUpdate {
15601567 did,
15611568 update_key,
15621569 new_update_key,
15631570 operation,
15641571 options,
15651572 } = update;
15661573 let did = SidetreeDID::<S>::from_str(&did).context("Parse Sidetree DID")?;
1567- ensure!(is_empty(&options), "Update options not supported");
1574 + for opt in options.keys() {
1575 + return Err(DIDMethodError::OptionNotSupported {
1576 + operation: "update",
1577 + option: opt.clone(),
1578 + });
1579 + }
15681580 let update_key = update_key.ok_or(anyhow!("Missing required new update key"))?;
15691581 let new_update_key = new_update_key.ok_or(anyhow!("Missing required new update key"))?;
15701582 S::validate_key(&new_update_key).context("Validate update key")?;
15711583 let new_update_pk =
@@ -1574,13 +1586,14 @@
15741586 .context("Convert DID document operation to Sidetree patch actions")?];
15751587 let did_suffix = DIDSuffix::from(did);
15761588 let update_operation = S::update(did_suffix, &update_key, &new_update_pk, patches)
15771589 .context("Construct Update operation")?;
1578- Self::op_to_transaction(Operation::Update(update_operation))
1579- .context("Construct update transaction")
1590 + let tx = Self::op_to_transaction(Operation::Update(update_operation))
1591 + .context("Construct update transaction")?;
1592 + Ok(tx)
15801593 }
15811594
1582- fn recover(&self, recover: DIDRecover) -> Result<DIDMethodTransaction> {
1595 + fn recover(&self, recover: DIDRecover) -> Result<DIDMethodTransaction, DIDMethodError> {
15831596 let DIDRecover {
15841597 did,
15851598 recovery_key,
15861599 new_recovery_key,
@@ -1589,9 +1602,14 @@
15891602 options,
15901603 } = recover;
15911604 let did = SidetreeDID::<S>::from_str(&did).context("Parse Sidetree DID")?;
15921605 let did_suffix = DIDSuffix::from(did);
1593- ensure!(is_empty(&options), "Recover options not supported");
1606 + for opt in options.keys() {
1607 + return Err(DIDMethodError::OptionNotSupported {
1608 + operation: "recover",
1609 + option: opt.clone(),
1610 + });
1611 + }
15941612 let recovery_key = recovery_key.ok_or(anyhow!("Missing required recovery key"))?;
15951613 let (new_update_pk, new_recovery_pk, patches) =
15961614 new_did_state::<S>(new_update_key, new_recovery_key, new_verification_key)
15971615 .context("Prepare keys for DID recovery")?;
@@ -1602,23 +1620,33 @@
16021620 &new_recovery_pk,
16031621 patches,
16041622 )
16051623 .context("Construct Recover operation")?;
1606- Self::op_to_transaction(operation).context("Construct recover transaction")
1624 + let tx = Self::op_to_transaction(operation).context("Construct recover transaction")?;
1625 + Ok(tx)
16071626 }
16081627
1609- fn deactivate(&self, deactivate: DIDDeactivate) -> Result<DIDMethodTransaction> {
1628 + fn deactivate(
1629 + &self,
1630 + deactivate: DIDDeactivate,
1631 + ) -> Result<DIDMethodTransaction, DIDMethodError> {
16101632 let DIDDeactivate { did, key, options } = deactivate;
16111633 let did = SidetreeDID::<S>::from_str(&did).context("Parse Sidetree DID")?;
16121634 let recovery_key = key.ok_or(anyhow!(
16131635 "Missing required recovery key for DID deactivation"
16141636 ))?;
1615- ensure!(is_empty(&options), "Deactivate options not supported");
1637 + for opt in options.keys() {
1638 + return Err(DIDMethodError::OptionNotSupported {
1639 + operation: "deactivate",
1640 + option: opt.clone(),
1641 + });
1642 + }
16161643 let did_suffix = DIDSuffix::from(did);
16171644 let deactivate_operation = <S as Sidetree>::deactivate(did_suffix, recovery_key)
16181645 .context("Construct DID Deactivate operation")?;
1619- Self::op_to_transaction(Operation::Deactivate(deactivate_operation))
1620- .context("Construct DID deactivate transaction")
1646 + let tx = Self::op_to_transaction(Operation::Deactivate(deactivate_operation))
1647 + .context("Construct DID deactivate transaction")?;
1648 + Ok(tx)
16211649 }
16221650 }
16231651
16241652 impl<S: Sidetree> SidetreeClient<S> {
@@ -1641,16 +1669,8 @@
16411669 Ok(op)
16421670 }
16431671 }
16441672
1645-fn is_empty(options: &Value) -> bool {
1646- options.is_null()
1647- || match options.as_object() {
1648- Some(obj) => obj.is_empty(),
1649- None => false,
1650- }
1651-}
1652-
16531673 #[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
16541674 #[cfg_attr(not(target_arch = "wasm32"), async_trait)]
16551675 impl<S: Sidetree + Send + Sync> DIDResolver for HTTPSidetreeDIDResolver<S> {
16561676 async fn resolve(
src/did.rsView
@@ -4,14 +4,14 @@
44 //!
55 //! [did-core]: https://www.w3.org/TR/did-core/
66
77 use crate::caip10::BlockchainAccountId;
8-use anyhow::{bail, Result as AResult};
98 use std::collections::BTreeMap as Map;
109 use std::collections::HashMap;
1110 use std::convert::TryFrom;
1211 use std::fmt;
1312 use std::str::FromStr;
13 +use thiserror::Error;
1414
1515 use crate::did_resolve::{
1616 Content, ContentMetadata, DIDResolver, DereferencingInputMetadata, DereferencingMetadata,
1717 DocumentMetadata, ResolutionInputMetadata, ResolutionMetadata, ERROR_INVALID_DID,
@@ -393,9 +393,9 @@
393393 pub struct DIDCreate {
394394 pub update_key: Option<JWK>,
395395 pub recovery_key: Option<JWK>,
396396 pub verification_key: Option<JWK>,
397- pub options: Value,
397 + pub options: Map<String, Value>,
398398 }
399399
400400 /// DID Update Operation
401401 ///
@@ -404,9 +404,9 @@
404404 pub did: String,
405405 pub update_key: Option<JWK>,
406406 pub new_update_key: Option<JWK>,
407407 pub operation: DIDDocumentOperation,
408- pub options: Value,
408 + pub options: Map<String, Value>,
409409 }
410410
411411 /// DID Recover Operation
412412 ///
@@ -416,18 +416,18 @@
416416 pub recovery_key: Option<JWK>,
417417 pub new_update_key: Option<JWK>,
418418 pub new_recovery_key: Option<JWK>,
419419 pub new_verification_key: Option<JWK>,
420- pub options: Value,
420 + pub options: Map<String, Value>,
421421 }
422422
423423 /// DID Deactivate Operation
424424 ///
425425 /// <https://identity.foundation/did-registration/#deactivate>
426426 pub struct DIDDeactivate {
427427 pub did: String,
428428 pub key: Option<JWK>,
429- pub options: Value,
429 + pub options: Map<String, Value>,
430430 }
431431
432432 /// DID Document Operation
433433 ///
@@ -482,8 +482,22 @@
482482 #[serde(flatten)]
483483 pub value: Value,
484484 }
485485
486 +/// An error having to do with a [DIDMethod].
487 +#[derive(Error, Debug)]
488 +pub enum DIDMethodError {
489 + #[error("Not implemented for DID method: {0}")]
490 + NotImplemented(&'static str),
491 + #[error("Option '{option}' not supported for DID operation '{operation}'")]
492 + OptionNotSupported {
493 + operation: &'static str,
494 + option: String,
495 + },
496 + #[error(transparent)]
497 + Other(#[from] anyhow::Error),
498 +}
499 +
486500 /// An implementation of a [DID method](https://www.w3.org/TR/did-core/#dfn-did-methods).
487501 ///
488502 /// Depends on the [DIDResolver][] trait.
489503 /// Also includes functionality to [generate][DIDMethod::generate] DIDs.
@@ -504,35 +518,38 @@
504518 None
505519 }
506520
507521 /// Retrieve a DID from a DID method transaction
508- fn did_from_transaction(&self, _tx: DIDMethodTransaction) -> AResult<String> {
509- bail!("DID from transaction not implemented for DID Method");
522 + fn did_from_transaction(&self, _tx: DIDMethodTransaction) -> Result<String, DIDMethodError> {
523 + Err(DIDMethodError::NotImplemented("DID from transaction"))
510524 }
511525
512526 /// Submit a DID transaction
513- async fn submit_transaction(&self, _tx: DIDMethodTransaction) -> AResult<Value> {
514- bail!("Transaction submission not implemented for DID Method");
527 + async fn submit_transaction(&self, _tx: DIDMethodTransaction) -> Result<Value, DIDMethodError> {
528 + Err(DIDMethodError::NotImplemented("Transaction submission"))
515529 }
516530
517531 /// Create a DID
518- fn create(&self, _create: DIDCreate) -> AResult<DIDMethodTransaction> {
519- bail!("Create operation not implemented for DID Method");
532 + fn create(&self, _create: DIDCreate) -> Result<DIDMethodTransaction, DIDMethodError> {
533 + Err(DIDMethodError::NotImplemented("Create operation"))
520534 }
521535
522536 /// Update a DID
523- fn update(&self, _update: DIDUpdate) -> AResult<DIDMethodTransaction> {
524- bail!("Update operation not implemented for DID Method");
537 + fn update(&self, _update: DIDUpdate) -> Result<DIDMethodTransaction, DIDMethodError> {
538 + Err(DIDMethodError::NotImplemented("Update operation"))
525539 }
526540
527541 /// Recover a DID
528- fn recover(&self, _recover: DIDRecover) -> AResult<DIDMethodTransaction> {
529- bail!("Recover operation not implemented for DID Method");
542 + fn recover(&self, _recover: DIDRecover) -> Result<DIDMethodTransaction, DIDMethodError> {
543 + Err(DIDMethodError::NotImplemented("Recover operation"))
530544 }
531545
532546 /// Deactivate a DID
533- fn deactivate(&self, _deactivate: DIDDeactivate) -> AResult<DIDMethodTransaction> {
534- bail!("Deactivate operation not implemented for DID Method");
547 + fn deactivate(
548 + &self,
549 + _deactivate: DIDDeactivate,
550 + ) -> Result<DIDMethodTransaction, DIDMethodError> {
551 + Err(DIDMethodError::NotImplemented("Deactivate operation"))
535552 }
536553
537554 /// Upcast the DID method as a DID resolver.
538555 ///

Built with git-ssb-web