QuasarFramework + Firebase で、userの情報を更新する

QuasarFramework + Firebaseでアプリを作る際に、Firebaseのuser情報の、displayName、emailVerified、photoURLを更新してみました。

# displayName(username)を更新

firebaseのユーザーのプロフィールにはデフォルトで、displayNameというプロパティがあるので、それをusernameとして、登録をしてみます。userオブジェクトのupdateProfileメソッドを使用します。
QusarFrameworkでは、`q-input`のpatternで、入力文字の制限ができるので、指定しておきます。

```html:Signup.vue
...
<div class="row">
  <div class="col-sm-10 offset-sm-1">
    <q-field>
      <q-input
        v-model="username"
        float-label="ユーザー名"
        color="primary"
        type="text"
        pattern="^[0-9A-Za-z]+$"/>
    </q-field>
  </div>
</div>
...
<script type="text/javascript">
...
methods: {
  signUp: function () {
    firebase.auth().createUserWithEmailAndPassword(this.email, this.password).then(
      (user) => {
        user.updateProfile({
          displayName: this.username
        }).then(() => {
          alert('アカウントの新規作成が完了しました！', user.email)
          this.$router.replace('hello')
        })
      },
      (err) => {
        let errorCode = err.code
        let errorMessage = err.message
        alert(errorCode, errorMessage)
      }
    )
  }
}
...
</script>
```

# 新規登録時に、emailVerifiedを更新するメソッドを追加する。

## メールアドレスの確認機能の設定をする。

* Firebaseのコンソール画面にログインして、Authenticationのテンプレートタブで、テンプレート言語をJapaneseに変更します。
* 件名、送信先など適宜変更します。

ここに画像

## Signup.vueにsendEmailVerificationメソッドを追記します。

```html:Signup.vue
<script type="text/javascript">
methods: {
  signUp: function () {
    firebase.auth().createUserWithEmailAndPassword(this.email, this.password).then(
      (user) => {
        user.updateProfile({
          displayName: this.username
        }).then(() => {
          user.sendEmailVerification().then(() => {
            alert('アカウントの新規作成が完了しました！', user.email)
          }).catch((err) => {
            alert('EmailVerificationでerrが発生しました。', err)
          })
          this.$router.replace('/')
        })
      },
      (err) => {
        let errorCode = err.code
        let errorMessage = err.message
        alert(errorCode, errorMessage)
      }
    )
  }
}
</script>
```

新規登録後、usernameが文面に入った確認メールが届けば成功です！

# photoUrl を更新する。
photoUrlは、プロフィール画像などを入れることができるプロパティです。
firebaseのStorageを使って、画像をアップして、そのURLをphotoUrlにセットするという手順です。

## MyPage.vueを作成する。

```html:MyPage.vue
<template lang="html">
<div class="row">
  <div class="col-xs-12 col-sm-12">
    <div class="row justify-center items-center">
      <div class="col-4">
        <img src="~assets/women.svg" class="profile-img"/>
      </div>
      <div class="col-6 offset-1 ">
        <p>{{ currentUser }}</p>
        <q-btn outline style="font-size:12px;">プロフィール写真を編集する</q-btn>
      </div>
    </div>
    <hr>
  </div>
</div>
</template>

<script>
import {
  QBtn
} from 'quasar'

export default {
  name: 'myPageProfile',
  components: {
    QBtn
  },
  computed: {
    currentUser () {
      return this.$store.getters.currentUser
    }
  }
}
</script>

<style lang="stylus">
.profile-img
  width 80px
  margin 20px

.tab-pane
  margin 20px
</style>
```

* ちなみに、Vuexは、store.jsと、module/users.jsに以下のようにセットしてます。

```javascript:store.js
import Vue from 'vue'
import Vuex from 'vuex'
import users from './modules/users'

Vue.use(Vuex)

export const store = new Vuex.Store({
  modules: {
    users
  }
})
```

```javascript:users.js
const state = {
  currentUser: null
}

const getters = {
  currentUser: state => state.currentUser
}

const mutations = {
  userStatus (state, user) {
    if (user) {
      state.currentUser = user.displayName
    }
    else {
      state.currentUser = null
    }
  }
}

const actions = {
  setUser ({ commit }, user) {
    commit('userStatus', user)
  }
}

export default {
  state,
  getters,
  mutations,
  actions
}
```

## Storageにファイルをアップする。
公式サイトを参考にセットしてみます。
https://firebase.google.com/docs/storage/web/start?hl=ja

* src/firebaseConfig.js というファイルを作成し、firebase storageを作成します。

```javascript:firebaseConfig.js
import firebase from 'firebase'

// const db = firebase.database()
const storage = firebase.storage()
export const storageProfilePhotoRef = storage.ref('profilePhoto')
```

* firebase storageのおおまかな流れは以下の通りです。
  * firebase.storage().ref(<フォルダ名>)で、Storage側の参照を作成する。
  * QusarFramework(Vue)側から、FIleAPIなどを使って、ファイルをアップする
  * QusarFramework(Vue)側で、アップしたファイル名や、ユーザー名を使用してStorage側に保存するときの絶対pathを作成する。
  * putメソッドを使って、ファイルを取得してCloud Storageにアップする


* MyPageProfile.vueに、`storageProfilePhotoRef`をimportして、ファイルをアップロードして、Cloud Storageにアップロードするようにコードを記載します。さらに、CloudStorageの読み込み用のURLも取得して、user情報にセットします。

```html:MyPageProfile.vuex
<template lang="html">
<div class="row">
  <div class="col-xs-12 col-sm-12">
    <div class="row justify-center items-center">
      <div class="col-4 text-right">
        <!-- <img src="~assets/women.svg" class="profile-img"/> -->
        <img :src="photoURL" class="profile-img"/>
      </div>
      <div class="col-6 offset-1 ">
        <p>{{ currentUser }}</p>
        <input type="file" @change="uploadPhoto">
      </div>

    </div>
    <hr>
  </div>
</div>
</template>

<script>
import {
  QBtn,
  QField,
  QInput
} from 'quasar'
import { storageProfilePhotoRef } from '../firebaseConfig'
import firebase from 'firebase'

export default {
  name: 'myPageProfile',
  components: {
    QBtn,
    QField,
    QInput
  },
  data () {
    return {
      image: '',
      url: ''
    }
  },
  computed: {
    currentUser () {
      return this.$store.getters.currentUser
    },
    photoURL () {
      return this.$store.getters.photoURL
    }
  },
  methods: {
    uploadPhoto (e) {
      // ここで、firebase storageの方のpathを作成する。
      let files = e.target.files || e.dataTransfer.files
      if (!files.length) {
        return
      }
      let path = 'images/' + this.currentUser + '/photo.png'
      let photoImagesRef = storageProfilePhotoRef.child(path)
      photoImagesRef.put(files[0]).then(
        (snapshot) => {
          const photoURL = snapshot.downloadURL
          let user = firebase.auth().currentUser
          if (user) {
            user.updateProfile({
              photoURL: photoURL
            }).then(
              () => {
                this.$store.dispatch('setUser', user)
              }
            )
          }
        },
        (err) => {
          console.log('err:', err)
        }
      )
    }
  }
}
</script>

<style lang="stylus">
.profile-img
  width 100px
  margin 20px

.tab-pane
  margin 20px
</style>
```

* Vuexのusers.jsにも、photoURLを別途取得するようにセットしておきます。

```javascript:users.js
const state = {
  currentUser: null,
  photoURL: ''
}

const getters = {
  currentUser: state => state.currentUser,
  photoURL: state => state.photoURL
}

const mutations = {
  userStatus (state, user) {
    if (user) {
      state.currentUser = user.displayName
      state.photoURL = user.photoURL
    }
    else {
      state.currentUser = null
      state.photoURL = ''
    }
  }
}

const actions = {
  setUser ({ commit }, user) {
    commit('userStatus', user)
  }
}

export default {
  state,
  getters,
  mutations,
  actions
}
```

これで、プロフィール欄に、アップロードした画像が表示されれば成功です！

![スクリーンショット 2018-01-28 21.54.08.png](https://qiita-image-store.s3.amazonaws.com/0/125574/76f2ade8-f403-36cb-46fb-2cf0b878c7f1.png)


# まとめ
Firebaseは、ファイルも比較的シンプルに処理できるのはめちゃくちゃ便利ですね！
画像保存のあたりのコードがちょっと複雑になっていますので、別のいいやり方がありましたら、ご指摘いただけますと幸いです。