hunt
Version:
High level nodejs framework build on top of expressjs, mongoose, sequilize, socketio and passportjs
162 lines (141 loc) • 4.87 kB
JavaScript
;
var
util = require('util'),
fieldsReadable = [
'_id',
'id',
'new',
'message',
'$isMine',
'$subscribeToken',
'createdAt',
'updatedAt',
'ago'],
fieldsWritable = ['message'],
fieldsToPopulate = ['to', 'from'];
/**
* @class Message
* @classdesc
* Class that represents users' private one-to-one messages.
* Usually used from {@link User} class.
* This class is an ancestor of mongoose active record object, described here {@link http://mongoosejs.com/docs/documents.html},
* {@link http://mongoosejs.com/docs/queries.html}
*
* Note: before saving message have all special symbols escaped.
*
* @property {ObjectId} _id
* @property {string} id
* @property {User} to
* @property {User} from
* @property {Date} createdAt
* @property {string} message
* @property {Number} ago
* */
module.exports = exports = function (core) {
var
validator = core.validator,
messageSchema = new core.mongoose.Schema({
'to': {type: core.mongoose.Schema.Types.ObjectId, ref: 'User', index: true, required: true},
'from': {type: core.mongoose.Schema.Types.ObjectId, ref: 'User', index: true, required: true},
'new': {type: Boolean, index: true, default: true},
'updatedAt': {type: Date, default: Date.now},
'createdAt': {type: Date, default: Date.now, index: true},
'message': {type: String, trim: true} //trim whitespaces - http://mongoosejs.com/docs/api.html#schema_string_SchemaString-trim
});
messageSchema.path('to').validate(function (value, callback) {
core.model.User.findById(value, function (error, clientFound) {
if (error) {
throw error;
}
callback(clientFound !== null);
});
}, 'Please provide an existent `to` user id!'); //https://stackoverflow.com/questions/14271682/mongoose-asynchronous-schema-validation-is-not-working
messageSchema.path('from').validate(function (value, callback) {
core.model.User.findById(value, function (error, clientFound) {
if (error) {
throw error;
}
callback(clientFound !== null);
});
}, 'Please provide an existent `from` user id!'); //https://stackoverflow.com/questions/14271682/mongoose-asynchronous-schema-validation-is-not-working
messageSchema.pre('save', function (next) {
this.message = validator.escape(this.message);
this.updatedAt = new Date();
next();
});
messageSchema.virtual('ago')
.get(function () {
var now = new Date().getTime();
return Math.floor((now - this.createdAt.getTime()) / 1000);
});
messageSchema.virtual('isMine')
.get(function () {
return true;
});
messageSchema.statics.canCreate = function (user, callback) {
callback(null, !!user, ['to', 'message']);
};
messageSchema.statics.listFilter = function (user, callback) {
if (user) {
if (user.root) {
callback(null, {});
} else {
callback(null, {$and: [{$or: [{'to': user._id}, {'from': user._id}]}]});
}
} else {
callback(null, false);
}
};
messageSchema.methods.canRead = function (user, callback) {
if (user && ((user._id.equals(this.to._id || this.to) || user._id.equals(this.from._id || this.from) || user.root))) {
callback(null, true, fieldsReadable, fieldsToPopulate);
} else {
callback(null, false);
}
};
messageSchema.methods.canUpdate = function (user, callback) {
if (user && (user.root || user._id.equals(this.from))) {
callback(null, true, fieldsWritable);
} else {
callback(null, false);
}
};
messageSchema.methods.canDelete = function (user, callback) {
callback(null, (user && user.root));
};
messageSchema.methods.dismiss = function (user, callback) {
if (user && user._id.equals(this.to)) {
this.new = false;
this.save(callback);
} else {
callback(new Error('NOT_YOUR_MESSAGE'));
}
};
messageSchema.methods.toString = function () {
return util.format('Message #%s', this.id);
};
messageSchema.post('save', function (msg) {
msg
.populate('to from', function (error, messageCreated) {
if (error) {
throw error;
}
var p = {
'_id': messageCreated._id,
'id': messageCreated.id,
'to': messageCreated.to,
'new': messageCreated.new,
'from': messageCreated.from,
'message': messageCreated.message,
'createdAt': messageCreated.createdAt,
'updatedAt': messageCreated.updatedAt,
'ago': messageCreated.ago
};
p.$isMine = false;
messageCreated.to.notifyBySocketIo(p, 'notify:pm:in');
p.$isMine = true;
messageCreated.from.notifyBySocketIo(p, 'notify:pm:out');
});
});
return core.mongoConnection.model('Message', messageSchema);
};