@dxos/client-services 0.1.2 → 0.1.3
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/src/index.d.ts +4 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/packlets/deprecated/index.d.ts +5 -0
- package/dist/src/packlets/deprecated/index.d.ts.map +1 -0
- package/dist/src/packlets/{services/impl → deprecated}/index.js +1 -3
- package/dist/src/packlets/deprecated/index.js.map +1 -0
- package/dist/src/packlets/{invitations/common.d.ts → deprecated/invitations.d.ts} +14 -2
- package/dist/src/packlets/deprecated/invitations.d.ts.map +1 -0
- package/dist/src/packlets/{invitations/common.js → deprecated/invitations.js} +1 -1
- package/dist/src/packlets/deprecated/invitations.js.map +1 -0
- package/dist/src/packlets/{services/impl → deprecated}/profile.d.ts +5 -5
- package/dist/src/packlets/deprecated/profile.d.ts.map +1 -0
- package/dist/src/packlets/{services/impl → deprecated}/profile.js +10 -10
- package/dist/src/packlets/deprecated/profile.js.map +1 -0
- package/dist/src/packlets/deprecated/space.d.ts +23 -0
- package/dist/src/packlets/deprecated/space.d.ts.map +1 -0
- package/dist/src/packlets/deprecated/space.js +206 -0
- package/dist/src/packlets/deprecated/space.js.map +1 -0
- package/dist/src/packlets/{services/impl → deprecated}/system.d.ts +2 -2
- package/dist/src/packlets/deprecated/system.d.ts.map +1 -0
- package/dist/src/packlets/{services/impl → deprecated}/system.js +3 -3
- package/dist/src/packlets/deprecated/system.js.map +1 -0
- package/dist/src/packlets/deprecated/tracing.d.ts +12 -0
- package/dist/src/packlets/deprecated/tracing.d.ts.map +1 -0
- package/dist/src/packlets/{services/impl → deprecated}/tracing.js +3 -3
- package/dist/src/packlets/deprecated/tracing.js.map +1 -0
- package/dist/src/packlets/{services/impl → devtools}/devtools.d.ts +11 -7
- package/dist/src/packlets/devtools/devtools.d.ts.map +1 -0
- package/dist/src/packlets/devtools/devtools.js +86 -0
- package/dist/src/packlets/devtools/devtools.js.map +1 -0
- package/dist/src/packlets/devtools/feeds.d.ts.map +1 -1
- package/dist/src/packlets/devtools/feeds.js +28 -26
- package/dist/src/packlets/devtools/feeds.js.map +1 -1
- package/dist/src/packlets/devtools/index.d.ts +1 -1
- package/dist/src/packlets/devtools/index.d.ts.map +1 -1
- package/dist/src/packlets/devtools/index.js +1 -1
- package/dist/src/packlets/devtools/index.js.map +1 -1
- package/dist/src/packlets/devtools/spaces.d.ts +2 -2
- package/dist/src/packlets/devtools/spaces.d.ts.map +1 -1
- package/dist/src/packlets/devtools/spaces.js +13 -13
- package/dist/src/packlets/devtools/spaces.js.map +1 -1
- package/dist/src/packlets/identity/devices-service-impl.d.ts +10 -0
- package/dist/src/packlets/identity/devices-service-impl.d.ts.map +1 -0
- package/dist/src/packlets/identity/devices-service-impl.js +47 -0
- package/dist/src/packlets/identity/devices-service-impl.js.map +1 -0
- package/dist/src/packlets/identity/identity-manager.test.js +7 -11
- package/dist/src/packlets/identity/identity-manager.test.js.map +1 -1
- package/dist/src/packlets/identity/identity.d.ts +2 -0
- package/dist/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/src/packlets/identity/identity.js +4 -1
- package/dist/src/packlets/identity/identity.js.map +1 -1
- package/dist/src/packlets/identity/identity.test.js +2 -3
- package/dist/src/packlets/identity/identity.test.js.map +1 -1
- package/dist/src/packlets/invitations/encoder.d.ts +9 -0
- package/dist/src/packlets/invitations/encoder.d.ts.map +1 -0
- package/dist/src/packlets/invitations/encoder.js +27 -0
- package/dist/src/packlets/invitations/encoder.js.map +1 -0
- package/dist/src/packlets/invitations/encoder.test.d.ts +2 -0
- package/dist/src/packlets/invitations/encoder.test.d.ts.map +1 -0
- package/dist/src/packlets/invitations/encoder.test.js +19 -0
- package/dist/src/packlets/invitations/encoder.test.js.map +1 -0
- package/dist/src/packlets/invitations/halo-invitations.d.ts +3 -3
- package/dist/src/packlets/invitations/halo-invitations.d.ts.map +1 -1
- package/dist/src/packlets/invitations/halo-invitations.js +14 -10
- package/dist/src/packlets/invitations/halo-invitations.js.map +1 -1
- package/dist/src/packlets/invitations/halo-invitations.test.d.ts +2 -0
- package/dist/src/packlets/invitations/halo-invitations.test.d.ts.map +1 -0
- package/dist/src/packlets/{services/testing/halo.test.js → invitations/halo-invitations.test.js} +6 -6
- package/dist/src/packlets/invitations/halo-invitations.test.js.map +1 -0
- package/dist/src/packlets/invitations/index.d.ts +6 -3
- package/dist/src/packlets/invitations/index.d.ts.map +1 -1
- package/dist/src/packlets/invitations/index.js +6 -3
- package/dist/src/packlets/invitations/index.js.map +1 -1
- package/dist/src/packlets/invitations/invitations-proxy.d.ts +14 -0
- package/dist/src/packlets/invitations/invitations-proxy.d.ts.map +1 -0
- package/dist/src/packlets/invitations/invitations-proxy.js +126 -0
- package/dist/src/packlets/invitations/invitations-proxy.js.map +1 -0
- package/dist/src/packlets/invitations/invitations.d.ts +90 -0
- package/dist/src/packlets/invitations/invitations.d.ts.map +1 -0
- package/dist/src/packlets/invitations/invitations.js +55 -0
- package/dist/src/packlets/invitations/invitations.js.map +1 -0
- package/dist/src/packlets/invitations/space-invitations-handler.d.ts +24 -0
- package/dist/src/packlets/invitations/space-invitations-handler.d.ts.map +1 -0
- package/dist/src/packlets/invitations/space-invitations-handler.js +232 -0
- package/dist/src/packlets/invitations/space-invitations-handler.js.map +1 -0
- package/dist/src/packlets/invitations/space-invitations-handler.test.d.ts +2 -0
- package/dist/src/packlets/invitations/space-invitations-handler.test.d.ts.map +1 -0
- package/dist/src/packlets/invitations/space-invitations-handler.test.js +131 -0
- package/dist/src/packlets/invitations/space-invitations-handler.test.js.map +1 -0
- package/dist/src/packlets/invitations/space-invitations-proxy.d.ts +11 -0
- package/dist/src/packlets/invitations/space-invitations-proxy.d.ts.map +1 -0
- package/dist/src/packlets/invitations/space-invitations-proxy.js +17 -0
- package/dist/src/packlets/invitations/space-invitations-proxy.js.map +1 -0
- package/dist/src/packlets/invitations/space-invitations-service.d.ts +22 -0
- package/dist/src/packlets/invitations/space-invitations-service.d.ts.map +1 -0
- package/dist/src/packlets/invitations/space-invitations-service.js +189 -0
- package/dist/src/packlets/invitations/space-invitations-service.js.map +1 -0
- package/dist/src/packlets/invitations/space-invitations-service.test.d.ts +2 -0
- package/dist/src/packlets/invitations/space-invitations-service.test.d.ts.map +1 -0
- package/dist/src/packlets/invitations/space-invitations-service.test.js +100 -0
- package/dist/src/packlets/invitations/space-invitations-service.test.js.map +1 -0
- package/dist/src/packlets/services/index.d.ts +3 -2
- package/dist/src/packlets/services/index.d.ts.map +1 -1
- package/dist/src/packlets/services/index.js +3 -2
- package/dist/src/packlets/services/index.js.map +1 -1
- package/dist/src/packlets/services/service-context.d.ts +4 -7
- package/dist/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/src/packlets/services/service-context.js +9 -25
- package/dist/src/packlets/services/service-context.js.map +1 -1
- package/dist/src/packlets/services/service-definitions.d.ts +30 -0
- package/dist/src/packlets/services/service-definitions.d.ts.map +1 -0
- package/dist/src/packlets/services/{services.js → service-definitions.js} +9 -5
- package/dist/src/packlets/services/service-definitions.js.map +1 -0
- package/dist/src/packlets/services/service-host.d.ts +9 -12
- package/dist/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/src/packlets/services/service-host.js +55 -54
- package/dist/src/packlets/services/service-host.js.map +1 -1
- package/dist/src/packlets/services/service-host.test.js +7 -17
- package/dist/src/packlets/services/service-host.test.js.map +1 -1
- package/dist/src/packlets/services/service-proxy.d.ts +17 -0
- package/dist/src/packlets/services/service-proxy.d.ts.map +1 -0
- package/dist/src/packlets/services/service-proxy.js +48 -0
- package/dist/src/packlets/services/service-proxy.js.map +1 -0
- package/dist/src/packlets/services/service-registry.d.ts +12 -0
- package/dist/src/packlets/services/service-registry.d.ts.map +1 -0
- package/dist/src/packlets/services/service-registry.js +24 -0
- package/dist/src/packlets/services/service-registry.js.map +1 -0
- package/dist/src/packlets/services/service-registry.test.d.ts +2 -0
- package/dist/src/packlets/services/service-registry.test.d.ts.map +1 -0
- package/dist/src/packlets/services/service-registry.test.js +75 -0
- package/dist/src/packlets/services/service-registry.test.js.map +1 -0
- package/dist/src/packlets/services/signer.d.ts +0 -3
- package/dist/src/packlets/services/signer.d.ts.map +1 -1
- package/dist/src/packlets/spaces/index.d.ts +2 -0
- package/dist/src/packlets/spaces/index.d.ts.map +1 -0
- package/dist/src/packlets/spaces/index.js +21 -0
- package/dist/src/packlets/spaces/index.js.map +1 -0
- package/dist/src/packlets/spaces/spaces-service.d.ts +11 -0
- package/dist/src/packlets/spaces/spaces-service.d.ts.map +1 -0
- package/dist/src/packlets/spaces/spaces-service.js +22 -0
- package/dist/src/packlets/spaces/spaces-service.js.map +1 -0
- package/dist/src/packlets/storage/storage.js +1 -1
- package/dist/src/packlets/storage/storage.js.map +1 -1
- package/dist/src/packlets/testing/index.d.ts +2 -0
- package/dist/src/packlets/testing/index.d.ts.map +1 -0
- package/dist/src/packlets/testing/index.js +21 -0
- package/dist/src/packlets/testing/index.js.map +1 -0
- package/dist/src/packlets/testing/test-builder.d.ts +14 -0
- package/dist/src/packlets/testing/test-builder.d.ts.map +1 -0
- package/dist/src/packlets/testing/test-builder.js +65 -0
- package/dist/src/packlets/testing/test-builder.js.map +1 -0
- package/dist/src/packlets/vault/iframe-runtime.d.ts +19 -0
- package/dist/src/packlets/vault/iframe-runtime.d.ts.map +1 -0
- package/dist/src/packlets/vault/iframe-runtime.js +54 -0
- package/dist/src/packlets/vault/iframe-runtime.js.map +1 -0
- package/dist/src/packlets/vault/index.d.ts +4 -0
- package/dist/src/packlets/vault/index.d.ts.map +1 -0
- package/dist/src/packlets/vault/index.js +23 -0
- package/dist/src/packlets/vault/index.js.map +1 -0
- package/dist/src/packlets/vault/services.d.ts +13 -0
- package/dist/src/packlets/vault/services.d.ts.map +1 -0
- package/dist/src/packlets/vault/services.js +15 -0
- package/dist/src/packlets/vault/services.js.map +1 -0
- package/dist/src/packlets/vault/worker-runtime.d.ts +32 -0
- package/dist/src/packlets/vault/worker-runtime.d.ts.map +1 -0
- package/dist/src/packlets/vault/worker-runtime.js +94 -0
- package/dist/src/packlets/vault/worker-runtime.js.map +1 -0
- package/dist/src/packlets/vault/worker-session.d.ts +29 -0
- package/dist/src/packlets/vault/worker-session.d.ts.map +1 -0
- package/dist/src/packlets/vault/worker-session.js +84 -0
- package/dist/src/packlets/vault/worker-session.js.map +1 -0
- package/package.json +26 -26
- package/src/index.ts +5 -2
- package/src/packlets/{services/impl → deprecated}/index.ts +1 -4
- package/src/packlets/{invitations/common.ts → deprecated/invitations.ts} +18 -3
- package/src/packlets/{services/impl → deprecated}/profile.ts +13 -13
- package/src/packlets/deprecated/space.ts +245 -0
- package/src/packlets/{services/impl → deprecated}/system.ts +2 -2
- package/src/packlets/{services/impl → deprecated}/tracing.ts +2 -2
- package/src/packlets/{services/impl → devtools}/devtools.ts +33 -34
- package/src/packlets/devtools/feeds.ts +31 -27
- package/src/packlets/devtools/index.ts +1 -1
- package/src/packlets/devtools/spaces.ts +19 -18
- package/src/packlets/identity/devices-service-impl.ts +54 -0
- package/src/packlets/identity/identity-manager.test.ts +7 -8
- package/src/packlets/identity/identity.test.ts +2 -3
- package/src/packlets/identity/identity.ts +5 -1
- package/src/packlets/invitations/encoder.test.ts +22 -0
- package/src/packlets/invitations/encoder.ts +26 -0
- package/src/packlets/{services/testing/halo.test.ts → invitations/halo-invitations.test.ts} +5 -5
- package/src/packlets/invitations/halo-invitations.ts +12 -10
- package/src/packlets/invitations/index.ts +6 -3
- package/src/packlets/invitations/invitations-proxy.ts +157 -0
- package/src/packlets/invitations/invitations.ts +149 -0
- package/src/packlets/invitations/space-invitations-handler.test.ts +154 -0
- package/src/packlets/invitations/space-invitations-handler.ts +266 -0
- package/src/packlets/invitations/space-invitations-proxy.ts +16 -0
- package/src/packlets/invitations/space-invitations-service.test.ts +129 -0
- package/src/packlets/invitations/space-invitations-service.ts +196 -0
- package/src/packlets/services/index.ts +3 -2
- package/src/packlets/services/service-context.ts +9 -31
- package/src/packlets/services/service-definitions.ts +54 -0
- package/src/packlets/services/service-host.test.ts +12 -24
- package/src/packlets/services/service-host.ts +64 -64
- package/src/packlets/services/service-proxy.ts +54 -0
- package/src/packlets/services/service-registry.test.ts +95 -0
- package/src/packlets/services/service-registry.ts +24 -0
- package/src/packlets/services/signer.ts +1 -3
- package/src/packlets/spaces/index.ts +5 -0
- package/src/packlets/spaces/spaces-service.ts +28 -0
- package/src/packlets/storage/storage.ts +1 -1
- package/src/packlets/testing/index.ts +5 -0
- package/src/packlets/testing/test-builder.ts +79 -0
- package/src/packlets/vault/iframe-runtime.ts +68 -0
- package/src/packlets/vault/index.ts +7 -0
- package/src/packlets/vault/services.ts +26 -0
- package/src/packlets/vault/worker-runtime.ts +111 -0
- package/src/packlets/vault/worker-session.ts +113 -0
- package/dist/src/packlets/devtools/devtools-host-events.d.ts +0 -5
- package/dist/src/packlets/devtools/devtools-host-events.d.ts.map +0 -1
- package/dist/src/packlets/devtools/devtools-host-events.js +0 -14
- package/dist/src/packlets/devtools/devtools-host-events.js.map +0 -1
- package/dist/src/packlets/invitations/common.d.ts.map +0 -1
- package/dist/src/packlets/invitations/common.js.map +0 -1
- package/dist/src/packlets/invitations/invitation-wrapper.d.ts +0 -36
- package/dist/src/packlets/invitations/invitation-wrapper.d.ts.map +0 -1
- package/dist/src/packlets/invitations/invitation-wrapper.js +0 -104
- package/dist/src/packlets/invitations/invitation-wrapper.js.map +0 -1
- package/dist/src/packlets/invitations/space-invitations.d.ts +0 -25
- package/dist/src/packlets/invitations/space-invitations.d.ts.map +0 -1
- package/dist/src/packlets/invitations/space-invitations.js +0 -136
- package/dist/src/packlets/invitations/space-invitations.js.map +0 -1
- package/dist/src/packlets/services/impl/devtools.d.ts.map +0 -1
- package/dist/src/packlets/services/impl/devtools.js +0 -77
- package/dist/src/packlets/services/impl/devtools.js.map +0 -1
- package/dist/src/packlets/services/impl/halo.d.ts +0 -20
- package/dist/src/packlets/services/impl/halo.d.ts.map +0 -1
- package/dist/src/packlets/services/impl/halo.js +0 -93
- package/dist/src/packlets/services/impl/halo.js.map +0 -1
- package/dist/src/packlets/services/impl/index.d.ts +0 -6
- package/dist/src/packlets/services/impl/index.d.ts.map +0 -1
- package/dist/src/packlets/services/impl/index.js.map +0 -1
- package/dist/src/packlets/services/impl/party.d.ts +0 -25
- package/dist/src/packlets/services/impl/party.d.ts.map +0 -1
- package/dist/src/packlets/services/impl/party.js +0 -265
- package/dist/src/packlets/services/impl/party.js.map +0 -1
- package/dist/src/packlets/services/impl/profile.d.ts.map +0 -1
- package/dist/src/packlets/services/impl/profile.js.map +0 -1
- package/dist/src/packlets/services/impl/system.d.ts.map +0 -1
- package/dist/src/packlets/services/impl/system.js.map +0 -1
- package/dist/src/packlets/services/impl/tracing.d.ts +0 -12
- package/dist/src/packlets/services/impl/tracing.d.ts.map +0 -1
- package/dist/src/packlets/services/impl/tracing.js.map +0 -1
- package/dist/src/packlets/services/service-factory.d.ts +0 -15
- package/dist/src/packlets/services/service-factory.d.ts.map +0 -1
- package/dist/src/packlets/services/service-factory.js +0 -25
- package/dist/src/packlets/services/service-factory.js.map +0 -1
- package/dist/src/packlets/services/services.d.ts +0 -19
- package/dist/src/packlets/services/services.d.ts.map +0 -1
- package/dist/src/packlets/services/services.js.map +0 -1
- package/dist/src/packlets/services/testing/halo.test.d.ts +0 -2
- package/dist/src/packlets/services/testing/halo.test.d.ts.map +0 -1
- package/dist/src/packlets/services/testing/halo.test.js.map +0 -1
- package/dist/src/packlets/services/testing/spaces.test.d.ts +0 -2
- package/dist/src/packlets/services/testing/spaces.test.d.ts.map +0 -1
- package/dist/src/packlets/services/testing/spaces.test.js +0 -68
- package/dist/src/packlets/services/testing/spaces.test.js.map +0 -1
- package/dist/src/packlets/services/testing/testing.d.ts +0 -8
- package/dist/src/packlets/services/testing/testing.d.ts.map +0 -1
- package/dist/src/packlets/services/testing/testing.js +0 -23
- package/dist/src/packlets/services/testing/testing.js.map +0 -1
- package/src/packlets/devtools/devtools-host-events.ts +0 -8
- package/src/packlets/invitations/invitation-wrapper.ts +0 -140
- package/src/packlets/invitations/space-invitations.ts +0 -159
- package/src/packlets/services/impl/halo.ts +0 -107
- package/src/packlets/services/impl/party.ts +0 -305
- package/src/packlets/services/service-factory.ts +0 -35
- package/src/packlets/services/services.ts +0 -39
- package/src/packlets/services/testing/spaces.test.ts +0 -87
- package/src/packlets/services/testing/testing.ts +0 -28
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import assert from 'assert';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
AsyncEvents,
|
|
9
|
+
CancellableObservable,
|
|
10
|
+
CancellableObservableEvents,
|
|
11
|
+
Observable,
|
|
12
|
+
CancellableObservableProvider
|
|
13
|
+
} from '@dxos/async';
|
|
14
|
+
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
15
|
+
|
|
16
|
+
export const AUTHENTICATION_CODE_LENGTH = 6;
|
|
17
|
+
|
|
18
|
+
export type CreateInvitationsOptions = {
|
|
19
|
+
type?: Invitation.Type;
|
|
20
|
+
timeout?: number;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Common invitation events (callbacks) for creating and accepting invitations.
|
|
25
|
+
*/
|
|
26
|
+
// TODO(burdon): Remove optionals.
|
|
27
|
+
export interface InvitationEvents extends AsyncEvents, CancellableObservableEvents {
|
|
28
|
+
onConnecting?(invitation: Invitation): void;
|
|
29
|
+
onConnected?(invitation: Invitation): void;
|
|
30
|
+
onAuthenticating?(invitation: Invitation): void;
|
|
31
|
+
onSuccess(invitation: Invitation): void; // TODO(burdon): Collides with AsyncEvents.
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Base class for all invitation observables and providers.
|
|
36
|
+
* Observable that supports inspection of the current value.
|
|
37
|
+
*/
|
|
38
|
+
export interface InvitationObservable extends CancellableObservable<InvitationEvents> {
|
|
39
|
+
get invitation(): Invitation | undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class InvitationObservableProvider
|
|
43
|
+
extends CancellableObservableProvider<InvitationEvents>
|
|
44
|
+
implements InvitationObservable
|
|
45
|
+
{
|
|
46
|
+
private _invitation?: Invitation;
|
|
47
|
+
|
|
48
|
+
get invitation(): Invitation | undefined {
|
|
49
|
+
return this._invitation;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
setInvitation(invitation: Invitation) {
|
|
53
|
+
this._invitation = invitation;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Cancelable observer.
|
|
59
|
+
*/
|
|
60
|
+
export type CancellableInvitationObservable = InvitationObservable;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Cancelable observer that relays authentication requests.
|
|
64
|
+
*/
|
|
65
|
+
export interface AuthenticatingInvitationObservable extends CancellableInvitationObservable {
|
|
66
|
+
authenticate(code: string): Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface AuthenticatingInvitationProviderActions {
|
|
70
|
+
onCancel(): Promise<void>;
|
|
71
|
+
onAuthenticate(code: string): Promise<void>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export class AuthenticatingInvitationProvider
|
|
75
|
+
extends InvitationObservableProvider
|
|
76
|
+
implements AuthenticatingInvitationObservable
|
|
77
|
+
{
|
|
78
|
+
// prettier-ignore
|
|
79
|
+
constructor(
|
|
80
|
+
private readonly _actions: AuthenticatingInvitationProviderActions
|
|
81
|
+
) {
|
|
82
|
+
super(() => this._actions.onCancel());
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async authenticate(authenticationCode: string): Promise<void> {
|
|
86
|
+
return this._actions.onAuthenticate(authenticationCode);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Common interface for Halo and Space invitation proxies and handlers.
|
|
92
|
+
* Handles the life-cycle of Space invitations between peers.
|
|
93
|
+
*
|
|
94
|
+
* Host
|
|
95
|
+
* - Creates an invitation containing a swarm topic.
|
|
96
|
+
* - Joins the swarm with the topic and waits for guest's admission request.
|
|
97
|
+
* - Responds with admission offer then waits for guest's credentials.
|
|
98
|
+
* - Writes credentials to control feed then exits.
|
|
99
|
+
*
|
|
100
|
+
* Guest
|
|
101
|
+
* - Joins the swarm with the topic.
|
|
102
|
+
* - NOTE: The topic is transmitted out-of-band (e.g., via a QR code).
|
|
103
|
+
* - Sends an admission request.
|
|
104
|
+
* - If Space handler then creates a local cloned space (with genesis block).
|
|
105
|
+
* - Sends admission credentials (containing local device and feed keys).
|
|
106
|
+
*
|
|
107
|
+
* TODO(burdon): Show proxy/service relationship and reference design doc/diagram.
|
|
108
|
+
*
|
|
109
|
+
* ```
|
|
110
|
+
* [Guest] [Host]
|
|
111
|
+
* |-------------------------------------RequestAdmission-->|
|
|
112
|
+
* |<--AdmissionOffer---------------------------------------|
|
|
113
|
+
* |
|
|
114
|
+
* |--------------------------PresentAdmissionCredentials-->|
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export interface InvitationsHandler<T> {
|
|
118
|
+
// TODO(burdon): Pass in options.
|
|
119
|
+
createInvitation(context: T, options?: CreateInvitationsOptions): InvitationObservable;
|
|
120
|
+
acceptInvitation(invitation: Invitation): AuthenticatingInvitationObservable;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Common interface for Halo and Space proxies.
|
|
125
|
+
*/
|
|
126
|
+
export interface InvitationsProxy<T> extends InvitationsHandler<T> {
|
|
127
|
+
createInvitationObject(context: T): Invitation;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Util to wrap observable with promise.
|
|
132
|
+
* @deprecated
|
|
133
|
+
*/
|
|
134
|
+
// TODO(burdon): Replace with InvitationObservableProvider.
|
|
135
|
+
export const invitationObservable = async (observable: Observable<InvitationEvents>): Promise<Invitation> => {
|
|
136
|
+
return new Promise((resolve, reject) => {
|
|
137
|
+
const unsubscribe = observable.subscribe({
|
|
138
|
+
onSuccess: (invitation: Invitation) => {
|
|
139
|
+
assert(invitation.state === Invitation.State.SUCCESS);
|
|
140
|
+
unsubscribe();
|
|
141
|
+
resolve(invitation);
|
|
142
|
+
},
|
|
143
|
+
onError: (err: Error) => {
|
|
144
|
+
unsubscribe();
|
|
145
|
+
reject(err);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import assert from 'assert';
|
|
6
|
+
import { expect } from 'chai';
|
|
7
|
+
|
|
8
|
+
import { asyncChain, Trigger } from '@dxos/async';
|
|
9
|
+
import { raise } from '@dxos/debug';
|
|
10
|
+
import { PublicKey } from '@dxos/keys';
|
|
11
|
+
import { ObjectModel } from '@dxos/object-model';
|
|
12
|
+
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
13
|
+
import { afterTest } from '@dxos/testutils';
|
|
14
|
+
|
|
15
|
+
import { ServiceContext } from '../services';
|
|
16
|
+
import { createIdentity, createPeers, syncItems } from '../testing';
|
|
17
|
+
|
|
18
|
+
const closeAfterTest = async (peer: ServiceContext) => {
|
|
19
|
+
afterTest(() => peer.close());
|
|
20
|
+
return peer;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
describe('services/space-invitations-handler', function () {
|
|
24
|
+
it('genesis', async function () {
|
|
25
|
+
const [peer] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(1));
|
|
26
|
+
|
|
27
|
+
const space = await peer.spaceManager!.createSpace();
|
|
28
|
+
expect(space.database).not.to.be.undefined;
|
|
29
|
+
expect(peer.spaceManager!.spaces.has(space.key)).to.be.true;
|
|
30
|
+
await space.close();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('genesis with database mutations', async function () {
|
|
34
|
+
const [peer] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(1));
|
|
35
|
+
const space = await peer.spaceManager!.createSpace();
|
|
36
|
+
|
|
37
|
+
{
|
|
38
|
+
const item = await space.database!.createItem<ObjectModel>({ type: 'test' });
|
|
39
|
+
void item.model.set('name', 'test');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
{
|
|
43
|
+
const [item] = space.database!.select({ type: 'test' }).exec().entities;
|
|
44
|
+
expect(item.model.get('name')).to.eq('test');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
await space.close();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('creates and accepts invitation', async function () {
|
|
51
|
+
const [host, guest] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(2));
|
|
52
|
+
|
|
53
|
+
const complete1 = new Trigger<PublicKey>();
|
|
54
|
+
const complete2 = new Trigger<PublicKey>();
|
|
55
|
+
|
|
56
|
+
const authenticationCode = new Trigger<string>();
|
|
57
|
+
|
|
58
|
+
const space1 = await host.spaceManager!.createSpace();
|
|
59
|
+
const observable1 = host.spaceInvitations!.createInvitation(space1);
|
|
60
|
+
observable1.subscribe({
|
|
61
|
+
onConnecting: async (invitation1: Invitation) => {
|
|
62
|
+
const observable2 = guest.spaceInvitations!.acceptInvitation(invitation1);
|
|
63
|
+
observable2.subscribe({
|
|
64
|
+
onConnecting: async (invitation2: Invitation) => {},
|
|
65
|
+
onConnected: async (invitation2: Invitation) => {
|
|
66
|
+
expect(invitation1.swarmKey).to.eq(invitation2.swarmKey);
|
|
67
|
+
},
|
|
68
|
+
onAuthenticating: async (invitation2: Invitation) => {
|
|
69
|
+
await observable2.authenticate(await authenticationCode.wait());
|
|
70
|
+
},
|
|
71
|
+
onSuccess: (invitation: Invitation) => {
|
|
72
|
+
complete2.wake(invitation.spaceKey!);
|
|
73
|
+
},
|
|
74
|
+
onCancelled: () => raise(new Error()),
|
|
75
|
+
onTimeout: (err: Error) => raise(new Error(err.message)),
|
|
76
|
+
onError: (err: Error) => raise(new Error(err.message))
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
onConnected: (invitation: Invitation) => {
|
|
80
|
+
assert(invitation.authenticationCode);
|
|
81
|
+
authenticationCode.wake(invitation.authenticationCode);
|
|
82
|
+
},
|
|
83
|
+
onSuccess: (invitation: Invitation) => {
|
|
84
|
+
complete1.wake(space1.key);
|
|
85
|
+
},
|
|
86
|
+
onCancelled: () => raise(new Error()),
|
|
87
|
+
onTimeout: (err: Error) => raise(new Error(err.message)),
|
|
88
|
+
onError: (err: Error) => raise(new Error(err.message))
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
{
|
|
92
|
+
const [spaceKey1, spaceKey2] = await Promise.all([complete1.wait(), complete2.wait()]);
|
|
93
|
+
expect(spaceKey1).to.deep.eq(spaceKey2);
|
|
94
|
+
|
|
95
|
+
const space1 = host.spaceManager!.spaces.get(spaceKey1)!;
|
|
96
|
+
const space2 = guest.spaceManager!.spaces.get(spaceKey2)!;
|
|
97
|
+
expect(space1).not.to.be.undefined;
|
|
98
|
+
expect(space2).not.to.be.undefined;
|
|
99
|
+
|
|
100
|
+
await syncItems(space1, space2);
|
|
101
|
+
|
|
102
|
+
await space1.close();
|
|
103
|
+
await space2.close();
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('cancels invitation', async function () {
|
|
108
|
+
const [host, guest] = await asyncChain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(2));
|
|
109
|
+
|
|
110
|
+
const cancelled = new Trigger();
|
|
111
|
+
const connecting1 = new Trigger<Invitation>(); // peer 1 connected.
|
|
112
|
+
const connecting2 = new Trigger<Invitation>(); // peer 2 connected.
|
|
113
|
+
|
|
114
|
+
const space1 = await host.spaceManager!.createSpace();
|
|
115
|
+
const observable1 = await host.spaceInvitations!.createInvitation(space1);
|
|
116
|
+
observable1.subscribe({
|
|
117
|
+
onConnecting: async (invitation1: Invitation) => {
|
|
118
|
+
connecting1.wake(invitation1);
|
|
119
|
+
|
|
120
|
+
const observable2 = await guest.spaceInvitations!.acceptInvitation(invitation1);
|
|
121
|
+
observable2.subscribe({
|
|
122
|
+
onConnecting: async (invitation2: Invitation) => {
|
|
123
|
+
expect(invitation1.swarmKey).to.eq(invitation2.swarmKey);
|
|
124
|
+
connecting2.wake(invitation2);
|
|
125
|
+
},
|
|
126
|
+
onConnected: async (invitation2: Invitation) => {},
|
|
127
|
+
onSuccess: () => {},
|
|
128
|
+
onCancelled: () => raise(new Error()),
|
|
129
|
+
onTimeout: (err: Error) => raise(new Error(err.message)),
|
|
130
|
+
onError: (err: Error) => raise(new Error(err.message))
|
|
131
|
+
});
|
|
132
|
+
},
|
|
133
|
+
onConnected: async (invitation1: Invitation) => {},
|
|
134
|
+
onCancelled: () => {
|
|
135
|
+
cancelled.wake();
|
|
136
|
+
},
|
|
137
|
+
onSuccess: () => raise(new Error()),
|
|
138
|
+
onTimeout: (err: Error) => raise(new Error(err.message)),
|
|
139
|
+
onError: (err: Error) => raise(new Error(err.message))
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const invitation1 = await connecting1.wait();
|
|
143
|
+
const invitation2 = await connecting2.wait();
|
|
144
|
+
expect(invitation1.swarmKey).to.eq(invitation2.swarmKey);
|
|
145
|
+
|
|
146
|
+
// TODO(burdon): Simulate network latency.
|
|
147
|
+
setTimeout(async () => {
|
|
148
|
+
await observable1.cancel();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
await cancelled.wait();
|
|
152
|
+
await space1.close();
|
|
153
|
+
});
|
|
154
|
+
});
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import assert from 'assert';
|
|
6
|
+
|
|
7
|
+
import { sleep, Trigger } from '@dxos/async';
|
|
8
|
+
import { createAdmissionCredentials, generatePasscode } from '@dxos/credentials';
|
|
9
|
+
import { SigningContext, Space, SpaceManager } from '@dxos/echo-db';
|
|
10
|
+
import { writeMessages } from '@dxos/feed-store';
|
|
11
|
+
import { PublicKey } from '@dxos/keys';
|
|
12
|
+
import { log } from '@dxos/log';
|
|
13
|
+
import { createProtocolFactory, NetworkManager, StarTopology, SwarmConnection } from '@dxos/network-manager';
|
|
14
|
+
import { createRpcPlugin, RpcPlugin } from '@dxos/protocol-plugin-rpc';
|
|
15
|
+
import { schema } from '@dxos/protocols';
|
|
16
|
+
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
17
|
+
import { createProtoRpcPeer } from '@dxos/rpc';
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
AuthenticatingInvitationProvider,
|
|
21
|
+
CreateInvitationsOptions,
|
|
22
|
+
InvitationsHandler,
|
|
23
|
+
InvitationObservable,
|
|
24
|
+
InvitationObservableProvider,
|
|
25
|
+
AUTHENTICATION_CODE_LENGTH
|
|
26
|
+
} from './invitations';
|
|
27
|
+
|
|
28
|
+
// TODO(burdon): Pass options from client.
|
|
29
|
+
// TODO(burdon): Don't close until RPC has complete.
|
|
30
|
+
const ON_CLOSE_DELAY = 500;
|
|
31
|
+
const INVITATION_TIMEOUT = 3 * 60_000; // 3 mins.
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Handles the life-cycle of Space invitations between peers.
|
|
35
|
+
*/
|
|
36
|
+
export class SpaceInvitationsHandler implements InvitationsHandler<Space> {
|
|
37
|
+
constructor(
|
|
38
|
+
private readonly _spaceManager: SpaceManager,
|
|
39
|
+
private readonly _networkManager: NetworkManager,
|
|
40
|
+
private readonly _signingContext: SigningContext
|
|
41
|
+
) {}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Creates an invitation and listens for a join request from the invited (guest) peer.
|
|
45
|
+
*/
|
|
46
|
+
createInvitation(space: Space, options?: CreateInvitationsOptions): InvitationObservable {
|
|
47
|
+
let swarmConnection: SwarmConnection | undefined;
|
|
48
|
+
const { type, timeout = INVITATION_TIMEOUT } = options ?? {};
|
|
49
|
+
assert(type !== Invitation.Type.OFFLINE);
|
|
50
|
+
|
|
51
|
+
const invitation: Invitation = {
|
|
52
|
+
type,
|
|
53
|
+
// type: Invitation.Type.INTERACTIVE_TESTING,
|
|
54
|
+
invitationId: PublicKey.random().toHex(),
|
|
55
|
+
swarmKey: PublicKey.random(),
|
|
56
|
+
spaceKey: space.key,
|
|
57
|
+
authenticationCode: generatePasscode(AUTHENTICATION_CODE_LENGTH)
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// TODO(burdon): Stop anything pending.
|
|
61
|
+
const observable = new InvitationObservableProvider(async () => {
|
|
62
|
+
await swarmConnection?.close();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
let authenticationCode: string;
|
|
66
|
+
const complete = new Trigger<PublicKey>();
|
|
67
|
+
const plugin = new RpcPlugin(async (port) => {
|
|
68
|
+
const peer = createProtoRpcPeer({
|
|
69
|
+
exposed: {
|
|
70
|
+
SpaceHostService: schema.getService('dxos.halo.invitations.SpaceHostService')
|
|
71
|
+
},
|
|
72
|
+
handlers: {
|
|
73
|
+
SpaceHostService: {
|
|
74
|
+
requestAdmission: async () => {
|
|
75
|
+
log('responding with admission offer', {
|
|
76
|
+
host: this._signingContext.deviceKey,
|
|
77
|
+
spaceKey: space.key
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// TODO(burdon): Is this the right place to set this state?
|
|
81
|
+
observable.callback.onAuthenticating?.(invitation);
|
|
82
|
+
return {
|
|
83
|
+
spaceKey: space.key,
|
|
84
|
+
genesisFeedKey: space.genesisFeedKey
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
authenticate: async ({ authenticationCode: code }) => {
|
|
89
|
+
log('received authentication request', { authenticationCode: code });
|
|
90
|
+
authenticationCode = code;
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
presentAdmissionCredentials: async ({ identityKey, deviceKey, controlFeedKey, dataFeedKey }) => {
|
|
94
|
+
try {
|
|
95
|
+
// Check authenticated.
|
|
96
|
+
if (invitation.type === undefined || invitation.type === Invitation.Type.INTERACTIVE) {
|
|
97
|
+
if (
|
|
98
|
+
invitation.authenticationCode === undefined ||
|
|
99
|
+
authenticationCode !== invitation.authenticationCode
|
|
100
|
+
) {
|
|
101
|
+
throw new Error('authentication code not set');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
log('writing guest credentials', { host: this._signingContext.deviceKey, guest: deviceKey });
|
|
106
|
+
// TODO(burdon): Check if already admitted.
|
|
107
|
+
await writeMessages(
|
|
108
|
+
space.controlPipeline.writer,
|
|
109
|
+
await createAdmissionCredentials(
|
|
110
|
+
this._signingContext.credentialSigner,
|
|
111
|
+
identityKey,
|
|
112
|
+
deviceKey,
|
|
113
|
+
space.key,
|
|
114
|
+
controlFeedKey,
|
|
115
|
+
dataFeedKey
|
|
116
|
+
)
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// Updating credentials complete.
|
|
120
|
+
complete.wake(deviceKey);
|
|
121
|
+
} catch (err) {
|
|
122
|
+
// TODO(burdon): Generic RPC callback to report error to client.
|
|
123
|
+
observable.callback.onError(err);
|
|
124
|
+
throw err; // Propagate error to guest.
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
port
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
await peer.open();
|
|
134
|
+
log('connected', { host: this._signingContext.deviceKey });
|
|
135
|
+
observable.callback.onConnected?.(invitation);
|
|
136
|
+
const deviceKey = await complete.wait({ timeout });
|
|
137
|
+
log('admitted guest', { host: this._signingContext.deviceKey, guest: deviceKey });
|
|
138
|
+
observable.callback.onSuccess(invitation);
|
|
139
|
+
} catch (err) {
|
|
140
|
+
if (!observable.cancelled) {
|
|
141
|
+
log.error('failed', err);
|
|
142
|
+
observable.callback.onError(err);
|
|
143
|
+
}
|
|
144
|
+
} finally {
|
|
145
|
+
await sleep(ON_CLOSE_DELAY);
|
|
146
|
+
await peer.close();
|
|
147
|
+
await swarmConnection!.close();
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
setTimeout(async () => {
|
|
152
|
+
const topic = invitation.swarmKey!;
|
|
153
|
+
const peerId = PublicKey.random(); // Use anonymous key.
|
|
154
|
+
swarmConnection = await this._networkManager.openSwarmConnection({
|
|
155
|
+
topic,
|
|
156
|
+
peerId: topic,
|
|
157
|
+
protocol: createProtocolFactory(topic, peerId, [plugin]),
|
|
158
|
+
topology: new StarTopology(topic)
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
observable.callback.onConnecting?.(invitation);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
return observable;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Waits for the host peer (inviter) to accept our join request.
|
|
169
|
+
* The local guest peer (invitee) then sends the local space invitation to the host,
|
|
170
|
+
* which then writes the guest's credentials to the space.
|
|
171
|
+
*/
|
|
172
|
+
acceptInvitation(invitation: Invitation): AuthenticatingInvitationProvider {
|
|
173
|
+
let swarmConnection: SwarmConnection | undefined;
|
|
174
|
+
|
|
175
|
+
const authenticated = new Trigger<string>();
|
|
176
|
+
const observable = new AuthenticatingInvitationProvider({
|
|
177
|
+
onCancel: async () => {
|
|
178
|
+
await swarmConnection?.close();
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
// TODO(burdon): Consider retry.
|
|
182
|
+
onAuthenticate: async (code: string) => {
|
|
183
|
+
authenticated.wake(code);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
let connectionCount = 0;
|
|
188
|
+
const complete = new Trigger();
|
|
189
|
+
const plugin = createRpcPlugin(async (port) => {
|
|
190
|
+
const peer = createProtoRpcPeer({
|
|
191
|
+
requested: {
|
|
192
|
+
SpaceHostService: schema.getService('dxos.halo.invitations.SpaceHostService')
|
|
193
|
+
},
|
|
194
|
+
port
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
await peer.open();
|
|
199
|
+
// TODO(burdon): Bug where guest may create multiple connections.
|
|
200
|
+
if (++connectionCount > 1) {
|
|
201
|
+
throw new Error(`multiple connections detected: ${connectionCount}`);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
log('connected', { guest: this._signingContext.deviceKey });
|
|
205
|
+
observable.callback.onConnected?.(invitation);
|
|
206
|
+
|
|
207
|
+
// 1. Send request.
|
|
208
|
+
log('sending admission request', { guest: this._signingContext.deviceKey });
|
|
209
|
+
const { spaceKey, genesisFeedKey } = await peer.rpc.SpaceHostService.requestAdmission();
|
|
210
|
+
|
|
211
|
+
// 2. Get authentication code.
|
|
212
|
+
// TODO(burdon): Test timeout (options for timeouts at different steps).
|
|
213
|
+
if (invitation.type === undefined || invitation.type === Invitation.Type.INTERACTIVE) {
|
|
214
|
+
log('waiting for authentication code...');
|
|
215
|
+
observable.callback.onAuthenticating?.(invitation);
|
|
216
|
+
const authenticationCode = await authenticated.wait({ timeout: INVITATION_TIMEOUT });
|
|
217
|
+
log('sending authentication request');
|
|
218
|
+
await peer.rpc.SpaceHostService.authenticate({ authenticationCode });
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// 3. Create local space.
|
|
222
|
+
// TODO(burdon): Abandon if does not complete (otherwise retry will fail).
|
|
223
|
+
const space = await this._spaceManager.acceptSpace({ spaceKey, genesisFeedKey });
|
|
224
|
+
|
|
225
|
+
// 4. Send admission credentials to host (with local space keys).
|
|
226
|
+
log('presenting admission credentials', { guest: this._signingContext.deviceKey, spaceKey: space.key });
|
|
227
|
+
await peer.rpc.SpaceHostService.presentAdmissionCredentials({
|
|
228
|
+
identityKey: this._signingContext.identityKey,
|
|
229
|
+
deviceKey: this._signingContext.deviceKey,
|
|
230
|
+
controlFeedKey: space.controlFeedKey,
|
|
231
|
+
dataFeedKey: space.dataFeedKey
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// 5. Success.
|
|
235
|
+
log('admitted by host', { guest: this._signingContext.deviceKey, spaceKey: space.key });
|
|
236
|
+
complete.wake();
|
|
237
|
+
} catch (err) {
|
|
238
|
+
if (!observable.cancelled) {
|
|
239
|
+
log.warn('failed', err);
|
|
240
|
+
observable.callback.onError(err);
|
|
241
|
+
}
|
|
242
|
+
} finally {
|
|
243
|
+
await peer.close();
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
setTimeout(async () => {
|
|
248
|
+
assert(invitation.swarmKey);
|
|
249
|
+
const topic = invitation.swarmKey;
|
|
250
|
+
const peerId = PublicKey.random(); // Use anonymous key.
|
|
251
|
+
swarmConnection = await this._networkManager.openSwarmConnection({
|
|
252
|
+
topic,
|
|
253
|
+
peerId: PublicKey.random(),
|
|
254
|
+
protocol: createProtocolFactory(topic, peerId, [plugin]),
|
|
255
|
+
topology: new StarTopology(topic)
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
observable.callback.onConnecting?.(invitation);
|
|
259
|
+
await complete.wait();
|
|
260
|
+
observable.callback.onSuccess(invitation);
|
|
261
|
+
await swarmConnection.close();
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
return observable;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { PublicKey } from '@dxos/keys';
|
|
6
|
+
|
|
7
|
+
import { AbstractInvitationsProxy } from './invitations-proxy';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Adapts invitation service observable to client/service stream.
|
|
11
|
+
*/
|
|
12
|
+
export class SpaceInvitationsProxy extends AbstractInvitationsProxy<PublicKey> {
|
|
13
|
+
createInvitationObject(spaceKey: PublicKey) {
|
|
14
|
+
return { spaceKey };
|
|
15
|
+
}
|
|
16
|
+
}
|