PouchDB plugin to simulate CouchDB’s admin accounts
pouchdb-admins
mimics how CouchDB stores a map of admin accounts in its configuration.
var PouchDB = require('pouchdb')
PouchDB.plugin(require('pouchdb-admins'))
var db = new PouchDB('my-users')
var admins = db.admins({
secret: 'secret123'
})
admins.get('kim').then(function (doc) {
console.log('"%s" is an admin', doc.name)
})
admins.validatePassword('pat', 'secret').then(function () {
// "pat" is admin and "secret" is correct password
})
admins.on('change', function (adminMap) {
// adminMap is all admins with their hashed password
// {
// "kim": "-pbkdf2-e079757b4cb58ae17467c8befe725778ce97e422,0aef36ccafa33f3e81ae897baf23f85c,10"
// }
})
admins.on('add', function (username) {
console.log('%s added as admin', username)
})
admins.on('update', function (username) {
console.log('password updated for %s', username)
})
admins.on('remove', function (username) {
console.log('%s removed from admins', username)
})
db.admins(options)
Argument | Type | Description | Required |
---|---|---|---|
options.secret |
String |
Server secret, like CouchDB’s couch_httpd_auth.secret
|
Yes |
options.admins |
Object | Map of existing admin accounts | No |
options.sessionTimeout |
Number |
Default timeout for sessions in milliseconds, used in
.calculateSessionId
|
No |
Returns admins
API.
Throws
TypeError |
options.secret is not a String |
---|
Example
var admins = db.admins({
secret: 'secret123',
admins: {
kim: '-pbkdf2-e079757b4cb58ae17467c8befe725778ce97e422,0aef36ccafa33f3e81ae897baf23f85c,10'
}
})
Looks up admin account by username
admins.get(username)
Argument | Type | Description | Required |
---|---|---|---|
username |
String | - | Yes |
Resolves without doc for admin as if it would be stored in CouchDB’s _users
but without a _rev
property.
{
id: 'org.couchdb.user:kim',
type: 'user',
name: 'kim',
password_scheme: 'pbkdf2',
derived_key: 'e079757b4cb58ae17467c8befe725778ce97e422',
salt: '0aef36ccafa33f3e81ae897baf23f85c',
iterations: 10,
roles: ['_admin']
}
Rejects with
TypeError |
username is not a String |
---|---|
not_found |
admin not found |
Example
admins.get('kim')
.then(function () {
console.log('"kim" is an admin')
})
.catch(function (error) {
if (error.name === 'not_found') {
console.log('"kim" is not an admin')
} else {
// something unforeseen happened
console.log(error)
}
})
Session validation example
var isValidSessionId = require('couchdb-is-valid-session-id')
admins.get('kim')
.then(function (doc) {
if (!isValidSessionId('secret123', doc.salt, sessionId)) {
throw new Error('Invalid sesion')
}
// kim has valid session
})
Adds or updates admin password
admins.set(username, password)
Argument | Type | Description | Required |
---|---|---|---|
username |
String | - | Yes |
password |
String | - | Yes |
Resolves without argument. Rejects with
TypeError |
username is not a String |
---|---|
TypeError |
password is not a String |
Example
admins.set('pat', 'secret')
.then(function () {
// pat added as admin with hashed password, or existing password updated
})
Validates password of admin account
admins.validatePassword(username, password)
Argument | Type | Description | Required |
---|---|---|---|
username |
String | - | Yes |
password |
String | - | Yes |
Resolves without argument. Rejects with
TypeError |
username is not a String |
---|---|
TypeError |
password is not a String |
not_found |
missing |
unauthorized |
Name or password is incorrect |
Example
admins.validatePassword('pat', 'secret')
.then(function () {
// "pat" is admin and "secret" is correct password
})
.catch(function (error) {
switch (error.name) {
case 'unauthorized':
// "pat" is admin but "secret" is incorrect password
break
case 'not_found':
// "pat" is not an admin
break
default:
// something unforeseen happened ...
console.log(error)
}
})
tbd
tbd
admins
is an event emitter and exposes
all methods .on
, once
, .removeListener
etc.
Event | Description | Argument |
---|---|---|
change |
triggered for any add , update and remove event
|
adminsMap of all admin accounts with hashed password
|
add |
New admin account created |
username of new admin account
|
update |
Existing admin account updated |
username of updated admin account
|
remove |
New admin account created |
username of removed admin account
|
Here an excerpt of a couch.ini
that stores a map of two admin accounts with
their hashed passwords. The format is -{password scheme}-{derived key},{salt},{iterations}
.
[admins]
admin=-pbkdf2-e079757b4cb58ae17467c8befe725778ce97e422,0aef36ccafa33f3e81ae897baf23f85c,10
anotheradmin=-pbkdf2-67c8befe725778ce97e422e079757b4cb58ae174,7baf23f85c0aef36ccafa33f3e81ae89,10
Local setup
git clone git@github.com:hoodiehq/pouchdb-admins.git
cd pouchdb-admins
npm install
Run all tests and code style checks
npm test
Run all tests on file change
npm run test:watch
Run tests from single file
node tests/integration/constructor-test.js
# PROTIP™: pipe output through https://www.npmjs.com/package/tape#pretty-reporters