@dxos/client-services 0.1.13 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +2747 -0
- package/dist/lib/browser/index.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -0
- package/dist/lib/node/index.cjs +2823 -0
- package/dist/lib/node/index.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -0
- package/dist/{src → types/src}/index.d.ts +0 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/deprecated/index.d.ts +0 -0
- package/dist/types/src/packlets/deprecated/index.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/deprecated/invitations.d.ts +4 -4
- package/dist/types/src/packlets/deprecated/invitations.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/deprecated/profile.d.ts +0 -0
- package/dist/types/src/packlets/deprecated/profile.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/deprecated/space.d.ts +0 -0
- package/dist/types/src/packlets/deprecated/space.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/deprecated/system.d.ts +0 -0
- package/dist/types/src/packlets/deprecated/system.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/deprecated/tracing.d.ts +0 -0
- package/dist/types/src/packlets/deprecated/tracing.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/devtools/devtools.d.ts +1 -1
- package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/devtools/feeds.d.ts +0 -0
- package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/devtools/index.d.ts +0 -0
- package/dist/types/src/packlets/devtools/index.d.ts.map +1 -0
- package/dist/types/src/packlets/devtools/keys.d.ts +7 -0
- package/dist/types/src/packlets/devtools/keys.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/devtools/network.d.ts +0 -0
- package/dist/types/src/packlets/devtools/network.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/devtools/spaces.d.ts +0 -0
- package/dist/types/src/packlets/devtools/spaces.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/identity/authenticator.d.ts +0 -0
- package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/identity/authenticator.test.d.ts +0 -0
- package/dist/types/src/packlets/identity/authenticator.test.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/identity/devices-service-impl.d.ts +0 -0
- package/dist/types/src/packlets/identity/devices-service-impl.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/identity/identity-manager.d.ts +3 -3
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/identity/identity-manager.test.d.ts +0 -0
- package/dist/types/src/packlets/identity/identity-manager.test.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/identity/identity.d.ts +2 -2
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/identity/identity.test.d.ts +0 -0
- package/dist/types/src/packlets/identity/identity.test.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/identity/index.d.ts +0 -0
- package/dist/types/src/packlets/identity/index.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/encoder.d.ts +0 -0
- package/dist/types/src/packlets/invitations/encoder.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/encoder.test.d.ts +0 -0
- package/dist/types/src/packlets/invitations/encoder.test.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/halo-invitations-handler.d.ts +0 -0
- package/dist/types/src/packlets/invitations/halo-invitations-handler.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/halo-invitations-handler.test.d.ts +0 -0
- package/dist/types/src/packlets/invitations/halo-invitations-handler.test.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/halo-invitations-proxy.d.ts +0 -0
- package/dist/types/src/packlets/invitations/halo-invitations-proxy.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/halo-invitations-service.d.ts +0 -0
- package/dist/types/src/packlets/invitations/halo-invitations-service.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/halo-invitations-service.test.d.ts +0 -0
- package/dist/types/src/packlets/invitations/halo-invitations-service.test.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/index.d.ts +0 -0
- package/dist/types/src/packlets/invitations/index.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/invitations-handler.d.ts +10 -10
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/invitations-proxy.d.ts +0 -0
- package/dist/types/src/packlets/invitations/invitations-proxy.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/invitations-service.d.ts +0 -0
- package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/invitations.d.ts +0 -0
- package/dist/types/src/packlets/invitations/invitations.d.ts.map +1 -0
- package/dist/types/src/packlets/invitations/rpc-extension.d.ts +17 -0
- package/dist/types/src/packlets/invitations/rpc-extension.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/space-invitations-handler.d.ts +3 -1
- package/dist/types/src/packlets/invitations/space-invitations-handler.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/space-invitations-handler.test.d.ts +0 -0
- package/dist/types/src/packlets/invitations/space-invitations-handler.test.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/space-invitations-proxy.d.ts +0 -0
- package/dist/types/src/packlets/invitations/space-invitations-proxy.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/space-invitations-service.d.ts +0 -0
- package/dist/types/src/packlets/invitations/space-invitations-service.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/invitations/space-invitations-service.test.d.ts +0 -0
- package/dist/types/src/packlets/invitations/space-invitations-service.test.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/services/index.d.ts +0 -0
- package/dist/types/src/packlets/services/index.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/services/service-context.d.ts +0 -0
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/services/service-definitions.d.ts +1 -1
- package/dist/types/src/packlets/services/service-definitions.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/services/service-host.d.ts +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/services/service-proxy.d.ts +0 -0
- package/dist/types/src/packlets/services/service-proxy.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/services/service-registry.d.ts +0 -0
- package/dist/types/src/packlets/services/service-registry.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/services/service-registry.test.d.ts +0 -0
- package/dist/types/src/packlets/services/service-registry.test.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/services/signer.d.ts +0 -0
- package/dist/types/src/packlets/services/signer.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/spaces/index.d.ts +0 -0
- package/dist/types/src/packlets/spaces/index.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/spaces/spaces-service.d.ts +0 -0
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/storage/index.d.ts +0 -0
- package/dist/types/src/packlets/storage/index.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/storage/storage.d.ts +1 -1
- package/dist/types/src/packlets/storage/storage.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/testing/index.d.ts +0 -0
- package/dist/types/src/packlets/testing/index.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/testing/test-builder.d.ts +0 -0
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/vault/iframe-runtime.d.ts +1 -1
- package/dist/types/src/packlets/vault/iframe-runtime.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/vault/index.d.ts +0 -0
- package/dist/types/src/packlets/vault/index.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/vault/services.d.ts +2 -2
- package/dist/types/src/packlets/vault/services.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/vault/worker-runtime.d.ts +1 -1
- package/dist/types/src/packlets/vault/worker-runtime.d.ts.map +1 -0
- package/dist/{src → types/src}/packlets/vault/worker-session.d.ts +1 -1
- package/dist/types/src/packlets/vault/worker-session.d.ts.map +1 -0
- package/package.json +32 -30
- package/src/packlets/devtools/devtools.ts +2 -1
- package/src/packlets/devtools/keys.ts +19 -0
- package/src/packlets/identity/authenticator.test.ts +5 -8
- package/src/packlets/identity/identity-manager.test.ts +5 -5
- package/src/packlets/identity/identity-manager.ts +6 -4
- package/src/packlets/identity/identity.test.ts +4 -4
- package/src/packlets/identity/identity.ts +1 -1
- package/src/packlets/invitations/encoder.test.ts +3 -2
- package/src/packlets/invitations/halo-invitations-handler.test.ts +5 -5
- package/src/packlets/invitations/halo-invitations-handler.ts +232 -135
- package/src/packlets/invitations/halo-invitations-service.test.ts +4 -4
- package/src/packlets/invitations/invitations-handler.ts +9 -9
- package/src/packlets/invitations/invitations-proxy.ts +1 -1
- package/src/packlets/invitations/invitations-service.ts +1 -1
- package/src/packlets/invitations/invitations.ts +1 -1
- package/src/packlets/invitations/rpc-extension.ts +56 -0
- package/src/packlets/invitations/space-invitations-handler.test.ts +15 -9
- package/src/packlets/invitations/space-invitations-handler.ts +293 -152
- package/src/packlets/invitations/space-invitations-service.test.ts +5 -5
- package/src/packlets/invitations/space-invitations-service.ts +1 -1
- package/src/packlets/services/service-context.ts +6 -1
- package/src/packlets/services/service-registry.test.ts +4 -3
- package/src/packlets/vault/worker-session.ts +8 -3
- package/testing.d.ts +1 -1
- package/testing.js +1 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -27
- package/dist/src/index.js.map +0 -1
- package/dist/src/packlets/deprecated/index.d.ts.map +0 -1
- package/dist/src/packlets/deprecated/index.js +0 -24
- package/dist/src/packlets/deprecated/index.js.map +0 -1
- package/dist/src/packlets/deprecated/invitations.d.ts.map +0 -1
- package/dist/src/packlets/deprecated/invitations.js +0 -12
- package/dist/src/packlets/deprecated/invitations.js.map +0 -1
- package/dist/src/packlets/deprecated/profile.d.ts.map +0 -1
- package/dist/src/packlets/deprecated/profile.js +0 -60
- package/dist/src/packlets/deprecated/profile.js.map +0 -1
- package/dist/src/packlets/deprecated/space.d.ts.map +0 -1
- package/dist/src/packlets/deprecated/space.js +0 -209
- package/dist/src/packlets/deprecated/space.js.map +0 -1
- package/dist/src/packlets/deprecated/system.d.ts.map +0 -1
- package/dist/src/packlets/deprecated/system.js +0 -33
- package/dist/src/packlets/deprecated/system.js.map +0 -1
- package/dist/src/packlets/deprecated/tracing.d.ts.map +0 -1
- package/dist/src/packlets/deprecated/tracing.js +0 -22
- package/dist/src/packlets/deprecated/tracing.js.map +0 -1
- package/dist/src/packlets/devtools/devtools.d.ts.map +0 -1
- package/dist/src/packlets/devtools/devtools.js +0 -88
- package/dist/src/packlets/devtools/devtools.js.map +0 -1
- package/dist/src/packlets/devtools/feeds.d.ts.map +0 -1
- package/dist/src/packlets/devtools/feeds.js +0 -77
- package/dist/src/packlets/devtools/feeds.js.map +0 -1
- package/dist/src/packlets/devtools/index.d.ts.map +0 -1
- package/dist/src/packlets/devtools/index.js +0 -24
- package/dist/src/packlets/devtools/index.js.map +0 -1
- package/dist/src/packlets/devtools/network.d.ts.map +0 -1
- package/dist/src/packlets/devtools/network.js +0 -79
- package/dist/src/packlets/devtools/network.js.map +0 -1
- package/dist/src/packlets/devtools/spaces.d.ts.map +0 -1
- package/dist/src/packlets/devtools/spaces.js +0 -39
- package/dist/src/packlets/devtools/spaces.js.map +0 -1
- package/dist/src/packlets/identity/authenticator.d.ts.map +0 -1
- package/dist/src/packlets/identity/authenticator.js +0 -40
- package/dist/src/packlets/identity/authenticator.js.map +0 -1
- package/dist/src/packlets/identity/authenticator.test.d.ts.map +0 -1
- package/dist/src/packlets/identity/authenticator.test.js +0 -32
- package/dist/src/packlets/identity/authenticator.test.js.map +0 -1
- package/dist/src/packlets/identity/devices-service-impl.d.ts.map +0 -1
- package/dist/src/packlets/identity/devices-service-impl.js +0 -47
- package/dist/src/packlets/identity/devices-service-impl.js.map +0 -1
- package/dist/src/packlets/identity/identity-manager.d.ts.map +0 -1
- package/dist/src/packlets/identity/identity-manager.js +0 -156
- package/dist/src/packlets/identity/identity-manager.js.map +0 -1
- package/dist/src/packlets/identity/identity-manager.test.d.ts.map +0 -1
- package/dist/src/packlets/identity/identity-manager.test.js +0 -88
- package/dist/src/packlets/identity/identity-manager.test.js.map +0 -1
- package/dist/src/packlets/identity/identity.d.ts.map +0 -1
- package/dist/src/packlets/identity/identity.js +0 -133
- package/dist/src/packlets/identity/identity.js.map +0 -1
- package/dist/src/packlets/identity/identity.test.d.ts.map +0 -1
- package/dist/src/packlets/identity/identity.test.js +0 -257
- package/dist/src/packlets/identity/identity.test.js.map +0 -1
- package/dist/src/packlets/identity/index.d.ts.map +0 -1
- package/dist/src/packlets/identity/index.js +0 -23
- package/dist/src/packlets/identity/index.js.map +0 -1
- package/dist/src/packlets/invitations/encoder.d.ts.map +0 -1
- package/dist/src/packlets/invitations/encoder.js +0 -27
- package/dist/src/packlets/invitations/encoder.js.map +0 -1
- package/dist/src/packlets/invitations/encoder.test.d.ts.map +0 -1
- package/dist/src/packlets/invitations/encoder.test.js +0 -19
- package/dist/src/packlets/invitations/encoder.test.js.map +0 -1
- package/dist/src/packlets/invitations/halo-invitations-handler.d.ts.map +0 -1
- package/dist/src/packlets/invitations/halo-invitations-handler.js +0 -231
- package/dist/src/packlets/invitations/halo-invitations-handler.js.map +0 -1
- package/dist/src/packlets/invitations/halo-invitations-handler.test.d.ts.map +0 -1
- package/dist/src/packlets/invitations/halo-invitations-handler.test.js +0 -69
- package/dist/src/packlets/invitations/halo-invitations-handler.test.js.map +0 -1
- package/dist/src/packlets/invitations/halo-invitations-proxy.d.ts.map +0 -1
- package/dist/src/packlets/invitations/halo-invitations-proxy.js +0 -17
- package/dist/src/packlets/invitations/halo-invitations-proxy.js.map +0 -1
- package/dist/src/packlets/invitations/halo-invitations-service.d.ts.map +0 -1
- package/dist/src/packlets/invitations/halo-invitations-service.js +0 -20
- package/dist/src/packlets/invitations/halo-invitations-service.js.map +0 -1
- package/dist/src/packlets/invitations/halo-invitations-service.test.d.ts.map +0 -1
- package/dist/src/packlets/invitations/halo-invitations-service.test.js +0 -83
- package/dist/src/packlets/invitations/halo-invitations-service.test.js.map +0 -1
- package/dist/src/packlets/invitations/index.d.ts.map +0 -1
- package/dist/src/packlets/invitations/index.js +0 -31
- package/dist/src/packlets/invitations/index.js.map +0 -1
- package/dist/src/packlets/invitations/invitations-handler.d.ts.map +0 -1
- package/dist/src/packlets/invitations/invitations-handler.js +0 -18
- package/dist/src/packlets/invitations/invitations-handler.js.map +0 -1
- package/dist/src/packlets/invitations/invitations-proxy.d.ts.map +0 -1
- package/dist/src/packlets/invitations/invitations-proxy.js +0 -121
- package/dist/src/packlets/invitations/invitations-proxy.js.map +0 -1
- package/dist/src/packlets/invitations/invitations-service.d.ts.map +0 -1
- package/dist/src/packlets/invitations/invitations-service.js +0 -174
- package/dist/src/packlets/invitations/invitations-service.js.map +0 -1
- package/dist/src/packlets/invitations/invitations.d.ts.map +0 -1
- package/dist/src/packlets/invitations/invitations.js +0 -59
- package/dist/src/packlets/invitations/invitations.js.map +0 -1
- package/dist/src/packlets/invitations/space-invitations-handler.d.ts.map +0 -1
- package/dist/src/packlets/invitations/space-invitations-handler.js +0 -239
- package/dist/src/packlets/invitations/space-invitations-handler.js.map +0 -1
- package/dist/src/packlets/invitations/space-invitations-handler.test.d.ts.map +0 -1
- package/dist/src/packlets/invitations/space-invitations-handler.test.js +0 -131
- package/dist/src/packlets/invitations/space-invitations-handler.test.js.map +0 -1
- package/dist/src/packlets/invitations/space-invitations-proxy.d.ts.map +0 -1
- package/dist/src/packlets/invitations/space-invitations-proxy.js +0 -17
- package/dist/src/packlets/invitations/space-invitations-proxy.js.map +0 -1
- package/dist/src/packlets/invitations/space-invitations-service.d.ts.map +0 -1
- package/dist/src/packlets/invitations/space-invitations-service.js +0 -31
- package/dist/src/packlets/invitations/space-invitations-service.js.map +0 -1
- package/dist/src/packlets/invitations/space-invitations-service.test.d.ts.map +0 -1
- package/dist/src/packlets/invitations/space-invitations-service.test.js +0 -100
- package/dist/src/packlets/invitations/space-invitations-service.test.js.map +0 -1
- package/dist/src/packlets/services/index.d.ts.map +0 -1
- package/dist/src/packlets/services/index.js +0 -26
- package/dist/src/packlets/services/index.js.map +0 -1
- package/dist/src/packlets/services/service-context.d.ts.map +0 -1
- package/dist/src/packlets/services/service-context.js +0 -103
- package/dist/src/packlets/services/service-context.js.map +0 -1
- package/dist/src/packlets/services/service-definitions.d.ts.map +0 -1
- package/dist/src/packlets/services/service-definitions.js +0 -25
- package/dist/src/packlets/services/service-definitions.js.map +0 -1
- package/dist/src/packlets/services/service-host.d.ts.map +0 -1
- package/dist/src/packlets/services/service-host.js +0 -88
- package/dist/src/packlets/services/service-host.js.map +0 -1
- package/dist/src/packlets/services/service-proxy.d.ts.map +0 -1
- package/dist/src/packlets/services/service-proxy.js +0 -48
- package/dist/src/packlets/services/service-proxy.js.map +0 -1
- package/dist/src/packlets/services/service-registry.d.ts.map +0 -1
- package/dist/src/packlets/services/service-registry.js +0 -24
- package/dist/src/packlets/services/service-registry.js.map +0 -1
- package/dist/src/packlets/services/service-registry.test.d.ts.map +0 -1
- package/dist/src/packlets/services/service-registry.test.js +0 -75
- package/dist/src/packlets/services/service-registry.test.js.map +0 -1
- package/dist/src/packlets/services/signer.d.ts.map +0 -1
- package/dist/src/packlets/services/signer.js +0 -6
- package/dist/src/packlets/services/signer.js.map +0 -1
- package/dist/src/packlets/spaces/index.d.ts.map +0 -1
- package/dist/src/packlets/spaces/index.js +0 -21
- package/dist/src/packlets/spaces/index.js.map +0 -1
- package/dist/src/packlets/spaces/spaces-service.d.ts.map +0 -1
- package/dist/src/packlets/spaces/spaces-service.js +0 -22
- package/dist/src/packlets/spaces/spaces-service.js.map +0 -1
- package/dist/src/packlets/storage/index.d.ts.map +0 -1
- package/dist/src/packlets/storage/index.js +0 -21
- package/dist/src/packlets/storage/index.js.map +0 -1
- package/dist/src/packlets/storage/storage.d.ts.map +0 -1
- package/dist/src/packlets/storage/storage.js +0 -89
- package/dist/src/packlets/storage/storage.js.map +0 -1
- package/dist/src/packlets/testing/index.d.ts.map +0 -1
- package/dist/src/packlets/testing/index.js +0 -21
- package/dist/src/packlets/testing/index.js.map +0 -1
- package/dist/src/packlets/testing/test-builder.d.ts.map +0 -1
- package/dist/src/packlets/testing/test-builder.js +0 -66
- package/dist/src/packlets/testing/test-builder.js.map +0 -1
- package/dist/src/packlets/vault/iframe-runtime.d.ts.map +0 -1
- package/dist/src/packlets/vault/iframe-runtime.js +0 -46
- package/dist/src/packlets/vault/iframe-runtime.js.map +0 -1
- package/dist/src/packlets/vault/index.d.ts.map +0 -1
- package/dist/src/packlets/vault/index.js +0 -23
- package/dist/src/packlets/vault/index.js.map +0 -1
- package/dist/src/packlets/vault/services.d.ts.map +0 -1
- package/dist/src/packlets/vault/services.js +0 -15
- package/dist/src/packlets/vault/services.js.map +0 -1
- package/dist/src/packlets/vault/worker-runtime.d.ts.map +0 -1
- package/dist/src/packlets/vault/worker-runtime.js +0 -99
- package/dist/src/packlets/vault/worker-runtime.js.map +0 -1
- package/dist/src/packlets/vault/worker-session.d.ts.map +0 -1
- package/dist/src/packlets/vault/worker-session.js +0 -106
- package/dist/src/packlets/vault/worker-session.js.map +0 -1
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import assert from 'assert';
|
|
6
5
|
import { expect } from 'chai';
|
|
6
|
+
import assert from 'node:assert';
|
|
7
7
|
|
|
8
8
|
import { asyncChain, Trigger } from '@dxos/async';
|
|
9
9
|
import { raise } from '@dxos/debug';
|
|
10
10
|
import { PublicKey } from '@dxos/keys';
|
|
11
11
|
import { ObjectModel } from '@dxos/object-model';
|
|
12
12
|
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
13
|
-
import { afterTest } from '@dxos/
|
|
13
|
+
import { describe, test, afterTest } from '@dxos/test';
|
|
14
14
|
|
|
15
15
|
import { ServiceContext } from '../services';
|
|
16
16
|
import { createIdentity, createPeers, syncItems } from '../testing';
|
|
@@ -20,8 +20,8 @@ const closeAfterTest = async (peer: ServiceContext) => {
|
|
|
20
20
|
return peer;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
describe('services/space-invitations-handler',
|
|
24
|
-
|
|
23
|
+
describe('services/space-invitations-handler', () => {
|
|
24
|
+
test('genesis', async () => {
|
|
25
25
|
const [peer] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(1));
|
|
26
26
|
|
|
27
27
|
const space = await peer.spaceManager!.createSpace();
|
|
@@ -30,13 +30,13 @@ describe('services/space-invitations-handler', function () {
|
|
|
30
30
|
await space.close();
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
test('genesis with database mutations', async () => {
|
|
34
34
|
const [peer] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(1));
|
|
35
35
|
const space = await peer.spaceManager!.createSpace();
|
|
36
36
|
|
|
37
37
|
{
|
|
38
38
|
const item = await space.database!.createItem<ObjectModel>({ type: 'test' });
|
|
39
|
-
|
|
39
|
+
await item.model.set('name', 'test');
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
{
|
|
@@ -47,12 +47,13 @@ describe('services/space-invitations-handler', function () {
|
|
|
47
47
|
await space.close();
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
test('creates and accepts invitation with retry', async () => {
|
|
51
51
|
const [host, guest] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(2));
|
|
52
52
|
|
|
53
53
|
const complete1 = new Trigger<PublicKey>();
|
|
54
54
|
const complete2 = new Trigger<PublicKey>();
|
|
55
55
|
|
|
56
|
+
let attempt = 0;
|
|
56
57
|
const authenticationCode = new Trigger<string>();
|
|
57
58
|
|
|
58
59
|
const space1 = await host.spaceManager!.createSpace();
|
|
@@ -66,7 +67,12 @@ describe('services/space-invitations-handler', function () {
|
|
|
66
67
|
expect(invitation1.swarmKey).to.eq(invitation2.swarmKey);
|
|
67
68
|
},
|
|
68
69
|
onAuthenticating: async () => {
|
|
69
|
-
|
|
70
|
+
if (attempt++ === 0) {
|
|
71
|
+
// Force retry.
|
|
72
|
+
await observable2.authenticate('000000');
|
|
73
|
+
} else {
|
|
74
|
+
await observable2.authenticate(await authenticationCode.wait());
|
|
75
|
+
}
|
|
70
76
|
},
|
|
71
77
|
onSuccess: (invitation: Invitation) => {
|
|
72
78
|
complete2.wake(invitation.spaceKey!);
|
|
@@ -104,7 +110,7 @@ describe('services/space-invitations-handler', function () {
|
|
|
104
110
|
}
|
|
105
111
|
});
|
|
106
112
|
|
|
107
|
-
|
|
113
|
+
test('cancels invitation', async () => {
|
|
108
114
|
const [host, guest] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(2));
|
|
109
115
|
|
|
110
116
|
const cancelled = new Trigger();
|
|
@@ -2,30 +2,42 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import assert from 'assert';
|
|
5
|
+
import assert from 'node:assert';
|
|
6
6
|
|
|
7
|
-
import { sleep, Trigger } from '@dxos/async';
|
|
8
|
-
import {
|
|
7
|
+
import { scheduleTask, sleep, Trigger } from '@dxos/async';
|
|
8
|
+
import { Context } from '@dxos/context';
|
|
9
|
+
import { createAdmissionCredentials, generatePasscode, getCredentialAssertion } from '@dxos/credentials';
|
|
9
10
|
import { SigningContext, Space, SpaceManager } from '@dxos/echo-db';
|
|
10
11
|
import { writeMessages } from '@dxos/feed-store';
|
|
12
|
+
import { Keyring } from '@dxos/keyring';
|
|
11
13
|
import { PublicKey } from '@dxos/keys';
|
|
12
14
|
import { log } from '@dxos/log';
|
|
13
|
-
import {
|
|
14
|
-
import { createRpcPlugin, RpcPlugin } from '@dxos/protocol-plugin-rpc';
|
|
15
|
+
import { createTeleportProtocolFactory, NetworkManager, StarTopology, SwarmConnection } from '@dxos/network-manager';
|
|
15
16
|
import { schema } from '@dxos/protocols';
|
|
16
17
|
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
17
18
|
import { ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
18
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
AuthenticationRequest,
|
|
21
|
+
AuthenticationResponse,
|
|
22
|
+
Introduction,
|
|
23
|
+
SpaceAdmissionCredentials,
|
|
24
|
+
SpaceAdmissionRequest,
|
|
25
|
+
SpaceHostService
|
|
26
|
+
} from '@dxos/protocols/proto/dxos/halo/invitations';
|
|
27
|
+
import { ExtensionContext } from '@dxos/teleport';
|
|
19
28
|
|
|
20
29
|
import {
|
|
21
30
|
AuthenticatingInvitationProvider,
|
|
31
|
+
AUTHENTICATION_CODE_LENGTH,
|
|
22
32
|
CancellableInvitationObservable,
|
|
23
33
|
InvitationObservableProvider,
|
|
24
|
-
AUTHENTICATION_CODE_LENGTH,
|
|
25
34
|
INVITATION_TIMEOUT,
|
|
26
35
|
ON_CLOSE_DELAY
|
|
27
36
|
} from './invitations';
|
|
28
37
|
import { AbstractInvitationsHandler, InvitationsOptions } from './invitations-handler';
|
|
38
|
+
import { RpcExtension } from './rpc-extension';
|
|
39
|
+
|
|
40
|
+
const MAX_OTP_ATTEMPTS = 3;
|
|
29
41
|
|
|
30
42
|
/**
|
|
31
43
|
* Handles the life-cycle of Space invitations between peers.
|
|
@@ -35,7 +47,8 @@ export class SpaceInvitationsHandler extends AbstractInvitationsHandler<Space> {
|
|
|
35
47
|
constructor(
|
|
36
48
|
networkManager: NetworkManager,
|
|
37
49
|
private readonly _spaceManager: SpaceManager,
|
|
38
|
-
private readonly _signingContext: SigningContext
|
|
50
|
+
private readonly _signingContext: SigningContext,
|
|
51
|
+
private readonly _keyring: Keyring
|
|
39
52
|
) {
|
|
40
53
|
super(networkManager);
|
|
41
54
|
}
|
|
@@ -49,6 +62,7 @@ export class SpaceInvitationsHandler extends AbstractInvitationsHandler<Space> {
|
|
|
49
62
|
assert(type !== Invitation.Type.OFFLINE);
|
|
50
63
|
assert(space);
|
|
51
64
|
|
|
65
|
+
// TODO(dmaretskyi): Add invitation kind: halo/space.
|
|
52
66
|
const invitation: Invitation = {
|
|
53
67
|
type,
|
|
54
68
|
invitationId: PublicKey.random().toHex(),
|
|
@@ -57,115 +71,132 @@ export class SpaceInvitationsHandler extends AbstractInvitationsHandler<Space> {
|
|
|
57
71
|
authenticationCode: generatePasscode(AUTHENTICATION_CODE_LENGTH)
|
|
58
72
|
};
|
|
59
73
|
|
|
74
|
+
const ctx = new Context({
|
|
75
|
+
onError: (err) => {
|
|
76
|
+
void ctx.dispose();
|
|
77
|
+
observable.callback.onError(err);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
60
81
|
// TODO(burdon): Stop anything pending.
|
|
61
82
|
const observable = new InvitationObservableProvider(async () => {
|
|
62
83
|
await swarmConnection?.close();
|
|
63
84
|
});
|
|
64
85
|
|
|
65
86
|
let authenticationCode: string;
|
|
87
|
+
let authenticationRetry = 0;
|
|
88
|
+
|
|
66
89
|
const complete = new Trigger<PublicKey>();
|
|
67
|
-
|
|
90
|
+
|
|
91
|
+
// Called for every connecting peer.
|
|
92
|
+
const createExtension = (): HostSpaceInvitationExtension => {
|
|
68
93
|
let guestProfile: ProfileDocument | undefined;
|
|
69
94
|
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
log('responding with admission offer', {
|
|
78
|
-
guestProfile: profile,
|
|
79
|
-
host: this._signingContext.deviceKey,
|
|
80
|
-
spaceKey: space.key
|
|
81
|
-
});
|
|
95
|
+
const hostInvitationExtension = new HostSpaceInvitationExtension({
|
|
96
|
+
introduce: async ({ profile }) => {
|
|
97
|
+
log('guest introduced itself', {
|
|
98
|
+
guestProfile: profile,
|
|
99
|
+
host: this._signingContext.deviceKey,
|
|
100
|
+
spaceKey: space.key
|
|
101
|
+
});
|
|
82
102
|
|
|
83
|
-
|
|
103
|
+
guestProfile = profile;
|
|
84
104
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
spaceKey: space.key,
|
|
90
|
-
genesisFeedKey: space.genesisFeedKey
|
|
91
|
-
};
|
|
92
|
-
},
|
|
105
|
+
// TODO(burdon): Is this the right place to set this state?
|
|
106
|
+
// TODO(dmaretskyi): Should we expose guest's profile in this callback?
|
|
107
|
+
observable.callback.onAuthenticating?.(invitation);
|
|
108
|
+
},
|
|
93
109
|
|
|
94
|
-
|
|
95
|
-
|
|
110
|
+
authenticate: async ({ authenticationCode: code }) => {
|
|
111
|
+
log('received authentication request', { authenticationCode: code });
|
|
112
|
+
let status = AuthenticationResponse.Status.OK;
|
|
113
|
+
if (invitation.authenticationCode) {
|
|
114
|
+
if (authenticationRetry++ > MAX_OTP_ATTEMPTS) {
|
|
115
|
+
status = AuthenticationResponse.Status.INVALID_OPT_ATTEMPTS;
|
|
116
|
+
} else if (code !== invitation.authenticationCode) {
|
|
117
|
+
status = AuthenticationResponse.Status.INVALID_OTP;
|
|
118
|
+
} else {
|
|
96
119
|
authenticationCode = code;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
presentAdmissionCredentials: async ({ identityKey, deviceKey, controlFeedKey, dataFeedKey }) => {
|
|
100
|
-
try {
|
|
101
|
-
// Check authenticated.
|
|
102
|
-
if (invitation.type === undefined || invitation.type === Invitation.Type.INTERACTIVE) {
|
|
103
|
-
if (
|
|
104
|
-
invitation.authenticationCode === undefined ||
|
|
105
|
-
authenticationCode !== invitation.authenticationCode
|
|
106
|
-
) {
|
|
107
|
-
invitation.authenticationCode &&
|
|
108
|
-
log.error('bad auth code', { code: authenticationCode, expected: invitation.authenticationCode });
|
|
109
|
-
throw new Error('authentication code not set');
|
|
110
|
-
}
|
|
111
|
-
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
112
122
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
controlFeedKey,
|
|
123
|
-
dataFeedKey,
|
|
124
|
-
guestProfile
|
|
125
|
-
)
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
// Updating credentials complete.
|
|
129
|
-
complete.wake(deviceKey);
|
|
130
|
-
} catch (err) {
|
|
131
|
-
// TODO(burdon): Generic RPC callback to report error to client.
|
|
132
|
-
observable.callback.onError(err);
|
|
133
|
-
throw err; // Propagate error to guest.
|
|
123
|
+
return { status };
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
requestAdmission: async ({ identityKey, deviceKey, controlFeedKey, dataFeedKey }) => {
|
|
127
|
+
try {
|
|
128
|
+
// Check authenticated.
|
|
129
|
+
if (invitation.type !== Invitation.Type.INTERACTIVE_TESTING) {
|
|
130
|
+
if (invitation.authenticationCode === undefined || invitation.authenticationCode !== authenticationCode) {
|
|
131
|
+
throw new Error(`invalid authentication code: ${authenticationCode}`);
|
|
134
132
|
}
|
|
135
133
|
}
|
|
134
|
+
|
|
135
|
+
log('writing guest credentials', { host: this._signingContext.deviceKey, guest: deviceKey });
|
|
136
|
+
// TODO(burdon): Check if already admitted.
|
|
137
|
+
const credentials = await createAdmissionCredentials(
|
|
138
|
+
this._signingContext.credentialSigner,
|
|
139
|
+
identityKey,
|
|
140
|
+
deviceKey,
|
|
141
|
+
space.key,
|
|
142
|
+
controlFeedKey,
|
|
143
|
+
dataFeedKey,
|
|
144
|
+
space.genesisFeedKey,
|
|
145
|
+
guestProfile
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
// TODO(dmaretskyi): Refactor.
|
|
149
|
+
assert(credentials[0]['@type'] === 'dxos.echo.feed.CredentialsMessage');
|
|
150
|
+
const spaceMemberCredential = credentials[0].credential;
|
|
151
|
+
assert(getCredentialAssertion(spaceMemberCredential)['@type'] === 'dxos.halo.credentials.SpaceMember');
|
|
152
|
+
|
|
153
|
+
await writeMessages(space.controlPipeline.writer, credentials);
|
|
154
|
+
|
|
155
|
+
// Updating credentials complete.
|
|
156
|
+
complete.wake(deviceKey);
|
|
157
|
+
|
|
158
|
+
return { credential: spaceMemberCredential };
|
|
159
|
+
} catch (err) {
|
|
160
|
+
// TODO(burdon): Generic RPC callback to report error to client.
|
|
161
|
+
observable.callback.onError(err);
|
|
162
|
+
throw err; // Propagate error to guest.
|
|
136
163
|
}
|
|
137
164
|
},
|
|
138
|
-
port
|
|
139
|
-
});
|
|
140
165
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
166
|
+
onOpen: () => {
|
|
167
|
+
scheduleTask(ctx, async () => {
|
|
168
|
+
try {
|
|
169
|
+
log('connected', { host: this._signingContext.deviceKey });
|
|
170
|
+
observable.callback.onConnected?.(invitation);
|
|
171
|
+
const deviceKey = await complete.wait({ timeout });
|
|
172
|
+
log('admitted guest', { host: this._signingContext.deviceKey, guest: deviceKey });
|
|
173
|
+
observable.callback.onSuccess(invitation);
|
|
174
|
+
} catch (err) {
|
|
175
|
+
if (!observable.cancelled) {
|
|
176
|
+
log.error('failed', err);
|
|
177
|
+
observable.callback.onError(err);
|
|
178
|
+
}
|
|
179
|
+
} finally {
|
|
180
|
+
await sleep(ON_CLOSE_DELAY);
|
|
181
|
+
await ctx.dispose();
|
|
182
|
+
}
|
|
183
|
+
});
|
|
152
184
|
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
await swarmConnection!.close();
|
|
157
|
-
}
|
|
158
|
-
});
|
|
185
|
+
});
|
|
186
|
+
return hostInvitationExtension;
|
|
187
|
+
};
|
|
159
188
|
|
|
160
|
-
|
|
189
|
+
scheduleTask(ctx, async () => {
|
|
161
190
|
const topic = invitation.swarmKey!;
|
|
162
|
-
const
|
|
163
|
-
swarmConnection = await this._networkManager.joinSwarm({
|
|
191
|
+
const swarmConnection = await this._networkManager.joinSwarm({
|
|
164
192
|
topic,
|
|
165
193
|
peerId: topic,
|
|
166
|
-
|
|
194
|
+
protocolProvider: createTeleportProtocolFactory(async (teleport) => {
|
|
195
|
+
teleport.addExtension('dxos.halo.invitations', createExtension());
|
|
196
|
+
}),
|
|
167
197
|
topology: new StarTopology(topic)
|
|
168
198
|
});
|
|
199
|
+
ctx.onDispose(() => swarmConnection.close());
|
|
169
200
|
|
|
170
201
|
observable.callback.onConnecting?.(invitation);
|
|
171
202
|
});
|
|
@@ -180,99 +211,209 @@ export class SpaceInvitationsHandler extends AbstractInvitationsHandler<Space> {
|
|
|
180
211
|
*/
|
|
181
212
|
acceptInvitation(invitation: Invitation, options?: InvitationsOptions): AuthenticatingInvitationProvider {
|
|
182
213
|
const { timeout = INVITATION_TIMEOUT } = options ?? {};
|
|
183
|
-
|
|
214
|
+
|
|
215
|
+
const ctx = new Context({
|
|
216
|
+
onError: (err) => {
|
|
217
|
+
void ctx.dispose();
|
|
218
|
+
observable.callback.onError(err);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
184
221
|
|
|
185
222
|
const authenticated = new Trigger<string>();
|
|
186
223
|
const observable = new AuthenticatingInvitationProvider({
|
|
187
224
|
onCancel: async () => {
|
|
188
|
-
await
|
|
225
|
+
await ctx.dispose();
|
|
189
226
|
},
|
|
190
227
|
|
|
191
|
-
// TODO(burdon): Consider retry.
|
|
192
228
|
onAuthenticate: async (code: string) => {
|
|
229
|
+
// TODO(burdon): Reset creates a race condition? Event?
|
|
193
230
|
authenticated.wake(code);
|
|
194
231
|
}
|
|
195
232
|
});
|
|
196
233
|
|
|
197
234
|
let connectionCount = 0;
|
|
198
235
|
const complete = new Trigger();
|
|
199
|
-
const plugin = createRpcPlugin(async (port) => {
|
|
200
|
-
const peer = createProtoRpcPeer({
|
|
201
|
-
requested: {
|
|
202
|
-
SpaceHostService: schema.getService('dxos.halo.invitations.SpaceHostService')
|
|
203
|
-
},
|
|
204
|
-
port
|
|
205
|
-
});
|
|
206
236
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
237
|
+
const createExtension = (): GuestSpaceInvitationExtension => {
|
|
238
|
+
const extension = new GuestSpaceInvitationExtension({
|
|
239
|
+
onOpen: () => {
|
|
240
|
+
scheduleTask(ctx, async () => {
|
|
241
|
+
try {
|
|
242
|
+
// TODO(burdon): Bug where guest may create multiple connections.
|
|
243
|
+
if (++connectionCount > 1) {
|
|
244
|
+
throw new Error(`multiple connections detected: ${connectionCount}`);
|
|
245
|
+
}
|
|
213
246
|
|
|
214
|
-
|
|
215
|
-
|
|
247
|
+
log('connected', { guest: this._signingContext.deviceKey });
|
|
248
|
+
observable.callback.onConnected?.(invitation);
|
|
216
249
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
250
|
+
// 1. Introduce guest to host.
|
|
251
|
+
log('introduce', { guest: this._signingContext.deviceKey });
|
|
252
|
+
await extension.rpc.SpaceHostService.introduce({
|
|
253
|
+
profile: this._signingContext.profile
|
|
254
|
+
});
|
|
222
255
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
256
|
+
// 2. Get authentication code.
|
|
257
|
+
// TODO(burdon): Test timeout (options for timeouts at different steps).
|
|
258
|
+
if (invitation.type === undefined || invitation.type === Invitation.Type.INTERACTIVE) {
|
|
259
|
+
for (let attempt = 1; attempt <= MAX_OTP_ATTEMPTS; attempt++) {
|
|
260
|
+
log('guest waiting for authentication code...');
|
|
261
|
+
observable.callback.onAuthenticating?.(invitation);
|
|
262
|
+
const authenticationCode = await authenticated.wait({ timeout });
|
|
263
|
+
|
|
264
|
+
log('sending authentication request');
|
|
265
|
+
const response = await extension.rpc.SpaceHostService.authenticate({ authenticationCode });
|
|
266
|
+
if (response.status === undefined || response.status === AuthenticationResponse.Status.OK) {
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
232
269
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
270
|
+
if (response.status === AuthenticationResponse.Status.INVALID_OTP) {
|
|
271
|
+
if (attempt === MAX_OTP_ATTEMPTS) {
|
|
272
|
+
throw new Error(`Maximum retry attempts: ${MAX_OTP_ATTEMPTS}`);
|
|
273
|
+
} else {
|
|
274
|
+
log('retrying invalid code', { attempt });
|
|
275
|
+
authenticated.reset();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// 3. Generate a pair of keys for our feeds.
|
|
281
|
+
const controlFeedKey = await this._keyring.createKey();
|
|
282
|
+
const dataFeedKey = await this._keyring.createKey();
|
|
283
|
+
|
|
284
|
+
// 4. Send admission credentials to host (with local space keys).
|
|
285
|
+
log('request admission', { guest: this._signingContext.deviceKey });
|
|
286
|
+
const { credential } = await extension.rpc.SpaceHostService.requestAdmission({
|
|
287
|
+
identityKey: this._signingContext.identityKey,
|
|
288
|
+
deviceKey: this._signingContext.deviceKey,
|
|
289
|
+
controlFeedKey,
|
|
290
|
+
dataFeedKey
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// TODO(dmaretskyi): Record credential in our HALO.
|
|
294
|
+
|
|
295
|
+
// 4. Create local space.
|
|
296
|
+
const assertion = getCredentialAssertion(credential);
|
|
297
|
+
assert(assertion['@type'] === 'dxos.halo.credentials.SpaceMember', 'Invalid credential');
|
|
298
|
+
assert(credential.subject.id.equals(this._signingContext.identityKey));
|
|
299
|
+
|
|
300
|
+
const space = await this._spaceManager.acceptSpace({
|
|
301
|
+
spaceKey: assertion.spaceKey,
|
|
302
|
+
genesisFeedKey: assertion.genesisFeedKey,
|
|
303
|
+
controlFeedKey,
|
|
304
|
+
dataFeedKey
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// 5. Success.
|
|
308
|
+
log('admitted by host', { guest: this._signingContext.deviceKey, spaceKey: space.key });
|
|
309
|
+
complete.wake();
|
|
310
|
+
} catch (err) {
|
|
311
|
+
if (!observable.cancelled) {
|
|
312
|
+
log.warn('auth failed', err);
|
|
313
|
+
observable.callback.onError(err);
|
|
314
|
+
}
|
|
315
|
+
} finally {
|
|
316
|
+
await ctx.dispose();
|
|
317
|
+
}
|
|
318
|
+
});
|
|
253
319
|
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
});
|
|
320
|
+
});
|
|
321
|
+
return extension;
|
|
322
|
+
};
|
|
258
323
|
|
|
259
|
-
|
|
324
|
+
scheduleTask(ctx, async () => {
|
|
260
325
|
assert(invitation.swarmKey);
|
|
261
326
|
const topic = invitation.swarmKey;
|
|
262
|
-
const
|
|
263
|
-
swarmConnection = await this._networkManager.joinSwarm({
|
|
327
|
+
const swarmConnection = await this._networkManager.joinSwarm({
|
|
264
328
|
topic,
|
|
265
329
|
peerId: PublicKey.random(),
|
|
266
|
-
|
|
330
|
+
protocolProvider: createTeleportProtocolFactory(async (teleport) => {
|
|
331
|
+
teleport.addExtension('dxos.halo.invitations', createExtension());
|
|
332
|
+
}),
|
|
267
333
|
topology: new StarTopology(topic)
|
|
268
334
|
});
|
|
335
|
+
ctx.onDispose(() => swarmConnection.close());
|
|
269
336
|
|
|
270
337
|
observable.callback.onConnecting?.(invitation);
|
|
271
338
|
await complete.wait();
|
|
272
339
|
observable.callback.onSuccess(invitation);
|
|
273
|
-
await
|
|
340
|
+
await ctx.dispose();
|
|
274
341
|
});
|
|
275
342
|
|
|
276
343
|
return observable;
|
|
277
344
|
}
|
|
278
345
|
}
|
|
346
|
+
|
|
347
|
+
type HostSpaceInvitationExtensionCallbacks = {
|
|
348
|
+
// Deliberately not async to not block the extensions opening.
|
|
349
|
+
onOpen: () => void;
|
|
350
|
+
|
|
351
|
+
introduce: (introduction: Introduction) => Promise<void>;
|
|
352
|
+
authenticate: (request: AuthenticationRequest) => Promise<AuthenticationResponse>;
|
|
353
|
+
requestAdmission: (request: SpaceAdmissionRequest) => Promise<SpaceAdmissionCredentials>;
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Host's side for a connection to a concrete peer in p2p network during invitation.
|
|
358
|
+
*/
|
|
359
|
+
class HostSpaceInvitationExtension extends RpcExtension<{}, { SpaceHostService: SpaceHostService }> {
|
|
360
|
+
constructor(private readonly _callbacks: HostSpaceInvitationExtensionCallbacks) {
|
|
361
|
+
super({
|
|
362
|
+
exposed: {
|
|
363
|
+
SpaceHostService: schema.getService('dxos.halo.invitations.SpaceHostService')
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
protected override async getHandlers(): Promise<{ SpaceHostService: SpaceHostService }> {
|
|
369
|
+
return {
|
|
370
|
+
// TODO(dmaretskyi): For now this is just forwarding the data to callbacks since we don't have session-specific logic.
|
|
371
|
+
// Perhaps in the future we will have more complex logic here.
|
|
372
|
+
SpaceHostService: {
|
|
373
|
+
introduce: async (params) => {
|
|
374
|
+
return this._callbacks.introduce(params);
|
|
375
|
+
},
|
|
376
|
+
|
|
377
|
+
authenticate: async (credentials) => {
|
|
378
|
+
return this._callbacks.authenticate(credentials);
|
|
379
|
+
},
|
|
380
|
+
|
|
381
|
+
requestAdmission: async (credentials) => {
|
|
382
|
+
return this._callbacks.requestAdmission(credentials);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
override async onOpen(context: ExtensionContext) {
|
|
389
|
+
await super.onOpen(context);
|
|
390
|
+
this._callbacks.onOpen();
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
type GuestSpaceInvitationExtensionCallbacks = {
|
|
395
|
+
// Deliberately not async to not block the extensions opening.
|
|
396
|
+
onOpen: () => void;
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Guest's side for a connection to a concrete peer in p2p network during invitation.
|
|
401
|
+
*/
|
|
402
|
+
class GuestSpaceInvitationExtension extends RpcExtension<{ SpaceHostService: SpaceHostService }, {}> {
|
|
403
|
+
constructor(private readonly _callbacks: GuestSpaceInvitationExtensionCallbacks) {
|
|
404
|
+
super({
|
|
405
|
+
requested: {
|
|
406
|
+
SpaceHostService: schema.getService('dxos.halo.invitations.SpaceHostService')
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
protected override async getHandlers() {
|
|
412
|
+
return {};
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
override async onOpen(context: ExtensionContext) {
|
|
416
|
+
await super.onOpen(context);
|
|
417
|
+
this._callbacks.onOpen();
|
|
418
|
+
}
|
|
419
|
+
}
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import assert from 'assert';
|
|
6
5
|
import { expect } from 'chai';
|
|
6
|
+
import assert from 'node:assert';
|
|
7
7
|
|
|
8
8
|
import { asyncChain, Trigger } from '@dxos/async';
|
|
9
9
|
import { raise } from '@dxos/debug';
|
|
10
10
|
import { Invitation, SpaceInvitationsService } from '@dxos/protocols/proto/dxos/client/services';
|
|
11
|
-
import { afterTest } from '@dxos/
|
|
11
|
+
import { describe, test, afterTest } from '@dxos/test';
|
|
12
12
|
|
|
13
13
|
import { ServiceContext } from '../services';
|
|
14
14
|
import { createIdentity, createPeers } from '../testing';
|
|
@@ -20,8 +20,8 @@ const closeAfterTest = async (peer: ServiceContext) => {
|
|
|
20
20
|
return peer;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
describe('services/space-invitation-service',
|
|
24
|
-
|
|
23
|
+
describe('services/space-invitation-service', () => {
|
|
24
|
+
test('creates space and invites peer', async () => {
|
|
25
25
|
const [host, guest] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(2));
|
|
26
26
|
|
|
27
27
|
assert(host.spaceManager);
|
|
@@ -82,7 +82,7 @@ describe('services/space-invitation-service', function () {
|
|
|
82
82
|
expect(invitation1.state).to.eq(Invitation.State.SUCCESS);
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
test('creates space and cancels invitation', async () => {
|
|
86
86
|
const [host, guest] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(2));
|
|
87
87
|
|
|
88
88
|
assert(host.spaceManager);
|