O cadastro ou Inscrição em qualquer site sempre requer um nome de usuário. Na maioria das vezes, usamos 'e-mail' para registrar em um site. O e-mail de registro é sempre único e deve referir-se a apenas um usuário, caso contrário, pode ocorrer conflito entre os usuários. Para resolver este conflito todo site deve ter a funcionalidade de não aceitar o e-mail que já existe no site. Esta funcionalidade pode ser implementada em qualquer lugar em nosso código, como no arquivo de índice ou no arquivo de rota, mas isso vem na parte de validação. Portanto, geralmente preferimos codificar essa lógica onde todas as outras validações são codificadas. Aqui, usamos o middleware 'express-validator' para implementar essa funcionalidade.

Comando para instalar express-validator:

npm install express-validator

Passos para usar express-validator para implementar a lógica:

  • Instale o middleware express-validator.
  • Crie um arquivo validator.js para codificar toda a lógica de validação.
  • Valide o e-mail por validateEmail : verifique ('e-mail') e encadeie toda a validação com ' . '
  • Use o nome de validação (validateEmail) nas rotas como um middleware como uma array de validações.
  • Destrói a função 'validationResult' de express-validator para usá-la para encontrar quaisquer erros.
  • Se ocorrer um erro, redirecione para a mesma página, passando as informações do erro.
  • Se a lista de erros estiver vazia, conceda acesso ao usuário para a solicitação subsequente.

Observação: aqui usamos um banco de dados local ou personalizado para implementar a lógica, as mesmas etapas podem ser seguidas para implementar a lógica em um banco de dados regular como MongoDB ou MySql.

Exemplo: Este exemplo ilustra como verificar se o endereço de e-mail já está em uso ou não para um determinado site.

Nome do arquivo: index.js

const express = require('express')
const bodyParser = require('body-parser')
const { validationResult } = require('express-validator')
const repo = require('./repository')
const { validateEmail } = require('./validator')
const signupTemplet = require('./signup')
  
const app = express()
  
const port = process.env.PORT || 3000
  
// The body-parser middleware to parse form data
app.use(bodyParser.urlencoded({ extended: true }))
  
// Get route to display HTML form to sign up
app.get('/signup', (req, res) => {
    res.send(signupTemplet({}))
})
  
// Post route to handle form submission logic and 
app.post(
    '/signup',
    [validateEmail],
    async (req, res) => {
        const errors = validationResult(req)
        if (!errors.isEmpty()) {
            return res.send(signupTemplet({ errors }))
        }
        const { email, password } = req.body
        await repo.create({ email, password })
        res.send('Sign Up successfully')
    })
  
// Server setup
app.listen(port, () => {
    console.log(`Server start on port ${port}`)
})

Nome do arquivo: repository.js Este arquivo contém toda a lógica para criar um banco de dados local e interagir com ele.

// Importing node.js file system module 
const fs = require('fs')
  
class Repository {
  
    constructor(filename) {
  
        // The filename where datas are
        // going to store
        if (!filename) {
            throw new Error(
'Filename is required to create a datastore!')
        }
  
        this.filename = filename
  
        try {
            fs.accessSync(this.filename)
        } catch (err) {
  
            // If file not exist it is created
            // with empty array
            fs.writeFileSync(this.filename, '[]')
        }
    }
  
    // Get all existing records
    async getAll() {
        return JSON.parse(
            await fs.promises.readFile(this.filename, {
                encoding: 'utf8'
            })
        )
    }
  
    // Find record by properties
    async getOneBy(filters) {
        const records = await this.getAll()
        for (let record of records) {
            let found = true
            for (let key in filters) {
                if (record[key] !== filters[key]) {
                    found = false
                }
            }
            if (found) return record;
        }
    }
  
    // Create new record
    async create(attrs) {
        const records = await this.getAll()
        records.push(attrs)
        await fs.promises.writeFile(
            this.filename,
            JSON.stringify(records, null, 2)
        )
        return attrs
    }
}
  
// The 'datastore.json' file created at runtime 
// and all the information provided via signup form
// store in this file in JSON formet.
module.exports = new Repository('datastore.json')

Nome do arquivo: signup.js Este arquivo contém a lógica para mostrar o formulário de inscrição.

const getError = (errors, prop) => {
    try {
  
        // Return error message if any error occurs
        return errors.mapped()[prop].msg
    } catch (error) {
  
        // Return empty string if no error
        return ''
    }
}
  
module.exports = ({ errors }) => {
    return `
      <!DOCTYPE html>
      <html>
        <head>
          <link rel='stylesheet'
href='https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.0/css/bulma.min.css'>
          <style>
            div.columns{
              margin-top: 100px;
            }
            .button{
              margin-top : 10px
            }
          </style>
        </head>
        <body>
          <div class='container'>
            <div class='columns is-centered'>
              <div class='column is-5'>
                <h1 class='title'>Sign Up<h1>
                <form method='POST'>             
                  <div>
                    <div>
                      <label class='label' 
                        id='email'>Username</label>
                    </div>
                    <input class='input' type='text' 
                        name='email' placeholder='Email'
                        for='email'>
                    <p class="help is-danger">
                        ${getError(errors, 'email')}
                    </p>
                  </div>
                  <div>
                    <div>
                        <label class='label' id='password'>
                            Password
                        </label>
                    </div>
                    <input class='input' type='password'
                    name='password' placeholder='Password'
                            for='password'>
                  </div>
                  <div>
                    <button class='button is-primary'>
                        Sign Up
                    </button>
                  </div>
                </form>
              </div>
            </div>
          </div>
        </body>
      </html>   
    `
}

Nome do arquivo: validator.js Este arquivo contém toda a lógica de validação (lógica para ver se o email já existe ou não).

const { check } = require('express-validator')
const repo = require('./repository')
  
module.exports = {
  
    validateEmail: check('email')
  
        // To delete leading and triling space
        .trim()
  
        // Normalizing the email address
        .normalizeEmail()
  
        // Checking if follow the email 
        // address formet or not
        .isEmail()
  
        // Custom message
        .withMessage('Invalid email')
  
        // Custom validation
        // Validate email in use or not
        .custom(async (email) => {
            const existingUser = 
                await repo.getOneBy({ email })
                  
            if (existingUser) {
                throw new Error('Email already in use')
            }
        })
}

Execute o arquivo index.js usando o seguinte comando:

node index.js

Nome do arquivo: package.json

arquivo package.json

Base de dados:

Base de dados

Saída:

Inscreva-se com o e-mail já em uso

Resposta quando se inscreve com e-mail que já está em uso

Cadastre-se com e-mail que não está em uso

Resposta quando se inscreve com um e-mail que não está em uso

Banco de dados após inscrição bem-sucedida (inscreva-se com e-mail que não está em uso)

Banco de dados após inscrição bem-sucedida (inscreva-se com e-mail que não está em uso)

Nota: Usamos algumas classes Bulma (estrutura CSS) no arquivo signup.js para projetar o conteúdo.