diff --git a/src/gmp/__tests__/gmp.test.ts b/src/gmp/__tests__/gmp.test.ts index 8d03a15aed..8f4c088b4d 100644 --- a/src/gmp/__tests__/gmp.test.ts +++ b/src/gmp/__tests__/gmp.test.ts @@ -255,6 +255,8 @@ describe('Gmp tests', () => { 'results', 'role', 'roles', + 'scanconfig', + 'scanconfigs', 'scanner', 'scanners', 'schedule', @@ -276,9 +278,6 @@ describe('Gmp tests', () => { 'vuln', 'vulns', 'wizard', - // registered commands (side-effect imports via registerCommand) - 'scanconfig', - 'scanconfigs', ])('should expose command %s', name => { const storage = createStorage(); const session = createSession(); diff --git a/src/gmp/commands/__tests__/scan-config.test.js b/src/gmp/commands/__tests__/scan-config.test.ts similarity index 75% rename from src/gmp/commands/__tests__/scan-config.test.js rename to src/gmp/commands/__tests__/scan-config.test.ts index 726daae02b..d5c6c30c74 100644 --- a/src/gmp/commands/__tests__/scan-config.test.js +++ b/src/gmp/commands/__tests__/scan-config.test.ts @@ -1,10 +1,14 @@ -/* SPDX-FileCopyrightText: 2024 Greenbone AG +/* SPDX-FileCopyrightText: 2026 Greenbone AG * * SPDX-License-Identifier: AGPL-3.0-or-later */ import {describe, test, expect} from '@gsa/testing'; -import {convertPreferences, ScanConfigCommand} from 'gmp/commands/scan-configs'; +import ScanConfigCommand, { + convert, + convertPreferences, + convertSelect, +} from 'gmp/commands/scan-config'; import { createEntityResponse, createHttp, @@ -15,12 +19,13 @@ import { import { SCANCONFIG_TREND_STATIC, SCANCONFIG_TREND_DYNAMIC, + type ScanConfigTrend, } from 'gmp/models/scan-config'; -import {YES_VALUE, NO_VALUE} from 'gmp/parser'; +import {YES_VALUE, NO_VALUE, type YesNo} from 'gmp/parser'; describe('convertPreferences tests', () => { test('should convert preferences', () => { - const prefenceValues = { + const preferenceValues = { 'foo Password:': { id: 1, value: undefined, @@ -43,7 +48,7 @@ describe('convertPreferences tests', () => { }, }; - expect(convertPreferences(prefenceValues, '1.2.3')).toEqual({ + expect(convertPreferences(preferenceValues, '1.2.3')).toEqual({ 'file:1.2.3:4:file:foo': 'yes', 'password:1.2.3:3:password:bar': 'yes', 'preference:1.2.3:2:entry:foo Username:': 'user', @@ -58,6 +63,45 @@ describe('convertPreferences tests', () => { }); }); +describe('convert tests', () => { + test('should convert values with prefix', () => { + const values = { + foo: 'bar', + baz: 123, + }; + const prefix = 'prefix_'; + const expected = { + prefix_foo: 'bar', + prefix_baz: 123, + }; + expect(convert(values, prefix)).toEqual(expected); + }); + + test('should return empty object if values are empty', () => { + expect(convert({}, 'prefix_')).toEqual({}); + }); +}); + +describe('convertSelect tests', () => { + test('should convert select values with prefix', () => { + const values: Record = { + foo: YES_VALUE, + bar: NO_VALUE, + baz: YES_VALUE, + }; + const prefix = 'select_'; + const expected = { + select_foo: YES_VALUE, + select_baz: YES_VALUE, + }; + expect(convertSelect(values, prefix)).toEqual(expected); + }); + + test('should return empty object if values are empty', () => { + expect(convertSelect({}, 'select_')).toEqual({}); + }); +}); + describe('ScanConfigCommand tests', () => { test('should return single config', async () => { const response = createEntityResponse('config', {_id: 'foo'}); @@ -110,11 +154,11 @@ describe('ScanConfigCommand tests', () => { test('should save a config', async () => { const response = createActionResultResponse(); const fakeHttp = createHttp(response); - const trend = { + const trend: Record = { 'AIX Local Security Checks': SCANCONFIG_TREND_DYNAMIC, 'Family Foo': SCANCONFIG_TREND_STATIC, }; - const select = { + const select: Record = { 'AIX Local Security Checks': YES_VALUE, 'Brute force attacks': YES_VALUE, 'Foo Family': NO_VALUE, @@ -146,6 +190,29 @@ describe('ScanConfigCommand tests', () => { }); }); + test('should save a config with family trend', async () => { + const response = createActionResultResponse(); + const fakeHttp = createHttp(response); + const cmd = new ScanConfigCommand(fakeHttp); + + await cmd.save({ + id: 'c1', + name: 'foo', + comment: 'somecomment', + familyTrend: SCANCONFIG_TREND_DYNAMIC, + }); + + expect(fakeHttp.request).toHaveBeenCalledWith('post', { + data: { + cmd: 'save_config', + comment: 'somecomment', + config_id: 'c1', + name: 'foo', + trend: SCANCONFIG_TREND_DYNAMIC, + }, + }); + }); + test('should save an in use config with undefined input objects', async () => { const response = createActionResultResponse(); const fakeHttp = createHttp(response); @@ -171,7 +238,7 @@ describe('ScanConfigCommand tests', () => { test('should save a config family', async () => { const response = createActionResultResponse(); const fakeHttp = createHttp(response); - const selected = { + const selected: Record = { 'oid:1': YES_VALUE, 'oid:2': NO_VALUE, 'oid:3': YES_VALUE, @@ -229,6 +296,28 @@ describe('ScanConfigCommand tests', () => { }); }); + test('should save a config nvt without timeout', async () => { + const response = createActionResultResponse(); + const fakeHttp = createHttp(response); + const cmd = new ScanConfigCommand(fakeHttp); + + await cmd.saveScanConfigNvt({ + id: 'c1', + oid: '1.2.3', + preferenceValues: undefined, + }); + + expect(fakeHttp.request).toHaveBeenCalledWith('post', { + data: { + cmd: 'save_config_nvt', + config_id: 'c1', + oid: '1.2.3', + 'preference:1.2.3:0:entry:timeout': '', + timeout: 0, + }, + }); + }); + test('should request scan config family data', async () => { const response = createResponse({ get_config_family_response: { diff --git a/src/gmp/commands/__tests__/scan-configs.test.ts b/src/gmp/commands/__tests__/scan-configs.test.ts new file mode 100644 index 0000000000..dc4c63041b --- /dev/null +++ b/src/gmp/commands/__tests__/scan-configs.test.ts @@ -0,0 +1,147 @@ +/* SPDX-FileCopyrightText: 2026 Greenbone AG + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import {describe, test, expect} from '@gsa/testing'; +import ScanConfigsCommand from 'gmp/commands/scan-configs'; +import {createEntitiesResponse, createHttp} from 'gmp/commands/testing'; +import Filter, {ALL_FILTER} from 'gmp/models/filter'; +import ScanConfig from 'gmp/models/scan-config'; + +describe('ScanConfigsCommand tests', () => { + test('should fetch all scan configs', async () => { + const response = createEntitiesResponse('config', [ + { + _id: '1', + }, + { + _id: '2', + }, + ]); + + const fakeHttp = createHttp(response); + const cmd = new ScanConfigsCommand(fakeHttp); + const resp = await cmd.getAll(); + expect(fakeHttp.request).toHaveBeenCalledWith('get', { + args: { + cmd: 'get_configs', + filter: ALL_FILTER.toFilterString(), + usage_type: 'scan', + }, + }); + const {data} = resp; + expect(data.length).toEqual(2); + }); + + test('should fetch scan configs with default params', async () => { + const response = createEntitiesResponse('config', [ + { + _id: '1', + }, + { + _id: '2', + }, + ]); + + const fakeHttp = createHttp(response); + const cmd = new ScanConfigsCommand(fakeHttp); + const resp = await cmd.get(); + expect(fakeHttp.request).toHaveBeenCalledWith('get', { + args: { + cmd: 'get_configs', + usage_type: 'scan', + }, + }); + const {data} = resp; + expect(data.length).toEqual(2); + }); + + test('should fetch scan configs with custom params', async () => { + const response = createEntitiesResponse('config', [ + { + _id: '1', + }, + { + _id: '2', + }, + ]); + + const fakeHttp = createHttp(response); + const cmd = new ScanConfigsCommand(fakeHttp); + const resp = await cmd.get({ + filter: ALL_FILTER, + details: 1, + }); + expect(fakeHttp.request).toHaveBeenCalledWith('get', { + args: { + cmd: 'get_configs', + filter: ALL_FILTER.toFilterString(), + details: 1, + usage_type: 'scan', + }, + }); + const {data} = resp; + expect(data.length).toEqual(2); + }); + + test('should allow to export scan configs by filter', async () => { + const response = createEntitiesResponse('config', []); + const fakeHttp = createHttp(response); + + const filter = Filter.fromString('name~foo'); + + const cmd = new ScanConfigsCommand(fakeHttp); + await cmd.exportByFilter(filter); + expect(fakeHttp.request).toHaveBeenCalledWith('post', { + data: { + cmd: 'bulk_export', + resource_type: 'config', + bulk_select: 0, + filter: 'name~foo', + }, + }); + }); + + test('should allow to export scan configs by ids', async () => { + const response = createEntitiesResponse('config', []); + const fakeHttp = createHttp(response); + + const cmd = new ScanConfigsCommand(fakeHttp); + + const ids = ['123', '456']; + + await cmd.exportByIds(ids); + + expect(fakeHttp.request).toHaveBeenCalledWith('post', { + data: { + 'bulk_selected:123': 1, + 'bulk_selected:456': 1, + cmd: 'bulk_export', + resource_type: 'config', + bulk_select: 1, + }, + }); + }); + + test('should allow to export scan configs', async () => { + const response = createEntitiesResponse('config', []); + const fakeHttp = createHttp(response); + + const cmd = new ScanConfigsCommand(fakeHttp); + + const entities = [new ScanConfig({id: '123'}), new ScanConfig({id: '456'})]; + + await cmd.export(entities); + + expect(fakeHttp.request).toHaveBeenCalledWith('post', { + data: { + 'bulk_selected:123': 1, + 'bulk_selected:456': 1, + cmd: 'bulk_export', + resource_type: 'config', + bulk_select: 1, + }, + }); + }); +}); diff --git a/src/gmp/commands/policy.ts b/src/gmp/commands/policy.ts index 248003aa66..a2b221fc87 100644 --- a/src/gmp/commands/policy.ts +++ b/src/gmp/commands/policy.ts @@ -8,24 +8,19 @@ import { convert, convertSelect, convertPreferences, -} from 'gmp/commands/scan-configs'; +} from 'gmp/commands/scan-config'; import type Http from 'gmp/http/http'; import logger from 'gmp/log'; import {type Element} from 'gmp/models/model'; import Policy from 'gmp/models/policy'; import { BASE_SCAN_CONFIG_ID, - type SCANCONFIG_TREND_DYNAMIC, - type SCANCONFIG_TREND_STATIC, + type ScanConfigTrend, } from 'gmp/models/scan-config'; import {YES_VALUE, NO_VALUE, type YesNo} from 'gmp/parser'; import {forEach, map} from 'gmp/utils/array'; import {isDefined} from 'gmp/utils/identity'; -type ScanConfigTrend = - | typeof SCANCONFIG_TREND_DYNAMIC - | typeof SCANCONFIG_TREND_STATIC; - interface NvtResponseEntry { _oid: string; cvss_base?: number; diff --git a/src/gmp/commands/scan-config.ts b/src/gmp/commands/scan-config.ts new file mode 100644 index 0000000000..4bb17dea13 --- /dev/null +++ b/src/gmp/commands/scan-config.ts @@ -0,0 +1,286 @@ +/* SPDX-FileCopyrightText: 2026 Greenbone AG + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import EntityCommand from 'gmp/commands/entity'; +import type Http from 'gmp/http/http'; +import logger from 'gmp/log'; +import {type Element} from 'gmp/models/model'; +import Nvt from 'gmp/models/nvt'; +import ScanConfig, { + type ScanConfigPreference, + type ScanConfigElement, + type ScanConfigTrend, +} from 'gmp/models/scan-config'; +import {NO_VALUE, YES_VALUE, type YesNo} from 'gmp/parser'; +import {forEach, map} from 'gmp/utils/array'; +import {isDefined} from 'gmp/utils/identity'; + +interface NvtResponseEntry { + _oid: string; + cvss_base?: number; + oid?: string; + severity?: number; + selected?: YesNo; +} + +interface ConfigFamilyResponse { + get_nvts_response: { + nvt: NvtResponseEntry[]; + }; +} + +interface PreferenceValues { + [key: string]: ScanConfigPreference; +} + +interface ScanConfigCommandImportParams { + xml_file: string; +} + +interface ScanConfigCommandCreateParams { + baseScanConfig: string; + name: string; + comment?: string; +} + +interface ScanConfigCommandSaveParams { + id: string; + familyTrend?: ScanConfigTrend; + name: string; + comment?: string; + trend?: Record; + select?: Record; + scannerPreferenceValues?: Record; +} + +interface ScanConfigCommandSaveFamilyParams { + id: string; + familyName: string; + selected: Record; +} + +interface ScanConfigCommandEditFamilyParams { + id: string; + familyName: string; +} + +interface NvtPreferenceValue { + id: number; + type: string; + value: string; +} + +interface ScanConfigCommandSaveNvtParams { + id: string; + timeout?: number; + oid: string; + preferenceValues?: Record; +} + +interface ScanConfigCommandEditNvtSettingsParams { + id: string; + oid: string; +} + +const log = logger.getLogger('gmp.commands.scanconfigs'); + +export const convert = (values: {[key: string]: unknown}, prefix: string) => { + const ret = {}; + for (const [key, value] of Object.entries(values)) { + ret[prefix + key] = value; + } + return ret; +}; + +export const convertSelect = ( + values: {[key: string]: YesNo}, + prefix: string, +) => { + const ret = {}; + for (const [key, value] of Object.entries(values)) { + if (value === YES_VALUE) { + ret[prefix + key] = value; + } + } + return ret; +}; + +export const convertPreferences = ( + values: PreferenceValues = {}, + nvtOid: string, +): {[key: string]: string} => { + const ret = {}; + for (const [prop, data] of Object.entries(values)) { + const {id, type, value} = data; + if (isDefined(value)) { + const typeString = `${nvtOid}:${id}:${type}:${prop}`; + if (type === 'password') { + ret['password:' + typeString] = 'yes'; + } else if (type === 'file') { + ret['file:' + typeString] = 'yes'; + } + ret['preference:' + typeString] = value; + } + } + return ret; +}; + +class ScanConfigCommand extends EntityCommand { + constructor(http: Http) { + super(http, 'config', ScanConfig); + } + + // eslint-disable-next-line @typescript-eslint/naming-convention + import({xml_file}: ScanConfigCommandImportParams) { + const data = { + cmd: 'import_config', + xml_file, + }; + log.debug('Importing scan config', data); + return this.httpPostWithTransform(data); + } + + create({baseScanConfig, name, comment}: ScanConfigCommandCreateParams) { + const data = { + cmd: 'create_config', + base: baseScanConfig, + comment, + name, + usage_type: 'scan', + }; + log.debug('Creating scan config', data); + return this.action(data); + } + + save({ + id, + name, + comment = '', + trend, + familyTrend, + select, + scannerPreferenceValues, + }: ScanConfigCommandSaveParams) { + const trendData = isDefined(trend) ? convert(trend, 'trend:') : {}; + const scannerPreferenceData = isDefined(scannerPreferenceValues) + ? convert(scannerPreferenceValues, 'preference:scanner:scanner:scanner:') + : {}; + + const selectData = isDefined(select) + ? convertSelect(select, 'select:') + : {}; + const data = { + ...trendData, + ...scannerPreferenceData, + ...selectData, + cmd: 'save_config', + id, + comment, + name, + trend: familyTrend, + }; + log.debug('Saving scan config', data); + return this.action(data); + } + + saveScanConfigFamily({ + id, + familyName, + selected, + }: ScanConfigCommandSaveFamilyParams) { + const data = { + ...convertSelect(selected, 'nvt:'), + cmd: 'save_config_family', + id, + family: familyName, + }; + log.debug('Saving scan config family', data); + return this.httpPostWithTransform(data); + } + + async editScanConfigFamilySettings({ + id, + familyName, + }: ScanConfigCommandEditFamilyParams) { + const get = this.httpGetWithTransform({ + cmd: 'edit_config_family', + id, + family: familyName, + }); + const all = this.httpGetWithTransform({ + cmd: 'edit_config_family_all', + id, + family: familyName, + }); + const [response, responseAll] = await Promise.all([get, all]); + const {data} = response; + const dataAll = responseAll.data; + const configResp = ( + data as {get_config_family_response: ConfigFamilyResponse} + ).get_config_family_response; + const configRespAll = ( + dataAll as {get_config_family_response: ConfigFamilyResponse} + ).get_config_family_response; + + const nvts: Record = {}; + forEach(configResp.get_nvts_response.nvt, nvt => (nvts[nvt._oid] = true)); + + const mappedNvts = map( + configRespAll.get_nvts_response.nvt, + (nvt: NvtResponseEntry) => ({ + oid: nvt._oid, + severity: nvt.cvss_base, + selected: nvt._oid in nvts ? YES_VALUE : NO_VALUE, + }), + ); + return response.setData({nvts: mappedNvts}); + } + + async saveScanConfigNvt({ + id, + timeout, + oid, + preferenceValues, + }: ScanConfigCommandSaveNvtParams) { + const data = { + ...convertPreferences(preferenceValues, oid), + cmd: 'save_config_nvt', + id, + oid, + timeout: isDefined(timeout) ? 1 : 0, + }; + + data['preference:' + oid + ':0:entry:timeout'] = isDefined(timeout) + ? timeout + : ''; + + log.debug('Saving scan config nvt', data); + await this.httpPostWithTransform(data); + } + + async editScanConfigNvtSettings({ + id, + oid, + }: ScanConfigCommandEditNvtSettingsParams) { + const response = await this.httpGetWithTransform({ + cmd: 'get_config_nvt', + id, + oid, + name: '', // doesn't matter + }); + const {data} = response; + const config_resp = data.get_config_nvt_response; + // @ts-expect-error + const nvt = Nvt.fromElement(config_resp.get_nvts_response); + return response.setData(nvt); + } + + getElementFromRoot(root: Element): ScanConfigElement { + // @ts-expect-error + return root.get_config.get_configs_response.config; + } +} + +export default ScanConfigCommand; diff --git a/src/gmp/commands/scan-configs.js b/src/gmp/commands/scan-configs.js deleted file mode 100644 index 0a857cdf17..0000000000 --- a/src/gmp/commands/scan-configs.js +++ /dev/null @@ -1,219 +0,0 @@ -/* SPDX-FileCopyrightText: 2024 Greenbone AG - * - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import registerCommand from 'gmp/command'; -import EntitiesCommand from 'gmp/commands/entities'; -import EntityCommand from 'gmp/commands/entity'; -import logger from 'gmp/log'; -import Nvt from 'gmp/models/nvt'; -import ScanConfig from 'gmp/models/scan-config'; -import {YES_VALUE, NO_VALUE} from 'gmp/parser'; -import {forEach, map} from 'gmp/utils/array'; -import {isDefined} from 'gmp/utils/identity'; - -const log = logger.getLogger('gmp.commands.scanconfigs'); - -export const convert = (values, prefix) => { - const ret = {}; - for (const [key, value] of Object.entries(values)) { - ret[prefix + key] = value; - } - return ret; -}; - -export const convertSelect = (values, prefix) => { - const ret = {}; - for (const [key, value] of Object.entries(values)) { - if (value === YES_VALUE) { - ret[prefix + key] = value; - } - } - return ret; -}; - -export const convertPreferences = (values = {}, nvtOid) => { - const ret = {}; - for (const [prop, data] of Object.entries(values)) { - const {id, type, value} = data; - if (isDefined(value)) { - const typestring = nvtOid + ':' + id + ':' + type + ':' + prop; - if (type === 'password') { - ret['password:' + typestring] = 'yes'; - } else if (type === 'file') { - ret['file:' + typestring] = 'yes'; - } - ret['preference:' + typestring] = value; - } - } - return ret; -}; - -export class ScanConfigCommand extends EntityCommand { - constructor(http) { - super(http, 'config', ScanConfig); - } - - import({xml_file}) { - const data = { - cmd: 'import_config', - xml_file, - }; - log.debug('Importing scan config', data); - return this.httpPostWithTransform(data); - } - - create({baseScanConfig, name, comment}) { - const data = { - cmd: 'create_config', - base: baseScanConfig, - comment, - name, - usage_type: 'scan', - }; - log.debug('Creating scanconfig', data); - return this.action(data); - } - - save({ - id, - name, - comment = '', - trend, - familyTrend, - select, - scannerPreferenceValues, - }) { - const trendData = isDefined(trend) ? convert(trend, 'trend:') : {}; - const scannerPreferenceData = isDefined(scannerPreferenceValues) - ? convert(scannerPreferenceValues, 'preference:scanner:scanner:scanner:') - : {}; - - const selectData = isDefined(select) - ? convertSelect(select, 'select:') - : {}; - const data = { - ...trendData, - ...scannerPreferenceData, - ...selectData, - cmd: 'save_config', - id, - comment, - name, - trend: familyTrend, - }; - log.debug('Saving scanconfig', data); - return this.action(data); - } - - saveScanConfigFamily({id, familyName, selected}) { - const data = { - ...convertSelect(selected, 'nvt:'), - cmd: 'save_config_family', - id, - family: familyName, - }; - log.debug('Saving scanconfigfamily', data); - return this.httpPostWithTransform(data); - } - - editScanConfigFamilySettings({id, familyName}) { - const get = this.httpGetWithTransform({ - cmd: 'edit_config_family', - id, - family: familyName, - }); - const all = this.httpGetWithTransform({ - cmd: 'edit_config_family_all', - id, - family: familyName, - }); - return Promise.all([get, all]).then(([response, response_all]) => { - const {data} = response; - const data_all = response_all.data; - const config_resp = data.get_config_family_response; - const config_resp_all = data_all.get_config_family_response; - const settings = {}; - - const nvts = {}; - forEach(config_resp.get_nvts_response.nvt, nvt => { - const oid = nvt._oid; - nvts[oid] = true; - }); - - settings.nvts = map(config_resp_all.get_nvts_response.nvt, nvt => { - nvt.oid = nvt._oid; - delete nvt._oid; - - nvt.severity = nvt.cvss_base; - delete nvt.cvss_base; - - nvt.selected = nvt.oid in nvts ? YES_VALUE : NO_VALUE; - return nvt; - }); - - return response.setData(settings); - }); - } - - saveScanConfigNvt({id, timeout, oid, preferenceValues}) { - const data = { - ...convertPreferences(preferenceValues, oid), - cmd: 'save_config_nvt', - id, - oid, - timeout: isDefined(timeout) ? 1 : 0, - }; - - data['preference:' + oid + ':0:entry:timeout'] = isDefined(timeout) - ? timeout - : ''; - - log.debug('Saving scanconfignvt', data); - return this.httpPostWithTransform(data); - } - - editScanConfigNvtSettings({id, oid}) { - return this.httpGetWithTransform({ - cmd: 'get_config_nvt', - id, - oid, - name: '', // don't matter - }).then(response => { - const {data} = response; - const config_resp = data.get_config_nvt_response; - - const nvt = Nvt.fromElement(config_resp.get_nvts_response); - - return response.setData(nvt); - }); - } - - getElementFromRoot(root) { - return root.get_config.get_configs_response.config; - } -} - -class ScanConfigsCommand extends EntitiesCommand { - constructor(http) { - super(http, 'config', ScanConfig); - } - - getEntitiesResponse(root) { - return root.get_configs.get_configs_response; - } - - get(params, options) { - params = {...params, usage_type: 'scan'}; - return this.httpGetWithTransform(params, options).then(response => { - const {entities, filter, counts} = this.getCollectionListFromRoot( - response.data, - ); - return response.set(entities, {filter, counts}); - }); - } -} - -registerCommand('scanconfig', ScanConfigCommand); -registerCommand('scanconfigs', ScanConfigsCommand); diff --git a/src/gmp/commands/scan-configs.ts b/src/gmp/commands/scan-configs.ts new file mode 100644 index 0000000000..df2a05c242 --- /dev/null +++ b/src/gmp/commands/scan-configs.ts @@ -0,0 +1,43 @@ +/* SPDX-FileCopyrightText: 2024 Greenbone AG + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import EntitiesCommand from 'gmp/commands/entities'; +import { + type HttpCommandInputParams, + type HttpCommandOptions, +} from 'gmp/commands/http'; +import type Http from 'gmp/http/http'; +import {type Element} from 'gmp/models/model'; +import ScanConfig from 'gmp/models/scan-config'; + +class ScanConfigsCommand extends EntitiesCommand { + constructor(http: Http) { + super(http, 'config', ScanConfig); + } + + getEntitiesResponse(root: Element): Element { + // @ts-expect-error + return root.get_configs.get_configs_response; + } + + async get( + params: HttpCommandInputParams = {}, + options: HttpCommandOptions = {}, + ) { + const response = await this.httpGetWithTransform( + { + ...params, + usage_type: 'scan', + }, + options, + ); + const {entities, filter, counts} = this.getCollectionListFromRoot( + response.data, + ); + return response.set(entities, {filter, counts}); + } +} + +export default ScanConfigsCommand; diff --git a/src/gmp/gmp.ts b/src/gmp/gmp.ts index fed5651071..1cc3802703 100644 --- a/src/gmp/gmp.ts +++ b/src/gmp/gmp.ts @@ -3,8 +3,6 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -import 'gmp/commands/scan-configs'; - import {getCommands} from 'gmp/command'; import AgentCommand from 'gmp/commands/agent'; import AgentGroupCommand from 'gmp/commands/agent-group'; @@ -78,6 +76,8 @@ import ResultCommand from 'gmp/commands/result'; import ResultsCommand from 'gmp/commands/results'; import RoleCommand from 'gmp/commands/role'; import RolesCommand from 'gmp/commands/roles'; +import ScanConfigCommand from 'gmp/commands/scan-config'; +import ScanConfigsCommand from 'gmp/commands/scan-configs'; import ScannerCommand from 'gmp/commands/scanner'; import ScannersCommand from 'gmp/commands/scanners'; import ScheduleCommand from 'gmp/commands/schedule'; @@ -195,6 +195,8 @@ class Gmp { public readonly resourcenames: ResourceNamesCommand; public readonly role: RoleCommand; public readonly roles: RolesCommand; + public readonly scanconfig: ScanConfigCommand; + public readonly scanconfigs: ScanConfigsCommand; public readonly scanner: ScannerCommand; public readonly scanners: ScannersCommand; public readonly schedule: ScheduleCommand; @@ -316,6 +318,8 @@ class Gmp { this.resourcenames = new ResourceNamesCommand(this.http); this.role = new RoleCommand(this.http); this.roles = new RolesCommand(this.http); + this.scanconfig = new ScanConfigCommand(this.http); + this.scanconfigs = new ScanConfigsCommand(this.http); this.scanner = new ScannerCommand(this.http); this.scanners = new ScannersCommand(this.http); this.schedule = new ScheduleCommand(this.http); diff --git a/src/gmp/models/scan-config.ts b/src/gmp/models/scan-config.ts index 42166ef8b6..fcf5c56072 100644 --- a/src/gmp/models/scan-config.ts +++ b/src/gmp/models/scan-config.ts @@ -11,6 +11,10 @@ import {isEmpty} from 'gmp/utils/string'; type ScanConfigPreferenceValue = string | number; +export type ScanConfigTrend = + | typeof SCANCONFIG_TREND_DYNAMIC + | typeof SCANCONFIG_TREND_STATIC; + export interface ScanConfigFamilyElement { name: string; growing?: number; @@ -35,7 +39,7 @@ export interface ScanConfigScannerElement extends ModelElement { __text?: string; } -interface ScanConfigElement extends ModelElement { +export interface ScanConfigElement extends ModelElement { deprecated?: YesNo; families?: { family: ScanConfigFamilyElement | ScanConfigFamilyElement[];