New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

cobox-config

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cobox-config - npm Package Compare versions

Comparing version 0.0.1 to 1.0.0

example.yaml

104

index.js

@@ -6,7 +6,4 @@ const yaml = require('js-yaml')

const mkdirp = require('mkdirp')
const { EventEmitter } = require('events')
const debug = require('debug')('cobox-config')
const logger = require('./logger')
const { isNamedKeypair } = require('./util')
const CONFIG_FILE = 'config.yml'

@@ -16,59 +13,47 @@

class CoBoxConfig extends EventEmitter {
constructor (storage) {
super()
const KeyHandler = require('./lib/key-handler')
this.storage = storage || path.join(os.homedir(), '.cobox')
const defaultConfig = () => ({
groups: { byKey: {}, byName: {} },
identities: { byKey: {}, byName: {} }
})
mkdirp.sync(path.join(this.storage))
// filename-safe date (probably there is a better way to do this)
const logfile = [new Date().toISOString().replace(/:/g, '-').replace(/\./, '-'), '.json'].join('')
try {
fs.accessSync(path.join(this.storage, CONFIG_FILE))
}
catch (e) {
fs.writeFileSync(path.join(this.storage, CONFIG_FILE), yaml.safeDump({
groups: [],
identities: []
}, { sortKeys: true }))
}
class CoBoxConfig {
constructor (storage) {
this.root = storage || path.join(os.homedir(), '.cobox')
this.storage = path.join(this.root, CONFIG_FILE)
this.secrets = path.join(this.root, 'secret_keys')
this.on('save', this.save)
this.on('load', this.load)
mkdirp.sync(path.join(this.root, 'logs'))
mkdirp.sync(this.secrets)
this.emit('load')
}
save () {
const config = {
groups: this._groups,
identities: this._identities
var config = defaultConfig()
if (!fs.existsSync(this.storage)) {
fs.writeFileSync(this.storage, yaml.safeDump(defaultConfig(), { sortKeys: true }))
this._groups = config.groups
this._identities = config.identities
} else {
this.load()
}
fs.writeFileSync(
path.join(this.storage, CONFIG_FILE),
yaml.safeDump(config, { sortKeys: true })
)
debug(`[SAVED] config:\n\n${JSON.stringify(config)}`)
}
this.logger = logger(path.join(this.root, 'logs', logfile))
this.log = this.logger('cobox-config')
load () {
const config = yaml.safeLoad(
fs.readFileSync(path.join(this.storage, CONFIG_FILE), 'utf8')
)
debug(`[LOADED] config:\n\n${config}`)
this._identities = config.identities || []
this._groups = config.groups || []
return true
this.groups = KeyHandler(this._groups)
this.identities = KeyHandler(this._identities)
}
groups () {
return this._groups || []
}
save () {
try {
var config = defaultConfig()
config.groups = this._groups
config.identities = this._identities
addGroup (params, opts = {}) {
if (isNamedKeypair(params)) {
this._groups.push(params)
opts.save ? this.emit('save') : null
fs.writeFileSync(this.storage, yaml.safeDump(config, { sortKeys: true }))
return true
} else {
} catch (err) {
console.error(err)
return false

@@ -78,12 +63,10 @@ }

identities () {
return this._identities || []
}
addIdentity (params, opts = {}) {
if (isNamedKeypair(params)) {
this._identities.push(params)
opts.save ? this.emit('save') : null
load () {
try {
const config = yaml.safeLoad(fs.readFileSync(this.storage, 'utf8'))
this._groups = config.groups
this._identities = config.identities
return true
} else {
} catch (err) {
console.error(err)
return false

@@ -93,1 +76,6 @@ }

}
function storeSecret (location, secret) {
fs.writeFileSync(secretKey, Buffer.from(secret))
return location
}
{
"name": "cobox-config",
"version": "0.0.1",
"version": "1.0.0",
"description": "load and save a cobox configuration",

@@ -11,11 +11,11 @@ "main": "index.js",

"debug": "^4.1.1",
"is-my-json-valid": "^2.20.0",
"js-yaml": "^3.13.1",
"mkdirp": "^0.5.1",
"os": "^0.1.1",
"pino": "^5.13.2",
"urlsafe-base64": "^1.0.0"
},
"devDependencies": {
"hypercore-crypto": "^1.0.0",
"istanbul": "^0.4.5",
"cobox-crypto": "^1.0.2",
"nyc": "^14.1.1",
"rimraf": "^2.6.3",

@@ -28,4 +28,4 @@ "tap-spec": "^5.0.0",

"scripts": {
"test": "istanbul cover tape test/**/*.test.js | tap-spec",
"test:debug": "DEBUG=cobox-config istanbul cover tape test/**/*.test.js | tap-spec"
"test": "tape test/**/*.test.js | tap-spec",
"cover": "nyc tape test/**/*.test.js | tap-spec"
},

@@ -41,3 +41,3 @@ "repository": {

"author": "kyphae",
"license": "ISC",
"license": "AGPL-3",
"bugs": {

@@ -44,0 +44,0 @@ "url": "https://github.com/coboxcoop/cobox-config/issues"

# cobox-config
Stores and retrieves a yaml configuration file for use in `cobox-group` and `cobox-core`.
Stores and retrieves a YAML configuration file for use with the cobox stack.

@@ -13,15 +13,53 @@ ## Example

var config = Config(storage)
```
var identity = crypto.keyPair()
config.addIdentity(Object.assign(identity, { name: 'Alice' }))
## API
var group = crypto.keyPair()
config.addGroup(group)
```
config.save()
```
# Todos
Write to YAML storage, path set using the storage path when initialising. Make sure you call this otherwise the config will not write to disk.
```
config.load()
```
Load from YAML, path set using the storage path when initialising. This is called automatically when initialising a `Config`.
```
config.identities.add(identity)
```
Append an identity to the config
```
var key = identity.name || identity.publicKey || identity.publicKey.toString('hex')
config.identities.remove(key)
```
Remove an identity from the config
```
var key = group.name || group.publicKey || group.publicKey.toString('hex')
config.groups.remove(group)
```
Remove a group from the config
```
config.identities.list()
```
List saved identities
```
config.groups.list()
```
List saved groups
## Todos
* [ ] encode public keys as base64 urlsafe in YAML
* [ ] store the path to secret key file (base64 urlsafe binary encoding) instead of raw secret key in the config file
* [ ] `sudo chmod 400` -> all secretKeys
* [ ] remove groups and identities
const { describe } = require('tape-plus')
const Config = require('../')
const crypto = require('hypercore-crypto')
const crypto = require('cobox-crypto')()
const fs = require('fs')

@@ -8,3 +8,3 @@ const path = require('path')

const { tmp, cleanup, base64encode } = require('./util')
const { tmp, cleanup } = require('./util')

@@ -22,13 +22,11 @@ describe('load', (context) => {

context('success', (assert) => {
context('default', (assert, next) => {
var config = Config(storage.path)
assert.ok(Array.isArray(config._identities), 'identities defaults to empty array')
assert.ok(Array.isArray(config._groups), 'groups defaults to empty array')
assert.deepEqual(config._identities, [], 'automatically loads identities from storage')
assert.deepEqual(config._groups, [], 'automatically loads groups from storage')
assert.ok(config.identities.list() instanceof Array, 'identities list defaults to empty Array')
assert.ok(config.groups.list() instanceof Array, 'groups list defaults to empty Array')
next()
})
})
describe('save', (context) => {
describe('add', (context) => {
var storage

@@ -44,39 +42,49 @@

context('success', (assert) => {
context('byKey', (assert, next) => {
var config = Config(storage.path)
config._groups = [ base64encode(crypto.keyPair()) ]
var group = crypto.unpack(crypto.accessKey())
var identity = crypto.keyPair()
config.groups.add(group)
config.identities.add(identity)
config.save()
var reload = yaml.safeLoad(fs.readFileSync(path.join(storage.path, 'config.yml')))
var rawGroup = reload.groups.byKey[group.publicKey.toString('hex')]
var rawIdentity = reload.identities.byKey[identity.publicKey.toString('hex')]
assert.deepEqual(config._groups, reload.groups, 'saves groups to storage')
assert.deepEqual(config._identities, reload.identities, 'saves identities to storage')
assert.same(config.groups.get(group.publicKey), rawGroup, 'saves groups to storage')
assert.same(config.identities.get(identity.publicKey), rawIdentity, 'saves identities to storage')
next()
})
})
describe('reload', (context) => {
var storage
context('byName', (assert, next) => {
var config = Config(storage.path)
var group = Object.assign({ name: 'group-a' }, crypto.unpack(crypto.accessKey()))
var identity = Object.assign({ name: 'Alice' }, crypto.keyPair())
context.beforeEach((c) => {
storage = tmp()
})
config.groups.add(group)
config.identities.add(identity)
context.afterEach((c) => {
cleanup(storage.root)
})
context('success', (assert) => {
var config = Config(storage.path)
config._groups = [ base64encode(crypto.keyPair()) ]
config._identities = [ base64encode(crypto.keyPair()) ]
config.save()
var reload = yaml.safeLoad(fs.readFileSync(path.join(storage.path, 'config.yml')))
var rawGroup = reload.groups.byKey[group.publicKey.toString('hex')]
var rawIdentity = reload.identities.byKey[identity.publicKey.toString('hex')]
assert.ok(rawGroup.name, 'saves group with a name')
assert.same(config.groups.get(group.name), rawGroup, 'gets the group using a name')
assert.ok(rawIdentity.name, 'saves identity with a name')
assert.same(config.identities.get(identity.name), rawIdentity, 'saves identities to storage')
var reload = Config(storage.path)
assert.deepEqual(config._identities, reload._identities, 'load identities from storage')
assert.deepEqual(config._groups, reload._groups, 'load groups from storage')
assert.same(reload._groups, config._groups, 'load groups from storage')
assert.same(reload._identities, config._identities, 'load identities from storage')
next()
})
})
describe('groups', (context) => {
describe('get', (context) => {
var storage

@@ -92,51 +100,22 @@

context('add: success', (assert) => {
context('works with buffers or strings', (assert, next) => {
var config = Config(storage.path)
var keyPair = base64encode(crypto.keyPair())
config.addGroup(keyPair)
var group = crypto.unpack(crypto.accessKey())
var identity = crypto.keyPair()
assert.deepEqual(config._groups[0], keyPair, 'stores group keypairs')
})
config.groups.add(group)
config.identities.add(identity)
context('add: manual save opt', (assert) => {
var config = Config(storage.path)
var keyPair = base64encode(crypto.keyPair())
config.addGroup(keyPair)
var reload = Config(storage.path)
assert.deepEqual(reload._groups, [], `doesn't save automatically`)
config.save()
var reload = Config(storage.path)
assert.deepEqual(config._groups, reload._groups, 'reloads successfully after save')
})
assert.ok(config.groups.get(group.publicKey), 'get group works with a buffer')
assert.ok(config.groups.get(group.publicKey.toString('hex')), 'get group works with a hex')
context('add: autosave opt', (assert) => {
var config = Config(storage.path)
var keyPair = base64encode(crypto.keyPair())
config.addGroup(keyPair, { save: true })
var reload = Config(storage.path)
assert.deepEqual(reload._groups, config._groups, `saves automatically`)
assert.ok(config.identities.get(identity.publicKey), 'get identity works with a buffer')
assert.ok(config.identities.get(identity.publicKey.toString('hex')), 'get identity works with a hex')
next()
})
context('add: fail', (assert) => {
var config = Config(storage.path)
var location = { place: 'Wonderland' }
assert.notOk(config.addGroup(location), 'returns false')
assert.deepEqual(config._groups, [], 'invalid params')
})
context('list', (assert) => {
var config = Config(storage.path)
assert.deepEqual(config.groups(), [], 'defaults to empty array')
var keyPair = Object.assign(base64encode(crypto.keyPair()), { name: 'BlockadesTeam' })
config._groups = [keyPair]
assert.deepEqual(config.groups(), [keyPair], 'stores identity keypairs')
})
})
describe('identities', (context) => {
describe('remove', (context) => {
var storage

@@ -152,48 +131,64 @@

context('add: success', (assert) => {
context('removes relevant entry using buffers', (assert, next) => {
var config = Config(storage.path)
var keyPair = Object.assign(base64encode(crypto.keyPair()), { name: 'Alice' })
config.addIdentity(keyPair)
var group = crypto.unpack(crypto.accessKey())
var identity = crypto.keyPair()
assert.deepEqual(config._identities[0], keyPair, 'stores identity keypairs')
config.groups.add(group)
config.identities.add(identity)
config.save()
config.load()
config.groups.remove(group.publicKey)
config.identities.remove(identity.publicKey)
assert.same(config.groups.list(), [], 'removed the group')
assert.same(config.identities.list(), [], 'removed the identity')
next()
})
context('add: manual save opt', (assert) => {
context('removes relevant entry using buffers', (assert, next) => {
var config = Config(storage.path)
var keyPair = base64encode(crypto.keyPair())
config.addIdentity(keyPair)
var group = crypto.unpack(crypto.accessKey())
var identity = crypto.keyPair()
var reload = Config(storage.path)
assert.deepEqual(reload._identities, [], `doesn't save automatically`)
config.groups.add(group)
config.identities.add(identity)
config.save()
config.load()
var reload = Config(storage.path)
assert.deepEqual(config._identities, reload._identities, 'reloads successfully after save')
config.groups.remove(group.publicKey.toString('hex'))
config.identities.remove(identity.publicKey.toString('hex'))
assert.same(config.groups.list(), [], 'removed the group')
assert.same(config.identities.list(), [], 'removed the identity')
next()
})
context('add: autosave opt', (assert) => {
context('removes relevant entry using names', (assert, next) => {
var config = Config(storage.path)
var keyPair = base64encode(crypto.keyPair())
config.addIdentity(keyPair, { save: true })
var group = Object.assign({ name: 'group-a' }, crypto.unpack(crypto.accessKey()))
var identity = Object.assign({ name: 'Alice' }, crypto.keyPair())
var reload = Config(storage.path)
assert.deepEqual(reload._identities, config._identities, `saves automatically`)
})
config.groups.add(group)
config.identities.add(identity)
context('add: fail', (assert) => {
var config = Config(storage.path)
var location = { place: 'Wonderland' }
assert.notOk(config.addIdentity(location), 'returns false')
assert.deepEqual(config._identities, [], 'invalid params')
})
config.save()
config.load()
context('list', (assert) => {
var config = Config(storage.path)
assert.deepEqual(config.identities(), [], 'defaults to empty array')
assert.same(config.groups.list().length, 1, 'saved the group')
assert.same(config.identities.list().length, 1, 'saved the identity')
var keyPair = Object.assign(base64encode(crypto.keyPair()), { name: 'Alice' })
config._identities = [keyPair]
assert.deepEqual(config.identities(), [keyPair], 'stores identity keypairs')
config.groups.remove(group.name)
config.identities.remove(identity.name)
config.save()
config.load()
assert.same(config.groups.list(), [], 'removed the group')
assert.same(config.identities.list(), [], 'removed the identity')
next()
})
})
const tmpdir = require('tmp').dirSync
const mkdirp = require('mkdirp')
const rimraf = require('rimraf')
const urlsafeBase64 = require('urlsafe-base64')
const debug = require('debug')('cobox-config')

@@ -22,9 +21,2 @@

function base64encode (obj) {
Object.keys(obj).map((key) => (
obj[key] = urlsafeBase64.encode(Buffer.from(obj[key])))
)
return obj
}
module.exports = { cleanup, tmp, base64encode }
module.exports = { cleanup, tmp }

@@ -1,29 +0,10 @@

const Validator = require('is-my-json-valid')
// Q: this is unnecessary?
function isNamedKeypair (content) {
content.publicKey = toStr(content.publicKey)
content.secretKey = toStr(content.secretKey)
var schema = {
$schema: 'http://json-schema.org/schema#',
type: 'object',
required: ['publicKey', 'secretKey'],
properties: {
publicKey: { type: 'string', pattern: '[A-Za-z0-9_-]' },
secretKey: { type: 'string', pattern: '[A-Za-z0-9_-]' },
name: { type: 'string' }
}
}
const validator = Validator(schema, { verbose: true })
return validator(content)
function isPubKey (variable) {
if (!(typeof variable === 'string' || variable instanceof Buffer)) return false
return Buffer.from(variable, 'hex').length === 32
}
function toStr (key) {
return Buffer.isBuffer(key)
? key.toString('hex')
: key
function isName (variable) {
return typeof variable === 'string'
}
module.exports = { isNamedKeypair }
module.exports = { isPubKey, isName }

Sorry, the diff of this file is not supported yet

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