さぁ、firebaseでユーザーが管理者かどうかの判別を行おう！

皆さん、「管理者のユーザーだけこのテキスト、ボタンを表示したい」とか、「ユーザーにはこのテキスト、ボタンを表示したい」と思ったこと一度はありますよね？？？

firebaseの関数``firebase.auth().currentUser``や``firebase.auth().onAuthStateChanged()``でユーザーの管理者かどうかを判断するプロパティは存在しないんです。悲しい。。。

なので、firebaseでユーザーの管理者かどうかを判別する方法をご紹介します！！

そんなに難しくないので、是非学習の参考にしてください！

それでは一緒に順を追って説明を見ていきましょう！！（ここからはfirebase-functionsを利用します。firebase-functionsの説明は致しませんのでご了承ください。）

また、この記事を書くにあたって[Firebase で公開するウェブサイトに「管理者機能」を付ける](https://lnly.hatenablog.com/entry/2019/01/25/012744)を参考にさせて頂きました。ご協力ありがとうございます！

#権限を付与する関数を作成#

```functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');

admin.initializeApp({
    databaseURL: 'YOUR_DATABASE_URL'
})

//ユーザー権限（管理者）付与
exports.addAdminClaim = functions.firestore.document('admin_users/{docID}').onCreate((snap) => {
    const newAdminUser = snap.data();
    if (newAdminUser === undefined) {
        return;
    }
    modifyAdmin(newAdminUser.uid, true);
    //true: 管理者
});
```

#権限を消去する関数を作成#

```functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');

//ユーザー権限（管理者）付与
exports.addAdminClaim = functions.firestore.document('admin_users/{docID}').onCreate((snap) => {
    const newAdminUser = snap.data();
    if (newAdminUser === undefined) {
        return;
    }
    modifyAdmin(newAdminUser.uid, true);
    //true: 管理者
});

//ユーザー権限（管理者）消去
exports.removeAdminClaim = functions.firestore.document('admin_users/{docID}').onDelete((snap) => {
  const deletedAdminUser = snap.data();
  if (deletedAdminUser === undefined) {
    return;
  }
  modifyAdmin(deletedAdminUser.uid, false);
  //false: 管理者ではないユーザー
});
```

#権限付与・消去を行う関数#

```functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');

//ユーザー権限（管理者）付与
exports.addAdminClaim = functions.firestore.document('admin_users/{docID}').onCreate((snap) => {
    const newAdminUser = snap.data();
    if (newAdminUser === undefined) {
        return;
    }
    modifyAdmin(newAdminUser.uid, true);
    //true: 管理者
});

//ユーザー権限（管理者）消去
exports.removeAdminClaim = functions.firestore.document('admin_users/{docID}').onDelete((snap) => {
  const deletedAdminUser = snap.data();
  if (deletedAdminUser === undefined) {
    return;
  }
  modifyAdmin(deletedAdminUser.uid, false);
  //false: 管理者ではないユーザー
});

const modifyAdmin = (uid, isAdmin) => {
  admin.auth().setCustomUserClaims(uid, {admin: isAdmin}).then()
}
```

#作成した関数をデプロイ#

```
firebase deploy --only functions
```


後は、「firebase console」を開き、以下の手順に沿ってコレクションを作成してください。

まず、初めに「Authentication」を開き、管理者の権限を付与したいユーザーの「ユーザー UID」をコピーしてください。（IDではなくユーザー UIDです！間違えないように！！！）

次に、Cloud firestore →　コレクションを開始 →　コレクションIDに「admin_users」と入力 →　ドキュメントIDを作成（自動IDをクリック） →　フィールドに「uid」と入力 →　タイプは「string」 →　値には先ほどコピーしたUIDをペーストしてください。

これで、設定は終わりです。

あとは、これを判別する関数を呼び出すだけ！

呼び出したいページで``getIdTokenResult()``を実行してください。

```index.js
firebase.auth().onAuthStateChanged((user) => {
  user.getIdTokenResult(true).then((idTokenResult) => {
        if (idTokenResult.claims.admin) {
          commit("userRights");
        }
      });
})
```

<br>

**2021/01/08：追記**
「Clound firestore」にて、ルールを追加しないとadminが機能しない事例が発生したので、下記のルールを追加してください。

```
service cloud.firestore {
  match /databases/{database}/documents {
    match /portfolios/{document=**} {
      allow read;
      allow write: if request.auth.token.admin == true;
    }
    match /skills/{document=**} {
      allow read;
      allow write: if request.auth.token.admin == true;
    }
  }
}
```

これで``idTokenResult.claims.admin``の実行結果が``true``ならば管理者、``false``ならユーザーという結果になります。

実際にこのコードをコピペして頂くだけで実行できるかと思います。

色々なところで活用できると思うので、ぜひ使ってください！！！！

以上、「firebaseでユーザーが管理者かどうかの判別を行う方法」でした！！

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

Thank you for reading