Vue.js,FirestoreでのSNSログインでも重複を防いでデータベースに保存する方法

2021.01.18

見出し画像

Firebaseの良いところはログイン関係が比較的楽に実装できるのが良いところだと思っています。

ですがまだまだ無知な部分があったのでその事を振り返っていきたいと思います。

目次

  1. 治したい事
  2. 考え方
  3. 実際のコード
  4. なんかもっと良さそうなやり方

改善したい事

ユーザーが新規登録する際にデータベースに保存されるようにしているが、SNSログインだと毎回データベースに保存されるようになってしまっている。

初回のログインはデータベースに保存するが、2回目以降は保存させないようにしたい。

考え方

初回はとにかくデータベースに保存する。(Usersコレクションに保存しています)

SNSログインの際は毎回データベースに既に保存されているユーザでは無いかを確認する。

保存されていない場合は、新規としてデータベースに保存する動きにする。

既に保存されている場合はログインするだけの処理にする。

こんな感じのイメージで分けていきました。

実際のコード

<script>
import firebase from 'firebase/app' 
import "@firebase/auth"
import 'firebase/database'
import db from '../firebase'
export default {  

 goggleLogin() {
     let provider =  new firebase.auth.GoogleAuthProvider()
     firebase.auth().signInWithPopup(provider).then(res => {
       let user = res.user
       db.collection('users').onSnapshot(users => {
         let array = []
         users.forEach(user => {
           let i = user.data()
           i.id = user.id
           array.push(i)
         })
         function checkAlreadyUsers(arr, id) {
           return arr.some(function(value) {
             return id === value.user_id
           })
         }
         if(array.length) {
           if(checkAlreadyUsers(array, user.uid)) {
             console.log('登録済み')
             this.$router.push('/list')
           } else {
             console.log('新規登録')
             db.collection('users').add({
             user_id: user.uid,
             email: user.email,
             name: user.displayName
             }).then(() => {
               this.$router.push('/list')
             }).catch(err => {
               console.log(err)
             })
           }
         }
       })
     })
     .catch(err => {
       console.log(err)
     })
   }
}
</script>

checkAlreadyUsersの処理について少し。

if(checkAlreadyUsers(array, user.uid))で引数のarrayはlet array = []で用意されている配列。user.uidは下記のlet userを使っている。

firebase.auth().signInWithPopup(provider).then(res => {
       let user = res.user

checkAlreadyUsers関数の処理ではsomeメソッドを使用している。詳しくは下記のサイトで。Array.prototype.some()some() メソッドは、配列の少なくとも 1 つの要素が、渡された関数によって実施されるテストに通るかどうかをテストしまdeveloper.mozilla.org

先ほど実引数として渡した値を、引数arrとidとして受け取り使用します。

idには現在ログインしようとしているuserのuidが入っています。

arrには現在Usersコレクションに保存されているuserたちが入っています。そこからsomeで取り出しarrの中でuser_idがidと一致するものがあるかどうかを処理しています。

     function checkAlreadyUsers(arr, id) {
           return arr.some(function(value) {
             return id === value.user_id
           })
         }

あとは一致した場合はログインさせ、一致しなかった場合はデータベースに保存する処理を通すようにしてあげると良いかなと思います。

なんかもっと良さそうなやり方

ユーザーが新規で新しく作成されると、FirebaseのAuthenticationというところに保存されている。

見た感じここは何度も同じユーザーでSNSログインしても重複していなかった。

なのでAuthenticationと比較するようにすれば、毎回Usersコレクションを使う必要がなくなりそう。

Usersコレクションを使う必要がなくなれば、Usersコレクション自体が無くても済んだりするのかな。。。。

とか思いつつw

以上!