来自beforeSave Model Hook的访问请求标头

时间:2014-11-14 10:24:20

标签: loopbackjs strongloop

如何访问从模型挂钩中提出请求的用户的详细信息

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();    
};

有没有办法做到这一点?我尝试使用远程钩子为主要项目

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();

});

一旦我从资源管理器发出请求,我就可以正确获取控制台日志,但是资源管理器始终会返回错误

"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   "
  }
}

我的模型就像

 "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
}

}

5 个答案:

答案 0 :(得分:10)

您似乎无法通过简单地覆盖ctx.req.body来更新相关模型。而不应该覆盖ctx.args.data - 看起来这个ctx参数用于初始化相关模型。

所以它看起来像那样:

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();

答案 1 :(得分:2)

beforeRemote挂钩在模型挂钩之前执行,因此您可以将userId添加到请求主体。

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();
});

您可能想要查看哪种方法字符串最适合您。

答案 2 :(得分:1)

面对同样的问题,我使用了节点expiremantal domain功能(用于错误处理)。

保存传入的请求对象:

// -- 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);
});

接下来,在模型内部钩子中,您可以访问每个连接创建的req对象:

process.domain.req 

StrongLoop团队还添加了context propagation(基于continuation-local-storage),但尚未记录。

答案 3 :(得分:1)

我通过添加用于正文解析的中间件来解决这个问题。在middleware.js中,我编写了以下代码:

...
"parse": {
   "body-parser#json": {},
   "body-parser#urlencoded": {"params": { "extended": true }}
},
...

另外,在server.js中我添加了body解析器和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
...

然后在package.json

中添加依赖项
"body-parser": "^1.12.4",
"multer": "^0.1.8"

现在你可以在/models/user.js中执行以下操作(适用于任何模型)

  user.beforeRemote('create', function(ctx, unused, next) {
     console.log("The registered user is: " + ctx.req.body.email);
     next();
  });

我希望这有帮助! :)

答案 4 :(得分:0)

如果我们假设用户的关系评论 - >注释,您也可以尝试填充foreignId的关系方法POST /users/{user_id}/comments(可以 added_by )。

另一件事是 added_at 。据我所知,在创建钩子之前触发验证钩子。这意味着验证将失败,因为此字段在模型中标记为必需。问题是这个字段是否应该标记为必需,因为它是由服务器设置的,不需要由API的客户端设置。