2020/03/16: USER_PUBLIC_FIELDS は廃止されました。
詳細: /資料/開発ガイドライン/USER_PUBLIC_FIELDS の扱いについて

発端の PR

https://github.com/weseek/growi/pull/2667#discussion_r472997559 external_link

データを model から取得する時は、route, service 層が何を取得するのかを決めるのであって、 Model 層のメソッドでは制限をすることはしない。
よって、 route, service 層でフィールド管理を忘れないようにしなければならない。

models/user.js には toObject に transform を設定してあって、
用途に応じて return する目的が定まっている主体によって利用される。

一例

src/server/service/page.js
serializeToObj(page) { const { User } = this.crowi.models; const returnObj = page.toObject(); // set the ObjectID to revisionHackmdSynced if (page.revisionHackmdSynced != null && page.revisionHackmdSynced._id != null) { returnObj.revisionHackmdSynced = page.revisionHackmdSynced._id; } if (page.lastUpdateUser != null && page.lastUpdateUser instanceof User) { returnObj.lastUpdateUser = page.lastUpdateUser.toObject(); } if (page.creator != null && page.creator instanceof User) { returnObj.creator = page.creator.toObject(); } return returnObj; }

model 層でフィールド制限をすることの危険性

  • route, service層で model 層を信頼したコード(password など secret な情報を制限しない)が発生しうる。
  • その結果、対策を行っているアクションとそうでないアクションが並行して存在する。
    • 結果としてメンテナンス時の落とし穴になりやすい。

開発にあたって

以下の 2点に気をつける

  • route, service 層でデータを取得する際には取得するデータにフィールドの制限がされていないことを意識する。
    • ORM の組み込みメソッド(Mongoose の findOne など)や、model メソッドどちらも制限がされていない。
    • 必要に応じて、select や toObject を使用しフィールドを制限する。
  • Model 層にはフィールド制限を使用したメソッドを作らない
    • model では対策を行わず、route, service 層での対策のみ。

例外

Model 層のメソッドであっても、 populateDataTo* のような名前がついている場合、体を表しているので許容する。