This commit is contained in:
Matteo Pagliazzi 2020-03-01 22:21:53 +01:00
parent 979d0c519d
commit c5208f0ef6
4 changed files with 67 additions and 0 deletions

View file

@ -0,0 +1,19 @@
import { model as Tag } from '../../../../website/server/models/tag';
describe('Tag Model', () => {
context('cleanupCorruptData', () => {
it('converts an array of tags to a safe version', () => {
const tags = [
null, // invalid, not an object
{ name: '123' }, // invalid, no id
{ id: '123' }, // invalid, no name
new Tag({ name: 'ABC', id: 123 }), // valid
];
const safetags = Tag.cleanupCorruptData(tags);
expect(safetags.length).to.equal(1);
expect(safetags[0].name).to.equal('ABC');
expect(safetags[0].id).to.equal('123');
});
});
});

View file

@ -182,6 +182,31 @@ describe('User Model', () => {
});
context('post init', () => {
it('removes invalid tags when loading the user', async () => {
let user = new User();
await user.save();
await user.update({
$set: {
tags: [
null, // invalid, not an object
// { name: '123' }, // invalid, no id - generated automatically
{ id: '123' }, // invalid, no name
{ name: 'ABC', id: '1234' }, // valid
],
},
}).exec();
user = await User.findById(user._id).exec();
const userToJSON = user.toJSON();
console.log(userToJSON.tags);
expect(userToJSON.tags.length).to.equal(1);
expect(userToJSON.tags[0]).to.have.all.keys(['id', 'name']);
expect(userToJSON.tags[0].id).to.equal('1234');
expect(userToJSON.tags[0].name).to.equal('ABC');
});
it('removes invalid push devices when loading the user', async () => {
let user = new User();
await user.save();

View file

@ -33,4 +33,19 @@ schema.statics.sanitizeUpdate = function sanitizeUpdate (updateObj) {
return this.sanitize(updateObj, noUpdate);
};
/**
* Remove invalid data from an array of tags.
* Fix for https://github.com/HabitRPG/habitica/issues/10688
* Called by user's post init hook (models/user/hooks.js)
*/
schema.statics.cleanupCorruptData = function cleanupCorruptTagsData (tags) {
if (!tags) return tags;
return tags.filter(tag => {
// Exclude tags with a nullish value or no id
if (!tag || !tag.id || !tag.name) return false;
return true;
});
};
export const model = mongoose.model('Tag', schema);

View file

@ -9,6 +9,9 @@ import {
import {
model as PushDevice,
} from '../pushDevice';
import {
model as Tag,
} from '../tag';
import { // eslint-disable-line import/no-cycle
userActivityWebhook,
} from '../../libs/webhook';
@ -198,6 +201,11 @@ schema.post('init', function postInitUser () {
this.pushDevices = PushDevice.cleanupCorruptData(this.pushDevices);
}
// Make sure tags are loaded
if (this.isDirectSelected('tags')) {
this.tags = Tag.cleanupCorruptData(this.tags);
}
return true;
});