Sphereon-Opensource / SSI-SDK

Self Sovereign Identity SDK
Apache License 2.0
61 stars 18 forks source link

feature: make getInstanceOpts from SIOPv2RP fetching from the DB #153

Open cre8 opened 9 months ago

cre8 commented 9 months ago

right now the the instances have to be passed to the constructor and are saved in a read only variable. My current solution is to read the values from the key value store and the pass it to the plugin:

const instanceOpts: IPEXInstanceOptions[] = await rep
    .find({ where: { key: Like('%oid4vp%') } })
    .then((res) =>
      res.map((r) => {
        const content = JSON.parse(r.data).value as IPresentationDefinition;
        return {
          definitionId: content.id,
          definition: content,
        } as IPEXInstanceOptions;
      })
    );

  return [
    new CredentialPlugin(),
    new PresentationExchange({
      stores: new KeyValueStore({
        namespace: 'oid4vp',
        store: new KeyValueTypeORMStoreAdapter({
          dbConnection: agentConfig.datasource,
        }),
      }),
    }),
    new SIOPv2RP({
      defaultOpts: {
        didOpts: {
          checkLinkedDomains: CheckLinkedDomain.IF_PRESENT,
          identifierOpts: {
            identifier,
            kid,
          },
        },
      },
      instanceOpts,
    }),

Would it be possible to implement this call directly into the siopv2RP instance so we don't have to restart it? Or at least make the variable olding the definitions public so we can patch it from outside (maybe via a new version).

Is this already covered on your roadmap? If not I would like to implement it :)

nklomp commented 9 months ago

Yeah, In all honesty the current approach we take needs a bit of an overhaul.

One thing which would be a nice approach is to emit an event from the key value store, which the siop plugin picks up

cre8 commented 9 months ago

In the meantime I am patching the value from outside like:

  setInterval(async () => {
    const rep = agentConfig.datasource.getRepository(KeyValueStoreEntity);
    //TODO: this is not the preferred way since we need to reload the application to get the latest version.
    const instanceOpts: IPEXInstanceOptions[] = await rep
      .find({ where: { key: Like('%oid4vp%') } })
      .then((res) =>
        res.map((r) => {
          const content = JSON.parse(r.data).value as IPresentationDefinition;
          return {
            definitionId: content.id,
            definition: content,
          } as IPEXInstanceOptions;
        })
      );
    //@ts-ignore
    siop.opts.instanceOpts = instanceOpts;
  }, 1500);

Not the best way, but it gets the job done for now

The event approach would be nice. However I think right now veramo was designed that listener can only be registered on the plugin level and not directly in a plugin (could be changed easily of course).

cre8 commented 7 months ago

Btw my posted solution only works when the presentation was not requested yet. Because when it did, the instance is managed in an internal map and therefore the update of instanceOpts is not working. Maybe you can patch the existing entries, but safest way is to restart the whole agent (with the risk of loosing open sessions)