TBD54566975 / web5-kt

Apache License 2.0
7 stars 9 forks source link

[Bug] Cannot update DID documents #310

Open angiejones opened 2 months ago

angiejones commented 2 months ago

Describe the bug There are several reasons why one might need to update a DID document including adding/deleting/updating service endpoints. However, the fields of the DidDocument class are final, and therefore cannot be updated.

To Reproduce:

Create and publish a DID:

var myBearerDid = DidDht.create(keyManager, CreateDidDhtOptions(publish = true))

Try to add a service later:

val serviceToAdd = Service.Builder()
      .id("pfi")
      .type("PFI")
      .serviceEndpoint(listOf("https://example.com/"))
      .build()

// this is immutable so there are no changes that can be made here
myBearerDid.document.service.

Expected behavior:

val serviceToAdd = Service.Builder()
      .id("pfi")
      .type("PFI")
      .serviceEndpoint(listOf("https://example.com/"))
      .build()

// if this were mutable, people could add a new service then republish their doc
myBearerDid.document.service.add(serviceToAdd)
DidDht.publish(keyManager, myBearerDid.document)

Supporting Material This is possible in web5-js:

const myBearerDid = await DidDht.create({ options: { publish: true } });

myBearerDid.document.service = myBearerDid.document.service || [];

// add a service to the DID document
myBearerDid.document.service.push({
  id: 'pfi',
  type: 'PFI',
  serviceEndpoint: 'https://example.com/'
});

// republish the updated DID document
DidDht.publish({did: myBearerDid});
michaelneale commented 2 months ago

@angiejones as a work around:

    val keyManager = InMemoryKeyManager()
    var myBearerDid = DidDht.create(keyManager, CreateDidDhtOptions(publish = true))

    val existingBearerDid: BearerDid = myBearerDid

    val serviceToAdd = Service.Builder()
      .id("pfi")
      .type("PFI")
      .serviceEndpoint(listOf("https://example.com/"))
      .build()

    val updatedServices = existingBearerDid.document.service?.toMutableList() ?: mutableListOf()
    updatedServices.add(serviceToAdd)

    print(updatedServices)

    val updatedDidDocument = DidDocument(
      id = existingBearerDid.document.id,
      context = existingBearerDid.document.context,
      controller = existingBearerDid.document.controller,
      verificationMethod = existingBearerDid.document.verificationMethod,
      authentication = existingBearerDid.document.authentication,
      assertionMethod = existingBearerDid.document.assertionMethod,
      keyAgreement = existingBearerDid.document.keyAgreement,
      capabilityInvocation = existingBearerDid.document.capabilityInvocation,
      capabilityDelegation = existingBearerDid.document.capabilityDelegation,
      service = updatedServices
    )

    val updatedBearerDid = BearerDid(
      uri = existingBearerDid.uri,
      did = existingBearerDid.did,
      keyManager = existingBearerDid.keyManager,
      document = updatedDidDocument
    )

    DidDht.publish(existingBearerDid.keyManager, updatedDidDocument)

works - I am not sure of idiomatic mods to make kotlin allow mutation but need to look into it

michaelneale commented 2 months ago

my attempt at an idiomatic change: https://github.com/TBD54566975/web5-kt/pull/311