fix(articles): Orphaned User reference throws server error

Adds an additional check for the existence of a populated user
reference, when determining if the current user has immediate access to
the requested article.

Without this fix, the server will throw an error if the requested
article doesn't have a populated user field.

Modified the article & articles list view's to check if the article has
a populated user. If not, then it will display "Deleted User" in place
of the missing user reference.

Added a server-side test that ensures we can get a single article if
the article.user field is referencing a deleted user.

Fixes #1082
This commit is contained in:
mleanos
2015-12-16 15:20:22 -08:00
parent 7e8d2ed43e
commit 2bdde4e9e2
4 changed files with 92 additions and 3 deletions

View File

@@ -8,7 +8,8 @@
Posted on
<span ng-bind="article.created | date:'mediumDate'"></span>
by
<span ng-bind="article.user.displayName"></span>
<span ng-if="article.user" ng-bind="article.user.displayName"></span>
<span ng-if="!article.user">Deleted User</span>
</small>
<h4 class="list-group-item-heading" ng-bind="article.title"></h4>
<p class="list-group-item-text" ng-bind="article.content"></p>

View File

@@ -15,7 +15,8 @@
Posted on
<span ng-bind="article.created | date:'mediumDate'"></span>
by
<span ng-bind="article.user.displayName"></span>
<span ng-if="article.user" ng-bind="article.user.displayName"></span>
<span ng-if="!article.user">Deleted User</span>
</em>
</small>
<p class="lead" ng-bind="article.content"></p>

View File

@@ -49,7 +49,7 @@ exports.isAllowed = function (req, res, next) {
var roles = (req.user) ? req.user.roles : ['guest'];
// If an article is being processed and the current user created it then allow any manipulation
if (req.article && req.user && req.article.user.id === req.user.id) {
if (req.article && req.user && req.article.user && req.article.user.id === req.user.id) {
return next();
}

View File

@@ -313,6 +313,93 @@ describe('Article CRUD tests', function () {
});
});
it('should be able to get a single article that has an orphaned user reference', function (done) {
// Create orphan user creds
var _creds = {
username: 'orphan',
password: 'M3@n.jsI$Aw3$0m3'
};
// Create orphan user
var _orphan = new User({
firstName: 'Full',
lastName: 'Name',
displayName: 'Full Name',
email: 'orphan@test.com',
username: _creds.username,
password: _creds.password,
provider: 'local'
});
_orphan.save(function (err, orphan) {
// Handle save error
if (err) {
return done(err);
}
agent.post('/api/auth/signin')
.send(_creds)
.expect(200)
.end(function (signinErr, signinRes) {
// Handle signin error
if (signinErr) {
return done(signinErr);
}
// Get the userId
var orphanId = orphan._id;
// Save a new article
agent.post('/api/articles')
.send(article)
.expect(200)
.end(function (articleSaveErr, articleSaveRes) {
// Handle article save error
if (articleSaveErr) {
return done(articleSaveErr);
}
// Set assertions on new article
(articleSaveRes.body.title).should.equal(article.title);
should.exist(articleSaveRes.body.user);
should.equal(articleSaveRes.body.user._id, orphanId);
// force the article to have an orphaned user reference
orphan.remove(function () {
// now signin with valid user
agent.post('/api/auth/signin')
.send(credentials)
.expect(200)
.end(function (err, res) {
// Handle signin error
if (err) {
return done(err);
}
// Get the article
agent.get('/api/articles/' + articleSaveRes.body._id)
.expect(200)
.end(function (articleInfoErr, articleInfoRes) {
// Handle article error
if (articleInfoErr) {
return done(articleInfoErr);
}
// Set assertions
(articleInfoRes.body._id).should.equal(articleSaveRes.body._id);
(articleInfoRes.body.title).should.equal(article.title);
should.equal(articleInfoRes.body.user, undefined);
// Call the assertion callback
done();
});
});
});
});
});
});
});
afterEach(function (done) {
User.remove().exec(function () {
Article.remove().exec(done);