mirror of
https://github.com/donl/slouch.git
synced 2026-06-30 06:11:57 -06:00
feat(user): resolve conflicts
This commit is contained in:
parent
72ea73bbd2
commit
ddaa14bb0e
3 changed files with 119 additions and 7 deletions
|
|
@ -75,10 +75,11 @@ Doc.prototype.updateIgnoreConflict = function (dbName, doc) {
|
|||
});
|
||||
};
|
||||
|
||||
Doc.prototype.get = function (dbName, docId) {
|
||||
Doc.prototype.get = function (dbName, docId, params) {
|
||||
return promisedRequest.request({
|
||||
uri: this._slouch._url + '/' + dbName + '/' + docId,
|
||||
method: 'GET'
|
||||
method: 'GET',
|
||||
qs: params
|
||||
}, true);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
var NotAuthenticatedError = require('./not-authenticated-error'),
|
||||
request = require('./request'),
|
||||
url = require('url'),
|
||||
sporks = require('sporks');
|
||||
sporks = require('sporks'),
|
||||
Promise = require('sporks/scripts/promise');
|
||||
|
||||
var User = function (slouch) {
|
||||
this._slouch = slouch;
|
||||
|
|
@ -37,8 +38,8 @@ User.prototype.create = function (username, password, roles, metadata) {
|
|||
return this._insert(username, user);
|
||||
};
|
||||
|
||||
User.prototype.get = function (username) {
|
||||
return this._slouch.doc.get(this._dbName, this.toUserId(username));
|
||||
User.prototype.get = function (username, params) {
|
||||
return this._slouch.doc.get(this._dbName, this.toUserId(username), params);
|
||||
};
|
||||
|
||||
User.prototype._update = function (username, user) {
|
||||
|
|
@ -159,4 +160,48 @@ User.prototype.authenticateAndGetSession = function (username, password) {
|
|||
});
|
||||
};
|
||||
|
||||
// Provides a simple way of resolving conflicts at the user layer whereby a merge of the roles is
|
||||
// assumed to be the only data needed in the conflicting docs. Until you resolve these conflicts,
|
||||
// users cannot log in. You can pretty easily encounter conflicts on user docs with CouchDB 2. For
|
||||
// example, if a user is being added to two roles simultaneously via different CouchDB nodes then
|
||||
// when the CouchDB nodes replicate the user, the user will be in conflict.
|
||||
User.prototype.resolveConflicts = function (username) {
|
||||
var self = this;
|
||||
return self.get(username, {
|
||||
conflicts: true
|
||||
}).then(function (user) {
|
||||
// Verify that there is a conflict
|
||||
if (user._conflicts) {
|
||||
|
||||
var roles = sporks.flip(user.roles),
|
||||
gets = [],
|
||||
destroys = [];
|
||||
|
||||
user._conflicts.forEach(function (rev) {
|
||||
gets.push(self.get(username, {
|
||||
rev: rev
|
||||
}).then(function (userRev) {
|
||||
userRev.roles.forEach(function (role) {
|
||||
// Build a list of all roles, using an associative array so that duplicates are ignored.
|
||||
roles[role] = true;
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
return Promise.all(gets).then(function () {
|
||||
// Update the user and set all the roles
|
||||
user.roles = sporks.keys(roles);
|
||||
return self._update(username, user);
|
||||
}).then(function () {
|
||||
// Delete all the conflicts
|
||||
user._conflicts.forEach(function (rev) {
|
||||
destroys.push(self._destroy(username, rev));
|
||||
});
|
||||
return Promise.all(destroys);
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = User;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue