mirror of https://codeberg.org/pzp/pzp-hub.git
members db and tokens db
This commit is contained in:
parent
a03950ac30
commit
80f2a3afb0
|
@ -2,4 +2,4 @@ node_modules
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
yarn.lock
|
yarn.lock
|
||||||
TODO
|
TODO
|
||||||
keypair
|
data
|
|
@ -0,0 +1,71 @@
|
||||||
|
const Crypto = require('node:crypto')
|
||||||
|
const Path = require('node:path')
|
||||||
|
const AtomicFileRW = require('atomic-file-rw')
|
||||||
|
const Base58 = require('bs58')
|
||||||
|
|
||||||
|
class Tokens {
|
||||||
|
static #filePath
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Set<string>}
|
||||||
|
*/
|
||||||
|
static #set
|
||||||
|
|
||||||
|
static #loaded = false
|
||||||
|
|
||||||
|
static #save(cb) {
|
||||||
|
const json = JSON.stringify([...this.#set])
|
||||||
|
AtomicFileRW.writeFile(this.#filePath, json, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
static load(parentPath) {
|
||||||
|
if (this.#loaded) return
|
||||||
|
this.#filePath = Path.join(parentPath, 'members.json')
|
||||||
|
this.#set = new Set()
|
||||||
|
|
||||||
|
AtomicFileRW.readFile(this.#filePath, (err, buf) => {
|
||||||
|
if (err) {
|
||||||
|
if (err.code === 'ENOENT') {
|
||||||
|
this.#loaded = true
|
||||||
|
} else {
|
||||||
|
console.warn('Problem loading members file:', err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const json = typeof buf === 'string' ? buf : buf.toString('utf-8')
|
||||||
|
const arr = JSON.parse(json)
|
||||||
|
for (const token of arr) {
|
||||||
|
this.#set.add(token)
|
||||||
|
}
|
||||||
|
this.#loaded = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} token
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
static has(token) {
|
||||||
|
if (!this.#loaded) {
|
||||||
|
throw new Error('Members not loaded yet, cannot call has()')
|
||||||
|
}
|
||||||
|
return this.#set.has(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
static create() {
|
||||||
|
if (!this.#loaded) {
|
||||||
|
throw new Error('Members not loaded yet, cannot call create()')
|
||||||
|
}
|
||||||
|
let token
|
||||||
|
do {
|
||||||
|
token = Base58.encode(Crypto.randomBytes(32))
|
||||||
|
} while (this.#set.has(token))
|
||||||
|
this.#set.add(token)
|
||||||
|
this.#save((err, _) => {
|
||||||
|
if (err) console.warn('Problem saving members file:', err)
|
||||||
|
})
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Tokens
|
|
@ -1,8 +1,12 @@
|
||||||
|
const Path = require('node:path')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
|
const caps = require('ppppp-caps')
|
||||||
const SSAPI = require('secret-stack/lib/api')
|
const SSAPI = require('secret-stack/lib/api')
|
||||||
|
|
||||||
module.exports = function startPeer() {
|
module.exports = function startPeer() {
|
||||||
const keypair = Keypair.loadOrCreateSync('./keypair')
|
const path = Path.join(__dirname, '..', 'data')
|
||||||
|
const keypairPath = Path.join(path, 'keypair')
|
||||||
|
const keypair = Keypair.loadOrCreateSync(keypairPath)
|
||||||
|
|
||||||
SSAPI([], {})
|
SSAPI([], {})
|
||||||
.use(require('secret-stack/lib/core'))
|
.use(require('secret-stack/lib/core'))
|
||||||
|
@ -11,7 +15,8 @@ module.exports = function startPeer() {
|
||||||
.use(require('ssb-conn'))
|
.use(require('ssb-conn'))
|
||||||
.use(require('./plugin-hub.cjs'))
|
.use(require('./plugin-hub.cjs'))
|
||||||
.call(null, {
|
.call(null, {
|
||||||
caps: { shse: 'p2pLq5VZKvNWaaafMUEcxH9BKm2WjNBCxsc8TRQV5gS' },
|
path,
|
||||||
|
caps,
|
||||||
keypair,
|
keypair,
|
||||||
conn: {
|
conn: {
|
||||||
autostart: false,
|
autostart: false,
|
||||||
|
|
|
@ -2,6 +2,8 @@ const cat = require('pull-cat')
|
||||||
const Notify = require('pull-notify')
|
const Notify = require('pull-notify')
|
||||||
const pull = require('pull-stream')
|
const pull = require('pull-stream')
|
||||||
const debug = require('debug')('ppppp:hub')
|
const debug = require('debug')('ppppp:hub')
|
||||||
|
const Tokens = require('./tokens.cjs')
|
||||||
|
const Members = require('./members.cjs')
|
||||||
|
|
||||||
function ErrorDuplex(message) {
|
function ErrorDuplex(message) {
|
||||||
const err = new Error(message)
|
const err = new Error(message)
|
||||||
|
@ -22,32 +24,36 @@ module.exports = {
|
||||||
createTunnel: 'duplex',
|
createTunnel: 'duplex',
|
||||||
ping: 'sync',
|
ping: 'sync',
|
||||||
attendants: 'source',
|
attendants: 'source',
|
||||||
createToken: 'async',
|
createToken: 'sync',
|
||||||
},
|
},
|
||||||
permissions: {
|
permissions: {
|
||||||
anonymous: {
|
anonymous: {
|
||||||
allow: ['createTunnel', 'ping', 'attendants', 'createToken'],
|
allow: ['createTunnel', 'ping', 'attendants', 'createToken'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
init(sstack) {
|
init(sstack, config) {
|
||||||
if (!sstack.conn || !sstack.conn.connect) {
|
if (!sstack.conn || !sstack.conn.connect) {
|
||||||
throw new Error('tunnel plugin is missing the required ssb-conn plugin')
|
throw new Error('tunnel plugin is missing the required ssb-conn plugin')
|
||||||
}
|
}
|
||||||
debug('running multiserver at %s', sstack.getAddress('public'))
|
debug('running multiserver at %s', sstack.getAddress('public'))
|
||||||
|
|
||||||
// Ensure that incoming connections are only from members
|
Tokens.load(config.path)
|
||||||
sstack.auth.hook(function (fn, args) {
|
Members.load(config.path)
|
||||||
const [incomingId, cb] = args
|
|
||||||
cb(null, true)
|
|
||||||
// fn.apply(this, args)
|
|
||||||
|
|
||||||
// FIXME:
|
// Ensure that client connections are only from members or to-be members
|
||||||
// if (members.has(incomingId)) {
|
sstack.auth.hook(function (fn, args) {
|
||||||
// fn.apply(this, args);
|
const [clientMetadata, cb] = args
|
||||||
// } else {
|
const {pubkey, extra} = clientMetadata
|
||||||
// debug('prevented stranger %s from connecting to us', incomingId);
|
if (Members.has(pubkey)) {
|
||||||
// cb(new Error('client is a stranger'));
|
cb(null, true)
|
||||||
// }
|
} else if (extra && Tokens.has(extra)) {
|
||||||
|
Tokens.delete(extra)
|
||||||
|
Members.add(pubkey)
|
||||||
|
cb(null, true)
|
||||||
|
} else {
|
||||||
|
debug('prevented stranger %s from connecting to us', pubkey)
|
||||||
|
cb(new Error('client is a stranger'))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const attendants = new Map()
|
const attendants = new Map()
|
||||||
|
@ -101,8 +107,8 @@ module.exports = {
|
||||||
return Date.now()
|
return Date.now()
|
||||||
},
|
},
|
||||||
|
|
||||||
createToken(cb) {
|
createToken() {
|
||||||
cb(new Error('not implemented'))
|
return Tokens.create()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
const Crypto = require('node:crypto')
|
||||||
|
const Path = require('node:path')
|
||||||
|
const AtomicFileRW = require('atomic-file-rw')
|
||||||
|
const Base58 = require('bs58')
|
||||||
|
|
||||||
|
class Tokens {
|
||||||
|
static #filePath
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Set<string>}
|
||||||
|
*/
|
||||||
|
static #set
|
||||||
|
|
||||||
|
static #loaded = false
|
||||||
|
|
||||||
|
static #save(cb) {
|
||||||
|
const json = JSON.stringify([...this.#set])
|
||||||
|
AtomicFileRW.writeFile(this.#filePath, json, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
static load(parentPath) {
|
||||||
|
if (this.#loaded) return
|
||||||
|
this.#filePath = Path.join(parentPath, 'tokens.json')
|
||||||
|
this.#set = new Set()
|
||||||
|
|
||||||
|
AtomicFileRW.readFile(this.#filePath, (err, buf) => {
|
||||||
|
if (err) {
|
||||||
|
if (err.code === 'ENOENT') {
|
||||||
|
this.#loaded = true
|
||||||
|
} else {
|
||||||
|
console.log('Problem loading tokens file:', err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const json = typeof buf === 'string' ? buf : Buffer.toString(buf, 'utf-8')
|
||||||
|
const arr = JSON.parse(json)
|
||||||
|
for (const token of arr) {
|
||||||
|
this.#set.add(token)
|
||||||
|
}
|
||||||
|
this.#loaded = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} token
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
static has(token) {
|
||||||
|
if (!this.#loaded) {
|
||||||
|
throw new Error('Tokens not loaded yet, cannot call has()')
|
||||||
|
}
|
||||||
|
return this.#set.has(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
static create() {
|
||||||
|
if (!this.#loaded) {
|
||||||
|
throw new Error('Tokens not loaded yet, cannot call create()')
|
||||||
|
}
|
||||||
|
let token
|
||||||
|
do {
|
||||||
|
token = Base58.encode(Crypto.randomBytes(32))
|
||||||
|
} while (this.#set.has(token))
|
||||||
|
this.#set.add(token)
|
||||||
|
this.#save((err, _) => {
|
||||||
|
if (err) console.log('Problem saving tokens file:', err)
|
||||||
|
})
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|
||||||
|
static delete(token) {
|
||||||
|
if (!this.#loaded) {
|
||||||
|
throw new Error('Tokens not loaded yet, cannot call delete()')
|
||||||
|
}
|
||||||
|
this.#set.delete(token)
|
||||||
|
this.#save((err, _) => {
|
||||||
|
if (err) console.log('Problem saving tokens file:', err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Tokens
|
|
@ -11,10 +11,13 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/static": "6.10.2",
|
"@fastify/static": "6.10.2",
|
||||||
"@fastify/view": "7.4.1",
|
"@fastify/view": "7.4.1",
|
||||||
|
"atomic-file-rw": "~0.3.0",
|
||||||
|
"bs58": "5.0.0",
|
||||||
"debug": "4.3.4",
|
"debug": "4.3.4",
|
||||||
"ejs": "3.1.9",
|
"ejs": "3.1.9",
|
||||||
"fastify": "4.17.0",
|
"fastify": "4.17.0",
|
||||||
"pino": "8.14.1",
|
"pino": "8.14.1",
|
||||||
|
"ppppp-caps": "github:staltz/ppppp-caps",
|
||||||
"ppppp-keypair": "github:staltz/ppppp-keypair",
|
"ppppp-keypair": "github:staltz/ppppp-keypair",
|
||||||
"pull-cat": "1.1.11",
|
"pull-cat": "1.1.11",
|
||||||
"pull-notify": "0.1.2",
|
"pull-notify": "0.1.2",
|
||||||
|
@ -2347,6 +2350,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.1.tgz",
|
||||||
"integrity": "sha512-wHuWB+CvSVb2XqXM0W/WOYUkVSPbiJb9S5fNB7TBhd8s892Xq910bRxwHtC4l71hgztObTjXL6ZheZXFjhDrDQ=="
|
"integrity": "sha512-wHuWB+CvSVb2XqXM0W/WOYUkVSPbiJb9S5fNB7TBhd8s892Xq910bRxwHtC4l71hgztObTjXL6ZheZXFjhDrDQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/ppppp-caps": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "git+ssh://git@github.com/staltz/ppppp-caps.git#a2111355a1d2bddfc4d5f82267257fe99c14f608",
|
||||||
|
"license": "CC0-1.0"
|
||||||
|
},
|
||||||
"node_modules/ppppp-keypair": {
|
"node_modules/ppppp-keypair": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "git+ssh://git@github.com/staltz/ppppp-keypair.git#2d0cd86dae6df2fa33eb14c836ab706244807f43",
|
"resolved": "git+ssh://git@github.com/staltz/ppppp-keypair.git#2d0cd86dae6df2fa33eb14c836ab706244807f43",
|
||||||
|
@ -5533,6 +5541,10 @@
|
||||||
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.1.tgz",
|
||||||
"integrity": "sha512-wHuWB+CvSVb2XqXM0W/WOYUkVSPbiJb9S5fNB7TBhd8s892Xq910bRxwHtC4l71hgztObTjXL6ZheZXFjhDrDQ=="
|
"integrity": "sha512-wHuWB+CvSVb2XqXM0W/WOYUkVSPbiJb9S5fNB7TBhd8s892Xq910bRxwHtC4l71hgztObTjXL6ZheZXFjhDrDQ=="
|
||||||
},
|
},
|
||||||
|
"ppppp-caps": {
|
||||||
|
"version": "git+ssh://git@github.com/staltz/ppppp-caps.git#a2111355a1d2bddfc4d5f82267257fe99c14f608",
|
||||||
|
"from": "ppppp-caps@github:staltz/ppppp-caps"
|
||||||
|
},
|
||||||
"ppppp-keypair": {
|
"ppppp-keypair": {
|
||||||
"version": "git+ssh://git@github.com/staltz/ppppp-keypair.git#2d0cd86dae6df2fa33eb14c836ab706244807f43",
|
"version": "git+ssh://git@github.com/staltz/ppppp-keypair.git#2d0cd86dae6df2fa33eb14c836ab706244807f43",
|
||||||
"from": "ppppp-keypair@github:staltz/ppppp-keypair",
|
"from": "ppppp-keypair@github:staltz/ppppp-keypair",
|
||||||
|
|
|
@ -26,9 +26,12 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/static": "6.10.2",
|
"@fastify/static": "6.10.2",
|
||||||
"@fastify/view": "7.4.1",
|
"@fastify/view": "7.4.1",
|
||||||
|
"atomic-file-rw": "~0.3.0",
|
||||||
|
"bs58": "5.0.0",
|
||||||
"debug": "4.3.4",
|
"debug": "4.3.4",
|
||||||
"ejs": "3.1.9",
|
"ejs": "3.1.9",
|
||||||
"fastify": "4.17.0",
|
"fastify": "4.17.0",
|
||||||
|
"ppppp-caps": "github:staltz/ppppp-caps",
|
||||||
"ppppp-keypair": "github:staltz/ppppp-keypair",
|
"ppppp-keypair": "github:staltz/ppppp-keypair",
|
||||||
"pino": "8.14.1",
|
"pino": "8.14.1",
|
||||||
"pull-cat": "1.1.11",
|
"pull-cat": "1.1.11",
|
||||||
|
|
Loading…
Reference in New Issue