diff --git a/LICENSE b/LICENSE index 32110fe..f873fd3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,8 +1,8 @@ The MIT License (MIT) -Copyright (c) 2016 Adrian Obelmejias +Copyright (c) 2016 Adrian Obelmejias & Chris Troutner Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 9093e66..6602ece 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ -#koa2-api-boilerplate +# babel-free-koa2-api-boilerplate [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com) Boilerplate for building APIs with [koa2](https://github.com/koajs/koa/tree/v2.x) and mongodb. +Modified to remove babel as a dependency. This repository is now natively compatible +with node v8.9 or higher. This project covers basic necessities of most APIs. * Authentication (passport & jwt) @@ -31,7 +33,6 @@ git clone https://github.com/adrianObel/koa2-api-boilerplate.git * [Nodemon](http://nodemon.io/) * [Mocha](https://mochajs.org/) * [apidoc](http://apidocjs.com/) -* [Babel](https://github.com/babel/babel) * [ESLint](http://eslint.org/) ##Structure diff --git a/bin/server.js b/bin/server.js index 8290e5f..51f1bea 100644 --- a/bin/server.js +++ b/bin/server.js @@ -1,38 +1,48 @@ -import Koa from 'koa' -import bodyParser from 'koa-bodyparser' -import convert from 'koa-convert' -import logger from 'koa-logger' -import mongoose from 'mongoose' -import session from 'koa-generic-session' -import passport from 'koa-passport' -import mount from 'koa-mount' -import serve from 'koa-static' +const Koa = require('koa') +const bodyParser = require('koa-bodyparser') +const convert = require('koa-convert') +const logger = require('koa-logger') +const mongoose = require('mongoose') +const session = require('koa-generic-session') +const passport = require('koa-passport') +const mount = require('koa-mount') +const serve = require('koa-static') -import config from '../config' -import { errorMiddleware } from '../src/middleware' +const config = require('../config') +const errorMiddleware = require('../src/middleware') +// Create a Koa instance. const app = new Koa() app.keys = [config.session] +// Connect to the Mongo Database. mongoose.Promise = global.Promise mongoose.connect(config.database) +// MIDDLEWARE START + app.use(convert(logger())) app.use(bodyParser()) app.use(session()) app.use(errorMiddleware()) +// Used to generate the docs. app.use(convert(mount('/docs', serve(`${process.cwd()}/docs`)))) +// User Authentication require('../config/passport') app.use(passport.initialize()) app.use(passport.session()) +// Custom Middleware Modules const modules = require('../src/modules') modules(app) +// MIDDLEWARE END + app.listen(config.port, () => { console.log(`Server started on ${config.port}`) }) -export default app +// export default app +module.exports = app diff --git a/config/env/common.js b/config/env/common.js index 9b237b0..4a03e2d 100644 --- a/config/env/common.js +++ b/config/env/common.js @@ -1,3 +1,7 @@ -export default { +// export default { +// port: process.env.PORT || 5000 +// } + +module.exports = { port: process.env.PORT || 5000 } diff --git a/config/env/development.js b/config/env/development.js index c77d155..47f1615 100644 --- a/config/env/development.js +++ b/config/env/development.js @@ -1,5 +1,13 @@ +/* export default { session: 'secret-boilerplate-token', token: 'secret-jwt-token', - database: 'mongodb://localhost:27017/koa2-boilerplate-dev' + database: 'mongodb://localhost:27017/p2pvps-server-dev' +} +*/ + +module.exports = { + session: 'secret-boilerplate-token', + token: 'secret-jwt-token', + database: 'mongodb://localhost:27017/p2pvps-server-dev' } diff --git a/config/env/production.js b/config/env/production.js index 4423425..a68e550 100644 --- a/config/env/production.js +++ b/config/env/production.js @@ -1,5 +1,13 @@ +/* export default { session: 'secret-boilerplate-token', token: 'secret-jwt-token', - database: 'mongodb://localhost:27017/koa2-boilerplate-prod' + database: 'mongodb://localhost:27017/p2pvps-server-prod' +} +*/ + +module.exports = { + session: 'secret-boilerplate-token', + token: 'secret-jwt-token', + database: 'mongodb://localhost:27017/p2pvps-server-prod' } diff --git a/config/env/test.js b/config/env/test.js index e73169c..9cc99f1 100644 --- a/config/env/test.js +++ b/config/env/test.js @@ -1,5 +1,13 @@ +/* export default { session: 'secret-boilerplate-token', token: 'secret-jwt-token', - database: 'mongodb://localhost:27017/koa2-boilerplate-test' + database: 'mongodb://localhost:27017/p2pvps-server-test' +} +*/ + +module.exports = { + session: 'secret-boilerplate-token', + token: 'secret-jwt-token', + database: 'mongodb://localhost:27017/p2pvps-server-test' } diff --git a/config/index.js b/config/index.js index 79ddc0a..db7fcb9 100644 --- a/config/index.js +++ b/config/index.js @@ -1,6 +1,6 @@ -import common from './env/common' +const common = require('./env/common') const env = process.env.NODE_ENV || 'development' -const config = require(`./env/${env}`).default +const config = require(`./env/${env}`) -export default Object.assign({}, common, config) +module.exports = Object.assign({}, common, config) diff --git a/config/passport.js b/config/passport.js index cee8ef9..a2805bd 100644 --- a/config/passport.js +++ b/config/passport.js @@ -1,6 +1,6 @@ -import passport from 'koa-passport' -import User from '../src/models/users' -import { Strategy } from 'passport-local' +const passport = require('koa-passport') +const User = require('../src/models/users') +const Strategy = require('passport-local') passport.serializeUser((user, done) => { done(null, user.id) diff --git a/index.js b/index.js index 7930742..ed2fd2b 100644 --- a/index.js +++ b/index.js @@ -1,3 +1 @@ -require('babel-core/register')() -require('babel-polyfill') require('./bin/server.js') diff --git a/install-mongo b/install-mongo new file mode 100755 index 0000000..74cd815 --- /dev/null +++ b/install-mongo @@ -0,0 +1,7 @@ +#!/bin/bash +sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 +echo "deb [ arch=amd64,arm64 ] http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list +sudo apt-get update +sudo apt-get install -y mongodb-org +sudo service mongod start + diff --git a/src/middleware/index.js b/src/middleware/index.js index 2febd47..cf8bca3 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -1,4 +1,4 @@ -export function errorMiddleware () { +module.exports = function errorMiddleware () { return async (ctx, next) => { try { await next() diff --git a/src/middleware/validators.js b/src/middleware/validators.js index 1d7ba74..2a5a2d8 100644 --- a/src/middleware/validators.js +++ b/src/middleware/validators.js @@ -1,24 +1,30 @@ -import User from '../models/users' -import config from '../../config' -import { getToken } from '../utils/auth' -import { verify } from 'jsonwebtoken' +const User = require('../models/users') +const config = require('../../config') +const getToken = require('../utils/auth') +const jwt = require('jsonwebtoken') -export async function ensureUser (ctx, next) { +module.exports = async function ensureUser (ctx, next) { + //console.log(`getToken: ${typeof (getToken)}`) const token = getToken(ctx) if (!token) { + //console.log(`Err: Token not provided.`) ctx.throw(401) } let decoded = null try { - decoded = verify(token, config.token) + //console.log(`token: ${JSON.stringify(token, null, 2)}`) + //console.log(`config: ${JSON.stringify(config, null, 2)}`) + decoded = jwt.verify(token, config.token) } catch (err) { + //console.log(`Err: Token could not be decoded: ${err}`) ctx.throw(401) } ctx.state.user = await User.findById(decoded.id, '-password') if (!ctx.state.user) { + //console.log(`Err: Could not find user.`) ctx.throw(401) } diff --git a/src/models/users.js b/src/models/users.js index 56f808a..28931b9 100644 --- a/src/models/users.js +++ b/src/models/users.js @@ -1,7 +1,7 @@ -import mongoose from 'mongoose' -import bcrypt from 'bcrypt' -import config from '../../config' -import jwt from 'jsonwebtoken' +const mongoose = require('mongoose') +const bcrypt = require('bcrypt') +const config = require('../../config') +const jwt = require('jsonwebtoken') const User = new mongoose.Schema({ type: { type: String, default: 'User' }, @@ -50,7 +50,11 @@ User.methods.validatePassword = function validatePassword (password) { User.methods.generateToken = function generateToken () { const user = this - return jwt.sign({ id: user.id }, config.token) + const token = jwt.sign({ id: user.id }, config.token) + //console.log(`config.token: ${config.token}`) + //console.log(`generated token: ${token}`) + return token } -export default mongoose.model('user', User) +// export default mongoose.model('user', User) +module.exports = mongoose.model('user', User) diff --git a/src/modules/auth/controller.js b/src/modules/auth/controller.js index 728225a..1062db7 100644 --- a/src/modules/auth/controller.js +++ b/src/modules/auth/controller.js @@ -1,4 +1,4 @@ -import passport from 'koa-passport' +const passport = require('koa-passport') /** * @apiDefine TokenError @@ -50,7 +50,7 @@ import passport from 'koa-passport' * } */ -export async function authUser (ctx, next) { +async function authUser (ctx, next) { return passport.authenticate('local', (user) => { if (!user) { ctx.throw(401) @@ -68,3 +68,5 @@ export async function authUser (ctx, next) { } })(ctx, next) } + +module.exports.authUser = authUser diff --git a/src/modules/auth/router.js b/src/modules/auth/router.js index 06b1d84..a03ff9b 100644 --- a/src/modules/auth/router.js +++ b/src/modules/auth/router.js @@ -1,8 +1,11 @@ -import * as auth from './controller' +// import * as auth from './controller' +const auth = require('./controller') -export const baseUrl = '/auth' +// export const baseUrl = '/auth' +module.exports.baseUrl = '/auth' -export default [ +// export default [ +module.exports.routes = [ { method: 'POST', route: '/', diff --git a/src/modules/index.js b/src/modules/index.js index 24d13b7..7d3f27c 100644 --- a/src/modules/index.js +++ b/src/modules/index.js @@ -1,30 +1,42 @@ -import glob from 'glob' -import Router from 'koa-router' +const glob = require('glob') +const Router = require('koa-router') -exports = module.exports = function initModules (app) { +module.exports = function initModules (app) { glob(`${__dirname}/*`, { ignore: '**/index.js' }, (err, matches) => { if (err) { throw err } + // Loop through each sub-directory in the modules directory. matches.forEach((mod) => { + // console.log(`router = ${mod}/router`) const router = require(`${mod}/router`) - const routes = router.default + const routes = router.routes const baseUrl = router.baseUrl const instance = new Router({ prefix: baseUrl }) + // console.log(`routes: ${JSON.stringify(routes, null, 2)}`) + + // Loop through each route defined in the router.js file. routes.forEach((config) => { - const { - method = '', - route = '', - handlers = [] - } = config + // console.log(`modules/index.js config: ${JSON.stringify(config, null, 2)}`) + // const { + // method = '', + // route = '', + // handlers = [] + // } = config + const method = config.method || '' + const route = config.route || '' + const handlers = config.handlers || [] const lastHandler = handlers.pop() - instance[method.toLowerCase()](route, ...handlers, async function(ctx) { + instance[method.toLowerCase()](route, ...handlers, async function (ctx) { + // console.log(`typeof lastHandler: ${typeof (lastHandler)}`) return await lastHandler(ctx) }) + // console.log(`instance: ${JSON.stringify(instance, null, 2)}`) + app .use(instance.routes()) .use(instance.allowedMethods()) diff --git a/src/modules/users/controller.js b/src/modules/users/controller.js index 22d3593..3ce1d02 100644 --- a/src/modules/users/controller.js +++ b/src/modules/users/controller.js @@ -1,4 +1,4 @@ -import User from '../../models/users' +const User = require('../../models/users') /** * @api {post} /users Create a new user @@ -38,7 +38,7 @@ import User from '../../models/users' * "error": "Unprocessable Entity" * } */ -export async function createUser (ctx) { +async function createUser (ctx) { const user = new User(ctx.request.body.user) try { await user.save() @@ -84,7 +84,7 @@ export async function createUser (ctx) { * * @apiUse TokenError */ -export async function getUsers (ctx) { +async function getUsers (ctx) { const users = await User.find({}, '-password') ctx.body = { users } } @@ -116,7 +116,7 @@ export async function getUsers (ctx) { * * @apiUse TokenError */ -export async function getUser (ctx, next) { +async function getUser (ctx, next) { try { const user = await User.findById(ctx.params.id, '-password') if (!user) { @@ -177,7 +177,7 @@ export async function getUser (ctx, next) { * * @apiUse TokenError */ -export async function updateUser (ctx) { +async function updateUser (ctx) { const user = ctx.body.user Object.assign(user, ctx.request.body.user) @@ -210,7 +210,7 @@ export async function updateUser (ctx) { * @apiUse TokenError */ -export async function deleteUser (ctx) { +async function deleteUser (ctx) { const user = ctx.body.user await user.remove() @@ -220,3 +220,11 @@ export async function deleteUser (ctx) { success: true } } + +module.exports = { + createUser, + getUsers, + getUser, + updateUser, + deleteUser +} diff --git a/src/modules/users/router.js b/src/modules/users/router.js index f03aed9..c8c43b0 100644 --- a/src/modules/users/router.js +++ b/src/modules/users/router.js @@ -1,9 +1,10 @@ -import { ensureUser } from '../../middleware/validators' -import * as user from './controller' +const ensureUser = require('../../middleware/validators') +const user = require('./controller') -export const baseUrl = '/users' +// export const baseUrl = '/users' +module.exports.baseUrl = '/users' -export default [ +module.exports.routes = [ { method: 'POST', route: '/', diff --git a/src/utils/auth.js b/src/utils/auth.js index 288098b..d478259 100644 --- a/src/utils/auth.js +++ b/src/utils/auth.js @@ -1,4 +1,4 @@ -export function getToken (ctx) { +module.exports = function getToken (ctx) { const header = ctx.request.header.authorization if (!header) { return null diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000..8cddb82 --- /dev/null +++ b/test/README.md @@ -0,0 +1,3 @@ +The files in this directory are named so as to control the order in which +the files are executed by mocha. a01... runs first. The order is important, +as some tests downstream depend on tests upstream. diff --git a/test/utils.js b/test/utils.js index e036fac..bc9fe2c 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,6 +1,6 @@ -import mongoose from 'mongoose' +const mongoose = require('mongoose') -export function cleanDb () { +function cleanDb () { for (const collection in mongoose.connection.collections) { if (mongoose.connection.collections.hasOwnProperty(collection)) { mongoose.connection.collections[collection].remove() @@ -8,7 +8,7 @@ export function cleanDb () { } } -export function authUser (agent, callback) { +function authUser (agent, callback) { agent .post('/users') .set('Accept', 'application/json') @@ -22,3 +22,8 @@ export function authUser (agent, callback) { }) }) } + +module.exports = { + cleanDb, + authUser +}