Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions forge/routes/api/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -1542,6 +1542,13 @@ module.exports = async function (app) {
code: 'not_found',
error: 'Snapshot not found'
})
} else {
if (targetSnapshot.ProjectId !== request.project.id) {
return reply.code(404).send({
code: 'not_found',
error: 'Snapshot not found'
})
}
}
break
}
Expand Down
50 changes: 49 additions & 1 deletion test/unit/forge/routes/api/project_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3685,7 +3685,8 @@ describe('Project API', function () {
toJSON: () => ({
settings: { env: { OLD: 'value' }, modules: { oldmod: '0.1.0' } },
flows: { flows: [{ id: 'old' }], credentials: {} }
})
}),
ProjectId: TestObjects.project1.id
}
}
return originalSnapshotById.call(this, sid)
Expand Down Expand Up @@ -3742,6 +3743,53 @@ describe('Project API', function () {
cookies: { sid: TestObjects.tokens.alice }
})

try {
response.statusCode.should.equal(404)
const body = response.json()
body.should.have.property('code', 'not_found')
invokeStub.called.should.equal(false)
} finally {
buildSnapshotStub.restore()
invokeStub.restore()
byIdStub.restore()
snapshotByIdStub.restore()
app.license = originalLicense
}
})
it('returns 404 when target snapshot belongs to a different instance', async function () {
const buildSnapshotStub = sinon.stub(app.db.controllers.ProjectSnapshot, 'buildProjectSnapshot').resolves({
ProjectId: 99,
settings: {},
flows: { flows: [], credentials: {} }
})
const invokeStub = sinon.stub(app.db.controllers.Assistant, 'invokeLLM').resolves({ transactionId: 'x', data: {} })

const originalLicense = app.license
app.license = { get: (k) => (k === 'tier' ? 'enterprise' : undefined) }
const originalProjectById = app.db.models.Project.byId
const byIdStub = sinon.stub(app.db.models.Project, 'byId').callsFake(async function (id, opts) {
const project = await originalProjectById.call(this, id, opts)
if (project && project.Team) {
project.Team.getTeamType = async () => ({
getFeatureProperty: (name, def) => (name === 'generatedSnapshotDescription' ? true : def)
})
}
return project
})

const snapshotByIdStub = sinon.stub(app.db.models.ProjectSnapshot, 'byId').resolves({
ProjectId: 88,
settings: {},
flows: { flows: [], credentials: {} }
})

const response = await app.inject({
method: 'POST',
url: `/api/v1/projects/${TestObjects.project1.id}/generate/snapshot-description`,
payload: { target: '88' },
cookies: { sid: TestObjects.tokens.alice }
})

try {
response.statusCode.should.equal(404)
const body = response.json()
Expand Down
Loading