additional tests and proper handling for purged flag targets, #5232

v1.18.x
Julian Lam 8 years ago
parent 7b471b76db
commit ad633aad45

@ -7,6 +7,7 @@
"assignee": "Assignee",
"update": "Update",
"updated": "Updated",
"target-purged": "The content this flag referred to has been purged and is no longer available.",
"quick-filters": "Quick Filters",
"filter-active": "There are one or more filters active in this list of flags",

@ -78,8 +78,13 @@ modsController.flags.detail = function (req, res, next) {
res.render('flags/detail', Object.assign(results.flagData, {
assignees: results.assignees,
type_bool: ['post', 'user'].reduce(function (memo, cur) {
memo[cur] = results.flagData.type === cur;
type_bool: ['post', 'user', 'empty'].reduce(function (memo, cur) {
if (cur !== 'empty') {
memo[cur] = results.flagData.type === cur && !!Object.keys(results.flagData.target).length;
} else {
memo[cur] = !Object.keys(results.flagData.target).length;
}
return memo;
}, {}),
title: '[[pages:flag-details, ' + req.params.flagId + ']]'

@ -202,31 +202,6 @@ Flags.validate = function (payload, callback) {
});
};
Flags.getTarget = function (type, id, uid, callback) {
switch (type) {
case 'post':
async.waterfall([
async.apply(posts.getPostsByPids, [id], uid),
function (posts, next) {
topics.addPostData(posts, uid, next);
}
], function (err, posts) {
callback(err, posts[0]);
});
break;
case 'user':
user.getUsersData([id], function (err, users) {
callback(err, users ? users[0] : undefined);
});
break;
default:
callback(new Error('[[error:invalid-data]]'));
break;
}
};
Flags.getNotes = function (flagId, callback) {
async.waterfall([
async.apply(db.getSortedSetRevRangeWithScores.bind(db), 'flag:' + flagId + ':notes', 0, -1),
@ -348,6 +323,41 @@ Flags.exists = function (type, id, uid, callback) {
db.isSortedSetMember('flags:hash', [type, id, uid].join(':'), callback);
};
Flags.getTarget = function (type, id, uid, callback) {
async.waterfall([
async.apply(Flags.targetExists, type, id),
function (exists, next) {
if (exists) {
switch (type) {
case 'post':
async.waterfall([
async.apply(posts.getPostsByPids, [id], uid),
function (posts, next) {
topics.addPostData(posts, uid, next);
}
], function (err, posts) {
next(err, posts[0]);
});
break;
case 'user':
user.getUsersData([id], function (err, users) {
next(err, users ? users[0] : undefined);
});
break;
default:
next(new Error('[[error:invalid-data]]'));
break;
}
} else {
// Target used to exist (otherwise flag creation'd fail), but no longer
next(null, {});
}
}
], callback);
};
Flags.targetExists = function (type, id, callback) {
switch (type) {
case 'post':

@ -144,9 +144,6 @@ module.exports = function (Posts) {
},
function (next) {
db.sortedSetsRemove(['posts:pid', 'posts:flagged'], pid, next);
},
function (next) {
flags.dismiss(pid, next);
}
], function (err) {
if (err) {

@ -455,53 +455,6 @@ Upgrade.upgrade = function (callback) {
next();
}
},
function (next) {
thisSchemaDate = Date.UTC(2016, 3, 29);
if (schemaDate < thisSchemaDate) {
updatesMade = true;
winston.info('[2016/04/29] Dismiss flags from deleted topics');
var posts = require('./posts');
var topics = require('./topics');
var flags = require('./flags');
var pids, tids;
async.waterfall([
async.apply(db.getSortedSetRange, 'posts:flagged', 0, -1),
function (_pids, next) {
pids = _pids;
posts.getPostsFields(pids, ['tid'], next);
},
function (_tids, next) {
tids = _tids.map(function (a) {
return a.tid;
});
topics.getTopicsFields(tids, ['deleted'], next);
},
function (state, next) {
var toDismiss = state.map(function (a, idx) {
return parseInt(a.deleted, 10) === 1 ? pids[idx] : null;
}).filter(Boolean);
winston.info('[2016/04/29] ' + toDismiss.length + ' dismissable flags found');
async.each(toDismiss, flags.dismiss, next);
}
], function (err) {
if (err) {
return next(err);
}
winston.info('[2016/04/29] Dismiss flags from deleted topics done');
Upgrade.update(thisSchemaDate, next);
});
} else {
winston.info('[2016/04/29] Dismiss flags from deleted topics skipped!');
next();
}
},
function (next) {
thisSchemaDate = Date.UTC(2016, 4, 28);

@ -56,14 +56,4 @@ module.exports = function (User) {
}
], callback);
};
User.resetFlags = function (uids, callback) {
if (!Array.isArray(uids) || !uids.length) {
return callback();
}
async.eachSeries(uids, function (uid, next) {
flags.dismissByUid(uid, next);
}, callback);
};
};

@ -82,6 +82,42 @@ describe('Flags', function () {
});
});
describe('.exists()', function () {
it('should return Boolean True if a flag matching the flag hash already exists', function (done) {
Flags.exists('post', 1, 1, function (err, exists) {
assert.ifError(err);
assert.strictEqual(true, exists);
done();
});
});
it('should return Boolean False if a flag matching the flag hash does not already exists', function (done) {
Flags.exists('post', 1, 2, function (err, exists) {
assert.ifError(err);
assert.strictEqual(false, exists);
done();
});
});
});
describe('.targetExists()', function () {
it('should return Boolean True if the targeted element exists', function (done) {
Flags.targetExists('post', 1, function (err, exists) {
assert.ifError(err);
assert.strictEqual(true, exists);
done();
});
});
it('should return Boolean False if the targeted element does not exist', function (done) {
Flags.targetExists('post', 15, function (err, exists) {
assert.ifError(err);
assert.strictEqual(false, exists);
done();
});
});
});
describe('.get()', function () {
it('should retrieve and display a flag\'s data', function (done) {
Flags.get(1, function (err, flagData) {
@ -252,6 +288,14 @@ describe('Flags', function () {
done();
});
});
it('should return a plain object with no properties if the target no longer exists', function (done) {
Flags.getTarget('user', 15, 1, function (err, data) {
assert.ifError(err);
assert.strictEqual(0, Object.keys(data).length);
done();
});
});
});
describe('.validate()', function () {

Loading…
Cancel
Save