0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

QR忘れ物アプリ (2) ログインページ [Vue,Vuetify,Firebase]

Last updated at Posted at 2021-04-17

はじめに

前回:環境構築

https://qiita.com/rayan/items/5d04ee2ca7860c220dec

GitHubリポジトリ

準備中

用いる省略名称

RTDB: Realtime Database

操作するファイル

  • public
    • index.js
  • src
    • mixins
      • databaseOps.js
    • router
      • index.js
    • views
      • Authentication.vue (新規ファイル)
    • App.vue

public/index.js

Vuetify用のfont, material-design-iconを追加。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <!-- update the version number as needed -->
    <script src="/__/firebase/8.3.1/firebase-app.js"></script>
    <!-- include only the Firebase features as you need -->
    <script src="/__/firebase/8.3.1/firebase-auth.js"></script>
    <script src="/__/firebase/8.3.1/firebase-database.js"></script>
    <script src="/__/firebase/8.3.1/firebase-functions.js"></script>
    <!-- 
      initialize the SDK after all desired features are loaded, set useEmulator to false
      to avoid connecting the SDK to running emulators.
    -->
    <script src="/__/firebase/init.js?useEmulator=true"></script>
    <script src="https://www.gstatic.com/firebasejs/ui/4.8.0/firebase-ui-auth.js"></script>
    <link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/4.8.0/firebase-ui-auth.css" />
    <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

src/mixins/databaseOps.js

  • Firebase RTDB関連のfunctionを格納します
  • mixinは複数のcomponentで共通するメソッドの格納する目的で用います
  • Vue.prototype.$userIdにユーザーIDを格納して、どのcomponentからも参照できるようにします。
import Vue from 'vue'

export default {
    methods: {
        // User Credentials
        addUserCredentials(data) {
            firebase.database().ref('userCredentials/'+this.$userId).set(data);
        },

        // User Preferences
        initUserPreferences() {    
            var data = {
                'notifyAtLinkOpen': false,
                'notifyNotLostItem': true,
                'whereToNotify': 'email'
            };
            firebase.database().ref('userPreferences/'+this.$userId).set(data);
        },
        setUserPreferences(data) {
            firebase.database().ref('userPreferences/'+this.$userId).set(data);
        },
    }
}

src/views/Authentication.vue

src/views内に新しくAuthentication.vueを作ります。ログイン・新規登録画面のHTMLです。

  • ログイン・新規登録画面画面

    • loaderはログイン・新規登録画面のdiv要素がロード中に"Loading..."と表示するdiv要素です。
    • firebaseui-auth-containerはログイン・新規登録画面のdiv要素です。
  • loginScreen

    • mounted
      • mountedは要素がDOMに追加されたときに呼ばれます。
    • uiconfig
      • EmailAuthProvider: メールアドレスとパスワードによるログインを行います。
    • callbacks
      • signInSuccessWithAuthResult
        • サインインに成功したときに呼ばれます。
          • サインイン結果からuiddisplayNameemailを得ることができます。
        • 新規登録の時にはaddUserを呼び、RTDBにユーザーを登録します。
      • uiShown
        • UIがロードされたときに呼ばれます。今回はロードが終了したため、loaderの表示を消します。
  • addUser

    • ユーザーを追加し、userPreferencesを初期設定します。
    • Firebase AuthのユーザーID(userId) をVue.prototype.$userIdに格納し、他のcomponentから参照できるようにします。
<template>
  <!-- authentication -->
  <div id="userAuthentication" style="display:block">
    <div id="firebaseui-auth-container"></div>
    <div id="loader">Loading...</div>
  </div>
</template>

<script>
import Vue from 'vue'
import DatabaseOps from '@/mixins/DatabaseOps'

export default {
  name: "Authentication",
  mounted () {
    this.loginScreen();
  },
  methods: {
    // I wanted to include this in a javascript file, but vue router cannot be called outside /src
    loginScreen (){
      // FirebaseUI config.
      var uiConfig = {
        signInOptions: [
          // Leave the lines as is for the providers you want to offer your users.
          //firebase.auth.GoogleAuthProvider.PROVIDER_ID,
          firebase.auth.EmailAuthProvider.PROVIDER_ID,
        ],    
        callbacks: {
          signInSuccessWithAuthResult: (authResult, redirectUrl) => {
            Vue.prototype.$userId = authResult.user.uid;
            if (authResult.additionalUserInfo.isNewUser){ // if new user, register to database
              this.addUser(authResult.user.displayName, authResult.user.email)
            }
            document.getElementById('userAuthentication').style.display = 'none';
            this.$router.push("/MainMenu"); // TBD: router does not work
            return false;
          },
          uiShown: () => {
            document.getElementById('loader').style.display = 'none';
          },
        },
      };
      // Initialize the FirebaseUI Widget using Firebase.
      var ui = new firebaseui.auth.AuthUI(firebase.auth());
      // The start method will wait until the DOM is loaded.
      ui.start('#firebaseui-auth-container', uiConfig);
    },    
    addUser(userName, email){
        var data = {
            'email': email,
            'name': userName
        };
        this.addUserCredentials(data);
        this.initUserPreferences();
    },
  },
  data: () => ({
    //
  }),
  mixins: [DatabaseOps]
};
</script>

src/router/index.js

新しく追加したAuthentication.vueのページの情報を追加します。
また、アクセス時には認証画面へのリダイレクトをするように設定します。

参考リンク: https://qiita.com/sin_tanaka/items/ea149a33bd9e4b388241

import Vue from "vue";
import VueRouter from "vue-router";

Vue.use(VueRouter);

const routes = [
  {
    path: "*",
    redirect: "/"
  },
  {
    path: "/",
    name: "Authentication",
    component: () =>
      import("@/views/Authentication.vue"),
  },
];

const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes,
});

router.beforeEach((to, from, next) => {
  let requiresAuth = to.matched.some(record => record.meta.requiresAuth)
  let currentUser = firebase.auth().currentUser
  if (requiresAuth) { // if this page requires auth, redirect to auth page
    if (!currentUser) {
      next({
        path: '/',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() // this is required
  }
})

export default router;

src/App.vue

Authentication.vueの設定を追加します。

<template>
  <v-app>
    <v-main>
      <Authentication />
    </v-main>
  </v-app>
</template>

<script>
//import HelloWorld from "./components/HelloWorld";
import Authentication from "./views/Authentication";

export default {
  name: "App",

  components: {
    Authentication,
  },
  data: () => ({
    //
  }),
};
</script>

Build

  • ビルドし、動作をテストします。動作のテストにはFirebase Emulatorが必要であるため、起動します。
npm run build
firebase emulators:start
  • dist/index.htmlをブラウザで閲覧し下の画像のような画面が出ることを確認します。

    • auth.PNG
  • アカウント作成実行後、AuthとTRDBに正常にアカウント登録の処理がされていることを確認します。

http://127.0.0.1:9000/?ns=[データベース名]: {
  userCredentials: {
    [Firebase AuthのUID]: {
      email: "[Email]"
      name: "[名前]"
    }
  },
  userPreferences: {
    [Firebase AuthのUID]: {
      notifyAtLinkOpen: false,
      notifyNotLostItem: true,
      whereToNotify: "email"
    }
  }
}

次回

ユーザー設定確認・変更画面

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?