Introducción

1

Qué necesitas para este curso y qué aprenderás sobre Node.js con Hapi

2

Conceptos principales de hapi y creación de nuestro primer servidor

3

Breve historia y estado actual

Creando un sitio básico con Hapi

4

El objeto h, response y sus herramientas

5

Uso de plugins - Contenido estático

6

Plantillas con Handlebars

7

Renderizado de vistas - Layout y template del home

8

Recibiendo parámetros en una ruta POST - Creación del registro

9

Definir una mejor estructura con buenas prácticas en Hapi

10

Validando la información - Implementando Joi

11

Introducción a Firebase

12

Creando un modelo y guardando en firebase

13

Implementando el login y validación del usuario

14

Autenticación de usuarios - Cookies y estado

15

Manejando errores

16

Visualización de errores

17

Controlar el error 404 en inert y el error de validación

18

Repaso - Creación del modelo y controlador para preguntas

19

Repaso - Creación de las rutas para crear preguntas

20

Listar las últimas preguntas en el home

Aplicacion de conceptos avanzados

21

Enrutamiento avanzado - visualizando una pregunta

22

Enrutamiento avanzado - respondiendo una pregunta

23

Generando la lógica de la plantilla según si es creador o contribuidor

24

Métodos de servidor - respuesta correcta

25

Usando métodos de servidor

26

Manejo del caché - Agregando el home al caché

27

Procesamiento de archivos - Aceptando imágenes

28

Logging con Good - Monitoreando el servidor

29

Creación de plugins - Teoría

30

Creación de plugins - Implementando un API REST

31

Estrategías de autenticación - Asegurando el API REST

32

Seguridad básica - Asegurando el servidor contra CSRF

33

Seguridad básica - Asegurando el servidor contra XSS

Herramientas de desarrollo

34

Depuración del proyecto

35

Ecosistema de Hapi

Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Creando un modelo y guardando en firebase

12/35
Recursos

Para implementar el uso de la base de datos de Firebase en nuestro proyecto, crearemos el directorio /config para guardar el archivo json con las credenciales de acceso al servicio, y el directorio /models con los modelos asociados a las diferentes entidades que requiere nuestra aplicación. Instalamos desde la terminal el módulo firebase-admin con npm. Requerimos el módulo en el index.js del directorio /models e invocamos el método firebase.initializeApp()

Aportes 18

Preguntas 6

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Con las nuevas versiones de Hapi tenemos el siguiente error: TypeError: queryData.hasOwnProperty is not a function

Solución
En el archivo users de la carpeta models

  async create(data) {
    console.log(data)
    // Destructuro el objeto con el payload enviado. Ya que Hapi lo decora con un prototipo null que no es compatible con Firebase
    const user = {
      ...data
    }
    console.log(data)
    user.password = await this.constructor.encrypt(user.password)
    const newUser = this.collection.push(user)
    return newUser.key
  }

Mi aporte en el código Septiembre 2019

Archivo de conexión a la base de datos

'use strict'

// Información de configuración proporcionada en 
// NombreProyectoFirebase -> configuración del proyecto -> cuentas del servicio

const firebase = require('firebase-admin')
const serviceAccount = require('../config/firebase.json')

firebase.initializeApp({
  credential: firebase.credential.cert(serviceAccount),
  databaseURL: "https://mxplatzi-overflow.firebaseio.com"
})

// Crear una instancia (referencia) de la base de datos
const db = firebase.database()

// Importar modulos (CLASES) correspondientes a los modelos de la base de datos
const User = require('./users')

// Recordar que los modelos esperan como parámetro una referencia hacia la base de datos.
// Exportamos las instancias de los modelos listas para ser invocadas en los controladores correspondientes
module.exports = {
  user: new User(db)
}

Archivo de modelo User

'use strict'

const bcrypt = require('bcrypt')

/**
 * Clase compatible con Firebase Data Base
 */

class User {
  // La clase recibe una referencia hacia la base de datos de firebase donde se guardará la información
  constructor(db) {
    this.db = db
    this.ref = this.db.ref('/')
    this.collection = this.ref.child('users')
  }

  // Método de clase para guardar un usuario en la base de datos de firebase
  async create(data) {
    console.log(data)
    // Destructuro el objeto con el payload enviado. Ya que Hapi lo decora con un prototipo null que no es compatible con Firebase
    const user = {
      ...data
    }
    // Se genera una contraseña encriptada a partir de la proporcionada. this.constructor llama a la clase, ya que el método encrypt es estático
    user.password = await this.constructor.encrypt(user.password)
    const newUser = this.collection.push(user)
    // Retornamos el id del usuario
    return newUser.key
  }

  // Método estático asincrono para la encriptacion de contraseñas
  static async encrypt(password) {
    const saltRounds = 10
    const hashedPassword = await bcrypt.hash(password, saltRounds)
    return hashedPassword
  }
}

module.exports = User

Archivo de controlador User

'use strict'

// Definición de controladores de ruta

// Importar el archivo de conexión a la base de datos
const { user } = require('../models/index')

function register(req, h) {
  return h.view('register')
}

/**
 * Controlador encargado de registrar un usuario en la base de datos.
 * La base de datos se encuentra en un servicio desentralizado (Firebase) que retonra una promesa.
 */
async function createUser(req, h) {
  try {
    const createUserId = await user.create(req.payload)
    return h.response(`Usuario registrado satisfactoriamente con el ID ${createUserId}`).code(201)
  } catch (error) {
    console.error(error)
    return h.response('Problemas al registrar el usuario').code(500)
  }
}

module.exports = {
  register,
  createUser
}

El problema de obj.hasOwnProperty se debe a que el objeto de payload tiene una decoración de prototipo null.

[Object: null prototype] {
  name: 'Fernanda Villar Becerril',
  email: '[email protected]',
  password: 'secreto' }

Esto se soluciona de muchas formas, la mas sencilla es destructurando el objeto.

Si tienen problemas al ejecutar el código y obtienen:
TypeError: obj.hasOwnProperty
Prueben des estructurando el objeto a la hora de pasarlo como argumento:

const result = await users.create({ ...req.payload })

Recuerden crear en Firebase una > Realtime Database
para que puedan continuar con la clase

Tengo problemas al instalar bcrypt, estoy en win 10 x64 y me dice que la plataforma no está soportada

¿Cómo hizo el profesor para detener la instalación de firebase-admin, cuando se le olvidó poner -S el final del comando de instalación de npm? ¿Lo hizo con el equivalente a Ctrl + C en Windows?

Solucion para instalar bcrypt en Windows

https://stackoverflow.com/a/40046466/9053821

PARA PODER INSTALAR BCRYPT EN WINDOWS 10 TUVE QUE EJECUTAR LOS SIGUIENTES PASOS

  1. Instalar las dependencias de node-gyp, así:
    Abrimis una consola de comandos normal o de PowerShell con privilegios de Administrador.
npm install --global --production windows-build-tools

Esto Instalará todas las herramientas y configuraciones requeridas

  1. Instalar el paquete de node-gyp, de forma global, con el siguiente comando:
$ npm install -g node-gyp
  1. Instalar el paquete de bcrypt, como dependencia del proyecto, con el siguiente comando:
npm install bcrypt -S

Como se utilizaria con una base de datos relacional como Mysql

para el momento en el que realizo el curso hay un problema con la ultima version de firebase-admin (8.2) y no funcionan los metodos que se ven en la creacion de la clase, o al menos a mi no me sirvio y tuve que usar la version que usan en el curso

Si alguien más usa Windows y tuvo problemas usando bcrypt por x o y razón, en el repo recomiendan utilizar mejor bcryptjs.
“Optimized bcrypt in JavaScript with zero dependencies. Compatible to the C++ bcrypt binding on node.js and also working in the browser.”

Las líneas utilzadas en el curso se pueden cambiar por estas:

 static async encrypt(password){
    const salt = 10    
    const hashedPassword = await bcrypt.hash( password, salt)
    return hashedPassword
  
    return hashedPassword
  }

Bye x)

Para los usuarios de Windows deben instalar primero python https://www.python.org/downloads/
Luego correr el siguiente comando en PowerShell como administrador:

npm install --global --production windows-build-tools

Reinicien Win, y luego ejecuten en la terminal:
npm i bcrypt -S

con la version 8.6 de Firebase da problema “obj.hasOwnProperty is not a function”, tal vez podrian explicar el por que para poder utilizar las librerias en su ultima version, me toco utilizar la que tienen declarada en el packege.json del curso.

Objeto no estructurado

[Object: null prototype] {
  name: 'Juan',
  email: '[email protected]',
  password: '123456'
}

Objeto estructurado

{ name: 'Juan', email: '[email protected]', password: '123456' }

me da este error al tratar de ejecutar npm run dev finalizando el video

@firebase/database: FIREBASE WARNING: {“code”:“app/invalid-credential”,“message”:“Credential implementation provided to initializeApp() via the “credential” property failed to fetch a valid Google OAuth2 access token with the following error: “Failed to parse access token response: Error: Server responded with status 400.”.”}

Si tienen error al instalar firebase-admin de este tipo:

npm ERR! code EPERM

Solo instalen nuevamente npm completamente con esta instruccion:

npm install

y vuelvan a instalar firebase

Me agrada bastante la integración con typescript ya que te permite incluir tipado escricto y detectar cuando se mutan los objetos y te conviene tener otro acercamiento…

así va quedando

import { database } from 'firebase-admin';
import { encrypt } from '../../helpers/encrypter';
import { Users } from '../interfaces/Users';

export class User {
  private db: database.Database;
  private ref: database.Reference;
  private collection: database.Reference;

  constructor(db: database.Database) {
    this.db = db;
    this.ref = this.db.ref('/');
    this.collection = this.ref.child('user');
  }

  async newUser(user: Users) {
    const refUser = this.collection.push();
    const { password, ...data } = user;

    await refUser.set({ ...data, password: await encrypt(password) });

    return refUser.key;
  }
}

y el zip con el avance hasta integrar firebase se los comparto:
zip file

Cualquier feedback bienvenido:
repo github