Skip to content
This repository was archived by the owner on Jul 30, 2018. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
!app
!bootstrap
!config
!services
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@ DB_PORT=27017
DB_NAME=
DB_USERNAME=arrecadar
DB_PASSWORD=secret

MAIL_PORT=
MAIL_HOST=
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_SENDER=
10 changes: 3 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# CHANGE LOG

## Unreleased
- [ ] Auth: add token refresh
- [ ] Register: add email validations
- [ ] Resources: add paginations
- [ ] Resources: index routes return `error not found` when needs to return `{ data: [] }`

### Add
- [x] Users.
Expand All @@ -15,9 +11,9 @@
- [x] Login with email and password.
- [x] JWT authorization.
- [ ] Token Refresh
- [ ] Register
- When register send an email confirmation.
- [ ] resources: add pagination.
- [x] Register
- [x] When register send an email confirmation.
- [ ] Resources: add pagination.
- [x] Added public routes
- [x] GET /ongs
- [x] GET /ongs/:id
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ COPY ./server.js /api/server.js
COPY ./app /api/app
COPY ./bootstrap /api/bootstrap
COPY ./config /api/config
COPY ./services /api/services

WORKDIR /api

Expand Down
17 changes: 15 additions & 2 deletions app/Authentication/controller.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
const passport = require('passport')
const { handleUnauthorized } = require('../Responses')
const Token = require('./token')
const trasnformUser = require('../Transformers/user')
const UserRepository = require('../Users/repository')
const { handleUnauthorized, handleResponse } = require('../Responses')

const login = (request, response) => (
passport.authenticate('local', (error, user) => {
Expand All @@ -13,6 +16,16 @@ const login = (request, response) => (
})(request, response)
)

const confirmation = (request, response) => {
const { user } = Token.decode(request.query.token, ['user'])

UserRepository
.save(user, { activated: true })
.then(trasnformUser.withToken)
.then(handleResponse(response))
}

module.exports = {
login
login,
confirmation
}
1 change: 1 addition & 0 deletions app/Authentication/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ const Router = require('express').Router()
const controller = require('./controller')

Router.post('/login', controller.login)
Router.get('/confirmation', controller.confirmation)

module.exports = Router
14 changes: 14 additions & 0 deletions app/Authentication/token.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const jwt = require('jsonwebtoken')
const { key } = require('../../config/app')

const create = (data, expiresIn) => jwt.sign(data, key, {
expiresIn,
algorithm: 'HS256'
})

const decode = token => jwt.decode(token)

module.exports = {
create: create,
decode: decode
}
2 changes: 1 addition & 1 deletion app/Organizations/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { authorizeWithJwt } = require('../Authentication/middleware')
const controller = require('./controller')
const request = require('./request')

Router.get('/', authorizeWithJwt, controller.index)
Router.get('/', controller.index)
Router.get('/:id', controller.show)
Router.put('/:id', authorizeWithJwt, controller.save)
Router.post('/', authorizeWithJwt, request, controller.store)
Expand Down
2 changes: 1 addition & 1 deletion app/Responses.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const handleResponse = response => result =>
const handleError = response => error =>
error.kind === 'ObjectId'
? notFound(response)
: responseWithInternalServerError(response)
: responseWithInternalServerError(response)(error)

const handleUnauthorized = response => (
response.status(401).json({
Expand Down
30 changes: 30 additions & 0 deletions app/Transformers/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const { applySpec, prop } = require('ramda')
const Token = require('../Authentication/token')

const createUsertToken = ({ id }) => Token.create({ user: id }, '15min')

const withToken = applySpec({
data: {
id: prop('id'),
name: prop('name'),
email: prop('email'),
token: createUsertToken,
created_at: prop('created_at'),
updated_at: prop('updated_at')
}
})

const transform = applySpec({
data: {
id: prop('id'),
name: prop('name'),
email: prop('email'),
created_at: prop('created_at'),
updated_at: prop('updated_at')
}
})

module.exports = {
withToken,
transform
}
24 changes: 18 additions & 6 deletions app/Users/controller.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
const {
Controller,
Transform
} = require('@anarklab/expressive-controller')
const { Controller, Transform } = require('@anarklab/expressive-controller')
const Repository = require('./repository')
const SendEmail = require('../../services/mail/send')
const { transform: transformUser } = require('../Transformers/user')
const { handleError, handleResponse } = require('../Responses')

const Repository = require('./repository')
const controller = Controller(Repository)

const show = (request, response) => {
Expand All @@ -17,7 +16,20 @@ const show = (request, response) => {
.catch(handleError(response))
}

const store = (request, response) => {
Repository
.create(request.body)
.then(user => {
SendEmail.confirmation(user)
return user
})
.then(transformUser)
.then(handleResponse(response))
.catch(error => handleError(response)([error.message]))
}

module.exports = {
...controller,
show
show,
store
}
4 changes: 4 additions & 0 deletions app/Users/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ const UserScheme = new Schema({
type: String,
required: true,
select: false
},
activated: {
type: Boolean,
default: false
}
}, {
timestamps: {
Expand Down
2 changes: 1 addition & 1 deletion app/Users/repository.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const handleSaveErrors = error => {
const find = () => User.find()
const findOne = id => User.findById(id)
const create = user => new User(user).save().catch(handleSaveErrors)
const save = (id, data) => User.findByIdAndUpdate(id, data).catch(handleSaveErrors)
const save = (id, data) => User.findByIdAndUpdate(id, data, {new: true}).catch(handleSaveErrors)
const remove = id => User.findByIdAndRemove(id)

module.exports = {
Expand Down
1 change: 1 addition & 0 deletions app/Users/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ const request = require('./request')

Router.get('/:id', authorizeWithJwt, users.show)
Router.post('/', request, users.store)
Router.get('/', authorizeWithJwt, users.index)

module.exports = Router
2 changes: 1 addition & 1 deletion bootstrap/strategies/local.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const { key } = require('../../config/app')

const auth = (email, password, done) => (
User
.findOne({ email })
.findOne({ email, activated: true })
.select('+password')
.then(validatePasswordAndGetUser(password))
.then(transformUser)
Expand Down
7 changes: 7 additions & 0 deletions config/mail.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
host: process.env.MAIL_HOST,
port: process.env.MAIL_PORT,
username: process.env.MAIL_USERNAME,
password: process.env.MAIL_PASSWORD,
sender: process.env.MAIL_SENDER
}
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ services:
- ./app:/api/app
- ./bootstrap:/api/bootstrap
- ./config:/api/config
- ./services:/api/services

base-tests:
extends: base
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"jsonwebtoken": "^8.2.1",
"mongoose-paginate": "^5.0.3",
"morgan": "^1.9.0",
"nodemailer": "^4.6.5",
"passport": "^0.4.0",
"passport-jwt": "^4.0.0",
"passport-local": "^1.0.0",
Expand Down
34 changes: 34 additions & 0 deletions services/mail/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const nodemailer = require('nodemailer')
const {
host,
username,
password,
sender
} = require('../../config/mail')

const transporter = nodemailer.createTransport({
service: host,
auth: {
user: username,
pass: password
}
})

const defaultMailOptions = {
from: sender
}

const dispatch = mail => transporter.sendMail({
...defaultMailOptions,
...mail
}, error => {
if (error) {
throw error
}

return true
})

module.exports = {
dispatch
}
20 changes: 20 additions & 0 deletions services/mail/send.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const Token = require('../../app/Authentication/token')
const Mail = require('./index')

const confirmation = user => {
const token = Token.create({ user: user.id }, '1day')
const mail = {
to: user.email,
subject: 'Confirme seu cadastro',
html: `
<h3>Olá ${user.name}.</h3>
<p>Você pode confirmar seu registro accesando este <a href="http://localhost:3000/confirmation?token=${token}">link.</a></p>
`
}

return Mail.dispatch(mail)
}

module.exports = {
confirmation
}
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3255,6 +3255,10 @@ node-pre-gyp@^0.6.39:
tar "^2.2.1"
tar-pack "^3.4.0"

nodemailer@^4.6.5:
version "4.6.5"
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-4.6.5.tgz#306ce18c4543f3f06e5f76665d3cb6277f872f53"

nodemon@^1.14.12:
version "1.17.3"
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.17.3.tgz#3b0bbc2ee05ccb43b1aef15ba05c63c7bc9b8530"
Expand Down