module.exports = adduser var url = require('url') var assert = require('assert') function adduser (uri, params, cb) { assert(typeof uri === 'string', 'must pass registry URI to adduser') assert( params && typeof params === 'object', 'must pass params to adduser' ) assert(typeof cb === 'function', 'must pass callback to adduser') assert(params.auth && typeof params.auth, 'must pass auth to adduser') var auth = params.auth assert(typeof auth.username === 'string', 'must include username in auth') assert(typeof auth.password === 'string', 'must include password in auth') assert(typeof auth.email === 'string', 'must include email in auth') // normalize registry URL if (uri.slice(-1) !== '/') uri += '/' var username = auth.username.trim() var password = auth.password.trim() var email = auth.email.trim() // validation if (!username) return cb(new Error('No username supplied.')) if (!password) return cb(new Error('No password supplied.')) if (!email) return cb(new Error('No email address supplied.')) if (!email.match(/^[^@]+@[^\.]+\.[^\.]+/)) { return cb(new Error('Please use a real email address.')) } var userobj = { _id: 'org.couchdb.user:' + username, name: username, password: password, email: email, type: 'user', roles: [], date: new Date().toISOString() } var token = this.config.couchToken if (this.couchLogin) this.couchLogin.token = null cb = done.call(this, token, cb) var logObj = Object.keys(userobj).map(function (k) { if (k === 'password') return [k, 'XXXXX'] return [k, userobj[k]] }).reduce(function (s, kv) { s[kv[0]] = kv[1] return s }, {}) this.log.verbose('adduser', 'before first PUT', logObj) var client = this uri = url.resolve(uri, '-/user/org.couchdb.user:' + encodeURIComponent(username)) var options = { method: 'PUT', body: userobj, auth: auth } this.request( uri, options, function (error, data, json, response) { if (!error || !response || response.statusCode !== 409) { return cb(error, data, json, response) } client.log.verbose('adduser', 'update existing user') return client.request( uri + '?write=true', { body: userobj, auth: auth }, function (er, data, json, response) { if (er || data.error) { return cb(er, data, json, response) } Object.keys(data).forEach(function (k) { if (!userobj[k] || k === 'roles') { userobj[k] = data[k] } }) client.log.verbose('adduser', 'userobj', logObj) client.request(uri + '/-rev/' + userobj._rev, options, cb) } ) } ) function done (token, cb) { return function (error, data, json, response) { if (!error && (!response || response.statusCode === 201)) { return cb(error, data, json, response) } // there was some kind of error, reinstate previous auth/token/etc. if (client.couchLogin) { client.couchLogin.token = token if (client.couchLogin.tokenSet) { client.couchLogin.tokenSet(token) } } client.log.verbose('adduser', 'back', [error, data, json]) if (!error) { error = new Error( (response && response.statusCode || '') + ' ' + 'Could not create user\n' + JSON.stringify(data) ) } if (response && (response.statusCode === 401 || response.statusCode === 403)) { client.log.warn('adduser', 'Incorrect username or password\n' + 'You can reset your account by visiting:\n' + '\n' + ' https://npmjs.org/forgot\n') } return cb(error) } } }