Skip to content

Commit

Permalink
fix: Update functions to use transactions (NUWCDIVNPT#1371)
Browse files Browse the repository at this point in the history
* fix: removeStigsFromAsset, removeStigFromAsset, deleteAsset, deleteAssets now use transactions

* attachAssetsToStig calls pruneCollectionRevMap earlier

* refactors error handling, fixes patchAssets Schema

* fix spec syntax
  • Loading branch information
Matte22 authored Sep 12, 2024
1 parent 5ec438b commit cb71c59
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 38 deletions.
8 changes: 4 additions & 4 deletions api/source/controllers/Asset.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ module.exports.deleteAsset = async function deleteAsset (req, res, next) {
let projection = req.query.projection
const { assetId } = await getAssetInfoAndVerifyAccess(req)
const response = await AssetService.getAsset(assetId, projection, elevate, req.userObject)
await AssetService.deleteAsset( assetId, projection, elevate, req.userObject )
await AssetService.deleteAsset( assetId, projection, elevate, req.userObject, res.svcStatus)
res.json(response)
}
catch (err) {
Expand All @@ -64,7 +64,7 @@ module.exports.removeStigFromAsset = async function removeStigFromAsset (req, re
let benchmarkId = req.params.benchmarkId
let elevate = req.query.elevate
const { assetId } = await getAssetInfoAndVerifyAccess(req)
let response = await AssetService.removeStigFromAsset(assetId, benchmarkId, elevate, req.userObject )
let response = await AssetService.removeStigFromAsset(assetId, benchmarkId, elevate, req.userObject, res.svcStatus)
res.json(response)
}
catch (err) {
Expand All @@ -76,7 +76,7 @@ module.exports.removeStigsFromAsset = async function removeStigsFromAsset (req,
try {
let elevate = req.query.elevate
const { assetId } = await getAssetInfoAndVerifyAccess(req)
let response = await AssetService.removeStigsFromAsset(assetId, elevate, req.userObject )
let response = await AssetService.removeStigsFromAsset(assetId, elevate, req.userObject, res.svcStatus)
res.json(response)
}
catch (err) {
Expand Down Expand Up @@ -663,7 +663,7 @@ module.exports.patchAssets = async function (req, res, next) {
if (!patchRequest.assetIds.every( a => collectionAssets.includes(a))) {
throw new SmError.PrivilegeError('One or more assetId is not a Collection member.')
}
await AssetService.deleteAssets(patchRequest.assetIds, req.userObject)
await AssetService.deleteAssets(patchRequest.assetIds, req.userObject, res.svcStatus)
res.json({
operation: 'deleted',
assetIds: patchRequest.assetIds
Expand Down
155 changes: 121 additions & 34 deletions api/source/service/AssetService.js
Original file line number Diff line number Diff line change
Expand Up @@ -1327,22 +1327,64 @@ exports.createAsset = async function({body, projection, elevate, userObject, svc
})
}

exports.deleteAsset = async function(assetId, projection, elevate, userObject) {
const rows = await _this.queryAssets(projection, {assetId: assetId}, elevate, userObject)
const sqlDelete = `UPDATE asset SET state = "disabled", stateDate = NOW(), stateUserId = ? where assetId = ?`
await dbUtils.pool.query(sqlDelete, [userObject.userId, assetId])
// changes above might have affected need for records in collection_rev_map
await dbUtils.pruneCollectionRevMap()
await dbUtils.updateDefaultRev(null, {})
return (rows[0])
exports.deleteAsset = async function(assetId, projection, elevate, userObject, svcStatus = {}) {

let connection
try {
connection = await dbUtils.pool.getConnection()
async function transaction () {
await connection.query('START TRANSACTION')
const sqlDelete = `UPDATE asset SET state = "disabled", stateDate = NOW(), stateUserId = ? where assetId = ?`
await connection.query(sqlDelete, [userObject.userId, assetId])
// changes above might have affected need for records in collection_rev_map
await dbUtils.pruneCollectionRevMap(connection)
await dbUtils.updateDefaultRev(connection, {})
await connection.commit()
}
const rows = await _this.queryAssets(projection, {assetId: assetId}, elevate, userObject)
await dbUtils.retryOnDeadlock(transaction, svcStatus)
return (rows[0])
}
catch (err) {
if (typeof connection !== 'undefined') {
await connection.rollback()
}
throw err
}
finally {
if (typeof connection !== 'undefined') {
await connection.release()
}
}
}

exports.deleteAssets = async function(assetIds, userObject) {
const sqlDelete = `UPDATE asset SET state = "disabled", stateDate = NOW(), stateUserId = ? where assetId IN ?`
await dbUtils.pool.query(sqlDelete, [userObject.userId, [assetIds]])
// changes above might have affected need for records in collection_rev_map
await dbUtils.pruneCollectionRevMap()
await dbUtils.updateDefaultRev(null, {})
exports.deleteAssets = async function(assetIds, userObject, svcStatus = {}) {

let connection
try{
connection = await dbUtils.pool.getConnection()
async function transaction () {
await connection.query('START TRANSACTION')
const sqlDelete = `UPDATE asset SET state = "disabled", stateDate = NOW(), stateUserId = ? where assetId IN ?`
await connection.query(sqlDelete, [userObject.userId, [assetIds]])
// changes above might have affected need for records in collection_rev_map
await dbUtils.pruneCollectionRevMap(connection)
await dbUtils.updateDefaultRev(connection, {})
await connection.commit()
}
await dbUtils.retryOnDeadlock(transaction, svcStatus)
}
catch (err) {
if (typeof connection !== 'undefined') {
await connection.rollback()
}
throw err
}
finally {
if (typeof connection !== 'undefined') {
await connection.release()
}
}
}

exports.attachStigToAsset = async function( {assetId, benchmarkId, collectionId, elevate, userObject, svcStatus = {}} ) {
Expand Down Expand Up @@ -1388,26 +1430,69 @@ exports.attachStigToAsset = async function( {assetId, benchmarkId, collectionId,
}
}

exports.removeStigFromAsset = async function (assetId, benchmarkId, elevate, userObject ) {
const sqlDelete = `DELETE FROM stig_asset_map where assetId = ? and benchmarkId = ?`
await dbUtils.pool.query(sqlDelete, [assetId, benchmarkId])
const rows = await _this.queryStigsByAsset( {
assetId: assetId
}, elevate, userObject)
// changes above might have affected need for records in collection_rev_map
await dbUtils.pruneCollectionRevMap()
await dbUtils.updateDefaultRev(null, {})
return (rows)
exports.removeStigFromAsset = async function (assetId, benchmarkId, elevate, userObject, svcStatus = {}) {

let connection
try{
connection = await dbUtils.pool.getConnection()
async function transaction () {
connection.query('START TRANSACTION')
const sqlDelete = `DELETE FROM stig_asset_map where assetId = ? and benchmarkId = ?`
await connection.query(sqlDelete, [assetId, benchmarkId])
// changes above might have affected need for records in collection_rev_map
const rows = await _this.queryStigsByAsset( {
assetId: assetId
}, elevate, userObject)
await dbUtils.pruneCollectionRevMap(connection)
await dbUtils.updateDefaultRev(connection, {})
await connection.commit()
return (rows)
}
return await dbUtils.retryOnDeadlock(transaction, svcStatus)
}
catch (err) {
if (typeof connection !== 'undefined') {
await connection.rollback()
}
throw err
}
finally {
if (typeof connection !== 'undefined') {
await connection.release()
}
}
}

exports.removeStigsFromAsset = async function (assetId, elevate, userObject ) {
const sqlDelete = `DELETE FROM stig_asset_map where assetId = ?`
await dbUtils.pool.query(sqlDelete, [assetId])
const rows = await _this.queryStigsByAsset( {assetId: assetId}, elevate, userObject)
// changes above might have affected need for records in collection_rev_map
await dbUtils.pruneCollectionRevMap()
await dbUtils.updateDefaultRev(null, {})
return (rows)
exports.removeStigsFromAsset = async function (assetId, elevate, userObject, svcStatus = {}) {

let connection

try{
connection = await dbUtils.pool.getConnection()
async function transaction () {
await connection.query('START TRANSACTION')
const sqlDelete = `DELETE FROM stig_asset_map where assetId = ?`
await connection.query(sqlDelete, [assetId])

// changes above might have affected need for records in collection_rev_map
await dbUtils.pruneCollectionRevMap(connection)
await dbUtils.updateDefaultRev(connection, {})
await connection.commit()
}
await dbUtils.retryOnDeadlock(transaction, svcStatus)
return await _this.queryStigsByAsset( {assetId: assetId}, elevate, userObject)
}
catch (err) {
if (typeof connection !== 'undefined') {
await connection.rollback()
}
throw err
}
finally {
if (typeof connection !== 'undefined') {
await connection.release()
}
}
}

exports.deleteAssetStigGrant = async function (assetId, benchmarkId, userId, elevate, userObject ) {
Expand Down Expand Up @@ -1524,6 +1609,9 @@ exports.attachAssetsToStig = async function(collectionId, benchmarkId, assetIds,
await connection.query(sqlInsertBenchmarks, [ binds ])
}

// changes above might have affected need for records in collection_rev_map
await dbUtils.pruneCollectionRevMap(connection)

await dbUtils.updateDefaultRev(connection, {
collectionId: collectionId,
benchmarkId: benchmarkId
Expand All @@ -1533,8 +1621,7 @@ exports.attachAssetsToStig = async function(collectionId, benchmarkId, assetIds,
benchmarkId: benchmarkId
})

// changes above might have affected need for records in collection_rev_map
await dbUtils.pruneCollectionRevMap(connection)


// Commit the changes
await connection.commit()
Expand Down
4 changes: 4 additions & 0 deletions api/source/specification/stig-manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4114,12 +4114,16 @@ components:
properties:
assetIds:
type: array
minItems: 1
items:
$ref: '#/components/schemas/AssetId'
operation:
type: string
enum:
- delete
required:
- assetIds
- operation
AssetsPatchResponse:
additionalProperties: false
type: object
Expand Down

0 comments on commit cb71c59

Please sign in to comment.