autopass 3.2.0 → 3.4.0
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/README.md +20 -3
- package/index.js +54 -15
- package/package.json +4 -3
- package/schema.js +47 -8
- package/spec/db/db.json +15 -1
- package/spec/db/index.js +137 -57
- package/spec/db/messages.js +157 -23
- package/spec/hyperdispatch/messages.js +106 -8
- package/spec/schema/index.js +106 -8
- package/spec/schema/schema.json +76 -2
- package/test.js +81 -19
package/README.md
CHANGED
|
@@ -71,19 +71,36 @@ Add new entry
|
|
|
71
71
|
|
|
72
72
|
Remove an entry.
|
|
73
73
|
|
|
74
|
+
#### `stream = pass.listWriters(query)`
|
|
75
|
+
|
|
76
|
+
List all writers, optionally takes a hyperdb query
|
|
77
|
+
|
|
78
|
+
#### `writer = await pass.getWriter(key)
|
|
79
|
+
|
|
80
|
+
Get a writer, object similar to the addWriter input.
|
|
81
|
+
|
|
74
82
|
#### `await pass.removeWriter(writerKey)`
|
|
75
83
|
|
|
76
84
|
Remove a writer explictly.
|
|
77
85
|
|
|
78
|
-
#### `await pass.addWriter(
|
|
86
|
+
#### `await pass.addWriter(writer)`
|
|
79
87
|
|
|
80
88
|
Add a writer explictly.
|
|
89
|
+
Writer should look like this
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
{
|
|
93
|
+
key: otherSidesLocalWriterKey,
|
|
94
|
+
name: 'optional name for the writer',
|
|
95
|
+
readOnly: false // weather the person can write or only read
|
|
96
|
+
}
|
|
97
|
+
```
|
|
81
98
|
|
|
82
99
|
#### `pass.writerKey`
|
|
83
100
|
|
|
84
101
|
Get the local writer key.
|
|
85
102
|
|
|
86
|
-
#### `inv = await pass.createInvite()`
|
|
103
|
+
#### `inv = await pass.createInvite({ readOnly })`
|
|
87
104
|
|
|
88
105
|
Get invite to add a writer.
|
|
89
106
|
|
|
@@ -127,7 +144,7 @@ Fully close the pass instance.
|
|
|
127
144
|
|
|
128
145
|
Suspend the swarm and discovery
|
|
129
146
|
|
|
130
|
-
#### `await pass.resume`
|
|
147
|
+
#### `await pass.resume()`
|
|
131
148
|
|
|
132
149
|
Resume the swarm is suspended
|
|
133
150
|
|
package/index.js
CHANGED
|
@@ -12,6 +12,12 @@ const { Router, encode, decode } = require('./spec/hyperdispatch')
|
|
|
12
12
|
const BlindPeering = require('blind-peering')
|
|
13
13
|
const db = require('./spec/db/index.js')
|
|
14
14
|
const enc = require('hypercore-id-encoding')
|
|
15
|
+
const c = require('compact-encoding')
|
|
16
|
+
|
|
17
|
+
const { getEncoding } = require('./spec/schema/index.js')
|
|
18
|
+
|
|
19
|
+
const PUBLIC_INVITE_METADATA = getEncoding('@autopass/public-invite-metadata')
|
|
20
|
+
const INVITEE = getEncoding('@autopass/invitee')
|
|
15
21
|
|
|
16
22
|
class AutopassPairer extends ReadyResource {
|
|
17
23
|
constructor(store, invite, opts = {}) {
|
|
@@ -29,6 +35,7 @@ class AutopassPairer extends ReadyResource {
|
|
|
29
35
|
this.pass = null
|
|
30
36
|
this.relayThrough = opts.relayThrough || null
|
|
31
37
|
this.blindEncryption = opts.blindEncryption || null
|
|
38
|
+
this.name = opts.name || null
|
|
32
39
|
|
|
33
40
|
this.ready().catch(noop)
|
|
34
41
|
}
|
|
@@ -54,9 +61,10 @@ class AutopassPairer extends ReadyResource {
|
|
|
54
61
|
await core.ready()
|
|
55
62
|
const key = core.key
|
|
56
63
|
await core.close()
|
|
64
|
+
|
|
57
65
|
this.candidate = this.pairing.addCandidate({
|
|
58
66
|
invite: z32.decode(this.invite),
|
|
59
|
-
userData: key,
|
|
67
|
+
userData: c.encode(INVITEE, { key, name: this.name }),
|
|
60
68
|
onadd: async (result) => {
|
|
61
69
|
if (this.pass === null) {
|
|
62
70
|
this.pass = new Autopass(this.store, {
|
|
@@ -70,14 +78,25 @@ class AutopassPairer extends ReadyResource {
|
|
|
70
78
|
|
|
71
79
|
await this.pass.deleteInvite()
|
|
72
80
|
}
|
|
81
|
+
|
|
82
|
+
const metadata = result.data ? c.decode(PUBLIC_INVITE_METADATA, result.data) : null
|
|
83
|
+
|
|
73
84
|
this.swarm = null
|
|
74
85
|
this.store = null
|
|
75
|
-
if (this.onresolve
|
|
86
|
+
if (this.onresolve && metadata && metadata.readOnly) {
|
|
87
|
+
this._whenReadable()
|
|
88
|
+
} else if (this.onresolve) {
|
|
89
|
+
this._whenWritable()
|
|
90
|
+
}
|
|
76
91
|
this.candidate.close().catch(noop)
|
|
77
92
|
}
|
|
78
93
|
})
|
|
79
94
|
}
|
|
80
95
|
|
|
96
|
+
_whenReadable() {
|
|
97
|
+
this.onresolve(this.pass)
|
|
98
|
+
}
|
|
99
|
+
|
|
81
100
|
_whenWritable() {
|
|
82
101
|
if (this.pass.base.writable) return
|
|
83
102
|
const check = () => {
|
|
@@ -136,11 +155,13 @@ class Autopass extends ReadyResource {
|
|
|
136
155
|
this.debug = !!opts.key
|
|
137
156
|
// Register handlers for commands
|
|
138
157
|
this.router.add('@autopass/remove-writer', async (data, context) => {
|
|
158
|
+
await context.view.delete('@autopass/writer', data)
|
|
139
159
|
await context.base.removeWriter(data.key)
|
|
140
160
|
})
|
|
141
161
|
|
|
142
162
|
this.router.add('@autopass/add-writer', async (data, context) => {
|
|
143
|
-
await context.
|
|
163
|
+
await context.view.insert('@autopass/writer', data)
|
|
164
|
+
if (!data.readOnly) await context.base.addWriter(data.key)
|
|
144
165
|
})
|
|
145
166
|
|
|
146
167
|
this.router.add('@autopass/put', async (data, context) => {
|
|
@@ -238,14 +259,23 @@ class Autopass extends ReadyResource {
|
|
|
238
259
|
|
|
239
260
|
async createInvite(opts) {
|
|
240
261
|
if (this.opened === false) await this.ready()
|
|
262
|
+
const readOnly = opts?.readOnly ? true : false
|
|
241
263
|
const existing = await this.base.view.findOne('@autopass/invite', {})
|
|
242
|
-
|
|
264
|
+
|
|
265
|
+
if (existing && existing.readOnly !== readOnly) {
|
|
266
|
+
await this.deleteInvite()
|
|
267
|
+
} else if (existing) {
|
|
243
268
|
if (this.member) await this.member.flushed()
|
|
244
269
|
return z32.encode(existing.invite)
|
|
245
270
|
}
|
|
246
|
-
const { id, invite, publicKey, expires } = BlindPairing.createInvite(
|
|
271
|
+
const { id, invite, publicKey, expires, additional } = BlindPairing.createInvite(
|
|
272
|
+
this.base.key,
|
|
273
|
+
{
|
|
274
|
+
data: c.encode(PUBLIC_INVITE_METADATA, { readOnly })
|
|
275
|
+
}
|
|
276
|
+
)
|
|
247
277
|
|
|
248
|
-
const record = { id, invite, publicKey, expires }
|
|
278
|
+
const record = { id, invite, publicKey, expires, readOnly, additional }
|
|
249
279
|
await this.base.append(encode('@autopass/add-invite', record))
|
|
250
280
|
if (this.member) await this.member.flushed()
|
|
251
281
|
return z32.encode(record.invite)
|
|
@@ -271,19 +301,25 @@ class Autopass extends ReadyResource {
|
|
|
271
301
|
return { value: data.value, file: data.file }
|
|
272
302
|
}
|
|
273
303
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
)
|
|
304
|
+
listWriters(query) {
|
|
305
|
+
return this.base.view.find('@autopass/writer', query)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async getWriter(key) {
|
|
309
|
+
return this.base.view.get('@autopass/writer', { key })
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
async addWriter(data) {
|
|
313
|
+
if (typeof data === 'string') data = b4a.from(data, 'hex')
|
|
314
|
+
if (b4a.isBuffer(data)) data = { key: data, name: null, readOnly: false }
|
|
315
|
+
await this.base.append(encode('@autopass/add-writer', data))
|
|
280
316
|
return true
|
|
281
317
|
}
|
|
282
318
|
|
|
283
319
|
async removeWriter(key) {
|
|
284
320
|
await this.base.append(
|
|
285
321
|
encode('@autopass/remove-writer', {
|
|
286
|
-
key: b4a.isBuffer(key) ? key : b4a.from(key)
|
|
322
|
+
key: b4a.isBuffer(key) ? key : b4a.from(key, 'hex')
|
|
287
323
|
})
|
|
288
324
|
)
|
|
289
325
|
}
|
|
@@ -313,11 +349,14 @@ class Autopass extends ReadyResource {
|
|
|
313
349
|
if (inv === null || !b4a.equals(inv.id, id)) {
|
|
314
350
|
return
|
|
315
351
|
}
|
|
352
|
+
const readOnly = inv.readOnly
|
|
316
353
|
candidate.open(inv.publicKey)
|
|
317
|
-
|
|
354
|
+
const { key, name } = c.decode(INVITEE, candidate.userData)
|
|
355
|
+
await this.addWriter({ key, name, readOnly })
|
|
318
356
|
candidate.confirm({
|
|
319
357
|
key: this.base.key,
|
|
320
|
-
encryptionKey: this.base.encryptionKey
|
|
358
|
+
encryptionKey: this.base.encryptionKey,
|
|
359
|
+
additional: inv.additional
|
|
321
360
|
})
|
|
322
361
|
await this.deleteInvite()
|
|
323
362
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autopass",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"brittle": "
|
|
7
|
-
"lint": "
|
|
6
|
+
"brittle": "brittle test.js",
|
|
7
|
+
"lint": "prettier . --check",
|
|
8
|
+
"format": "prettier . --write",
|
|
8
9
|
"test": "npm run lint && npm run brittle"
|
|
9
10
|
},
|
|
10
11
|
"author": "Holepunch Inc",
|
package/schema.js
CHANGED
|
@@ -4,9 +4,9 @@ const Hyperdispatch = require('hyperdispatch')
|
|
|
4
4
|
|
|
5
5
|
// SCHEMA CREATION START //
|
|
6
6
|
const autopass = Hyperschema.from('./spec/schema')
|
|
7
|
-
const
|
|
7
|
+
const pass = autopass.namespace('autopass')
|
|
8
8
|
// You can find a list of supported data types here: https://github.com/holepunchto/compact-encoding
|
|
9
|
-
|
|
9
|
+
pass.register({
|
|
10
10
|
name: 'records',
|
|
11
11
|
compact: false,
|
|
12
12
|
fields: [
|
|
@@ -27,7 +27,7 @@ template.register({
|
|
|
27
27
|
}
|
|
28
28
|
]
|
|
29
29
|
})
|
|
30
|
-
|
|
30
|
+
pass.register({
|
|
31
31
|
name: 'mirrors',
|
|
32
32
|
compact: false,
|
|
33
33
|
fields: [
|
|
@@ -38,7 +38,7 @@ template.register({
|
|
|
38
38
|
}
|
|
39
39
|
]
|
|
40
40
|
})
|
|
41
|
-
|
|
41
|
+
pass.register({
|
|
42
42
|
name: 'writer',
|
|
43
43
|
compact: false,
|
|
44
44
|
fields: [
|
|
@@ -46,11 +46,19 @@ template.register({
|
|
|
46
46
|
name: 'key',
|
|
47
47
|
type: 'buffer',
|
|
48
48
|
required: true
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'name',
|
|
52
|
+
type: 'string'
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'readOnly',
|
|
56
|
+
type: 'bool'
|
|
49
57
|
}
|
|
50
58
|
]
|
|
51
59
|
})
|
|
52
60
|
|
|
53
|
-
|
|
61
|
+
pass.register({
|
|
54
62
|
name: 'delete',
|
|
55
63
|
compact: false,
|
|
56
64
|
fields: [
|
|
@@ -62,7 +70,28 @@ template.register({
|
|
|
62
70
|
]
|
|
63
71
|
})
|
|
64
72
|
|
|
65
|
-
|
|
73
|
+
pass.register({
|
|
74
|
+
name: 'invitee',
|
|
75
|
+
fields: [
|
|
76
|
+
{ name: 'key', type: 'fixed32', required: true },
|
|
77
|
+
{ name: 'name', type: 'string' }
|
|
78
|
+
]
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
pass.register({
|
|
82
|
+
name: 'public-invite-metadata',
|
|
83
|
+
fields: [{ name: 'readOnly', type: 'bool' }]
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
pass.register({
|
|
87
|
+
name: 'additional-invite-data',
|
|
88
|
+
fields: [
|
|
89
|
+
{ name: 'data', type: 'buffer', required: true },
|
|
90
|
+
{ name: 'signature', type: 'buffer', required: true }
|
|
91
|
+
]
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
pass.register({
|
|
66
95
|
name: 'invite',
|
|
67
96
|
compact: false,
|
|
68
97
|
fields: [
|
|
@@ -85,11 +114,21 @@ template.register({
|
|
|
85
114
|
name: 'expires',
|
|
86
115
|
type: 'int',
|
|
87
116
|
required: true
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: 'readOnly',
|
|
120
|
+
type: 'bool',
|
|
121
|
+
required: false
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: 'additional',
|
|
125
|
+
type: '@autopass/additional-invite-data',
|
|
126
|
+
required: false
|
|
88
127
|
}
|
|
89
128
|
]
|
|
90
129
|
})
|
|
91
130
|
|
|
92
|
-
|
|
131
|
+
pass.register({
|
|
93
132
|
name: 'del-invite',
|
|
94
133
|
compact: false,
|
|
95
134
|
fields: [
|
|
@@ -100,7 +139,7 @@ template.register({
|
|
|
100
139
|
}
|
|
101
140
|
]
|
|
102
141
|
})
|
|
103
|
-
|
|
142
|
+
pass.register({
|
|
104
143
|
name: 'del-mirror',
|
|
105
144
|
compact: false,
|
|
106
145
|
fields: [
|
package/spec/db/db.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version":
|
|
2
|
+
"version": 1,
|
|
3
3
|
"offset": 0,
|
|
4
4
|
"schema": [
|
|
5
5
|
{
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
"namespace": "autopass",
|
|
8
8
|
"id": 0,
|
|
9
9
|
"type": 1,
|
|
10
|
+
"version": 1,
|
|
11
|
+
"versionField": null,
|
|
10
12
|
"indexes": [],
|
|
11
13
|
"schema": "@autopass/records",
|
|
12
14
|
"derived": false,
|
|
@@ -18,6 +20,8 @@
|
|
|
18
20
|
"namespace": "autopass",
|
|
19
21
|
"id": 1,
|
|
20
22
|
"type": 1,
|
|
23
|
+
"version": 1,
|
|
24
|
+
"versionField": null,
|
|
21
25
|
"indexes": [],
|
|
22
26
|
"schema": "@autopass/invite",
|
|
23
27
|
"derived": false,
|
|
@@ -29,6 +33,8 @@
|
|
|
29
33
|
"namespace": "autopass",
|
|
30
34
|
"id": 2,
|
|
31
35
|
"type": 1,
|
|
36
|
+
"version": 1,
|
|
37
|
+
"versionField": null,
|
|
32
38
|
"indexes": [],
|
|
33
39
|
"schema": "@autopass/mirrors",
|
|
34
40
|
"derived": false,
|
|
@@ -40,6 +46,8 @@
|
|
|
40
46
|
"namespace": "autopass",
|
|
41
47
|
"id": 3,
|
|
42
48
|
"type": 1,
|
|
49
|
+
"version": 1,
|
|
50
|
+
"versionField": null,
|
|
43
51
|
"indexes": [],
|
|
44
52
|
"schema": "@autopass/writer",
|
|
45
53
|
"derived": false,
|
|
@@ -51,6 +59,8 @@
|
|
|
51
59
|
"namespace": "autopass",
|
|
52
60
|
"id": 4,
|
|
53
61
|
"type": 1,
|
|
62
|
+
"version": 1,
|
|
63
|
+
"versionField": null,
|
|
54
64
|
"indexes": [],
|
|
55
65
|
"schema": "@autopass/delete",
|
|
56
66
|
"derived": false,
|
|
@@ -62,6 +72,8 @@
|
|
|
62
72
|
"namespace": "autopass",
|
|
63
73
|
"id": 5,
|
|
64
74
|
"type": 1,
|
|
75
|
+
"version": 1,
|
|
76
|
+
"versionField": null,
|
|
65
77
|
"indexes": [],
|
|
66
78
|
"schema": "@autopass/del-invite",
|
|
67
79
|
"derived": false,
|
|
@@ -73,6 +85,8 @@
|
|
|
73
85
|
"namespace": "autopass",
|
|
74
86
|
"id": 6,
|
|
75
87
|
"type": 1,
|
|
88
|
+
"version": 1,
|
|
89
|
+
"versionField": null,
|
|
76
90
|
"indexes": [],
|
|
77
91
|
"schema": "@autopass/del-mirror",
|
|
78
92
|
"derived": false,
|