Antes de começarmos este tutorial, primeiro teremos que entender o que é Prisma e por que ele é uma boa escolha para desenvolvedores que são novos no Express. Também discutiremos o PostgreSQL e como usá-lo para esquema e estruturação de banco de dados.
Também aprenderemos sobre a eficácia do Prisma e como usá-lo para autenticação básica, junto com exemplos de código e exemplos de teste para ajudá-lo a acompanhar este tutorial.
O que é Prisma?
Prisma é um ORM de código aberto que permite gerenciar e interagir facilmente com seu banco de dados. Isso é feito com o esquema Prisma , um lugar onde você pode definir seu banco de dados modelos e relações usando a linguagem de esquema Prisma.
Você pode executar seu esquema do zero ou gerá-lo por meio da introspecção de um banco de dados existente. Em seguida, você pode usar o Prisma Client para interagir com seu banco de dados e o Prisma Migrate para migrar seu esquema para o banco de dados.
O Prisma oferece suporte a PostgreSQL, MySQL, SQLite e Microsoft SQL Server. O Prisma interage com cada estrutura de back-end Node.js e facilita o gerenciamento e a migração do banco de dados.
Construindo um esquema de autenticação com Prisma no Express
Para começar, vamos configurar um aplicativo Express e adicione Prisma. Em seguida, usaremos pacotes de terceiros como JWT para autenticação baseada em token para criar um esquema de autenticação. Por fim, abordaremos como executar testes e garantir que nosso esquema de autenticação esteja funcionando corretamente.
Pré-requisitos
Para seguir este tutorial, você deve ter um conhecimento prático dessas tecnologias, bem como suas versões mais recentes instaladas em seu computador:
Configurando o Express
Para instalar o Express, primeiro teremos que inicializar nosso aplicativo usando npm. Para fazer isso, execute os seguintes códigos em seu terminal:
mkdir express-prisma cd express-prisma npm init-y
Em seguida, podemos instalar o express usando npm em nosso aplicativo recém-criado usando o seguinte código:
npm install express
Em seguida, configuramos nosso PostgreSQL usando Docker.
Para fazer isso, vamos criar um novo arquivo Docker usando o seguinte comando composer:
nano docker-compose.yml
Então, em nosso arquivo docker-compose.yml, podemos adicionar o código abaixo para conectar ao banco de dados:
version:’3.8’services: postgres: image: postgres: 10.3 restart: always environment:-POSTGRES_USER=sammy-POSTGRES_PASSWORD=seus volumes de senha:-postgres:/var/lib/postgresql/portas de dados:-‘5432: 5432’volumes: postgres:
Observe que POSTGRES_USER e POST_PASSWORD são o nome de usuário e a senha predefinidos que irão ser usado para acessar o banco de dados.
Instalando e configurando o Prisma
Quando a instalação e configuração do nosso r O aplicativo Express está pronto, agora podemos prosseguir e instalar o Prisma em nosso aplicativo usando npm. Para fazer isso, basta usar o comando abaixo:
npx prisma init
Isso criará uma nova pasta Prisma que conterá o arquivo schema.prisma e também criará um arquivo.env se ele não existir.
Depois que os arquivos foram gerados, abra o arquivo.env e adicione um link ao seu banco de dados:
DATABASE_URL=”postgresql://
Certifique-se de usar seu nome de banco de dados e senha personalizados.
Agora que concluímos a configuração do Prisma, podemos criar um esquema do Prisma e adicionar nosso esquema de autenticação.
Criando um esquema Prisma
Começaremos criando um esquema que conterá os parâmetros do usuário que serão migrados para o banco de dados. Isso nos permitirá interagir com eles para concluir a autenticação.
Para adicionar um esquema, vá para o arquivo prisma/schema.prisma e adicione o código abaixo:
model User {id Int @id @default (autoincrement ()) email String @unique name String? String da senha? }
Feito isso, podemos executar nossa migração, que criará o usuário da tabela no banco de dados e adicionará as colunas para ele.
Para executar a migração, adicione o código abaixo ao seu terminal e execute-o:
npx prisma migrate dev–name”init”–preview-feature
Se a migração for bem-sucedida, uma nova pasta será criada dentro da pasta prisma que foi criada anteriormente. A pasta se chamará migrações e conterá um arquivo SQL.
O meu veio como 20210613163752_init/migration.sql com o arquivo migration.sql contendo a estrutura SQL criada no esquema:
-CreateTable CREATE TABLE”User”(“id”SERIAL NOT NULL,”email”TEXT NOT NULL,”name”TEXT,”password”TEXT, PRIMARY KEY (“id”));-CreateIndex CRIAR ÍNDICE ÚNICO”User.email_unique”ON”Usuário”(“email”);
Usando o Prisma Client
O Prisma Client é um criador de consultas gerado automaticamente e com segurança de tipo que você pode usar para ler e gravar dados programaticamente em um banco de dados de um aplicativo Node.js ou TypeScript. Você o usará para acessar o banco de dados em suas rotas de API REST, substituindo ORMs tradicionais, consultas SQL simples, camadas de acesso a dados personalizados ou qualquer outro método de comunicação com um banco de dados.
Para instalar o Cliente Prisma em seu projeto , simplesmente insira o seguinte comando em seu terminal e execute-o:
npm install @ prisma/client
Isso permitirá que você use o Prisma Client em qualquer lugar em seu projeto e, por sua vez, permitirá que você interaja com seu banco de dados.
Requisitos de índice
Após o Prisma Client ter sido configurado, podemos prosseguir e adicionar nosso controlador, que irá interagir com nossas rotas (que apontam para as funções especificadas em nossos controladores). Também adicionaremos nossos serviços, que interagem com o banco de dados ou Prisma.
Para começar, criaremos alguns arquivos e pastas para hospedá-los. O primeiro serão as rotas-vamos criar uma pasta chamada routes e adicionar nossos arquivos index.js e auth.js.
Em seguida, iniciamos nosso servidor Express no arquivo raiz index.js e apontamos as rotas para routes/index.js.
Em seguida, exigimos o Prisma Client no arquivo raiz index.js:
const express=require (‘express’); require (‘@ prisma/client’); const app=express (); require (‘dotenv’). config (); rota const=requer (‘./rotas’); const bodyParser=require (‘body-parser’); const multer=require (‘multer’); app.use (bodyParser.urlencoded ({extended: true})) app.use (bodyParser.json ())//redirecionar para routes/index.js const route=require (‘./routes’); app.use (‘/’, rota); const port=process.env.PORT || 5000; app.listen (port, ()=> {console.log (`server is running on port $ {port}`);});
Roteamento de índice
Quando isso for feito, podemos seguir em frente e apontar nossas rotas para seus vários destinos no arquivo routes/index.js:
const express=require (‘express’); roteador const=express.Router (); const auth=require (‘./auth’); const createError=require (‘http-errors’) router.get (‘/’, (req, res)=> {res.send (‘Hello World!’);}); router.use (‘/auth’, auth); router.use (async (req, res, next)=> {next (createError.NotFound (‘Route not Found’))}) router.use ((err, req, res, next)=> {res.status ( err.status || 500).json ({status: false, mensagem: err.message})}) module.exports=router;
Se você perceber, estou solicitando o pacote http-errors em meu arquivo index.js. Isso ocorre porque irei usá-lo para interceptar erros e passá-los corretamente para o cliente como uma mensagem.
Para usar erros de http, você pode instalar usando:
npm install http-erros
Criando um serviço de autorização
Precisamos criar um arquivo de serviço para a comunicação entre nosso banco de dados e o controlador. Dentro do arquivo de serviço, vamos criar três funções: registrar, fazer login e todos, que irão registrar um novo usuário no banco de dados, obter as informações do usuário e fazer o login do usuário.
A função todos irá obter todos os usuários, o que só acontecerá se a solicitação tiver um token válido gerado durante o login ou registro.
Para começar, criaremos uma pasta chamada services, em seguida, criaremos um arquivo dentro da pasta services chamada auth. services.js. Em seguida, podemos criar nossa função de registro e instalar bcrypt e JWT para hashing de senha e geração de tokens.
Para instalar bcrypt e JWT, insira o comando abaixo em seu terminal e execute-o:
npm install bcryptjs jsonwebtoken
Depois de concluída a instalação, criaremos uma pasta chamada utils para adicionar nossa função JWT, que usaremos posteriormente para a geração de tokens.
Em nossa pasta utils, crie um arquivo denominado jwt.js e adicione as funções abaixo:
const jwt=require (‘jsonwebtoken’) const createError=require (‘http-errors’) require (‘dotenv’). config () const accessTokenSecret=process.env.ACCESS_TOKEN_SECRET module.exports={signAccessToken (carga útil) {return new Promise ((resolver, rejeitar)=> {jwt.sign ({payload}, accessTokenSecret, {}, (err, token)=> {if (err) { rejeitar (createError.InternalServerError ())} resolver (token)})})}, verifyAccessToken (token) {return new Promise ((resolve, rejeita)=> {jwt.verify (token, accessTokenSecret, (err, payload)=> {if (err) {const message=err.name==’JsonWebTokenError’?’Unauthorized’: err.message return rejeitar (createError.Unauthorized (message))} resolve (payload)})})}}
Então, em nosso arquivo.env, adicionamos nosso ACCESS_TOKEN_SECRET:
ACCESS_TOKEN_SECRET=
Podemos então voltar para auth.service.js e exigir nosso arquivo JWT junto com bcrypt e Prisma:
//services/auth.service.js const {PrismaClient}=require (‘@ prisma/cliente’); const prisma=novo PrismaClient (); require (‘dotenv’). config (); const bcrypt=require (‘bcryptjs’); const jwt=require (‘../utils/jwt’);
A seguir, crie nossa função de registro para adicionar um novo usuário ao banco de dados:
class AuthService {static async register (data) {const {email}=data; data.password=bcrypt.hashSync (data.password, 8); deixar usuário=prisma.user.create ({dados}) data.accessToken=esperar jwt.signAccessToken (usuário); dados de retorno; }} module.exports=authService;
Já que estamos nisso, também podemos adicionar nosso login e todas as funções:
//services/auth.service.js login assíncrono estático (dados) {const {email, password}=data; const user=await prisma.user.findUnique ({onde: {email}}); if (! user) {throw createError.NotFound (‘Usuário não registrado’)} const checkPassword=bcrypt.compareSync (senha, user.password) if (! checkPassword) throw createError.Unauthorized (‘Endereço de e-mail ou senha inválida’) excluir user.password const accessToken=await jwt.signAccessToken (user) return {… user, accessToken}} static async all () {const allUsers=await prisma.user.findMany (); return allUsers; }
Criando um controlador de autorização
Para obter nosso corpo de solicitação de nossas rotas, criaremos um controlador chamado controllers/auth.controller.js e adicionaremos nosso registro, login e todas as funções para comunicação nossos respectivos serviços:
const auth=require (‘../services/auth.service’); const createError=require (‘http-erros’); classe authController {registro estático=assíncrono (req, res, próximo)=> {try {const user=await auth.register (req.body); res.status (200).json ({status: true, mensagem:’Usuário criado com sucesso’, dados: usuário})} catch (e) {next (createError (e.statusCode, e.message))}} login estático=async (req, res, next)=> {try {const data=await auth.login (req.body) res.status (200).json ({status: true, message:”Account login bem-sucedido”, data} )} catch (e) {next (createError (e.statusCode, e.message))}} static all=async (req, res, next)=> {try {const users=await auth.all (); res.status (200).json ({status: true, mensagem:’Todos os usuários’, dados: usuários})} módulo catch (e) {next (createError (e.statusCode, e.message))}}}. exportações=authController;
Criando um guarda de autorização
Depois que o controlador foi adicionado, podemos adicionar nosso guarda, que irá proteger algumas rotas como todas de usuários que não estão logados. Este guarda irá verificar nossos tokens JWT emitidos e, se válido, permitirá que os usuários acessem essas rotas.
Crie um arquivo chamado middlewares/auth.js e adicione o código abaixo:
const jwt=require (‘../utils/jwt’) const createError=require (‘http-errors’) const auth=async (req, res, next)=> {if (! req.headers.authorization) {return next (createError.Unauthorized (‘token de acesso é necessário’))} const token=req.headers.authorization.split (”) [1] if (! token) {return next (createError.Unauthorized ())} await jwt.verifyAccessToken (token).then (user=> {req.user=user next ()}). catch (e=> {next (createError.Unauthorized (e.message))})} module.exports=auth;
O código acima pegará o token passado dos cabeçalhos adicionados nas rotas para verificar o token JWT e retornar um verdadeiro ou falso.
Criando uma rota de autorização
Agora estamos prontos com nosso controlador, serviço e guarda. Agora podemos abrir nosso arquivo routes/auth.js e adicionar nossas rotas:
const router=require (‘express’). Router (); const user=require (‘../controllers/auth.controller’); const auth=require (‘../middlewares/auth’);//registrar router.post (‘/’, user.register);//login router.post (‘/login’, user.login);//todos os usuários router.get (‘/’, auth, user.all); módulo.exportações=roteador;
O protetor de autenticação é adicionado a todas as rotas para restringir a rota de usuários sem tokens JWT.
Teste
Agora que terminamos de construir nosso aplicativo, podemos testar veja se está funcionando corretamente. Estaremos testando o registro, login e todas as rotas usando Postman .
Registre-se
Conforme visto acima na captura de tela do Postman, depois de inserir seu e-mail, nome e senha, você será registrado com sucesso como um novo usuário.
Login
Quando um usuário fornece o e-mail e a senha corretos, ele recebe um token de acesso que usará para fazer login. Isso é passado como um cabeçalho em solicitações que exigem tokens JWT no cabeçalho.
Todos os usuários
A rota all é uma rota protegida apenas para usuários com um token válido. Como você pode ver na captura de tela acima, o token é adicionado ao cabeçalho com a propriedade BearerToken.
Concluindo
Neste tutorial, passamos pelo processo de construção de um aplicativo autenticado do lado do servidor usando Prisma para o esquema de banco de dados e migração. Então, usando os dados migrados, podemos registrar e fazer login um usuário e criar rotas protegidas que aceitam tokens válidos.
Para uma base de código mais detalhada, você pode clonar o repositório e configurá-lo.