mirror of
https://github.com/Permissionless-Software-Foundation/ipfs-bch-wallet-service.git
synced 2026-09-21 16:52:03 -07:00
Refactored users REST API controller and router
This commit is contained in:
@@ -8,23 +8,23 @@
|
||||
|
||||
// Load the REST API Controllers.
|
||||
const AuthRESTController = require('./auth')
|
||||
const UserRESTController = require('./users')
|
||||
const UserRouter = require('./users')
|
||||
const ContactRESTController = require('./contact')
|
||||
const LogsRESTController = require('./logs')
|
||||
|
||||
class RESTControllers {
|
||||
constructor (localConfig) {
|
||||
constructor (localConfig = {}) {
|
||||
// Dependency Injection.
|
||||
this.adapters = localConfig.adapters
|
||||
if (!this.adapters) {
|
||||
throw new Error(
|
||||
'Instance of Adapters library required when instantiating PostEntry REST Controller.'
|
||||
'Instance of Adapters library required when instantiating REST Controller libraries.'
|
||||
)
|
||||
}
|
||||
this.useCases = localConfig.useCases
|
||||
if (!this.useCases) {
|
||||
throw new Error(
|
||||
'Instance of Use Cases library required when instantiating PostEntry REST Controller.'
|
||||
'Instance of Use Cases library required when instantiating REST Controller libraries.'
|
||||
)
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ class RESTControllers {
|
||||
authRESTController.attach(app)
|
||||
|
||||
// Attach the REST API Controllers associated with the /user route
|
||||
const userRESTController = new UserRESTController(dependencies)
|
||||
userRESTController.attach(app)
|
||||
const userRouter = new UserRouter(dependencies)
|
||||
userRouter.attach(app)
|
||||
|
||||
// Attach the REST API Controllers associated with the /contact route
|
||||
const contactRESTController = new ContactRESTController(dependencies)
|
||||
|
||||
@@ -2,12 +2,6 @@
|
||||
REST API Controller library for the /user route
|
||||
*/
|
||||
|
||||
// User database model.
|
||||
// const UserModel = require('../../../adapters/localdb/models/users')
|
||||
|
||||
// User library for business logic.
|
||||
// const UserLib = require('../../../use-cases/user')
|
||||
|
||||
const { wlogger } = require('../../../adapters/wlogger')
|
||||
|
||||
let _this
|
||||
|
||||
@@ -2,9 +2,16 @@
|
||||
REST API library for /user route.
|
||||
*/
|
||||
|
||||
const UserRESTRouter = require('./router')
|
||||
// Public npm libraries.
|
||||
const Router = require('koa-router')
|
||||
|
||||
class UserRESTController {
|
||||
// Local libraries.
|
||||
const UserRESTControllerLib = require('./controller')
|
||||
const Validators = require('../middleware/validators')
|
||||
|
||||
let _this
|
||||
|
||||
class UserRouter {
|
||||
constructor (localConfig = {}) {
|
||||
// Dependency Injection.
|
||||
this.adapters = localConfig.adapters
|
||||
@@ -20,12 +27,62 @@ class UserRESTController {
|
||||
)
|
||||
}
|
||||
|
||||
this.userRESTRouter = new UserRESTRouter(localConfig)
|
||||
const dependencies = {
|
||||
adapters: this.adapters,
|
||||
useCases: this.useCases
|
||||
}
|
||||
|
||||
// Encapsulate dependencies.
|
||||
this.userRESTController = new UserRESTControllerLib(dependencies)
|
||||
this.validators = new Validators()
|
||||
|
||||
// Instantiate the router and set the base route.
|
||||
const baseUrl = '/users'
|
||||
this.router = new Router({ prefix: baseUrl })
|
||||
|
||||
_this = this
|
||||
}
|
||||
|
||||
attach (app) {
|
||||
this.userRESTRouter.attachControllers(app)
|
||||
if (!app) {
|
||||
throw new Error(
|
||||
'Must pass app object when attaching REST API controllers.'
|
||||
)
|
||||
}
|
||||
|
||||
// Define the routes and attach the controller.
|
||||
this.router.post('/', this.userRESTController.createUser)
|
||||
this.router.get('/', this.getAll)
|
||||
this.router.get('/:id', this.getById)
|
||||
this.router.put('/:id', this.updateUser)
|
||||
this.router.delete('/:id', this.deleteUser)
|
||||
|
||||
// Attach the Controller routes to the Koa app.
|
||||
app.use(this.router.routes())
|
||||
app.use(this.router.allowedMethods())
|
||||
}
|
||||
|
||||
async getAll (ctx, next) {
|
||||
await _this.validators.ensureUser(ctx, next)
|
||||
await _this.userRESTController.getUsers(ctx, next)
|
||||
}
|
||||
|
||||
async getById (ctx, next) {
|
||||
await _this.validators.ensureUser(ctx, next)
|
||||
await _this.userRESTController.getUser(ctx, next)
|
||||
}
|
||||
|
||||
async updateUser (ctx, next) {
|
||||
await _this.validators.ensureTargetUserOrAdmin(ctx, next)
|
||||
await _this.userRESTController.getUser(ctx, next)
|
||||
await _this.userRESTController.updateUser(ctx, next)
|
||||
}
|
||||
|
||||
async deleteUser (ctx, next) {
|
||||
await _this.validators.ensureTargetUserOrAdmin(ctx, next)
|
||||
await _this.userRESTController.getUser(ctx, next)
|
||||
await _this.userRESTController.deleteUser(ctx, next)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UserRESTController
|
||||
module.exports = UserRouter
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
REST Router for the /user route.
|
||||
*/
|
||||
|
||||
// Public npm libraries.
|
||||
const Router = require('koa-router')
|
||||
|
||||
// Local libraries.
|
||||
const UserRESTControllerLib = require('./controller')
|
||||
const Validators = require('../middleware/validators')
|
||||
|
||||
let _this
|
||||
|
||||
class UserRESTRouter {
|
||||
constructor (localConfig = {}) {
|
||||
// Dependency Injection.
|
||||
this.adapters = localConfig.adapters
|
||||
if (!this.adapters) {
|
||||
throw new Error(
|
||||
'Instance of Adapters library required when instantiating /users REST Controller.'
|
||||
)
|
||||
}
|
||||
this.useCases = localConfig.useCases
|
||||
if (!this.useCases) {
|
||||
throw new Error(
|
||||
'Instance of Use Cases library required when instantiating /users REST Controller.'
|
||||
)
|
||||
}
|
||||
const dependencies = {
|
||||
adapters: this.adapters,
|
||||
useCases: this.useCases
|
||||
}
|
||||
|
||||
// Encapsulate dependencies.
|
||||
this.userRESTController = new UserRESTControllerLib(dependencies)
|
||||
this.validators = new Validators()
|
||||
|
||||
// Instantiate the router and set the base route.
|
||||
const baseUrl = '/users'
|
||||
this.router = new Router({ prefix: baseUrl })
|
||||
|
||||
_this = this
|
||||
}
|
||||
|
||||
attachControllers (app) {
|
||||
if (!app) {
|
||||
throw new Error(
|
||||
'Must pass app object when attaching REST API controllers.'
|
||||
)
|
||||
}
|
||||
|
||||
// Define the routes and attach the controller.
|
||||
this.router.post('/', this.userRESTController.createUser)
|
||||
this.router.get('/', this.getAll)
|
||||
this.router.get('/:id', this.getById)
|
||||
this.router.put('/:id', this.updateUser)
|
||||
this.router.delete('/:id', this.deleteUser)
|
||||
|
||||
// Attach the Controller routes to the Koa app.
|
||||
app.use(this.router.routes())
|
||||
app.use(this.router.allowedMethods())
|
||||
}
|
||||
|
||||
async getAll (ctx, next) {
|
||||
await _this.validators.ensureUser(ctx, next)
|
||||
await _this.userRESTController.getUsers(ctx, next)
|
||||
}
|
||||
|
||||
async getById (ctx, next) {
|
||||
await _this.validators.ensureUser(ctx, next)
|
||||
await _this.userRESTController.getUser(ctx, next)
|
||||
}
|
||||
|
||||
async updateUser (ctx, next) {
|
||||
await _this.validators.ensureTargetUserOrAdmin(ctx, next)
|
||||
await _this.userRESTController.getUser(ctx, next)
|
||||
await _this.userRESTController.updateUser(ctx, next)
|
||||
}
|
||||
|
||||
async deleteUser (ctx, next) {
|
||||
await _this.validators.ensureTargetUserOrAdmin(ctx, next)
|
||||
await _this.userRESTController.getUser(ctx, next)
|
||||
await _this.userRESTController.deleteUser(ctx, next)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UserRESTRouter
|
||||
@@ -292,7 +292,7 @@ describe('Users', () => {
|
||||
|
||||
assert.fail('Unexpected code path!')
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
// console.log(err)
|
||||
assert.equal(err.response.status, 422)
|
||||
assert.equal(err.response.data, 'test error')
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ process.env.SVC_ENV = 'test'
|
||||
|
||||
// Local libraries
|
||||
const UserRPC = require('../../../../src/controllers/json-rpc/users')
|
||||
const RateLimit = require('../../../../src/controllers/json-rpc/rate-limit')
|
||||
// const UserModel = require('../../../src/adapters/localdb/models/users')
|
||||
const adapters = require('../../mocks/adapters')
|
||||
const UseCasesMock = require('../../mocks/use-cases')
|
||||
|
||||
@@ -29,7 +27,6 @@ describe('#UserRPC', () => {
|
||||
const useCases = new UseCasesMock()
|
||||
|
||||
uut = new UserRPC({ adapters, useCases })
|
||||
uut.rateLimit = new RateLimit({ max: 100 })
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
Unit tests for the REST API controllers/rest-api/index.js library.
|
||||
*/
|
||||
|
||||
// Public npm libraries
|
||||
const assert = require('chai').assert
|
||||
const sinon = require('sinon')
|
||||
|
||||
// Local libraries
|
||||
const RESTControllers = require('../../../../src/controllers/rest-api/')
|
||||
// const mockContext = require('../../../unit/mocks/ctx-mock').context
|
||||
const adapters = require('../../mocks/adapters')
|
||||
const UseCasesMock = require('../../mocks/use-cases')
|
||||
|
||||
describe('#RESTControllers', () => {
|
||||
let uut
|
||||
let sandbox
|
||||
// let ctx
|
||||
|
||||
before(async () => {})
|
||||
|
||||
beforeEach(() => {
|
||||
const useCases = new UseCasesMock()
|
||||
uut = new RESTControllers({ adapters, useCases })
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
|
||||
// Mock the context object.
|
||||
// ctx = mockContext()
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe('#constructor', () => {
|
||||
it('should throw an error if adapters are not passed in', () => {
|
||||
try {
|
||||
uut = new RESTControllers()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Adapters library required when instantiating REST Controller libraries.'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should throw an error if useCases are not passed in', () => {
|
||||
try {
|
||||
uut = new RESTControllers({ adapters })
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
|
||||
// use to prevent complaints from linter.
|
||||
console.log('uut: ', uut)
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Use Cases library required when instantiating REST Controller libraries.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
+45
-48
@@ -5,62 +5,21 @@
|
||||
// Public npm libraries
|
||||
const assert = require('chai').assert
|
||||
const sinon = require('sinon')
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
// Local support libraries
|
||||
const config = require('../../../../config')
|
||||
const testUtils = require('../../../utils/test-utils')
|
||||
const adapters = require('../../mocks/adapters')
|
||||
const UseCasesMock = require('../../mocks/use-cases')
|
||||
const adapters = require('../../../mocks/adapters')
|
||||
const UseCasesMock = require('../../../mocks/use-cases')
|
||||
|
||||
const UserController = require('../../../../src/controllers/rest-api/users/controller')
|
||||
const UserController = require('../../../../../src/controllers/rest-api/users/controller')
|
||||
let uut
|
||||
let sandbox
|
||||
let ctx
|
||||
|
||||
const mockContext = require('../../../unit/mocks/ctx-mock').context
|
||||
const mockContext = require('../../../../unit/mocks/ctx-mock').context
|
||||
|
||||
describe('Users', () => {
|
||||
describe('#Users-REST-Controller', () => {
|
||||
// const testUser = {}
|
||||
|
||||
before(async () => {
|
||||
// Connect to the Mongo Database.
|
||||
mongoose.Promise = global.Promise
|
||||
mongoose.set('useCreateIndex', true) // Stop deprecation warning.
|
||||
await mongoose.connect(config.database, {
|
||||
useUnifiedTopology: true,
|
||||
useNewUrlParser: true
|
||||
})
|
||||
|
||||
// Delete all previous users in the database.
|
||||
await testUtils.deleteAllUsers()
|
||||
|
||||
// console.log(`config: ${JSON.stringify(config, null, 2)}`)
|
||||
|
||||
// Create a second test user.
|
||||
// const userObj = {
|
||||
// email: 'test2@test.com',
|
||||
// password: 'pass2'
|
||||
// }
|
||||
// const testUser = await testUtils.createUser(userObj)
|
||||
// console.log(`testUser2: ${JSON.stringify(testUser, null, 2)}`)
|
||||
|
||||
// context.user2 = testUser.user
|
||||
// context.token2 = testUser.token
|
||||
// context.id2 = testUser.user._id
|
||||
|
||||
// Get the JWT used to log in as the admin 'system' user.
|
||||
// const adminJWT = await testUtils.getAdminJWT()
|
||||
// // console.log(`adminJWT: ${adminJWT}`)
|
||||
// context.adminJWT = adminJWT
|
||||
|
||||
// const admin = await testUtils.loginAdminUser()
|
||||
// context.adminJWT = admin.token
|
||||
|
||||
// const admin = await adminLib.loginAdmin()
|
||||
// console.log(`admin: ${JSON.stringify(admin, null, 2)}`)
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
const useCases = new UseCasesMock()
|
||||
uut = new UserController({ adapters, useCases })
|
||||
@@ -73,8 +32,32 @@ describe('Users', () => {
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
after(() => {
|
||||
mongoose.connection.close()
|
||||
describe('#constructor', () => {
|
||||
it('should throw an error if adapters are not passed in', () => {
|
||||
try {
|
||||
uut = new UserController()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Adapters library required when instantiating /users REST Controller.'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should throw an error if useCases are not passed in', () => {
|
||||
try {
|
||||
uut = new UserController({ adapters })
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Use Cases library required when instantiating /users REST Controller.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#POST /users', () => {
|
||||
@@ -258,4 +241,18 @@ describe('Users', () => {
|
||||
assert.equal(ctx.status, 200)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#handleError', () => {
|
||||
it('should still throw error if there is no message', () => {
|
||||
try {
|
||||
const err = {
|
||||
status: 404
|
||||
}
|
||||
|
||||
uut.handleError(ctx, err)
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Not Found')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Unit tests for the REST API handler for the /users endpoints.
|
||||
*/
|
||||
|
||||
// Public npm libraries
|
||||
const assert = require('chai').assert
|
||||
const sinon = require('sinon')
|
||||
|
||||
// Local support libraries
|
||||
const adapters = require('../../../mocks/adapters')
|
||||
const UseCasesMock = require('../../../mocks/use-cases')
|
||||
// const app = require('../../../mocks/app-mock')
|
||||
|
||||
const UserRouter = require('../../../../../src/controllers/rest-api/users')
|
||||
let uut
|
||||
let sandbox
|
||||
// let ctx
|
||||
|
||||
// const mockContext = require('../../../../unit/mocks/ctx-mock').context
|
||||
|
||||
describe('#Users-REST-Router', () => {
|
||||
// const testUser = {}
|
||||
|
||||
beforeEach(() => {
|
||||
const useCases = new UseCasesMock()
|
||||
uut = new UserRouter({ adapters, useCases })
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
|
||||
// Mock the context object.
|
||||
// ctx = mockContext()
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe('#constructor', () => {
|
||||
it('should throw an error if adapters are not passed in', () => {
|
||||
try {
|
||||
uut = new UserRouter()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Adapters library required when instantiating PostEntry REST Controller.'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should throw an error if useCases are not passed in', () => {
|
||||
try {
|
||||
uut = new UserRouter({ adapters })
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Use Cases library required when instantiating PostEntry REST Controller.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#attach', () => {
|
||||
it('should throw an error if app is not passed in.', () => {
|
||||
try {
|
||||
uut.attach()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Must pass app object when attaching REST API controllers.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
Mocks for Koa 'app' object.
|
||||
*/
|
||||
|
||||
const app = {
|
||||
use: () => {}
|
||||
}
|
||||
|
||||
module.exports = app
|
||||
Reference in New Issue
Block a user