text:
require('dotenv').config()
const CveId = require('../src/model/cve-id')
const logger = require('../src/middleware/logger')
const getConstants = require('../src/constants').getConstants
const errors = require('../src/controller/cve-id.controller/error')
const error = new errors.CveIdControllerError()
const CONSOLE_OUTPUT = false

// DONE *
async function reserveCveId (req, res) {
  const requester = req.ctx.user
  const cnaShortName = req.ctx.org
  let batchType
  let amount
  let shortName
  let year
  const orgRepo = req.ctx.repositories.getOrgRepository()

  Object.keys(req.ctx.query).forEach(k => {
    const key = k.toLowerCase()

    if (key === 'amount') {
      amount = req.ctx.query.amount
    } else if (key === 'batch_type') {
      batchType = req.ctx.query.batch_type
    } else if (key === 'short_name') {
      shortName = req.ctx.query.short_name
    } else if (key === 'cve_year') {
      year = req.ctx.query.cve_year
    }
  })

  const result = await orgRepo.findOneByShortName(shortName)
  if (!result) {
    return res.status(403).json(error.orgDne(shortName))
  }

  const payload = await getPayload(req, result)
  if (amount > payload.available) {
    return res.status(403).json(error.overIdQuota(payload))
  }

  if (batchType === 'non-sequential' || batchType === 'nonsequential') {
    await nonSequentialReservation(year, amount, shortName, cnaShortName, requester, payload.available, res, req)
  }
}

// DONE *
async function nonSequentialReservation (year, amount, shortName, cnaShortName, requester, availableIds, res, req) {
  const cveIdRepo = req.ctx.repositories.getCveIdRepository()
  const cveIdRangeRepo = req.ctx.repositories.getCveIdRangeRepository()
  const reqUUID = req.ctx.uuid
  const CONSTANTS = getConstants()
  let isFull = false
  let available
  amount = parseInt(amount)
  let availableLimit = Math.max(3 * amount, CONSTANTS.DEFAULT_AVAILABLE_POOL)
  let result = await cveIdRangeRepo.findOne({ cve_year: year })

  if (CONSOLE_OUTPUT) {
    console.log('amount = ' + amount)
    console.log('availableLimit = ' + availableLimit)
  }

  // Cve Id Range for 'year' does not exists
  if (!result) {
    logger.info('CVE IDs for year ' + year + ' cannot be reserved at this time.')
    res.header(CONSTANTS.QUOTA_HEADER, availableIds)
    return res.status(403).json(error.cannotReserveForYear(year))
  }

  if (CONSOLE_OUTPUT) {
    console.log('available count (uncapped) = ' + (await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' })).length) // get available ids
  }

  available = await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' }, { limit: availableLimit }) // get available ids

  if (CONSOLE_OUTPUT) {
    console.log('available count (capped) = ' + available.length) // get available ids
  }

  // Case 1: Not enough IDs in the 'AVAILABLE' pool
  if (available.length < availableLimit) {
    result = await incrementNonSequentialPool(availableLimit, result.ranges.general.end, result.ranges.general.top_id, amount, available.length, year, cveIdRangeRepo)
    isFull = result.isFull

    if (isFull) {
      logger.error('The cve id non-sequential block is full for year ' + year + '. No more sequential ids can be reserved at this time.')
      res.header(CONSTANTS.QUOTA_HEADER, availableIds)
      return res.status(403).json(error.yearRangeFull(year))
    }

    await allocateAvailableCveIds(result.ids, year, cveIdRepo) // Pool was incremented. Create 'AVAILABLE' cve ids.

    if (CONSOLE_OUTPUT) {
      console.log('available count (uncapped) = ' + (await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' })).length) // get available ids
    }

    available = await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' }, { limit: availableLimit }) // get available ids

    if (CONSOLE_OUTPUT) {
      console.log('available count (capped) = ' + available.length) // get available ids
    }
  }

  // Case 2: Enough IDs in the 'AVAILABLE' pool
  const orgRepo = req.ctx.repositories.getOrgRepository()
  const userRepo = req.ctx.repositories.getUserRepository()
  let index
  let counter = 0
  let dummyCounter = 0
  const cveIdDocuments = []
  const cveIdDocumentsUUID = []
  const owningOrgUUID = await orgRepo.getOrgUUID(shortName)
  const orgUUID = await orgRepo.getOrgUUID(cnaShortName)
  const requesterUUID = (await userRepo.findOneByUserNameAndOrgUUID(requester, orgUUID)).UUID

  if (CONSOLE_OUTPUT) {
    console.log('counter = ' + counter)
    console.log('dummyCounter = ' + dummyCounter)
  }

  while ((counter < amount) && !isFull) {
    index = getRandomInt(0, available.length) // get random index in the available array
    result = await reserveNonSequentialCveId(index, available, year, shortName, cnaShortName, requester, owningOrgUUID, orgUUID, requesterUUID, dummyCounter, cveIdRepo)

    if (CONSOLE_OUTPUT && !result.isReserved) {
      console.log('isReserved: ' + result.isReserved)
    }

    if (result.isReserved) {
      cveIdDocuments.push(result.cveId) // add reserved cve id to the array of reserved cve ids
      cveIdDocumentsUUID.push(result.cveIdUUID) // add reserved cve id UUID to the array of reserved cve ids
      available.splice(index, 1) // remove reserved cve id from the 'AVAILABLE' pool
      counter++

      if (CONSOLE_OUTPUT) {
        console.log('cveIdDocuments: ' + cveIdDocuments.length + ', available: ' + available.length + ', counter = ' + counter)
      }
    } else {
      if (CONSOLE_OUTPUT) {
        console.log('available = ' + available.length)
        console.log('available count (uncapped) = ' + (await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' })).length) // get available ids
      }

      available = await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' }, { limit: availableLimit }) // get available ids

      if (CONSOLE_OUTPUT) {
        console.log('available count (capped) = ' + available.length) // get available ids
      }

      availableLimit = Math.max(3 * (amount - counter), CONSTANTS.DEFAULT_AVAILABLE_POOL) // recalculate the available limit since some ids might have been reserved

      if (CONSOLE_OUTPUT) {
        console.log('availableLimit = ' + availableLimit)
      }

      // Case 1: Not enough IDs in the 'AVAILABLE' pool
      if (available.length < availableLimit) {
        result = await cveIdRangeRepo.findOne({ cve_year: year })
        result = await incrementNonSequentialPool(availableLimit, result.ranges.general.end, result.ranges.general.top_id, amount - counter, available.length, year, cveIdRangeRepo)
        isFull = result.isFull

        if (isFull) {
          logger.info({ message: 'Only ' + counter + ' cve ids were reserved because there are not enough ids in the CVE ID non-sequential block. Non-sequential CVE IDs were reserved for \'' + shortName + '\' org on behalf of \'' + cnaShortName + '\' org.', cve_ids: cveIdDocumentsUUID })
          res.header(CONSTANTS.QUOTA_HEADER, availableIds - counter)
          return res.status(206).json(error.reservedPartialAmount(counter, cveIdDocuments))
        }

        await allocateAvailableCveIds(result.ids, year, cveIdRepo) // Pool was incremented. Create 'AVAILABLE' cve ids.

        if (CONSOLE_OUTPUT) {
          console.log('available count (uncapped) = ' + (await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' })).length) // get available ids
        }

        available = await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' }, { limit: availableLimit }) // get available ids

        if (CONSOLE_OUTPUT) {
          console.log('available count (capped) = ' + available.length) // get available ids
        }
      }
    }

    dummyCounter++

    if (CONSOLE_OUTPUT) {
      console.log('dummyCounter = ' + dummyCounter)
    }
  }

  if (!isFull) {
    const payload = {
      action: 'nonsequential_reservation',
      change: 'Non-sequential CVE IDs were reserved for \'' + shortName + '\' org on behalf of \'' + cnaShortName + '\' org.',
      req_UUID: reqUUID,
      org_UUID: orgUUID,
      user_UUID: requesterUUID,
      cve_ids: cveIdDocumentsUUID
    }

    logger.info(JSON.stringify(payload))
    res.header(CONSTANTS.QUOTA_HEADER, availableIds - amount)
    return res.status(200).json({ cve_ids: cveIdDocuments })
  }
}

// DONE
async function incrementNonSequentialPool (availableLimit, end, top, amount, available, year, cveIdRR) {
  let increment = availableLimit - available + amount // the amount is the increment amount
  const cveIdRangeRepo = cveIdRR
  const endRange = parseInt(end)
  const topId = parseInt(top)

  if (CONSOLE_OUTPUT) {
    console.log('increment = ' + increment)
    console.log('endRange = ' + endRange)
    console.log('topId = ' + topId)
  }

  // Cap increment to end of general CVE ID block
  if (endRange < (topId + increment)) {
    increment = endRange - topId
  }

  if (CONSOLE_OUTPUT) {
    console.log('increment = ' + increment)
  }

  const result = {
    isFull: false,
    ids: null
  }

  if (increment > 0) {
    let r = await cveIdRangeRepo.findOneAndUpdate({ $and: [{ cve_year: year }, { 'ranges.general.end': { $gte: increment } }] }, { $inc: { 'ranges.general.top_id': increment } }, { new: true })

    if (CONSOLE_OUTPUT) {
      console.log('top_id = ' + r.ranges.general.top_id)
    }

    // Cap increment because it went over end of general block
    if (r.ranges.general.top_id > endRange) {
      if (CONSOLE_OUTPUT) {
        console.log('increment = ' + increment)
      }

      increment = increment - (r.ranges.general.top_id - endRange) // adjusting real increment
      r = await cveIdRangeRepo.findOneAndUpdate({ cve_year: year }, { $set: { 'ranges.general.top_id': endRange } }, { new: true }) // Cap top_id to end of the block

      if (CONSOLE_OUTPUT) {
        console.log('top_id = ' + r.ranges.general.top_id)
      }
    }

    if (CONSOLE_OUTPUT) {
      console.log('increment = ' + increment)
    }

    if (increment > 0) {
      result.ids = generateSequentialIds(year, r.ranges.general.top_id, increment)
    } else if (available < amount) { // You hit the end of the boundary
      result.isFull = true
    }
  } else if (available < amount) { // You hit the end of the boundary
    result.isFull = true
  }

  return result
}

// DONE *
async function allocateAvailableCveIds (ids, year, cveIdR) {
  if (ids) {
    const cveIdRepo = cveIdR
    const cveIdDocuments = []
    let cveId

    ids.forEach(id => {
      cveId = new CveId()
      cveId.cve_id = id
      cveId.cve_year = year
      cveId.state = 'AVAILABLE'
      cveId.owning_cna = 'N/A' // the org who gets assigned the reserved CVE IDs
      cveId.reserved = Date.now()
      cveId.requested_by = {
        cna: 'N/A', // the org who requested the CVE IDs
        user: 'N/A'
      }

      cveIdDocuments.push(cveId)
    })

    if (CONSOLE_OUTPUT) {
      console.log('Allocated ids: [' + cveIdDocuments[0].cve_id + ', ... , ' + cveIdDocuments[cveIdDocuments.length - 1].cve_id + ']')
      console.log('Allocated count = ' + cveIdDocuments.length)
    }

    await cveIdRepo.insertMany(cveIdDocuments) // Save the 'AVAILABLE' cve ids
  }
}

// DONE *
async function reserveNonSequentialCveId (index, available, year, shortName, cnaShortName, requester, owningOrgUUID, orgUUID, requesterUUID, dummyCounter, cveIdR) {
  // Update available Cve Id
  const cveIdUUID = new CveId()
  const cveId = new CveId()
  const cveIdRepo = cveIdR
  cveIdUUID.cve_id = cveId.cve_id = available[index].cve_id
  cveIdUUID.cve_year = cveId.cve_year = year
  cveIdUUID.state = cveId.state = 'RESERVED'
  cveIdUUID.owning_cna = owningOrgUUID
  cveId.owning_cna = shortName // the org who gets assigned the reserved CVE IDs
  cveIdUUID.reserved = cveId.reserved = Date.now()
  cveIdUUID.requested_by = {
    cna: orgUUID, // the org who requested the CVE IDs
    user: requesterUUID
  }
  cveId.requested_by = {
    cna: cnaShortName, // the org who requested the CVE IDs
    user: requester
  }

  const result = {
    cveId: cveId,
    cveIdUUID: cveIdUUID
  }

  if (dummyCounter === 5) {
    result.isReserved = await cveIdRepo.findOneAndUpdate({ cve_id: 'CVE-2888-5465', state: 'AVAILABLE' }, cveIdUUID, { new: true })
  } else {
    result.isReserved = await cveIdRepo.findOneAndUpdate({ cve_id: cveIdUUID.cve_id, state: 'AVAILABLE' }, cveIdUUID, { new: true })
  }

  return result
}

// DONE *
async function getPayload (req, org) {
  const payload = {
    id_quota: org.policies.id_quota
  }
  const cveIdRepo = req.ctx.repositories.getCveIdRepository()

  const result = await cveIdRepo.countDocuments({ owning_cna: org.UUID, state: 'RESERVED' })
  payload.total_reserved = result
  payload.available = (payload.id_quota - payload.total_reserved)

  return payload
}

// DONE
function generateSequentialIds (year, topId, increment) {
  const start = topId - increment + 1 // before the pool 'AVAILABLE' pool increment
  const end = topId // after the 'AVAILABLE' pool increment
  const ids = []

  if (CONSOLE_OUTPUT) {
    console.log('start = ' + start)
    console.log('end = ' + end)
  }

  for (let i = start; i < end + 1; i++) {
    ids.push('CVE-' + year + '-' + String(i).padStart(4, '0'))
  }

  if (CONSOLE_OUTPUT) {
    console.log('Generated ids: [' + ids[0] + ', ... , ' + ids[ids.length - 1] + ']')
  }

  return ids
}

// DONE
function getRandomInt (min, max) {
  min = Math.ceil(min)
  max = Math.floor(max)

  return Math.floor(Math.random() * (max - min) + min) // The maximum is exclusive and the minimum is inclusive
}

module.exports = {
  CVEID_RESERVE: reserveCveId
}


text:
require('dotenv').config()
const CveId = require('../src/model/cve-id')
const logger = require('../src/middleware/logger')
const getConstants = require('../src/constants').getConstants
const errors = require('../src/controller/cve-id.controller/error')
const error = new errors.CveIdControllerError()
const reservedByOther = []
const CONSOLE_OUTPUT = false

async function reserveCveId (req, res) {
  const requester = req.ctx.user
  const cnaShortName = req.ctx.org
  let batchType
  let amount
  let shortName
  let year
  const orgRepo = req.ctx.repositories.getOrgRepository()

  Object.keys(req.ctx.query).forEach(k => {
    const key = k.toLowerCase()

    if (key === 'amount') {
      amount = req.ctx.query.amount
    } else if (key === 'batch_type') {
      batchType = req.ctx.query.batch_type
    } else if (key === 'short_name') {
      shortName = req.ctx.query.short_name
    } else if (key === 'cve_year') {
      year = req.ctx.query.cve_year
    }
  })

  const result = await orgRepo.findOneByShortName(shortName)
  if (!result) {
    return res.status(403).json(error.orgDne(shortName))
  }

  const payload = await getPayload(req, result)
  if (amount > payload.available) {
    return res.status(403).json(error.overIdQuota(payload))
  }

  if (batchType === 'non-sequential' || batchType === 'nonsequential') {
    await nonSequentialReservation(year, amount, shortName, cnaShortName, requester, payload.available, res, req)
  }
}

async function nonSequentialReservation (year, amount, shortName, cnaShortName, requester, availableIds, res, req) {
  const cveIdRepo = req.ctx.repositories.getCveIdRepository()
  const cveIdRangeRepo = req.ctx.repositories.getCveIdRangeRepository()
  const orgRepo = req.ctx.repositories.getOrgRepository()
  const userRepo = req.ctx.repositories.getUserRepository()
  const reqUUID = req.ctx.uuid
  const CONSTANTS = getConstants()
  let isFull = false
  let available
  amount = parseInt(amount)
  let availableLimit = Math.max(3 * amount, CONSTANTS.DEFAULT_AVAILABLE_POOL)
  let result = await cveIdRangeRepo.findOne({ cve_year: year })

  if (CONSOLE_OUTPUT) {
    console.log('amount = ' + amount)
    console.log('availableLimit = ' + availableLimit)
  }

  // Cve Id Range for 'year' does not exists
  if (!result) {
    logger.info('CVE IDs for year ' + year + ' cannot be reserved at this time.')
    res.header(CONSTANTS.QUOTA_HEADER, availableIds)
    return res.status(403).json(error.cannotReserveForYear(year))
  }

  if (CONSOLE_OUTPUT) {
    console.log('available count (uncapped) = ' + (await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' })).length) // get available ids
  }

  available = await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' }, { limit: availableLimit }) // get available ids

  if (CONSOLE_OUTPUT) {
    console.log('available count (capped) = ' + available.length) // get available ids
  }

  // Case 1: Not enough IDs in the 'AVAILABLE' pool
  if (available.length < availableLimit) {
    result = await incrementNonSequentialPool(availableLimit, result.ranges.general.end, result.ranges.general.top_id, amount, available.length, year, cveIdRangeRepo, cveIdRepo, userRepo, orgRepo)
    isFull = result.isFull

    if (isFull) {
      logger.error('The cve id non-sequential block is full for year ' + year + '. No more sequential ids can be reserved at this time.')
      res.header(CONSTANTS.QUOTA_HEADER, availableIds)
      return res.status(403).json(error.yearRangeFull(year))
    }

    await allocateAvailableCveIds(result.ids, year, cveIdRepo) // Pool was incremented. Create 'AVAILABLE' cve ids.

    if (CONSOLE_OUTPUT) {
      console.log('available count (uncapped) = ' + (await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' })).length) // get available ids
    }

    available = await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' }, { limit: availableLimit }) // get available ids

    if (CONSOLE_OUTPUT) {
      console.log('available count (capped) = ' + available.length) // get available ids
    }
  }

  // Case 2: Enough IDs in the 'AVAILABLE' pool
  let index
  let counter = 0
  const cveIdDocuments = []
  const cveIdDocumentsUUID = []
  const owningOrgUUID = await orgRepo.getOrgUUID(shortName)
  const orgUUID = await orgRepo.getOrgUUID(cnaShortName)
  const requesterUUID = (await userRepo.findOneByUserNameAndOrgUUID(requester, orgUUID)).UUID

  if (CONSOLE_OUTPUT) {
    console.log('counter = ' + counter)
  }

  while ((counter < amount) && !isFull) {
    index = getRandomInt(0, available.length) // get random index in the available array
    result = await reserveNonSequentialCveId(index, available, year, shortName, cnaShortName, requester, owningOrgUUID, orgUUID, requesterUUID, cveIdRepo)

    if (CONSOLE_OUTPUT && !result.isReserved) {
      console.log('isReserved: ' + result.isReserved)
    }

    if (result.isReserved) {
      cveIdDocuments.push(result.cveId) // add reserved cve id to the array of reserved cve ids
      cveIdDocumentsUUID.push(result.cveIdUUID) // add reserved cve id UUID to the array of reserved cve ids
      available.splice(index, 1) // remove reserved cve id from the 'AVAILABLE' pool
      counter++

      if (CONSOLE_OUTPUT) {
        console.log('cveIdDocuments: ' + cveIdDocuments.length + ', available: ' + available.length + ', counter = ' + counter)
      }
    } else {
      if (CONSOLE_OUTPUT) {
        console.log('available = ' + available.length)
        console.log('available count (uncapped) = ' + (await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' })).length) // get available ids
      }

      available = await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' }, { limit: availableLimit }) // get available ids

      if (CONSOLE_OUTPUT) {
        console.log('available count (capped) = ' + available.length) // get available ids
      }

      availableLimit = Math.max(3 * (amount - counter), CONSTANTS.DEFAULT_AVAILABLE_POOL) // recalculate the available limit since some ids might have been reserved

      if (CONSOLE_OUTPUT) {
        console.log('availableLimit = ' + availableLimit)
      }

      // Case 1: Not enough IDs in the 'AVAILABLE' pool
      if (available.length < availableLimit) {
        result = await cveIdRangeRepo.findOne({ cve_year: year })
        result = await incrementNonSequentialPool(availableLimit, result.ranges.general.end, result.ranges.general.top_id, amount - counter, available.length, year, cveIdRangeRepo, cveIdRepo, userRepo, orgRepo)
        isFull = result.isFull

        if (isFull) {
          logger.info({ message: 'Only ' + counter + ' cve ids were reserved because there are not enough ids in the CVE ID non-sequential block. Non-sequential CVE IDs were reserved for \'' + shortName + '\' org on behalf of \'' + cnaShortName + '\' org.', cve_ids: cveIdDocumentsUUID })
          res.header(CONSTANTS.QUOTA_HEADER, availableIds - counter)
          return res.status(206).json(error.reservedPartialAmount(counter, cveIdDocuments))
        }

        await allocateAvailableCveIds(result.ids, year, cveIdRepo) // Pool was incremented. Create 'AVAILABLE' cve ids.

        if (CONSOLE_OUTPUT) {
          console.log('available count (uncapped) = ' + (await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' })).length) // get available ids
        }

        available = await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' }, { limit: availableLimit }) // get available ids

        if (CONSOLE_OUTPUT) {
          console.log('available count (capped) = ' + available.length) // get available ids
        }
      }
    }
  }

  if (!isFull) {
    const payload = {
      action: 'nonsequential_reservation',
      change: 'Non-sequential CVE IDs were reserved for \'' + shortName + '\' org on behalf of \'' + cnaShortName + '\' org.',
      req_UUID: reqUUID,
      org_UUID: orgUUID,
      user_UUID: requesterUUID,
      cve_ids: cveIdDocumentsUUID
    }

    logger.info(JSON.stringify(payload))
    res.header(CONSTANTS.QUOTA_HEADER, availableIds - amount)
    return res.status(200).json({ cve_ids: cveIdDocuments })
  }
}

async function incrementNonSequentialPool (availableLimit, end, top, amount, available, year, cveIdRR, cveIdR, userR, orgR) {
  let increment = availableLimit - available + amount // the amount is the increment amount
  const cveIdRangeRepo = cveIdRR
  const cveIdRepo = cveIdR
  const userRepo = userR
  const orgRepo = orgR
  const endRange = parseInt(end)
  const topId = parseInt(top)

  if (CONSOLE_OUTPUT) {
    console.log('increment = ' + increment)
    console.log('endRange = ' + endRange)
    console.log('topId = ' + topId)
  }

  // Cap increment to end of general CVE ID block
  if (endRange < (topId + increment)) {
    increment = endRange - topId
  }

  if (CONSOLE_OUTPUT) {
    console.log('increment = ' + increment)
  }

  const result = {
    isFull: false,
    ids: null
  }

  // ---- Reserve 20 cve ids ----
  let temp = await cveIdRangeRepo.findOneAndUpdate({ $and: [{ cve_year: year }, { 'ranges.general.end': { $gte: increment } }] }, { $inc: { 'ranges.general.top_id': increment } }, { new: true })

  if (CONSOLE_OUTPUT) {
    console.log('top_id = ' + temp.ranges.general.top_id)
  }

  temp = generateSequentialIds(year, temp.ranges.general.top_id, increment)
  await allocateAvailableCveIds(temp, year, cveIdRepo) // Pool was incremented. Create 'AVAILABLE' cve ids.

  if (CONSOLE_OUTPUT) {
    console.log('available count (uncapped) = ' + (await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' })).length) // get available ids
  }

  available = await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' }, { limit: availableLimit }) // get available ids

  if (CONSOLE_OUTPUT) {
    console.log('available count (capped) = ' + available.length) // get available ids
  }

  const tempOwningOrgUUID = await orgRepo.getOrgUUID('mitre')
  const tempOrgUUID = tempOwningOrgUUID
  const tempRequesterUUID = (await userRepo.findOneByUserNameAndOrgUUID('cpadro', tempOrgUUID)).UUID

  for (let i = 0; i < 20; i++) {
    const r = getRandomInt(0, available.length)
    temp = await reserveNonSequentialCveId(r, available, year, 'mitre', 'mitre', 'cpadro', tempOwningOrgUUID, tempOrgUUID, tempRequesterUUID, cveIdRepo)
    available.splice(r, 1) // remove reserved cve id from the 'AVAILABLE' pool
    reservedByOther.push(temp.cveId.cve_id)

    if (CONSOLE_OUTPUT) {
      console.log('* available = ' + available.length)
      console.log('* available count (uncapped) = ' + (await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' })).length) // get available ids
      console.log('* available count (capped) = ' + (await cveIdRepo.find({ cve_year: year, state: 'AVAILABLE' }, { limit: availableLimit })).length) // get available ids
    }
  }
  // ----------------------------

  if (increment > 0) {
    let r = await cveIdRangeRepo.findOneAndUpdate({ $and: [{ cve_year: year }, { 'ranges.general.end': { $gte: increment } }] }, { $inc: { 'ranges.general.top_id': increment } }, { new: true })

    if (CONSOLE_OUTPUT) {
      console.log('top_id = ' + r.ranges.general.top_id)
    }

    // Cap increment because it went over end of general block
    //  -------------------- F - G ----------------------
    if (r.ranges.general.top_id > endRange) {
      if (CONSOLE_OUTPUT) {
        console.log('increment = ' + increment)
      }

      increment = increment - (r.ranges.general.top_id - endRange) // adjusting real increment
      r = await cveIdRangeRepo.findOneAndUpdate({ cve_year: year }, { $set: { 'ranges.general.top_id': endRange } }, { new: true }) // Cap top_id to end of the block

      if (CONSOLE_OUTPUT) {
        console.log('top_id = ' + r.ranges.general.top_id)
      }
    }
    //  -----------------------------------------------

    if (CONSOLE_OUTPUT) {
      console.log('increment = ' + increment)
    }

    if (increment > 0) {
      result.ids = generateSequentialIds(year, r.ranges.general.top_id, increment)
    } else if (available < amount) { // You hit the end of the boundary
      //  ------------------- F -------------------------
      result.isFull = true
      //  -----------------------------------------------
    }
  } else if (available < amount) { // You hit the end of the boundary
    result.isFull = true
  }

  return result
}

async function allocateAvailableCveIds (ids, year, cveIdR) {
  if (ids) {
    const cveIdRepo = cveIdR
    const cveIdDocuments = []
    let cveId

    ids.forEach(id => {
      cveId = new CveId()
      cveId.cve_id = id
      cveId.cve_year = year
      cveId.state = 'AVAILABLE'
      cveId.owning_cna = 'N/A' // the org who gets assigned the reserved CVE IDs
      cveId.reserved = Date.now()
      cveId.requested_by = {
        cna: 'N/A', // the org who requested the CVE IDs
        user: 'N/A'
      }

      cveIdDocuments.push(cveId)
    })

    if (CONSOLE_OUTPUT) {
      console.log('Allocated ids: [' + cveIdDocuments[0].cve_id + ', ... , ' + cveIdDocuments[cveIdDocuments.length - 1].cve_id + ']')
      console.log('Allocated count = ' + cveIdDocuments.length)
    }

    await cveIdRepo.insertMany(cveIdDocuments) // Save the 'AVAILABLE' cve ids
  }
}

async function reserveNonSequentialCveId (index, available, year, shortName, cnaShortName, requester, owningOrgUUID, orgUUID, requesterUUID, cveIdR) {
  // Update available Cve Id
  const cveIdUUID = new CveId()
  const cveId = new CveId()
  const cveIdRepo = cveIdR
  cveIdUUID.cve_id = cveId.cve_id = available[index].cve_id
  cveIdUUID.cve_year = cveId.cve_year = year
  cveIdUUID.state = cveId.state = 'RESERVED'
  cveIdUUID.owning_cna = owningOrgUUID
  cveId.owning_cna = shortName // the org who gets assigned the reserved CVE IDs
  cveIdUUID.reserved = cveId.reserved = Date.now()
  cveIdUUID.requested_by = {
    cna: orgUUID, // the org who requested the CVE IDs
    user: requesterUUID
  }
  cveId.requested_by = {
    cna: cnaShortName, // the org who requested the CVE IDs
    user: requester
  }

  const result = {
    cveId: cveId,
    cveIdUUID: cveIdUUID,
    isReserved: await cveIdRepo.findOneAndUpdate({ cve_id: cveIdUUID.cve_id, state: 'AVAILABLE' }, cveIdUUID, { new: true })
  }

  return result
}

async function getPayload (req, org) {
  const payload = {
    id_quota: org.policies.id_quota
  }
  const cveIdRepo = req.ctx.repositories.getCveIdRepository()

  const result = await cveIdRepo.countDocuments({ owning_cna: org.UUID, state: 'RESERVED' })
  payload.total_reserved = result
  payload.available = (payload.id_quota - payload.total_reserved)

  return payload
}

function generateSequentialIds (year, topId, increment) {
  const start = topId - increment + 1 // before the pool 'AVAILABLE' pool increment
  const end = topId // after the 'AVAILABLE' pool increment
  const ids = []

  if (CONSOLE_OUTPUT) {
    console.log('start = ' + start)
    console.log('end = ' + end)
  }

  for (let i = start; i < end + 1; i++) {
    ids.push('CVE-' + year + '-' + String(i).padStart(4, '0'))
  }

  if (CONSOLE_OUTPUT) {
    console.log('Generated ids: [' + ids[0] + ', ... , ' + ids[ids.length - 1] + ']')
  }

  return ids
}

function getRandomInt (min, max) {
  min = Math.ceil(min)
  max = Math.floor(max)

  return Math.floor(Math.random() * (max - min) + min) // The maximum is exclusive and the minimum is inclusive
}

module.exports = {
  CVEID_RESERVE: reserveCveId,
  reservedByOther: reservedByOther
}

repo_name: CVEProject/cve-services

repo_language: JavaScript

file_name: Dockerfile

mime_type: text/plain


text:
version: '3'
services:
  docdb:
    # use a mongo image that most closely matches the DocumentDB API
    image: mongo:3.6.20-xenial
    container_name: mongo
    env_file: .docker-env
    networks: ["cve-services"]
    ports: ["27017:27017"]
  cveawg:
    container_name: cveawg
    build:
      context: ../
      dockerfile: docker/Dockerfile.dev
    depends_on: [docdb]
    env_file: .docker-env
    networks: ["cve-services"]
    ports: ["3000:3000"]
    volumes:
      - ../package.json:/home/node/app/package.json
      - ../src:/home/node/app/src
      - ../test:/home/node/app/test
      - ../test-examples:/home/node/app/test-examples
      - ../test-utils:/home/node/app/test-utils
      - ../.eslintrc.js:/home/node/app/.eslintrc.js

networks:
  cve-services:


text:
#!/bin/sh
echo "> NODE_ENV=$NODE_ENV"
echo "> MONGO_HOST=$MONGO_HOST"
echo "> MONGO_PORT=$MONGO_PORT"

# run the application based on node environment
if [[ "$NODE_ENV" == "development" ]]; then
    npm run start:dev
elif [[ "$NODE_ENV" == "staging" ]]; then
    npm run start:stage
elif [[ "$NODE_ENV" == "integration" ]]; then
    npm run start:int
elif [[ "$NODE_ENV" == "prod-staging" ]]; then
    npm run start:prdstg
elif [[ "$NODE_ENV" == "production" ]]; then
    npm run start:prd
else
    echo "Your NODE_ENV, $NODE_ENV, specified in entrypoint.sh does not correspond with an application environment."
    exit 1
fi


text:
FROM node:16.14.2-alpine3.15
# do not copy files we mount in compose
# our local and production docker files could co-exist using "targets" in
# the `FROM` statements

LABEL \
    mitre.name=cveawg \
    mitre.project=cveawg

# Run an optional pre-flight script for host-dependent reqs such as CA certs
# Use --build-arg:
# docker compose --build-arg CVE_PREFLIGHT="wget -q -O - --no-check-certificate http://pki.local/install_certs.sh | sh"
ARG CVE_PREFLIGHT
RUN sh -c "${CVE_PREFLIGHT:-exit 0}"

# Install python/pip (required for argon2 build from source)
ENV PYTHONUNBUFFERED=1
RUN apk add --update --no-cache python3
RUN python3 -m ensurepip
RUN pip3 install --no-cache --upgrade pip setuptools

# Install build essentials (also required for argon2)
RUN apk add --update --no-cache build-base

# Set up directory to run as node user rather than root
ADD . /home/node/app
RUN chown -R node:node /home/node
RUN rm -Rf /home/node/app/.git

WORKDIR /home/node/app

# Run as the node user rather than root
USER node

# copy into development container only what we need to have
# Change db hostname from localhost to docdb for use inside docker
COPY --chown=node:node docker/default.json-docker /home/node/app/config/default.json

RUN npm install
COPY --chown=node:node docker/entrypoint.sh /home/node/app/entrypoint.sh
RUN echo '{}' > /home/node/app/config/development.json
RUN echo '{}' > /home/node/app/config/integration.json
RUN echo '{}' > /home/node/app/config/production.json
RUN echo '{}' > /home/node/app/config/test.json
RUN echo '{}' > /home/node/app/config/staging.json

# we don't need to expose ports that are exposed in our compose file
ENTRYPOINT '/home/node/app/entrypoint.sh'


text:
FROM node:16.14.2-alpine3.15

LABEL \
    mitre.name=cveawg \
    mitre.project=cveawg

# Run an optional pre-flight script for host-dependent reqs such as CA certs
# Use --build-arg:
# docker compose --build-arg CVE_PREFLIGHT="wget -q -O - --no-check-certificate http://pki.local/install_certs.sh | sh"
ARG CVE_PREFLIGHT
RUN sh -c "${CVE_PREFLIGHT:-exit 0}"

# Install python/pip (required for argon2 build from source)
ENV PYTHONUNBUFFERED=1
RUN apk add --update --no-cache python3
RUN python3 -m ensurepip
RUN pip3 install --no-cache --upgrade pip setuptools

# Install build essentials (also required for argon2)
RUN apk add --update --no-cache build-base

# Set up directory to run as node user rather than root
ADD . /home/node/app
RUN rm -Rf /home/node/app/.git # we don't need this
RUN chown -R node:node /home/node

WORKDIR /home/node/app

RUN npm install --production
COPY --chown=node:node docker/entrypoint.sh /home/node/app/entrypoint.sh
RUN echo '{}' > /home/node/app/config/dev.json
RUN echo '{}' > /home/node/app/config/test.json
RUN echo '{}' > /home/node/app/config/staging.json

# Change db hostname from localhost to docdb for use inside docker
COPY docker/default.json-docker /home/node/app/config/default.json

# Run as the node user rather than root
USER node
EXPOSE 3000
ENTRYPOINT '/home/node/app/entrypoint.sh'


text:
# Using Docker with CVE Services

## Security Considerations

>**Warning**
>
>DO NOT use the included Docker compose configuration on a public network. The environment and docker-compose.yml files contain CVE Services credentials and do not enforce MongoDB authentication. This enables rapid, local-only development and is not secure for public deployment.

## Local Development and Testing

The following builds and runs cve-services (Node.js app and Mongo) in Docker containers. The included example configurations run the services in `dev` or `int` mode.

>**Note**
>
> These commands must be run from the `docker/` directory.

### Environments

See the `.docker-env.example` and `.docker-env.int-example` files for examples of required environment variables. For development environments, it's important to define the following:

```
LOCAL_KEY=XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX
NODE_ENV=development
```

When using a development environment, the `LOCAL_KEY` is the API token key for the secretariat. In integration environments, the API keys will be written to a file named `user-secret.txt` in the project directory after database population.

### Start Docker Containers

```bash
cd docker/
git switch <branchname>

# use the integration environment
cp .docker-env.int-example .docker-env
docker compose up --build
```

>**Note**
>
> Use branch name `int` for penetration testing, and `dev` for local development.

Docker will build or update the containers if needed. In a few minutes, you should see something similar to the following:

```
[+] Running 3/3
 ⠿ Network docker_cve-services  Created
 ⠿ Container mongo              Created
 ⠿ Container cveawg             Created
Attaching to cveawg, mongo
mongo   | 2022-06-07T19:29:07.594+0000 I CONTROL  [initandlisten] MongoDB starting : pid=1 port=27017 dbpath=/data/db 64-bit host=551bb45dbadc
...
mongo   | 2022-06-07T19:29:08.106+0000 I NETWORK  [initandlisten] listening via socket bound to 0.0.0.0
mongo   | 2022-06-07T19:29:08.106+0000 I NETWORK  [initandlisten] listening via socket bound to /tmp/mongodb-27017.sock
mongo   | 2022-06-07T19:29:08.106+0000 I NETWORK  [initandlisten] waiting for connections on port 27017
...
cveawg  | > cve-services@0.0.3 start:dev /app
cveawg  | > node src/swagger.js && NODE_ENV=development node src/scripts/updateOpenapiHost.js && NODE_ENV=development node-dev src/index.js
...
cveawg  | 2022-06-07 19:29:10 [info]: "Using NODE_ENV 'development' and app environment 'development'"
cveawg  | 2022-06-07 19:29:11 [info]: "Using dbName = cve_dev"
...
cveawg  | 2022-06-07 19:29:11 [info]: "Successfully connected to database!"
cveawg  | 2022-06-07 19:29:11 [info]: "Serving on port 3000"
```

#### The Docker CVE_PREFLIGHT argument

The Docker build process fetches resources on the public internet. Some corporate environments require specific configuration to enable communication with public networks (e.g., corporate proxies or custom CA certificates). The included Dockerfiles expose an optional build argument, `CVE_PREFLIGHT`, that allows a script to run before any network traffic is attempted. For example, to fetch and run a script that installs corporate CA certificates:

```
docker compose build --no-cache --build-arg CVE_PREFLIGHT="wget -q -O - --no-check-certificate https://pki.intranet/install_certs.sh | sh"
```

If you do not require special configuration to access the internet, you can safely omit the build argument.

### Pre-load Data

Populate mongoDB with test data included in `datadump/pre-population/`

Run the command below using `populate:dev` or `populate:int` depending on your environment:
```
docker-compose exec cveawg npm run populate:int
```

You should see the following:
```
> cve-services@0.0.3 populate:dev /app
> NODE_ENV=development node-dev src/scripts/populate.js

2022-06-07 19:58:32 [info]: "Using NODE_ENV 'development' and app environment 'development'"
2022-06-07 19:58:32 [info]: "Using dbName = cve_dev"
2022-06-07 19:58:32 [info]: "Will try to connect to database cve_dev at docdb:27017"
2022-06-07 19:58:32 [info]: "Successfully connected to database!"
Are you sure you wish to pre-populate the database for the development environment? Doing so will drop the Cve, Cve-Id-Range, Cve-Id, User, Org collection(s) in the cve_dev database. (y/n) y

2022-06-07 19:58:37 [info]: "Populating Org collection..."
2022-06-07 19:58:37 [info]: "Org populated!"
2022-06-07 19:58:37 [info]: "Populating User collection..."
2022-06-07 19:58:38 [info]: "User populated!"
2022-06-07 19:58:38 [info]: "Populating Cve-Id-Range collection..."
2022-06-07 19:58:38 [info]: "Populating Cve collection..."
2022-06-07 19:58:38 [info]: "Populating Cve-Id collection..."
2022-06-07 19:58:38 [info]: "Cve-Id-Range populated!"
2022-06-07 19:58:38 [info]: "Cve populated!"
2022-06-07 19:58:39 [info]: "Cve-Id populated!"
2022-06-07 19:58:39 [info]: "Successfully populated the database!"

```

### Display the API key

The API token key is generated or stored differently depending on the value of the `NODE_ENV` environment variable.

#### Integration

For `integration` Node environments, the API key will be generate and saved to the `user-secret.txt` file when the database is populated.

Display the key with:

`docker-compose exec cveawg grep admin2 user-secret.txt`

#### Development

In `development` environments, the API is the value of the `LOCAL_KEY` variable in the `.docker-env` file.

You can view the value for the running container with:

`docker-compose exec cveawg env | grep LOCAL_KEY`

### Use Curl to Test

#### Create a curl config file (recommended)

Securely create a curl config file in `$HOME/.curl-cve-config` similar to the following, where each line is a curl argument. In dev environments, use the value of the `LOCAL_KEY` environment variable (also output when pre-populating) as the API key.

>**Warning**
>
>To ensure security of the credentials, create an empty file and restrict its permissions before saving the API key:
>
>`touch $HOME/.curl-cve-config && chmod 600 $HOME/.curl-cve-config && vi $HOME/.curl-cve-config`

```
-H "CVE-API-ORG: mitre"
-H "CVE-API-USER: admin2@mitre.org"
-H "CVE-API-KEY: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX"
-H "Content-type: application/json"
-s
-S
```

#### Use curl to test the API endpoints

See the [API documentation](https://github.com/CVEProject/cve-services#api-documentation) for available endpoints.

  * Show CVE IDs:
  `curl -K ~/.curl-cve-config http://localhost:3000/api/cve-id`

  * Retrieve organization info (Secretariat only. Use appropriate credentials in curl config file):
  `curl -K ~/.curl-cve-config http://localhost:3000/api/org`

  * Add a CNA (Secretariat only. Use appropriate credentials in curl config file):
    `curl -K ~/.curl-cve-config -X POST \
      --data-binary '{"name": "Example Corporation","short_name": "exampleCorp"}' \
      http://localhost:3000/api/org`

>**Note**
>
>Each command returns unformatted JSON. Piping through a formatter like [JQ](https://stedolan.github.io/jq/) makes it easier to read: `curl -K ~/.curl-cve-config http://localhost:3000/api/cve-id | jq .`

## To shell into the web app server

  `docker compose exec cveawg /bin/sh`

## Mongo DB

The `docker-compose.yml` file exposes the default Mongo port to the host: `localhost:27017`. You can connect using any Mongo viewer such as [Mongo Express](https://github.com/mongo-express/mongo-express) or [Compass](https://www.mongodb.com/try/download/compass) on the host.

## Running unit tests

You can run unit tests using the docker image by running the following command:

`docker exec -it cveawg npm run test`


type: object

type: string

type: array

required: lang value


title: Media type

description: RFC2046 compliant IANA Media type for eg., text/markdown, text/html.

examples: text/markdown text/html image/png image/svg audio/mp3

type: boolean

title: Encoding

description: If true then the value field contains the media data encoded in base64. If false then the value field contains the UTF-8 media content.

description: Supporting media content, up to 16K. If base64 is true, this field stores base64 encoded data.

required: type value


type: integer


title: Media type

title: Encoding

format: date-time


required: affected descriptions providerMetadata references


title: CVE JSON record format

description: cve-schema specifies the CVE JSON record format. This is the blueprint for a rich set of JSON data that can be submitted by CVE Numbering Authorities (CNAs) and Authorized Data Publishers (ADPs) to describe a CVE Record. Some examples of CVE Record data include CVE ID number, affected product(s), affected version(s), and public references. While those specific items are required when assigning a CVE, there are many other optional data in the schema that can be used to enrich CVE Records for community benefit. Learn more about the CVE program at [the official website](https://cve.mitre.org). This CVE JSON record format is defined using JSON Schema. Learn more about JSON Schema [here](https://json-schema.org/).

format: uri

$ref: #/definitions/uriType

$ref: #/definitions/tagExtension

$ref: #/definitions/uuidType

format: date

required: vendor product

required: collectionURL packageName

$ref: #/definitions/status

required: version status

required: version status versionType

$ref: #/definitions/version

required: at status

required: cveId assignerOrgId state

$ref: #/definitions/cveId

$ref: #/definitions/orgId

$ref: #/definitions/shortName

$ref: #/definitions/userId

$ref: #/definitions/timestamp

$ref: #/definitions/providerMetadata

$ref: #/definitions/descriptions

$ref: #/definitions/affected

$ref: #/definitions/problemTypes

$ref: #/definitions/references

$ref: #/definitions/impacts

$ref: #/definitions/metrics

$ref: #/definitions/configurations

$ref: #/definitions/workarounds

$ref: #/definitions/solutions

$ref: #/definitions/exploits

$ref: #/definitions/timeline

$ref: #/definitions/credits

$ref: #/definitions/source

required: providerMetadata descriptions affected references

description: CVSS Version

required: version vectorString baseScore baseSeverity


required: affected descriptions references


title: CVE JSON record format

$ref: #/definitions/uriType

$ref: #/definitions/tagExtension

$ref: #/definitions/uuidType

$ref: #/definitions/status

$ref: #/definitions/version

$ref: #/definitions/cveId

$ref: #/definitions/orgId

$ref: #/definitions/shortName

description: CVSS Version

title: Create

description: When a CNA populates the data associated with a CVE ID as a CVE Record, the state of the CVE Record is Published.

description:
A set of structures (called containers) used to store vulnerability information related to a specific CVE ID provided by a specific organization participating in the CVE program. Each container includes information provided by a different source.

At minimum, a 'cna' container containing the vulnerability information provided by the CNA who initially assigned the CVE ID must be included.

There can only be one 'cna' container, as there can only be one assigning CNA. However, there can be multiple 'adp' containers, allowing multiple organizations participating in the CVE program to add additional information related to the vulnerability. For the most part, the 'cna' and 'adp' containers contain the same properties. The main differences are the source of the information and the 'cna' container requires the CNA include certain fields, while the 'adp' container does not.


text:
# CVE-API-Unit-Tests
In order to Run Tests, make sure you configure a DB connection in the config/config.json under the `test` environment.

## Dependencies

This project uses or depends on software from

- NodeJS https://nodejs.org/
- Express https://github.com/expressjs
- MYSQL
- Sequelize http://docs.sequelizejs.com/
- Mocha https://mochajs.org/
- Chai https://www.chaijs.com/

In order to run unit tests, use the following command:

```sh
npm run start:test
```

## Notes

Please note, test will run on every attempted `git push` command. Pushing into a repo will only be successful if and only if tests successfully pass.


text:
const express = require('express')
const app = express()
const chai = require('chai')
const expect = chai.expect
chai.use(require('chai-http'))

// Body Parser Middleware
app.use(express.json()) // Allows us to handle raw JSON data
app.use(express.urlencoded({ extended: false })) // Allows us to handle url encoded data
const middleware = require('../../../src/middleware/middleware')
app.use(middleware.createCtxAndReqUUID)

const getConstants = require('../../../src/constants').getConstants
const nonExistentCveRecord = 'CVE-2020-1425'
const cveIdPublished5 = 'CVE-2017-4024'
const cveIdRejected5 = 'CVE-2017-5835'
const errors = require('../../../src/controller/cve.controller/error')
const error = new errors.CveControllerError()

const cveFixtures = require('./mockObjects.cve')
const cveController = require('../../../src/controller/cve.controller/cve.controller')
const cveParams = require('../../../src/controller/cve.controller/cve.middleware')

class MyCveNegativeTests {
  async findOneByCveId () {
    return null
  }
}

class MyCvePositiveTests {
  async findOneByCveId (id) {
    if (id === cveIdPublished5) {
      return cveFixtures.cveRecordPublished5
    } else if (id === cveIdRejected5) {
      return cveFixtures.cveRecordRejected5
    }
  }
}

app.route('/cve-get-record-negative-tests/:id')
  .get((req, res, next) => {
    const factory = {
      getCveRepository: () => { return new MyCveNegativeTests() }
    }
    req.ctx.repositories = factory
    next()
  }, cveParams.parseGetParams, cveController.CVE_GET_SINGLE)

app.route('/cve-get-record-positive-tests/:id')
  .get((req, res, next) => {
    const factory = {
      getCveRepository: () => { return new MyCvePositiveTests() }
    }
    req.ctx.repositories = factory
    next()
  }, cveParams.parseGetParams, cveController.CVE_GET_SINGLE)

describe('Testing the GET /cve/:id endpoint in Cve Controller', () => {
  context('Negative Tests', () => {
    it('CVE_RECORD_DNE returned: The cve record does not exist for the provided cve id', (done) => {
      chai.request(app)
        .get(`/cve-get-record-negative-tests/${nonExistentCveRecord}`)
        .set(cveFixtures.secretariatHeader)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(404)
          expect(res).to.have.property('body').and.to.be.a('object')
          const errObj = error.cveRecordDne()
          expect(res.body.error).to.equal(errObj.error)
          expect(res.body.message).to.equal(errObj.message)
          done()
        })
    })
  })

  context('Positive Tests', () => {
    it('JSON schema v5.0 returned: The secretariat gets a cve record in PUBLISHED state', (done) => {
      chai.request(app)
        .get(`/cve-get-record-positive-tests/${cveIdPublished5}`)
        .set(cveFixtures.secretariatHeader)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          const CONSTANTS = getConstants()

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body).to.have.nested.property('cveMetadata.cveId').and.to.equal(cveIdPublished5)
          expect(res.body).to.have.nested.property('cveMetadata.state').and.to.equal(CONSTANTS.CVE_STATES.PUBLISHED)
          done()
        })
    })

    it('JSON schema v5.0 returned: The secretariat gets a cve record in REJECTED state', (done) => {
      chai.request(app)
        .get(`/cve-get-record-positive-tests/${cveIdRejected5}`)
        .set(cveFixtures.secretariatHeader)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          const CONSTANTS = getConstants()

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body).to.have.nested.property('cveMetadata.cveId').and.to.equal(cveIdRejected5)
          expect(res.body).to.have.nested.property('cveMetadata.state').and.to.equal(CONSTANTS.CVE_STATES.REJECTED)
          done()
        })
    })

    it('Filter by assignerShortName', (done) => {
      chai.request(app)
        .get(`/cve-get-record-positive-tests/${cveIdPublished5}`)
        .set(cveFixtures.secretariatHeader)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body).to.have.nested.property('cveMetadata.cveId').and.to.equal(cveIdPublished5)
          expect(res.body).to.have.nested.property('cveMetadata.assignerShortName').and.to.equal('cisco')
          done()
        })
    })

    it('Filter by assigner', (done) => {
      chai.request(app)
        .get(`/cve-get-record-positive-tests/${cveIdPublished5}`)
        .set(cveFixtures.secretariatHeader)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body).to.have.nested.property('cveMetadata.cveId').and.to.equal(cveIdPublished5)
          expect(res.body).to.have.nested.property('cveMetadata.assignerOrgId').and.to.equal('88c02595-c8f7-4864-a0e7-e09b3e1da691')
          done()
        })
    })
  })
})


text:
const express = require('express')
const app = express()
const chai = require('chai')
const expect = chai.expect
chai.use(require('chai-http'))

// Body Parser Middleware
app.use(express.json()) // Allows us to handle raw JSON data
app.use(express.urlencoded({ extended: false })) // Allows us to handle url encoded data
const middleware = require('../../../src/middleware/middleware')
app.use(middleware.createCtxAndReqUUID)

const getConstants = require('../../../src/constants').getConstants
const nonExistentCveId = 'CVE-2020-1425'
const cveIdPublished5 = 'CVE-2017-4024'
const cveIdReserved5 = 'CVE-2017-5833'
const cveIdRejected5 = 'CVE-2017-5835'
const cvePublishedPass5 = require('../../schemas/5.0/' + cveIdPublished5 + '_published.json')
const cveReservedPass5 = require('../../schemas/5.0/' + cveIdReserved5 + '_reserved.json')
const cveRejectedPass5 = require('../../schemas/5.0/' + cveIdRejected5 + '_rejected.json')
const errors = require('../../../src/controller/cve.controller/error')
const error = new errors.CveControllerError()

const cveFixtures = require('./mockObjects.cve')
const cveController = require('../../../src/controller/cve.controller/cve.controller')
const cveParams = require('../../../src/controller/cve.controller/cve.middleware')

describe('Testing the PUT /cve/:id endpoint in Cve Controller', () => {
  context('Negative Tests', () => {
    it('CVE record not updated when cve id doesnt match record', (done) => {
      class OrgRepo {
        async getOrgUUID () {
          return null
        }
      }
      class CveRepo {
        async updateByCveId (cveId, newCve) {
          return null
        }

        async findOneByCveId () {
          return null
        }
      }
      class CveIdRepo {
        async updateByCveId (cveId, newCve) {
          return null
        }

        async findOneByCveId () {
          return null
        }
      }
      class UserRepo {
        async getUserUUID () {
          return null
        }
      }
      app.route('/cve-not-updated-id-mismatch/:id')
        .put((req, res, next) => {
          const factory = {
            getCveIdRepository: () => { return new CveIdRepo() },
            getCveRepository: () => { return new CveRepo() },
            getOrgRepository: () => { return new OrgRepo() },
            getUserRepository: () => { return new UserRepo() }
          }
          req.ctx.repositories = factory
          next()
        }, cveParams.parsePostParams, cveController.CVE_UPDATE_SINGLE)

      chai.request(app)
        .put(`/cve-not-updated-id-mismatch/${nonExistentCveId}`)
        .set(cveFixtures.secretariatHeader)
        .send(cvePublishedPass5)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(400)
          expect(res).to.have.property('body').and.to.be.a('object')
          const errObj = error.cveIdMismatch()
          expect(res.body.error).to.equal(errObj.error)
          expect(res.body.message).to.equal(errObj.message)
          done()
        })
    })

    it('CVE record not updated when cve record doesnt exist', (done) => {
      const nonExistentCve = JSON.parse(JSON.stringify(cvePublishedPass5))
      nonExistentCve.cveMetadata.cveId = nonExistentCveId
      class OrgRepo {
        async getOrgUUID () {
          return null
        }
      }
      class CveRepo {
        async updateByCveId (cveId, newCve) {
          // test shouldn't reach here
          expect.fail()
          return null
        }

        async findOneByCveId () {
          return null
        }
      }
      class CveIdRepo {
        async updateByCveId (cveId, newCve) {
          expect.fail()
          return null
        }

        async findOneByCveId () {
          return true
        }
      }
      class UserRepo {
        async getUserUUID () {
          return null
        }
      }
      app.route('/cve-not-updated-cve-dne/:id')
        .put((req, res, next) => {
          const factory = {
            getCveIdRepository: () => { return new CveIdRepo() },
            getCveRepository: () => { return new CveRepo() },
            getOrgRepository: () => { return new OrgRepo() },
            getUserRepository: () => { return new UserRepo() }
          }
          req.ctx.repositories = factory
          next()
        }, cveParams.parsePostParams, cveController.CVE_UPDATE_SINGLE)

      chai.request(app)
        .put(`/cve-not-updated-cve-dne/${nonExistentCveId}`)
        .set(cveFixtures.secretariatHeader)
        .send(nonExistentCve)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(403)
          expect(res).to.have.property('body').and.to.be.a('object')
          const errObj = error.cveRecordDne()
          expect(res.body.error).to.equal(errObj.error)
          expect(res.body.message).to.equal(errObj.message)
          done()
        })
    })

    it('CVE record not updated when cve id doesnt exist', (done) => {
      const nonExistentCve = JSON.parse(JSON.stringify(cvePublishedPass5))
      nonExistentCve.cveMetadata.cveId = nonExistentCveId
      class OrgRepo {
        async getOrgUUID () {
          return null
        }
      }
      class CveRepo {
        async updateByCveId (cveId, newCve) {
          // test shouldn't reach here
          expect.fail()
          return null
        }

        async findOneByCveId () {
          // set to anything not false to pass the check
          return true
        }
      }
      class CveIdRepo {
        async updateByCveId (cveId, newCve) {
          expect.fail()
          return null
        }

        async findOneByCveId () {
          return null
        }
      }
      class UserRepo {
        async getUserUUID () {
          return null
        }
      }
      app.route('/cve-not-updated-cve-id-dne/:id')
        .put((req, res, next) => {
          const factory = {
            getCveIdRepository: () => { return new CveIdRepo() },
            getCveRepository: () => { return new CveRepo() },
            getOrgRepository: () => { return new OrgRepo() },
            getUserRepository: () => { return new UserRepo() }
          }
          req.ctx.repositories = factory
          next()
        }, cveParams.parsePostParams, cveController.CVE_UPDATE_SINGLE)

      chai.request(app)
        .put(`/cve-not-updated-cve-id-dne/${nonExistentCveId}`)
        .set(cveFixtures.secretariatHeader)
        .send(nonExistentCve)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(403)
          expect(res).to.have.property('body').and.to.be.a('object')
          const errObj = error.cveDne()
          expect(res.body.error).to.equal(errObj.error)
          expect(res.body.message).to.equal(errObj.message)
          done()
        })
    })

    it('CVE record not updated when cve record updated to RESERVED state', (done) => {
      class OrgRepo {
        async getOrgUUID () {
          return null
        }
      }
      class CveRepo {
        async updateByCveId (cveId, newCve) {
          return null
        }
      }
      class CveIdRepo {
        async updateByCveId (cveId, newCve) {
          return null
        }
      }
      class UserRepo {
        async getUserUUID () {
          return null
        }
      }
      app.route('/cve-not-updated-reserved-state/:id')
        .put((req, res, next) => {
          const factory = {
            getCveIdRepository: () => { return new CveIdRepo() },
            getCveRepository: () => { return new CveRepo() },
            getOrgRepository: () => { return new OrgRepo() },
            getUserRepository: () => { return new UserRepo() }
          }
          req.ctx.repositories = factory
          next()
        }, cveParams.parsePostParams, cveController.CVE_UPDATE_SINGLE)

      chai.request(app)
        .put(`/cve-not-updated-reserved-state/${cveIdReserved5}`)
        .set(cveFixtures.secretariatHeader)
        .send(cveReservedPass5)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(400)
          expect(res).to.have.property('body').and.to.be.a('object')
          const CONSTANTS = getConstants()
          const errObj = error.cveUpdateUnsupportedState(CONSTANTS.CVE_STATES.RESERVED)
          expect(res.body.error).to.equal(errObj.error)
          expect(res.body.message).to.equal(errObj.message)
          done()
        })
    })
  })

  context('Positive Tests', () => {
    it('Update CVE record when requestor is secretariat', (done) => {
      class OrgRepo {
        async getOrgUUID () {
          return null
        }
      }
      class CveRepo {
        async updateByCveId (cveId, newCve) {
          expect(cveId).to.equal(cveIdPublished5)
          expect(newCve).to.have.nested.property('cve.cveMetadata.state').and.to.equal('PUBLISHED')
          return null
        }

        async findOneByCveId () {
          return true
        }
      }
      class CveIdRepo {
        async updateByCveId (cveId, newCve) {
          expect(cveId).to.equal(cveIdPublished5)
          expect(newCve).to.have.property('state')
          return null
        }

        async findOneByCveId () {
          return true
        }
      }
      class UserRepo {
        async getUserUUID () {
          return null
        }
      }
      app.route('/cve-update-record/:id')
        .put((req, res, next) => {
          const factory = {
            getCveIdRepository: () => { return new CveIdRepo() },
            getCveRepository: () => { return new CveRepo() },
            getOrgRepository: () => { return new OrgRepo() },
            getUserRepository: () => { return new UserRepo() }
          }
          req.ctx.repositories = factory
          next()
        }, cveParams.parsePostParams, cveController.CVE_UPDATE_SINGLE)

      chai.request(app)
        .put(`/cve-update-record/${cveIdPublished5}`)
        .set(cveFixtures.secretariatHeader)
        .send(cvePublishedPass5)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body).to.have.property('updated').and.to.be.a('object')
          expect(res.body.updated).to.have.nested.property('cveMetadata.cveId').and.to.equal(cveIdPublished5)
          expect(res.body.updated).to.have.nested.property('cveMetadata.state').and.to.equal('PUBLISHED')
          done()
        })
    })

    it('Update CVE record when requestor is secretariat and valid REJECTED JSON', (done) => {
      class OrgRepo {
        async getOrgUUID () {
          return null
        }
      }
      class CveRepo {
        async updateByCveId (cveId, newCve) {
          return null
        }

        async findOneByCveId () {
          return true
        }
      }
      class CveIdRepo {
        async updateByCveId (cveId, newCve) {
          return null
        }

        async findOneByCveId () {
          return true
        }
      }
      class UserRepo {
        async getUserUUID () {
          return null
        }
      }
      app.route('/cve-update-record-rejected/:id')
        .put((req, res, next) => {
          const factory = {
            getCveIdRepository: () => { return new CveIdRepo() },
            getCveRepository: () => { return new CveRepo() },
            getOrgRepository: () => { return new OrgRepo() },
            getUserRepository: () => { return new UserRepo() }
          }
          req.ctx.repositories = factory
          next()
        }, cveParams.parsePostParams, cveController.CVE_UPDATE_SINGLE)

      chai.request(app)
        .put(`/cve-update-record-rejected/${cveIdRejected5}`)
        .set(cveFixtures.secretariatHeader)
        .send(cveRejectedPass5)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body).to.have.property('updated').and.to.be.a('object')
          expect(res.body.updated).to.have.nested.property('cveMetadata.cveId').and.to.equal(cveIdRejected5)
          expect(res.body.updated).to.have.nested.property('cveMetadata.state').and.to.equal('REJECTED')
          done()
        })
    })
  })
})


text:
const express = require('express')
const app = express()
const chai = require('chai')
const expect = chai.expect
chai.use(require('chai-http'))

// Body Parser Middleware
app.use(express.json()) // Allows us to handle raw JSON data
app.use(express.urlencoded({ extended: false })) // Allows us to handle url encoded data
const middleware = require('../../../src/middleware/middleware')
app.use(middleware.createCtxAndReqUUID)

const cveFixtures = require('./mockObjects.cve')
const cnaPass = require('../../schemas/cna-container/cna-container_pass.json')
const cnaFail = require('../../schemas/cna-container/cna-container-missing-container.json')
const cveMw = require('../../../src/controller/cve.controller/cve.middleware')

app.route('/api/test/mw/cnaschema')
  .post(cveMw.validateCveCnaContainerJsonSchema, (req, res) => {
    return res.status(200).json({ message: 'Success! You have reached the target endpoint.' })
  })

describe('Test the JSON schema cna container validation middleware', () => {
  context('Negative Tests', () => {
    it('Json validator fails because missing cnaContainer object', (done) => {
      chai.request(app)
        .post('/api/test/mw/cnaschema')
        .set(cveFixtures.secretariatHeader)
        .send(cnaFail)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(400)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body).to.have.property('message').and.to.be.a('string')
          expect(res.body.message).to.equal('CVE cnaContainer JSON schema validation FAILED.')
          expect(res.body.details).to.have.property('errors').and.to.be.an('array')
          expect(res.body.details.errors[0].message).to.have.string("must have required property 'cnaContainer'")
          done()
        })
    })
  })

  context('Positive Tests', () => {
    it('Json validator pass with all required elements', (done) => {
      chai.request(app)
        .post('/api/test/mw/cnaschema')
        .set(cveFixtures.secretariatHeader)
        .send(cnaPass)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body).to.have.property('message').and.to.be.a('string')
          expect(res.body.message).to.equal('Success! You have reached the target endpoint.')
          done()
        })
    })
  })
})


text:
const express = require('express')
const app = express()
const chai = require('chai')
const expect = chai.expect
chai.use(require('chai-http'))

// Body Parser Middleware
app.use(express.json()) // Allows us to handle raw JSON data
app.use(express.urlencoded({ extended: false })) // Allows us to handle url encoded data
const middleware = require('../../../src/middleware/middleware')
app.use(middleware.createCtxAndReqUUID)

const nonExistentCveId = 'CVE-2020-1425'
const cveIdPublished5 = 'CVE-2017-4024'
const cveIdReserved = 'CVE-2017-5835'
const url = process.env.NODE_ENV === 'staging' ? 'https://test.cve.org/' : 'https://cve.org/' // Used in updateCna response messages
const cveCnaContainerFail = require('../../schemas/cna-container/cna-container_fail.json')
const cveCnaContainerPass = require('../../schemas/cna-container/cna-container_pass.json')
const cveRecordPublished = require('../../schemas/5.0/CVE-2017-4024_published.json')
const errors = require('../../../src/controller/cve.controller/error')
const error = new errors.CveControllerError()

const getConstants = require('../../../src/constants').getConstants
const cveFixtures = require('./mockObjects.cve')
const cveController = require('../../../src/controller/cve.controller/cve.controller')
const cveParams = require('../../../src/controller/cve.controller/cve.middleware')

class MyOrg {
  async getOrgUUID (shortName) {
    if (shortName === cveFixtures.regularOrg.short_name) {
      return cveFixtures.regularOrg.UUID
    } else if (shortName === cveFixtures.secretariatOrg.short_name) {
      return cveFixtures.secretariatOrg.UUID
    }
    return null
  }

  async isSecretariat (org) {
    if (org === cveFixtures.secretariatHeader['CVE-API-ORG']) {
      return true
    }
    return null
  }

  async findOneByUUID () {
    return cveFixtures.secretariatOrg
  }
}

class MyUser {
  async getUserUUID () {
    return null
  }
}

class MyCveIdNegativeTests {
  async findOneByCveId (id) {
    const CONSTANTS = getConstants()

    if (id === cveIdPublished5) {
      const fixture = Object.assign({}, cveFixtures.cvePublished5)
      fixture.state = CONSTANTS.CVE_STATES.REJECTED
      fixture.owning_cna = 'random'
      return fixture
    }
    if (id === cveIdReserved) {
      const fixture = Object.assign({}, cveFixtures.cveRejected5)
      fixture.reserved = new Date()
      return fixture
    }
    return null
  }

  async updateByCveId () {
    return null
  }
}

class MyCveNegativeTests {
  async findOneByCveId (id) {
    if (id === cveIdPublished5) {
      const cveModel = { cve: cveRecordPublished }
      return cveModel
    }
    return null
  }

  async updateByCveId () {
    return null
  }
}

class MyCveIdPositiveTests {
  async findOneByCveId (id) {
    if (id === cveIdPublished5) {
      const cveId = Object.assign({}, cveFixtures.cvePublished5)
      cveId.owning_cna = cveFixtures.regularOrg.UUID
      return cveId
    }
    if (id === cveIdReserved) {
      const cveId = Object.assign({}, cveFixtures.cveRejected5)
      cveId.owning_cna = cveFixtures.regularOrg.UUID
      return cveId
    }
    return cveFixtures.cveRejected5
  }

  async updateByCveId (id, cveId) {
    return null
  }
}

class MyCvePositiveTests {
  async findOneByCveId (id) {
    if (id === cveIdPublished5) {
      const cveModel = { cve: cveRecordPublished }
      return cveModel
    }
    return null
  }

  async updateByCveId () {
    return null
  }
}

app.route('/cve-cna-negative-tests/:id')
  .put((req, res, next) => {
    const factory = {
      getCveIdRepository: () => { return new MyCveIdNegativeTests() },
      getCveRepository: () => { return new MyCveNegativeTests() },
      getOrgRepository: () => { return new MyOrg() },
      getUserRepository: () => { return new MyUser() }
    }
    req.ctx.repositories = factory
    next()
  }, cveParams.parsePostParams, cveController.CVE_UPDATE_CNA)

app.route('/cve-cna-positive-tests/:id')
  .put((req, res, next) => {
    const factory = {
      getCveIdRepository: () => { return new MyCveIdPositiveTests() },
      getCveRepository: () => { return new MyCvePositiveTests() },
      getOrgRepository: () => { return new MyOrg() },
      getUserRepository: () => { return new MyUser() }
    }
    req.ctx.repositories = factory
    next()
  }, cveParams.parsePostParams, cveController.CVE_UPDATE_CNA)

describe('Testing the PUT /cve/:id/cna endpoint in Cve Controller', () => {
  context('Negative Tests', () => {
    it('should return 400 when cveId does not exist', (done) => {
      chai.request(app)
        .put(`/cve-cna-negative-tests/${nonExistentCveId}`)
        .set(cveFixtures.secretariatHeader)
        .send(cveCnaContainerFail)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(400)
          expect(res).to.have.property('body').and.to.be.a('object')
          const errObj = error.cveDne()
          expect(res.body.error).to.equal(errObj.error)
          expect(res.body.message).to.equal(errObj.message)
          done()
        })
    })

    it('should return 403 when cveId does not belong to cveId owning org', (done) => {
      const headers = Object.assign({}, cveFixtures.secretariatHeader)
      headers['CVE-API-ORG'] = 'cisco'
      chai.request(app)
        .put(`/cve-cna-negative-tests/${cveIdPublished5}`)
        .set(headers)
        .send(cveCnaContainerFail)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(403)
          expect(res).to.have.property('body').and.to.be.a('object')
          const errObj = error.owningOrgDoesNotMatch()
          expect(res.body.error).to.equal(errObj.error)
          expect(res.body.message).to.equal(errObj.message)
          done()
        })
    })

    it('should return 403 when cve record does not exist', (done) => {
      chai.request(app)
        .put(`/cve-cna-negative-tests/${cveIdReserved}`)
        .set(cveFixtures.secretariatHeader)
        .send(cveCnaContainerFail)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(403)
          expect(res).to.have.property('body').and.to.be.a('object')
          const errObj = error.cveRecordDne()
          expect(res.body.error).to.equal(errObj.error)
          expect(res.body.message).to.equal(errObj.message)
          done()
        })
    })

    it('should return 400 when cve record is not valid', (done) => {
      chai.request(app)
        .put(`/cve-cna-negative-tests/${cveIdPublished5}`)
        .set(cveFixtures.secretariatHeader)
        .send(cveCnaContainerFail)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(400)
          expect(res).to.have.property('body').and.to.be.a('object')
          const errObj = error.invalidCnaContainerJsonSchema()
          expect(res.body.error).to.equal(errObj.error)
          expect(res.body.message).to.equal(errObj.message)
          done()
        })
    })

    it('should return 500 when fails to update cve id state', (done) => {
      chai.request(app)
        .put(`/cve-cna-negative-tests/${cveIdPublished5}`)
        .set(cveFixtures.secretariatHeader)
        .send(cveCnaContainerPass)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(500)
          expect(res).to.have.property('body').and.to.be.a('object')
          const errObj = error.serverError()
          expect(res.body.error).to.equal(errObj.error)
          expect(res.body.message).to.equal(errObj.message)
          done()
        })
    })
  })

  context('Positive Tests', () => {
    it('Put cna container as secretariat', (done) => {
      chai.request(app)
        .put(`/cve-cna-positive-tests/${cveIdPublished5}`)
        .set(cveFixtures.secretariatHeader)
        .send(cveCnaContainerPass)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body.message).to.equal(`${cveIdPublished5} record was successfully updated. This submission should appear on ${url} within 15 minutes.`)
          done()
        })
    })

    it('Put cna container as user', (done) => {
      const headers = Object.assign({}, cveFixtures.secretariatHeader)
      headers['CVE-API-ORG'] = cveFixtures.regularOrg.short_name
      headers['CVE-API-USER'] = cveFixtures.regularUser.username
      chai.request(app)
        .put(`/cve-cna-positive-tests/${cveIdPublished5}`)
        .set(headers)
        .send(cveCnaContainerPass)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body.message).to.include(`${cveIdPublished5} record was successfully updated. This submission should appear on ${url} within 15 minutes.`)
          expect(res.body.created).to.not.equal(cveRecordPublished)
          done()
        })
    })
  })
})


text:
const express = require('express')
const app = express()
const chai = require('chai')
const expect = chai.expect
chai.use(require('chai-http'))

// Body Parser Middleware
app.use(express.json()) // Allows us to handle raw JSON data
app.use(express.urlencoded({ extended: false })) // Allows us to handle url encoded data
const middleware = require('../../../src/middleware/middleware')
app.use(middleware.createCtxAndReqUUID)

const getConstants = require('../../../src/constants').getConstants
const cveList = require('../../schemas/5.0/cveRecordList.json')

const cveFixtures = require('./mockObjects.cve')
const cveController = require('../../../src/controller/cve.controller/cve.controller')
const cveParams = require('../../../src/controller/cve.controller/cve.middleware')

describe('Testing the GET /cve endpoint in Cve Controller', () => {
  context('Positive Tests', () => {
    it('JSON schema v5.0 returned: The secretariat gets a list of non-paginated cve records', (done) => {
      const itemsPerPage = 500

      class MyCvePositiveTests {
        async aggregatePaginate () {
          const res = {
            itemsList: cveList,
            itemCount: cveList.length,
            itemsPerPage: itemsPerPage,
            currentPage: 1,
            pageCount: 1,
            pagingCounter: 1,
            hasPrevPage: false,
            hasNextPage: false,
            prevPage: null,
            nextPage: null
          }

          return res
        }
      }

      app.route('/cve-get-all-records-positive-tests-non-empty-non-paginated')
        .get((req, res, next) => {
          const factory = {
            getCveRepository: () => { return new MyCvePositiveTests() }
          }
          req.ctx.repositories = factory
          next()
        }, cveParams.parseGetParams, cveController.CVE_GET_FILTERED)

      chai.request(app)
        .get('/cve-get-all-records-positive-tests-non-empty-non-paginated')
        .set(cveFixtures.secretariatHeader)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body).to.have.property('cveRecords').and.to.be.a('array').and.to.have.lengthOf(cveList.length)
          expect(res.body).to.not.have.property('totalCount')
          expect(res.body).to.not.have.property('itemsPerPage')
          expect(res.body).to.not.have.property('pageCount')
          expect(res.body).to.not.have.property('currentPage')
          expect(res.body).to.not.have.property('prevPage')
          expect(res.body).to.not.have.property('nextPage')
          res.body.cveRecords.forEach(obj => {
            const CONSTANTS = getConstants()
            // only cve records with state 'PUBLISHED' or 'REJECTED' are stored in the db
            expect(obj).to.have.nested.property('cveMetadata.state').and.to.be.oneOf([CONSTANTS.CVE_STATES.PUBLISHED, CONSTANTS.CVE_STATES.REJECTED])
          })
          done()
        })
    })

    it('JSON schema v5.0 returned: The secretariat gets a list of paginated cve records with "page" query param undefined', (done) => {
      const itemsPerPage = 3

      class MyCvePositiveTests {
        async aggregatePaginate () {
          const res = {
            itemsList: [cveList[0], cveList[1], cveList[2]],
            itemCount: cveList.length,
            itemsPerPage: itemsPerPage,
            currentPage: 1,
            pageCount: 2,
            pagingCounter: 1,
            hasPrevPage: false,
            hasNextPage: true,
            prevPage: null,
            nextPage: 2
          }

          return res
        }
      }

      app.route('/cve-get-all-records-positive-tests-non-empty-paginated')
        .get((req, res, next) => {
          const factory = {
            getCveRepository: () => { return new MyCvePositiveTests() }
          }
          req.ctx.repositories = factory
          // temporary fix for #920: force pagnation
          req.TEST_PAGINATOR_LIMIT = itemsPerPage
          next()
        }, cveParams.parseGetParams, cveController.CVE_GET_FILTERED)

      chai.request(app)
        .get('/cve-get-all-records-positive-tests-non-empty-paginated')
        .set(cveFixtures.secretariatHeader)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          const CONSTANTS = getConstants()

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body).to.have.property('cveRecords').and.to.be.a('array').and.to.have.lengthOf(itemsPerPage)
          expect(res.body).to.have.property('totalCount').and.to.equal(cveList.length)
          expect(res.body).to.have.property('itemsPerPage').and.to.equal(itemsPerPage)
          expect(res.body).to.have.property('pageCount').and.to.equal(2)
          expect(res.body).to.have.property('currentPage').and.to.equal(1)
          expect(res.body).to.have.property('prevPage').and.to.equal(null)
          expect(res.body).to.have.property('nextPage').and.to.equal(2)
          res.body.cveRecords.forEach(obj => {
            // only cve records with state 'PUBLISHED' or 'REJECTED' are stored in the db
            expect(obj).to.have.nested.property('cveMetadata.state').and.to.be.oneOf([CONSTANTS.CVE_STATES.PUBLISHED, CONSTANTS.CVE_STATES.REJECTED])
          })
          done()
        })
    })

    it('JSON schema v5.0 returned: The secretariat gets a list of paginated cve records with "page" query param defined', (done) => {
      const itemsPerPage = 3

      class MyCvePositiveTests {
        async aggregatePaginate () {
          const res = {
            itemsList: [cveList[3], cveList[4]],
            itemCount: cveList.length,
            itemsPerPage: itemsPerPage,
            currentPage: 2,
            pageCount: 2,
            pagingCounter: 1,
            hasPrevPage: true,
            hasNextPage: false,
            prevPage: 1,
            nextPage: null
          }

          return res
        }
      }

      app.route('/cve-get-all-records-positive-tests-non-empty-paginated-2')
        .get((req, res, next) => {
          const factory = {
            getCveRepository: () => { return new MyCvePositiveTests() }
          }
          req.ctx.repositories = factory
          // temporary fix for #920: force pagnation
          req.TEST_PAGINATOR_LIMIT = itemsPerPage
          next()
        }, cveParams.parseGetParams, cveController.CVE_GET_FILTERED)

      chai.request(app)
        .get('/cve-get-all-records-positive-tests-non-empty-paginated-2?page=2')
        .set(cveFixtures.secretariatHeader)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body).to.have.property('cveRecords').and.to.be.a('array').and.to.have.lengthOf(2)
          expect(res.body).to.have.property('totalCount').and.to.equal(cveList.length)
          expect(res.body).to.have.property('itemsPerPage').and.to.equal(itemsPerPage)
          expect(res.body).to.have.property('pageCount').and.to.equal(2)
          expect(res.body).to.have.property('currentPage').and.to.equal(2)
          expect(res.body).to.have.property('prevPage').and.to.equal(1)
          expect(res.body).to.have.property('nextPage').and.to.equal(null)
          res.body.cveRecords.forEach(obj => {
            const CONSTANTS = getConstants()
            // only cve records with state 'PUBLISHED' or 'REJECTED' are stored in the db
            expect(obj).to.have.nested.property('cveMetadata.state').and.to.be.oneOf([CONSTANTS.CVE_STATES.PUBLISHED, CONSTANTS.CVE_STATES.REJECTED])
          })
          done()
        })
    })

    it('JSON schema v5.0 returned: The secretariat gets an empty list of cve records because there are no cve records in the database', (done) => {
      const itemsPerPage = 500

      class MyCvePositiveTests {
        async aggregatePaginate () {
          const res = {
            itemsList: [],
            itemCount: 0,
            itemsPerPage: itemsPerPage,
            currentPage: 1,
            pageCount: 1,
            pagingCounter: 1,
            hasPrevPage: false,
            hasNextPage: false,
            prevPage: null,
            nextPage: null
          }

          return res
        }
      }

      app.route('/cve-get-all-records-positive-tests-empty')
        .get((req, res, next) => {
          const factory = {
            getCveRepository: () => { return new MyCvePositiveTests() }
          }
          req.ctx.repositories = factory
          next()
        }, cveParams.parseGetParams, cveController.CVE_GET_FILTERED)

      chai.request(app)
        .get('/cve-get-all-records-positive-tests-empty')
        .set(cveFixtures.secretariatHeader)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          expect(res.body).to.have.property('cveRecords').and.to.be.a('array').and.to.have.lengthOf(0)
          expect(res.body).to.not.have.property('totalCount')
          expect(res.body).to.not.have.property('itemsPerPage')
          expect(res.body).to.not.have.property('pageCount')
          expect(res.body).to.not.have.property('currentPage')
          expect(res.body).to.not.have.property('prevPage')
          expect(res.body).to.not.have.property('nextPage')
          done()
        })
    })

    it('Filter by reserved state', (done) => {
      class MyCvePositiveTests {
        async filterByState () {
          const res = {
            state: 'RESERVED'
          }

          return res
        }
      }

      app.route('/cve-get-all-records-by-reserved-state')
        .get((req, res, next) => {
          const factory = {
            getCveRepository: () => { return new MyCvePositiveTests() }
          }
          req.ctx.repositories = factory
          next()
        }, cveParams.parseGetParams, cveController.CVE_GET_FILTERED)

      chai.request(app)
        .get('/cve-get-all-records-positive-tests-non-empty-non-paginated')
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          res.body.cveRecords.forEach(obj => {
            const CONSTANTS = getConstants()
            // only cve records with state 'PUBLISHED' or 'REJECTED' are stored in the db
            expect(obj).to.have.nested.property('cveMetadata.state').and.to.be.oneOf([CONSTANTS.CVE_STATES.RESERVED, CONSTANTS.CVE_STATES.REJECTED, CONSTANTS.CVE_STATES.PUBLISHED])
          })
          done()
        })
    })

    it('Filter by published state', (done) => {
      class MyCvePositiveTests {
        async filterByState () {
          const res = {
            state: 'PUBLISHED'
          }

          return res
        }
      }

      app.route('/cve-get-all-records-by-reserved-state')
        .get((req, res, next) => {
          const factory = {
            getCveRepository: () => { return new MyCvePositiveTests() }
          }
          req.ctx.repositories = factory
          next()
        }, cveParams.parseGetParams, cveController.CVE_GET_FILTERED)

      chai.request(app)
        .get('/cve-get-all-records-positive-tests-non-empty-non-paginated')
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          res.body.cveRecords.forEach(obj => {
            const CONSTANTS = getConstants()
            // only cve records with state 'PUBLISHED' or 'REJECTED' are stored in the db
            expect(obj).to.have.nested.property('cveMetadata.state').and.to.be.oneOf([CONSTANTS.CVE_STATES.RESERVED, CONSTANTS.CVE_STATES.REJECTED, CONSTANTS.CVE_STATES.PUBLISHED])
          })
          done()
        })
    })

    it('Filter by rejected state', (done) => {
      class MyCvePositiveTests {
        async filterByState () {
          const res = {
            state: 'REJECTED'
          }

          return res
        }
      }

      app.route('/cve-get-all-records-by-reserved-state')
        .get((req, res, next) => {
          const factory = {
            getCveRepository: () => { return new MyCvePositiveTests() }
          }
          req.ctx.repositories = factory
          next()
        }, cveParams.parseGetParams, cveController.CVE_GET_FILTERED)

      chai.request(app)
        .get('/cve-get-all-records-positive-tests-non-empty-non-paginated')
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          res.body.cveRecords.forEach(obj => {
            const CONSTANTS = getConstants()
            // only cve records with state 'PUBLISHED' or 'REJECTED' are stored in the db
            expect(obj).to.have.nested.property('cveMetadata.state').and.to.be.oneOf([CONSTANTS.CVE_STATES.RESERVED, CONSTANTS.CVE_STATES.REJECTED, CONSTANTS.CVE_STATES.PUBLISHED])
          })
          done()
        })
    })
  })
})


text:
const chai = require('chai')
const expect = chai.expect
const _ = require('lodash')
const cveRecordPublished = require('../../schemas/5.0/CVE-2017-4024_published.json')
const cveRejectExample = require('../../schemas/5.0/rejectCveExample.json')

const Cve = require('../../../src/model/cve')
const cveCopy = _.cloneDeep(cveRecordPublished)

describe('Testing rejecting CVE record that has an ADP container', () => {
  it('Should return rejected Cve record without ADP container', async () => {
    const newRecord = await Cve.updateCveToRejected('', cveRecordPublished.containers.cna.providerMetadata, cveCopy, cveRejectExample)

    expect(newRecord.containers).to.not.have.property('adp')
    expect(cveRecordPublished.containers).to.have.property('adp')
    expect(newRecord.cveMetadata.state).to.equal('REJECTED')
  })
})


text:
const getConstants = require('../../../src/constants').getConstants
const CONSTANTS = getConstants()
const cveIdPublished5 = 'CVE-2017-4024'
const cveIdRejected5 = 'CVE-2017-5835'
const cvePublishedPass5 = require('../../schemas/5.0/' + cveIdPublished5 + '_published.json')
const cveRejectedPass5 = require('../../schemas/5.0/' + cveIdRejected5 + '_rejected.json')

const secretariatHeader = {
  'content-type': 'application/json',
  'CVE-API-ORG': 'mitre',
  'CVE-API-USER': 'cpadro',
  'CVE-API-KEY': 'S96E4QT-SMT4YE3-KX03X6K-4615CED'
}

const secretariatOrg = {
  UUID: '15fd129f-af00-4d8c-8f7b-e19b0587223f',
  authority: {
    active_roles: [CONSTANTS.AUTH_ROLE_ENUM.CNA, CONSTANTS.AUTH_ROLE_ENUM.SECRETARIAT]
  },
  name: 'The MITRE Corporation',
  policies: {
    id_quota: 1000
  },
  short_name: 'mitre'
}

const secretariatUser = {
  UUID: 'e13186d5-ce3d-4fd9-aecd-8698c26897f2',
  org_UUID: secretariatOrg.UUID,
  name: {
    first: 'Cristina',
    last: 'Padro'
  },
  authority: {
    active_roles: []
  },
  secret: '$argon2i$v=19$m=4096,t=3,p=1$+qGHEfH5h4/tk404iWBxFw$xV96/b4NvQVvlZIq57wTS8s7gfKzsfMXRiOyf3ffgcw',
  username: 'cpadro',
  active: true
}

const regularOrg = {
  UUID: '16fd129f-af00-4d8c-8f7b-e19b0587223a',
  authority: {
    active_roles: [
      CONSTANTS.AUTH_ROLE_ENUM.CNA
    ]
  },
  name: 'Booker LLC',
  short_name: 'window_1',
  time: {
    modified: '2021-05-11T15:07:19.468216Z',
    created: '2021-05-11T15:07:19.468216Z'
  },
  policies: {
    id_quota: 1251
  }
}

const regularUser = {
  UUID: 'f13186d5-ce3d-4fd9-aecd-8698c26897f3',
  org_UUID: regularOrg.UUID,
  name: {
    first: 'Robert',
    last: 'Petal'
  },
  authority: {
    active_roles: []
  },
  secret: '$argon2i$v=19$m=4096,t=3,p=1$+qGHEfH5h4/tk404iWBxFw$xV96/b4NvQVvlZIq57wTS8s7gfKzsfMXRiOyf3ffgcw',
  username: 'rpetal',
  active: true
}

const cveAvailable5 = {
  cve_id: 'CVE-2017-5834',
  cve_year: '2017',
  state: CONSTANTS.CVE_STATES.AVAILABLE,
  owning_cna: 'N/A',
  reserved: Date.now(),
  requested_by: {
    cna: 'N/A',
    user: 'N/A'
  }
}

const cvePublished5 = {
  cve_id: 'CVE-2017-4024',
  cve_year: '2017',
  state: CONSTANTS.CVE_STATES.RESERVED,
  owning_cna: secretariatOrg.UUID,
  reserved: Date.now(),
  requested_by: {
    cna: secretariatUser.org_UUID,
    user: secretariatUser.UUID
  }
}

const cveRejected5 = {
  cve_id: 'CVE-2017-5835',
  cve_year: '2017',
  state: CONSTANTS.CVE_STATES.RESERVED,
  owning_cna: secretariatOrg.UUID,
  reserved: Date.now(),
  requested_by: {
    cna: secretariatUser.org_UUID,
    user: secretariatUser.UUID
  }
}

const cveToReject = {
  cve_id: 'CVE-2019-1421',
  cve_year: '2019',
  state: CONSTANTS.CVE_STATES.RESERVED,
  owning_cna: secretariatOrg.UUID,
  reserved: Date.now(),
  requested_by: {
    cna: secretariatUser.org_UUID,
    user: secretariatUser.UUID
  }
}

const cveRecordPublished5 = {
  time: {
    created: Date.now(),
    modified: Date.now()
  },
  cve: cvePublishedPass5
}

const cveRecordRejected5 = {
  time: {
    created: Date.now(),
    modified: Date.now()
  },
  cve: cveRejectedPass5
}

module.exports = {
  secretariatHeader,
  secretariatOrg,
  secretariatUser,
  regularOrg,
  regularUser,
  cveAvailable5,
  cvePublished5,
  cveRejected5,
  cveToReject,
  cveRecordPublished5,
  cveRecordRejected5
}


text:
const express = require('express')
const app = express()
const chai = require('chai')
const expect = chai.expect
chai.use(require('chai-http'))

// Body Parser Middleware
app.use(express.json()) // Allows us to handle raw JSON data
app.use(express.urlencoded({ extended: false })) // Allows us to handle url encoded data
const middleware = require('../../../src/middleware/middleware')
app.use(middleware.createCtxAndReqUUID)

const errors = require('../../../src/controller/cve.controller/error')
const error = new errors.CveControllerError()
const cveFixtures = require('./mockObjects.cve')
const cveController = require('../../../src/controller/cve.controller/cve.controller')
const cveMiddleware = require('../../../src/controller/cve.controller/cve.middleware')

const rejectedBody = require('../../../test-http/src/test/cve_tests/cve_record_fixtures/rejectBody.json')
const nonExistentId = 'CVE-1800-0001'
const cveIdReserved = 'CVE-2019-1421'

class MyOrg {
  async findOneByShortName (shortName) {
    if (shortName === cveFixtures.regularOrg.short_name) {
      return cveFixtures.regularOrg
    } else if (shortName === cveFixtures.secretariatOrg.short_name) {
      return cveFixtures.secretariatOrg
    }
    return null
  }

  async findOneByUUID (uuid) {
    if (uuid === cveFixtures.regularOrg.UUID) {
      return cveFixtures.regularOrg
    } else if (uuid === cveFixtures.secretariatOrg.UUID) {
      return cveFixtures.secretariatOrg
    }
    return null
  }

  async getOrgUUID (shortName) {
    if (shortName === cveFixtures.regularOrg.short_name) {
      return cveFixtures.regularOrg.UUID
    }
    return null
  }
}

class MyUser {
  async getUserUUID () {
    return null
  }
}

class MyCveIdNegativeTests {
  async findOneByCveId () {
    return null
  }

  async updateByCveId () {
    return null
  }
}

class MyCveNegativeTests {
  async findOneByCveId () {
    return null
  }

  async updateByCveId () {
    return null
  }
}

class MyCveIdPositiveTests {
  async findOneByCveId () {
    return cveFixtures.cveToReject
  }

  async updateByCveId () {
    return cveFixtures.cveToReject
  }
}

class MyCvePositiveTests {
  async findOneByCveId () {
    return null
  }

  async updateByCveId () {
    return cveFixtures.cveToReject
  }
}

app.route('/cve-reject-negative-tests/:id')
  .post((req, res, next) => {
    const factory = {
      getCveIdRepository: () => { return new MyCveIdNegativeTests() },
      getCveRepository: () => { return new MyCveNegativeTests() },
      getOrgRepository: () => { return new MyOrg() },
      getUserRepository: () => { return new MyUser() }
    }
    req.ctx.repositories = factory
    next()
  }, cveMiddleware.parsePostParams, cveController.CVE_REJECT_RECORD)

app.route('/cve-reject-positive-tests/:id')
  .post((req, res, next) => {
    const factory = {
      getCveIdRepository: () => { return new MyCveIdPositiveTests() },
      getCveRepository: () => { return new MyCvePositiveTests() },
      getOrgRepository: () => { return new MyOrg() },
      getUserRepository: () => { return new MyUser() }
    }
    req.ctx.repositories = factory
    next()
  }, cveMiddleware.parsePostParams, cveController.CVE_REJECT_RECORD)

describe('Testing the POST /cve/:id/reject endpoint in Cve Controller', () => {
  context('Negative Tests', () => {
    it('Submit a reject request for record that dne, returns 400', (done) => {
      chai.request(app)
        .post(`/cve-reject-negative-tests/${nonExistentId}`)
        .set(cveFixtures.secretariatHeader)
        .send(rejectedBody)
        .end((err, res) => {
          if (err) {
            done(err)
          }

          expect(res).to.have.status(400)
          expect(res).to.have.property('body').and.to.be.a('object')
          const errObj = error.cveDne()
          expect(res.body.error).to.equal(errObj.error)
          expect(res.body.message).to.equal(errObj.message)
          done()
        })
    })
  })

  context('Positive Tests', () => {
    it('Reject record as secretariat', (done) => {
      chai.request(app)
        .post(`/cve-reject-positive-tests/${cveIdReserved}`)
        .set(cveFixtures.secretariatHeader)
        .send(rejectedBody)
        .end((err, res) => {
          if (err) {
            done(err)
          }
          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          done()
        })
    })

    it('Reject record as user', (done) => {
      const headers = Object.assign({}, cveFixtures.secretariatHeader)
      headers['CVE-API-ORG'] = cveFixtures.regularOrg.short_name
      headers['CVE-API-USER'] = cveFixtures.regularUser.username
      chai.request(app)
        .post(`/cve-reject-positive-tests/${cveIdReserved}`)
        .set(headers)
        .send(rejectedBody)
        .end((err, res) => {
          if (err) {
            done(err)
          }
          expect(res).to.have.status(200)
          expect(res).to.have.property('body').and.to.be.a('object')
          done()
        })
    })
  })
})


text:
/* eslint-disable no-unused-expressions */
// https://github.com/standard/standard/issues/690#issuecomment-278533482
const chai = require('chai')
const expect = chai.expect

const cveMiddleware = require('../../../src/controller/cve.controller/cve.middleware')
const rejectedBody = require('../../../test-http/src/test/cve_tests/cve_record_fixtures/rejectBody.json')
const multipleEngDescriptions = require('../../../test-http/src/test/cve_tests/cve_record_fixtures/rejectBodyMultipleSameEngValues.json')

describe('Testing the uniqueEnglishDescription middleware', () => {
  context('Negative Tests', () => {
    it('Submit a reject request with multiple English descriptions', () => {
      const result = cveMiddleware.hasSingleEnglishEntry(multipleEngDescriptions.cnaContainer.rejectedReasons)
      expect(result).to.be.false
    })
  })

  context('Positive Tests', () => {
    it('Submit a reject request with single English descriptions', () => {
      const result = cveMiddleware.hasSingleEnglishEntry(rejectedBody.cnaContainer.rejectedReasons)
      expect(result).to.be.true
    })
  })
})


text:
const chai = require('chai')
const expect = chai.expect
const _ = require('lodash')
const cveRecordPublished = require('../../schemas/5.0/CVE-2017-4024_published.json')

const Cve = require('../../../src/model/cve')
const cveCopy = _.cloneDeep(cveRecordPublished)

describe('Testing validating CVE record that has an ADP container', () => {
  it('Should return TRUE for valid Cve record ADP container', () => {
    const validationObj = Cve.validateCveRecord(cveCopy)
    expect(validationObj.isValid).to.be.equal(true)
  })

  it('Should return FALSE for Cve record with invalid ADP container', () => {
    // providerMetadata is a required adpContainer field, so validation will fail
    delete cveCopy.containers.adp[0].providerMetadata

    const validationObj = Cve.validateCveRecord(cveCopy)
    expect(validationObj.isValid).to.be.equal(false)
  })
})