├── src ├── routes │ ├── index-route.js │ ├── order-route.js │ ├── customer-route.js │ └── product-route.js ├── config.js ├── services │ ├── email-service.js │ └── auth-service.js ├── repositories │ ├── order-repository.js │ ├── customer-repository.js │ └── product-repository.js ├── models │ ├── customer.js │ ├── product.js │ └── order.js ├── controllers │ ├── order-controller.js │ ├── customer-controller.js │ └── product-controller.js ├── validators │ └── fluent-validator.js └── app.js ├── package.json ├── .gitignore ├── bin └── server.js └── README.md /src/routes/index-route.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const express = require('express'); 4 | const router = express.Router(); 5 | 6 | router.get('/', (req, res, next) => { 7 | res.status(200).send({ 8 | title: "Node Store API", 9 | version: "0.0.2" 10 | }); 11 | }); 12 | 13 | module.exports = router; -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | global.SALT_KEY = 'f5b99242-6504-4ca3-90f2-05e78e5761ef'; 2 | global.EMAIL_TMPL = 'Olá, {0}, seja bem vindo à Node Store!'; 3 | 4 | module.exports = { 5 | connectionString: 'mongodb://balta:balta@ds032340.mlab.com:32340/ndstr', 6 | sendgridKey: 'SUA CHAVE', 7 | containerConnectionString: 'SUA CONNECTION STRING' 8 | } -------------------------------------------------------------------------------- /src/services/email-service.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var config = require('../config'); 3 | var sendgrid = require('sendgrid')(config.sendgridKey); 4 | 5 | exports.send = async (to, subject, body) => { 6 | sendgrid.send({ 7 | to: to, 8 | from: 'hello@balta.io', 9 | subject: subject, 10 | html: body 11 | }); 12 | } -------------------------------------------------------------------------------- /src/routes/order-route.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const express = require('express'); 4 | const router = express.Router(); 5 | const controller = require('../controllers/order-controller'); 6 | const authService = require('../services/auth-service'); 7 | 8 | router.get('/', authService.authorize, controller.get); 9 | router.post('/', authService.authorize, controller.post); 10 | 11 | module.exports = router; -------------------------------------------------------------------------------- /src/routes/customer-route.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const express = require('express'); 4 | const router = express.Router(); 5 | const controller = require('../controllers/customer-controller'); 6 | const authService = require('../services/auth-service'); 7 | 8 | router.post('/', controller.post); 9 | router.post('/authenticate', controller.authenticate); 10 | router.post('/refresh-token', authService.authorize, controller.refreshToken); 11 | 12 | module.exports = router; -------------------------------------------------------------------------------- /src/repositories/order-repository.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const mongoose = require('mongoose'); 3 | const Order = mongoose.model('Order'); 4 | 5 | exports.get = async(data) => { 6 | var res = await Order 7 | .find({}, 'number status customer items') 8 | .populate('customer', 'name') 9 | .populate('items.product', 'title'); 10 | return res; 11 | } 12 | 13 | exports.create = async(data) => { 14 | var order = new Order(data); 15 | await order.save(); 16 | } -------------------------------------------------------------------------------- /src/repositories/customer-repository.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const mongoose = require('mongoose'); 3 | const Customer = mongoose.model('Customer'); 4 | 5 | exports.create = async(data) => { 6 | var customer = new Customer(data); 7 | await customer.save(); 8 | } 9 | 10 | exports.authenticate = async(data) => { 11 | const res = await Customer.findOne({ 12 | email: data.email, 13 | password: data.password 14 | }); 15 | return res; 16 | } 17 | 18 | exports.getById = async(id) => { 19 | const res = await Customer.findById(id); 20 | return res; 21 | } -------------------------------------------------------------------------------- /src/models/customer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | 6 | const schema = new Schema({ 7 | name: { 8 | type: String, 9 | required: true 10 | }, 11 | email: { 12 | type: String, 13 | required: true 14 | }, 15 | password: { 16 | type: String, 17 | required: true 18 | }, 19 | roles: [{ 20 | type: String, 21 | required: true, 22 | enum: ['user', 'admin'], 23 | default: 'user' 24 | }] 25 | }); 26 | 27 | module.exports = mongoose.model('Customer', schema); -------------------------------------------------------------------------------- /src/routes/product-route.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const express = require('express'); 4 | const router = express.Router(); 5 | const controller = require('../controllers/product-controller'); 6 | const authService = require('../services/auth-service'); 7 | 8 | router.get('/', controller.get); 9 | router.get('/:slug', controller.getBySlug); 10 | router.get('/admin/:id', controller.getById); 11 | router.get('/tags/:tag', controller.getByTag); 12 | router.post('/', authService.isAdmin, controller.post); 13 | router.put('/:id', authService.isAdmin, controller.put); 14 | router.delete('/', authService.isAdmin, controller.delete); 15 | 16 | module.exports = router; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-str", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node ./bin/server.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "azure-storage": "^2.1.0", 14 | "body-parser": "^1.17.2", 15 | "debug": "^2.6.8", 16 | "express": "^4.15.3", 17 | "guid": "0.0.12", 18 | "http": "0.0.0", 19 | "jsonwebtoken": "^7.4.0", 20 | "md5": "^2.2.1", 21 | "mongoose": "^4.11.0", 22 | "sendgrid": "^2.0.0" 23 | }, 24 | "devDependencies": { 25 | "nodemon": "^1.11.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/models/product.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | 6 | const schema = new Schema({ 7 | title: { 8 | type: String, 9 | required: true, 10 | trim: true 11 | }, 12 | slug: { 13 | type: String, 14 | required: [true, 'O slug é obrigatório'], 15 | trim: true, 16 | index: true, 17 | unique: true 18 | }, 19 | description: { 20 | type: String, 21 | required: true 22 | }, 23 | price: { 24 | type: Number, 25 | required: true 26 | }, 27 | active: { 28 | type: Boolean, 29 | required: true, 30 | default: true 31 | }, 32 | tags: [{ 33 | type: String, 34 | required: true 35 | }], 36 | image: { 37 | type: String, 38 | required: true, 39 | trim: true 40 | } 41 | }); 42 | 43 | module.exports = mongoose.model('Product', schema); -------------------------------------------------------------------------------- /src/models/order.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | 6 | const schema = new Schema({ 7 | customer: { 8 | type: mongoose.Schema.Types.ObjectId, 9 | ref: 'Customer' 10 | }, 11 | number: { 12 | type: String, 13 | required: true 14 | }, 15 | createDate: { 16 | type: Date, 17 | required: true, 18 | default: Date.now 19 | }, 20 | status: { 21 | type: String, 22 | required: true, 23 | enum: ['created', 'done'], 24 | default: 'created' 25 | }, 26 | items: [{ 27 | quantity: { 28 | type: Number, 29 | required: true, 30 | default: 1 31 | }, 32 | price: { 33 | type: Number, 34 | required: true 35 | }, 36 | product: { 37 | type: mongoose.Schema.Types.ObjectId, 38 | ref: 'Product' 39 | } 40 | }], 41 | }); 42 | 43 | module.exports = mongoose.model('Order', schema); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | -------------------------------------------------------------------------------- /src/controllers/order-controller.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const repository = require('../repositories/order-repository'); 4 | const guid = require('guid'); 5 | const authService = require('../services/auth-service'); 6 | 7 | exports.get = async(req, res, next) => { 8 | try { 9 | var data = await repository.get(); 10 | res.status(200).send(data); 11 | } catch (e) { 12 | res.status(500).send({ 13 | message: 'Falha ao processar sua requisição' 14 | }); 15 | } 16 | } 17 | 18 | exports.post = async(req, res, next) => { 19 | try { 20 | const token = req.body.token || req.query.token || req.headers['x-access-token']; 21 | const data = await authService.decodeToken(token); 22 | 23 | await repository.create({ 24 | customer: data.id, 25 | number: guid.raw().substring(0, 6), 26 | items: req.body.items 27 | }); 28 | res.status(201).send({ 29 | message: 'Pedido cadastrado com sucesso!' 30 | }); 31 | } catch (e) { 32 | console.log(e); 33 | res.status(500).send({ 34 | message: 'Falha ao processar sua requisição' 35 | }); 36 | } 37 | }; -------------------------------------------------------------------------------- /src/validators/fluent-validator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | let errors = []; 4 | 5 | function ValidationContract() { 6 | errors = []; 7 | } 8 | 9 | ValidationContract.prototype.isRequired = (value, message) => { 10 | if (!value || value.length <= 0) 11 | errors.push({ message: message }); 12 | } 13 | 14 | ValidationContract.prototype.hasMinLen = (value, min, message) => { 15 | if (!value || value.length < min) 16 | errors.push({ message: message }); 17 | } 18 | 19 | ValidationContract.prototype.hasMaxLen = (value, max, message) => { 20 | if (!value || value.length > max) 21 | errors.push({ message: message }); 22 | } 23 | 24 | ValidationContract.prototype.isFixedLen = (value, len, message) => { 25 | if (value.length != len) 26 | errors.push({ message: message }); 27 | } 28 | 29 | ValidationContract.prototype.isEmail = (value, message) => { 30 | var reg = new RegExp(/^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/); 31 | if (!reg.test(value)) 32 | errors.push({ message: message }); 33 | } 34 | 35 | ValidationContract.prototype.errors = () => { 36 | return errors; 37 | } 38 | 39 | ValidationContract.prototype.clear = () => { 40 | errors = []; 41 | } 42 | 43 | ValidationContract.prototype.isValid = () => { 44 | return errors.length == 0; 45 | } 46 | 47 | module.exports = ValidationContract; -------------------------------------------------------------------------------- /bin/server.js: -------------------------------------------------------------------------------- 1 | const app = require('../src/app'); 2 | const debug = require('debug')('balta:server'); 3 | const http = require('http'); 4 | 5 | const port = normalizePort(process.env.PORT || '3000'); 6 | app.set('port', port); 7 | 8 | const server = http.createServer(app); 9 | 10 | server.listen(port); 11 | server.on('error', onError); 12 | server.on('listening', onListening); 13 | console.log('API rodando na porta ' + port); 14 | 15 | function normalizePort(val) { 16 | const port = parseInt(val, 10); 17 | 18 | if (isNaN(port)) { 19 | return val; 20 | } 21 | 22 | if (port >= 0) { 23 | return port; 24 | } 25 | 26 | return false; 27 | } 28 | 29 | function onError(error) { 30 | if (error.syscall !== 'listen') { 31 | throw error; 32 | } 33 | 34 | const bind = typeof port === 'string' 35 | ? 'Pipe ' + port 36 | : 'Port ' + port; 37 | 38 | switch (error.code) { 39 | case 'EACCES': 40 | console.error(bind + ' requires elevated privileges'); 41 | process.exit(1); 42 | break; 43 | case 'EADDRINUSE': 44 | console.error(bind + ' is already in use'); 45 | process.exit(1); 46 | break; 47 | default: 48 | throw error; 49 | } 50 | } 51 | 52 | function onListening() { 53 | const addr = server.address(); 54 | const bind = typeof addr === 'string' 55 | ? 'pipe ' + addr 56 | : 'port ' + addr.port; 57 | debug('Listening on ' + bind); 58 | } -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const express = require('express'); 4 | const bodyParser = require('body-parser'); 5 | const mongoose = require('mongoose'); 6 | const config = require('./config'); 7 | 8 | const app = express(); 9 | const router = express.Router(); 10 | 11 | // Connecta ao banco 12 | mongoose.connect(config.connectionString); 13 | 14 | // Carrega os Models 15 | const Product = require('./models/product'); 16 | const Customer = require('./models/customer'); 17 | const Order = require('./models/order'); 18 | 19 | // Carrega as Rotas 20 | const indexRoute = require('./routes/index-route'); 21 | const productRoute = require('./routes/product-route'); 22 | const customerRoute = require('./routes/customer-route'); 23 | const orderRoute = require('./routes/order-route'); 24 | 25 | app.use(bodyParser.json({ 26 | limit: '5mb' 27 | })); 28 | app.use(bodyParser.urlencoded({ 29 | extended: false 30 | })); 31 | 32 | // Habilita o CORS 33 | app.use(function (req, res, next) { 34 | res.header('Access-Control-Allow-Origin', '*'); 35 | res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, x-access-token'); 36 | res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); 37 | next(); 38 | }); 39 | 40 | app.use('/', indexRoute); 41 | app.use('/products', productRoute); 42 | app.use('/customers', customerRoute); 43 | app.use('/orders', orderRoute); 44 | 45 | module.exports = app; -------------------------------------------------------------------------------- /src/repositories/product-repository.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const mongoose = require('mongoose'); 3 | const Product = mongoose.model('Product'); 4 | 5 | exports.get = async() => { 6 | const res = await Product.find({ 7 | active: true 8 | }, 'title price slug'); 9 | return res; 10 | } 11 | 12 | exports.getBySlug = async(slug) => { 13 | const res = await Product 14 | .findOne({ 15 | slug: slug, 16 | active: true 17 | }, 'title description price slug tags'); 18 | return res; 19 | } 20 | 21 | exports.getById = async(id) => { 22 | const res = await Product 23 | .findById(id); 24 | return res; 25 | } 26 | 27 | exports.getByTag = async(tag) => { 28 | const res = Product 29 | .find({ 30 | tags: tag, 31 | active: true 32 | }, 'title description price slug tags'); 33 | return res; 34 | } 35 | 36 | exports.create = async(data) => { 37 | var product = new Product(data); 38 | await product.save(); 39 | } 40 | 41 | exports.update = async(id, data) => { 42 | await Product 43 | .findByIdAndUpdate(id, { 44 | $set: { 45 | title: data.title, 46 | description: data.description, 47 | price: data.price, 48 | slug: data.slug 49 | } 50 | }); 51 | } 52 | 53 | exports.delete = async(id) => { 54 | await Product 55 | .findOneAndRemove(id); 56 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 1972 - Criando APIs com NodeJs 2 | 3 | ### LINK PARA OS VÍDEOS 4 | Você pode assistir os vídeos deste curso sendo um assinante do site http://balta.io. 5 | 6 | http://player.balta.io/#/courses/1972 7 | 8 | ### Sumário 9 | Neste curso vamos unir a popularidade das APIs com a popularidade do JavaScript criando uma API completa com NodeJs, passando pelos principais pontos que você precisa conhecer para colocar seu projeto em produção. 10 | 11 | ### Conteúdo Programático 12 | * Instalação Node, NPM e VS Code 13 | * npm init e instalação dos pacotes 14 | * Criando um servidor Web 15 | * Normalizando a porta 16 | * Gerenciando Erros do Servidor 17 | * Iniciando o Debug 18 | * Separando o Servidor 19 | * Configurando o NPM Start 20 | * Nodemon 21 | * CRUD REST 22 | * Rotas 23 | * Controllers 24 | * MongoDb Setup 25 | * Mongooose 26 | * Models 27 | * Criando um Produto 28 | * Listando os Produtos 29 | * Listando um Produto pelo slug 30 | * Listando um Produto pelo Id 31 | * Listando os Produtos de uma tag 32 | * Atualizando um produto 33 | * Excluindo um produto 34 | * Validações 35 | * Repositórios 36 | * Async/Await 37 | * Revisitando os Models: Customer 38 | * Revisitando os Models: Order 39 | * Revisitando os Models: OrderItems 40 | * Revisitando os Controllers: Customer 41 | * Revisitando os Controllers: Order 42 | * Arquivo de Configurações 43 | * Enviando E-mail de Boas Vindas 44 | * Upload da Imagem do Produto 45 | * Autenticação 46 | * Autorização 47 | * Habilitando CORS 48 | * Publicando a API 49 | 50 | -------------------------------------------------------------------------------- /src/services/auth-service.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const jwt = require('jsonwebtoken'); 3 | 4 | exports.generateToken = async (data) => { 5 | return jwt.sign(data, global.SALT_KEY, { expiresIn: '1d' }); 6 | } 7 | 8 | exports.decodeToken = async (token) => { 9 | var data = await jwt.verify(token, global.SALT_KEY); 10 | return data; 11 | } 12 | 13 | exports.authorize = function (req, res, next) { 14 | var token = req.body.token || req.query.token || req.headers['x-access-token']; 15 | 16 | if (!token) { 17 | res.status(401).json({ 18 | message: 'Acesso Restrito' 19 | }); 20 | } else { 21 | jwt.verify(token, global.SALT_KEY, function (error, decoded) { 22 | if (error) { 23 | res.status(401).json({ 24 | message: 'Token Inválido' 25 | }); 26 | } else { 27 | next(); 28 | } 29 | }); 30 | } 31 | }; 32 | 33 | exports.isAdmin = function (req, res, next) { 34 | var token = req.body.token || req.query.token || req.headers['x-access-token']; 35 | 36 | if (!token) { 37 | res.status(401).json({ 38 | message: 'Token Inválido' 39 | }); 40 | } else { 41 | jwt.verify(token, global.SALT_KEY, function (error, decoded) { 42 | if (error) { 43 | res.status(401).json({ 44 | message: 'Token Inválido' 45 | }); 46 | } else { 47 | if (decoded.roles.includes('admin')) { 48 | next(); 49 | } else { 50 | res.status(403).json({ 51 | message: 'Esta funcionalidade é restrita para administradores' 52 | }); 53 | } 54 | } 55 | }); 56 | } 57 | }; -------------------------------------------------------------------------------- /src/controllers/customer-controller.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const ValidationContract = require('../validators/fluent-validator'); 4 | const repository = require('../repositories/customer-repository'); 5 | const md5 = require('md5'); 6 | const authService = require('../services/auth-service'); 7 | 8 | const emailService = require('../services/email-service'); 9 | 10 | exports.post = async(req, res, next) => { 11 | let contract = new ValidationContract(); 12 | contract.hasMinLen(req.body.name, 3, 'O nome deve conter pelo menos 3 caracteres'); 13 | contract.isEmail(req.body.email, 'E-mail inválido'); 14 | contract.hasMinLen(req.body.password, 6, 'A senha deve conter pelo menos 6 caracteres'); 15 | 16 | // Se os dados forem inválidos 17 | if (!contract.isValid()) { 18 | res.status(400).send(contract.errors()).end(); 19 | return; 20 | } 21 | 22 | try { 23 | await repository.create({ 24 | name: req.body.name, 25 | email: req.body.email, 26 | password: md5(req.body.password + global.SALT_KEY), 27 | roles: ["user"] 28 | }); 29 | 30 | emailService.send( 31 | req.body.email, 32 | 'Bem vindo ao Node Store', 33 | global.EMAIL_TMPL.replace('{0}', req.body.name)); 34 | 35 | res.status(201).send({ 36 | message: 'Cliente cadastrado com sucesso!' 37 | }); 38 | } catch (e) { 39 | res.status(500).send({ 40 | message: 'Falha ao processar sua requisição' 41 | }); 42 | } 43 | }; 44 | 45 | exports.authenticate = async(req, res, next) => { 46 | try { 47 | const customer = await repository.authenticate({ 48 | email: req.body.email, 49 | password: md5(req.body.password + global.SALT_KEY) 50 | }); 51 | 52 | if (!customer) { 53 | res.status(404).send({ 54 | message: 'Usuário ou senha inválidos' 55 | }); 56 | return; 57 | } 58 | 59 | const token = await authService.generateToken({ 60 | id: customer._id, 61 | email: customer.email, 62 | name: customer.name, 63 | roles: customer.roles 64 | }); 65 | 66 | res.status(201).send({ 67 | token: token, 68 | data: { 69 | email: customer.email, 70 | name: customer.name 71 | } 72 | }); 73 | } catch (e) { 74 | res.status(500).send({ 75 | message: 'Falha ao processar sua requisição' 76 | }); 77 | } 78 | }; 79 | 80 | exports.refreshToken = async(req, res, next) => { 81 | try { 82 | const token = req.body.token || req.query.token || req.headers['x-access-token']; 83 | const data = await authService.decodeToken(token); 84 | 85 | const customer = await repository.getById(data.id); 86 | 87 | if (!customer) { 88 | res.status(404).send({ 89 | message: 'Cliente não encontrado' 90 | }); 91 | return; 92 | } 93 | 94 | const tokenData = await authService.generateToken({ 95 | id: customer._id, 96 | email: customer.email, 97 | name: customer.name, 98 | roles: customer.roles 99 | }); 100 | 101 | res.status(201).send({ 102 | token: token, 103 | data: { 104 | email: customer.email, 105 | name: customer.name 106 | } 107 | }); 108 | } catch (e) { 109 | res.status(500).send({ 110 | message: 'Falha ao processar sua requisição' 111 | }); 112 | } 113 | }; -------------------------------------------------------------------------------- /src/controllers/product-controller.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const ValidationContract = require('../validators/fluent-validator'); 4 | const repository = require('../repositories/product-repository'); 5 | const azure = require('azure-storage'); 6 | const guid = require('guid'); 7 | var config = require('../config'); 8 | 9 | exports.get = async(req, res, next) => { 10 | try { 11 | var data = await repository.get(); 12 | res.status(200).send(data); 13 | } catch (e) { 14 | res.status(500).send({ 15 | message: 'Falha ao processar sua requisição' 16 | }); 17 | } 18 | } 19 | 20 | exports.getBySlug = async(req, res, next) => { 21 | try { 22 | var data = await repository.getBySlug(req.params.slug); 23 | res.status(200).send(data); 24 | } catch (e) { 25 | res.status(500).send({ 26 | message: 'Falha ao processar sua requisição' 27 | }); 28 | } 29 | } 30 | 31 | exports.getById = async(req, res, next) => { 32 | try { 33 | var data = await repository.getById(req.params.id); 34 | res.status(200).send(data); 35 | } catch (e) { 36 | res.status(500).send({ 37 | message: 'Falha ao processar sua requisição' 38 | }); 39 | } 40 | } 41 | 42 | exports.getByTag = async(req, res, next) => { 43 | try { 44 | const data = await repository.getByTag(req.params.tag); 45 | res.status(200).send(data); 46 | } catch (e) { 47 | res.status(500).send({ 48 | message: 'Falha ao processar sua requisição' 49 | }); 50 | } 51 | } 52 | 53 | exports.post = async(req, res, next) => { 54 | let contract = new ValidationContract(); 55 | contract.hasMinLen(req.body.title, 3, 'O título deve conter pelo menos 3 caracteres'); 56 | contract.hasMinLen(req.body.slug, 3, 'O título deve conter pelo menos 3 caracteres'); 57 | contract.hasMinLen(req.body.description, 3, 'O título deve conter pelo menos 3 caracteres'); 58 | 59 | // Se os dados forem inválidos 60 | if (!contract.isValid()) { 61 | res.status(400).send(contract.errors()).end(); 62 | return; 63 | } 64 | 65 | try { 66 | // Cria o Blob Service 67 | // const blobSvc = azure.createBlobService(config.containerConnectionString); 68 | 69 | let filename = guid.raw().toString() + '.jpg'; 70 | let rawdata = req.body.image; 71 | let matches = rawdata.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/); 72 | let type = matches[1]; 73 | let buffer = new Buffer(matches[2], 'base64'); 74 | 75 | // Salva a imagem 76 | await blobSvc.createBlockBlobFromText('product-images', filename, buffer, { 77 | contentType: type 78 | }, function (error, result, response) { 79 | if (error) { 80 | filename = 'default-product.png' 81 | } 82 | }); 83 | 84 | await repository.create({ 85 | title: req.body.title, 86 | slug: req.body.slug, 87 | description: req.body.description, 88 | price: req.body.price, 89 | active: true, 90 | tags: req.body.tags, 91 | image: 'https://nodestr.blob.core.windows.net/product-images/' + filename 92 | }); 93 | res.status(201).send({ 94 | message: 'Produto cadastrado com sucesso!' 95 | }); 96 | } catch (e) { 97 | console.log(e); 98 | res.status(500).send({ 99 | message: 'Falha ao processar sua requisição' 100 | }); 101 | } 102 | }; 103 | 104 | exports.put = async(req, res, next) => { 105 | try { 106 | await repository.update(req.params.id, req.body); 107 | res.status(200).send({ 108 | message: 'Produto atualizado com sucesso!' 109 | }); 110 | } catch (e) { 111 | res.status(500).send({ 112 | message: 'Falha ao processar sua requisição' 113 | }); 114 | } 115 | }; 116 | 117 | exports.delete = async(req, res, next) => { 118 | try { 119 | await repository.delete(req.body.id) 120 | res.status(200).send({ 121 | message: 'Produto removido com sucesso!' 122 | }); 123 | } catch (e) { 124 | res.status(500).send({ 125 | message: 'Falha ao processar sua requisição' 126 | }); 127 | } 128 | }; --------------------------------------------------------------------------------