web-dev-qa-db-ja.com

RESTful MEANスタックでのリクエストとレスポンスのフィルタリング

MEANスタック(MongoDb、Express.js、Angular.js、Node.js)を使用し、Mongoose ODMを利用して書かれた非常に基本的なRESTfulサービスがあります。

Productスキーマ

var productSchema = new mongoose.Schema({
  name: {type: String, required: true, maxlength: 250},
  _prices: [{
    amount: {type: Number,required: true,min: 0.0},
    date: {type: Date, required: true, default: Date.now}
  }]
});

productSchema
.virtual('price')
.get(function () {
  var price = this._prices[this._prices.length - 1];
  return price !== undefined ? price.amount : undefined;
});

productSchema.methods.setPrice = function (amount) {
  this._prices.Push({amount: amount});  
};

_prices配列とprice仮想プロパティの目的は、価格履歴の監査証跡を保存することです。

通常のGETPOSTPUTおよびDELETEをサポートする/productsのRESTfulインターフェイスがあります。

私のシステムでは、管理者はPOSTPUT、およびDELETEを許可されていますが、匿名アクセスの場合に問題が発生します。匿名ユーザーはGETのみを許可されていますが、履歴を表示できるのは管理者だけなので、GETレスポンスには_pricesフィールドを含めないでください。

匿名として

{
  name: "Widget", 
  price: "5.99"
}

管理者として

{
  name: "Widget", 
  price: "5.99", 
  _prices: [
    {price: "7.25", date: "2015-02-28"}, 
    {price: "5.99", date: "2016-01-09"}
  ]
}

MEANスタックに関して読んだチュートリアルの大部分は、常にマングースモデルを直接返すことを示しています。

exports.getAll = function(request, response) {
  Product.find({}, '-_prices', function (err, products) {
    res.json(200, products);
  });
};

これはproductsコントローラーから回避するのは非常に簡単ですが、このフィルターロジックがコントローラーにあるため、これは非常に見当違いであり、スキーマに新しいフィールドを追加する場合は脆弱であることがわかります。コントローラに戻って、将来フィールドを公開しないようにします。

また、リクエストの検証を行う、別の方法についても質問があります。ほとんどのチュートリアルでは、ユーザー入力をそのまま受け入れて、マングースの検証を失敗させているようです。

exports.post = function(request, response) {
  var product = new Product(request.body)

  product.save(function(error, product) {
    if (error) {
      return response.json(422, error);
    }

    response.send(201);
  });  
};

ASP.NET WebApiに慣れているため、これに対する私の見方は少し歪んでいます。私はおそらく、リクエストに対して個別のビューモデルを作成し、レスポンスに対して異なるビューモデルを作成し(認証されているかどうかに応じて)、リクエストのビューモデルで入力検証を行い、エンティティ内で不変の検証のみを行います。ただし、MEANスタックの方法で実行していることを確認します。

私の質問は次のとおりです。

  1. 入力の検証はmongooseの検証のみに依存する必要がありますか、それともmongooseに到達する前に独自に作成する必要がありますか?

  2. 出力フィルタリングの場合、Productを受け入れ、ユーザーの管理者であるかどうかに応じて、ユーザーのコンテキストに応じてビューモデルを返すセキュリティ/フィルタリングモジュールを作成する必要がありますか?

  3. フィルタリングを行うには、toJSONの動作(マングースで拡張可能です)をオーバーライドする必要がありますか?

  4. コントローラとマングースの間に抽象レイヤーを作成する必要がありますか?

私の最初の考えは、マングース自体は責任が多すぎるということですが、それが最善のアプローチである場合は、使用を避けたくありません。

4
Matthew
  1. 入力の検証はmongooseの検証のみに依存する必要がありますか、それともmongooseに到達する前に独自に作成する必要がありますか?

サービスの種類によっては、DB内ではなく、DBモジュールとHTTPモジュールの間でチェックを行う必要があると思います。

  1. 出力フィルタリングの場合、製品を受け入れ、管理者であるかどうかに応じて、ユーザーのコンテキストに応じてビューモデルを返すセキュリティ/フィルタリングモジュールを作成する必要がありますか?

モデルからHTTPインターフェースに何かが直接返される方法が嫌いですが、ここでは最も簡単な方法を使用できます。必要に応じて、リクエストハンドラーで権限を確認し、余分なフィールドを削除してオブジェクトを調整します。これは行数が少なくなります。

  1. フィルタリングを行うには、toJSONの動作(Mongooseでは拡張可能です)をオーバーライドする必要がありますか?

番号。

  1. コントローラとマングースの間に抽象レイヤーを作成する必要がありますか?

データモデルレイヤーですか?いいえ。コントローラでこれを「制御」します。

1