Skip to content

Commit

Permalink
[CON-222] Fix SequelizeUniqueConstraintError for blockchain track+use…
Browse files Browse the repository at this point in the history
…r IDs (#3660)
  • Loading branch information
theoilie authored and dmanjunath committed Aug 16, 2022
1 parent 2415086 commit 9f5d7de
Show file tree
Hide file tree
Showing 7 changed files with 344 additions and 51 deletions.
15 changes: 15 additions & 0 deletions creator-node/src/routes/audiusUsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,21 @@ router.post(
)
}

// Verify that wallet of the user on the blockchain for the given ID matches the user attempting to update
const serviceRegistry = req.app.get('serviceRegistry')
const { libs } = serviceRegistry
const userResp = await libs.contracts.UserFactoryClient.getUser(
blockchainUserId
)
if (
!userResp?.wallet ||
userResp.wallet.toLowerCase() !== req.session.wallet.toLowerCase()
) {
throw new Error(
`Owner wallet ${userResp.wallet} of blockchainUserId ${blockchainUserId} does not match the wallet of the user attempting to write this data: ${req.session.wallet}`
)
}

const cnodeUserUUID = req.session.cnodeUserUUID

// Fetch metadataJSON for metadataFileUUID.
Expand Down
16 changes: 16 additions & 0 deletions creator-node/src/routes/tracks.js
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,22 @@ router.post(
throw new Error('Cannot create track without transcodedTrackUUID.')
}

// Verify that blockchain track id is owned by user attempting to upload it
const serviceRegistry = req.app.get('serviceRegistry')
const { libs } = serviceRegistry
const trackResp = await libs.contracts.TrackFactoryClient.getTrack(
blockchainTrackId
)
if (
!trackResp?.trackOwnerId ||
parseInt(trackResp.trackOwnerId, 10) !==
parseInt(req.session.userId, 10)
) {
throw new Error(
`Owner ID ${trackResp.trackOwnerId} of blockchainTrackId ${blockchainTrackId} does not match the ID of the user attempting to write this track: ${req.session.userId}`
)
}

// Associate the transcode file db record with trackUUID
const transcodedFile = await models.File.findOne({
where: {
Expand Down
62 changes: 57 additions & 5 deletions creator-node/test/audiusUsers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,24 @@ describe('Test AudiusUsers', function () {
} })
assert.ok(file)

// Make chain recognize current session wallet as the wallet for the session user ID
const blockchainUserId = 1
const getUserStub = sinon.stub().callsFake((blockchainUserIdArg) => {
let wallet = 'no wallet'
if (blockchainUserIdArg === blockchainUserId) {
wallet = session.walletPublicKey
}
return {
wallet
}
})
libsMock.contracts.UserFactoryClient = { getUser: getUserStub }

await request(app)
.post('/audius_users')
.set('X-Session-ID', session.sessionToken)
.set('User-Id', session.userId)
.send({ blockchainUserId: 1, blockNumber: 10, metadataFileUUID: resp.body.data.metadataFileUUID })
.send({ blockchainUserId, blockNumber: 10, metadataFileUUID: resp.body.data.metadataFileUUID })
.expect(200)
})

Expand All @@ -143,18 +156,31 @@ describe('Test AudiusUsers', function () {
throw new Error('invalid return data')
}

// Make chain recognize current session wallet as the wallet for the session user ID
const blockchainUserId = 1
const getUserStub = sinon.stub().callsFake((blockchainUserIdArg) => {
let wallet = 'no wallet'
if (blockchainUserIdArg === blockchainUserId) {
wallet = session.walletPublicKey
}
return {
wallet
}
})
libsMock.contracts.UserFactoryClient = { getUser: getUserStub }

await request(app)
.post('/audius_users')
.set('X-Session-ID', session.sessionToken)
.set('User-Id', session.userId)
.send({ blockchainUserId: 1, blockNumber: 10, metadataFileUUID: resp.body.data.metadataFileUUID })
.send({ blockchainUserId, blockNumber: 10, metadataFileUUID: resp.body.data.metadataFileUUID })
.expect(200)

await request(app)
.post('/audius_users')
.set('X-Session-ID', session.sessionToken)
.set('User-Id', session.userId)
.send({ blockchainUserId: 1, blockNumber: 10, metadataFileUUID: resp.body.data.metadataFileUUID })
.send({ blockchainUserId, blockNumber: 10, metadataFileUUID: resp.body.data.metadataFileUUID })
.expect(200)
})

Expand Down Expand Up @@ -191,11 +217,24 @@ describe('Test AudiusUsers', function () {
throw new Error('invalid return data')
}

// Make chain recognize current session wallet as the wallet for the session user ID
const blockchainUserId = 1
const getUserStub = sinon.stub().callsFake((blockchainUserIdArg) => {
let wallet = 'no wallet'
if (blockchainUserIdArg === blockchainUserId) {
wallet = session.walletPublicKey
}
return {
wallet
}
})
libsMock.contracts.UserFactoryClient = { getUser: getUserStub }

await request(app)
.post('/audius_users')
.set('X-Session-ID', session.sessionToken)
.set('User-Id', session.userId)
.send({ blockchainUserId: 1, blockNumber: 10, metadataFileUUID: resp2.body.data.metadataFileUUID })
.send({ blockchainUserId, blockNumber: 10, metadataFileUUID: resp2.body.data.metadataFileUUID })
.expect(200)
})

Expand All @@ -220,11 +259,24 @@ describe('Test AudiusUsers', function () {
const cnodeUser = await models.CNodeUser.findOne({ where: { cnodeUserUUID: session.cnodeUserUUID } })
await cnodeUser.update({ latestBlockNumber: 100 })

// Make chain recognize current session wallet as the wallet for the session user ID
const blockchainUserId = 1
const getUserStub = sinon.stub().callsFake((blockchainUserIdArg) => {
let wallet = 'no wallet'
if (blockchainUserIdArg === blockchainUserId) {
wallet = session.walletPublicKey
}
return {
wallet
}
})
libsMock.contracts.UserFactoryClient = { getUser: getUserStub }

await request(app)
.post('/audius_users')
.set('X-Session-ID', session.sessionToken)
.set('User-Id', session.userId)
.send({ blockchainUserId: 1, blockNumber: 10, metadataFileUUID: resp.body.data.metadataFileUUID })
.send({ blockchainUserId, blockNumber: 10, metadataFileUUID: resp.body.data.metadataFileUUID })
.expect(400, {
error: 'Invalid blockNumber param 10. Must be greater or equal to previously processed blocknumber 100.'
})
Expand Down
13 changes: 13 additions & 0 deletions creator-node/test/contentBlacklist.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,19 @@ describe('test ContentBlacklist', function () {
.set('User-Id', inputUserId)
.set('Enforce-Write-Quorum', false)
.send({ metadata: trackMetadata, source_file: sourceFile })

// Make chain recognize wallet as owner of track
const getTrackStub = sinon.stub().callsFake((blockchainTrackId) => {
let trackOwnerId = -1
if (blockchainTrackId === trackId) {
trackOwnerId = inputUserId
}
return {
trackOwnerId
}
})
libsMock.contracts.TrackFactoryClient = { getTrack: getTrackStub }

// associate track metadata with track
await request(app)
.post('/tracks')
Expand Down
106 changes: 71 additions & 35 deletions creator-node/test/dbManager.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,34 +27,6 @@ const { fetchDBStateForWallet, assertTableEquality } = require('./lib/utils')

const TestAudioFilePath = path.resolve(__dirname, 'testTrack.mp3')

/** Add state to AudiusUsers table for given userId */
const uploadAudiusUserState = async function ({
app,
userId,
sessionToken,
metadataObj,
audiusUserBlockNumber
}) {
const audiusUserMetadataResp = await request(app)
.post('/audius_users/metadata')
.set('X-Session-ID', sessionToken)
.set('User-Id', userId)
.set('Enforce-Write-Quorum', false)
.send({ metadata: metadataObj })
.expect(200)

await request(app)
.post('/audius_users')
.set('X-Session-ID', sessionToken)
.set('User-Id', userId)
.send({
blockchainUserId: userId,
blockNumber: audiusUserBlockNumber,
metadataFileUUID: audiusUserMetadataResp.body.data.metadataFileUUID
})
.expect(200)
}

describe('Test createNewDataRecord()', async function () {
const req = {
logger: {
Expand Down Expand Up @@ -714,6 +686,18 @@ describe('Test deleteAllCNodeUserDataFromDB()', async function () {
.set('Enforce-Write-Quorum', false)
.send({ metadata: audiusUserMetadata })
.expect(200)
// Make chain recognize current session wallet as the wallet for the session user ID
const blockchainUserId = 1
const getUserStub = sinon.stub().callsFake((blockchainUserIdArg) => {
let wallet = 'no wallet'
if (blockchainUserIdArg === blockchainUserId) {
wallet = session.walletPublicKey
}
return {
wallet
}
})
libsMock.contracts.UserFactoryClient = { getUser: getUserStub }
await request(app)
.post('/audius_users')
.set('X-Session-ID', session.sessionToken)
Expand Down Expand Up @@ -792,13 +776,26 @@ describe('Test deleteAllCNodeUserDataFromDB()', async function () {
expectedTrackMetadataMultihash
)

// Make chain recognize wallet as owner of track
const blockchainTrackId = 1
const getTrackStub = sinon.stub().callsFake((blockchainTrackIdArg) => {
let trackOwnerId = -1
if (blockchainTrackIdArg === blockchainTrackId) {
trackOwnerId = userId
}
return {
trackOwnerId
}
})
libsMock.contracts.TrackFactoryClient = { getTrack: getTrackStub }

// Complete track upload
await request(app)
.post('/tracks')
.set('X-Session-ID', session.sessionToken)
.set('User-Id', session.userId)
.send({
blockchainTrackId: 1,
blockchainTrackId,
blockNumber: 10,
metadataFileUUID: trackMetadataResp.body.data.metadataFileUUID,
transcodedTrackUUID
Expand Down Expand Up @@ -1099,11 +1096,12 @@ describe('Test fetchFilesHashFromDB()', async function () {
describe('Test fixInconsistentUser()', async function () {
const userId = 1

let server, app
let server, app, libsMock

/** Init server to run DB migrations */
before(async function () {
const appInfo = await getApp(getLibsMock())
libsMock = getLibsMock()
const appInfo = await getApp(libsMock)
server = appInfo.server
app = appInfo.app
})
Expand All @@ -1119,6 +1117,46 @@ describe('Test fixInconsistentUser()', async function () {
await server.close()
})

/** Add state to AudiusUsers table for given userId */
const uploadAudiusUserState = async function ({
sessionToken,
walletPublicKey,
metadataObj,
audiusUserBlockNumber
}) {
const audiusUserMetadataResp = await request(app)
.post('/audius_users/metadata')
.set('X-Session-ID', sessionToken)
.set('User-Id', userId)
.set('Enforce-Write-Quorum', false)
.send({ metadata: metadataObj })
.expect(200)

// Make chain recognize current session wallet as the wallet for the session user ID
const blockchainUserId = 1
const getUserStub = sinon.stub().callsFake((blockchainUserIdArg) => {
let wallet = 'no wallet'
if (blockchainUserIdArg === blockchainUserId) {
wallet = walletPublicKey
}
return {
wallet
}
})
libsMock.contracts.UserFactoryClient = { getUser: getUserStub }

await request(app)
.post('/audius_users')
.set('X-Session-ID', sessionToken)
.set('User-Id', userId)
.send({
blockchainUserId: userId,
blockNumber: audiusUserBlockNumber,
metadataFileUUID: audiusUserMetadataResp.body.data.metadataFileUUID
})
.expect(200)
}

it('Confirm no change to healthy users DB state', async function () {
const { cnodeUserUUID, walletPublicKey, sessionToken } = await createStarterCNodeUser(userId)

Expand All @@ -1127,9 +1165,8 @@ describe('Test fixInconsistentUser()', async function () {
const audiusUserMetadata = { test: 'field1' }
const metadataCID = 'QmQMHXPMuey2AT6fPTKnzKQCrRjPS7AbaQdDTM8VXbHC8W'
await uploadAudiusUserState({
app,
userId,
sessionToken,
walletPublicKey,
metadataObj: audiusUserMetadata,
audiusUserBlockNumber
})
Expand Down Expand Up @@ -1214,9 +1251,8 @@ describe('Test fixInconsistentUser()', async function () {
const audiusUserMetadata = { test: 'field1' }
const metadataCID = 'QmQMHXPMuey2AT6fPTKnzKQCrRjPS7AbaQdDTM8VXbHC8W'
await uploadAudiusUserState({
app,
userId,
sessionToken,
walletPublicKey,
metadataObj: audiusUserMetadata,
audiusUserBlockNumber
})
Expand Down
Loading

0 comments on commit 9f5d7de

Please sign in to comment.