mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 23:27:26 +01:00
add baseModel plugin with some tests
This commit is contained in:
59
test/api/v3/unit/libs/baseModel.test.js
Normal file
59
test/api/v3/unit/libs/baseModel.test.js
Normal file
@@ -0,0 +1,59 @@
|
||||
import baseModel from '../../../../../website/src/libs/api-v3/baseModel';
|
||||
|
||||
describe('Base model plugin', () => {
|
||||
let schema = {
|
||||
add () {
|
||||
return true;
|
||||
},
|
||||
statics: {},
|
||||
options: {},
|
||||
pre () {
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
sandbox.stub(schema, 'add');
|
||||
});
|
||||
|
||||
it('adds a _id field to the schema', () => {
|
||||
baseModel(schema);
|
||||
|
||||
expect(schema.add).to.be.calledWith(sinon.match({
|
||||
_id: sinon.match.object,
|
||||
}));
|
||||
});
|
||||
|
||||
it('can add timestamps fields', () => {
|
||||
baseModel(schema, {timestamps: true});
|
||||
|
||||
expect(schema.add).to.be.calledTwice;
|
||||
});
|
||||
|
||||
it('can sanitize input objects', () => {
|
||||
baseModel(schema, {
|
||||
noSet: ['noUpdateForMe']
|
||||
});
|
||||
|
||||
expect(schema.statics.sanitize).to.exist;
|
||||
let sanitized = schema.statics.sanitize({ok: true, noUpdateForMe: true});
|
||||
|
||||
expect(sanitized).to.have.property('ok');
|
||||
expect(sanitized).to.have.property('noUpdateForMe');
|
||||
expect(sanitized.noUpdateForMe).to.equal(undefined);
|
||||
});
|
||||
|
||||
it('can make fields private', () => {
|
||||
baseModel(schema, {
|
||||
private: ['amPrivate']
|
||||
});
|
||||
|
||||
expect(schema.options.toObject.transform).to.exist;
|
||||
let objToTransform = {ok: true, amPrivate: true};
|
||||
let privatized = schema.options.toObject.transform({}, objToTransform);
|
||||
|
||||
expect(objToTransform).to.have.property('ok');
|
||||
expect(objToTransform).to.have.property('amPrivate');
|
||||
expect(objToTransform.amPrivate).to.equal(undefined);
|
||||
});
|
||||
});
|
||||
53
website/src/libs/api-v3/baseModel.js
Normal file
53
website/src/libs/api-v3/baseModel.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import _ from 'lodash';
|
||||
import { uuid } from '../../../../common';
|
||||
import validator from 'validator';
|
||||
|
||||
export default function baseModel (schema, options = {}) {
|
||||
schema.add({
|
||||
_id: {
|
||||
type: String,
|
||||
default: uuid.v4,
|
||||
validate: [validator.isUUID, 'Invalid uuid.'], // TODO check for UUID version
|
||||
},
|
||||
});
|
||||
|
||||
if (options.timestamps) {
|
||||
schema.add({
|
||||
createdAt: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (options.timestamps) {
|
||||
schema.pre('save', function updateUpdatedAt (next) {
|
||||
if (!this.isNew) this.updatedAt = Date.now();
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
let noSetFields = ['createdAt', 'updatedAt'];
|
||||
let privateFields = ['__v'];
|
||||
|
||||
if (Array.isArray(options.noSet)) noSetFields.push(...options.noSet);
|
||||
schema.statics.sanitize = function sanitize (objToSanitize = {}) {
|
||||
noSetFields.forEach((fieldPath) => {
|
||||
_.set(objToSanitize, fieldPath, undefined); // TODO decide wheter to use delete here
|
||||
});
|
||||
|
||||
return objToSanitize;
|
||||
};
|
||||
|
||||
if (Array.isArray(options.private)) privateFields.push(...options.private);
|
||||
if (!schema.options.toObject) schema.options.toObject = {};
|
||||
schema.options.toObject.transform = function transformToObject (doc, plainObj) {
|
||||
privateFields.forEach((fieldPath) => {
|
||||
_.set(plainObj, fieldPath, undefined); // TODO decide wheter to use delete here
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -5,19 +5,13 @@ import _ from 'lodash';
|
||||
import validator from 'validator';
|
||||
import moment from 'moment';
|
||||
import TaskSchemas from './task';
|
||||
import baseModel from '../libs/api-v3/baseModel';
|
||||
// import {model as Challenge} from './challenge';
|
||||
|
||||
let Schema = mongoose.Schema;
|
||||
|
||||
// User schema definition
|
||||
export let schema = new Schema({
|
||||
// The user _id, stored as a string
|
||||
// TODO validation
|
||||
_id: {
|
||||
type: String,
|
||||
default: shared.uuid,
|
||||
},
|
||||
// TODO validation
|
||||
apiToken: {
|
||||
type: String,
|
||||
default: shared.uuid,
|
||||
@@ -480,6 +474,12 @@ export let schema = new Schema({
|
||||
minimize: false, // So empty objects are returned
|
||||
});
|
||||
|
||||
schema.plugin(baseModel, {
|
||||
noSet: ['_id', 'apikey', 'auth.blocked', 'auth.timestamps', 'lastCron', 'auth.local.hashed_password', 'auth.local.salt'],
|
||||
private: ['auth.local.hashed_password', 'auth.local.salt'],
|
||||
});
|
||||
|
||||
|
||||
schema.methods.deleteTask = function deleteTask (tid) {
|
||||
this.ops.deleteTask({params: {id: tid}}, () => {}); // TODO remove this whole method, since it just proxies, and change all references to this method
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user