Socket
Socket
Sign inDemoInstall

ssb-invite

Package Overview
Dependencies
Maintainers
20
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ssb-invite - npm Package Compare versions

Comparing version 2.1.5 to 2.1.6

.travis.yml

3

help.js

@@ -31,3 +31,3 @@ module.exports = {

invite: {
type:'InviteCode',
type: 'InviteCode',
description: 'the invite code to accept'

@@ -39,2 +39,1 @@ }

}

@@ -10,3 +10,2 @@ 'use strict'

var level = require('level')
var sublevel = require('level-sublevel/bytewise')
var path = require('path')

@@ -21,11 +20,11 @@

function isFunction (f) {
return 'function' === typeof f
return typeof f === 'function'
}
function isObject(o) {
return o && 'object' === typeof o
function isObject (o) {
return o && typeof o === 'object'
}
function isNumber(n) {
return 'number' === typeof n && !isNaN(n)
function isNumber (n) {
return typeof n === 'number' && !isNaN(n)
}

@@ -38,22 +37,16 @@

permissions: {
master: {allow: ['create']},
//temp: {allow: ['use']}
master: { allow: ['create'] }
// temp: {allow: ['use']}
},
init: function (server, config) {
let codesDB
if(server.sublevel)
codesDB = server.sublevel('codes')
else {
var db = sublevel(level(path.join(config.path, 'db'), {
valueEncoding: 'json'
}))
codesDB = db.sublevel('codes')
}
//add an auth hook.
server.auth.hook(function (fn, args) {
var pubkey = args[0], cb = args[1]
const codesDB = level(path.join(config.path, 'invites'), {
valueEncoding: 'json'
})
// add an auth hook.
server.auth.hook((fn, args) => {
var pubkey = args[0]; var cb = args[1]
// run normal authentication
fn(pubkey, function (err, auth) {
if(err || auth) return cb(err, auth)
if (err || auth) return cb(err, auth)

@@ -63,4 +56,4 @@ // if no rights were already defined for this pubkey

codesDB.get(pubkey, function (_, code) {
//disallow if this invite has already been used.
if(code && (code.used >= code.total)) cb()
// disallow if this invite has already been used.
if (code && (code.used >= code.total)) cb()
else cb(null, code && code.permissions)

@@ -81,36 +74,38 @@ })

opts = opts || {}
if(isNumber(opts))
opts = {uses: opts}
else if(isObject(opts)) {
if(opts.modern)
opts.uses = 1
if (isNumber(opts)) {
opts = { uses: opts }
} else if (isObject(opts) && opts.modern) {
opts.uses = 1
} else if (isFunction(opts)) {
cb = opts
opts = {}
}
else if(isFunction(opts))
cb = opts, opts = {}
var addr = getInviteAddress()
if(!addr) return cb(new Error(
'no address available for creating an invite,'+
'configuration needed for server.\n'+
if (!addr) {
return cb(new Error(
'no address available for creating an invite,' +
'configuration needed for server.\n' +
'see: https://github.com/ssbc/ssb-config/#connections'
))
))
}
addr = addr.split(';').shift()
var host = ref.parseAddress(addr).host
if(typeof host !== 'string') {
if (typeof host !== 'string') {
return cb(new Error('Could not parse host portion from server address:' + addr))
}
if (opts.external)
host = opts.external
if (opts.external) { host = opts.external }
if(!config.allowPrivate && (ip.isPrivate(host) || 'localhost' === host || host === ''))
if (!config.allowPrivate && (ip.isPrivate(host) || host === 'localhost' || host === '')) {
return cb(new Error(
'Server has no public ip address, cannot create useable invitation')
)
}
//this stuff is SECURITY CRITICAL
//so it should be moved into the main app.
//there should be something that restricts what
//permissions the plugin can create also:
//it should be able to diminish it's own permissions.
// this stuff is SECURITY CRITICAL
// so it should be moved into the main app.
// there should be something that restricts what
// permissions the plugin can create also:
// it should be able to diminish it's own permissions.

@@ -122,3 +117,3 @@ // generate a key-seed and its key

// store metadata under the generated pubkey
codesDB.put(keyCap.id, {
codesDB.put(keyCap.id, {
id: keyCap.id,

@@ -128,16 +123,14 @@ total: +opts.uses || 1,

used: 0,
permissions: {allow: ['invite.use', 'getAddress'], deny: null}
permissions: { allow: ['invite.use', 'getAddress'], deny: null }
}, function (err) {
// emit the invite code: our server address, plus the key-seed
if(err) cb(err)
else if(opts.modern) {
var ws_addr = getInviteAddress().split(';').sort(function (a, b) {
if (err) cb(err)
else if (opts.modern) {
var wsAddr = getInviteAddress().split(';').sort(function (a, b) {
return +/^ws/.test(b) - +/^ws/.test(a)
}).shift()
if(!/^ws/.test(ws_addr)) throw new Error('not a ws address:'+ws_addr)
cb(null, ws_addr+':'+seed.toString('base64'))
}
else {
if (!/^ws/.test(wsAddr)) throw new Error('not a ws address:' + wsAddr)
cb(null, wsAddr + ':' + seed.toString('base64'))
} else {
addr = ref.parseAddress(addr)

@@ -152,35 +145,34 @@ cb(null, [opts.external ? opts.external : addr.host, addr.port, addr.key].join(':') + '~' + seed.toString('base64'))

// fetch the code
codesDB.get(rpc.id, function(err, invite) {
if(err) return cb(err)
codesDB.get(rpc.id, function (err, invite) {
if (err) return cb(err)
// check if we're already following them
server.friends.get(function (err, follows) {
server.friends.get((err, follows) => {
if (err) return cb(err)
// server.friends.all('follow', function(err, follows) {
// if(hops[req.feed] == 1)
if (follows && follows[server.id] && follows[server.id][req.feed])
return cb(new Error('already following'))
if (follows && follows[server.id] && follows[server.id][req.feed]) { return cb(new Error('already following')) }
// although we already know the current feed
// it's included so that request cannot be replayed.
if(!req.feed)
return cb(new Error('feed to follow is missing'))
if (!req.feed) { return cb(new Error('feed to follow is missing')) }
if(invite.used >= invite.total)
return cb(new Error('invite has expired'))
if (invite.used >= invite.total) { return cb(new Error('invite has expired')) }
invite.used ++
invite.used++
//never allow this to be used again
if(invite.used >= invite.total) {
invite.permissions = {allow: [], deny: null}
// never allow this to be used again
if (invite.used >= invite.total) {
invite.permissions = { allow: [], deny: null }
}
//TODO
//okay so there is a small race condition here
//if people use a code massively in parallel
//then it may not be counted correctly...
//this is not a big enough deal to fix though.
//-dominic
// TODO
// okay so there is a small race condition here
// if people use a code massively in parallel
// then it may not be counted correctly...
// this is not a big enough deal to fix though.
// -dominic
// update code metadata
codesDB.put(rpc.id, invite, function (err) {
codesDB.put(rpc.id, invite, (err) => {
if (err) return cb(err)
server.emit('log:info', ['invite', rpc.id, 'use', req])

@@ -200,31 +192,32 @@

}, 'object'),
accept: valid.async(function (invite, cb) {
accept: valid.async((invite, cb) => {
// remove surrounding quotes, if found
if(isObject(invite))
invite = invite.invite
if (isObject(invite)) { invite = invite.invite }
if (invite.charAt(0) === '"' && invite.charAt(invite.length - 1) === '"')
invite = invite.slice(1, -1)
if (invite.charAt(0) === '"' && invite.charAt(invite.length - 1) === '"') { invite = invite.slice(1, -1) }
var opts
// connect to the address in the invite code
// using a keypair generated from the key-seed in the invite code
if(ref.isInvite(invite)) { //legacy ivite
if(ref.isLegacyInvite(invite)) {
if (ref.isInvite(invite)) { // legacy invite
if (ref.isLegacyInvite(invite)) {
var parts = invite.split('~')
opts = ref.parseAddress(parts[0])//.split(':')
//convert legacy code to multiserver invite code.
opts = ref.parseAddress(parts[0])// .split(':')
// convert legacy code to multiserver invite code.
var protocol = 'net:'
if (opts.host.endsWith(".onion"))
protocol = 'onion:'
invite = protocol+opts.host+':'+opts.port+'~shs:'+opts.key.slice(1, -8)+':'+parts[1]
if (opts.host.endsWith('.onion')) { protocol = 'onion:' }
invite = protocol + opts.host + ':' + opts.port + '~shs:' + opts.key.slice(1, -8) + ':' + parts[1]
}
}
opts = ref.parseAddress(ref.parseInvite(invite).remote)
const parsedInvite = ref.parseInvite(invite)
if (!parsedInvite || !parsedInvite.remote) {
return cb(new Error(`ssb-invite failed to parse invite ${invite}`))
}
opts = ref.parseAddress(parsedInvite.remote)
function connect (cb) {
createClient({
keys: true, //use seed from invite instead.
keys: true, // use seed from invite instead.
remote: invite,
config: config,
manifest: {invite: {use: 'async'}, getAddress: 'async'}
manifest: { invite: { use: 'async' }, getAddress: 'async' }
}, cb)

@@ -244,4 +237,4 @@ }

n++
if(n >= 3) cb(err, value)
else if(err) setTimeout(next, 500 + (Date.now()-start)*n)
if (n >= 3) cb(err, value)
else if (err) setTimeout(next, 500 + (Date.now() - start) * n)
else cb(null, value)

@@ -252,9 +245,8 @@ })

retry(connect, function (err, rpc) {
retry(connect, (err, rpc) => {
if (err) return cb(explain(err, 'could not connect to server'))
if(err) return cb(explain(err, 'could not connect to server'))
// command the peer to follow me
rpc.invite.use({ feed: server.id }, function (err, msg) {
if(err) return cb(explain(err, 'invite not accepted'))
rpc.invite.use({ feed: server.id }, (err, msg) => {
if (err) return cb(explain(err, 'invite not accepted'))

@@ -271,14 +263,14 @@ // follow and announce the pub

opts.host
? cont(server.publish)({
type: 'pub',
address: opts
})
: function (cb) { cb() }
? cont(server.publish)({
type: 'pub',
address: opts
})
: (cb) => cb()
)
])(function (err, results) {
if(err) return cb(err)
])((err, results) => {
if (err) return cb(err)
rpc.close()
rpc.close()
//ignore err if this is new style invite
if(server.gossip) server.gossip.add(ref.parseInvite(invite).remote, 'seed')
// ignore err if this is new style invite
if (server.gossip) server.gossip.add(ref.parseInvite(invite).remote, 'seed')
cb(null, results)

@@ -292,2 +284,1 @@ })

}
{
"name": "ssb-invite",
"description": "",
"version": "2.1.5",
"version": "2.1.6",
"homepage": "https://github.com/ssbc/ssb-invite",

@@ -10,2 +10,7 @@ "repository": {

},
"scripts": {
"test": "npm run test:js && npm run lint",
"test:js": "tape test/*.test.js",
"lint": "standard --fix"
},
"dependencies": {

@@ -16,21 +21,18 @@ "cont": "^1.0.3",

"level": "^6.0.1",
"level-sublevel": "^6.6.5",
"muxrpc-validation": "^3.0.0",
"ssb-client": "^4.7.4",
"ssb-keys": "^7.1.3",
"ssb-ref": "^2.13.9"
"muxrpc-validation": "^3.0.2",
"ssb-client": "^4.9.0",
"ssb-keys": "^7.2.2",
"ssb-ref": "^2.14.0"
},
"devDependencies": {
"pull-stream": "^3.6.11",
"ssb-friends": "^4.1.0",
"ssb-replicate": "^1.0.1",
"ssb-server": "^14.1.0",
"ssb-ws": "^6.2.0",
"tape": "^4.9.2"
"pull-stream": "^3.6.14",
"scuttle-testbot": "^1.2.3",
"ssb-friends": "^4.1.4",
"ssb-replicate": "^1.3.2",
"ssb-ws": "^6.2.3",
"standard": "^14.3.4",
"tape": "^4.13.2"
},
"scripts": {
"test": "set -e; for t in test/*.js; do node $t; done"
},
"author": "Dominic Tarr <dominic.tarr@gmail.com> (http://dominictarr.com)",
"license": "MIT"
}

@@ -26,3 +26,4 @@ # ssb-invite

- `modern` (boolean): if true the invite code will be a valid multiserver address.
if modern is enabled, uses will be set to 1.
- if modern is enabled, uses will be set to 1.
- :warning: "modern" invites with ipv6 addresses currently have some problems

@@ -29,0 +30,0 @@ This produces an invite-code which encodes the ssb-server instance's public address,

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc