web-dev-qa-db-ja.com

逐次化:パスワードを返さない

私はSequelizeを使用してユーザーレコードのDB検索を行い、モデルのデフォルトの動作でnotpasswordフィールド。 passwordフィールドはハッシュですが、それを返したくありません。

うまくいくいくつかのオプションがありますが、特に良いようには見えません:

  1. findWithoutPasswordモデルのカスタムクラスメソッドUserを作成し、そのメソッド内でUser.findattributesのように設定されている)Sequelize docs

  2. 通常のUser.findおよびコントローラーで結果をフィルター処理します(推奨されません)

  3. 他のライブラリを使用して、不要な属性を取り除きます

もっと良い方法はありますか?何よりも、Sequelizeモデル定義でpasswordフィールドを返さないように指定する方法がある場合が最善ですが、それを行う方法が見つかりません。

29
Tyler

toJSON関数をオーバーライドすることをお勧めします。

sequelize.define('user', attributes, {
  instanceMethods: {
    toJSON: function () {
      var values = Object.assign({}, this.get());

      delete values.password;
      return values;
    }
  }
});

またはsequelize v4

const User = sequelize.define('user', attributes, {});

User.prototype.toJSON =  function () {
  var values = Object.assign({}, this.get());

  delete values.password;
  return values;
}

toJSONは、データがユーザーに返されるときに呼び出されるため、エンドユーザーにはパスワードフィールドは表示されませんが、コードでは引き続き使用できます。

Object.assignは、返されたオブジェクトのクローンを作成します。それ以外の場合は、インスタンスからプロパティを完全に削除します。

56

もう1つの方法は、デフォルトのスコープをUserモデルに追加することです。

これをモデルのオプションオブジェクトに追加します

defaultScope: {
  attributes: { exclude: ['password'] },
}

または、特定のクエリでのみ使用する別のスコープを作成することもできます。

これをモデルのオプションオブジェクトに追加します

scopes: {
  withoutPassword: {
    attributes: { exclude: ['password'] },
  }
}

その後、クエリで使用できます

User.scope('withoutPassword').findAll();
48
Pawan Samdani

多分あなたはあなたの属性にexcludefindのときに次のように追加することができます:

var User = sequelize.define('user', attributes);

User.findAll({
    attributes: {
        exclude: ['password']
    }
});

詳細については docs を参照してください

23
Lai32290

私はPawanの両方の答えを組み合わせて使用​​し、以下を宣言するのが好きです。

defaultScope: {
    attributes: { exclude: ['password'] },
},
scopes: {
    withPassword: {
        attributes: { },
    }
}

これにより、デフォルトでパスワードを除外し、withPasswordスコープを使用して、ログインメソッドの実行時など、必要なときに明示的にパスワードを返すことができます。

userModel.scope('withPassword').findAll()

これにより、参照フィールドを介してユーザーを含めるときに、パスワードが返されないことが保証されます。

accountModel.findAll({
    include: [{
        model: userModel,
        as: 'user'
    }]
})
12
Matthew Cawley

undefinedを返すフィールドにゲッターを追加することで、これを機能させることができました

firstName: {
      type: DataTypes.STRING,
      get() {
        return undefined;
      }
    }

承認された回答 は、モデルが別のモデルから含まれている場合は機能しません。

非表示にしたいフィールドに依存するfullNameと言う仮想フィールドがありました。たとえば、firstNamelastNameです。また、この場合、defaultScopeに基づく solution は機能しません。

1
Ajmal Ahammed

スコーピング属性 のためのプラグインがあります---議論されたように ここ

api docs で説明されているように、this.constructor.super_.prototype.toJSON.apply(this, arguments)を使用してtoJSONではなく、元のgetを呼び出したことを除いて、受け入れられた回答で述べたようにオーバーライドを行いました。

0
user2571090

以下のコードは私のために働いた。実行時にインスタンス属性にアクセスする必要がありましたが、クライアントにデータを送信する前にそれらを削除しました。

const Sequelize = require('sequelize')

const sequelize = new Sequelize('postgres://user:[email protected]:5432/dbname')

const PROTECTED_ATTRIBUTES = ['password', 'token']

const Model = Sequelize.Model

class User extends Model {
  toJSON () {
    // hide protected fields
    let attributes = Object.assign({}, this.get())
    for (let a of PROTECTED_ATTRIBUTES) {
      delete attributes[a]
    }
    return attributes
  }
}

User.init({
  email: {
    type: Sequelize.STRING,
    unique: true,
    allowNull: false,
    validate: {
      isEmail: true
    }
  },
  password: {
    type: Sequelize.STRING,
    allowNull: false
  },
  token: {
    type: Sequelize.STRING(16),
    unique: true,
    allowNull: false
  },
},
{
  sequelize,
  modelName: 'user'
})

module.exports = User

Github Gist

0
Arivia