private fieldに設定した項目を特定のAPIで取得する方法

Strapi Advent Calenderの12日目は、11日目の記事[strapiのGETで関連テーブルのデータ取得を制御する方法](https://qiita.com/yamagamisan/items/9a786cc1590f688d65e7)内の、項目をprivateにする方法で取得を制御した時に、特定のAPIでのみprivate項目も含めて取得させる、APIのカスタマイズ方法を書いて行きたいと思います。

例えば、usersモデルのemailなど、find、findOneなどのAPIでは取得したくないけどme APIだけでは取得させたい。。。などの時に使えるかなと思います。

# 前提

サンプルとして、11日目の記事[strapiのGETで関連テーブルのデータ取得を制御する方法](https://qiita.com/yamagamisan/items/9a786cc1590f688d65e7)と同じモデルを使用します。

```
baseModel: emailを持っていて、relationalModelに1:1のリレーションが張られている
relationalModel: name, summaryを持っていて、baseModelに1:1のリレーションが張られている
```

privateの設定についても11日目の記事の[privateをtrueに設定する]()のように、`relational_model`が`true`になっている前提で、findOne APIの時だけ、private fieldを取得するようにAPIをカスタマイズしていきます。

```json:/api/base-model/models/base-model.settings.json
{
  "kind": "collectionType",
  "collectionName": "base_models",
  "info": {
    "name": "baseModel"
  },
  "options": {
    "increments": true,
    "timestamps": true
  },
  "attributes": {
    "email": {
      "type": "email"
    },
    "relational_model": {
      "model": "relational-model",
      "via": "base_model",
      "private": true
    }
  }
}
```

# APIをカスタマイズする

と言っても、とっても簡単です。
デフォルトのfindOne APIの中身はこんな感じで、取得したデータを`sanitizeEntity()`に通してから返却しています。この`sanitizeEntity()`のなかでprivateに設定した項目を払っているので、カスタマイズの方法としては、a.` sanitizeEntity()`に通さずにデータを返却すると b. `sanitizeEntity()`後に、改めてデータを付与してから返却するの2通り考えられます。

```javascript

  async findOne(ctx) {
    const { id } = ctx.params;

    const entity = await strapi.services.restaurant.findOne({ id });
    return sanitizeEntity(entity, { model: strapi.models.restaurant });
  },
```

## 1. findOne の中身をコピーする
`/api/base-model/controllers/base-model.settings.js`にfindOneの処理をコピぺします。
[strapiのドキュメント](https://strapi.io/documentation/v3.x/concepts/controllers.html#controllers)から引っ張ってくると楽です。

```javascript:/api/base-model/controllers/base-model.settings.js
'use strict';
const { sanitizeEntity } = require('strapi-utils');

module.exports = {
  async findOne(ctx) {
    const { id } = ctx.params;
    const entity = await strapi.services.restaurant.findOne({ id });
    return sanitizeEntity(entity, { model: strapi.models.restaurant });
  },
};
```

## 2-a. sanitizeEntity()に通さずにデータを返却する
private設定した項目を全て取得したい場合は、こちらの方法が良いと思います。

```javascript:/api/base-model/controllers/base-model.settings.js
'use strict';
const { sanitizeEntity } = require('strapi-utils');

module.exports = {
  async findOne(ctx) {
    const { id } = ctx.params;
    const entity = await strapi.services.restaurant.findOne({ id });
    return entity
  },
};
```

## 2-b. sanitizeEntity()後に、改めてデータを付与してから返却する
private設定にした一部の項目を取得したい場合などに。

```javascript:/api/base-model/controllers/base-model.settings.js
'use strict';
const { sanitizeEntity } = require('strapi-utils');

module.exports = {
  async findOne(ctx) {
    const { id } = ctx.params;
    const entity = await strapi.services.restaurant.findOne({ id });
    const sanitizeEntity = sanitizeEntity(entity, { model: strapi.models.restaurant });
    sanitizeEntity.relational_model = enity.relational_model;
    return 
  },
};
```

# 終わりに

今回はprivateに設定した項目を、APIをカスタマイズして取得する方法を紹介しましたが、それ以外にもデータの取得をする方法を前日に紹介していますので、併せてチェックしていただければと思います。
[strapiのGETで関連テーブルのデータ取得を制御する方法](https://qiita.com/yamagamisan/items/9a786cc1590f688d65e7)

# 参考
https://strapi.io/documentation/3.0.0-beta.x/guides/custom-data-response.html#get-the-data-back
https://strapi.io/documentation/v3.x/concepts/controllers.html#core-controllers