Skip to content

Commit

Permalink
add logs to twilio api, lint fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
serdiukov-o-nordwhale committed Sep 18, 2020
1 parent b332f51 commit 9aec2d3
Show file tree
Hide file tree
Showing 20 changed files with 101 additions and 83 deletions.
3 changes: 1 addition & 2 deletions .env.dev
Expand Up @@ -8,8 +8,6 @@ MNEMONIC="they bus duty candy uncover assault bullet kitchen kit acid spin physi
INFURA_API=
NETWORK=develop
LOG_LEVEL=debug
OTP_DIGITS=6
OTP_TTL_MINUTES=5
WALLET_URL=http://localhost:3000
MAUTIC_URL=https://go.gooddollar.org
MAUTIC_TOKEN=""
Expand All @@ -34,6 +32,7 @@ ENABLE_MONGO_LOCK=false
FUSE_API=https://explorer.fuse.io
TWILIO_AUTH_ID=
TWILIO_AUTH_TOKEN=
TWILIO_VERIFY_ID=
NUMBER_OF_ADMIN_WALLET_ACCOUNTS=5
ADMIN_MIN_BALANCE=100000
FACEBOOK_GRAPH_API_URL=https://graph.facebook.com/
Expand Down
3 changes: 1 addition & 2 deletions .env.example
Expand Up @@ -14,8 +14,6 @@ RELEASE_PHASE=
PLIVO_AUTH_ID=MADSFJASDF2341ASDF0G
PLIVO_AUTH_TOKEN=YWRiMl2nomwsdfoQeTBadk9290dkmEAVB13zg5G5
PLIVO_PHONE_NUMBER=1555555555
OTP_DIGITS=6
OTP_TTL_MINUTES=5
RECAPTCHA_SECRET=
SENDGRID_API_KEY=
SENDGRID_TEMPLATE_RECOVERY_INSTRUCTIONS=
Expand Down Expand Up @@ -57,6 +55,7 @@ ENABLE_MONGO_LOCK=
FUSE_API=https://explorer.fuse.io
TWILIO_AUTH_ID=
TWILIO_AUTH_TOKEN=
TWILIO_VERIFY_ID=
NUMBER_OF_ADMIN_WALLET_ACCOUNTS=1
#minimum balance in gwei of admin account to be valid
ADMIN_MIN_BALANCE=
Expand Down
3 changes: 1 addition & 2 deletions .env.test
Expand Up @@ -7,8 +7,6 @@ GUNDB_SERVERMODE=false
MNEMONIC="they bus duty candy uncover assault bullet kitchen kit acid spin physical"
NETWORK=develop
LOG_LEVEL=debug
OTP_DIGITS=6
OTP_TTL_MINUTES=5
RECAPTCHA_SECRET=
WALLET_URL=http://localhost:3000
# Zoom (Face Recognition / Liveness Test API) License key
Expand All @@ -30,6 +28,7 @@ WEB3_SITE_URL=https://inivtation.herokuapp.com
FUSE_API=https://explorer.fuse.io
TWILIO_AUTH_ID=
TWILIO_AUTH_TOKEN=
TWILIO_VERIFY_ID=
ADMIN_MIN_BALANCE=100000
SECURE_KEY=d41d8cd98f00b204e9800998ecf8427f
ENABLE_MONGO_LOCK=false
Expand Down
6 changes: 3 additions & 3 deletions src/imports/__tests__/generateOTP.js
Expand Up @@ -2,7 +2,7 @@
* @jest-environment node
*/

import { generateOTP } from '../otp'
import OTP from '../otp'

describe('generateOTP positive values', () => {
// Given
Expand All @@ -11,7 +11,7 @@ describe('generateOTP positive values', () => {
lengths.forEach(length => {
it(`should generate an OTP code of ${length} chars for length = ${length}`, () => {
// When
const otp = generateOTP(length)
const otp = OTP.generateOTP(length)

// Then
expect(otp.length).toBe(length)
Expand All @@ -26,7 +26,7 @@ describe('generateOTP negative values and zero', () => {
lengths.forEach(length => {
it(`should generate an OTP equal to '0' for: ${length}`, () => {
// When
const otp = generateOTP(length)
const otp = OTP.generateOTP(length)

// Then
expect(otp.length).toBe(1)
Expand Down
2 changes: 1 addition & 1 deletion src/imports/logger/ErrorsTransport.js
Expand Up @@ -2,7 +2,7 @@ import * as Sentry from '@sentry/node'
import { RewriteFrames } from '@sentry/integrations'
import Transport from 'winston-transport'
import { SPLAT } from 'triple-beam'
import { assign, forEach, bindAll, trimEnd } from 'lodash'
import { forEach, trimEnd } from 'lodash'

import Config from '../../server/server.config'

Expand Down
72 changes: 46 additions & 26 deletions src/imports/otp.js
Expand Up @@ -3,48 +3,68 @@ import random from 'math-random'
import Twilio from 'twilio'

import conf from '../server/server.config'
import logger from './logger'
import type { UserRecord } from './types'

/**
* Creates an OTP code and returns it as a string
* @param {number} length - length of OTP code
* @returns {string}
*/
export const generateOTP = (length: number = 0): string => {
const exponent = length - 1
const base = Number(`1e${exponent}`)
const multiplier = Number(`9e${exponent}`)
export default new (class {
constructor(Config, Twilio, logger) {
const { twilioAuthID, twilioAuthToken, twilioVerifyID } = Config
const { services } = Twilio(twilioAuthID, twilioAuthToken).verify

return Math.floor(base + random() * multiplier).toString()
}
this.log = logger
this.service = services(twilioVerifyID)
}

export default new (class {
constructor(Config, Twilio) {
const { twilioAuthID, twilioAuthToken, twilioVerifyID, otpDigits } = Config
/**
* Creates an OTP code and returns it as a string
* @param {number} length - length of OTP code
* @returns {string}
*/
generateOTP(length: number = 0): string {
const exponent = length - 1
const base = Number(`1e${exponent}`)
const multiplier = Number(`9e${exponent}`)

this.client = Twilio(twilioAuthID, twilioAuthToken)
this.options = { friendlyName: 'GoodDollar', codeLength: otpDigits }
this.service = this.client.verify.services(twilioVerifyID)
return Math.floor(base + random() * multiplier).toString()
}

/**
* Generates and sends an OTP code to the user's mobile number
* @param {UserRecord} user - object with user's information
* @returns {Promise<void>}
* @returns {Promise<object>}
*/
async sendOTP(user: UserRecord): Promise<void> {
const options = { to: user.mobile, channel: 'sms' }
async sendOTP(user: UserRecord): Promise<object> {
const { mobile } = user
const { log, service } = this
const options = { to: mobile, channel: 'sms' }

try {
return await service.verifications.create(options)
} catch (exception) {
const { message } = exception

return this.service.verifications.create(options)
log.error('Error sending OTP:', message, exception, { mobile })
throw exception
}
}

/**
* Checks OTP code sent to the user's mobile number
* @param {UserRecord} user - object with user's information
* @returns {Promise<string>}
* @returns {Promise<object>}
*/
async checkOTP(user: UserRecord, code: string): Promise<boolean> {
const options = { to: user.mobile, code }
return this.service.verificationChecks.create(options)
async checkOTP(user: UserRecord, code: string): Promise<object> {
const { mobile } = user
const { log, service } = this
const options = { to: mobile, code }

try {
return await service.verificationChecks.create(options)
} catch (exception) {
const { message } = exception

log.error('Error verification OTP:', message, exception, { mobile, code })
throw exception
}
}
})(conf, Twilio)
})(conf, Twilio, logger.child({ from: 'Twilio' }))
23 changes: 17 additions & 6 deletions src/server/blockchain/__tests__/adminWallet.test.js
Expand Up @@ -2,7 +2,6 @@ import Web3 from 'web3'
import AdminWallet from '../AdminWallet'

import txManager from '../../utils/tx-manager'
import { delay } from '../../utils/timeout'

const web3 = new Web3()
const generateWalletAddress = () => web3.eth.accounts.create().address
Expand All @@ -27,54 +26,66 @@ describe('adminwallet', () => {

test('adminWallet can whitelist user', async () => {
const unverifiedAddress = generateWalletAddress()
const tx = await AdminWallet.whitelistUser(unverifiedAddress, 'did:gd' + Math.random())
await AdminWallet.whitelistUser(unverifiedAddress, 'did:gd' + Math.random())
const isVerified = await AdminWallet.isVerified(unverifiedAddress)

expect(isVerified).toBeTruthy()
})

test('adminWallet can authenticate user', async () => {
const unverifiedAddress = generateWalletAddress()
const tx = await AdminWallet.authenticateUser(unverifiedAddress)

await AdminWallet.authenticateUser(unverifiedAddress)

const isVerified = await AdminWallet.isVerified(unverifiedAddress)
const lastAuth = await AdminWallet.identityContract.methods
.lastAuthenticated(unverifiedAddress)
.call()
.then(_ => _.toNumber())

expect(isVerified).toBeFalsy()
expect(lastAuth).toBeGreaterThan(0)
})

test('adminWallet can blacklist user', async () => {
const unverifiedAddress = generateWalletAddress()
const tx = await AdminWallet.whitelistUser(unverifiedAddress, 'did:gd' + Math.random())
const tx2 = await AdminWallet.removeWhitelisted(unverifiedAddress)

await AdminWallet.whitelistUser(unverifiedAddress, 'did:gd' + Math.random())
await AdminWallet.removeWhitelisted(unverifiedAddress)

const isVerified = await AdminWallet.isVerified(unverifiedAddress)

expect(isVerified).not.toBeTruthy()
})

test('adminWallet throws exception', async () => {
const unverifiedAddress = '0x888185b656fe770677a91412f9f09B23A787242A'

expect(await AdminWallet.removeWhitelisted(unverifiedAddress).catch(e => false)).toBeFalsy()
})

test('adminWallet get balance correctly', async () => {
const balance = await AdminWallet.getBalance()

expect(balance > 0).toBeTruthy()
})

test('adminWallet receive queue nonce', async () => {
const promises = []

for (let i = 0; i < 5; i++) {
// await delay(300) //hack otherwise txes fail, looks like a web3 issue, sending txes out of order
const unverifiedAddress = generateWalletAddress()

promises.push(
AdminWallet.topWallet(unverifiedAddress)
.then(tx => tx.blockNumber)
.catch(e => e)
)
}

const res = await Promise.all(promises)
const uniqueBlocks = new Set(res)

res.forEach(n => expect(n).toEqual(expect.any(Number))) //check it was excuted in 5 or les blocks, if ganache is set 1 sec per block it should be under 5. otherwise 5.
expect(uniqueBlocks.size).toBeLessThanOrEqual(5)
expect(res).toBeTruthy()
Expand Down
2 changes: 1 addition & 1 deletion src/server/blockchain/__tests__/fishManager.test.js
@@ -1,7 +1,7 @@
import AdminWallet from '../AdminWallet'
import { fishManager } from '../stakingModelTasks'
import delay from 'delay'
import { version } from '@gooddollar/goodcontracts/package.json'

jest.setTimeout(20000)

const setNextDay = async () => {
Expand Down
2 changes: 1 addition & 1 deletion src/server/claimQueue/claimQueueAPI.js
Expand Up @@ -2,7 +2,7 @@
import { Router } from 'express'
import { body } from 'express-validator'
import passport from 'passport'
import { map, get, flatten } from 'lodash'
import { map, get } from 'lodash'
import { sha3 } from 'web3-utils'
import moment from 'moment'

Expand Down
2 changes: 1 addition & 1 deletion src/server/db/mongo/models/delayed-task.js
Expand Up @@ -34,7 +34,7 @@ export const DelayedTaskSchema = new Schema({
},
subject: {
// some parameters (subject, options) of the task. Could be string number or object corresponding to the kind of the task.
type: mongoose.Schema.Types.Mixed,
type: Mixed,
index: true
},
status: {
Expand Down
4 changes: 2 additions & 2 deletions src/server/db/mongo/models/user-private.js
@@ -1,7 +1,7 @@
import mongoose from '../../mongo-db.js'
import mongoose, { Schema } from '../../mongo-db.js'
import { MODEL_USER_PRIVATE } from './constants'

export const UserPrivateSchema = new mongoose.Schema({
export const UserPrivateSchema = new Schema({
identifier: {
type: String,
index: { unique: true },
Expand Down
4 changes: 2 additions & 2 deletions src/server/db/mongo/models/wallet-nonce.js
@@ -1,7 +1,7 @@
import mongoose from '../../mongo-db.js'
import mongoose, { Schema } from '../../mongo-db.js'
import { MODEL_WALLET_NONCE } from './constants'

export const WalletNonceSchema = new mongoose.Schema({
export const WalletNonceSchema = new Schema({
address: {
type: String
},
Expand Down
18 changes: 11 additions & 7 deletions src/server/gun/__tests__/GunDB.js
Expand Up @@ -11,10 +11,9 @@ import makeServer from '../../server-test'

jest.setTimeout(10000)
let server

describe('GunDB', () => {
beforeAll(async done => {
// storage.init(null, 'test', 'testdb')
// await storage.ready
server = makeServer(done)
})

Expand All @@ -27,12 +26,11 @@ describe('GunDB', () => {

it('Gun and SEA should work in tests', async () => {
const gun = Gun()
const password = 'test'
const uname = 'gdtest' + Math.random()
const user = gun.user()
let res = await new Promise((res, rej) => user.create('gdtest', 'test', res))
// expect(res.err).toBeFalsy()

await new Promise((res, rej) => user.create('gdtest', 'test', res))
let res2 = await new Promise((res, rej) => user.auth('gdtest', 'test', res))

expect(res2.err).toBeFalsy()
})

Expand All @@ -43,6 +41,7 @@ describe('GunDB', () => {

it('Should sign attestation', async () => {
let res = await storage.signClaim('dummykey', { passedTest: true })

expect(res).toMatchObject({
sig: expect.anything(),
claim: { passedTest: true },
Expand All @@ -56,7 +55,9 @@ describe('GunDB', () => {
},
issuedAt: expect.any(Date)
})

let msg = await SEA.verify(res.sig, storage.user.is.pub)

expect(msg).toBeTruthy()
})

Expand Down Expand Up @@ -135,15 +136,18 @@ describe('GunDB', () => {
const indexid = storage.getIndexId('walletAddress')
storage.user.leave()
const user = storage.gun.user()
let res = await new Promise((res, rej) => user.create('maluser', 'test', res))

await new Promise((res, rej) => user.create('maluser', 'test', res))
// expect(res.err).toBeFalsy()
let res2 = await new Promise((res, rej) => user.auth('maluser', 'test', res))
expect(res2.err).toBeFalsy()

let indexres = await storage.gun
.get(indexid)
.get('0x01')
.putAck('ABCDEF')
.catch(_ => false)

expect(indexres).toEqual(false)
})
})
4 changes: 2 additions & 2 deletions src/server/send/send.sendgrid.js
Expand Up @@ -6,7 +6,7 @@ import conf from '../server.config'
import logger from '../../imports/logger'

import type { UserRecord } from '../../imports/types'
import { generateOTP } from '../../imports/otp'
import OTP from '../../imports/otp'

sgMail.setApiKey(conf.sendGrid.apiKey)

Expand Down Expand Up @@ -82,7 +82,7 @@ export const sendRecoveryInstructionsByEmail = (to: string, name: string, key: s
* @returns {Promise<R>|Promise<R|*>}
*/
export const sendEmailConfirmationLink = (user: UserRecord) => {
const validationHash = generateOTP(10)
const validationHash = OTP.generateOTP(10)
const validationLink = `${conf.walletUrl}/Signup/EmailConfirmation/?validation=${validationHash}`

// structure required by SendGrid API: https://sendgrid.api-docs.io/v3.0/mail-send
Expand Down

0 comments on commit 9aec2d3

Please sign in to comment.