Skip to content

Commit e273791

Browse files
committed
named devices and readonly
1 parent 77d2532 commit e273791

10 files changed

Lines changed: 588 additions & 228 deletions

File tree

index.js

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ const { Router, encode, decode } = require('./spec/hyperdispatch')
1212
const BlindPeering = require('blind-peering')
1313
const db = require('./spec/db/index.js')
1414
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')
1521

1622
class AutopassPairer extends ReadyResource {
1723
constructor(store, invite, opts = {}) {
@@ -29,6 +35,7 @@ class AutopassPairer extends ReadyResource {
2935
this.pass = null
3036
this.relayThrough = opts.relayThrough || null
3137
this.blindEncryption = opts.blindEncryption || null
38+
this.name = opts.name || null
3239

3340
this.ready().catch(noop)
3441
}
@@ -54,9 +61,10 @@ class AutopassPairer extends ReadyResource {
5461
await core.ready()
5562
const key = core.key
5663
await core.close()
64+
5765
this.candidate = this.pairing.addCandidate({
5866
invite: z32.decode(this.invite),
59-
userData: key,
67+
userData: c.encode(INVITEE, { key, name: this.name }),
6068
onadd: async (result) => {
6169
if (this.pass === null) {
6270
this.pass = new Autopass(this.store, {
@@ -70,10 +78,12 @@ class AutopassPairer extends ReadyResource {
7078

7179
await this.pass.deleteInvite()
7280
}
73-
const readOnly = JSON.parse(result.data.toString()).readOnly
81+
82+
const metadata = result.data ? c.decode(PUBLIC_INVITE_METADATA, result.data) : null
83+
7484
this.swarm = null
7585
this.store = null
76-
if (this.onresolve && readOnly) {
86+
if (this.onresolve && metadata && metadata.readOnly) {
7787
this._whenReadable()
7888
} else if (this.onresolve) {
7989
this._whenWritable()
@@ -84,11 +94,7 @@ class AutopassPairer extends ReadyResource {
8494
}
8595

8696
_whenReadable() {
87-
const check = () => {
88-
this.pass.base.off('update', check)
89-
this.onresolve(this.pass)
90-
}
91-
this.pass.base.on('update', check)
97+
this.onresolve(this.pass)
9298
}
9399

94100
_whenWritable() {
@@ -149,11 +155,13 @@ class Autopass extends ReadyResource {
149155
this.debug = !!opts.key
150156
// Register handlers for commands
151157
this.router.add('@autopass/remove-writer', async (data, context) => {
158+
await context.view.delete('@autopass/writer', data)
152159
await context.base.removeWriter(data.key)
153160
})
154161

155162
this.router.add('@autopass/add-writer', async (data, context) => {
156-
await context.base.addWriter(data.key)
163+
await context.view.insert('@autopass/writer', data)
164+
if (!data.readOnly) await context.base.addWriter(data.key)
157165
})
158166

159167
this.router.add('@autopass/put', async (data, context) => {
@@ -263,7 +271,7 @@ class Autopass extends ReadyResource {
263271
const { id, invite, publicKey, expires, additional } = BlindPairing.createInvite(
264272
this.base.key,
265273
{
266-
data: Buffer.from(JSON.stringify({ readOnly }))
274+
data: c.encode(PUBLIC_INVITE_METADATA, { readOnly })
267275
}
268276
)
269277

@@ -293,19 +301,25 @@ class Autopass extends ReadyResource {
293301
return { value: data.value, file: data.file }
294302
}
295303

296-
async addWriter(key) {
297-
await this.base.append(
298-
encode('@autopass/add-writer', {
299-
key: b4a.isBuffer(key) ? key : b4a.from(key)
300-
})
301-
)
304+
listWriters(query) {
305+
return this.base.view.find('@autopass/writer', query)
306+
}
307+
308+
async getWriter(query) {
309+
return this.base.view.get('@autopass/writer', query)
310+
}
311+
312+
async addWriter(data) {
313+
if (typeof key === 'string') key = b4a.from(key, 'hex')
314+
if (b4a.isBuffer(data)) data = { key: data, name: null, readOnly: false }
315+
await this.base.append(encode('@autopass/add-writer', data))
302316
return true
303317
}
304318

305319
async removeWriter(key) {
306320
await this.base.append(
307321
encode('@autopass/remove-writer', {
308-
key: b4a.isBuffer(key) ? key : b4a.from(key)
322+
key: b4a.isBuffer(key) ? key : b4a.from(key, 'hex')
309323
})
310324
)
311325
}
@@ -337,9 +351,8 @@ class Autopass extends ReadyResource {
337351
}
338352
const readOnly = inv.readOnly
339353
candidate.open(inv.publicKey)
340-
if (!readOnly) {
341-
await this.addWriter(candidate.userData)
342-
}
354+
const { key, name } = c.decode(INVITEE, candidate.userData)
355+
await this.addWriter({ key, name, readOnly })
343356
candidate.confirm({
344357
key: this.base.key,
345358
encryptionKey: this.base.encryptionKey,

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
"version": "3.3.0",
44
"main": "index.js",
55
"scripts": {
6-
"brittle": "npx brittle test.js",
7-
"lint": "npx prettier . --check",
6+
"brittle": "brittle test.js",
7+
"lint": "prettier . --check",
8+
"format": "prettier . --write",
89
"test": "npm run lint && npm run brittle"
910
},
1011
"author": "Holepunch Inc",

schema.js

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ const Hyperdispatch = require('hyperdispatch')
44

55
// SCHEMA CREATION START //
66
const autopass = Hyperschema.from('./spec/schema')
7-
const template = autopass.namespace('autopass')
7+
const pass = autopass.namespace('autopass')
88
// You can find a list of supported data types here: https://github.com/holepunchto/compact-encoding
9-
template.register({
9+
pass.register({
1010
name: 'records',
1111
compact: false,
1212
fields: [
@@ -27,7 +27,7 @@ template.register({
2727
}
2828
]
2929
})
30-
template.register({
30+
pass.register({
3131
name: 'mirrors',
3232
compact: false,
3333
fields: [
@@ -38,19 +38,27 @@ template.register({
3838
}
3939
]
4040
})
41-
template.register({
41+
pass.register({
4242
name: 'writer',
4343
compact: false,
4444
fields: [
4545
{
4646
name: 'key',
4747
type: 'buffer',
4848
required: true
49+
},
50+
{
51+
name: 'name',
52+
type: 'string'
53+
},
54+
{
55+
name: 'readOnly',
56+
type: 'bool'
4957
}
5058
]
5159
})
5260

53-
template.register({
61+
pass.register({
5462
name: 'delete',
5563
compact: false,
5664
fields: [
@@ -62,15 +70,28 @@ template.register({
6270
]
6371
})
6472

65-
template.register({
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({
6687
name: 'additional-invite-data',
6788
fields: [
6889
{ name: 'data', type: 'buffer', required: true },
6990
{ name: 'signature', type: 'buffer', required: true }
7091
]
7192
})
7293

73-
template.register({
94+
pass.register({
7495
name: 'invite',
7596
compact: false,
7697
fields: [
@@ -107,7 +128,7 @@ template.register({
107128
]
108129
})
109130

110-
template.register({
131+
pass.register({
111132
name: 'del-invite',
112133
compact: false,
113134
fields: [
@@ -118,7 +139,7 @@ template.register({
118139
}
119140
]
120141
})
121-
template.register({
142+
pass.register({
122143
name: 'del-mirror',
123144
compact: false,
124145
fields: [

spec/db/db.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
2-
"version": 0,
2+
"version": 1,
33
"offset": 0,
44
"schema": [
55
{
66
"name": "records",
77
"namespace": "autopass",
88
"id": 0,
99
"type": 1,
10-
"version": 0,
10+
"version": 1,
1111
"versionField": null,
1212
"indexes": [],
1313
"schema": "@autopass/records",
@@ -20,7 +20,7 @@
2020
"namespace": "autopass",
2121
"id": 1,
2222
"type": 1,
23-
"version": 0,
23+
"version": 1,
2424
"versionField": null,
2525
"indexes": [],
2626
"schema": "@autopass/invite",
@@ -33,7 +33,7 @@
3333
"namespace": "autopass",
3434
"id": 2,
3535
"type": 1,
36-
"version": 0,
36+
"version": 1,
3737
"versionField": null,
3838
"indexes": [],
3939
"schema": "@autopass/mirrors",
@@ -46,7 +46,7 @@
4646
"namespace": "autopass",
4747
"id": 3,
4848
"type": 1,
49-
"version": 0,
49+
"version": 1,
5050
"versionField": null,
5151
"indexes": [],
5252
"schema": "@autopass/writer",
@@ -59,7 +59,7 @@
5959
"namespace": "autopass",
6060
"id": 4,
6161
"type": 1,
62-
"version": 0,
62+
"version": 1,
6363
"versionField": null,
6464
"indexes": [],
6565
"schema": "@autopass/delete",
@@ -72,7 +72,7 @@
7272
"namespace": "autopass",
7373
"id": 5,
7474
"type": 1,
75-
"version": 0,
75+
"version": 1,
7676
"versionField": null,
7777
"indexes": [],
7878
"schema": "@autopass/del-invite",
@@ -85,7 +85,7 @@
8585
"namespace": "autopass",
8686
"id": 6,
8787
"type": 1,
88-
"version": 0,
88+
"version": 1,
8989
"versionField": null,
9090
"indexes": [],
9191
"schema": "@autopass/del-mirror",

0 commit comments

Comments
 (0)