slouch/scripts/user.js
Geoff Cox da7ca1123e 100% coverage (#4)
* doc(readme): clean up reasons

* doc(motto)

* test(db-and-doc): more coverage

* test(create-or-update-ignore-conflict)

* test(upsert)

* test(ignore-missing)

* test(post-and-ignore-conflict)

* test(get-merge-put)

* refactor(all): rename post and put

* test(get-merge-create-or-update)

* test(get-merge-update-ignore-conflict)

* test(get-merge-upsert)

* test(get-modify-upsert)

* refactor(doc): redundant code

* test(destroy-ignore-conflict)

* test(get-and-destroy)

* test(mark-as-destroyed)

* test(set-destroyed)

* refactor(attachment)

* test(doc): 100% coverage

* test(attachment): create with base 64

* test(attachment): clean up binary code

* test(attachment): get

* test(attachment): destroy

* test(system): is couchdb 1

* test(system): get

* test(system): reset

* test(updates)

* test(updates)

* test(all): unique DB names

* test(system): reactivate tests

* test(user): add role

* test(user): downsert role

* feat(stream-iterator): indefinite

* test(user): 100% coverage

* test(request-class)

* test(request-class): 100% coverage

* test(config)

* test(config): more coverage

* test(config): more coverage

* test(config): 100% coverage

* test(all): 100% coverage

* refactor(beautify)

* test(coverage): enforce 100%

* test(system): fix race condition

* test(user): shortcut for browser

* test(updates): test continuous stream in phantomjs

* test(updates): test continuous stream in phantomjs

* test(continuous): mock for phantomjs

* test(system): abort iterators

* test(system): fake abort
2017-07-18 07:45:32 -07:00

162 lines
4.4 KiB
JavaScript

'use strict';
var NotAuthenticatedError = require('./not-authenticated-error'),
request = require('./request'),
url = require('url'),
sporks = require('sporks');
var User = function (slouch) {
this._slouch = slouch;
this._dbName = '_users';
this._request = request;
};
User.prototype.toUserId = function (username) {
return 'org.couchdb.user:' + username;
};
User.prototype.toUsername = function (userId) {
return userId.replace(/org.couchdb.user:/, '');
};
User.prototype._insert = function (username, user) {
user._id = this.toUserId(username);
return this._slouch.doc.update(this._dbName, user);
};
User.prototype.create = function (username, password, roles, metadata) {
var user = {
name: username,
password: password,
roles: typeof roles === 'undefined' ? [] : roles,
type: 'user',
metadata: metadata,
createdAt: (new Date().toISOString())
};
return this._insert(username, user);
};
User.prototype.get = function (username) {
return this._slouch.doc.get(this._dbName, this.toUserId(username));
};
User.prototype._update = function (username, user) {
return this._insert(username, user);
};
User.prototype.addRole = function (username, role) {
var self = this;
return self.get(username).then(function (user) {
user.roles.push(role);
return self._update(username, user);
});
};
User.prototype.upsertRole = function (username, role) {
var self = this;
return self._slouch.doc._persistThroughConflicts(function () {
return self.addRole(username, role);
});
};
User.prototype.removeRole = function (username, role) {
var self = this;
return self.get(username).then(function (user) {
user.roles.splice(user.roles.indexOf(role), 1);
return self._update(username, user);
});
};
User.prototype.downsertRole = function (username, role) {
var self = this;
return self._slouch.doc._persistThroughConflicts(function () {
return self.removeRole(username, role);
});
};
User.prototype.setPassword = function (username, password) {
var self = this;
return self.get(username).then(function (user) {
user.password = password;
return self._update(username, user);
});
};
User.prototype.setMetadata = function (username, metadata) {
var self = this;
return self.get(username).then(function (user) {
user.metadata = sporks.merge(user.metadata, metadata);
return self._update(username, user);
});
};
User.prototype._destroy = function (username, rev) {
return this._slouch.doc.destroy(this._dbName, this.toUserId(username), rev);
};
User.prototype.destroy = function (username) {
var self = this;
return self.get(username).then(function (user) {
return self._destroy(username, user._rev);
});
};
User.prototype.authenticate = function (username, password) {
return this.createSession({
name: username,
password: password
}).then(function (response) {
return {
cookie: response.headers['set-cookie'][0]
};
}).catch(function (err) {
throw new NotAuthenticatedError(err.message);
});
};
User.prototype.createSession = function (doc) {
return this._request.request({
uri: this._slouch._url + '/_session',
method: 'POST',
json: doc
});
};
// TODO: get authenticate() and authenticated() working properly in the browser. For now, we
// have to fake the responses as it appears that the session cookie is not being propogated from
// the session post to the session get.
User.prototype.authenticated = function (cookie) {
// Specify a URL w/o a username and password as we want to check to make sure that the cookie is
// for a current session
var parts = url.parse(this._slouch._url);
var _url = parts.protocol + '//' + parts.host + parts.pathname;
return this._request.request({
uri: _url + '/_session',
method: 'GET',
headers: {
'Cookie': cookie
}
}).then(function (response) {
var body = JSON.parse(response.body);
if (!body.userCtx.name) { // not authenticated?
throw new NotAuthenticatedError('not authenticated via cookie');
}
return body;
});
};
User.prototype.authenticateAndGetSession = function (username, password) {
var self = this,
response = null;
return self.authenticate(username, password).then(function (_response) {
response = _response;
return self.authenticated(response.cookie);
}).then(function (session) {
session.cookie = response.cookie;
return session;
});
};
module.exports = User;