I've created a Mongoose base schema to take care of encrypting _id and returning it as just id for my restify based API.
BaseSchema = () ->
Schema.apply @, arguments
# Ensure virtual fields are serialised.
@set 'toJSON', {
virtuals: true
}
@set 'toObject', {
virtuals: true
}
# transform our JSON so its friendly for our API
@options.toJSON.transform = ( doc, ret, options ) ->
# remove _id and __v so we dont expose it in the API
delete ret._id
delete ret.__v
return ret
# encrypted _id in id using a virtual
@virtual('id')
.get ->
id = hashids.encryptHex this._id.toHexString()
return id
.set ( id ) ->
console.log 'Setting', id
@_id = mongoose.Types.ObjectId hashids.decryptHex(id)
return
# some default and consistent schema fields
@add {
# when the document was created
createdAt: {
type: Date,
default: Date.now
},
# when the document was modified
modifiedAt: {
type: Date,
default: Date.now
}
}
And then in subsequent schemas:
PersonSchema = new BaseSchema {}, { id: false }
To alleviate the problem of transforming the id I receive in the API querying call I've created the following restify middleware:
server.use ( req, res, next ) ->
if req.params.id
req.params.id = hashids.decryptHex req.params.id
next()
This works but I'm not happy with this.
I would like to know if there is a way of handling the decryption of the id and the translation to _id ObjectId in the Base Schema somewhere. I would like to be able to do:
server.get '/interfaces/:id', ( req, res, next ) ->
# get the interface based on id
iface = Interface.findOne { _id: req.params.id } , ( err, iface ) ->
res.send iface
next()
_id is part of the findOne {} query and so it should be translated before the actual query executes.
That would centralise the logic nicely.
Thanks !
You can use mongodb's ObjectID to convert the hex string to ObjectID before doing the query
var ObjectID = require('mongodb').ObjectID;
:
:
var id = ObjectID.createFromHexString(req.params.id);
iface = Interface.findOne { _id: id } , ( err, iface )