<|start_filename|>src/config.js<|end_filename|>
import path from 'path';
import dotenvSafe from 'dotenv-safe';

const root = path.join.bind(this, __dirname, '../');

dotenvSafe.load({
  path: root('.env'),
  sample: root('.env.example'),
});

// Export Server settings
export const serverPort = process.env.SERVER_PORT || 5000;


<|start_filename|>src/routes/login/login.test.js<|end_filename|>
// require the Koa server
const server = require('../../index');
// require supertest
const request = require('supertest');
// close the server after each test
afterEach(() => {
  server.close();
});
describe('routes: login', () => {
  test('should respond as expected', async () => {
    // const response = await request(server).post('/login');
    // expect(response.status).toEqual(200);
    // expect(response.type).toEqual('application/json');
    // expect(response.body.token).not.toEqual(null);
    // expect(response.body.token).not.toEqual(undefined);
  });
});


<|start_filename|>src/services/auth/createJwtToken.js<|end_filename|>
import jwt from 'jsonwebtoken';
import Boom from 'boom';

const createJwtToken = user =>
  new Promise((resolve, reject) => {
    if (!user) {
      throw Boom.badRequest('Email ou senha inválido. Tente novamente por favor.');
    }

    const token = jwt.sign(
      {
        username: user.email,
        id: user.id,
      },
      process.env.JWT_KEY,
    );

    if (token) {
      resolve(token);
    }

    reject('Ops! Token não criado');
  });

export default createJwtToken;


<|start_filename|>src/utils/encrypt.js<|end_filename|>
import crypto from 'crypto';

const encrypt = value => crypto.createHmac('sha256', value).digest('hex');

export default encrypt;


<|start_filename|>src/utils/handleErrors.js<|end_filename|>
const handleErrors = error => {
  console.log(error);
  if (error.isBoom) {
    return { ...error.output.payload, status: error.output.payload.statusCode };
  }

  return error;
};

export default handleErrors;


<|start_filename|>src/routes/login/index.js<|end_filename|>
import loginRoute from './login';

export default loginRoute;


<|start_filename|>src/index.js<|end_filename|>
import 'babel-polyfill';
import koa from 'koa';
import cors from 'kcors';
import logger from 'koa-logger';
import koaRouter from 'koa-router';
import bodyParser from 'koa-bodyparser';
import Boom from 'boom';
import jwt from 'koa-jwt';

import { serverPort } from './config';
import loadRoutes from './routes';
import db from './db/models';

// app
const app = new koa();

// routes
const router = new koaRouter();
loadRoutes(router);

if (process.env.NODE_ENV === 'development') {
  const corsOptions = {
    credentials: true,
    origin: '*',
  };
  app.use(cors(corsOptions));
}

app
  .use(bodyParser())
  .use(
    jwt({
      secret: process.env.JWT_KEY,
    }).unless({
      path: ['/', '/login'],
    }),
  )
  .use(logger())
  .use(router.routes())
  .use(
    router.allowedMethods({
      throw: true,
      notImplemented: () => new Boom.notImplemented(),
      methodNotAllowed: () => new Boom.methodNotAllowed(),
    }),
  )
  .use(async context => {
    context.body = 'INSIDE API';
  });

// server
const server = app.listen(serverPort, () => {
  db.sequelize.sync();
  console.log(`Server started on port ${serverPort}`);
});

module.exports = server;


<|start_filename|>src/utils/index.js<|end_filename|>
import handleErrors from './handleErrors';
import encrypt from './encrypt';

export { handleErrors, encrypt };


<|start_filename|>src/services/auth/index.js<|end_filename|>
import createJwtToken from './createJwtToken';

export { createJwtToken };


<|start_filename|>src/db/models/user.js<|end_filename|>
import _ from 'lodash';

module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define(
    'User',
    {
      name: DataTypes.STRING,
      cpf: {
        type: DataTypes.STRING,
        unique: true,
      },
      email: {
        type: DataTypes.STRING,
        unique: true,
        validate: {
          isEmail: true,
        },
      },
      password: DataTypes.STRING,
    },
    {
      tableName: 'Users',
      classMethods: {
        associate(models) {
          // associations can be defined here
        },
      },
      instanceMethods: {
        toJSON() {
          const privateAttributes = ['password'];

          return _.omit(this.dataValues, privateAttributes);
        },
      },
    },
  );
  return User;
};


<|start_filename|>src/db/seeders/20180112142114-superadmin-user.js<|end_filename|>
module.exports = {
  up: (queryInterface, Sequelize) =>
    queryInterface.bulkInsert(
      'Users',
      [
        {
          name: 'Super',
          cpf: 'Admin',
          email: '<EMAIL>',
          password: '<PASSWORD>',
          createdAt: new Date(),
          updatedAt: new Date(),
        },
      ],
      {},
    ),

  down: (queryInterface, Sequelize) => {
    queryInterface.bulkDelete('Users', [
      {
        email: '<EMAIL>',
      },
    ]);
  },
};


<|start_filename|>src/services/user/index.js<|end_filename|>
import getUserByEmailAndPassword from './getUserByEmailAndPassword';

export { getUserByEmailAndPassword };


<|start_filename|>src/services/user/getUserByEmailAndPassword.js<|end_filename|>
import Sequelize from 'sequelize';
import { encrypt } from '../../utils';
import { User } from '../../db/models';

const Op = Sequelize.Op;

const getUserByEmailAndPassword = async (email, password) => {
  const hash = encrypt(password);
  return User.findOne({
    where: {
      email: {
        [Op.eq]: email,
      },
      password: {
        [Op.eq]: hash,
      },
    },
  });
};

export default getUserByEmailAndPassword;


<|start_filename|>src/routes/index.js<|end_filename|>
import loginRoute from './login';

const loadRoutes = router => {
  loginRoute(router);
};

export default loadRoutes;


<|start_filename|>src/routes/login/login.js<|end_filename|>
import { login } from '../../services/login';
import { handleErrors } from '../../utils/';

const loginRoute = router => {
  router.post('/login', async ctx => {
    try {
      ctx.body = await login(ctx.request.body);
    } catch (error) {
      const { status, ...body } = handleErrors(error);
      ctx.status = status;
      ctx.body = body;
    }
  });
};

export default loginRoute;


<|start_filename|>src/services/login/login.js<|end_filename|>
import Boom from 'boom';
import { getUserByEmailAndPassword } from '../user';
import { createJwtToken } from '../auth';

const loginService = async data => {
  if (!data.email || !data.password) {
    throw Boom.badRequest('Dados Inválidos');
  }
  const user = await getUserByEmailAndPassword(data.email, data.password);
  const jwt = await createJwtToken(user);
  return {
    token: jwt,
  };
};

export default loginService;
