Fermer

avril 15, 2018

Construisez une application CRUD Basic avec Vue.js et Node –


Cet article a été publié à l'origine le blog du développeur Okta . Merci de soutenir les partenaires qui rendent SitePoint possible.

J'ai dansé le shuffle du framework JavaScript pendant des années en commençant par jQuery, puis par Angular. Après avoir été frustré par la complexité d'Angular, j'ai trouvé React et pensé que j'étais dans le clair. Ce qui semblait simple à la surface a fini par être un gâchis frustrant. Puis j'ai trouvé Vue.js. Cela me semblait juste. Cela a fonctionné comme prévu. C'était rapide. La documentation était incroyable. Le modèle était éloquent. Il y avait un consensus unanime sur la façon de gérer la gestion d'état, le rendu conditionnel, la liaison bidirectionnelle, le routage, etc.

Ce tutoriel vous guidera étape par étape pour échafauder un projet Vue.js, déchargeant l'authentification sécurisée vers OpenID Connect API (OIDC) d'Okta qui verrouille les routes protégées et effectue des opérations CRUD via un serveur d'API REST backend. Ce tutoriel utilise les technologies suivantes mais ne nécessite pas de connaissances intimes à suivre:

A propos de Vue.js

Vue.js est un framework Javascript robuste mais simple. Il a l'une des barrières les plus basses à l'entrée de tout cadre moderne tout en fournissant toutes les fonctionnalités requises pour les applications Web haute performance.

 Vue.js Homepage

Ce tutoriel couvre deux builds primaires, une frontend application web et serveur d'API REST backend. Le frontend sera une application d'une seule page (SPA) avec une page d'accueil, login et déconnexion, et un gestionnaire de posts.

Okid OpenID Connect (OIDC) gérera l'authentification de notre application web en utilisant Vue SDK d'Okta . Si un utilisateur non authentifié accède au gestionnaire des publications, l'application Web doit tenter d'authentifier l'utilisateur.

Le serveur s'exécutera Express avec Sequelize et Epilogue . À un niveau élevé, avec Sequelize et Epilogue, vous pouvez générer rapidement des points de terminaison REST dynamiques avec juste quelques lignes de code.

Vous utiliserez l'authentification basée sur JWT pour faire des requêtes depuis l'application web et Okta's JWT Verifier dans un intergiciel Express pour valider le jeton. Votre application exposera les points de terminaison suivants qui requièrent tous des demandes pour avoir un jeton d'accès valide.

 - GET / posts
- GET / posts /: id
- POST / messages
- PUT / posts /: id
- DELETE / posts /: id

Créez votre application Vue.js

Pour décoller rapidement votre projet, vous pouvez tirer parti de la fonctionnalité d'échafaudage de vue-cli . Pour ce didacticiel, vous allez utiliser le modèle d'application Web progressive qui inclut une poignée de fonctionnalités, notamment webpack rechargement à chaud extraction CSS,

Si vous n'êtes pas familier avec les principes de PWA, consultez notre guide ultime pour les applications web progressives .

Pour installer vue-cli :

 npm installer -g vue-cli

Ensuite, vous devez initialiser votre projet. Lorsque vous exécutez la commande vue init acceptez simplement toutes les valeurs par défaut.

 vue init pwa my-vue-app
cd ./my-vue-app
npm installer
NPM Run Dev

Pointez votre navigateur préféré vers http: // localhost: 8080 et vous devriez voir les fruits de votre travail:

 Bienvenue dans votre Vue.js PWA

Extra Credit : Découvrez les autres templates disponibles pour vue-cli .

Installer Bootstrap

Installez bootstrap-vue ainsi vous pouvez tirer parti des divers composants premade (plus vous pouvez garder l'accent sur la fonctionnalité et non sur la coutume CSS):

 npm je --save bootstrap-vue bootstrap

Pour terminer l'installation, modifiez ./ src / main.js pour inclure bootstrap-vue et importez les fichiers CSS requis. Votre fichier ./ src / main.js devrait ressembler à ceci:

 // La version de construction de Vue à charger avec la commande `import`
// (runtime-only ou standalone) a été défini dans webpack.base.conf avec un alias.
importer Vue de 'vue'
importer une application à partir de './App'
importer un routeur à partir de './router'
importer BootstrapVue à partir de 'bootstrap-vue'
import 'bootstrap / dist / css / bootstrap.css'
import 'bootstrap-vue / dist / bootstrap-vue.css'

Vue.use (BootstrapVue)
Vue.config.productionTip = false

/ * eslint-disable non-nouveau * /
nouvelle Vue ({
  el: '#app',
  routeur,
  modèle: '',
  composants: {App}
})

Ajouter l'authentification avec Okta

Traiter l'authentification dans une application web est le fléau de l'existence de chaque développeur. C'est là que Okta intervient pour sécuriser vos applications web avec un minimum de code. Pour commencer, vous devrez créer une application OIDC dans Okta. Créez un compte développeur forever-free (ou identifiez-vous si vous en avez déjà un)

 Okta Developer S'inscrire

Une fois connecté, créez une nouvelle application en cliquant sur "Ajouter une application"

 Ajouter une application

Sélectionnez l'option de plateforme "App Page unique"

 Nouvelles options d'application

L'application par défaut les paramètres doivent être les mêmes que ceux illustrés.

 Paramètres d'application Okta

Pour installer Okta Vue SDK, exécutez la commande suivante:

 npm i --save @ okta / okta-vue

Ouvrez ./src/router/index.js et remplacez le fichier entier par le code suivant:

 import Vue de 'vue'
import Router à partir de 'vue-router'
import Bonjour à partir de '@ / components / Hello'
importer PostsManager à partir de '@ / components / PostsManager'
Importer l'autorisation depuis '@ okta / okta-vue'

Vue.use (Auth, {
  émetteur: 'https: // {yourOktaDomain} .com / oauth2 / default',
  client_id: '{votreClientId}',
  redirect_uri: 'http: // localhost: 8080 / implicite / callback',
  scope: 'email de profil openid'
})

Vue.use (Routeur)

let router = nouveau Routeur ({
  mode: 'histoire',
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: Hello
    },
    {
      path: '/implicit/callback',
      component: Auth.handleCallback()
    },
    {
      path: '/posts-manager',
      name: 'PostsManager',
      component: PostsManager,
      meta: {
        requiresAuth: true
      }
    }
  ]
})

router.beforeEach (Vue.prototype. $ auth.authRedirectGuard ())

exporter le routeur par défaut

Vous devrez remplacer {yourOktaDomain} et {yourClientId} qui se trouvent sur la page de présentation de votre application dans la console développeur Okta. Cela va injecter un objet authClient dans votre instance de Vue, accessible en appelant this. $ Auth n'importe où dans votre instance de Vue.

 Vue.use (Auth, {
  émetteur: 'https: // {yourOktaDomain} .com / oauth2 / default',
  client_id: '{votreClientId}',
  redirect_uri: 'http: // localhost: 8080 / implicite / callback',
  scope: 'email de profil openid'
})

La ​​dernière étape du processus d'authentification d'Okta consiste à rediriger l'utilisateur vers votre application avec les valeurs de jeton dans l'URL. Le composant Auth.handleCallback () inclus dans le SDK gère la redirection et conserve les jetons sur le navigateur.

 {
  chemin: '/ implicite / callback',
  composant: Auth.handleCallback ()
}

Vous devez également verrouiller les routes protégées contre l'accès par des utilisateurs non authentifiés. Ceci est accompli en mettant en œuvre un garde de navigation . Comme son nom l'indique, les gardes de navigation sont principalement utilisés pour protéger les navigations en les redirigeant ou en les annulant.

Le SDK est livré avec la méthode auth.authRedirectGuard () vérifiant les routes correspondantes metadata pour la clé requiresAuth et redirige l'utilisateur vers le flux d'authentification s'il n'est pas authentifié.

 router.beforeEach (Vue.prototype. $ auth.authRedirectGuard ())

Cette garde de navigation étant installée, toute route ayant les métadonnées suivantes sera protégée.

 meta: {
  requiresAuth: true
}

Personnaliser la disposition de votre application dans Vue

La disposition de l'application Web se trouve dans un composant ./src/App.vue . Vous pouvez utiliser le composant routeur-view pour rendre le composant correspondant au chemin donné.

Pour le menu principal, vous souhaiterez modifier la visibilité de certains éléments de menu en fonction de l'état du activeUser :

  • Non authentifié: Afficher uniquement Connexion
  • Authentifié: Montrer seulement Déconnexion

Vous pouvez changer la visibilité de ces éléments de menu en utilisant le v- if directive dans Vue.js qui vérifie l'existence de activeUser sur le composant. Lorsque le composant est chargé (qui appelle created () ) ou lorsqu'un itinéraire change, nous voulons actualiser le activeUser .

Ouvrir ./ src / App.vue et copiez / collez le code suivant:

   

Chaque connexion doit être déconnectée. L'extrait suivant déconnecte votre utilisateur, actualise l'utilisateur actif (désormais null), puis redirige l'utilisateur vers la page d'accueil. Cette méthode est appelée lorsqu'un utilisateur clique sur le lien de déconnexion dans la navigation.

 async logout () {
  attendez ceci. $ auth.logout ()
  attendre this.refreshActiveUser ()
  ceci. $ router.push ('/')
}

Les composants sont les blocs de construction dans Vue.js. Chacune de vos pages sera définie dans l'application en tant que composant. Étant donné que le modèle webpack vue-cli utilise vue-loader les fichiers sources de vos composants ont une convention qui sépare le modèle, le script et le style ( voir ici ).

'ai ajouté vue-bootstrap, modifiez ./ src / components / Hello.vue pour supprimer les liens standards générés par la vue-cli.

 

À ce stade, vous pouvez remplacer la page Post Manager pour tester votre flux d'authentification. Une fois l'authentification validée, vous commencerez à créer les appels API et les composants requis pour effectuer des opérations CRUD sur votre modèle Posts.

Créer un nouveau fichier ./src/ components / PostsManager.vue et collez le code suivant:

 

Prenez votre flux Vue.js Frontend et Auth pour un test

Dans votre terminal exécutez npm run dev (si c'est pas encore en cours d'exécution). Accédez à http: // localhost: 8080 et vous devriez voir la nouvelle page d'accueil

 Hello World

Si vous cliquez sur Posts Manager ou Login vous devriez être dirigé vers le flux d'Okta. Entrez vos informations d'identification de compte Okta.

NOTE: Si vous êtes connecté à votre compte de développeur Okta, vous serez automatiquement redirigé vers l'application. Vous pouvez le tester en utilisant la navigation privée ou en mode navigation privée

 Okta Connexion

Si réussi, vous devriez retourner à la page d'accueil.

 Page d'accueil après s'être connecté

En cliquant sur le lien Posts Manager devrait rendre le composant protégé

 Posts Manager

Ajouter un serveur API REST backend

Maintenant que les utilisateurs peuvent s'authentifier en toute sécurité, Vous pouvez créer le serveur API REST pour effectuer des opérations CRUD sur un modèle de publication. Ajoutez les dépendances suivantes à votre projet:

 npm i --save express cors @ okta / jwt-verifier sequelize sqlite3 epilogue axios

Ensuite, créez le fichier ./src/server.js et collez le code suivant:

 const express = require ('express')
const cors = require ('cors')
const bodyParser = require ('body-parser')
const Sequelize = require ('sequelize')
const epilogue = require ('épilogue')
const OktaJwtVerifier = require ('@ okta / jwt-verifier')

const oktaJwtVerifier = nouveau OktaJwtVerifier ({
  clientId: '{votreClientId}',
  émetteur: 'https: // {yourOktaDomain} .com / oauth2 / default'
})

laissez app = express ()
app.use (cors ())
app.use (bodyParser.json ())

// vérifie le middleware de jeton JWT
app.use ((req, res, next) => {
  // demande à chaque requête d'avoir un en-tête d'autorisation
  if (! req.headers.authorization) {
    return next (nouvelle erreur ('L'en-tête d'autorisation est obligatoire'))
  }
  let parties = req.headers.authorization.trim (). split ('')
  laissez accessToken = parts.pop ()
  oktaJwtVerifier.verifyAccessToken (accessToken)
    .then (jwt => {
      req.user = {
        uid: jwt.claims.uid,
        email: jwt.claims.sub
      }
      prochain()
    })
    .catch (suivant) // jwt n'a pas vérifié!
})

// Pour faciliter ce tutoriel, nous allons utiliser SQLite pour limiter les dépendances
let database = new Sequelize ({
  dialecte: 'sqlite',
  stockage: './test.sqlite'
})

// Définir notre modèle Post
// id, createdAt et updatedAt sont ajoutés automatiquement par sequelize
let Post = database.define ('posts', {
  titre: Sequelize.STRING,
  corps: Sequelize.TEXT
})

// Initialiser l'épilogue
epilogue.initialize ({
  application: application,
  sequelize: base de données
})

// Créer la ressource REST dynamique pour notre modèle Post
Laissez userResource = epilogue.resource ({
  modèle: Post,
  paramètres: ['/posts', '/posts/:id']
})

// Réinitialise la base de données et lance l'application express sur: 8081
base de données
  .sync ({force: vrai})
  .then (() => {
    app.listen (8081, () => {
      console.log ('écoute le port localhost: 8081')
    })
  })

Assurez-vous de remplacer les variables {yourOktaDomain} et {clientId} dans le code ci-dessus par les valeurs de votre application OIDC en Okta.

Ajouter Sequelize

Sequelize est un ORM basé sur des promesses pour Node.js. Il prend en charge les dialectes PostgreSQL, MySQL, SQLite et MSSQL et offre une prise en charge solide des transactions, des relations, la réplication en lecture, etc.

Pour faciliter ce tutoriel, vous allez utiliser SQLite pour limiter les dépendances externes. Le code suivant initialise une instance Sequelize en utilisant SQLite comme pilote.

 let database = new Sequelize ({
  dialecte: 'sqlite',
  stockage: './test.sqlite'
})

Chaque publication a un titre et un corps . (Les champs createdAt et updatedAt sont automatiquement ajoutés par Sequelize). Avec Sequelize, vous définissez des modèles en appelant define () sur votre instance.

 let Post = database.define ('posts', {
  titre: Sequelize.STRING,
  corps: Sequelize.TEXT
})

Ajouter Epilogue

Epilogue crée des points de terminaison REST flexibles à partir de modèles Sequelize dans une application Express. Si vous avez déjà codé des points de terminaison REST, vous savez combien il y a de répétitions. SEC. FTW!

 // Initialiser l'épilogue
epilogue.initialize ({
  application: application,
  sequelize: base de données
})

// Créer la ressource REST dynamique pour notre modèle Post
Laissez userResource = epilogue.resource ({
  modèle: Post,
  paramètres: ['/posts', '/posts/:id']
})

Vérifiez votre JWT

Ceci est le composant le plus crucial de votre serveur API REST. Sans ce middleware, n'importe quel utilisateur peut effectuer des opérations CRUD sur notre base de données. Si aucun en-tête d'autorisation n'est présent ou si le jeton d'accès n'est pas valide, l'appel API échoue et renvoie une erreur.

 // Vérifier le middleware de jeton JWT
app.use ((req, res, next) => {
  // demande à chaque requête d'avoir un en-tête d'autorisation
  if (! req.headers.authorization) {
    return next (nouvelle erreur ('L'en-tête d'autorisation est obligatoire'))
  }
  let parties = req.headers.authorization.trim (). split ('')
  laissez accessToken = parts.pop ()
  oktaJwtVerifier.verifyAccessToken (accessToken)
    .then (jwt => {
      req.user = {
        uid: jwt.claims.uid,
        email: jwt.claims.sub
      }
      prochain()
    })
    .catch (suivant) // jwt n'a pas vérifié!
})

Exécuter le serveur

Ouvrez une nouvelle fenêtre de terminal et exécutez le serveur avec la commande node ./src/server. Complétez le composant Posts Manager

Maintenant que le serveur API REST est terminé, vous pouvez commencer à câbler votre gestionnaire de posts pour récupérer des publications, créer des publications, éditer les messages, et supprimer les messages.

Je centralise toujours mes intégrations d'API dans un seul module d'aide. Cela conserve le code dans les composants beaucoup plus propre et fournit un emplacement unique au cas où vous avez besoin de modifier quoi que ce soit avec la demande d'API.

Créez un fichier ./src/api.js et copiez / collez le code suivant dedans:

 import Vue de 'vue'
import axios de 'axios'

const client = axios.create ({
  baseURL: 'http: // localhost: 8081 /',
  json: vrai
})

valeur par défaut d'exportation {
  async execute (méthode, ressource, données) {
    // injecte le accessToken pour chaque requête
    Laisser accessToken = attendre Vue.prototype. $ auth.getAccessToken ()
    retour client ({
      méthode,
      url: ressource,
      Les données,
      en-têtes: {
        Autorisation: `Porteur $ {accessToken}`
      }
    }). then (req => {
      return req.data
    })
  },
  getPosts () {
    renvoie this.execute ('get', '/ posts')
  },
  getPost (id) {
    renvoie this.execute ('get', `/ posts / $ {id}`)
  },
  createPost (données) {
    return this.execute ('post', '/ posts', données)
  },
  updatePost (id, données) {
    return this.execute ('put', `/ posts / $ {id}`, données)
  },
  deletePost (id) {
    renvoie this.execute ('delete', `/ posts / $ {id}`)
  }
}

Lorsque vous vous authentifiez avec OIDC, un jeton d'accès est conservé localement dans le navigateur. Comme chaque requête API doit avoir un jeton d'accès, vous pouvez le récupérer à partir du client d'authentification et le définir dans la requête.

 let accessToken = wait Vue.prototype. $ Auth.getAccessToken ()
retour client ({
  méthode,
  url: ressource,
  Les données,
  en-têtes: {
    Autorisation: `Porteur $ {accessToken}`
  }
})

En créant les méthodes proxy suivantes à l'intérieur de votre API, le code en dehors du module auxiliaire reste propre et sémantique.

 getPosts () {
  renvoie this.execute ('get', '/ posts')
},
getPost (id) {
  renvoie this.execute ('get', `/ posts / $ {id}`)
},
createPost (données) {
  return this.execute ('post', '/ posts', données)
},
updatePost (id, données) {
  return this.execute ('put', `/ posts / $ {id}`, données)
},
deletePost (id) {
  renvoie this.execute ('delete', `/ posts / $ {id}`)
}

Vous disposez maintenant de tous les composants requis pour câbler votre composant de gestionnaire de posts afin d'effectuer des opérations CRUD via l'API REST. Ouvrez ./ src / components / PostsManager.vue et copiez / collez le code suivant.

   

Liste des messages

Vous allez utiliser api.getPosts () pour récupérer des messages de votre serveur API REST. Vous devez actualiser la liste des messages lorsque le composant est chargé et après toute opération de mutation (créer, mettre à jour ou supprimer).

 async refreshPosts () {
  this.loading = true
  this.posts = attend api.getPosts ()
  this.loading = false
}

L'attribut this.loading est basculé pour que l'interface utilisateur reflète l'appel d'API en attente. Vous ne pouvez pas voir le message de chargement puisque la demande d'API ne sort pas sur Internet.

Création de messages

Un formulaire est inclus dans le composant pour enregistrer un message. Il est câblé pour appeler savePosts () lorsque le formulaire est soumis et ses entrées sont liées à l'objet modèle sur le composant.

Quand savePost () est appelée, elle effectuera une mise à jour ou créera en fonction de l'existence de model.id . Il s'agit principalement d'un raccourci pour ne pas avoir à définir deux formulaires distincts pour la création et la mise à jour.

 async savePost () {
  if (this.model.id) {
    attendez api.updatePost (this.model.id, this.model)
  } autre {
    attendre api.createPost (this.model)
  }
  this.model = {} // réinitialiser le formulaire
  attendre this.refreshPosts ()
}

Mise à jour des messages

Lors de la mise à jour d'un message, vous devez d'abord charger le message dans le formulaire. Cela définit model.id qui déclenchera une mise à jour dans savePost () .

 async populatePostToEdit (post) {
  this.model = Object.assign ({}, publication)
}

Important: L'appel Object.assign () copie la valeur de l'argument post plutôt que la référence. Lorsque vous manipulez la mutation d'objets dans Vue, vous devez toujours définir la valeur, et non la référence.

Supprimer des messages

Pour supprimer un message, appelez simplement api.deletePost (id) . Il est toujours bon de confirmer avant de supprimer, donc jetons un message dans une boîte d'alerte de confirmation native pour nous assurer que le clic était intentionnel.

 async deletePost (id) {
  if (confirmez ('Êtes-vous sûr de vouloir supprimer cet article?')) {
    attendez api.deletePost (id)
    attendre this.refreshPosts ()
  }
}

Test de votre application Vue.js + noeud CRUD

Assurez-vous que le serveur et le frontal sont en cours d'exécution.

No de terminal 1

 node ./src/server

Terminal n ° 2

 npm run dev

Accédez à http: // localhost: 8080 et donnez-lui un tourbillon.

 Nouveau message

 Nouveau Hello World Post [19659003]  Supprimer le message

Faire plus avec Vue!

Comme je l'ai dit au début de ce post, je pense que Vue se tient tête et épaules au-dessus d'autres cadres. Voici cinq raisons rapides pourquoi:

J'ai couvert beaucoup de matériel dans ce tutoriel mais ne vous sentez pas mal si vous n'avez pas tout saisi la première fois. Plus vous travaillerez avec ces technologies, plus elles deviendront familières.

Pour en savoir plus sur Vue.js, rendez-vous sur https://vuejs.org ou consultez ces autres excellentes ressources du @oktadev team :

Vous pouvez trouver le code source de l'application développée dans ce post à https://github.com/oktadeveloper/okta-vue-node-example

Comme toujours, suivez @oktadev sur Twitter pour voir tout le contenu cool créé par notre équipe de développement






Source link