sábado, 30 de abril de 2022

Firebase Authentication vía Vuex con Vue js SDK 9



En esta entrada del blog vamos a crear un sistema de Autenticación, con Firebase SDK 9 , Vuejs y Vuex. 

Este flujo de trabajo usa npm y requiere agrupadores de módulos o herramientas del framework de JavaScript, porque la v9 del SDK está optimizada para funcionar con agrupadores de módulos a fin de eliminar el código que no se usa (eliminación de código no utilizado) y reducir el tamaño del SDK.

En una entrada anterior , explicamos el proceso para crear un nuevo proyecto Vue con Vue CLI. seguiremos los pasos indicados añadiendo al proyecto tanto Router como Vuex.

Una vez tenemos instalado el proyecto con router, vuex:

1.- npm i firebase

Creo en la raíz del proyecto un archivo index.js

 

Figura 1. Archivo de configuración de Firebase en la raíz del proyecto.


En el index.js de firebase pego la configuración de mi firebase. NOTA ya he importado algunos módulos, por ahora sólo usaremos getAuth el resto los dejo comentados y estamos usando el SDK 9:

// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
//import { getFirestore } from "firebase/firestore"
//import { getStorage } from "firebase/storage";
 
// https://firebase.google.com/docs/web/setup#available-libraries
 
// Your web app's Firebase configuration
const firebaseConfig = {
  apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  authDomain: "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  projectId: "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
  storageBucket: "xxxxxxxxxxxxxxxxxxxxxxx",
  messagingSenderId: "xxxxxxxxxxxxxxxxxxx",
  appId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
};
 
// Initialize Firebase
const app = initializeApp(firebaseConfig);
 
//Exportando las funciones que tengo inportadas de firebase
const auth = getAuth(app)
export { auth }
 
//const db = getFirestore(app);
//export { db }
 
//const storage = getStorage(app);
//export { storage}

Configurando nuestro Store de Vuex

Vuex es la librería de gestión de estados para Vue. js por excelencia, de hecho Vuex es referenciada desde la la documentación de Vue. js como el gestor de estados oficial. Esto quiere decir que está totalmente soportado por todas las las versiones de Vue.

Ya explicamos qué es Vuex en una entrada anterior, en esta entrada vamos a aplicarlo a un caso real, que es el manejo de estados para la la autenticación de usuarios. Al hacer nuestra instalación del proyecto con Vue CLI, se ha creado por defecto una carpeta Store en la raíz del proyecto, que contiene un archivo index.js, vamos a abrir el archivo:

Figura 2. Archivo index.js del Store Vuex

Al abrirlo encontraremos el siguiente código por defecto:

import { createStore } from 'vuex'
 
export default createStore({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

Vamos a cambiar la forma de nuestro Store para poder exportarlo de forma global y que esté disponible en toda la App, para ello hacemos los siguientes cambios:

//import { createStore } from 'vuex'
import Vuex from "vuex"

const store = new Vuex.Store({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
 }
})
export default store;

Dividiendo el Store de Vuex en módulos

podríamos trabajar directamente en el index.js del store,  pero una buena práctica es separar en  "módulos" independientes  que luego importaremos en el index, por ejemplo en este caso yo voy a crear un módulo en mi store que se encargará exclusivamente del estado de autenticación de los usuarios.

Voy a crear ese módulo del store que llamaré user.js, para ello en la carpeta Store, creo mi nuevo archivo user.js:

Figura 3. Archivo user.js "módulo" del store de Vuex

Abriremos nuestro nuevo archivo y crearemos un "esqueleto" básico, donde tendremos una pieza de estado principal, que podemos llamar user e inicializamos a null.

luego creramos nuestros getters, mutations y actions como constantes que dejaremos vacías por el momento, solo nos queda exportarlas por defecto indicando que queremos namespaced.

const state = {
    user: null,
}
const getters = {}
const mutations = {}
const actions = {}
export default {
    namespaced: true,
    state,
    getters,
    actions,
    mutations
}

¿Que es eso de namespaced: true?

cunado tenemos una aplicación muy grande ( o que creemos que escalará ) solemos, como en este caso dividir el Store en módulo, lo que básicamente significa que estamos dividiendo el estado en trozos más pequeños, esto tiene el inconveniente de que no podemos usar un mismo nombre de método en distintos módulos ya que éstos están integrados en el mismo estado. Para solucionar esto, tenemos la opción de definir el módulo como namespaced, lo que nos permite usar el mismo método en diferentes módulos.

Hay que tener en cuenta que esto puede complicar un poco las cosas si usamos mapGetters o mapActions ya que los getters ahora están en la forma ['modulo /  cliente'], esto lo veremos más adelante.

Ahora que ya hemos creado nuestro primer módulo debemos integrarlo en nuestro Store, para lograrlo tenemos que importar nuestro módulo user.js en el index.js añadiendo lo siguiente:

//import { createStore } from 'vuex'
import Vuex from "vuex"
import user from "./user"  //Importo el módulo user.js
const store = new Vuex.Store({
  state: {
  },
  mutations: {
  },
  actions: {

  },
  modules: {
    user                   //Declaro el módulo user.js
})
export default store;

En este punto ya tenemos configurado nuestro store de Vuex para empezar a usarlo en  nuestra App. Creemos ahora una nueva vista donde tendremos nuestros formularios de Login y Register y una cabecera "Header" para nuestro proyecto.

Creando la cabecera del proyecto

En este apartado crearemos la barra de navegación del proyecto, es una pieza muy importante porque va a gestionar el acceso a todas las secciones de la aplicación, así como diferentes botones que mostrarán distintas opciones dependiendo del estado de autenticación del usuario.

Para crear la barra de navegación usaré el componente navbar de bulma. Como bulma no incorpora nada de JavaScript debo crear la funcionalidad para colapsar y descolapsar.

<template>
<nav class="navbar" role="navigation" aria-label="main navigation">
  <div class="navbar-brand">
    <a class="navbar-item" href="https://bulma.io">
      <img class="navbar__logo" src="../assets/img/MitTalk.png" alt="">
    </a>
    <a role="button"
    class="navbar-burger"
    aria-label="menu"
    aria-expanded="false"
    data-target="navbarBasicExample">
      <span aria-hidden="true"></span>
      <span aria-hidden="true"></span>
      <span aria-hidden="true"></span>
    </a>
  </div>
  <div id="navbarBasicExample" class="navbar-menu">
    <div class="navbar-start">
      <router-link class="navbar-item" to="/">Home</router-link>
      <router-link class="navbar-item" to="/">Some View</router-link>
    </div>
    <div class="navbar-end">
      <div class="navbar-item">
        <div class="buttons">
          <a class="button is-primary">
            <strong>Sign up</strong>
          </a>
          <a class="button is-light">
            Log in
          </a>
        </div>
      </div>
    </div>
  </div>
</nav>
</template>
<script>
export default {
  name: "NavBarComponent"
}
</script>
<style lang="scss" scoped>
.navbar-item img {
    max-height: none;
}
.navbar__logo {
    width: 200px;
    height: auto;
}
</style>

Hemos usado sccs y bulma, el ejemplo de la documentación basic navbar. Modificando algunos enlaces con router-link. Una vez todo listo solo nos queda instanciarlo dentro de Home.vue:


<template>
<NavBarComponent />   // 3 Instanciamos el componente
</template>
<script>
 // 1 Importamos el componente
import NavBarComponent from '@/components/NavBarComponent.vue'
export default {
  name: 'Home',
  components: {
   NavBarComponent     // 2 Registramos el componente
  }
}
</script>

Trabajando el menú de hamburguesa

Dentro del template del componente NavBarComponent.vue que acabamos de crear con bulma introduciomos unas referencias tanto al menú de hamburguesa con al nav, para capturarlas:

    <a
     role="button"
     class="navbar-burger"
     aria-label="menu"
     aria-expanded="false"
     ref="burger"
     >
      <span aria-hidden="true"></span>
      <span aria-hidden="true"></span>
      <span aria-hidden="true"></span>
    </a>
  </div>
  <div id="navbarBasicExample" class="navbar-menu" ref="navBar">
    <div class="navbar-start">
      <router-link class="navbar-item" to="/">Home</router-link>
    </div>


Ahora que las tenemos creadas, las capturamos dentro de la instancia del componente, creando un Mounted y un data, lo que estamos haciendo es iniciar en data las propiedades Burger y navBar a null y cuando se monta el componente, las igualamos a las referencias que acabamos de crear, que están capturando la barra de navegación y el menú de hamburguesa:


<script>
export default {
  name: "NavBarComponent",
  mounted(){
    this.burger = this.$refs.burger
    this.navBar = this.$refs.navBar
  },
  data() {
    return {
      burger: null,
      navBar: null
    }
  }
}
</script>

Lo que quiero hacer es conmutar una clase de bulma llamada is-active cada vez que haga click en el menú de hamburguesa, esto lo logramos creando un método que llamaremos toggleNavbar

  methods: {
    toggleNavBar() {
      this.burger.classList.toggle("is-active")
      this.navBar.classList.toggle("is-active")
    }

Con el Api del DOM classList hacemos activo el toggle en los dos, debemos ahora añadir la llamada al método, cuando se haga clic en el botón de hamburguesa, le añadimreos un prevent para prevenir la acción por defecto:

    <a
    @click.prevent="toggleNavBar"
     role="button"
     class="navbar-burger"
     aria-label="menu"
     aria-expanded="false"
     ref="burger"
     >

Ahora si hacemos clic en el botón de hamburguesa el nav y el botón de hamburguesa se abre y se cierra:

Figura 4. Navegación en la cabecera 


Creando la vista AuthView.vue 

Vamos a crear la vista Auth.vue que perimitirá al usuario registrarse en caso de que ya se haya registrado, más adelante conectaremos los métodos que vamos a crear en esta vista con nuestro almacén de estado Vuex que ya tenemos configurado, en el módulo user.

Vamos a la carpeta Views y creamos el archivo AuthView.vue, allí hacemos:

<template>
 
</template>
<script>
export default {
  name: "AuthView"
}
</script>


En el template usando Bulma trabajaremos con formularios, columnas y botones. Empezaremos con un article con la clase section (bulma):

<template>
  <arcticle class="section">
      <div class="container">
         
      </div>
  </arcticle>
</template>
<script>
export default {
  name: "AuthView"
}
</script>

Vamos a trabajar las columnas, container es el ancho total, pero queremos dividirlo en una sola columna centrada, trabajaremos con columns, bulma está basado en grid css y dispone de 12 columnas, esta podría ser la estructura básica:

<template>
  <arcticle class="section">
      <div class="container">
        <div class="columns">
            <div class="column is-half is-offset-one-quarter">
                <h1 class="title has-text-centered">Login</h1>
                <!--Login Form-->
               
                <!--End of Login Form-->
            </div>
        </div>  
      </div>
  </arcticle>
</template>
<script>
export default {
  name: "AuthView"
}
</script>

Vamos ahora a crear el formulario de login

<template>
  <arcticle class="section">
      <div class="container">
        <div class="columns">
            <div class="column is-half is-offset-one-quarter">
                <h1 class="title has-text-centered">Login</h1>
                <!--Login Form-->
                <form>
                    <div class="field">
                    <label class="label">Email</label>
                    <div class="control">
                    <input
                    v-model="userData.email"
                    class="input"
                    type="email"
                    placeholder="e.g alexsmith@gmail.com"
                    required
                     />
                    </div>
                    </div>
                    <div class="field">
                    <label class="label">Password</label>
                    <div class="control">
                    <input
                    v-model="userData.password"
                    class="input"
                    type="password"
                    required
                     />
                    </div>
                    </div>
                    <div class="field has-text-right">
                    <div class="control">
                    <button
                    type="submit"
                    class="button is-link"
                    :class="{ 'is-loading': isLoading}"
                    >
                    Login
                    </button>
                    </div>
                    </div>                    
                </form>
                <!--End of Login Form-->
            </div>
        </div>  
      </div>
  </arcticle>
</template>
<script>
export default {
  name: "AuthView"
}
</script>

Remarcado en azul, estoy añadiendo dinámicamente una clase de bulma que incorpora un spining en la carga. Una vez creado nuestro template, es hora de crear las propiedades del modelo local (remarcadas en verde) y otras:

<script>
export default {
  name: "AuthView",
  data(){
      return {
          isLogin: true,
          isLoading: false,
          userData:{
              name: "",
              email: "",
              password: ""
          }
      }
  }
}
</script>

Por ultimo vamos a crear los métodos locales que de momento dejaremos vacíos, pero que vasmos a conectar con Vuex

<script>
export default {
  name: "AuthView",
  data(){
      return {
          isLogin: true,
          isLoading: false,
          userData:{
              name: "",
              email: "",
              password: ""
          }
      }
  },
  methods: {
      doRegister() {},
      doLogin() {}
  }
}
</script>

Asociamos el form con el método que acabamos de crear, en su declaración le añadimos:

                <!--Login Form-->
                <form @submit.prevent="doLogin">


Ahora vamos a añadir justo donde termina el form de login un form de register, podemos copiar el form de login y modificar lo que sea necesario:

                <!--Register Form-->
                <form @submit.prevent="doRegister">
                    <div class="field">
                    <label class="label">Name</label>
                    <div class="control">
                    <input
                    v-model="userData.name"
                    class="input"
                    type="text"
                    placeholder="e.g Alex Smith"
                    required
                     />                                    
            </div>
        </div>
                    <div class="field">
                    <label class="label">Email</label>
                    <div class="control">
                    <input
                    v-model="userData.email"
                    class="input"
                    type="email"
                    placeholder="e.g alexsmith@gmail.com"
                    required
                     />
                    </div>
                    </div>
                    <div class="field">
                    <label class="label">Password</label>
                    <div class="control">
                    <input
                    v-model="userData.password"
                    class="input"
                    type="password"
                    required
                     />
                    </div>
                    </div>
                    <div class="field has-text-right">
                    <div class="control">
                    <button
                    type="submit"
                    class="button is-link"
                    :class="{ 'is-loading': isLoading}"
                    >
                    Login
                    </button>
                    </div>
                    </div>
                    <!--Fin del Register Form-->    


El form es igual que en anterior en cuanto a e-mail y password, ambos apuntan a email y password del data mediante v-model, hemos añadido el name que apunta a name del data y hemos vinculado el form al método local doRegister.

Ahora tenemos visibles los dos formularios, pero nosotros necesitamos que sólo sea visible uno en función de si el usuario esta logeado o no, para ello podemos usar la directiva v-if v-else, preguntando por la propiedad isLogin, si isLogin es true (que será true por defector) queremos ver el formulario de Login y si es false veremos el de register.

Añado los enlaces para hacer login o registrase en sus correspondientes formularios, estos enlaces afectarán a la propiedad isLogin que será true o false en función de lo que el usuario quiera hacer (en azul).

También debemos envolver los formularios en un template para hacer uso de las directivas v-if v-else para mostrar uno u otro formulario (en verde)

                <!--Login Form-->
                <template v-if="isLogin">
                <h1 class="title has-text-centered">Login</h1>  
                <form @submit.prevent="doLogin">
                    <div class="field">
                    <label class="label">Email</label>
                    <div class="control">
                    <input
                    v-model="userData.email"
                    class="input"
                    type="email"
                    placeholder="e.g alexsmith@gmail.com"
                    required
                     />
                    </div>
                    </div>
                    <div class="field">
                    <label class="label">Password</label>
                    <div class="control">
                    <input
                    v-model="userData.password"
                    class="input"
                    type="password"
                    required
                     />
                    </div>
                    </div>
                    <div class="field has-text-right">
                    <div class="control">
                    <button
                    type="submit"
                    class="button is-link"
                    :class="{ 'is-loading': isLoading}"
                    >
                    Login
                    </button>
                    </div>
                    </div>
                    <a @click="isLogin = false">Don´t have an account?</a>                  
                </form>
                </template>
                <!--End of Login Form-->
                <!--Register Form-->
                <template v-else>
                <h1 class="title has-text-centered">Register</h1>  
                <form @submit.prevent="doRegister">
                    <div class="field">
                    <label class="label">Name</label>
                    <div class="control">
                    <input
                    v-model="userData.name"
                    class="input"
                    type="text"
                    placeholder="e.g Alex Smith"
                    required
                     />                                    
            </div>
        </div>
                    <div class="field">
                    <label class="label">Email</label>
                    <div class="control">
                    <input
                    v-model="userData.email"
                    class="input"
                    type="email"
                    placeholder="e.g alexsmith@gmail.com"
                    required
                     />
                    </div>
                    </div>
                    <div class="field">
                    <label class="label">Password</label>
                    <div class="control">
                    <input
                    v-model="userData.password"
                    class="input"
                    type="password"
                    required
                     />
                    </div>
                    </div>
                    <div class="field has-text-right">
                    <div class="control">
                    <button
                    type="submit"
                    class="button is-link"
                    :class="{ 'is-loading': isLoading}"
                    >
                    Register
                    </button>
                    </div>
                    </div>
                    <a @click="isLogin = true">Want to login?</a>
                </form>
                </template>
                    <!--Fin del Register Form-->   

Salvamos y vamos a verlo en el navegador para comprobar si tenemos algún error, para ello vamos a nuestro enrutador. Routerindex.js y añadimos la ruta a nuestro componente AuthView.vue:

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'
import AuthView from '../views/AuthView.vue'
const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/auth',
    name: "auth",
    component: AuthView
  }
]
const router = createRouter({
  history: createWebHashHistory(),
  routes
})
export default router


Ahora si vamos a la ruta recien creada veremos nuestros formularios funcionando:

Figura 5. Vista Login

Figura 6. Vista Register


Auth con correo y contraseña (vía Vuex)


Si aún no lohas hecho recuerda ir a la consola de Firebase de tu proyecto y en la pestaña de Authentication, activar el método correo y contraseña:

Figura 7. Sign-in method (activación en la consola de Firebase)


Creo los métodos locales en AuthView.vue

Voy a mi vista AuthView y creo los dos métodos que de momento dejo vacíos:


methods: {
/*Metodos locales que conectan con Store vuex*/
    doRegister() {},
    doLogin() {}    
  }

 creando las mutaciones en el módulo user.js del store vuex:

Nos situamos ahora en el módulo user.js,  crearemos una mutación setUser que será la encargada de modificar el estado de user.

La mutación recibe por parámetro el estado y el usuario, y le pasaremos nulo cuando queramos hacer logout y le pasaremos el objeto usuario que venga de Firebase authentication cuando hayamos conseguido conectar. Ya sea registrando o haciendo login ya que al registrar lleva implícito un login.


const mutations = {
    setUser(state, user) {
        state.user = user
    }
}


Creando las acciones en el módulo user.js que acometerán la mutación

Lo primero es importar en el módulo user.js de vuex el auth que exporto desde firebase y como estamos trabajando con la versión 9 del SDK de firebase, tenemos que importar algunos métodos que necesitaremos. Esta es la nueva forma en que se trabaja con la versión 9 que nos permite importar los servicios de Firebase que necesitemos de forma modular en vez de importar todos de una vez, esto mejora sustancialmente el "bounce" de nuestra app.

import { auth } from "../firebase.js"
import {   //Servicios Firebase auth
    SignInWithEmailAndPassword,
    signInWithEmailAndPassword,
    signOut } from 'firebase/auth'

const state = {
    user: null,
}

const getters = {}

const mutations = {
    setUser(state, user) {
        state.user = user
    }
}
const actions = {}

export default {
    namespaced: true,
    state,
    getters,
    actions,
    mutations
}

Ahora si creo las acciones para acometer la mutación a user:

Con el SDK9 cuando se usan los métodos signInWithEmailAndPassword, createUserWithEmailAndPassword o signOut, hay que pasarle auth antes del payload:

Acciones doLogin y doLogout:

Para las acciones necesitaremos importar algunos métodos de auth al modulo user.js:


import { auth } from "../firebase.js"
import {
    createUserWithEmailAndPassword,
    signInWithEmailAndPassword,
    signOut
 } from 'firebase/auth'

const actions = {
    async doLogin({ commit }, {email, password}) {
        await signInWithEmailAndPassword(auth, email, password)
        commit("setUser", auth.currentUser)
    },
    async doLogout({ commit }) {
        await (auth)
        commit("setUser", null)
    }
     
}


La acción doRegister:

En la acción doRegister, introducimos el nombre de usuario, vamos a usar le método updateProfile, que nos permite cambiar algunas propiedades del usuario actual, estas propiedades como el nombre o la foto, las almacenaremos mas adelante en le cloud firestore, de momento solo añadiremos el nombre a la propiedad displayName, mediante el método updateProfile:

Para opder hacerlo necesitamos importar el método updateProfile, aquí en user.js vamos a las importaciones y hacemos y añadimos:


import { auth } from "../firebase.js"
import {
    createUserWithEmailAndPassword,
    signInWithEmailAndPassword,
    updateProfile,
    signOut
 } from 'firebase/auth'

Una vez importado el método, creamos el usuario con el mail y el password como payload añadiendo la autentificación y usamos el método updateProfile de forma asíncrona para modificar la propiedad displayName del usuario, añadiéndole el nombre que el usuario ha introducido (que viene desde el método local)


    async doRegister({ commit }, { name,email, password}) {
        await createUserWithEmailAndPassword(auth, email, password)
        await updateProfile( auth.currentUser, {
            displayName: name
        })    
        commit("setUser", auth.currentUser)
    },

 Completar métodos locales para conectar con las acciones

Teniendo listas las acciones del módulo Vuex vamos a completar los métodos locales para que conecten con las acciones, vamos a AuthView.vue:

doLogin:

este método se dispara cuando le damos clic al submit del formulario de login. Es un método asíncrono le vamos a pasar un try catch, el catch para la captura de eventuales errores, en el try con un await accedermos al store* y hacemos el dispatch de la acción, como estamos usando namespacing le pasamos el nombre del módulo user y el nombre de la acción doLogin (mismo nombre en método local que en acción es una muy buena práctica), y esta acción está esperando un email y una contraseña que le pasamos con this (lo que se ha introducido en el form):


     //Método doLogin__________________________________
      async doLogin() {
         this.isLoading = true //Para el spiner en el botón
         try {
             await this.$store.dispatch('user/doLogin', {
                 email: this.userData.email,
                 password: this.userData.password
             })
             this.resetData()
             this.reDirect()
         } catch(error){
             console.error(error.message)
         } finally {
             this.isLoading = false
         }
      },


doRegister:

El método doRegister , incorpora también el nombre de usuario, que pasaremos en el payload a la acción en vuex y añadiremos a las propiedades de usuario usando el método updateProfile, pero la forma de hacer esto es distinta cuando usamos el SDK 9 veamos cómo hacerlo:

En el await le pasamos a la acción doRegister de vuex los datos del form que incluye el name:

      async doRegister() {
         this.isLoading = true //Para el spiner en el botón
         try {
             await this.$store.dispatch("user/doRegister", {
                 name: this.userData.name,
                 email: this.userData.email,
                 password: this.userData.password
             })
             this.resetData()
             this.reDirect()
         } catch(error){
             console.log(error.message)
         } finally {
             this.isLoading = false
         }
      },


Cambiando los botones del NavBar si hay user

En nuestra vista NavBAr, estamos mapeando el estado de la pieza user, gracias a la propiedad computada mapState:

  computed: {
    ...mapState("user", ["user"])
  }  
}


Recuerda que para poder acceder a esta información sobre el estado hemos tenido que importar mapState

import { mapState } from "vuex"


Con esto podemos saber si hay un usuario conectado o no y vamos a usar esto para mostrar los botones de SingUp y LogOut en función de si hay alguien conectado o no.

Quermos que se muestre el logout sólo si hay alguien conectado: para ello mediante un template y la directiva v-if envolvemos el loguot con la condición “muéstrate si hay usuario”:

      <div class="navbar-item">
        <div class="buttons">
          <template v-if="user">
          <router-link class="button is-primary" :to="{ name: 'profile' }">
            <strong>Profile</strong>
          </router-link>
          <a @click="doLogout" class="button is-light">
            Log out
          </a>
          </template>
        </div>
      </div>


Del mismo modo queremos que el signup sólo se muestre si no hay nadie autenticado así que añadimos:


        <template v-if="!user">        
          <router-link to="auth">
          <a class="button is-dark">
            <strong>Sign up</strong>
          </a>
          </router-link>
          </template>
           <template v-if="user">          
          <a @click="doLogout"  class="button is-light">
            Log out
          </a>
          </template>

Listo, ahora tenemos nuestra atutentificación con Firebase lista. mediante Firebase y Vuex modular. Podremos crear una cuenta con el Register y hacer Login y Logout.

No hay comentarios:

Publicar un comentario