mirror of
https://github.com/Permissionless-Software-Foundation/ipfs-bch-wallet-consumer.git
synced 2026-09-21 16:52:03 -07:00
fix(upstream): Syncing with upstream and fixing merge conflicts
This commit is contained in:
Vendored
+6
-1
@@ -172,6 +172,11 @@ export default {
|
||||
// Preferred P2WDB provider
|
||||
preferredIpfsFileProvider: process.env.PREFERRED_IPFS_FILE_PROVIDER
|
||||
? process.env.PREFERRED_IPFS_FILE_PROVIDER
|
||||
: ''
|
||||
: '',
|
||||
|
||||
// Account Configuration
|
||||
disableNewAccounts: process.env.DISABLE_NEW_ACCOUNTS ? true : false,
|
||||
|
||||
// Admin password
|
||||
adminPassword: process.env.ADMIN_PASSWORD
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"password": "YsFhsCVCqussWyyLYUjM",
|
||||
"email": "system@system.com",
|
||||
"id": "67ffbea61a8de3388f82c401",
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY3ZmZiZWE2MWE4ZGUzMzg4ZjgyYzQwMSIsImlhdCI6MTc0NDgxMzczNH0.a4wM-CfGudF40yi4lwTsnd_aDZHrRn87zjHYxFZmeC4"
|
||||
"name": "admin",
|
||||
"password": "O52nYamPmP7zE9Jfwgxo",
|
||||
"type": "admin",
|
||||
"id": "684246cf4e94f2261caf9848",
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY4NDI0NmNmNGU5NGYyMjYxY2FmOTg0OCIsImlhdCI6MTc0OTE3NDAyMX0.9GAS6q_xFz5Bwi7RwIqrqM3Q48DFlz_A-S0_r_L2pTQ"
|
||||
}
|
||||
+4
-3
@@ -6,11 +6,12 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"test": "npm run test:all",
|
||||
"test": "npm run test:unit",
|
||||
"test:all": "export CONSUMER_ENV=test && c8 --reporter=text mocha --exit --timeout 15000 --recursive test/unit test/e2e/automated/",
|
||||
"test:unit": "export CONSUMER_ENV=test && mocha --exit --timeout 15000 --recursive test/unit/",
|
||||
"test:unit": "export CONSUMER_ENV=test && c8 --reporter=text mocha --exit --timeout 15000 --recursive test/unit/",
|
||||
"test:e2e:auto": "export CONSUMER_ENV=test && mocha --exit --timeout 15000 test/e2e/automated/",
|
||||
"test:temp": "export CONSUMER_ENV=test && mocha --exit --timeout 15000 -g '#rate-limit' test/unit/json-rpc/",
|
||||
"start:e2e:server": "export CONSUMER_ENV=test && node index.js",
|
||||
"test:temp": "export SVC_ENV=test && mocha --exit --timeout 15000 -g '#rate-limit' test/unit/json-rpc/",
|
||||
"lint": "standard --env mocha --fix",
|
||||
"docs": "./node_modules/.bin/apidoc -i src/ -o docs",
|
||||
"coverage": "c8 report --reporter=text-lcov | coveralls",
|
||||
|
||||
+26
-58
@@ -51,70 +51,37 @@ class Admin {
|
||||
// used by the Listing Manager and test scripts, in order access private API
|
||||
// functions.
|
||||
async createSystemUser () {
|
||||
// Create the system user.
|
||||
try {
|
||||
context.password = _this._randomString(20)
|
||||
|
||||
const options = {
|
||||
method: 'POST',
|
||||
url: `${LOCALHOST}/users`,
|
||||
data: {
|
||||
user: {
|
||||
email: 'system@system.com',
|
||||
password: context.password,
|
||||
name: 'admin'
|
||||
}
|
||||
}
|
||||
const context = {
|
||||
email: 'system@system.com',
|
||||
name: 'admin',
|
||||
password: _this.config.adminPassword || _this._randomString(20),
|
||||
type: 'admin'
|
||||
}
|
||||
const result = await _this.axios.request(options)
|
||||
// console.log('admin.data: ', result.data)
|
||||
// Check if the user already exists
|
||||
let adminUser = await _this.User.findOne({ email: context.email })
|
||||
|
||||
context.email = result.data.user.email
|
||||
context.id = result.data.user._id
|
||||
context.token = result.data.token
|
||||
if (adminUser) {
|
||||
// Update the password
|
||||
adminUser.password = context.password
|
||||
} else {
|
||||
// Create a new admin user
|
||||
adminUser = new _this.User(context)
|
||||
}
|
||||
// Update context with the new user id and token
|
||||
context.id = adminUser._id
|
||||
context.token = await adminUser.generateToken()
|
||||
|
||||
// Get the mongoDB entry
|
||||
const user = await _this.User.findById(context.id)
|
||||
// Save the user
|
||||
await adminUser.save()
|
||||
|
||||
// Change the user type to admin
|
||||
user.type = 'admin'
|
||||
// console.log(`user created: ${JSON.stringify(user, null, 2)}`)
|
||||
|
||||
// Save the user model.
|
||||
await user.save()
|
||||
|
||||
// console.log(`admin user created: ${JSON.stringify(result.body, null, 2)}`)
|
||||
// console.log(`with password: ${context.password}`)
|
||||
|
||||
// Write out the system user information to a JSON file that external
|
||||
// applications like the Task Manager and the test scripts can access.
|
||||
|
||||
await jsonFiles.writeJSON(context, JSON_PATH)
|
||||
// console.log('context: ', context)
|
||||
// console.log('JSON_PATH: ', JSON_PATH)
|
||||
// Write the user data to the JSON file
|
||||
await _this.jsonFiles.writeJSON(context, JSON_PATH)
|
||||
|
||||
return context
|
||||
} catch (err) {
|
||||
// Handle existing system user.
|
||||
if (err.response.status === 422) {
|
||||
try {
|
||||
// Delete the existing user
|
||||
await _this.deleteExistingSystemUser()
|
||||
|
||||
// Call this function again.
|
||||
return _this.createSystemUser()
|
||||
} catch (err2) {
|
||||
console.error(
|
||||
'Error in admin.js/createSystemUser() while trying generate new system user.'
|
||||
)
|
||||
// process.end(1)
|
||||
throw err2
|
||||
}
|
||||
} else {
|
||||
console.log('Error in admin.js/createSystemUser: ')
|
||||
// process.end(1)
|
||||
throw err
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error in admin.js/createSystemUser()')
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +96,7 @@ class Admin {
|
||||
})
|
||||
|
||||
await _this.User.deleteOne({ email: 'system@system.com' })
|
||||
return true
|
||||
} catch (err) {
|
||||
console.log('Error in admin.js/deleteExistingSystemUser()')
|
||||
throw err
|
||||
@@ -152,7 +120,7 @@ class Admin {
|
||||
Accept: 'application/json'
|
||||
},
|
||||
data: {
|
||||
email: 'system@system.com',
|
||||
email: existingUser.email,
|
||||
password: existingUser.password
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
|
||||
// Load Mongoose models.
|
||||
import Users from './models/users.js'
|
||||
import Usage from './models/usage.js'
|
||||
|
||||
class LocalDB {
|
||||
constructor () {
|
||||
// Encapsulate dependencies
|
||||
this.Users = Users
|
||||
this.Usage = Usage
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
Usage data model
|
||||
*/
|
||||
|
||||
// Global npm libraries
|
||||
import mongoose from 'mongoose'
|
||||
|
||||
const Usage = new mongoose.Schema({
|
||||
ip: { type: String },
|
||||
url: { type: String },
|
||||
method: { type: String },
|
||||
timestamp: { type: Date }
|
||||
})
|
||||
|
||||
export default mongoose.model('usage', Usage)
|
||||
@@ -10,6 +10,8 @@ import UserRESTControllerLib from './controller.js'
|
||||
|
||||
import Validators from '../middleware/validators.js'
|
||||
|
||||
import config from '../../../../config/index.js'
|
||||
|
||||
let _this
|
||||
|
||||
class UserRouter {
|
||||
@@ -34,6 +36,7 @@ class UserRouter {
|
||||
}
|
||||
|
||||
// Encapsulate dependencies.
|
||||
this.config = config
|
||||
this.userRESTController = new UserRESTControllerLib(dependencies)
|
||||
this.validators = new Validators()
|
||||
|
||||
@@ -52,7 +55,7 @@ class UserRouter {
|
||||
}
|
||||
|
||||
// Define the routes and attach the controller.
|
||||
this.router.post('/', this.userRESTController.createUser)
|
||||
this.router.post('/', this.createUser)
|
||||
this.router.get('/', this.getAll)
|
||||
this.router.get('/:id', this.getById)
|
||||
this.router.put('/:id', this.updateUser)
|
||||
@@ -63,6 +66,14 @@ class UserRouter {
|
||||
app.use(this.router.allowedMethods())
|
||||
}
|
||||
|
||||
async createUser (ctx, next) {
|
||||
if (process.env.DISABLE_NEW_ACCOUNTS) {
|
||||
await _this.validators.ensureAdmin(ctx, next)
|
||||
}
|
||||
await _this.userRESTController.createUser(ctx, next)
|
||||
return true
|
||||
}
|
||||
|
||||
async getAll (ctx, next) {
|
||||
await _this.validators.ensureUser(ctx, next)
|
||||
await _this.userRESTController.getUsers(ctx, next)
|
||||
|
||||
@@ -23,58 +23,76 @@ class TimerControllers {
|
||||
|
||||
this.debugLevel = localConfig.debugLevel
|
||||
|
||||
// Constants
|
||||
this.cleanUsageInterval = 60000 * 60 // 1 hour
|
||||
this.backupUsageInterval = 60000 * 10 // 10 minutes
|
||||
|
||||
// Encapsulate dependencies
|
||||
this.config = config
|
||||
|
||||
// Bind 'this' object to all subfunctions.
|
||||
this.exampleTimerFunc = this.exampleTimerFunc.bind(this)
|
||||
this.cleanUsage = this.cleanUsage.bind(this)
|
||||
|
||||
// this.startTimers()
|
||||
this.backupUsage = this.backupUsage.bind(this)
|
||||
}
|
||||
|
||||
// Start all the time-based controllers.
|
||||
startTimers () {
|
||||
// Any new timer control functions can be added here. They will be started
|
||||
// when the server starts.
|
||||
this.optimizeWalletHandle = setInterval(this.exampleTimerFunc, 60000 * 60)
|
||||
this.cleanUsageHandle = setInterval(this.cleanUsage, 60000 * 60) // 1 hour
|
||||
this.cleanUsageHandle = setInterval(this.cleanUsage, this.cleanUsageInterval)
|
||||
this.backupUsageHandle = setInterval(this.backupUsage, this.backupUsageInterval)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
stopTimers () {
|
||||
clearInterval(this.optimizeWalletHandle)
|
||||
clearInterval(this.cleanUsageHandle)
|
||||
clearInterval(this.backupUsageHandle)
|
||||
}
|
||||
|
||||
// Replace this example function with your own timer handler.
|
||||
exampleTimerFunc (negativeTest) {
|
||||
// Clean the usage state so that stats reflect the last 24 hours.
|
||||
cleanUsage () {
|
||||
try {
|
||||
// console.log('Example timer controller executed.')
|
||||
clearInterval(this.cleanUsageHandle)
|
||||
|
||||
if (negativeTest) throw new Error('test error')
|
||||
const now = new Date()
|
||||
console.log(`cleanUsage() Timer Controller executing at ${now.toLocaleString()}`)
|
||||
|
||||
this.useCases.usage.cleanUsage()
|
||||
|
||||
this.cleanUsageHandle = setInterval(this.cleanUsage, this.cleanUsageInterval)
|
||||
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error('Error in exampleTimerFunc(): ', err)
|
||||
console.error('Error in time-controller.js/cleanUsage(): ', err)
|
||||
|
||||
this.cleanUsageHandle = setInterval(this.cleanUsage, this.cleanUsageInterval)
|
||||
|
||||
// Note: Do not throw an error. This is a top-level function.
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Clean the usage state so that stats reflect the last 24 hours.
|
||||
cleanUsage () {
|
||||
// Backup the usage stats to the database
|
||||
async backupUsage () {
|
||||
try {
|
||||
const now = new Date()
|
||||
console.log(`cleanUsage() Timer Controller executing at ${now.toLocaleString()}`)
|
||||
clearInterval(this.backupUsageHandle)
|
||||
|
||||
this.useCases.usage.cleanUsage()
|
||||
console.log('backupUsage() Timer Controller executing at ', new Date().toLocaleString())
|
||||
|
||||
// Clear the database of old usage data.
|
||||
await this.useCases.usage.clearUsage()
|
||||
|
||||
// Save the current usage snapshot to the database.
|
||||
await this.useCases.usage.saveUsage()
|
||||
|
||||
this.backupUsageHandle = setInterval(this.backupUsage, this.backupUsageInterval)
|
||||
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error('Error in time-controller.js/cleanUsage(): ', err)
|
||||
console.error('Error in time-controller.js/backupUsage(): ', err)
|
||||
|
||||
this.backupUsageHandle = setInterval(this.backupUsage, this.backupUsageInterval)
|
||||
|
||||
// Note: Do not throw an error. This is a top-level function.
|
||||
return false
|
||||
|
||||
@@ -32,6 +32,9 @@ class UseCases {
|
||||
|
||||
// Run any startup Use Cases at the start of the app.
|
||||
async start () {
|
||||
// Load the usage stats from the database
|
||||
await this.usage.loadUsage()
|
||||
|
||||
console.log('Async Use Cases have been started.')
|
||||
|
||||
return true
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
for tracking the usage of REST API and JSON RPC calls. This library is used
|
||||
by admins to keep an eye on how many API calls were made in a 24-hour and
|
||||
1-hour time period.
|
||||
|
||||
Usage stats are held in memory. But they are periodically backed up to the
|
||||
Mongo database. On startup, the usage stats are loaded from the database.
|
||||
This allows the usage stats to be persisted across restarts.
|
||||
*/
|
||||
|
||||
// This global variable is used to share data between the REST middleware and
|
||||
@@ -19,11 +23,17 @@ class UsageUseCases {
|
||||
)
|
||||
}
|
||||
|
||||
// Encapsulate dependencies
|
||||
this.UsageModel = this.adapters.localdb.Usage
|
||||
|
||||
// Bind 'this' object to all subfunctions
|
||||
this.cleanUsage = this.cleanUsage.bind(this)
|
||||
this.getRestSummary = this.getRestSummary.bind(this)
|
||||
this.getTopIps = this.getTopIps.bind(this)
|
||||
this.getTopEndpoints = this.getTopEndpoints.bind(this)
|
||||
this.clearUsage = this.clearUsage.bind(this)
|
||||
this.saveUsage = this.saveUsage.bind(this)
|
||||
this.loadUsage = this.loadUsage.bind(this)
|
||||
|
||||
// State
|
||||
}
|
||||
@@ -108,6 +118,56 @@ class UsageUseCases {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the usage database data
|
||||
async clearUsage () {
|
||||
try {
|
||||
await this.UsageModel.deleteMany({})
|
||||
|
||||
// Debugging: verify the database is empty
|
||||
// Delete this code after debugging
|
||||
const usage = await this.UsageModel.find({})
|
||||
console.log('clearUsage() usage: ', usage)
|
||||
} catch (err) {
|
||||
console.error('Error in usage-use-cases.js/clearUsage()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
// Save the usage data to the database
|
||||
async saveUsage (inObj = {}) {
|
||||
try {
|
||||
for (let i = 0; i < restCalls.length; i++) {
|
||||
const thisRestCall = restCalls[i]
|
||||
|
||||
const usageData = {
|
||||
ip: thisRestCall.ip,
|
||||
url: thisRestCall.url,
|
||||
method: thisRestCall.method,
|
||||
timestamp: thisRestCall.timestamp
|
||||
}
|
||||
|
||||
const usage = new this.UsageModel(usageData)
|
||||
await usage.save()
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error in usage-use-cases.js/saveUsage()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
// Load usage data from the database
|
||||
async loadUsage () {
|
||||
try {
|
||||
const usage = await this.UsageModel.find({})
|
||||
// console.log('usage: ', usage)
|
||||
|
||||
restCalls = usage
|
||||
} catch (err) {
|
||||
console.error('Error in usage-use-cases.js/loadUsage(): ', err)
|
||||
// throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This Koa middleware is called any time there is a REST API. It logs the
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Liveness test runs before all other tests to ensure the server is running.
|
||||
*/
|
||||
|
||||
// Public npm libraries
|
||||
import { assert } from 'chai'
|
||||
import axios from 'axios'
|
||||
import testUtils from '../../utils/test-utils.js'
|
||||
|
||||
// const sinon = require('sinon')
|
||||
|
||||
// Local support libraries
|
||||
import config from '../../../config/index.js'
|
||||
// import Server from '../../../bin/server.js'
|
||||
// import testUtils from '../../utils/test-utils.js'
|
||||
// const adminLib = new AdminLib()
|
||||
|
||||
const LOCALHOST = `http://localhost:${config.port}`
|
||||
|
||||
describe('#Check Server Liveness', () => {
|
||||
// before(async () => {
|
||||
it('should confirm the server is running', async () => {
|
||||
try {
|
||||
const response = await axios.get(`${LOCALHOST}/`)
|
||||
assert(response.status === 200, 'Server is running, continuing with E2E tests.')
|
||||
} catch (err) {
|
||||
console.log('\nServer is not running, exiting tests.')
|
||||
console.log('Start the server with `npm run start:e2e:server` before running E2E tests.\n')
|
||||
console.log('Ensure running npm run docs before running the test server')
|
||||
process.exit(1)
|
||||
}
|
||||
})
|
||||
it('should confirm the server is running over test enviroment', async () => {
|
||||
try {
|
||||
const res = await testUtils.loginAdminUser()
|
||||
assert.property(res, 'user')
|
||||
assert.property(res, 'token')
|
||||
assert.property(res, 'id')
|
||||
} catch (err) {
|
||||
console.log('\nServer is not running over test enviroment, exiting tests.')
|
||||
console.log('Start the server with `npm run start:e2e:server` before running E2E tests.\n')
|
||||
process.exit(1)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -13,10 +13,8 @@ import axios from 'axios'
|
||||
|
||||
// Local support libraries
|
||||
import config from '../../../config/index.js'
|
||||
import Server from '../../../bin/server.js'
|
||||
// import Server from '../../../bin/server.js'
|
||||
import testUtils from '../../utils/test-utils.js'
|
||||
import AdminLib from '../../../src/adapters/admin.js'
|
||||
const adminLib = new AdminLib()
|
||||
|
||||
// const request = supertest.agent(app.listen())
|
||||
const context = {}
|
||||
@@ -26,10 +24,12 @@ const LOCALHOST = `http://localhost:${config.port}`
|
||||
if (!config.noMongo) {
|
||||
describe('Auth', () => {
|
||||
before(async () => {
|
||||
const app = new Server()
|
||||
// const app = new Server()
|
||||
|
||||
// This should be the first instruction. It starts the REST API server.
|
||||
await app.startServer()
|
||||
// await app.startServer()
|
||||
|
||||
// TODO:
|
||||
|
||||
// Stop the IPFS node for the rest of the e2e tests.
|
||||
// await app.controllers.adapters.ipfs.stop()
|
||||
@@ -37,9 +37,6 @@ if (!config.noMongo) {
|
||||
// Delete all previous users in the database.
|
||||
await testUtils.deleteAllUsers()
|
||||
|
||||
// Create a new admin user.
|
||||
await adminLib.createSystemUser()
|
||||
|
||||
const userObj = {
|
||||
email: 'test@test.com',
|
||||
password: 'pass',
|
||||
|
||||
@@ -5,22 +5,11 @@ import axios from 'axios'
|
||||
import sinon from 'sinon'
|
||||
import util from 'util'
|
||||
|
||||
import UserController from '../../../src/controllers/rest-api/users/controller.js'
|
||||
import Adapters from '../../../src/adapters/index.js'
|
||||
import UseCases from '../../../src/use-cases/index.js'
|
||||
|
||||
// import UserController from '../../../src/controllers/rest-api/users/controller.js'
|
||||
// import Adapters from '../../../src/adapters/index.js'
|
||||
import EventEmitter from 'events'
|
||||
util.inspect.defaultOptions = { depth: 1 }
|
||||
|
||||
const LOCALHOST = `http://localhost:${config.port}`
|
||||
|
||||
const context = {}
|
||||
const adapters = new Adapters({ eventEmitter: new EventEmitter() })
|
||||
// import UseCases from '../../../src/use-cases/index.js'
|
||||
|
||||
let uut
|
||||
let sandbox
|
||||
|
||||
// const mockContext = require('../../unit/mocks/ctx-mock').context
|
||||
@@ -56,9 +45,6 @@ if (!config.noMongo) {
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
const useCases = new UseCases({ adapters })
|
||||
uut = new UserController({ adapters, useCases })
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
})
|
||||
|
||||
@@ -274,33 +260,6 @@ if (!config.noMongo) {
|
||||
assert.hasAnyKeys(users[0], ['type', '_id', 'email'])
|
||||
assert.isNumber(users.length)
|
||||
})
|
||||
|
||||
it('should return a 422 http status if biz-logic throws an error', async () => {
|
||||
try {
|
||||
const { token } = context
|
||||
|
||||
// Force an error
|
||||
sandbox
|
||||
.stub(uut.useCases.user, 'getAllUsers')
|
||||
.rejects(new Error('test error'))
|
||||
|
||||
const options = {
|
||||
method: 'GET',
|
||||
url: `${LOCALHOST}/users`,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
await axios(options)
|
||||
|
||||
assert.fail('Unexpected code path!')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.equal(err.response.status, 422)
|
||||
assert.equal(err.response.data, 'test error')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('GET /users/:id', () => {
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
import { assert } from 'chai'
|
||||
import Admin from '../../../src/adapters/admin.js'
|
||||
import sinon from 'sinon'
|
||||
import util from 'util'
|
||||
import config from '../../../config/index.js'
|
||||
|
||||
util.inspect.defaultOptions = { depth: 1 }
|
||||
|
||||
let sandbox
|
||||
let uut
|
||||
describe('Admin', () => {
|
||||
beforeEach(() => {
|
||||
uut = new Admin()
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
if (!config.noMongo) {
|
||||
describe('loginAdmin()', () => {
|
||||
it('should logind admin', async () => {
|
||||
try {
|
||||
const error = new Error('test error')
|
||||
error.response = {
|
||||
status: 422
|
||||
}
|
||||
// sandbox.stub(uut.axios, 'request').onFirstCall().throws(error)
|
||||
|
||||
const result = await uut.loginAdmin()
|
||||
const user = result.data.user
|
||||
|
||||
assert.property(user, '_id')
|
||||
assert.property(user, 'email')
|
||||
assert.property(user, 'type')
|
||||
|
||||
assert.isString(user._id)
|
||||
assert.isString(user.email)
|
||||
assert.isString(user.type)
|
||||
|
||||
assert.equal(user.type, 'admin')
|
||||
} catch (err) {
|
||||
assert(false, 'Unexpected result')
|
||||
}
|
||||
})
|
||||
|
||||
it('should handle axios error', async () => {
|
||||
try {
|
||||
// Returns an erroneous password to force
|
||||
// an auth error
|
||||
sandbox.stub(uut.jsonFiles, 'readJSON').resolves({ password: 'wrong' })
|
||||
|
||||
await uut.loginAdmin()
|
||||
assert(false, 'Unexpected result')
|
||||
} catch (err) {
|
||||
assert.equal(err.response.status, 401)
|
||||
assert.include(err.response.data, 'Unauthorized')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('createSystemUser()', () => {
|
||||
it('should create admin', async () => {
|
||||
try {
|
||||
const result = await uut.createSystemUser()
|
||||
|
||||
assert.property(result, 'email')
|
||||
assert.property(result, 'password')
|
||||
assert.property(result, 'id')
|
||||
assert.property(result, 'token')
|
||||
} catch (err) {
|
||||
assert(false, 'Unexpected result')
|
||||
}
|
||||
})
|
||||
|
||||
it('should handle axios error', async () => {
|
||||
try {
|
||||
const error1 = new Error('test error')
|
||||
error1.response = {
|
||||
status: 422
|
||||
}
|
||||
const error2 = new Error('test error')
|
||||
error1.response = {
|
||||
status: 500
|
||||
}
|
||||
// The loginAdmin() function in some use cases is recursive
|
||||
// after handling the 422 error, it gets called again
|
||||
sandbox
|
||||
.stub(uut.axios, 'request')
|
||||
.onFirstCall()
|
||||
.throws(error1)
|
||||
.onSecondCall()
|
||||
.throws(error2)
|
||||
|
||||
await uut.createSystemUser()
|
||||
assert(false, 'Unexpected result')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
|
||||
it('should handle errors when remove user', async () => {
|
||||
try {
|
||||
const error1 = new Error('test error')
|
||||
error1.response = {
|
||||
status: 422
|
||||
}
|
||||
sandbox.stub(uut.axios, 'request').throws(error1)
|
||||
sandbox.stub(uut.User, 'deleteOne').throws(new Error('test error'))
|
||||
|
||||
await uut.createSystemUser()
|
||||
assert(false, 'Unexpected result')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,121 @@
|
||||
import { assert } from 'chai'
|
||||
import Admin from '../../../src/adapters/admin.js'
|
||||
import sinon from 'sinon'
|
||||
import util from 'util'
|
||||
import config from '../../../config/index.js'
|
||||
|
||||
util.inspect.defaultOptions = { depth: 1 }
|
||||
|
||||
let sandbox
|
||||
let uut
|
||||
describe('Admin', () => {
|
||||
beforeEach(() => {
|
||||
uut = new Admin()
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
if (!config.noMongo) {
|
||||
describe('loginAdmin()', () => {
|
||||
// it('should login admin', async () => {
|
||||
// try {
|
||||
// sandbox.stub(uut.axios, 'request').resolves(true)
|
||||
|
||||
// const result = await uut.loginAdmin()
|
||||
// assert.isTrue(result)
|
||||
// } catch (err) {
|
||||
// assert(false, 'Unexpected result')
|
||||
// }
|
||||
// })
|
||||
|
||||
it('should handle axios error', async () => {
|
||||
try {
|
||||
// Returns an erroneous password to force
|
||||
// an auth error
|
||||
sandbox.stub(uut.axios, 'request').throws(new Error('test error'))
|
||||
sandbox.stub(uut.jsonFiles, 'readJSON').resolves({ password: 'wrong' })
|
||||
|
||||
await uut.loginAdmin()
|
||||
assert(false, 'Unexpected result')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('createSystemUser()', () => {
|
||||
it('should create admin', async () => {
|
||||
try {
|
||||
await uut.deleteExistingSystemUser()
|
||||
const result = await uut.createSystemUser()
|
||||
|
||||
assert.property(result, 'email')
|
||||
assert.property(result, 'password')
|
||||
assert.property(result, 'id')
|
||||
assert.property(result, 'token')
|
||||
} catch (err) {
|
||||
assert(false, 'Unexpected result')
|
||||
}
|
||||
})
|
||||
it('should update admin password', async () => {
|
||||
try {
|
||||
uut.config.adminPassword = 'newpassword'
|
||||
|
||||
const fakeUser = {
|
||||
password: 'oldpassword',
|
||||
save: () => { return 'token' },
|
||||
generateToken: () => { return 'token' }
|
||||
}
|
||||
|
||||
sandbox.stub(uut.User, 'findOne').resolves(fakeUser)
|
||||
sandbox.stub(uut.jsonFiles, 'writeJSON').resolves(true)
|
||||
const result = await uut.createSystemUser()
|
||||
|
||||
assert.property(result, 'email')
|
||||
assert.property(result, 'password')
|
||||
assert.property(result, 'id')
|
||||
assert.property(result, 'token')
|
||||
|
||||
assert.equal(fakeUser.password, 'newpassword', 'password should be updated')
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
assert(false, 'Unexpected result')
|
||||
}
|
||||
})
|
||||
|
||||
it('should handle error', async () => {
|
||||
try {
|
||||
sandbox.stub(uut.User, 'findOne').throws(new Error('test error'))
|
||||
await uut.createSystemUser()
|
||||
assert.fail('Unexpected result')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('deleteExistingSystemUser()', () => {
|
||||
it('should delete admin', async () => {
|
||||
try {
|
||||
sandbox.stub(uut.User, 'deleteOne').resolves(true)
|
||||
const result = await uut.deleteExistingSystemUser()
|
||||
assert.isTrue(result)
|
||||
} catch (err) {
|
||||
assert(false, 'Unexpected result')
|
||||
}
|
||||
})
|
||||
|
||||
it('should handle error when deleting admin', async () => {
|
||||
try {
|
||||
sandbox.stub(uut.User, 'deleteOne').throws(new Error('test error'))
|
||||
await uut.deleteExistingSystemUser()
|
||||
assert.fail('Unexpected result')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -79,4 +79,32 @@ describe('#Users-REST-Router', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#createUser', () => {
|
||||
it('should ignore admin validator when DISABLE_NEW_ACCOUNTS is not defined', async () => {
|
||||
// Stub functions
|
||||
const validationSpy = sandbox.stub(uut.validators, 'ensureAdmin').resolves(true)
|
||||
sandbox.stub(uut.userRESTController, 'createUser').resolves(true)
|
||||
|
||||
// Call function
|
||||
await uut.createUser()
|
||||
|
||||
// Assertions
|
||||
assert.isTrue(validationSpy.notCalled, 'Admin validator should not be called')
|
||||
})
|
||||
it('should ensure admin when DISABLE_NEW_ACCOUNTS is defined', async () => {
|
||||
// Set environment variable
|
||||
process.env.DISABLE_NEW_ACCOUNTS = true
|
||||
|
||||
// Stub functions
|
||||
const validationSpy = sandbox.stub(uut.validators, 'ensureAdmin').resolves(true)
|
||||
sandbox.stub(uut.userRESTController, 'createUser').resolves(true)
|
||||
|
||||
// Call function
|
||||
await uut.createUser()
|
||||
|
||||
// Assertions
|
||||
assert.isTrue(validationSpy.calledOnce, 'Admin validator should be called')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -66,19 +66,19 @@ describe('#Timer-Controllers', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('#exampleTimerFunc', () => {
|
||||
it('should kick off the Use Case', async () => {
|
||||
const result = await uut.exampleTimerFunc()
|
||||
// describe('#exampleTimerFunc', () => {
|
||||
// it('should kick off the Use Case', async () => {
|
||||
// const result = await uut.exampleTimerFunc()
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
// assert.equal(result, true)
|
||||
// })
|
||||
|
||||
it('should return false on error', async () => {
|
||||
const result = await uut.exampleTimerFunc(true)
|
||||
// it('should return false on error', async () => {
|
||||
// const result = await uut.exampleTimerFunc(true)
|
||||
|
||||
assert.equal(result, false)
|
||||
})
|
||||
})
|
||||
// assert.equal(result, false)
|
||||
// })
|
||||
// })
|
||||
|
||||
describe('#cleanUsage', () => {
|
||||
it('should kick off the Use Case', async () => {
|
||||
@@ -94,4 +94,21 @@ describe('#Timer-Controllers', () => {
|
||||
assert.equal(result, false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#backupUsage', () => {
|
||||
it('should kick off the Use Case', async () => {
|
||||
const result = await uut.backupUsage()
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
it('should return false on error', async () => {
|
||||
sandbox.stub(uut.useCases.usage, 'clearUsage').throws(new Error('test error'))
|
||||
// sandbox.stub(uut.useCases.usage, 'saveUsage').throws(new Error('test error'))
|
||||
|
||||
const result = await uut.backupUsage()
|
||||
|
||||
assert.equal(result, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -65,6 +65,14 @@ class UsageUseCaseMock {
|
||||
async getTopEndpoints(existingUser, newData) {
|
||||
return true
|
||||
}
|
||||
|
||||
async clearUsage() {
|
||||
return true
|
||||
}
|
||||
|
||||
async saveUsage() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class IpfsUseCaseMock {
|
||||
|
||||
+45
-20
@@ -8,7 +8,6 @@ import axios from 'axios'
|
||||
|
||||
// Local libraries
|
||||
import config from '../../config/index.js'
|
||||
import User from '../../src/adapters/localdb/models/users.js'
|
||||
import JsonFiles from '../../src/adapters/json-files.js'
|
||||
|
||||
// Hack to get __dirname back.
|
||||
@@ -33,24 +32,6 @@ async function cleanDb () {
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all users in the database. This ensures there is no previous state
|
||||
// to confuse tests.
|
||||
async function deleteAllUsers () {
|
||||
try {
|
||||
// Get all the users in the DB.
|
||||
const users = await User.find({}, '-password')
|
||||
// console.log(`users: ${JSON.stringify(users, null, 2)}`)
|
||||
|
||||
// Delete each user.
|
||||
for (let i = 0; i < users.length; i++) {
|
||||
const thisUser = users[i]
|
||||
await thisUser.remove()
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error in test-utils.js/deleteAllUsers()')
|
||||
}
|
||||
}
|
||||
|
||||
// This function is used to create new users.
|
||||
// userObj = {
|
||||
// username,
|
||||
@@ -170,12 +151,56 @@ async function getAdminJWT () {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
// Fetches all users from the database.
|
||||
async function getAllUsers () {
|
||||
try {
|
||||
const adminJWT = await getAdminJWT()
|
||||
const options = {
|
||||
method: 'GET',
|
||||
url: `${LOCALHOST}/users`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${adminJWT}`
|
||||
}
|
||||
}
|
||||
const result = await axios(options)
|
||||
return result.data.users
|
||||
} catch (err) {
|
||||
console.error('Error in test/utils.js/getAllUsers()', err)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
// Deletes all users from the database.
|
||||
async function deleteAllUsers () {
|
||||
try {
|
||||
const allUsers = await getAllUsers()
|
||||
const adminJWT = await getAdminJWT()
|
||||
for (let i = 0; i < allUsers.length; i++) {
|
||||
const user = allUsers[i]
|
||||
// Skip the admin user.
|
||||
if (user.type === 'admin') {
|
||||
continue
|
||||
}
|
||||
const options = {
|
||||
method: 'DELETE',
|
||||
url: `${LOCALHOST}/users/${user._id}`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${adminJWT}`
|
||||
}
|
||||
}
|
||||
await axios(options)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error in test/utils.js/deleteAllUsers()', err)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
export default {
|
||||
cleanDb,
|
||||
createUser,
|
||||
loginTestUser,
|
||||
loginAdminUser,
|
||||
getAdminJWT,
|
||||
deleteAllUsers
|
||||
deleteAllUsers,
|
||||
getAllUsers
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import mongoose from 'mongoose'
|
||||
import config from '../../config/index.js'
|
||||
import User from '../../src/adapters/localdb/models/users.js'
|
||||
|
||||
const EMAIL = 'test@test.com'
|
||||
const PASSWORD = 'pass'
|
||||
const EMAIL = process.env.EMAIL || 'test@test3.com'
|
||||
const PASSWORD = process.env.PASSWORD || 'pass'
|
||||
|
||||
async function addUser () {
|
||||
// Connect to the Mongo Database.
|
||||
@@ -13,8 +14,6 @@ async function addUser () {
|
||||
{ useNewUrlParser: true, useUnifiedTopology: true }
|
||||
)
|
||||
|
||||
const User = require('../../src/models/users')
|
||||
|
||||
const userData = {
|
||||
email: EMAIL,
|
||||
password: PASSWORD
|
||||
|
||||
Reference in New Issue
Block a user