Skip to content

Commit

Permalink
Creator node Track owner validation from discovery (#3851)
Browse files Browse the repository at this point in the history
* Update content node track owner validation

* lint

* Update tests

Co-authored-by: Sid Sethi <3323835+SidSethi@users.noreply.github.com>
Co-authored-by: Theo Ilie <theoilie.ti@gmail.com>
  • Loading branch information
3 people committed Sep 21, 2022
1 parent 8a4cb0c commit 41c0ac7
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 58 deletions.
55 changes: 43 additions & 12 deletions creator-node/src/routes/tracks.js
Expand Up @@ -23,6 +23,7 @@ const {
validateStateForImageDirCIDAndReturnFileUUID,
currentNodeShouldHandleTranscode
} = require('../utils')
const asyncRetry = require('../utils/asyncRetry')
const {
authMiddleware,
ensurePrimaryMiddleware,
Expand Down Expand Up @@ -311,6 +312,37 @@ router.post(
})
)

const validateTrackOwner = async ({
libs,
logger,
trackId,
userId,
blockNumber
}) => {
const asyncFn = async () => {
const discoveryTrackResponse = await libs.Track.getTracks(1, 0, [trackId])
if (
!Array.isArray(discoveryTrackResponse) ||
discoveryTrackResponse.length === 0 ||
!discoveryTrackResponse[0].hasOwnProperty('blocknumber')
) {
throw new Error('Missing or malformatted track fetched from discprov.')
}
const track = discoveryTrackResponse[0]
if (track.blocknumber >= blockNumber) {
return parseInt(userId) === track.owner_id
}
throw new Error(
`Block not yet indexed: Waiting for ${track.blocknumber}, but at ${blockNumber}`
)
}

return await asyncRetry({
asyncFn,
logger
})
}

/**
* Given track blockchainTrackId, blockNumber, and metadataFileUUID, creates/updates Track DB track entry
* and associates segment & image file entries with track. Ends track creation/update process.
Expand Down Expand Up @@ -426,19 +458,18 @@ 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)
) {
// Verify that track id is owned by user attempting to upload it
const libs = req.app.get('audiusLibs')
const isValidTrackOwner = await validateTrackOwner({
libs,
trackId: blockchainTrackId,
userId: req.session.userId,
logger: req.logger,
blockNumber
})
if (!isValidTrackOwner) {
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}`
`Owner ID of track ${blockchainTrackId} does not match ${req.session.userId}`
)
}

Expand Down
15 changes: 9 additions & 6 deletions creator-node/test/contentBlacklist.test.js
Expand Up @@ -1093,16 +1093,19 @@ describe('test ContentBlacklist', function () {
.send({ metadata: trackMetadata, source_file: sourceFile })

// Make chain recognize wallet as owner of track
const getTrackStub = sinon.stub().callsFake((blockchainTrackId) => {
const getTrackStub = sinon.stub().callsFake((_, __, trackIds) => {
let trackOwnerId = -1
if (blockchainTrackId === trackId) {
if (trackIds[0] === trackId) {
trackOwnerId = inputUserId
}
return {
trackOwnerId
}
return [
{
blocknumber: 99999,
owner_id: trackOwnerId
}
]
})
libsMock.contracts.TrackFactoryClient = { getTrack: getTrackStub }
libsMock.Track = { getTracks: getTrackStub }

// associate track metadata with track
await request(app)
Expand Down
16 changes: 9 additions & 7 deletions creator-node/test/dbManager.test.js
Expand Up @@ -778,16 +778,19 @@ describe('Test deleteAllCNodeUserDataFromDB()', async function () {

// Make chain recognize wallet as owner of track
const blockchainTrackId = 1
const getTrackStub = sinon.stub().callsFake((blockchainTrackIdArg) => {
const getTrackStub = sinon.stub().callsFake((_, __, trackIds) => {
let trackOwnerId = -1
if (blockchainTrackIdArg === blockchainTrackId) {
if (trackIds[0] === blockchainTrackId) {
trackOwnerId = userId
}
return {
trackOwnerId
}
return [
{
blocknumber: 99999,
owner_id: trackOwnerId
}
]
})
libsMock.contracts.TrackFactoryClient = { getTrack: getTrackStub }
libsMock.Track = { getTracks: getTrackStub }

// Complete track upload
await request(app)
Expand Down Expand Up @@ -1335,5 +1338,4 @@ describe('Test fixInconsistentUser()', async function () {
['createdAt', 'updatedAt']
)
})

})
71 changes: 44 additions & 27 deletions creator-node/test/pollingTracks.test.js
Expand Up @@ -687,16 +687,19 @@ describe('test Polling Tracks with mocked IPFS', function () {

// Make chain recognize wallet as owner of track
const blockchainTrackId = 1
const getTrackStub = sinon.stub().callsFake((blockchainTrackIdArg) => {
const getTrackStub = sinon.stub().callsFake((_, __, trackIds) => {
let trackOwnerId = -1
if (blockchainTrackIdArg === blockchainTrackId) {
if (trackIds[0] === blockchainTrackId) {
trackOwnerId = userId
}
return {
trackOwnerId
}
return [
{
blocknumber: 99999,
owner_id: trackOwnerId
}
]
})
libsMock.contracts.TrackFactoryClient = { getTrack: getTrackStub }
libsMock.Track = { getTracks: getTrackStub }

await request(app)
.post('/tracks')
Expand Down Expand Up @@ -746,8 +749,13 @@ describe('test Polling Tracks with mocked IPFS', function () {

// Make chain NOT recognize wallet as owner of track
const blockchainTrackId = 1
const getTrackStub = sinon.stub().resolves(-1)
libsMock.contracts.TrackFactoryClient = { getTrack: getTrackStub }
const getTrackStub = sinon.stub().resolves([
{
blocknumber: 0,
owner_id: -1
}
])
libsMock.Track = { getTracks: getTrackStub }

await request(app)
.post('/tracks')
Expand Down Expand Up @@ -852,16 +860,19 @@ describe('test Polling Tracks with mocked IPFS', function () {

// Make chain recognize wallet as owner of track
const blockchainTrackId = 1
const getTrackStub = sinon.stub().callsFake((blockchainTrackIdArg) => {
const getTrackStub = sinon.stub().callsFake((_, __, trackIds) => {
let trackOwnerId = -1
if (blockchainTrackIdArg === blockchainTrackId) {
if (trackIds[0] === blockchainTrackId) {
trackOwnerId = userId
}
return {
trackOwnerId
}
return [
{
blocknumber: 99999,
owner_id: trackOwnerId
}
]
})
libsMock.contracts.TrackFactoryClient = { getTrack: getTrackStub }
libsMock.Track = { getTracks: getTrackStub }

await request(app)
.post('/tracks')
Expand Down Expand Up @@ -1111,16 +1122,19 @@ describe('test Polling Tracks with real files', function () {

// Make chain recognize wallet as owner of track
const blockchainTrackId = 1
const getTrackStub = sinon.stub().callsFake((blockchainTrackIdArg) => {
const getTrackStub = sinon.stub().callsFake((_, __, trackIds) => {
let trackOwnerId = -1
if (blockchainTrackIdArg === blockchainTrackId) {
if (trackIds[0] === blockchainTrackId) {
trackOwnerId = userId
}
return {
trackOwnerId
}
return [
{
blocknumber: 99999,
owner_id: trackOwnerId
}
]
})
libsMock.contracts.TrackFactoryClient = { getTrack: getTrackStub }
libsMock.Track = { getTracks: getTrackStub }

// Complete track creation
await request(app2)
Expand Down Expand Up @@ -1196,19 +1210,22 @@ describe('test Polling Tracks with real files', function () {
// Make chain recognize wallet as owner of track
const track1BlockchainId = 1
const track2BlockchainId = 2
const getTrackStub = sinon.stub().callsFake((blockchainTrackId) => {
const getTrackStub = sinon.stub().callsFake((_, __, trackIds) => {
let trackOwnerId = -1
if (
blockchainTrackId === track1BlockchainId ||
blockchainTrackId === track2BlockchainId
trackIds[0] === track1BlockchainId ||
trackIds[0] === track2BlockchainId
) {
trackOwnerId = userId
}
return {
trackOwnerId
}
return [
{
blocknumber: 99999,
owner_id: trackOwnerId
}
]
})
libsMock.contracts.TrackFactoryClient = { getTrack: getTrackStub }
libsMock.Track = { getTracks: getTrackStub }

// Complete track1 creation
await request(app2)
Expand Down
15 changes: 9 additions & 6 deletions creator-node/test/sync.test.js
Expand Up @@ -195,16 +195,19 @@ describe('Test secondarySyncFromPrimary()', async function () {

// Make chain recognize wallet as owner of track
const blockchainTrackId = 1
const getTrackStub = sinon.stub().callsFake((blockchainTrackIdArg) => {
const getTrackStub = sinon.stub().callsFake((_, __, trackIds) => {
let trackOwnerId = -1
if (blockchainTrackIdArg === blockchainTrackId) {
if (trackIds[0] === blockchainTrackId) {
trackOwnerId = userId
}
return {
trackOwnerId
}
return [
{
blocknumber: 99999,
owner_id: trackOwnerId
}
]
})
libsMock.contracts.TrackFactoryClient = { getTrack: getTrackStub }
libsMock.Track = { getTracks: getTrackStub }

// associate track + track metadata with blockchain ID
await request(app)
Expand Down

0 comments on commit 41c0ac7

Please sign in to comment.