Skip to content

Commit

Permalink
oas definition, api endpoint, ui integration
Browse files Browse the repository at this point in the history
  • Loading branch information
csmig committed Feb 23, 2024
1 parent 639d6b7 commit 5e99f0e
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 51 deletions.
53 changes: 20 additions & 33 deletions api/source/controllers/Asset.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const config = require('../utils/config')
const escape = require('../utils/escape')
const AssetService = require(`../service/AssetService`);
const CollectionService = require(`../service/CollectionService`);
const Security = require('../utils/accessLevels')
const dbUtils = require(`../service/utils`)
const {XMLBuilder} = require("fast-xml-parser")
const SmError = require('../utils/error')
Expand Down Expand Up @@ -785,47 +786,33 @@ module.exports.deleteAssetMetadataKey = async function (req, res, next) {
}
}

module.exports.getAssetLabels = async function (req, res, next) {
module.exports.patchAssets = async function (req, res, next) {
try {
res.json({})
const collectionId = getCollectionIdAndCheckPermission(req, Security.ACCESS_LEVEL.Manage)
const patchRequest = req.body
const collection = await CollectionService.getCollection( collectionId, ['assets'], false, req.userObject)
const collectionAssets = collection.assets.map( a => a.assetId)
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)
res.json({
operation: 'deleted',
assetIds: patchRequest.assetIds
})
}
catch (err) {
next(err)
}
}

module.exports.addAssetLabels = async function (req, res, next) {
try {
res.json({})
}
catch (err) {
next(err)
function getCollectionIdAndCheckPermission(request, minimumAccessLevel = Security.ACCESS_LEVEL.Manage) {
let collectionId = request.query.collectionId
const collectionGrant = request.userObject.collectionGrants.find( g => g.collection.collectionId === collectionId )
if (collectionGrant?.accessLevel < minimumAccessLevel) {
throw new SmError.PrivilegeError()
}
return collectionId
}

module.exports.replaceAssetLabels = async function (req, res, next) {
try {
res.json({})
}
catch (err) {
next(err)
}
}

module.exports.deleteAssetLabels = async function (req, res, next) {
try {
res.json({})
}
catch (err) {
next(err)
}
}

module.exports.deleteAssetLabelById = async function (req, res, next) {
try {
res.json({})
}
catch (err) {
next(err)
}
}
7 changes: 7 additions & 0 deletions api/source/service/AssetService.js
Original file line number Diff line number Diff line change
Expand Up @@ -1333,6 +1333,13 @@ exports.deleteAsset = async function(assetId, projection, elevate, userObject) {
return (rows[0])
}

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.attachStigToAsset = async function( {assetId, benchmarkId, collectionId, elevate, userObject, svcStatus = {}} ) {

Expand Down
65 changes: 63 additions & 2 deletions api/source/specification/stig-manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ servers:
- url: 'http://localhost:64001/api'
paths:
/assets:
parameters:
- $ref: '#/components/parameters/AssetProjectionQuery'
get:
tags:
- Asset
Expand All @@ -26,6 +24,7 @@ paths:
- $ref: '#/components/parameters/NameMatchQuery'
- $ref: '#/components/parameters/MetadataQuery'
- $ref: '#/components/parameters/BenchmarkIdQuery'
- $ref: '#/components/parameters/AssetProjectionQuery'
responses:
'200':
description: AssetProjected array response
Expand All @@ -49,6 +48,8 @@ paths:
- Asset
summary: Create an Asset
operationId: createAsset
parameters:
- $ref: '#/components/parameters/AssetProjectionQuery'
requestBody:
required: true
content:
Expand Down Expand Up @@ -77,6 +78,42 @@ paths:
security:
- oauth:
- 'stig-manager:collection'
patch:
tags:
- Asset
summary: Delete one or more Assets
operationId: patchAssets
parameters:
- $ref: '#/components/parameters/CollectionIdQuery'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AssetsPatchRequest'
responses:
'200':
description: AssetsPatch response
content:
application/json:
schema:
$ref: '#/components/schemas/AssetsPatchResponse'
'400':
description: Client Error
content:
application/json:
schema:
$ref: '#/components/schemas/ClientErrorDuplicateAsset'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
security:
- oauth:
- 'stig-manager:collection'

'/assets/{assetId}':
parameters:
- $ref: '#/components/parameters/AssetIdPath'
Expand Down Expand Up @@ -4031,6 +4068,30 @@ components:
type: array
items:
$ref: '#/components/schemas/StigUserBasic'
AssetsPatchRequest:
type: object
additionalProperties: false
properties:
operation:
type: string
enum:
- delete
assetIds:
type: array
items:
$ref: '#/components/schemas/AssetId'
AssetsPatchResponse:
type: object
additionalProperties: false
properties:
operation:
type: string
enum:
- deleted
assetIds:
type: array
items:
$ref: '#/components/schemas/AssetId'
AssetStigResponse:
type: object
additionalProperties: false
Expand Down
34 changes: 18 additions & 16 deletions client/src/js/SM/CollectionAsset.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,24 +265,26 @@ SM.CollectionAssetGrid = Ext.extend(Ext.grid.GridPanel, {
try {
let assetRecords = me.getSelectionModel().getSelections()
const multiDelete = assetRecords.length > 1
var confirmStr=`Deleting ${multiDelete ? '<b>multiple assets</b>' : 'this asset'} will <b>permanently remove</b> all data associated with the asset${multiDelete ? 's' : ''}. This includes all the corresponding STIG assessments. The deleted data <b>cannot be recovered</b>.<br><br>Do you wish to continue?`;
const confirmStr=`Deleting ${multiDelete ? '<b>multiple assets</b>' : 'this asset'} will <b>permanently remove</b> all data associated with the asset${multiDelete ? 's' : ''}. This includes all the corresponding STIG assessments. The deleted data <b>cannot be recovered</b>.<br><br>Do you wish to continue?`;
let btn = await SM.confirmPromise("Confirm Delete", confirmStr)
if (btn == 'yes') {
const l = assetRecords.length
let apiAsset
for (let i=0; i < l; i++) {
Ext.getBody().mask(`Deleting ${i+1}/${l} Assets`)
// Edge case to handle when the selected record was changed (e.g., stats updated)
// while still selected, then is deleted
const thisRecord = me.store.getById(assetRecords[i].id)
apiAsset = await Ext.Ajax.requestPromise({
responseType: 'json',
url: `${STIGMAN.Env.apiBase}/assets/${thisRecord.data.assetId}`,
method: 'DELETE'
})
me.store.remove(thisRecord)
}
SM.Dispatcher.fireEvent('assetdeleted', apiAsset) //only need the last deleted asset
const assetIds = assetRecords.map( r => r.data.assetId)
Ext.getBody().mask(`Deleting ${assetRecords.length} Assets`)
await Ext.Ajax.requestPromise({
responseType: 'json',
url: `${STIGMAN.Env.apiBase}/assets?collectionId=${me.collectionId}`,
method: 'PATCH',
jsonData: {
operation: 'delete',
assetIds
}
})
me.store.suspendEvents(false)
// Might need to handle edge case when the selected record was changed (e.g., stats updated) while still selected, then is deleted
me.store.remove(assetRecords)
me.store.resumeEvents()

SM.Dispatcher.fireEvent('assetdeleted', {collection: {collectionId: me.collectionId}}) // mock an Asset for collectionManager.onAssetEvent
}
}
catch (e) {
Expand Down

0 comments on commit 5e99f0e

Please sign in to comment.