@dxos/client-services 0.1.4 → 0.1.6
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/LICENSE +5 -18
- package/README.md +14 -10
- package/README.yml +5 -0
- package/dist/src/packlets/deprecated/profile.d.ts +2 -5
- package/dist/src/packlets/deprecated/profile.d.ts.map +1 -1
- package/dist/src/packlets/deprecated/profile.js +1 -73
- package/dist/src/packlets/deprecated/profile.js.map +1 -1
- package/dist/src/packlets/deprecated/system.d.ts +4 -0
- package/dist/src/packlets/deprecated/system.d.ts.map +1 -1
- package/dist/src/packlets/deprecated/system.js +6 -0
- package/dist/src/packlets/deprecated/system.js.map +1 -1
- package/dist/src/packlets/deprecated/tracing.d.ts +1 -1
- package/dist/src/packlets/deprecated/tracing.js +1 -1
- package/dist/src/packlets/devtools/devtools.d.ts +3 -0
- package/dist/src/packlets/devtools/devtools.d.ts.map +1 -1
- package/dist/src/packlets/devtools/devtools.js +3 -1
- package/dist/src/packlets/devtools/devtools.js.map +1 -1
- package/dist/src/packlets/identity/devices-service-impl.d.ts.map +1 -1
- package/dist/src/packlets/identity/devices-service-impl.js.map +1 -1
- package/dist/src/packlets/identity/identity-manager.d.ts +2 -2
- package/dist/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/src/packlets/identity/identity-manager.js +44 -43
- package/dist/src/packlets/identity/identity-manager.js.map +1 -1
- package/dist/src/packlets/identity/identity.d.ts +3 -0
- package/dist/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/src/packlets/identity/identity.js +51 -1
- package/dist/src/packlets/identity/identity.js.map +1 -1
- package/dist/src/packlets/invitations/halo-invitations-handler.d.ts +23 -0
- package/dist/src/packlets/invitations/halo-invitations-handler.d.ts.map +1 -0
- package/dist/src/packlets/invitations/halo-invitations-handler.js +231 -0
- package/dist/src/packlets/invitations/halo-invitations-handler.js.map +1 -0
- package/dist/src/packlets/invitations/halo-invitations-handler.test.d.ts +2 -0
- package/dist/src/packlets/invitations/halo-invitations-handler.test.d.ts.map +1 -0
- package/dist/src/packlets/invitations/halo-invitations-handler.test.js +69 -0
- package/dist/src/packlets/invitations/halo-invitations-handler.test.js.map +1 -0
- package/dist/src/packlets/invitations/halo-invitations-proxy.d.ts +8 -0
- package/dist/src/packlets/invitations/halo-invitations-proxy.d.ts.map +1 -0
- package/dist/src/packlets/invitations/halo-invitations-proxy.js +17 -0
- package/dist/src/packlets/invitations/halo-invitations-proxy.js.map +1 -0
- package/dist/src/packlets/invitations/halo-invitations-service.d.ts +13 -0
- package/dist/src/packlets/invitations/halo-invitations-service.d.ts.map +1 -0
- package/dist/src/packlets/invitations/halo-invitations-service.js +20 -0
- package/dist/src/packlets/invitations/halo-invitations-service.js.map +1 -0
- package/dist/src/packlets/invitations/halo-invitations-service.test.d.ts +2 -0
- package/dist/src/packlets/invitations/halo-invitations-service.test.d.ts.map +1 -0
- package/dist/src/packlets/invitations/halo-invitations-service.test.js +83 -0
- package/dist/src/packlets/invitations/halo-invitations-service.test.js.map +1 -0
- package/dist/src/packlets/invitations/index.d.ts +5 -1
- package/dist/src/packlets/invitations/index.d.ts.map +1 -1
- package/dist/src/packlets/invitations/index.js +5 -1
- package/dist/src/packlets/invitations/index.js.map +1 -1
- package/dist/src/packlets/invitations/invitations-handler.d.ts +48 -0
- package/dist/src/packlets/invitations/invitations-handler.d.ts.map +1 -0
- package/dist/src/packlets/invitations/invitations-handler.js +18 -0
- package/dist/src/packlets/invitations/invitations-handler.js.map +1 -0
- package/dist/src/packlets/invitations/invitations-proxy.d.ts +11 -7
- package/dist/src/packlets/invitations/invitations-proxy.d.ts.map +1 -1
- package/dist/src/packlets/invitations/invitations-proxy.js +5 -10
- package/dist/src/packlets/invitations/invitations-proxy.js.map +1 -1
- package/dist/src/packlets/invitations/invitations-service.d.ts +25 -0
- package/dist/src/packlets/invitations/invitations-service.d.ts.map +1 -0
- package/dist/src/packlets/invitations/invitations-service.js +174 -0
- package/dist/src/packlets/invitations/invitations-service.js.map +1 -0
- package/dist/src/packlets/invitations/invitations.d.ts +10 -42
- package/dist/src/packlets/invitations/invitations.d.ts.map +1 -1
- package/dist/src/packlets/invitations/invitations.js +5 -2
- package/dist/src/packlets/invitations/invitations.js.map +1 -1
- package/dist/src/packlets/invitations/space-invitations-handler.d.ts +6 -6
- package/dist/src/packlets/invitations/space-invitations-handler.d.ts.map +1 -1
- package/dist/src/packlets/invitations/space-invitations-handler.js +18 -19
- package/dist/src/packlets/invitations/space-invitations-handler.js.map +1 -1
- package/dist/src/packlets/invitations/space-invitations-handler.test.js +5 -5
- package/dist/src/packlets/invitations/space-invitations-handler.test.js.map +1 -1
- package/dist/src/packlets/invitations/space-invitations-proxy.d.ts +1 -1
- package/dist/src/packlets/invitations/space-invitations-proxy.d.ts.map +1 -1
- package/dist/src/packlets/invitations/space-invitations-proxy.js +2 -2
- package/dist/src/packlets/invitations/space-invitations-proxy.js.map +1 -1
- package/dist/src/packlets/invitations/space-invitations-service.d.ts +8 -14
- package/dist/src/packlets/invitations/space-invitations-service.d.ts.map +1 -1
- package/dist/src/packlets/invitations/space-invitations-service.js +11 -169
- package/dist/src/packlets/invitations/space-invitations-service.js.map +1 -1
- package/dist/src/packlets/invitations/space-invitations-service.test.js +4 -4
- package/dist/src/packlets/invitations/space-invitations-service.test.js.map +1 -1
- package/dist/src/packlets/services/service-context.d.ts +2 -2
- package/dist/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/src/packlets/services/service-context.js +8 -8
- package/dist/src/packlets/services/service-context.js.map +1 -1
- package/dist/src/packlets/services/service-definitions.d.ts +5 -4
- package/dist/src/packlets/services/service-definitions.d.ts.map +1 -1
- package/dist/src/packlets/services/service-definitions.js +6 -4
- package/dist/src/packlets/services/service-definitions.js.map +1 -1
- package/dist/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/src/packlets/services/service-host.js +10 -8
- package/dist/src/packlets/services/service-host.js.map +1 -1
- package/dist/src/packlets/services/service-proxy.js +1 -1
- package/dist/src/packlets/services/service-registry.test.js +2 -2
- package/dist/src/packlets/services/service-registry.test.js.map +1 -1
- package/dist/src/packlets/vault/iframe-runtime.d.ts +5 -4
- package/dist/src/packlets/vault/iframe-runtime.d.ts.map +1 -1
- package/dist/src/packlets/vault/iframe-runtime.js +4 -12
- package/dist/src/packlets/vault/iframe-runtime.js.map +1 -1
- package/dist/src/packlets/vault/worker-runtime.d.ts +4 -3
- package/dist/src/packlets/vault/worker-runtime.d.ts.map +1 -1
- package/dist/src/packlets/vault/worker-runtime.js +29 -24
- package/dist/src/packlets/vault/worker-runtime.js.map +1 -1
- package/dist/src/packlets/vault/worker-session.d.ts +5 -2
- package/dist/src/packlets/vault/worker-session.d.ts.map +1 -1
- package/dist/src/packlets/vault/worker-session.js +23 -10
- package/dist/src/packlets/vault/worker-session.js.map +1 -1
- package/package.json +26 -26
- package/src/packlets/deprecated/profile.ts +2 -84
- package/src/packlets/deprecated/system.ts +7 -0
- package/src/packlets/deprecated/tracing.ts +1 -1
- package/src/packlets/devtools/devtools.ts +3 -1
- package/src/packlets/identity/devices-service-impl.ts +0 -1
- package/src/packlets/identity/identity-manager.ts +50 -49
- package/src/packlets/identity/identity.ts +58 -1
- package/src/packlets/invitations/halo-invitations-handler.test.ts +79 -0
- package/src/packlets/invitations/halo-invitations-handler.ts +255 -0
- package/src/packlets/invitations/halo-invitations-proxy.ts +14 -0
- package/src/packlets/invitations/halo-invitations-service.test.ts +96 -0
- package/src/packlets/invitations/halo-invitations-service.ts +24 -0
- package/src/packlets/invitations/index.ts +5 -1
- package/src/packlets/invitations/invitations-handler.ts +59 -0
- package/src/packlets/invitations/invitations-proxy.ts +15 -13
- package/src/packlets/invitations/invitations-service.ts +184 -0
- package/src/packlets/invitations/invitations.ts +14 -46
- package/src/packlets/invitations/space-invitations-handler.test.ts +6 -6
- package/src/packlets/invitations/space-invitations-handler.ts +16 -16
- package/src/packlets/invitations/space-invitations-proxy.ts +2 -2
- package/src/packlets/invitations/space-invitations-service.test.ts +13 -13
- package/src/packlets/invitations/space-invitations-service.ts +16 -177
- package/src/packlets/services/service-context.ts +6 -6
- package/src/packlets/services/service-definitions.ts +20 -10
- package/src/packlets/services/service-host.ts +15 -7
- package/src/packlets/services/service-proxy.ts +1 -1
- package/src/packlets/services/service-registry.test.ts +5 -5
- package/src/packlets/vault/iframe-runtime.ts +8 -15
- package/src/packlets/vault/worker-runtime.ts +36 -30
- package/src/packlets/vault/worker-session.ts +20 -6
- package/dist/src/packlets/invitations/halo-invitations.d.ts +0 -23
- package/dist/src/packlets/invitations/halo-invitations.d.ts.map +0 -1
- package/dist/src/packlets/invitations/halo-invitations.js +0 -154
- package/dist/src/packlets/invitations/halo-invitations.js.map +0 -1
- package/dist/src/packlets/invitations/halo-invitations.test.d.ts +0 -2
- package/dist/src/packlets/invitations/halo-invitations.test.d.ts.map +0 -1
- package/dist/src/packlets/invitations/halo-invitations.test.js +0 -34
- package/dist/src/packlets/invitations/halo-invitations.test.js.map +0 -1
- package/dist/src/packlets/services/iframe-service-proxy.d.ts +0 -23
- package/dist/src/packlets/services/iframe-service-proxy.d.ts.map +0 -1
- package/dist/src/packlets/services/iframe-service-proxy.js +0 -53
- package/dist/src/packlets/services/iframe-service-proxy.js.map +0 -1
- package/dist/src/packlets/services/service-host.test.d.ts +0 -2
- package/dist/src/packlets/services/service-host.test.d.ts.map +0 -1
- package/dist/src/packlets/services/service-host.test.js +0 -68
- package/dist/src/packlets/services/service-host.test.js.map +0 -1
- package/src/packlets/invitations/halo-invitations.test.ts +0 -40
- package/src/packlets/invitations/halo-invitations.ts +0 -164
- package/src/packlets/services/iframe-service-proxy.ts +0 -71
- package/src/packlets/services/service-host.test.ts +0 -76
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/client-services",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"description": "DXOS client services implementation",
|
|
4
5
|
"homepage": "https://dxos.org",
|
|
5
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
6
7
|
"license": "MIT",
|
|
@@ -15,29 +16,28 @@
|
|
|
15
16
|
"src"
|
|
16
17
|
],
|
|
17
18
|
"dependencies": {
|
|
18
|
-
"@dxos/async": "0.1.
|
|
19
|
-
"@dxos/codec-protobuf": "0.1.
|
|
20
|
-
"@dxos/config": "0.1.
|
|
21
|
-
"@dxos/credentials": "0.1.
|
|
22
|
-
"@dxos/crypto": "0.1.
|
|
23
|
-
"@dxos/debug": "0.1.
|
|
24
|
-
"@dxos/echo-db": "0.1.
|
|
25
|
-
"@dxos/feed-store": "0.1.
|
|
26
|
-
"@dxos/keyring": "0.1.
|
|
27
|
-
"@dxos/keys": "0.1.
|
|
28
|
-
"@dxos/log": "0.1.
|
|
29
|
-
"@dxos/messaging": "0.1.
|
|
30
|
-
"@dxos/model-factory": "0.1.
|
|
31
|
-
"@dxos/network-manager": "0.1.
|
|
32
|
-
"@dxos/object-model": "0.1.
|
|
33
|
-
"@dxos/protocol-plugin-rpc": "0.1.
|
|
34
|
-
"@dxos/protocols": "0.1.
|
|
35
|
-
"@dxos/random-access-storage": "0.1.
|
|
36
|
-
"@dxos/rpc": "0.1.
|
|
37
|
-
"@dxos/
|
|
38
|
-
"@dxos/
|
|
39
|
-
"@dxos/
|
|
40
|
-
"@dxos/util": "0.1.4",
|
|
19
|
+
"@dxos/async": "0.1.6",
|
|
20
|
+
"@dxos/codec-protobuf": "0.1.6",
|
|
21
|
+
"@dxos/config": "0.1.6",
|
|
22
|
+
"@dxos/credentials": "0.1.6",
|
|
23
|
+
"@dxos/crypto": "0.1.6",
|
|
24
|
+
"@dxos/debug": "0.1.6",
|
|
25
|
+
"@dxos/echo-db": "0.1.6",
|
|
26
|
+
"@dxos/feed-store": "0.1.6",
|
|
27
|
+
"@dxos/keyring": "0.1.6",
|
|
28
|
+
"@dxos/keys": "0.1.6",
|
|
29
|
+
"@dxos/log": "0.1.6",
|
|
30
|
+
"@dxos/messaging": "0.1.6",
|
|
31
|
+
"@dxos/model-factory": "0.1.6",
|
|
32
|
+
"@dxos/network-manager": "0.1.6",
|
|
33
|
+
"@dxos/object-model": "0.1.6",
|
|
34
|
+
"@dxos/protocol-plugin-rpc": "0.1.6",
|
|
35
|
+
"@dxos/protocols": "0.1.6",
|
|
36
|
+
"@dxos/random-access-storage": "0.1.6",
|
|
37
|
+
"@dxos/rpc": "0.1.6",
|
|
38
|
+
"@dxos/text-model": "0.1.6",
|
|
39
|
+
"@dxos/timeframe": "0.1.6",
|
|
40
|
+
"@dxos/util": "0.1.6",
|
|
41
41
|
"abstract-leveldown": "~7.0.0",
|
|
42
42
|
"assert": "^2.0.0",
|
|
43
43
|
"base-x": "~3.0.9",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"memdown": "^5.1.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@dxos/signal": "0.1.
|
|
50
|
-
"@dxos/testutils": "0.1.
|
|
49
|
+
"@dxos/signal": "0.1.6",
|
|
50
|
+
"@dxos/testutils": "0.1.6",
|
|
51
51
|
"@types/level-js": "~4.0.1",
|
|
52
52
|
"@types/memdown": "^3.0.0",
|
|
53
53
|
"@types/readable-stream": "^2.3.9"
|
|
@@ -2,31 +2,22 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import assert from 'node:assert';
|
|
6
|
-
import { v4 } from 'uuid';
|
|
7
|
-
|
|
8
|
-
import { latch } from '@dxos/async';
|
|
9
5
|
import { Stream } from '@dxos/codec-protobuf';
|
|
10
|
-
import { generatePasscode } from '@dxos/credentials';
|
|
11
6
|
import { todo } from '@dxos/debug';
|
|
12
7
|
import {
|
|
13
|
-
AuthenticateInvitationRequest,
|
|
14
8
|
CreateProfileRequest,
|
|
15
|
-
InvitationRequest,
|
|
16
|
-
InvitationState,
|
|
17
9
|
Profile,
|
|
18
10
|
ProfileService,
|
|
19
11
|
RecoverProfileRequest,
|
|
20
|
-
RedeemedInvitation,
|
|
21
12
|
SubscribeProfileResponse
|
|
22
13
|
} from '@dxos/protocols/proto/dxos/client';
|
|
23
|
-
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
24
14
|
|
|
25
15
|
import { ServiceContext } from '../services';
|
|
26
|
-
import {
|
|
16
|
+
import { InviteeInvitations } from './invitations';
|
|
27
17
|
|
|
28
18
|
/**
|
|
29
19
|
* Profile service implementation.
|
|
20
|
+
* @deprecated
|
|
30
21
|
*/
|
|
31
22
|
export class ProfileServiceImpl implements ProfileService {
|
|
32
23
|
private inviteeInvitations: InviteeInvitations = new Map();
|
|
@@ -65,77 +56,4 @@ export class ProfileServiceImpl implements ProfileService {
|
|
|
65
56
|
// assert(profile, 'Recovering profile failed.');
|
|
66
57
|
// return profile;
|
|
67
58
|
}
|
|
68
|
-
|
|
69
|
-
createInvitation(): Stream<InvitationRequest> {
|
|
70
|
-
return new Stream(({ next, close }) => {
|
|
71
|
-
setTimeout(async () => {
|
|
72
|
-
const authenticationCode = generatePasscode();
|
|
73
|
-
// TODO(burdon): Not used.
|
|
74
|
-
// const secretProvider = async () => {
|
|
75
|
-
// next({ descriptor: invitation.toProto(), state: InvitationState.CONNECTED });
|
|
76
|
-
// return Buffer.from(secret);
|
|
77
|
-
// };
|
|
78
|
-
|
|
79
|
-
const invitation = await this.context.haloInvitations.createInvitation({
|
|
80
|
-
onFinish: () => {
|
|
81
|
-
next({ state: InvitationState.SUCCESS });
|
|
82
|
-
close();
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
invitation.authenticationCode = authenticationCode;
|
|
86
|
-
|
|
87
|
-
next({
|
|
88
|
-
state: InvitationState.WAITING_FOR_CONNECTION,
|
|
89
|
-
descriptor: invitation
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
acceptInvitation(invitation: Invitation): Stream<RedeemedInvitation> {
|
|
96
|
-
return new Stream(({ next, close }) => {
|
|
97
|
-
const id = v4();
|
|
98
|
-
const [, secretTrigger] = latch();
|
|
99
|
-
const inviteeInvitation: InviteeInvitation = { secretTrigger };
|
|
100
|
-
|
|
101
|
-
// Secret will be provided separately (in AuthenticateInvitation).
|
|
102
|
-
// Process will continue when `secretLatch` resolves, triggered by `secretTrigger`.
|
|
103
|
-
// const secretProvider: SecretProvider = async () => {
|
|
104
|
-
// await secretLatch;
|
|
105
|
-
// const secret = inviteeInvitation.secret;
|
|
106
|
-
// if (!secret) {
|
|
107
|
-
// throw new Error('Secret not provided.');
|
|
108
|
-
// }
|
|
109
|
-
// return Buffer.from(secret);
|
|
110
|
-
// };
|
|
111
|
-
|
|
112
|
-
// Joining process is kicked off, and will await authentication with a secret.
|
|
113
|
-
const haloSpacePromise = this.context.haloInvitations.acceptInvitation(invitation);
|
|
114
|
-
this.inviteeInvitations.set(id, inviteeInvitation);
|
|
115
|
-
next({ id, state: InvitationState.CONNECTED });
|
|
116
|
-
|
|
117
|
-
haloSpacePromise
|
|
118
|
-
.then((identity) => {
|
|
119
|
-
next({
|
|
120
|
-
id,
|
|
121
|
-
state: InvitationState.SUCCESS,
|
|
122
|
-
spaceKey: identity.identityKey
|
|
123
|
-
});
|
|
124
|
-
})
|
|
125
|
-
.catch((err) => {
|
|
126
|
-
next({ id, state: InvitationState.ERROR, error: String(err) });
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
async authenticateInvitation(request: AuthenticateInvitationRequest) {
|
|
132
|
-
assert(request.processId, 'Process ID is missing.');
|
|
133
|
-
const invitation = this.inviteeInvitations.get(request.processId);
|
|
134
|
-
assert(invitation, 'Invitation not found.');
|
|
135
|
-
assert(request.secret, 'Secret not provided.');
|
|
136
|
-
|
|
137
|
-
// Supply the secret, and move the internal invitation process by triggering the secretTrigger.
|
|
138
|
-
invitation.secret = request.secret;
|
|
139
|
-
invitation.secretTrigger?.();
|
|
140
|
-
}
|
|
141
59
|
}
|
|
@@ -6,9 +6,16 @@ import { Config } from '@dxos/config';
|
|
|
6
6
|
import { todo } from '@dxos/debug';
|
|
7
7
|
import { SystemService } from '@dxos/protocols/proto/dxos/client';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @deprecated
|
|
11
|
+
*/
|
|
9
12
|
export class SystemServiceImpl implements SystemService {
|
|
10
13
|
constructor(private readonly _config: Config) {}
|
|
11
14
|
|
|
15
|
+
async initSession() {
|
|
16
|
+
// Ok.
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
async getConfig(request: void) {
|
|
13
20
|
return this._config.values;
|
|
14
21
|
}
|
|
@@ -42,7 +42,6 @@ import { subscribeToFeedBlocks, subscribeToFeeds } from './feeds';
|
|
|
42
42
|
import { subscribeToNetworkStatus, subscribeToSignalTrace, subscribeToSwarmInfo } from './network';
|
|
43
43
|
import { subscribeToSpaces } from './spaces';
|
|
44
44
|
|
|
45
|
-
// TODO(burdon): Remove?
|
|
46
45
|
export class DevtoolsHostEvents {
|
|
47
46
|
readonly ready = new AsyncEvent();
|
|
48
47
|
}
|
|
@@ -53,6 +52,9 @@ export type DevtoolsServiceParams = {
|
|
|
53
52
|
context: ServiceContext;
|
|
54
53
|
};
|
|
55
54
|
|
|
55
|
+
/**
|
|
56
|
+
* @deprecated
|
|
57
|
+
*/
|
|
56
58
|
export class DevtoolsServiceImpl implements DevtoolsHost {
|
|
57
59
|
constructor(private readonly params: DevtoolsServiceParams) {}
|
|
58
60
|
|
|
@@ -74,54 +74,6 @@ export class IdentityManager {
|
|
|
74
74
|
await this._identity?.close();
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
private async _constructIdentity(identityRecord: IdentityRecord) {
|
|
78
|
-
assert(!this._identity);
|
|
79
|
-
log('constructing identity', { identityRecord });
|
|
80
|
-
|
|
81
|
-
const space = await this._constructSpace({
|
|
82
|
-
spaceRecord: identityRecord.haloSpace,
|
|
83
|
-
swarmIdentity: {
|
|
84
|
-
peerKey: identityRecord.deviceKey,
|
|
85
|
-
credentialProvider: MOCK_AUTH_PROVIDER,
|
|
86
|
-
credentialAuthenticator: MOCK_AUTH_VERIFIER
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
log('done', { identityKey: identityRecord.identityKey });
|
|
91
|
-
return new Identity({
|
|
92
|
-
space,
|
|
93
|
-
signer: this._keyring,
|
|
94
|
-
identityKey: identityRecord.identityKey,
|
|
95
|
-
deviceKey: identityRecord.deviceKey
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
private async _constructSpace({ spaceRecord, swarmIdentity }: ConstructSpaceParams) {
|
|
100
|
-
const controlFeed = await this._feedStore.openFeed(spaceRecord.writeControlFeedKey, { writable: true });
|
|
101
|
-
const dataFeed = await this._feedStore.openFeed(spaceRecord.writeDataFeedKey, { writable: true });
|
|
102
|
-
|
|
103
|
-
// The genesis feed will be the same as the control feed if the space was created by the local agent.
|
|
104
|
-
// NOTE: Must be initialized after writable feeds so that it is in a writable state.
|
|
105
|
-
const genesisFeed = await this._feedStore.openFeed(spaceRecord.genesisFeedKey);
|
|
106
|
-
|
|
107
|
-
const protocol = new SpaceProtocol({
|
|
108
|
-
topic: spaceRecord.spaceKey,
|
|
109
|
-
identity: swarmIdentity,
|
|
110
|
-
networkManager: this._networkManager
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
return new Space({
|
|
114
|
-
spaceKey: spaceRecord.spaceKey,
|
|
115
|
-
protocol,
|
|
116
|
-
genesisFeed,
|
|
117
|
-
controlFeed,
|
|
118
|
-
dataFeed,
|
|
119
|
-
feedProvider: (feedKey) => this._feedStore.openFeed(feedKey),
|
|
120
|
-
databaseFactory: async ({ databaseBackend }) =>
|
|
121
|
-
new Database(this._modelFactory, databaseBackend, swarmIdentity.peerKey)
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
77
|
async createIdentity() {
|
|
126
78
|
assert(!this._identity, 'Identity already exists.');
|
|
127
79
|
log('creating identity...');
|
|
@@ -169,6 +121,7 @@ export class IdentityManager {
|
|
|
169
121
|
}
|
|
170
122
|
}
|
|
171
123
|
|
|
124
|
+
// TODO(burdon): ???
|
|
172
125
|
// await this._keyring.deleteKey(identityRecord.identity_key);
|
|
173
126
|
// await this._keyring.deleteKey(identityRecord.halo_space.space_key);
|
|
174
127
|
|
|
@@ -177,7 +130,7 @@ export class IdentityManager {
|
|
|
177
130
|
await this._identity.ready();
|
|
178
131
|
this.stateUpdate.emit();
|
|
179
132
|
|
|
180
|
-
log('created identity', { identityKey: identity.identityKey });
|
|
133
|
+
log('created identity', { identityKey: identity.identityKey, deviceKey: identity.deviceKey });
|
|
181
134
|
return identity;
|
|
182
135
|
}
|
|
183
136
|
|
|
@@ -204,4 +157,52 @@ export class IdentityManager {
|
|
|
204
157
|
this.stateUpdate.emit();
|
|
205
158
|
return identity;
|
|
206
159
|
}
|
|
160
|
+
|
|
161
|
+
private async _constructIdentity(identityRecord: IdentityRecord) {
|
|
162
|
+
assert(!this._identity);
|
|
163
|
+
log('constructing identity', { identityRecord });
|
|
164
|
+
|
|
165
|
+
const space = await this._constructSpace({
|
|
166
|
+
spaceRecord: identityRecord.haloSpace,
|
|
167
|
+
swarmIdentity: {
|
|
168
|
+
peerKey: identityRecord.deviceKey,
|
|
169
|
+
credentialProvider: MOCK_AUTH_PROVIDER,
|
|
170
|
+
credentialAuthenticator: MOCK_AUTH_VERIFIER
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
log('done', { identityKey: identityRecord.identityKey });
|
|
175
|
+
return new Identity({
|
|
176
|
+
space,
|
|
177
|
+
signer: this._keyring,
|
|
178
|
+
identityKey: identityRecord.identityKey,
|
|
179
|
+
deviceKey: identityRecord.deviceKey
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private async _constructSpace({ spaceRecord, swarmIdentity }: ConstructSpaceParams) {
|
|
184
|
+
const controlFeed = await this._feedStore.openFeed(spaceRecord.writeControlFeedKey, { writable: true });
|
|
185
|
+
const dataFeed = await this._feedStore.openFeed(spaceRecord.writeDataFeedKey, { writable: true });
|
|
186
|
+
|
|
187
|
+
// The genesis feed will be the same as the control feed if the space was created by the local agent.
|
|
188
|
+
// NOTE: Must be initialized after writable feeds so that it is in a writable state.
|
|
189
|
+
const genesisFeed = await this._feedStore.openFeed(spaceRecord.genesisFeedKey);
|
|
190
|
+
|
|
191
|
+
const protocol = new SpaceProtocol({
|
|
192
|
+
topic: spaceRecord.spaceKey,
|
|
193
|
+
identity: swarmIdentity,
|
|
194
|
+
networkManager: this._networkManager
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
return new Space({
|
|
198
|
+
spaceKey: spaceRecord.spaceKey,
|
|
199
|
+
protocol,
|
|
200
|
+
genesisFeed,
|
|
201
|
+
controlFeed,
|
|
202
|
+
dataFeed,
|
|
203
|
+
feedProvider: (feedKey) => this._feedStore.openFeed(feedKey),
|
|
204
|
+
databaseFactory: async ({ databaseBackend }) =>
|
|
205
|
+
new Database(this._modelFactory, databaseBackend, swarmIdentity.peerKey)
|
|
206
|
+
});
|
|
207
|
+
}
|
|
207
208
|
}
|
|
@@ -14,7 +14,12 @@ import {
|
|
|
14
14
|
import { Signer } from '@dxos/crypto';
|
|
15
15
|
import { failUndefined } from '@dxos/debug';
|
|
16
16
|
import { Database, Space } from '@dxos/echo-db';
|
|
17
|
+
import { writeMessages } from '@dxos/feed-store';
|
|
17
18
|
import { PublicKey } from '@dxos/keys';
|
|
19
|
+
import { log } from '@dxos/log';
|
|
20
|
+
import { TypedMessage } from '@dxos/protocols';
|
|
21
|
+
import { AdmittedFeed } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
22
|
+
import { HaloAdmissionCredentials } from '@dxos/protocols/proto/dxos/halo/invitations';
|
|
18
23
|
import { ComplexSet } from '@dxos/util';
|
|
19
24
|
|
|
20
25
|
export type IdentityParams = {
|
|
@@ -46,7 +51,7 @@ export class Identity {
|
|
|
46
51
|
|
|
47
52
|
this._deviceStateMachine = new DeviceStateMachine(this.identityKey, this.deviceKey);
|
|
48
53
|
|
|
49
|
-
// Save device
|
|
54
|
+
// Save device keychain credential when processed by the space state machine.
|
|
50
55
|
this._space.onCredentialProcessed.set(async (credential) => {
|
|
51
56
|
await this._deviceStateMachine.process(credential);
|
|
52
57
|
this.stateUpdate.emit();
|
|
@@ -91,6 +96,14 @@ export class Identity {
|
|
|
91
96
|
return this._space.database ?? failUndefined();
|
|
92
97
|
}
|
|
93
98
|
|
|
99
|
+
getAdmissionCredentials(): HaloAdmissionCredentials {
|
|
100
|
+
return {
|
|
101
|
+
deviceKey: this.deviceKey,
|
|
102
|
+
controlFeedKey: this._space.controlFeedKey,
|
|
103
|
+
dataFeedKey: this._space.dataFeedKey
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
94
107
|
/**
|
|
95
108
|
* Issues credentials as identity.
|
|
96
109
|
* Requires identity to be ready.
|
|
@@ -110,4 +123,48 @@ export class Identity {
|
|
|
110
123
|
getDeviceCredentialSigner(): CredentialSigner {
|
|
111
124
|
return createCredentialSignerWithKey(this._signer, this.deviceKey);
|
|
112
125
|
}
|
|
126
|
+
|
|
127
|
+
async admitDevice({ deviceKey, controlFeedKey, dataFeedKey }: HaloAdmissionCredentials) {
|
|
128
|
+
log('Admitting device:', {
|
|
129
|
+
identityKey: this.identityKey,
|
|
130
|
+
hostDevice: this.deviceKey,
|
|
131
|
+
deviceKey,
|
|
132
|
+
controlFeedKey,
|
|
133
|
+
dataFeedKey
|
|
134
|
+
});
|
|
135
|
+
const signer = this.getIdentityCredentialSigner();
|
|
136
|
+
await writeMessages(
|
|
137
|
+
this.controlPipeline.writer,
|
|
138
|
+
[
|
|
139
|
+
await signer.createCredential({
|
|
140
|
+
subject: deviceKey,
|
|
141
|
+
assertion: {
|
|
142
|
+
'@type': 'dxos.halo.credentials.AuthorizedDevice',
|
|
143
|
+
identityKey: this.identityKey,
|
|
144
|
+
deviceKey
|
|
145
|
+
}
|
|
146
|
+
}),
|
|
147
|
+
await signer.createCredential({
|
|
148
|
+
subject: controlFeedKey,
|
|
149
|
+
assertion: {
|
|
150
|
+
'@type': 'dxos.halo.credentials.AdmittedFeed',
|
|
151
|
+
spaceKey: this.haloSpaceKey,
|
|
152
|
+
deviceKey,
|
|
153
|
+
identityKey: this.identityKey,
|
|
154
|
+
designation: AdmittedFeed.Designation.CONTROL
|
|
155
|
+
}
|
|
156
|
+
}),
|
|
157
|
+
await signer.createCredential({
|
|
158
|
+
subject: dataFeedKey,
|
|
159
|
+
assertion: {
|
|
160
|
+
'@type': 'dxos.halo.credentials.AdmittedFeed',
|
|
161
|
+
spaceKey: this.haloSpaceKey,
|
|
162
|
+
deviceKey,
|
|
163
|
+
identityKey: this.identityKey,
|
|
164
|
+
designation: AdmittedFeed.Designation.DATA
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
].map((credential): TypedMessage => ({ '@type': 'dxos.echo.feed.CredentialsMessage', credential }))
|
|
168
|
+
);
|
|
169
|
+
}
|
|
113
170
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
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 { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
12
|
+
import { afterTest } from '@dxos/testutils';
|
|
13
|
+
|
|
14
|
+
import { ServiceContext } from '../services';
|
|
15
|
+
import { createPeers, createServiceContext } from '../testing';
|
|
16
|
+
|
|
17
|
+
const closeAfterTest = async (peer: ServiceContext) => {
|
|
18
|
+
afterTest(() => peer.close());
|
|
19
|
+
return peer;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
describe('services/halo', function () {
|
|
23
|
+
it('creates identity', async function () {
|
|
24
|
+
const peer = createServiceContext();
|
|
25
|
+
await peer.open();
|
|
26
|
+
afterTest(() => peer.close());
|
|
27
|
+
|
|
28
|
+
const identity = await peer.createIdentity();
|
|
29
|
+
expect(identity).not.to.be.undefined;
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('creates and accepts invitation', async function () {
|
|
33
|
+
const [host, guest] = await asyncChain<ServiceContext>([closeAfterTest])(createPeers(2));
|
|
34
|
+
|
|
35
|
+
const identity1 = await host.createIdentity();
|
|
36
|
+
expect(host.identityManager.identity).to.eq(identity1);
|
|
37
|
+
|
|
38
|
+
const observable1 = await host.haloInvitations.createInvitation();
|
|
39
|
+
|
|
40
|
+
const complete1 = new Trigger<PublicKey>();
|
|
41
|
+
const complete2 = new Trigger<PublicKey>();
|
|
42
|
+
|
|
43
|
+
const authenticationCode = new Trigger<string>();
|
|
44
|
+
|
|
45
|
+
observable1.subscribe({
|
|
46
|
+
onConnecting: async (invitation1: Invitation) => {
|
|
47
|
+
const observable2 = guest.haloInvitations!.acceptInvitation(invitation1);
|
|
48
|
+
observable2.subscribe({
|
|
49
|
+
onConnecting: async () => {},
|
|
50
|
+
onConnected: async (invitation2: Invitation) => {
|
|
51
|
+
expect(invitation1.swarmKey).to.eq(invitation2.swarmKey);
|
|
52
|
+
},
|
|
53
|
+
onAuthenticating: async () => {
|
|
54
|
+
await observable2.authenticate(await authenticationCode.wait());
|
|
55
|
+
},
|
|
56
|
+
onSuccess: (invitation: Invitation) => {
|
|
57
|
+
complete2.wake(invitation.identityKey!);
|
|
58
|
+
},
|
|
59
|
+
onCancelled: () => raise(new Error()),
|
|
60
|
+
onTimeout: (err: Error) => raise(new Error(err.message)),
|
|
61
|
+
onError: (err: Error) => raise(new Error(err.message))
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
onConnected: (invitation: Invitation) => {
|
|
65
|
+
assert(invitation.authenticationCode);
|
|
66
|
+
authenticationCode.wake(invitation.authenticationCode);
|
|
67
|
+
},
|
|
68
|
+
onSuccess: (invitation: Invitation) => {
|
|
69
|
+
complete1.wake(host.identityManager.identity!.identityKey);
|
|
70
|
+
},
|
|
71
|
+
onCancelled: () => raise(new Error()),
|
|
72
|
+
onTimeout: (err: Error) => raise(new Error(err.message)),
|
|
73
|
+
onError: (err: Error) => raise(new Error(err.message))
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const [identityKey1, identityKey2] = await Promise.all([complete1.wait(), complete2.wait()]);
|
|
77
|
+
expect(identityKey1).to.deep.eq(identityKey2);
|
|
78
|
+
});
|
|
79
|
+
});
|