How can i access the details of the user who raise the request from a Model Hook
Comment.beforeSave = function(next,com) {
//Want to add 2 more properties before saving
com.added_at = new Date();
com.added_by = //How can i set the user id here ??
//In case of a Remote hook i have ctx in param and i can get user id like this ctx.req.accessToken.userId; But in Model Hook how can i do the same?
next();
};
Is there any way to do this? I tried with Remote hook for main Item in the way
MainItem.beforeRemote('**', function(ctx, user, next) {
if(ctx.methodString == 'leave_request.prototype.__create__comments'){
ctx.req.body.added_by = ctx.req.accessToken.userId;
ctx.req.body.added_at = new Date();
console.log("Added headers as .."+ctx.req.body.added_by);
}
else{
ctx.req.body.requested_at = new Date();
ctx.req.body.requested_by = ctx.req.accessToken.userId;
console.log("Added header @ else as .."+ctx.req.body.requested_by);
}
next();
});
And i get the console logs properly once i make request from explorer , but But the explorer always return me the error
"error": {
"name": "ValidationError",
"status": 422,
"message": "The `comment` instance is not valid. Details: `added_by` can't be blank; `added_at` can't be blank.",
"statusCode": 422,
"details": {
"context": "comment",
"codes": {
"added_by": [
"presence"
],
"added_at": [
"presence"
]
},
"messages": {
"added_by": [
"can't be blank"
],
"added_at": [
"can't be blank"
]
}
},
"stack": "ValidationError: The `comment` instance is not valid. Details: `added_by` can't be blank; `added_at` can't be blank.\n "
}
}
and my model is like
"properties": {
"body": {
"type": "string",
"required": true
},
"added_by": {
"type": "number",
"required": true
},
"added_at": {
"type": "date",
"required": true
},
"leave_request_id":{
"type": "number",
"required": true
}
}
It seems that you can't update related model with simply overriding ctx.req.body
. Instead of you should override ctx.args.data
- it looks like this ctx parameter is used to initalize the related model.
So it will look like that:
MainItem.beforeRemote('**', function(ctx, user, next) {
if(ctx.methodString == 'leave_request.prototype.__create__comments'){
ctx.args.data.added_by = ctx.req.accessToken.userId;
ctx.args.data.added_at = new Date();
console.log("Added headers as .."+ctx.args.data.added_by);
}
else{ ... }
next();
The beforeRemote hooks execute before the model hooks, so you can add the userId to the request body.
Comment.beforeRemote('**', function (ctx, unused, next) {
var userId = ctx.req.accessToken.userId;
if (ctx.methodString == 'Comment.create' || ctx.methodString == 'Comment.updateAttributes') {
ctx.req.body.userId = userId;
}
next();
});
you might want to review which methodstring suit you best.
Faced with the same problem, I used node expiremantal domain feature (that intended for error handling).
Saving incoming request object:
// -- Your pre-processing middleware here --
app.use(function (req, res, next) {
// create per request domain instance
var domain = require('domain').create();
// save request to domain, to make it accessible everywhere
domain.req = req;
domain.run(next);
});
Next inside model hook you have access to req object, which is created per each connection:
process.domain.req
Also StrongLoop team added context propagation (based on continuation-local-storage), but it is not documented yet.
I solved this by adding the middleware for body parsing. In the middleware.js I wrote the following code:
...
"parse": {
"body-parser#json": {},
"body-parser#urlencoded": {"params": { "extended": true }}
},
...
Also, in the server.js I added the require for the body parser and multer:
var loopback = require('loopback');
...
var bodyParser = require('body-parser');
var multer = require('multer');
...
app.use(bodyParser.json()); // application/json
app.use(bodyParser.urlencoded({ extended: true })); // application/x-www-form-urlencoded
app.use(multer()); // multipart/form-data
...
Then add the dependencies in the package.json
"body-parser": "^1.12.4",
"multer": "^0.1.8"
Now you can do things like the following in the /models/user.js (for any model)
user.beforeRemote('create', function(ctx, unused, next) {
console.log("The registered user is: " + ctx.req.body.email);
next();
});
I hope this helps! :)
If we assume that there is a relation comments of User -> Comment, you may also to try relation method POST /users/{user_id}/comments
which will populate the foreignId (which can be added_by).
Another thing is added_at. As far as I understand, validation hook is triggered before create hook. It means that validation will fail, since this field is marked as required in a model. The question is whether this field should be marked as required, since it is set by the server, and not required to be set by the client of the API.
来源:https://stackoverflow.com/questions/26927791/access-request-headers-from-beforesave-model-hook