fix: make error codes consistent (#1054)

Sometimes they are `NOT_FOUND`, sometimes `ERR_NOT_FOUND`, etc.

Move all error codes into `errors.js` and reference them from there.
This commit is contained in:
Alex Potsides 2021-12-07 14:42:10 +00:00 committed by GitHub
parent cbaa5a2ef3
commit b25e0fe531
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 73 additions and 48 deletions

View File

@ -7,6 +7,7 @@ const FIFO = require('p-fifo')
const pAny = require('p-any')
// @ts-expect-error setMaxListeners is missing from the types
const { setMaxListeners } = require('events')
const { codes } = require('../errors')
/**
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
@ -55,7 +56,7 @@ class DialRequest {
const tokens = this.dialer.getTokens(this.addrs.length)
// If no tokens are available, throw
if (tokens.length < 1) {
throw errCode(new Error('No dial tokens available'), 'ERR_NO_DIAL_TOKENS')
throw errCode(new Error('No dial tokens available'), codes.ERR_NO_DIAL_TOKENS)
}
const tokenHolder = new FIFO()

View File

@ -36,5 +36,29 @@ exports.codes = {
ERR_TRANSPORT_DIAL_FAILED: 'ERR_TRANSPORT_DIAL_FAILED',
ERR_UNSUPPORTED_PROTOCOL: 'ERR_UNSUPPORTED_PROTOCOL',
ERR_INVALID_MULTIADDR: 'ERR_INVALID_MULTIADDR',
ERR_SIGNATURE_NOT_VALID: 'ERR_SIGNATURE_NOT_VALID'
ERR_SIGNATURE_NOT_VALID: 'ERR_SIGNATURE_NOT_VALID',
ERR_FIND_SELF: 'ERR_FIND_SELF',
ERR_NO_ROUTERS: 'ERR_NO_ROUTERS',
ERR_CONNECTION_NOT_MULTIPLEXED: 'ERR_CONNECTION_NOT_MULTIPLEXED',
ERR_NO_DIAL_TOKENS: 'ERR_NO_DIAL_TOKENS',
ERR_KEYCHAIN_REQUIRED: 'ERR_KEYCHAIN_REQUIRED',
ERR_INVALID_CMS: 'ERR_INVALID_CMS',
ERR_MISSING_KEYS: 'ERR_MISSING_KEYS',
ERR_NO_KEY: 'ERR_NO_KEY',
ERR_INVALID_KEY_NAME: 'ERR_INVALID_KEY_NAME',
ERR_INVALID_KEY_TYPE: 'ERR_INVALID_KEY_TYPE',
ERR_KEY_ALREADY_EXISTS: 'ERR_KEY_ALREADY_EXISTS',
ERR_INVALID_KEY_SIZE: 'ERR_INVALID_KEY_SIZE',
ERR_KEY_NOT_FOUND: 'ERR_KEY_NOT_FOUND',
ERR_OLD_KEY_NAME_INVALID: 'ERR_OLD_KEY_NAME_INVALID',
ERR_NEW_KEY_NAME_INVALID: 'ERR_NEW_KEY_NAME_INVALID',
ERR_PASSWORD_REQUIRED: 'ERR_PASSWORD_REQUIRED',
ERR_PEM_REQUIRED: 'ERR_PEM_REQUIRED',
ERR_CANNOT_READ_KEY: 'ERR_CANNOT_READ_KEY',
ERR_MISSING_PRIVATE_KEY: 'ERR_MISSING_PRIVATE_KEY',
ERR_INVALID_OLD_PASS_TYPE: 'ERR_INVALID_OLD_PASS_TYPE',
ERR_INVALID_NEW_PASS_TYPE: 'ERR_INVALID_NEW_PASS_TYPE',
ERR_INVALID_PASS_LENGTH: 'ERR_INVALID_PASS_LENGTH',
ERR_NOT_IMPLEMENTED: 'ERR_NOT_IMPLEMENTED',
ERR_WRONG_PING_ACK: 'ERR_WRONG_PING_ACK'
}

View File

@ -10,6 +10,7 @@ const { certificateForKey, findAsync } = require('./util')
const errcode = require('err-code')
const { fromString: uint8ArrayFromString } = require('uint8arrays/from-string')
const { toString: uint8ArrayToString } = require('uint8arrays/to-string')
const { codes } = require('../errors')
const privates = new WeakMap()
@ -31,7 +32,7 @@ class CMS {
*/
constructor (keychain, dek) {
if (!keychain) {
throw errcode(new Error('keychain is required'), 'ERR_KEYCHAIN_REQUIRED')
throw errcode(new Error('keychain is required'), codes.ERR_KEYCHAIN_REQUIRED)
}
this.keychain = keychain
@ -49,7 +50,7 @@ class CMS {
*/
async encrypt (name, plain) {
if (!(plain instanceof Uint8Array)) {
throw errcode(new Error('Plain data must be a Uint8Array'), 'ERR_INVALID_PARAMS')
throw errcode(new Error('Plain data must be a Uint8Array'), codes.ERR_INVALID_PARAMETERS)
}
const key = await this.keychain.findKeyByName(name)
@ -81,7 +82,7 @@ class CMS {
*/
async decrypt (cmsData) {
if (!(cmsData instanceof Uint8Array)) {
throw errcode(new Error('CMS data is required'), 'ERR_INVALID_PARAMS')
throw errcode(new Error('CMS data is required'), codes.ERR_INVALID_PARAMETERS)
}
let cms
@ -91,7 +92,7 @@ class CMS {
// @ts-ignore not defined
cms = forge.pkcs7.messageFromAsn1(obj)
} catch (/** @type {any} */ err) {
throw errcode(new Error('Invalid CMS: ' + err.message), 'ERR_INVALID_CMS')
throw errcode(new Error('Invalid CMS: ' + err.message), codes.ERR_INVALID_CMS)
}
// Find a recipient whose key we hold. We only deal with recipient certs
@ -123,7 +124,7 @@ class CMS {
if (!r) {
// @ts-ignore cms types not defined
const missingKeys = recipients.map(r => r.keyId)
throw errcode(new Error('Decryption needs one of the key(s): ' + missingKeys.join(', ')), 'ERR_MISSING_KEYS', {
throw errcode(new Error('Decryption needs one of the key(s): ' + missingKeys.join(', ')), codes.ERR_MISSING_KEYS, {
missingKeys
})
}
@ -131,7 +132,7 @@ class CMS {
const key = await this.keychain.findKeyById(r.keyId)
if (!key) {
throw errcode(new Error('No key available to decrypto'), 'ERR_NO_KEY')
throw errcode(new Error('No key available to decrypto'), codes.ERR_NO_KEY)
}
const pem = await this.keychain._getPrivateKey(key.name)

View File

@ -10,6 +10,7 @@ const crypto = require('libp2p-crypto')
const { Key } = require('interface-datastore/key')
const CMS = require('./cms')
const errcode = require('err-code')
const { codes } = require('../errors')
const { toString: uint8ArrayToString } = require('uint8arrays/to-string')
const { fromString: uint8ArrayFromString } = require('uint8arrays/from-string')
@ -210,21 +211,21 @@ class Keychain {
const self = this
if (!validateKeyName(name) || name === 'self') {
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
}
if (typeof type !== 'string') {
return throwDelayed(errcode(new Error(`Invalid key type '${type}'`), 'ERR_INVALID_KEY_TYPE'))
return throwDelayed(errcode(new Error(`Invalid key type '${type}'`), codes.ERR_INVALID_KEY_TYPE))
}
const dsname = DsName(name)
const exists = await self.store.has(dsname)
if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), 'ERR_KEY_ALREADY_EXISTS'))
if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), codes.ERR_KEY_ALREADY_EXISTS))
switch (type.toLowerCase()) {
case 'rsa':
if (!Number.isSafeInteger(size) || size < 2048) {
return throwDelayed(errcode(new Error(`Invalid RSA key size ${size}`), 'ERR_INVALID_KEY_SIZE'))
return throwDelayed(errcode(new Error(`Invalid RSA key size ${size}`), codes.ERR_INVALID_KEY_SIZE))
}
break
default:
@ -297,7 +298,7 @@ class Keychain {
*/
async findKeyByName (name) {
if (!validateKeyName(name)) {
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
}
const dsname = DsInfoName(name)
@ -305,7 +306,7 @@ class Keychain {
const res = await this.store.get(dsname)
return JSON.parse(uint8ArrayToString(res))
} catch (/** @type {any} */ err) {
return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), 'ERR_KEY_NOT_FOUND'))
return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), codes.ERR_KEY_NOT_FOUND))
}
}
@ -318,7 +319,7 @@ class Keychain {
async removeKey (name) {
const self = this
if (!validateKeyName(name) || name === 'self') {
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
}
const dsname = DsName(name)
const keyInfo = await self.findKeyByName(name)
@ -339,10 +340,10 @@ class Keychain {
async renameKey (oldName, newName) {
const self = this
if (!validateKeyName(oldName) || oldName === 'self') {
return throwDelayed(errcode(new Error(`Invalid old key name '${oldName}'`), 'ERR_OLD_KEY_NAME_INVALID'))
return throwDelayed(errcode(new Error(`Invalid old key name '${oldName}'`), codes.ERR_OLD_KEY_NAME_INVALID))
}
if (!validateKeyName(newName) || newName === 'self') {
return throwDelayed(errcode(new Error(`Invalid new key name '${newName}'`), 'ERR_NEW_KEY_NAME_INVALID'))
return throwDelayed(errcode(new Error(`Invalid new key name '${newName}'`), codes.ERR_NEW_KEY_NAME_INVALID))
}
const oldDsname = DsName(oldName)
const newDsname = DsName(newName)
@ -350,7 +351,7 @@ class Keychain {
const newInfoName = DsInfoName(newName)
const exists = await self.store.has(newDsname)
if (exists) return throwDelayed(errcode(new Error(`Key '${newName}' already exists`), 'ERR_KEY_ALREADY_EXISTS'))
if (exists) return throwDelayed(errcode(new Error(`Key '${newName}' already exists`), codes.ERR_KEY_ALREADY_EXISTS))
try {
const pem = await self.store.get(oldDsname)
@ -379,10 +380,10 @@ class Keychain {
*/
async exportKey (name, password) {
if (!validateKeyName(name)) {
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
}
if (!password) {
return throwDelayed(errcode(new Error('Password is required'), 'ERR_PASSWORD_REQUIRED'))
return throwDelayed(errcode(new Error('Password is required'), codes.ERR_PASSWORD_REQUIRED))
}
const dsname = DsName(name)
@ -409,20 +410,20 @@ class Keychain {
async importKey (name, pem, password) {
const self = this
if (!validateKeyName(name) || name === 'self') {
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
}
if (!pem) {
return throwDelayed(errcode(new Error('PEM encoded key is required'), 'ERR_PEM_REQUIRED'))
return throwDelayed(errcode(new Error('PEM encoded key is required'), codes.ERR_PEM_REQUIRED))
}
const dsname = DsName(name)
const exists = await self.store.has(dsname)
if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), 'ERR_KEY_ALREADY_EXISTS'))
if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), codes.ERR_KEY_ALREADY_EXISTS))
let privateKey
try {
privateKey = await crypto.keys.import(pem, password)
} catch (/** @type {any} */ err) {
return throwDelayed(errcode(new Error('Cannot read the key, most likely the password is wrong'), 'ERR_CANNOT_READ_KEY'))
return throwDelayed(errcode(new Error('Cannot read the key, most likely the password is wrong'), codes.ERR_CANNOT_READ_KEY))
}
let kid
@ -457,16 +458,16 @@ class Keychain {
async importPeer (name, peer) {
const self = this
if (!validateKeyName(name)) {
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
}
if (!peer || !peer.privKey) {
return throwDelayed(errcode(new Error('Peer.privKey is required'), 'ERR_MISSING_PRIVATE_KEY'))
return throwDelayed(errcode(new Error('Peer.privKey is required'), codes.ERR_MISSING_PRIVATE_KEY))
}
const privateKey = peer.privKey
const dsname = DsName(name)
const exists = await self.store.has(dsname)
if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), 'ERR_KEY_ALREADY_EXISTS'))
if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), codes.ERR_KEY_ALREADY_EXISTS))
try {
const kid = await privateKey.id()
@ -495,7 +496,7 @@ class Keychain {
*/
async _getPrivateKey (name) {
if (!validateKeyName(name)) {
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
}
try {
@ -503,7 +504,7 @@ class Keychain {
const res = await this.store.get(dsname)
return uint8ArrayToString(res)
} catch (/** @type {any} */ err) {
return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), 'ERR_KEY_NOT_FOUND'))
return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), codes.ERR_KEY_NOT_FOUND))
}
}
@ -515,13 +516,13 @@ class Keychain {
*/
async rotateKeychainPass (oldPass, newPass) {
if (typeof oldPass !== 'string') {
return throwDelayed(errcode(new Error(`Invalid old pass type '${typeof oldPass}'`), 'ERR_INVALID_OLD_PASS_TYPE'))
return throwDelayed(errcode(new Error(`Invalid old pass type '${typeof oldPass}'`), codes.ERR_INVALID_OLD_PASS_TYPE))
}
if (typeof newPass !== 'string') {
return throwDelayed(errcode(new Error(`Invalid new pass type '${typeof newPass}'`), 'ERR_INVALID_NEW_PASS_TYPE'))
return throwDelayed(errcode(new Error(`Invalid new pass type '${typeof newPass}'`), codes.ERR_INVALID_NEW_PASS_TYPE))
}
if (newPass.length < 20) {
return throwDelayed(errcode(new Error(`Invalid pass length ${newPass.length}`), 'ERR_INVALID_PASS_LENGTH'))
return throwDelayed(errcode(new Error(`Invalid pass length ${newPass.length}`), codes.ERR_INVALID_PASS_LENGTH))
}
log('recreating keychain')
const oldDek = privates.get(this).dek

View File

@ -5,6 +5,7 @@ const log = Object.assign(debug('libp2p:peer-routing'), {
error: debug('libp2p:peer-routing:err')
})
const errCode = require('err-code')
const errors = require('./errors')
const {
storeAddresses,
uniquePeers,
@ -104,11 +105,11 @@ class PeerRouting {
*/
async findPeer (id, options) { // eslint-disable-line require-await
if (!this._routers.length) {
throw errCode(new Error('No peer routers available'), 'NO_ROUTERS_AVAILABLE')
throw errCode(new Error('No peer routers available'), errors.codes.ERR_NO_ROUTERS)
}
if (id.toB58String() === this._peerId.toB58String()) {
throw errCode(new Error('Should not try to find self'), 'ERR_FIND_SELF')
throw errCode(new Error('Should not try to find self'), errors.codes.ERR_FIND_SELF)
}
const output = await pipe(
@ -125,7 +126,7 @@ class PeerRouting {
return output
}
throw errCode(new Error('not found'), 'NOT_FOUND')
throw errCode(new Error(errors.messages.NOT_FOUND), errors.codes.ERR_NOT_FOUND)
}
/**
@ -139,7 +140,7 @@ class PeerRouting {
*/
async * getClosestPeers (key, options = { timeout: 30e3 }) {
if (!this._routers.length) {
throw errCode(new Error('No peer routers available'), 'NO_ROUTERS_AVAILABLE')
throw errCode(new Error('No peer routers available'), errors.codes.ERR_NO_ROUTERS)
}
if (options.timeout) {

View File

@ -2,10 +2,7 @@
const errcode = require('err-code')
const PeerId = require('peer-id')
const {
codes: { ERR_INVALID_PARAMETERS }
} = require('../errors')
const { codes } = require('../errors')
/**
* @param {any} data
@ -48,7 +45,7 @@ class Book {
* @param {any[]|any} data
*/
set (peerId, data) {
throw errcode(new Error('set must be implemented by the subclass'), 'ERR_NOT_IMPLEMENTED')
throw errcode(new Error('set must be implemented by the subclass'), codes.ERR_NOT_IMPLEMENTED)
}
/**
@ -94,7 +91,7 @@ class Book {
*/
get (peerId) {
if (!PeerId.isPeerId(peerId)) {
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
throw errcode(new Error('peerId must be an instance of peer-id'), codes.ERR_INVALID_PARAMETERS)
}
const rec = this.data.get(peerId.toB58String())
@ -111,7 +108,7 @@ class Book {
*/
delete (peerId) {
if (!PeerId.isPeerId(peerId)) {
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
throw errcode(new Error('peerId must be an instance of peer-id'), codes.ERR_INVALID_PARAMETERS)
}
if (!this.data.delete(peerId.toB58String())) {

View File

@ -5,7 +5,7 @@ const log = Object.assign(debug('libp2p:ping'), {
error: debug('libp2p:ping:err')
})
const errCode = require('err-code')
const { codes } = require('../errors')
const crypto = require('libp2p-crypto')
const { pipe } = require('it-pipe')
// @ts-ignore it-buffer has no types exported
@ -50,7 +50,7 @@ async function ping (node, peer) {
const end = Date.now()
if (!equals(data, result)) {
throw errCode(new Error('Received wrong ping ack'), 'ERR_WRONG_PING_ACK')
throw errCode(new Error('Received wrong ping ack'), codes.ERR_WRONG_PING_ACK)
}
return end - start

View File

@ -297,7 +297,7 @@ class Upgrader {
maConn.timeline.upgraded = Date.now()
const errConnectionNotMultiplexed = () => {
throw errCode(new Error('connection is not multiplexed'), 'ERR_CONNECTION_NOT_MULTIPLEXED')
throw errCode(new Error('connection is not multiplexed'), codes.ERR_CONNECTION_NOT_MULTIPLEXED)
}
// Create the connection

View File

@ -296,7 +296,7 @@ describe('keychain', () => {
it('requires plain data as a Uint8Array', async () => {
const err = await ks.cms.encrypt(rsaKeyName, 'plain data').then(fail, err => err)
expect(err).to.exist()
expect(err).to.have.property('code', 'ERR_INVALID_PARAMS')
expect(err).to.have.property('code', 'ERR_INVALID_PARAMETERS')
})
it('encrypts', async () => {
@ -308,7 +308,7 @@ describe('keychain', () => {
it('is a PKCS #7 message', async () => {
const err = await ks.cms.decrypt('not CMS').then(fail, err => err)
expect(err).to.exist()
expect(err).to.have.property('code', 'ERR_INVALID_PARAMS')
expect(err).to.have.property('code', 'ERR_INVALID_PARAMETERS')
})
it('is a PKCS #7 binary message', async () => {