Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CON-222] Fix SequelizeUniqueConstraintError for blockchain track ID #3660

Merged
merged 8 commits into from
Aug 10, 2022
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