Skip to content

Commit

Permalink
fix: invalid poeAddressVerified when changing the address (#989)
Browse files Browse the repository at this point in the history
  • Loading branch information
lautarodragan authored Aug 17, 2019
1 parent adcc327 commit 03d0c10
Show file tree
Hide file tree
Showing 4 changed files with 334 additions and 5 deletions.
22 changes: 22 additions & 0 deletions src/api/accounts/PatchAccount.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,28 @@ describe('isPoeAddressVerified()', async (assert) => {
expected: false,
})

assert({
given: 'clearing the address of a verified account',
should: 'return false',
actual: isPoeAddressVerified('', undefined, {
...account,
poeAddressVerified: true,
}),
expected: false,
})

assert({
given: 'clearing the address of a verified account (with complete signature data)',
should: 'return false',
actual: isPoeAddressVerified('', undefined, {
...account,
poeAddress: signedMessage.address,
poeAddressSignature: signedMessage.sig,
poeAddressVerified: true,
}),
expected: false,
})

// Default cases - nothing provided in request should not change anything

assert({
Expand Down
10 changes: 5 additions & 5 deletions src/api/accounts/PatchAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ export const PatchAccount = (accountController: AccountController) => async (ctx
}

export const isPoeAddressVerified = (poeAddress: string, poeSignature: string, account: Account): boolean =>
(poeAddress || poeSignature)
(poeAddress !== undefined || poeSignature !== undefined) // TODO: https://github.com/microsoft/TypeScript/issues/26578
? signatureIsValid(
poeAddress || account.poeAddress,
account.poeAddressMessage,
poeSignature || account.poeAddressSignature,
)
poeAddress !== undefined ? poeAddress : account.poeAddress,
account.poeAddressMessage,
poeSignature !== undefined ? poeSignature : account.poeAddressSignature,
)
: !!account.poeAddressVerified
1 change: 1 addition & 0 deletions tests/integration/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ import './cors.test'
import './create-account.test'
import './health.test'
import './login.test'
import './patch-account.test'
import './securityHeaders.test'
import './upload-archive.test'
306 changes: 306 additions & 0 deletions tests/integration/patch-account.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
import { createReadStream } from 'fs'

import { privateToAddress, ecsign, hashPersonalMessage, toRpcSig } from 'ethereumjs-util'
import fetch from 'node-fetch'
import { describe } from 'riteway'

import { Frost } from '../../src/Frost'
import { Path } from '../../src/api/Path'
import {
testUserEmail,
testUserPassword,
FROST_HOST,
FROST_PORT,
FROST_URL,
delay,
runtimeId,
createDatabase,
} from '../helpers/utils'

const createUserOptions = {
method: 'post',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: testUserEmail, password: testUserPassword }),
}

describe('Changing the poeAddress sets poeAddressVerified back to false', async assert => {
const db = await createDatabase(`test-integration-frost-api-poet-${runtimeId()}`)

const server = await Frost({
FROST_PORT,
FROST_HOST,
MONGODB_DATABASE: db.settings.tempDbName,
MONGODB_USER: db.settings.tempDbUser,
MONGODB_PASSWORD: db.settings.tempDbPassword,
MONGODB_URL: 'mongodb://localhost:27017/frost', // force calc of url in configuration
LOGGING_LEVEL: 'error',
POE_BALANCE_MINIMUM: 0,
})
await delay(5000)

const response = await fetch(`${FROST_URL}${Path.ACCOUNTS}`, createUserOptions)
const createdUser = await response.json()
const proofOfPoeUrl = `${FROST_URL}${Path.ACCOUNTS_ID_POE_CHALLENGE}`.replace(':issuer', createdUser.issuer)

const getProofOfPoeMessageResponse = await fetch(proofOfPoeUrl, {
method: 'post',
headers: {
'Content-Type': 'application/json',
token: createdUser.token,
},
})
const { poeAddressMessage } = await getProofOfPoeMessageResponse.json()

assert({
given: `a request for a Proof of POE Message`,
should: 'return a Proof of POE Message',
actual: typeof poeAddressMessage,
expected: 'string',
})

assert({
given: `a request for a Proof of POE Message`,
should: 'return a Proof of POE Message',
actual: poeAddressMessage.startsWith('Proof of POE'),
expected: true,
})

const pk = '0x411813af354a4bfcefc0e4408c51deb6654ae88ddd6cf8a47504c49449f6d462'
const pkBuffer = Buffer.from(pk.slice(2), 'hex')
const poeAddress = '0x' + privateToAddress(pkBuffer).toString('hex')
const hashedmsg = hashPersonalMessage(Buffer.from(poeAddressMessage))
const sig = ecsign(hashedmsg, pkBuffer)
const poeSignature = toRpcSig(sig.v, sig.r, sig.s)

const patchAccountUrl = `${FROST_URL}${Path.ACCOUNTS_ID}`.replace(':issuer', createdUser.issuer)
const patchAccountResponse = await fetch(patchAccountUrl, {
method: 'patch',
headers: {
'Content-Type': 'application/json',
token: createdUser.token,
},
body: JSON.stringify({
poeAddress,
poeSignature,
}),
})

assert({
given: `a PATCH /accounts with poeAddress and poeSignature`,
should: 'succeed',
actual: patchAccountResponse.ok,
expected: true,
})

const patchedAccount = await patchAccountResponse.json()

assert({
given: `a patched account with poeAddress and poeSignature`,
should: 'have the same issuer',
actual: patchedAccount.issuer,
expected: createdUser.issuer,
})
assert({
given: `a patched account with poeAddress and poeSignature`,
should: 'have the same email',
actual: patchedAccount.email,
expected: testUserEmail,
})
assert({
given: `a patched account with poeAddress and poeSignature`,
should: 'have the same poeAddress',
actual: patchedAccount.poeAddress,
expected: poeAddress,
})
assert({
given: `a patched account with poeAddress and poeSignature`,
should: 'have the same poeSignature',
actual: patchedAccount.poeSignature,
expected: poeSignature,
})
assert({
given: `a patched account with poeAddress and poeSignature`,
should: 'have poeAddressVerified = true',
actual: patchedAccount.poeAddressVerified,
expected: true,
})

const newPoeAddress = 'address'

const patchAccountResponse2 = await fetch(patchAccountUrl, {
method: 'patch',
headers: {
'Content-Type': 'application/json',
token: createdUser.token,
},
body: JSON.stringify({
poeAddress: newPoeAddress,
}),
})

assert({
given: `a PATCH /accounts with poeAddress and poeSignature`,
should: 'succeed',
actual: patchAccountResponse2.ok,
expected: true,
})

const patchedAccount2 = await patchAccountResponse2.json()

assert({
given: `a patched account with changed poeAddress`,
should: 'have the new poeAddress',
actual: patchedAccount2.poeAddress,
expected: newPoeAddress,
})
assert({
given: `a patched account with changed poeAddress`,
should: 'have poeAddressVerified = false',
actual: patchedAccount2.poeAddressVerified,
expected: false,
})

await server.stop()
await db.teardown()
})

describe('Clearing the poeAddress sets poeAddressVerified back to false', async assert => {
const db = await createDatabase(`test-integration-frost-api-poet-${runtimeId()}`)

const server = await Frost({
FROST_PORT,
FROST_HOST,
MONGODB_DATABASE: db.settings.tempDbName,
MONGODB_USER: db.settings.tempDbUser,
MONGODB_PASSWORD: db.settings.tempDbPassword,
MONGODB_URL: 'mongodb://localhost:27017/frost', // force calc of url in configuration
LOGGING_LEVEL: 'error',
POE_BALANCE_MINIMUM: 0,
})
await delay(5000)

const response = await fetch(`${FROST_URL}${Path.ACCOUNTS}`, createUserOptions)
const createdUser = await response.json()
const proofOfPoeUrl = `${FROST_URL}${Path.ACCOUNTS_ID_POE_CHALLENGE}`.replace(':issuer', createdUser.issuer)

const getProofOfPoeMessageResponse = await fetch(proofOfPoeUrl, {
method: 'post',
headers: {
'Content-Type': 'application/json',
token: createdUser.token,
},
})
const { poeAddressMessage } = await getProofOfPoeMessageResponse.json()

assert({
given: `a request for a Proof of POE Message`,
should: 'return a Proof of POE Message',
actual: typeof poeAddressMessage,
expected: 'string',
})

assert({
given: `a request for a Proof of POE Message`,
should: 'return a Proof of POE Message',
actual: poeAddressMessage.startsWith('Proof of POE'),
expected: true,
})

const pk = '0x411813af354a4bfcefc0e4408c51deb6654ae88ddd6cf8a47504c49449f6d462'
const pkBuffer = Buffer.from(pk.slice(2), 'hex')
const poeAddress = '0x' + privateToAddress(pkBuffer).toString('hex')
const hashedmsg = hashPersonalMessage(Buffer.from(poeAddressMessage))
const sig = ecsign(hashedmsg, pkBuffer)
const poeSignature = toRpcSig(sig.v, sig.r, sig.s)

const patchAccountUrl = `${FROST_URL}${Path.ACCOUNTS_ID}`.replace(':issuer', createdUser.issuer)
const patchAccountResponse = await fetch(patchAccountUrl, {
method: 'patch',
headers: {
'Content-Type': 'application/json',
token: createdUser.token,
},
body: JSON.stringify({
poeAddress,
poeSignature,
}),
})

assert({
given: `a PATCH /accounts with poeAddress and poeSignature`,
should: 'succeed',
actual: patchAccountResponse.ok,
expected: true,
})

const patchedAccount = await patchAccountResponse.json()

assert({
given: `a patched account with poeAddress and poeSignature`,
should: 'have the same issuer',
actual: patchedAccount.issuer,
expected: createdUser.issuer,
})
assert({
given: `a patched account with poeAddress and poeSignature`,
should: 'have the same email',
actual: patchedAccount.email,
expected: testUserEmail,
})
assert({
given: `a patched account with poeAddress and poeSignature`,
should: 'have the same poeAddress',
actual: patchedAccount.poeAddress,
expected: poeAddress,
})
assert({
given: `a patched account with poeAddress and poeSignature`,
should: 'have the same poeSignature',
actual: patchedAccount.poeSignature,
expected: poeSignature,
})
assert({
given: `a patched account with poeAddress and poeSignature`,
should: 'have poeAddressVerified = true',
actual: patchedAccount.poeAddressVerified,
expected: true,
})

const newPoeAddress = ''

const patchAccountResponse2 = await fetch(patchAccountUrl, {
method: 'patch',
headers: {
'Content-Type': 'application/json',
token: createdUser.token,
},
body: JSON.stringify({
poeAddress: newPoeAddress,
}),
})

assert({
given: `a PATCH /accounts with poeAddress and poeSignature`,
should: 'succeed',
actual: patchAccountResponse2.ok,
expected: true,
})

const patchedAccount2 = await patchAccountResponse2.json()

assert({
given: `a patched account with changed poeAddress`,
should: 'have the new poeAddress',
actual: patchedAccount2.poeAddress,
expected: newPoeAddress,
})
assert({
given: `a patched account with changed poeAddress`,
should: 'have poeAddressVerified = false',
actual: patchedAccount2.poeAddressVerified,
expected: false,
})

await server.stop()
await db.teardown()
})

0 comments on commit 03d0c10

Please sign in to comment.