Skip to content
This repository has been archived by the owner on Aug 18, 2022. It is now read-only.

Commit

Permalink
Primeiro Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
herbertvpb committed Apr 9, 2019
0 parents commit 79a5b40
Show file tree
Hide file tree
Showing 34 changed files with 4,614 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
root = true

[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
14 changes: 14 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
NODE_ENV=development
APP_SECRET=GoNode03

DB_URL=mongodb://localhost:27017/gonode03

MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USER=1e3335b21f2028
MAIL_PASS=85b18f30734bfe

REDIS_HOST=127.0.0.1
REDIS_PORT=6379

SENTRY_DSN=https://[email protected]/1425597
16 changes: 16 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"env": {
"commonjs": true,
"es6": true,
"node": true
},
"extends": "standard",
"globals": {
"Atomics": "writable",
"SharedArrayBuffer": "writable"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {}
}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
tmp
node_modules
36 changes: 36 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "modulo3",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "nodemon src/index.js"
},
"dependencies": {
"@sentry/node": "^4.6.5",
"bcryptjs": "^2.4.3",
"dotenv": "^7.0.0",
"express": "^4.16.4",
"express-async-handler": "^1.1.4",
"express-handlebars": "^3.0.2",
"express-validation": "^1.0.2",
"joi": "^14.3.1",
"jsonwebtoken": "^8.5.1",
"kue": "^0.11.6",
"mongoose": "^5.4.19",
"mongoose-paginate": "^5.0.3",
"nodemailer": "^6.0.0",
"nodemailer-express-handlebars": "^3.0.0",
"require-dir": "^1.2.0",
"youch": "^2.0.10"
},
"devDependencies": {
"eslint": "^5.15.3",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"nodemon": "^1.18.10"
}
}
62 changes: 62 additions & 0 deletions src/app/controllers/AdController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
const Ad = require('../models/Ad')

class AdController {
async index (req, res) {
const filters = {
purchasedBy: null
}

if (req.query.price_min || req.query.price_max) {
filters.price = {}

if (req.query.price_min) {
filters.price.$gte = req.query.price_min
}

if (req.query.price_max) {
filters.price.$lte = req.query.price_max
}
}

if (req.query.title) {
filters.title = new RegExp(req.query.title, 'i')
}

const ads = await Ad.paginate(filters, {
page: req.query.page || 1,
limit: 20,
populate: ['author'],
sort: '-createdAt'
})

return res.json(ads)
}

async show (req, res) {
const ad = await Ad.findById(req.params.id)

return res.json(ad)
}

async store (req, res) {
const ad = await Ad.create({ ...req.body, author: req.userId })

return res.json(ad)
}

async update (req, res) {
const ad = await Ad.findByIdAndUpdate(req.params.id, req.body, {
new: true
})

return res.json(ad)
}

async destroy (req, res) {
await Ad.findByIdAndDelete(req.params.id)

return res.send()
}
}

module.exports = new AdController()
32 changes: 32 additions & 0 deletions src/app/controllers/ApproveController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const Purchase = require('../models/Purchase')

class ApproveController {
async update (req, res) {
const { id } = req.params

const { ad } = await Purchase.findById(id).populate({
path: 'ad',
populate: {
path: 'author'
}
})

if (!ad.author._id.equals(req.userId)) {
return res.status(401).json({ error: "You're not the ad author" })
}

if (ad.purchaseBy) {
return res
.status(400)
.json({ error: 'This ad had already been purchased' })
}

ad.purchaseBy = id

await ad.save()

return res.json(ad)
}
}

module.exports = new ApproveController()
30 changes: 30 additions & 0 deletions src/app/controllers/PurchaseController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const Ad = require('../models/Ad')
const Purchase = require('../models/Purchase')
const User = require('../models/User')
const PurchaseMail = require('../jobs/PurchaseMail')
const Queue = require('../services/Queue')

class PurchaseController {
async store (req, res) {
const { ad, content } = req.body

const purchaseAd = await Ad.findById(ad).populate('author')
const user = await User.findById(req.userId)

const purchase = await Purchase.create({
content,
ad,
user: user._id
})

Queue.create(PurchaseMail.key, {
ad: purchaseAd,
user,
content
}).save()

return res.json(purchase)
}
}

module.exports = new PurchaseController()
21 changes: 21 additions & 0 deletions src/app/controllers/SessionController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const User = require('../models/User')

class SessionController {
async store (req, res) {
const { email, password } = req.body

const user = await User.findOne({ email })

if (!user) {
return res.status(400).json({ error: 'User not found' })
}

if (!(await user.compareHash(password))) {
return res.status(400).json({ error: 'Invalid password' })
}

return res.json({ user, token: User.generateToken(user) })
}
}

module.exports = new SessionController()
17 changes: 17 additions & 0 deletions src/app/controllers/UserController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const User = require('../models/User')

class UserController {
async store (req, res) {
const { email } = req.body

if (await User.findOne({ email })) {
return res.status(400).json({ error: 'User already exists' })
}

const user = await User.create(req.body)

return res.json(user)
}
}

module.exports = new UserController()
1 change: 1 addition & 0 deletions src/app/controllers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('require-dir')()
23 changes: 23 additions & 0 deletions src/app/jobs/PurchaseMail.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const Mail = require('../services/Mail')

class PurchaseMail {
get key () {
return 'PurchaseMail'
}

async handle (job, done) {
const { ad, user, content } = job.data

await Mail.sendMail({
from: '"Larissa de Paula" <lalapaula>@gmail.com>',
to: ad.author.email,
subject: `Solicitação de compra: ${ad.title}`,
template: 'purchase',
context: { user, content, ad }
})

return done()
}
}

module.exports = new PurchaseMail()
1 change: 1 addition & 0 deletions src/app/jobs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('require-dir')()
23 changes: 23 additions & 0 deletions src/app/middlewares/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const jwt = require('jsonwebtoken')
const authConfig = require('../../config/auth')
const { promisify } = require('util')

module.exports = async (req, res, next) => {
const authHeader = req.headers.authorization

if (!authHeader) {
return res.status(401).json({ error: 'Token not provided' })
}

const [, token] = authHeader.split(' ')

try {
const decoded = await promisify(jwt.verify)(token, authConfig.secret)

req.userId = decoded.id

return next()
} catch (err) {
return res.status(401).json({ error: 'Token invalid' })
}
}
34 changes: 34 additions & 0 deletions src/app/models/Ad.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const mongoose = require('mongoose')
const mongoosePaginate = require('mongoose-paginate')

const Ad = new mongoose.Schema({
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
price: {
type: Number,
required: true
},
purchaseBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Purchase'
},
createdAt: {
type: Date,
default: Date.now
}
})

Ad.plugin(mongoosePaginate)

module.exports = mongoose.model('Ad', Ad)
24 changes: 24 additions & 0 deletions src/app/models/Purchase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const mongoose = require('mongoose')

const Purchase = new mongoose.Schema({
content: {
type: String,
required: true
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
ad: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Ad',
required: true
},
createdAt: {
type: Date,
default: Date.now
}
})

module.exports = mongoose.model('Purchase', Purchase)
Loading

0 comments on commit 79a5b40

Please sign in to comment.