Comment créer une application d’enquête Vue à l’aide de l’authentification et de la base de données Firebase – Smashing Magazine


A propos de l’auteur

David écrit actuellement du code frontal pour canaryng.com et s’efforce constamment de rendre le Web plus accessible à tous.

Les intérêts en dehors du codage incluent…
Plus à propos
David

Ce didacticiel vous guidera étape par étape pour créer une application d’enquête fonctionnelle à l’aide de Vue.js et Firebase. De la validation des données de l’utilisateur via Vuelidate à l’authentification, au stockage des données de l’utilisateur, à la protection de l’itinéraire et à l’envoi de données aux serveurs Firebase. Toutes les étapes utilisées dans le didacticiel sont pratiques et peuvent être reproduites dans n’importe quel projet réel, même avec un backend personnalisé.

Dans ce didacticiel, vous allez créer une application d’enquête, où nous apprendrons à valider les données de nos utilisateurs, à implémenter l’authentification dans Vue et à pouvoir recevoir des données d’enquête à l’aide de Vue et Firebase (une plateforme BaaS).

Au fur et à mesure que nous construisons cette application, nous apprendrons à gérer la validation des formulaires pour différents types de données, notamment en contactant le backend pour vérifier si un e-mail a déjà été pris, avant même que l’utilisateur envoie le formulaire lors de l’inscription.

De plus, l’application gérerait la connexion de l’utilisateur avec des API reposantes. Il utilisera Authguard dans le routeur Vue pour empêcher les utilisateurs non connectés d’accéder au formulaire d’enquête et envoyer avec succès les données d’enquête des utilisateurs connectés à une base de données sécurisée.

Pour que nous soyons sur la même page, clarifions ce qu’est Firebase et ce qu’elle fera dans ce didacticiel. Firebase est un ensemble d’outils pour «créer, améliorer et développer votre application», il vous donne accès à une grande partie des services que les développeurs devraient normalement construire eux-mêmes, mais ne veulent pas vraiment construire, car ils préfèrent se concentrer sur l’expérience de l’application elle-même. Cela comprend des éléments comme l’analyse, l’authentification, les bases de données, le stockage de fichiers, et la liste continue.

Ceci est différent du développement d’applications traditionnel, qui implique généralement l’écriture de logiciels frontaux et principaux. Le code frontend appelle simplement les points de terminaison API exposés par le backend, et le code backend fait réellement le travail. Cependant, avec les produits Firebase, le backend traditionnel est contourné, mettant le travail dans le client. Cela permet techniquement aux ingénieurs frontaux comme moi de créer des applications à pile complète en écrivant uniquement du code frontal.

L’essentiel est que Firebase agisse comme notre backend dans ce projet en nous fournissant les points de terminaison API nécessaires pour gérer à la fois nos besoins d’authentification et de base de données. À la fin, vous aurez créé une application d’enquête fonctionnelle à l’aide de Vue + Firebase. Après cela, vous pouvez continuer et créer n’importe quelle application Web de votre choix en utilisant ces mêmes processus, même avec un backend personnalisé.

Pour suivre, vous devez avoir installé Node et npm / yarn sur votre machine. Si vous ne l’avez pas déjà fait, suivez ces guides rapides pour installer fil ou npm sur votre machine. Vous devez également avoir une compréhension de base de Vue, Vuex et Routeur Vue syntaxe de ce didacticiel.

Les fichiers de démarrage de ce didacticiel sont corrects ici, qui contient les fichiers de base de ce projet, et voici le repo pour l’achèvement démo. Vous pouvez cloner ou télécharger les dépôts et exécuter npm install dans votre terminal.

Après avoir installé le fichier de démarrage, vous verrez une page de bienvenue, qui a les options pour vous inscrire et vous connecter. Après vous être connecté, vous pouvez alors avoir accès à l’enquête.

Architecture de l'application Survey
Cela décrit le fonctionnement de notre application d’enquête. (Grand aperçu)

N’hésitez pas à créer un nouveau projet si vous souhaitez construire ce projet entièrement par vous-même, assurez-vous simplement d’installer Vuex, Routeur Vue, Vuelidate et axios dans votre projet Vue. Alors, allons droit au but:

Tout d’abord, nous aurons besoin d’un compte Firebase pour mettre en place ce projet qui ressemble beaucoup à la création d’un conteneur pour notre application, nous donnant accès à la base de données, divers moyens d’authentification, l’hébergement, etc. Il est simple de configurer une fois que vous êtes sur le site Firebase.

Page de destination Firebase
La page de destination où vous pouvez vous inscrire et commencer votre voyage Firebase. (Grand aperçu)
Créer de nouveaux projets Firebase
Création de projets Firebase (Grand aperçu)

Maintenant que nous avons notre projet, la prochaine étape consiste à configurer notre système d’authentification et notre base de données (base de données en temps réel) sur Firebase.

  • Cliquez sur l’option «authentification»;
  • Configurez la «méthode de connexion» que nous voulons (dans ce cas, email / mot de passe).
Configuration de la méthode de connexion
Configuration de la méthode d’authentification par e-mail / mot de passe pour le projet. (Grand aperçu)
  • Cliquez sur «base de données».
  • Choisissez “Base de données en temps réel” et copiez ce lien qui se trouve juste en haut.

Ce sera très utile comme point de terminaison de l’API lorsque nous voulons envoyer les données à notre base de données Firebase.

Nous désignerons cette API comme l’API de base de données. Pour l’utiliser, vous devrez ajouter le nom de la base de données de votre choix lors de son envoi. Par exemple, pour envoyer à une base de données appelée utilisateur. Vous ajoutez simplement user.json à la fin:

{databaseAPI}/user.json
Base de données en temps réel
Utilisez l’API au-dessus de la base de données elle-même pour envoyer des données à la base de données. (Grand aperçu)

Après cela, nous irons ensuite à API de repos d’authentification Firebase documentation pour obtenir nos points de terminaison d’API d’inscription et de connexion. Au sein de ces points de terminaison, nous aurons besoin de la clé API de notre projet, qui se trouve dans les paramètres de notre projet.

Validation

De retour à notre code, il y aura une validation des données d’inscription avant leur envoi au serveur, juste pour s’assurer que l’utilisateur envoie les informations appropriées. Nous utiliserons Vuelidate qui est une bibliothèque sympa qui facilite la validation dans Vue. Tout d’abord, installez Vuelidate dans le projet:

npm i vuelidate

Aller à src/components/auth/signup.vue et dans la balise de script, importez vuelidate et tous les événements nécessaires dont nous aurons besoin de la bibliothèque, comme indiqué ci-dessous.

Remarque: Vous pouvez consulter les documents pour un aperçu complet de la bibliothèque et de tous événements disponibles.

import { required, email, numeric, minValue, minLength, sameAs } from 'vuelidate/lib/validators'

Une explication rapide:

requiredLa valeur est obligatoire
emailLa valeur doit être un e-mail
numericDoit être un nombre
minValueLa plus petite valeur numérique que l’utilisateur peut saisir.
sameAsUtilisé pour comparer entre deux valeurs pour vous assurer qu’elles sont identiques

Importer également axios pour pouvoir envoyer une requête HTTP au serveur:

import axios from 'axios'

Avant de continuer, nous devons ajouter quelques règles à la base de données pour pouvoir valider l’e-mail comme nous le devrions, comme indiqué ci-dessous:

Règles Firebase
Les règles de base de données permettent de décider que vous pouvez ou non accéder à la base de données à tout moment. (Grand aperçu)
"read" = "true"

Cela signifie que la base de données peut être lue sans aucune entrave du côté client.

"write" = "auth" !== null

Vous ne pouvez pas écrire sur la base de données sauf si vous êtes un utilisateur authentifié.

"Users" = {
  "onIndex" : ["email"]
}

Cela nous permet d’interroger le users document avec un index de email. Autrement dit, vous pouvez littéralement filtrer la base de données pour un e-mail unique.

Ajoutez ensuite une propriété calculée personnalisée avec le nom validations tout comme nous avons des méthodes, calculées, etc.

En dessous de validations nous aurons des méthodes pour valider les données nécessaires à partir de email où il est requis et doit évidemment être un e-mail. De plus, nous voulons être en mesure de dire à un utilisateur quand un e-mail a déjà été pris par quelqu’un d’autre, en vérifiant la base de données après que l’utilisateur l’a tapée à l’aide de quelque chose appelé validateurs asynchrones dans un validateur personnalisé et tout est pris en charge par vuelidate.


    validations : {
      email: {
        required,
        email,
        unique: val => {
          if (val === '') return true
          return axios.get('https://vue-journal.firebaseio.com/users.json?orderBy="email"&equalTo="' + val + '"')
            .then(res => {
              return Object.keys(res.data).length === 0
            })
        }
      }
    }

Ensuite, sous unique, interrogez la base de données à l’aide d’axios et utilisez les Object.keys par défaut pour renvoyer la réponse uniquement si sa longueur est 0.

Pour l’âge, vous ajouterez les valeurs obligatoires, numériques et une valeur minimale de 18 qui est affectée à minVal comme ses propriétés.

age: {
        required,
        numeric,
        minVal: minValue(18)
      }

Les propriétés du mot de passe sont obligatoires, avec une longueur minimale de 6 affectée à minLen.

password: {
        required,
        minLen: minLength(6)
      }

confirmPassword les propriétés doivent être essentiellement les mêmes que le mot de passe.

confirmPassword: {
        sameAs: sameAs(vm => {
          return vm.password
        })
      }

Pour informer l’utilisateur que l’e-mail a bien été pris, utilisez v-if vérifier si unique est vrai ou faux. Si la valeur est true, cela signifie que la longueur de l’objet retourné est 0, et le courrier électronique peut toujours être utilisé ainsi que vice versa.

De la même manière, vous pouvez vérifier si la saisie de l’utilisateur est un e-mail réel en utilisant v-if.

Et pour tous les divs environnants sur l’entrée individuelle, nous ajouterons une classe d’invalides qui devient active dès qu’il y a une erreur sur cette entrée.

Pour lier les événements de validation à chacune des entrées du HTML, nous utilisons $touch() comme vu avec le email au dessous de.

Please provide a valid email address.
This email address has been taken.

Age, password, et confirmPassword sera lié à leur entrée HTML de la même manière que le email.

Et nous rendrons le bouton “Soumettre” inactif en cas d’erreur dans l’une des entrées.

Voici une complète Exemple CodePen pour cette section vuelidate.

Mise en œuvre de Vuelidate
Vuelidate est utilisé ici pour déterminer le type de données envoyées à la base de données. (Grand aperçu)

Authentification

Cette application est un SPA et ne se recharge pas comme les sites traditionnels.Nous utiliserons donc Vuex, notre unique «source de vérité» pour permettre à chaque composant de notre application de connaître l’état général d’authentification. Nous allons dans notre fichier de magasin et créons la méthode de connexion / inscription dans les actions.

La réponse (token et userId) reçues lorsque nous envoyons les données des utilisateurs, vont être stockées dans notre état. Ceci est important car le jeton va être utilisé pour savoir si nous sommes toujours connectés ou non à aucun moment dans notre application.

le token, userIdet l’utilisateur sont créés dans l’état avec une valeur initiale nulle. Nous arriverons à l’utilisateur beaucoup plus tard, mais pour l’instant, nous nous concentrerons sur les deux premiers.

state: {
  idToken: null,
  userId: null,
  user: null
}

Des mutations sont ensuite créées pour changer l’état en cas de besoin.

authUserEnregistre le jeton et userId
storeUserStocke les informations utilisateur
clearAuthDataEfface les données à leur état initial
mutations: {
  authUser (state, userData) {
    state.idToken = userData.token
    state.userId = userData.userId
  },
  storeUser (state, user) {
    state.user = user
  },
  clearAuthData (state) {
    state.idToken = null
    state.userId = null
    state.user = null
  }
}

Pour l’inscription / la connexion, nous devons créer des actions individuelles pour les deux, où nous envoyons nos demandes d’authentification au serveur. Après quoi, notre réponse (token et userId) de l’inscription / connexion est validée pour authUser et enregistrée sur le stockage local.

signup ({commit, dispatch}, authData) {
      axios.post('https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=AIzaSyCFr-OMMzDGp4Mmr0t66w2cTGfNazYjptQ', {
        email: authData.email,
        password: authData.password,
        returnSecureToken: true
      })
        .then(res => {
          console.log(res)
          commit('authUser', {
            token: res.data.idToken,
            userId: res.data.localId
          })
          localStorage.setItem('token', res.data.idToken)
          localStorage.setItem('userId', res.data.localId)
          localStorage.setItem('email', res.data.email)
          dispatch('storeUser', authData)
       
          setTimeout(function () {
            router.push('/dashboard')
          }, 3000)
        })
        .catch(error => console.log(error))
    }
login ({commit}, authData) {
      axios.post('https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=AIzaSyCFr-OMMzDGp4Mmr0t66w2cTGfNazYjptQ', {
        email: authData.email,
        password: authData.password,
        returnSecureToken: true
      })
        .then(res => {
          console.log(res)
          localStorage.setItem('token', res.data.idToken)
          localStorage.setItem('userId', res.data.localId)
          localStorage.setItem('email', res.data.email)
          commit('authUser', {
            token: res.data.idToken,
            userId: res.data.localId
          })
          router.push('/dashboard')
        })
        .catch(error => console.log(error.message))
    }

Mais voici la partie délicate, ce que nous allons faire avec l’action d’inscription en particulier est d’envoyer uniquement l’e-mail et le mot de passe à enregistrer dans la base de données d’authentification. Dans le vrai sens, nous n’avons pas accès à l’utilisation des données de cette base de données d’authentification, et nous n’avons envoyé aucune de nos données d’inscription à part l’e-mail / mot de passe.

Nous allons donc créer une autre action pour envoyer les données d’inscription complètes à une autre base de données. Dans ce document de base de données distinct, nous aurons un accès complet à toutes les informations que nous choisissons d’y enregistrer. Nous appellerons cette nouvelle action appelée storeUser

Nous passons ensuite à notre action d’inscription et envoyons l’objet entier contenant nos données d’inscription à une base de données à laquelle nous avons maintenant accès via storeUser.

Remarque: Vous ne voudrez peut-être pas envoyer le mot de passe de votre utilisateur avec storeUser à la base de données pour des raisons de sécurité.

storeUser ({ state}, userData) {
      if (!state.idToken) {
        return
      }
      axios.post('https://vue-journal.firebaseio.com/users.json' + '?auth=' + state.idToken, userData)
        .then(res => console.log(res))
        .catch(error => console.log(error))
    }
  }

storeUser ajoute une requête en utilisant notre nouveau jeton et notre API de base de données lors de la publication dans la base de données.

En effet, nous ne pouvons pas écrire dans notre base de données, sauf que nous sommes authentifiés avec notre preuve (le jeton). C’est la règle que nous avons donnée à Firebase au début, vous vous souvenez?

“write” = “auth” !== null

Le code complet pour les actions d’inscription / de connexion est correct ici.

Envoyez ensuite à la fois l’inscription et la connexion à partir de leurs composants dans le onSubmit méthode aux actions respectives dans le magasin.

methods : { 
  onSubmit () {
    const signupData = {
      email : this.email,
      name : this.name,
      age : this.age,
      password : this.password,
      confirmPassword : this.co
      nfirmPassword
    }
    this.$store.dispatch('signup', signupData)
    }
  }
}

Remarque: signupData contient les données du formulaire.

methods : {
  onSubmit = {
    const formData = {
      email : this.email,
      password : this.password
    }
    this.$store.dispatch('login', {email: formData.email, password: formData.password})
  }
}

AuthGuard

AuthGuard doit empêcher les utilisateurs non connectés d’accéder au tableau de bord où ils enverront l’enquête.

Accédez au fichier d’itinéraire et importez notre magasin.

import store from './store'

Dans l’itinéraire, accédez au chemin du tableau de bord et ajoutez ce qui suit:

const routes = [
  { path: '/', component: WelcomePage },
  { path: '/signup', component: SignupPage },
  { path: '/signin', component: SigninPage },
  {
    path: '/dashboard',
    component: DashboardPage,
    beforeEnter (to, from, next) {
      if (store.state.idToken) {
        next()
      } else {
        next('/signin')
      }
    }
  }
]

Tout cela ne fait que vérifier s’il y a un jeton dans l’état, si oui, nous donnons accès au tableau de bord et vice versa.

Se déconnecter

Pour créer notre option de déconnexion, nous utiliserons clearAuth que nous avons créé plus tôt sous mutations qui définit à la fois le token et userId à null.

Nous créons maintenant un nouveau logout action , qui s’engage à clearAuth, supprimez le stockage local et ajoutez router.replace('/') pour rediriger complètement l’utilisateur.

actions: {
  logout ({commit}) {
    commit('clearAuth')
    localStorage.removeItem('token')
    localStorage.removeItem('userId')
    router.replace('/')
  }
 }

Dans le composant d’en-tête, nous avons un onLogout qui envoie notre action de déconnexion dans le magasin.

methods: {
      onLogout() {
        this.$store.dispatch('logout')
      }
    }

On ajoute ensuite un @click au bouton qui déclenche le onLogout méthode comme nous pouvons le voir ici.

    Log Out

UI_State

Maintenant que nous avons accordé un accès conditionnel au tableau de bord, l’étape suivante consiste à le supprimer de la barre de navigation, afin que seuls les utilisateurs authentifiés puissent le voir. Pour ce faire, nous ajouterions une nouvelle méthode sous le getters appelé ifAuthenticated qui vérifie si le jeton dans notre état est nul. Lorsqu’il y a un jeton, cela montre que l’utilisateur est authentifié et nous voulons qu’il voit l’option du tableau de bord de l’enquête sur la barre de navigation.

getters: {
  isAuthenticated (state) {
    return state.idToken !== null
  }
}

Après quoi, vous revenez au composant d’en-tête et créez une méthode auth sous calculé, qui envoie à notre isAuthenticated dans le getters nous venons de créer dans la boutique. Ce que cela fait, c’est que isAuthenticated retournerait faux s’il n’y avait pas de jeton, ce qui signifie auth serait également nul et vice versa.

computed: {
      auth () {
        return this.$store.getters.ifAuthenticated
      }
    }

Après cela, nous ajoutons un v-if à notre HTML pour vérifier si auth est nul ou non, déterminant si cette option apparaîtra sur la barre de navigation.

  • Dashboard
  • Register
  • Log In
    • Vous trouverez le code complet de la section État de l’interface utilisateur ici.
    État de l'interface utilisateur
    Il y a un changement dans l’en-tête en fonction du statut d’authentification de l’utilisateur. (Grand aperçu)

    Connexion automatique

    Lorsque nous rechargeons notre application, nous perdons les données et nous sommes déconnectés, nous devons tout recommencer. En effet, notre jeton et notre identifiant sont stockés dans Vuex, qui est javascript, et cela signifie que notre application est rechargée avec le navigateur lorsqu’elle est actualisée.

    Et enfin, ce que nous allons faire, c’est récupérer le jeton dans notre stockage local. Ce faisant, nous pouvons avoir le jeton de l’utilisateur sur le navigateur, quel que soit le moment où nous actualisons la fenêtre, et avoir une méthode de connexion automatique à notre utilisateur dans la mesure où le jeton est toujours valide.

    Un nouveau actions méthode appelée AutoLogin est créé, où nous obtiendrons le jeton et userId à partir du stockage local, et de valider nos données sur le authUser méthode dans les mutations.

    actions : {
      AutoLogin ({commit}) {
          const token = localStorage.getItem('token')
          if (!token) {
            return
          }
          const userId = localStorage.getItem('userId')
          const token = localStorage.getItem('token')
          commit('authUser', {
            idToken: token,
            userId: userId
          })
      }
    }

    Nous allons ensuite sur notre App.vue et écrivons un created méthode, qui enverra le autoLogin de notre boutique à chaque fois que l’application est chargée.

    created () {
        this.$store.dispatch('AutoLogin')
      }

    Fetch_User_Data

    Nous souhaitons la bienvenue à l’utilisateur sur le tableau de bord en affichant son nom. Et donc, une autre action appelée fetchUser est créé qui vérifie d’abord s’il y a un jeton comme d’habitude. Ensuite, il obtient le courrier électronique du stockage local et interroge la base de données comme cela a été fait précédemment avec la validation du courrier électronique.

    Cela renvoie un objet contenant les données de l’utilisateur initialement soumises lors de l’inscription. Nous convertissons ensuite cet objet en tableau et le validons dans le storeUser mutation initialement créée.

    fetchUser ({ commit, state}) {
      if (!state.idToken) {
        return
      }
      const email = localStorage.getItem('email')
      axios.get('https://vue-journal.firebaseio.com/users.json?orderBy="email"&equalTo="' + email + '"')
        .then(res => {
          console.log(res)
        
         // const users = [] 
          console.log(res.data)
          const data = res.data
          const users = []
          for (let key in data) {
            const user = data[key]
            user.id = key
            users.push(user)
            console.log(users)
          }
         commit('storeUser', users[0])
        })
        .catch(error => console.log(error))
    }

    Après quoi, nous créons un autre getter appelé user qui renvoie le state.user déjà engagé par storeUser.

    getters: {
      user (state) {
        return state.user
      },
      isAuthenticated (state) {
        return state.idToken !== null
      }
    }

    De retour au tableau de bord, nous créons une nouvelle méthode calculée appelée name qui revient state.user.name uniquement si l’utilisateur existe.

    computed: {
      name () {
          return !this.$store.getters.user ? false : this.$store.getters.user.name
        }
      },
      created () {
        this.$store.dispatch('fetchUser')
      }
    }

    Et nous ajouterons également le created propriété calculée pour envoyer le fetchUser une fois la page chargée. Nous utilisons ensuite le v-if dans notre HTML afin d’afficher le nom s’il existe.

     

    Welcome, {{ name }}

    Send_Survey

    Pour envoyer l’enquête, nous allons créer un postData action qui envoie les données à la base de données à l’aide de l’API de base de données, avec le jeton pour indiquer au serveur que l’utilisateur est connecté.

    postData ({state}, surveyData) {
      if (!state.idToken) {
        return
      }
      axios.post('https://vue-journal.firebaseio.com/survey.json' + '?auth=' + state.idToken , surveyData)
        .then(res => {
         console.log(res)
        })
        .catch(error => console.log(error))
    }

    Nous revenons au composant du tableau de bord et envoyons les données à notre postData action dans le magasin.

    methods : {
      onSubmit () {
        const postData = {
          price: this.price,
          long: this.long,
          comment: this.comment
        }
        console.log(postData)
        this.$store.dispatch('postData', postData)
      }
    }

    Voilà, nous avons de nombreuses fonctionnalités utiles implémentées dans notre application de démonstration lors de la communication avec notre serveur Firebase. J’espère que vous utiliserez ces fonctionnalités puissantes dans votre prochain projet, car elles sont très importantes pour la création d’applications Web modernes aujourd’hui.

    Si vous avez des questions, vous pouvez les laisser dans la section commentaires et je serai heureux de répondre à chacune d’elles!

    • La démo du tutoriel est en direct ici.
    Application d'enquête Vue
    L’application d’enquête terminée (Grand aperçu)

    D’autres ressources qui peuvent s’avérer utiles comprennent:

    • Pour en savoir plus sur Firebase et les autres services qu’elle propose, consultez l’article de Chris Esplin, “Qu’est-ce que Firebase?
    • Vuelidate est une bibliothèque vraiment sympa dans laquelle vous devriez vraiment creuser. Vous devriez lire sa documentation pour avoir un aperçu complet.https://vuelidate.js.org/.
    • Vous pouvez également explorer axios seul, surtout si vous souhaitez l’utiliser dans des projets plus importants.
    Smashing Editorial
    (ra, yk, il)
    Close Menu