Fermer

mai 8, 2020

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


À 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 mis à part le codage incluent…
En savoir plus
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 nos utilisateurs forment des données, implémentent l'authentification dans Vue et peuvent recevoir des données d'enquête à l'aide de Vue et Firebase (une plate-forme BaaS).

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 enverra avec succès les données d'enquête des utilisateurs connectés à une base de données sécurisée.

Juste pour que nous soyons sur la même page, clarifions ce qu'est Firebase et ce qu'il fera dans ce tutoriel. 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 inclut 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 backend. Le code frontend appelle simplement les points de terminaison API exposés par le backend, et le code backend fait 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 complètes empilant 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 le fil ou npm sur votre machine. Vous devez également avoir une compréhension de base de Vue, Vuex et Syntaxe du routeur Vue pour 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 la démo terminée . 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. une fois connecté, vous pouvez alors accéder à l'enquête.

 Architecture de l'application d'enquête
Ceci 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 créer 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-y:

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. . La configuration est simple 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 parcours 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 appellerons cette API l'API de la 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. ( Large preview )

Après cela, nous irons à la documentation Firebase auth rest API pour nous inscrire et nous connecter aux points de terminaison de l'API. Dans 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 d'être envoyées à le 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 

Accédez à src / components / auth / signup.vue et dans la balise de script importez vuelidate et tous les événements nécessaires que nous 'll aura besoin de la bibliothèque comme vu ci-dessous.

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

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

Une explication rapide:

required La valeur est obligatoire
email La valeur doit être un e-mail
numérique Doit être un nombre
minValue La plus petite valeur numérique que l'utilisateur peut entrer.
sameAs Utilisé pour comparer entre deux valeurs pour s'assurer qu'elles sont identiques [19659052] Importez également axios pour pouvoir envoyer une requête HTTP au serveur:
 importez axios depuis 'axios' 

Avant de continuez, nous devons ajouter des 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 la base de données vous aident à décider si 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 document des utilisateurs avec un index de e-mail . 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.

Sous validations nous aurons des méthodes pour valider les données nécessaires à partir de e-mail où cela est requis et doit évidemment être un e-mail. En outre, nous voulons être en mesure de dire à un utilisateur lorsqu'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 cela est pris en charge par vuelidate.


     validations: {
      email: {
        obligatoire,
        email,
        unique: val => {
          if (val === '') return true
          retour 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 min. sur 18 affectées à minVal comme propriétés.

 âge: {
        obligatoire,
        numérique,
        minVal: minValue (18)
      } 

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

 mot de passe: {
        obligatoire,
        minLen: minLength (6)
      } 

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

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

Pour indiquer à l'utilisateur que l'e-mail est pris, utilisez v-if pour vérifier si unique est vrai ou faux. Si la valeur est true, cela signifie que la longueur de l'objet renvoyé est 0 et que le courrier électronique peut toujours être utilisé ainsi que vice versa.

De la même manière, vous pouvez vérifier si l'entrée utilisateur est un courrier électronique réel en utilisant v -si .

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

Pour lier les événements de validation à chacun des en HTML, nous utilisons $ touch () comme on le voit avec le courriel ci-dessous.

Veuillez fournir une adresse courriel valide.
Cette adresse courriel a été prise.

Âge mot de passe et confirmPassword seront liés à leur entrée HTML de la même manière que l'e-mail .

Et nous rendrons le bouton «Soumettre» inactif s'il y a une erreur dans l'une des entrées.

  

Voici un exemple complet CodePen pour cette section vuelidate.

 Implémentation 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, donc nous utiliserons Vuex, comme notre "source de vérité" unique pour permettre à chaque composant de notre application pour connaître l'état général d'authentification. Nous accédons à notre fichier de magasin et créons la méthode de connexion / inscription dans les actions.

La réponse ( jeton et userId ) reçue lorsque nous envoyons les données des utilisateurs , vont être stockés 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 jeton userId et les utilisateurs sont créés dans l'état avec une valeur initiale nulle. Nous parviendrons à l'utilisateur beaucoup plus tard, mais pour l'instant, nous nous concentrerons sur les deux premiers.

 déclare: {
  idToken: null,
  userId: null,
  utilisateur: null
} 

Des mutations sont ensuite créées pour modifier l'état si nécessaire.

authUser Enregistre le jeton et userId
storeUser Stocke les informations utilisateur
clearAuthData [19659043] Efface les données à leur état initial
 mutations: {
  authUser (état, userData) {
    state.idToken = userData.token
    state.userId = userData.userId
  },
  storeUser (état, utilisateur) {
    state.user = utilisateur
  },
  clearAuthData (état) {
    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', {
        e-mail: authData.email,
        mot de passe: authData.password,
        returnSecureToken: true
      })
        .then (res => {
          console.log (res)
          commit ('authUser', {
            jeton: 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 (fonction () {
            router.push ('/ dashboard')
          }, 3000)
        })
        .catch (erreur => console.log (erreur))
    } 
 connexion ({commit}, authData) {
      axios.post ('https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=AIzaSyCFr-OMMzDGp4Mmr0t66w2cTGfNazYjptQ', {
        e-mail: authData.email,
        mot de passe: 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', {
            jeton: res.data.idToken,
            userId: res.data.localId
          })
          router.push ('/ dashboard')
        })
        .catch (erreur => console.log (erreur.message))
    } 

Mais voici la partie délicate, ce que nous allons faire avec l'action d'inscription en particulier, c'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 pour utiliser les données de cette base de données d'authentification, et nous n'avons envoyé aucune de nos données d'inscription en dehors de l'e-mail / mot de passe.

Nous allons donc en 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 souhaiterez 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}, données d'utilisateur) {
      if (! state.idToken) {
        revenir
      }
      axios.post ('https://vue-journal.firebaseio.com/users.json' + '? auth =' + state.idToken, userData)
        .then (res => console.log (res))
        .catch (erreur => console.log (erreur))
    }
  } 

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

En effet, nous ne pouvons pas écrire dans notre base de données, sauf si 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 l'inscription et la connexion à partir de leurs composants dans la méthode onSubmit aux actions respectives dans le magasin.

 méthodes: {
  onSubmit () {
    const signupData = {
      email: this.email,
      nom: this.name,
      âge: this.age,
      mot de passe: this.password,
      confirmPassword: this.co
      nfirmPassword
    }
    $ store.dispatch ('signup', signupData)
    }
  }
} 

Remarque: signupData contient les données du formulaire.

 méthodes: {
  onSubmit = {
    const formData = {
      email: this.email,
      mot de passe: this.password
    }
    $ store.dispatch ('login', {email: formData.email, mot de passe: 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. [19659055] import store from './store'[19659038[Dansl'itinéraireaccédezauchemindutableaudebordetajoutezcequisuit:

 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 le si oui, nous donnons accès au tableau de bord et vice versa.

LogOut

Pour créer notre option de déconnexion, nous utiliserons clearAuth que nous avons créé précédemment sous mutations qui définit à la fois le jeton et userId sur null .

Nous créons maintenant une nouvelle action de déconnexion , qui s'engage à clearAuth supprimer le stockage local et ajouter router.replace ('/') pour rediriger complètement l'utilisateur .

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

Dans le composant d'en-tête, nous avons une méthode onLogout qui distribue notre action de déconnexion dans le magasin.

 méthodes: {
      onLogout () {
        $ store.dispatch ('déconnexion')
      }
    } 

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

 
    Se déconnecter

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 les getters appelée 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 (état) {
    return state.idToken! == null
  }
} 

Après quoi, vous revenez au composant d'en-tête et créez une méthode auth sous calculée, qui est envoyée à notre isAuthenticated dans les getters we ' ai juste créé dans le magasin. Cela signifie que isAuthenticated renverrait false s'il n'y a pas de jeton, ce qui signifie que auth serait également nul et vice versa.

 calculé: {
      auth () {
        retourner ceci. $ 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. [19659055]

  •            Tableau de bord
  • S'inscrire
  • Connexion
    • 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 sur l'état d'authentification de l'utilisateur. ( Grand aperçu )

    AutoLogin

    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 donc finalement, 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 disposer d'une méthode de connexion automatique à notre utilisateur dans la mesure où le jeton est toujours valide.

    A new actions La ​​méthode appelée AutoLogin est créée, où nous récupérons le jeton et userId à partir du stockage local et validons nos données dans la méthode authUser dans les mutations.

     actions: {
      Connexion automatique ({commit}) {
          const token = localStorage.getItem ('token')
          si (! jeton) {
            revenir
          }
          const userId = localStorage.getItem ('userId')
          const token = localStorage.getItem ('token')
          commit ('authUser', {
            idToken: jeton,
            userId: userId
          })
      }
    } 

    Nous allons ensuite dans notre App.vue et écrivons une méthode créée qui enverra le autoLogin de notre magasin chaque fois que l'application est chargée.

     créé () {
        $ 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éée qui vérifie d'abord s'il y a un jeton comme d'habitude. Ensuite, il récupère l'e-mail du stockage local et interroge la base de données comme cela avait été fait précédemment avec la validation de l'e-mail.

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

     fetchUser ({commit, state}) {
      if (! state.idToken) {
        revenir
      }
      const email = localStorage.getItem ('email')
      axios.get ('https://vue-journal.firebaseio.com/users.json?orderBy= "email" & equalTo = "' + email + '"')
        .then (res => {
          console.log (res)
        
         // const utilisateurs = []
          console.log (res.data)
          const data = res.data
          utilisateurs const = []
          pour (laissez entrer les données) {
            const user = data [key]
            user.id = clé
            users.push (utilisateur)
            console.log (utilisateurs)
          }
         commit ('storeUser', utilisateurs [0])
        })
        .catch (erreur => console.log (erreur))
    } 

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

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

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

     calculé: {
      Nom () {
          retourner! this. $ store.getters.user? false: this. $ store.getters.user.name
        }
      },
      créé () {
        this. $ store.dispatch ('fetchUser')
      }
    } 

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

     

    Bienvenue, {{name}}

    Send_Survey

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

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

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

     méthodes: {
      onSubmit () {
        const postData = {
          prix: this.price,
          long: this.long,
          commentaire: 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 puissantes fonctionnalités dans votre prochain projet car elles sont très importantes pour la création d'applications Web modernes.

    Si vous avez des questions, vous pouvez les laisser dans la section des commentaires et je serai heureux pour répondre à chacun d'entre eux!

    • La démo du didacticiel est en ligne ici .
     Application d'enquête Vue
    L'application d'enquête terminée ( Grand aperçu ) [19659016] D'autres ressources qui peuvent s'avérer utiles incluent:
    • Pour en savoir plus sur Firebase et les autres services qu'il propose, consultez l'article de Chris Esplin, " Qu'est-ce que Firebase? "
    • Vuelidate est vraiment un belle bibliothèque 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 le souhaitez pour l'utiliser dans des projets plus importants.
     Éditorial fracassant (ra, yk, il)




    Source link