@dxos/client-services 0.6.13 → 0.6.14-main.1366248
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/{chunk-CRXXOI45.mjs → chunk-KQURG5PQ.mjs} +6537 -5279
- package/dist/lib/browser/chunk-KQURG5PQ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +7 -3
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +20 -9
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-PZ3JJJ3K.cjs → chunk-WNXJ7EP5.cjs} +6324 -5068
- package/dist/lib/node/chunk-WNXJ7EP5.cjs.map +7 -0
- package/dist/lib/node/index.cjs +50 -46
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +26 -14
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/lib/node-esm/chunk-OQSP5ADY.mjs +8982 -0
- package/dist/lib/node-esm/chunk-OQSP5ADY.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +420 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/testing/index.mjs +431 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +35 -0
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -0
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts +10 -0
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -0
- package/dist/types/src/packlets/agents/index.d.ts +3 -0
- package/dist/types/src/packlets/agents/index.d.ts.map +1 -0
- package/dist/types/src/packlets/devices/devices-service.d.ts +3 -1
- package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.node.test.d.ts +2 -0
- package/dist/types/src/packlets/identity/authenticator.node.test.d.ts.map +1 -0
- package/dist/types/src/packlets/identity/contacts-service.d.ts +1 -1
- package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-manager.d.ts +28 -9
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +18 -0
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -0
- package/dist/types/src/packlets/identity/identity-service.d.ts +7 -2
- package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +12 -3
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts +31 -0
- package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -0
- package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts +2 -1
- package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts +2 -1
- package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-state.d.ts +19 -0
- package/dist/types/src/packlets/invitations/invitation-state.d.ts.map +1 -0
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts +8 -8
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +14 -9
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +2 -0
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +7 -3
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +5 -3
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +4 -0
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.test.d.ts +2 -0
- package/dist/types/src/packlets/spaces/edge-feed-replicator.test.d.ts.map +1 -0
- package/dist/types/src/packlets/spaces/epoch-migrations.d.ts +1 -1
- package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +35 -6
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts +1 -2
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
- package/dist/types/src/testing/setup.d.ts +3 -0
- package/dist/types/src/testing/setup.d.ts.map +1 -0
- package/dist/types/src/version.d.ts +1 -1
- package/dist/types/src/version.d.ts.map +1 -1
- package/package.json +44 -45
- package/src/index.ts +1 -0
- package/src/packlets/agents/edge-agent-manager.ts +163 -0
- package/src/packlets/agents/edge-agent-service.ts +42 -0
- package/src/packlets/agents/index.ts +6 -0
- package/src/packlets/devices/devices-service.test.ts +4 -5
- package/src/packlets/devices/devices-service.ts +18 -7
- package/src/packlets/diagnostics/diagnostics-broadcast.ts +1 -0
- package/src/packlets/identity/{authenticator.test.ts → authenticator.node.test.ts} +2 -3
- package/src/packlets/identity/authenticator.ts +5 -2
- package/src/packlets/identity/contacts-service.ts +1 -1
- package/src/packlets/identity/identity-manager.test.ts +31 -16
- package/src/packlets/identity/identity-manager.ts +76 -32
- package/src/packlets/identity/identity-recovery-manager.ts +95 -0
- package/src/packlets/identity/identity-service.test.ts +5 -8
- package/src/packlets/identity/identity-service.ts +11 -5
- package/src/packlets/identity/identity.test.ts +141 -239
- package/src/packlets/identity/identity.ts +60 -17
- package/src/packlets/invitations/device-invitation-protocol.test.ts +7 -4
- package/src/packlets/invitations/device-invitation-protocol.ts +8 -2
- package/src/packlets/invitations/edge-invitation-handler.ts +188 -0
- package/src/packlets/invitations/invitation-guest-extenstion.ts +13 -9
- package/src/packlets/invitations/invitation-host-extension.ts +15 -17
- package/src/packlets/invitations/invitation-state.ts +112 -0
- package/src/packlets/invitations/invitations-handler.test.ts +19 -15
- package/src/packlets/invitations/invitations-handler.ts +91 -126
- package/src/packlets/invitations/invitations-service.ts +5 -1
- package/src/packlets/invitations/space-invitation-protocol.test.ts +4 -3
- package/src/packlets/invitations/space-invitation-protocol.ts +5 -0
- package/src/packlets/logging/logging.test.ts +1 -2
- package/src/packlets/network/network-service.test.ts +2 -3
- package/src/packlets/services/service-context.test.ts +3 -1
- package/src/packlets/services/service-context.ts +113 -35
- package/src/packlets/services/service-host.test.ts +8 -12
- package/src/packlets/services/service-host.ts +26 -8
- package/src/packlets/services/service-registry.test.ts +1 -2
- package/src/packlets/spaces/data-space-manager.test.ts +2 -2
- package/src/packlets/spaces/data-space-manager.ts +44 -7
- package/src/packlets/spaces/data-space.ts +37 -6
- package/src/packlets/spaces/edge-feed-replicator.test.ts +257 -0
- package/src/packlets/spaces/edge-feed-replicator.ts +84 -22
- package/src/packlets/spaces/epoch-migrations.ts +2 -2
- package/src/packlets/spaces/notarization-plugin.test.ts +10 -7
- package/src/packlets/spaces/notarization-plugin.ts +196 -29
- package/src/packlets/spaces/spaces-service.test.ts +5 -9
- package/src/packlets/spaces/spaces-service.ts +6 -1
- package/src/packlets/storage/storage.ts +0 -1
- package/src/packlets/system/system-service.test.ts +1 -2
- package/src/packlets/testing/invitation-utils.ts +7 -0
- package/src/packlets/testing/test-builder.ts +7 -4
- package/src/packlets/worker/worker-runtime.ts +2 -2
- package/src/testing/setup.ts +11 -0
- package/src/version.ts +1 -5
- package/dist/lib/browser/chunk-CRXXOI45.mjs.map +0 -7
- package/dist/lib/node/chunk-PZ3JJJ3K.cjs.map +0 -7
- package/dist/types/src/packlets/identity/authenticator.test.d.ts +0 -2
- package/dist/types/src/packlets/identity/authenticator.test.d.ts.map +0 -1
- package/dist/types/src/packlets/services/automerge-host.test.d.ts +0 -2
- package/dist/types/src/packlets/services/automerge-host.test.d.ts.map +0 -1
- package/src/packlets/services/automerge-host.test.ts +0 -60
|
@@ -2,21 +2,17 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
import chaiAsPromised from 'chai-as-promised';
|
|
5
|
+
import { afterEach, onTestFinished, beforeEach, describe, expect, test } from 'vitest';
|
|
7
6
|
|
|
8
7
|
import { Trigger } from '@dxos/async';
|
|
9
8
|
import { Context } from '@dxos/context';
|
|
10
9
|
import { PublicKey } from '@dxos/keys';
|
|
11
10
|
import { type Identity, type IdentityService } from '@dxos/protocols/proto/dxos/client/services';
|
|
12
|
-
import { afterEach, afterTest, beforeEach, describe, test } from '@dxos/test';
|
|
13
11
|
|
|
14
12
|
import { IdentityServiceImpl } from './identity-service';
|
|
15
13
|
import { type ServiceContext } from '../services';
|
|
16
14
|
import { createServiceContext } from '../testing';
|
|
17
15
|
|
|
18
|
-
chai.use(chaiAsPromised);
|
|
19
|
-
|
|
20
16
|
describe('IdentityService', () => {
|
|
21
17
|
let serviceContext: ServiceContext;
|
|
22
18
|
let identityService: IdentityService;
|
|
@@ -49,7 +45,7 @@ describe('IdentityService', () => {
|
|
|
49
45
|
|
|
50
46
|
test('fails to create identity if one already exists', async () => {
|
|
51
47
|
await identityService.createIdentity({});
|
|
52
|
-
await expect(identityService.createIdentity({})).
|
|
48
|
+
await expect(identityService.createIdentity({})).rejects.toThrowError('Identity already exists');
|
|
53
49
|
});
|
|
54
50
|
});
|
|
55
51
|
|
|
@@ -72,7 +68,7 @@ describe('IdentityService', () => {
|
|
|
72
68
|
query.subscribe(({ identity }) => {
|
|
73
69
|
result.wake(identity);
|
|
74
70
|
});
|
|
75
|
-
|
|
71
|
+
onTestFinished(() => query.close());
|
|
76
72
|
expect(await result.wait()).to.be.undefined;
|
|
77
73
|
});
|
|
78
74
|
|
|
@@ -82,7 +78,7 @@ describe('IdentityService', () => {
|
|
|
82
78
|
query.subscribe(({ identity }) => {
|
|
83
79
|
result.wake(identity);
|
|
84
80
|
});
|
|
85
|
-
|
|
81
|
+
onTestFinished(() => query.close());
|
|
86
82
|
expect(await result.wait()).to.be.undefined;
|
|
87
83
|
|
|
88
84
|
result = new Trigger<Identity | undefined>();
|
|
@@ -120,6 +116,7 @@ describe('open', () => {
|
|
|
120
116
|
const createIdentityService = (serviceContext: ServiceContext) => {
|
|
121
117
|
return new IdentityServiceImpl(
|
|
122
118
|
serviceContext.identityManager,
|
|
119
|
+
serviceContext.recoveryManager,
|
|
123
120
|
serviceContext.keyring,
|
|
124
121
|
() => serviceContext.dataSpaceManager!,
|
|
125
122
|
(options) => serviceContext.createIdentity(options),
|
|
@@ -6,7 +6,6 @@ import { Trigger, sleep } from '@dxos/async';
|
|
|
6
6
|
import { Stream } from '@dxos/codec-protobuf';
|
|
7
7
|
import { Resource } from '@dxos/context';
|
|
8
8
|
import { signPresentation } from '@dxos/credentials';
|
|
9
|
-
import { todo } from '@dxos/debug';
|
|
10
9
|
import { invariant } from '@dxos/invariant';
|
|
11
10
|
import { type Keyring } from '@dxos/keyring';
|
|
12
11
|
import { log } from '@dxos/log';
|
|
@@ -24,6 +23,7 @@ import { safeAwaitAll } from '@dxos/util';
|
|
|
24
23
|
|
|
25
24
|
import { type Identity } from './identity';
|
|
26
25
|
import { type CreateIdentityOptions, type IdentityManager } from './identity-manager';
|
|
26
|
+
import { type EdgeIdentityRecoveryManager } from './identity-recovery-manager';
|
|
27
27
|
import { type DataSpaceManager } from '../spaces';
|
|
28
28
|
|
|
29
29
|
const DEFAULT_SPACE_SEARCH_TIMEOUT = 10_000;
|
|
@@ -31,6 +31,7 @@ const DEFAULT_SPACE_SEARCH_TIMEOUT = 10_000;
|
|
|
31
31
|
export class IdentityServiceImpl extends Resource implements IdentityService {
|
|
32
32
|
constructor(
|
|
33
33
|
private readonly _identityManager: IdentityManager,
|
|
34
|
+
private readonly _recoveryManager: EdgeIdentityRecoveryManager,
|
|
34
35
|
private readonly _keyring: Keyring,
|
|
35
36
|
private readonly _dataSpaceManagerProvider: () => DataSpaceManager,
|
|
36
37
|
private readonly _createIdentity: (params: CreateIdentityOptions) => Promise<Identity>,
|
|
@@ -60,10 +61,6 @@ export class IdentityServiceImpl extends Resource implements IdentityService {
|
|
|
60
61
|
await identity.updateDefaultSpace(space.id);
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
async recoverIdentity(request: RecoverIdentityRequest): Promise<IdentityProto> {
|
|
64
|
-
return todo();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
64
|
queryIdentity(): Stream<QueryIdentityResponse> {
|
|
68
65
|
return new Stream(({ next }) => {
|
|
69
66
|
const emitNext = () => next({ identity: this._getIdentity() });
|
|
@@ -92,6 +89,15 @@ export class IdentityServiceImpl extends Resource implements IdentityService {
|
|
|
92
89
|
return this._getIdentity()!;
|
|
93
90
|
}
|
|
94
91
|
|
|
92
|
+
async createRecoveryPhrase() {
|
|
93
|
+
return this._recoveryManager.createRecoveryPhrase();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async recoverIdentity(request: RecoverIdentityRequest): Promise<IdentityProto> {
|
|
97
|
+
await this._recoveryManager.recoverIdentity(request);
|
|
98
|
+
return this._getIdentity()!;
|
|
99
|
+
}
|
|
100
|
+
|
|
95
101
|
// TODO(burdon): Rename createPresentation?
|
|
96
102
|
async signPresentation({ presentation, nonce }: SignPresentationRequest): Promise<Presentation> {
|
|
97
103
|
invariant(this._identityManager.identity, 'Identity not initialized.');
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import expect from '
|
|
5
|
+
import { onTestFinished, describe, expect, test } from 'vitest';
|
|
6
6
|
|
|
7
7
|
import { Context } from '@dxos/context';
|
|
8
8
|
import { CredentialGenerator, verifyCredential } from '@dxos/credentials';
|
|
@@ -15,7 +15,9 @@ import {
|
|
|
15
15
|
SpaceProtocol,
|
|
16
16
|
valueEncoding,
|
|
17
17
|
} from '@dxos/echo-pipeline';
|
|
18
|
+
import { type EdgeConnection, type MessageListener } from '@dxos/edge-client';
|
|
18
19
|
import { FeedFactory, FeedStore } from '@dxos/feed-store';
|
|
20
|
+
import { type FeedWrapper } from '@dxos/feed-store';
|
|
19
21
|
import { Keyring } from '@dxos/keyring';
|
|
20
22
|
import { type PublicKey } from '@dxos/keys';
|
|
21
23
|
import { MemorySignalManager, MemorySignalManagerContext } from '@dxos/messaging';
|
|
@@ -24,7 +26,6 @@ import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
|
24
26
|
import { AdmittedFeed } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
25
27
|
import { createStorage, StorageType } from '@dxos/random-access-storage';
|
|
26
28
|
import { BlobStore } from '@dxos/teleport-extension-object-sync';
|
|
27
|
-
import { afterTest, describe, test } from '@dxos/test';
|
|
28
29
|
|
|
29
30
|
import { Identity } from './identity';
|
|
30
31
|
|
|
@@ -42,16 +43,120 @@ const createStores = () => {
|
|
|
42
43
|
|
|
43
44
|
describe('identity/identity', () => {
|
|
44
45
|
test('create', async () => {
|
|
46
|
+
const setup = await setupIdentity();
|
|
47
|
+
|
|
48
|
+
await writeGenesisCredential(setup);
|
|
49
|
+
|
|
50
|
+
// Wait for identity to be ready.
|
|
51
|
+
await setup.identity.ready();
|
|
52
|
+
const identitySigner = setup.identity.getIdentityCredentialSigner();
|
|
53
|
+
const credential = await identitySigner.createCredential({
|
|
54
|
+
subject: setup.identityKey,
|
|
55
|
+
assertion: {
|
|
56
|
+
'@type': 'dxos.halo.credentials.IdentityProfile',
|
|
57
|
+
profile: {
|
|
58
|
+
displayName: 'Alice',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
expect(credential.issuer).toEqual(setup.identityKey);
|
|
64
|
+
expect(await verifyCredential(credential)).toEqual({ kind: 'pass' });
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('two devices', async () => {
|
|
68
|
+
const signalContext = new MemorySignalManagerContext();
|
|
69
|
+
|
|
70
|
+
const owner = await setupIdentity({ signalContext });
|
|
71
|
+
await writeGenesisCredential(owner);
|
|
72
|
+
await owner.identity.ready();
|
|
73
|
+
|
|
74
|
+
const secondDevice = (
|
|
75
|
+
await setupIdentity({
|
|
76
|
+
signalContext,
|
|
77
|
+
spaceKey: owner.spaceKey,
|
|
78
|
+
identityKey: owner.identityKey,
|
|
79
|
+
genesisFeedKey: owner.controlFeed.key,
|
|
80
|
+
})
|
|
81
|
+
).identity;
|
|
82
|
+
|
|
83
|
+
//
|
|
84
|
+
// Second device admission
|
|
85
|
+
//
|
|
86
|
+
{
|
|
87
|
+
const signer = owner.identity.getIdentityCredentialSigner();
|
|
88
|
+
void owner.identity.controlPipeline.writer.write({
|
|
89
|
+
credential: {
|
|
90
|
+
credential: await signer.createCredential({
|
|
91
|
+
subject: secondDevice.deviceKey,
|
|
92
|
+
assertion: {
|
|
93
|
+
'@type': 'dxos.halo.credentials.AuthorizedDevice',
|
|
94
|
+
identityKey: owner.identityKey,
|
|
95
|
+
deviceKey: secondDevice.deviceKey,
|
|
96
|
+
},
|
|
97
|
+
}),
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
await secondDevice.ready();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
expect(Array.from(owner.identity.authorizedDeviceKeys.keys())).toEqual([owner.deviceKey, secondDevice.deviceKey]);
|
|
105
|
+
expect(Array.from(secondDevice.authorizedDeviceKeys.keys())).toEqual([owner.deviceKey, secondDevice.deviceKey]);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test('edge feed replicator', async () => {
|
|
109
|
+
let replicationStarted = false;
|
|
110
|
+
let isConnected = false;
|
|
111
|
+
const listeners: Array<() => void> = [];
|
|
112
|
+
const setup = await setupIdentity({
|
|
113
|
+
edgeConnection: {
|
|
114
|
+
onReconnected: (listener) => {
|
|
115
|
+
if (isConnected) {
|
|
116
|
+
listener();
|
|
117
|
+
} else {
|
|
118
|
+
listeners.push(listener);
|
|
119
|
+
}
|
|
120
|
+
return () => {};
|
|
121
|
+
},
|
|
122
|
+
get isConnected() {
|
|
123
|
+
return isConnected;
|
|
124
|
+
},
|
|
125
|
+
open: async () => {},
|
|
126
|
+
close: async () => {},
|
|
127
|
+
onMessage: (_: MessageListener): (() => void) => {
|
|
128
|
+
return () => {};
|
|
129
|
+
},
|
|
130
|
+
send: async (_) => {
|
|
131
|
+
replicationStarted = true;
|
|
132
|
+
},
|
|
133
|
+
} as EdgeConnection,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
await writeGenesisCredential(setup);
|
|
137
|
+
listeners.forEach((callback) => callback());
|
|
138
|
+
isConnected = true;
|
|
139
|
+
|
|
140
|
+
await expect.poll(() => replicationStarted).toBeTruthy();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const setupIdentity = async (args?: {
|
|
144
|
+
signalContext?: MemorySignalManagerContext;
|
|
145
|
+
spaceKey?: PublicKey;
|
|
146
|
+
identityKey?: PublicKey;
|
|
147
|
+
genesisFeedKey?: PublicKey;
|
|
148
|
+
edgeConnection?: EdgeConnection;
|
|
149
|
+
}): Promise<TestIdentitySetup> => {
|
|
45
150
|
const { storage, metadataStore, blobStore } = createStores();
|
|
46
151
|
|
|
47
152
|
const keyring = new Keyring();
|
|
48
|
-
const identityKey = await keyring.createKey();
|
|
49
153
|
const deviceKey = await keyring.createKey();
|
|
50
|
-
const
|
|
154
|
+
const identityKey = args?.identityKey ?? (await keyring.createKey());
|
|
155
|
+
const spaceKey = args?.spaceKey ?? (await keyring.createKey());
|
|
51
156
|
|
|
52
157
|
const feedStore = new FeedStore<FeedMessage>({
|
|
53
158
|
factory: new FeedFactory<FeedMessage>({
|
|
54
|
-
root: storage.createDirectory(
|
|
159
|
+
root: storage.createDirectory(),
|
|
55
160
|
signer: keyring,
|
|
56
161
|
hypercore: {
|
|
57
162
|
valueEncoding,
|
|
@@ -77,8 +182,9 @@ describe('identity/identity', () => {
|
|
|
77
182
|
},
|
|
78
183
|
blobStore,
|
|
79
184
|
networkManager: new SwarmNetworkManager({
|
|
80
|
-
signalManager: new MemorySignalManager(new MemorySignalManagerContext()),
|
|
185
|
+
signalManager: new MemorySignalManager(args?.signalContext ?? new MemorySignalManagerContext()),
|
|
81
186
|
transportFactory: MemoryTransportFactory,
|
|
187
|
+
peerInfo: { identityKey: identityKey.toHex(), peerKey: deviceKey.toHex() },
|
|
82
188
|
}),
|
|
83
189
|
});
|
|
84
190
|
|
|
@@ -87,7 +193,7 @@ describe('identity/identity', () => {
|
|
|
87
193
|
id: await createIdFromSpaceKey(spaceKey),
|
|
88
194
|
spaceKey,
|
|
89
195
|
protocol,
|
|
90
|
-
genesisFeed: controlFeed,
|
|
196
|
+
genesisFeed: args?.genesisFeedKey ? await feedStore.openFeed(args.genesisFeedKey) : controlFeed,
|
|
91
197
|
feedProvider: (feedKey) => feedStore.openFeed(feedKey),
|
|
92
198
|
memberKey: identityKey,
|
|
93
199
|
metadataStore,
|
|
@@ -103,242 +209,38 @@ describe('identity/identity', () => {
|
|
|
103
209
|
identityKey,
|
|
104
210
|
deviceKey,
|
|
105
211
|
space,
|
|
212
|
+
edgeFeatures: args?.edgeConnection && { feedReplicator: true },
|
|
213
|
+
edgeConnection: args?.edgeConnection,
|
|
106
214
|
});
|
|
107
215
|
|
|
108
216
|
await identity.open(new Context());
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
//
|
|
114
|
-
{
|
|
115
|
-
const generator = new CredentialGenerator(keyring, identityKey, deviceKey);
|
|
116
|
-
const credentials = [
|
|
117
|
-
...(await generator.createSpaceGenesis(spaceKey, controlFeed.key)),
|
|
118
|
-
await generator.createDeviceAuthorization(deviceKey),
|
|
119
|
-
await generator.createFeedAdmission(spaceKey, dataFeed.key, AdmittedFeed.Designation.DATA),
|
|
120
|
-
];
|
|
121
|
-
|
|
122
|
-
for (const credential of credentials) {
|
|
123
|
-
await identity.controlPipeline.writer.write({
|
|
124
|
-
credential: { credential },
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Wait for identity to be ready.
|
|
130
|
-
await identity.ready();
|
|
131
|
-
const identitySigner = identity.getIdentityCredentialSigner();
|
|
132
|
-
const credential = await identitySigner.createCredential({
|
|
133
|
-
subject: identityKey,
|
|
134
|
-
assertion: {
|
|
135
|
-
'@type': 'dxos.halo.credentials.IdentityProfile',
|
|
136
|
-
profile: {
|
|
137
|
-
displayName: 'Alice',
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
expect(credential.issuer).toEqual(identityKey);
|
|
143
|
-
expect(await verifyCredential(credential)).toEqual({ kind: 'pass' });
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
test('two devices', async () => {
|
|
147
|
-
const signalContext = new MemorySignalManagerContext();
|
|
148
|
-
|
|
149
|
-
let spaceKey: PublicKey;
|
|
150
|
-
let identityKey: PublicKey;
|
|
151
|
-
let genesisFeedKey: PublicKey;
|
|
152
|
-
let identity1: Identity;
|
|
153
|
-
let identity2: Identity;
|
|
154
|
-
|
|
155
|
-
//
|
|
156
|
-
// First device
|
|
157
|
-
//
|
|
158
|
-
{
|
|
159
|
-
const { storage, metadataStore, blobStore } = createStores();
|
|
160
|
-
|
|
161
|
-
const keyring = new Keyring();
|
|
162
|
-
identityKey = await keyring.createKey();
|
|
163
|
-
const deviceKey = await keyring.createKey();
|
|
164
|
-
spaceKey = await keyring.createKey();
|
|
165
|
-
|
|
166
|
-
const feedStore = new FeedStore<FeedMessage>({
|
|
167
|
-
factory: new FeedFactory<FeedMessage>({
|
|
168
|
-
root: storage.createDirectory(),
|
|
169
|
-
signer: keyring,
|
|
170
|
-
hypercore: {
|
|
171
|
-
valueEncoding,
|
|
172
|
-
},
|
|
173
|
-
}),
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
const createFeed = async () => {
|
|
177
|
-
const feedKey = await keyring.createKey();
|
|
178
|
-
return feedStore.openFeed(feedKey, { writable: true });
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
const controlFeed = await createFeed();
|
|
182
|
-
genesisFeedKey = controlFeed.key;
|
|
183
|
-
|
|
184
|
-
const dataFeed = await createFeed();
|
|
185
|
-
|
|
186
|
-
const protocol = new SpaceProtocol({
|
|
187
|
-
topic: spaceKey,
|
|
188
|
-
swarmIdentity: {
|
|
189
|
-
peerKey: deviceKey,
|
|
190
|
-
identityKey,
|
|
191
|
-
credentialProvider: MOCK_AUTH_PROVIDER, // createHaloAuthProvider(createCredentialSignerWithKey(keyring, device_key)),
|
|
192
|
-
credentialAuthenticator: MOCK_AUTH_VERIFIER, // createHaloAuthVerifier(() => identity.authorizedDeviceKeys),
|
|
193
|
-
},
|
|
194
|
-
blobStore,
|
|
195
|
-
networkManager: new SwarmNetworkManager({
|
|
196
|
-
signalManager: new MemorySignalManager(signalContext),
|
|
197
|
-
transportFactory: MemoryTransportFactory,
|
|
198
|
-
}),
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
await metadataStore.setIdentityRecord({ haloSpace: { key: spaceKey }, identityKey, deviceKey });
|
|
202
|
-
const space = new Space({
|
|
203
|
-
id: await createIdFromSpaceKey(spaceKey),
|
|
204
|
-
spaceKey,
|
|
205
|
-
protocol,
|
|
206
|
-
genesisFeed: controlFeed,
|
|
207
|
-
feedProvider: (feedKey) => feedStore.openFeed(feedKey),
|
|
208
|
-
memberKey: identityKey,
|
|
209
|
-
metadataStore,
|
|
210
|
-
onDelegatedInvitationStatusChange: async () => {},
|
|
211
|
-
onMemberRolesChanged: async () => {},
|
|
212
|
-
});
|
|
213
|
-
await space.setControlFeed(controlFeed);
|
|
214
|
-
await space.setDataFeed(dataFeed);
|
|
215
|
-
|
|
216
|
-
const identity = (identity1 = new Identity({
|
|
217
|
-
signer: keyring,
|
|
218
|
-
identityKey,
|
|
219
|
-
deviceKey,
|
|
220
|
-
space,
|
|
221
|
-
}));
|
|
222
|
-
|
|
223
|
-
await identity.open(new Context());
|
|
224
|
-
afterTest(() => identity.close(new Context()));
|
|
225
|
-
|
|
226
|
-
//
|
|
227
|
-
// Identity genesis
|
|
228
|
-
//
|
|
229
|
-
{
|
|
230
|
-
const generator = new CredentialGenerator(keyring, identityKey, deviceKey);
|
|
231
|
-
const credentials = [
|
|
232
|
-
...(await generator.createSpaceGenesis(spaceKey, controlFeed.key)),
|
|
233
|
-
await generator.createDeviceAuthorization(deviceKey),
|
|
234
|
-
await generator.createFeedAdmission(spaceKey, dataFeed.key, AdmittedFeed.Designation.DATA),
|
|
235
|
-
];
|
|
236
|
-
|
|
237
|
-
for (const credential of credentials) {
|
|
238
|
-
await identity.controlPipeline.writer.write({
|
|
239
|
-
credential: { credential },
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Wait for identity to be ready.
|
|
245
|
-
await identity.ready();
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
//
|
|
249
|
-
// Second device
|
|
250
|
-
//
|
|
251
|
-
{
|
|
252
|
-
const { storage, metadataStore, blobStore } = createStores();
|
|
253
|
-
|
|
254
|
-
const keyring = new Keyring();
|
|
255
|
-
const deviceKey = await keyring.createKey();
|
|
256
|
-
|
|
257
|
-
const feedStore = new FeedStore<FeedMessage>({
|
|
258
|
-
factory: new FeedFactory<FeedMessage>({
|
|
259
|
-
root: storage.createDirectory(),
|
|
260
|
-
signer: keyring,
|
|
261
|
-
hypercore: {
|
|
262
|
-
valueEncoding,
|
|
263
|
-
},
|
|
264
|
-
}),
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
const createFeed = async () => {
|
|
268
|
-
const feedKey = await keyring.createKey();
|
|
269
|
-
return feedStore.openFeed(feedKey, { writable: true });
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
const controlFeed = await createFeed();
|
|
273
|
-
const dataFeed = await createFeed();
|
|
274
|
-
|
|
275
|
-
const protocol = new SpaceProtocol({
|
|
276
|
-
topic: spaceKey,
|
|
277
|
-
swarmIdentity: {
|
|
278
|
-
peerKey: deviceKey,
|
|
279
|
-
identityKey,
|
|
280
|
-
credentialProvider: MOCK_AUTH_PROVIDER, // createHaloAuthProvider(createCredentialSignerWithKey(keyring, device_key)),
|
|
281
|
-
credentialAuthenticator: MOCK_AUTH_VERIFIER, // createHaloAuthVerifier(() => identity.authorizedDeviceKeys),
|
|
282
|
-
},
|
|
283
|
-
blobStore,
|
|
284
|
-
networkManager: new SwarmNetworkManager({
|
|
285
|
-
signalManager: new MemorySignalManager(signalContext),
|
|
286
|
-
transportFactory: MemoryTransportFactory,
|
|
287
|
-
}),
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
await metadataStore.setIdentityRecord({
|
|
291
|
-
haloSpace: { key: spaceKey },
|
|
292
|
-
identityKey: identity1.identityKey,
|
|
293
|
-
deviceKey,
|
|
294
|
-
});
|
|
295
|
-
const space = new Space({
|
|
296
|
-
id: await createIdFromSpaceKey(spaceKey),
|
|
297
|
-
spaceKey,
|
|
298
|
-
protocol,
|
|
299
|
-
genesisFeed: await feedStore.openFeed(genesisFeedKey),
|
|
300
|
-
feedProvider: (feedKey) => feedStore.openFeed(feedKey),
|
|
301
|
-
memberKey: identityKey,
|
|
302
|
-
metadataStore,
|
|
303
|
-
onDelegatedInvitationStatusChange: async () => {},
|
|
304
|
-
onMemberRolesChanged: async () => {},
|
|
305
|
-
});
|
|
306
|
-
await space.setControlFeed(controlFeed);
|
|
307
|
-
await space.setDataFeed(dataFeed);
|
|
308
|
-
|
|
309
|
-
const identity = (identity2 = new Identity({
|
|
310
|
-
signer: keyring,
|
|
311
|
-
identityKey: identity1.identityKey,
|
|
312
|
-
deviceKey,
|
|
313
|
-
space,
|
|
314
|
-
}));
|
|
315
|
-
|
|
316
|
-
await identity.open(new Context());
|
|
317
|
-
afterTest(() => identity.close(new Context()));
|
|
318
|
-
}
|
|
217
|
+
await identity.joinNetwork();
|
|
218
|
+
onTestFinished(() => identity.close(new Context()));
|
|
219
|
+
return { identity, identityKey, keyring, deviceKey, controlFeed, spaceKey, dataFeed };
|
|
220
|
+
};
|
|
319
221
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
identityKey: identity1.identityKey,
|
|
332
|
-
deviceKey: identity2.deviceKey,
|
|
333
|
-
},
|
|
334
|
-
}),
|
|
335
|
-
},
|
|
222
|
+
const writeGenesisCredential = async (setup: TestIdentitySetup) => {
|
|
223
|
+
const generator = new CredentialGenerator(setup.keyring, setup.identityKey, setup.deviceKey);
|
|
224
|
+
const credentials = [
|
|
225
|
+
...(await generator.createSpaceGenesis(setup.spaceKey, setup.controlFeed.key)),
|
|
226
|
+
await generator.createDeviceAuthorization(setup.deviceKey),
|
|
227
|
+
await generator.createFeedAdmission(setup.spaceKey, setup.dataFeed.key, AdmittedFeed.Designation.DATA),
|
|
228
|
+
];
|
|
229
|
+
|
|
230
|
+
for (const credential of credentials) {
|
|
231
|
+
await setup.identity.controlPipeline.writer.write({
|
|
232
|
+
credential: { credential },
|
|
336
233
|
});
|
|
337
|
-
|
|
338
|
-
await identity2.ready();
|
|
339
234
|
}
|
|
340
|
-
|
|
341
|
-
expect(Array.from(identity1.authorizedDeviceKeys.keys())).toEqual([identity1.deviceKey, identity2.deviceKey]);
|
|
342
|
-
expect(Array.from(identity2.authorizedDeviceKeys.keys())).toEqual([identity1.deviceKey, identity2.deviceKey]);
|
|
343
|
-
});
|
|
235
|
+
};
|
|
344
236
|
});
|
|
237
|
+
|
|
238
|
+
type TestIdentitySetup = {
|
|
239
|
+
identity: Identity;
|
|
240
|
+
keyring: Keyring;
|
|
241
|
+
identityKey: PublicKey;
|
|
242
|
+
deviceKey: PublicKey;
|
|
243
|
+
spaceKey: PublicKey;
|
|
244
|
+
controlFeed: FeedWrapper<FeedMessage>;
|
|
245
|
+
dataFeed: FeedWrapper<FeedMessage>;
|
|
246
|
+
};
|