summaryrefslogblamecommitdiffstats
path: root/server/api/ipxeconfigs.js
blob: 6845952506456ce7668b4d9295f3ddc084afd983 (plain) (tree)
1
2
3
4
5
6
7
8
9

                          
                                    

                                                         
                                                   
                                          
                                                                        
                                                      
 

















                                                                                                                                                         


                                                                               










                                                                                                     
                               

  
                                             
                                                                     

                                                                                                          
                                                     

  
                                                     
                                                                     
                                          

                                 


                                                                                                         
                                                     

  
                                                    
                                                                     

                                                                                               
                                                     

  
                                                     
                                                                     

                                                                                                
                                                     

  

                                                                               
 
                                                    
                                                                       
                                                                                                       























































                                                                                                         
          
              


                                                    










                                                                                                     

                                   
                                                                        
                                                                        













                                                                                                      
            








                                                                                                                                         
     
                                                                   
   

  
                                                                               
                                                                               
 
                                                    

                                                                                                     


                                                                          
                                                                              











                                                                                                                      


                                                  

  
                                                     

                                                                                                     


                                                                          











                                                                                                                       



                                                                              

  


                                                                          
                                                                            


                                                                                






                                                                                                     





                                                                          
                                                                               

                                                                               
                                                
                                                                     
                                                                          
                                                                         














                                                                                                   

  


                                                                               
                              
/* global __appdir */
var path = require('path')
var Sequelize = require('sequelize')
var db = require(path.join(__appdir, 'lib', 'sequelize'))
var express = require('express')
const { decorateApp } = require('@awaitjs/express')
var router = decorateApp(express.Router())
const HttpResponse = require(path.join(__appdir, 'lib', 'httpresponse'))
const log = require(path.join(__appdir, 'lib', 'log'))

// Permission check middleware
router.all(['', '/:x'], async (req, res, next) => {
  switch (req.method) {
    case 'GET':
      if (!await req.user.hasPermission('ipxeconfigs.view')) return res.status(403).send({ error: 'Missing permission', permission: 'ipxeconfigs.view' })
      break

    case 'POST': case 'PUT': case 'DELETE':
      if (!await req.user.hasPermission('ipxeconfigs.edit')) return res.status(403).send({ error: 'Missing permission', permission: 'ipxeconfigs.edit' })
      break

    default:
      return res.status(400).send()
  }

  next()
})

// ############################################################################
// ###########################  GET requests  #################################

router.getAsync('', async (req, res) => {
  const configs = await db.config.findAll({
    include: [{ association: 'groups', attributes: [] }, { association: 'clients', attributes: [] }],
    attributes: {
      include: [
        [Sequelize.fn('COUNT', Sequelize.col('groups.id')), 'groupCount'],
        [Sequelize.fn('COUNT', Sequelize.col('clients.id')), 'clientCount']
      ]
    },
    group: ['id']
  })
  res.status(200).send(configs)
})

router.getAsync('/:id', async (req, res) => {
  if (!(req.params.id > 0)) return HttpResponse.invalidId().send(res)
  const config = await db.config.findOne({ where: { id: req.params.id }, include: ['groups', 'clients'] })
  if (config) res.status(200).send(config)
  else HttpResponse.notFound(req.params.id).send(res)
})

router.getAsync('/:id/entries', async (req, res) => {
  if (!(req.params.id > 0)) return HttpResponse.invalidId().send(res)
  const config = await db.config.findOne({
    where: { id: req.params.id },
    include: ['entries'],
    order: [[db.config.associations.entries, db.config.associations.entries.through, 'sortValue', 'ASC']]
  })
  if (config) res.status(200).send(config.entries)
  else HttpResponse.notFound(req.params.id).send(res)
})

router.getAsync('/:id/groups', async (req, res) => {
  if (!(req.params.id > 0)) return HttpResponse.invalidId().send(res)
  const config = await db.config.findOne({ where: { id: req.params.id }, include: ['groups'] })
  if (config) res.status(200).send(config.groups)
  else HttpResponse.notFound(req.params.id).send(res)
})

router.getAsync('/:id/clients', async (req, res) => {
  if (!(req.params.id > 0)) return HttpResponse.invalidId().send(res)
  const config = await db.config.findOne({ where: { id: req.params.id }, include: ['clients'] })
  if (config) res.status(200).send(config.clients)
  else HttpResponse.notFound(req.params.id).send(res)
})

// ############################################################################
// ##########################  POST requests  #################################

router.postAsync(['', '/:id'], async (req, res) => {
  if (req.query.delete !== undefined && req.query.delete !== 'false') {
    if (!Array.isArray(req.body.ids)) return HttpResponse.invalidBodyValue('ids', 'an array').send(res)

    const user = await db.user.findOne({ where: { id: req.user.id } })
    // Only need to log batch request if there is more than one ipxeconfig to delete.
    if (req.body.ids.length > 1) {
      await log({
        category: 'IPXECONFIG_BATCH_DELETE',
        description: 'Batch deletion of ' + req.body.ids.length + ' ipxe configs initiated by user.',
        user,
        userId: req.user.id
      })
    }

    let deletionCounter = 0
    // Delete every config on its own, to get a better log
    for (let index in req.body.ids) {
      const config = await db.config.findOne({ where: { id: req.body.ids[index] } })
      const count = await db.config.destroy({ where: { id: req.body.ids[index] } })
      if (count !== 1) {
        await log({
          category: 'ERROR_IPXECONFIG_DELETE',
          description: '[' + config.id + '] ' + config.name + ': Ipxe config could not be deleted.\n' +
                       'ID: ' + config.id + '\n' +
                       'Name: ' + config.name + '\n' +
                       'Description: ' + config.description + '\n' +
                       'Default Entry: ' + config.defaultEntry + '\n' +
                       'Timeout: ' + config.timeout + '\n' +
                       'Default Config: ' + config.isDefault,
          user,
          userId: req.user.id
        })
      } else {
        await log({
          category: 'IPXECONFIG_DELETE',
          description: '[' + config.id + '] ' + config.name + ': Ipxe config successfully deleted.\n' +
                       'ID: ' + config.id + '\n' +
                       'Name: ' + config.name + '\n' +
                       'Description: ' + config.description + '\n' +
                       'Default Entry: ' + config.defaultEntry + '\n' +
                       'Timeout: ' + config.timeout + '\n' +
                       'Default Config: ' + config.isDefault,
          user,
          userId: req.user.id
        })
        deletionCounter++
      }
    }
    if (req.body.ids.length > 1) {
      log({
        category: 'IPXECONFIG_BATCH_DELETE',
        description: deletionCounter + '/' + req.body.ids.length + ' ipxe configs successfully deleted.',
        user,
        userId: req.user.id
      })
    }

    HttpResponse.successBatch('deleted', 'ipxe config', deletionCounter).send(res)
  } else {
    let config
    let action = 'updated'
    if (req.params.id === undefined) {
      config = await db.config.create(req.body.data)
      log({
        category: 'IPXECONFIG_CREATE',
        description: '[' + config.id + '] ' + config.name + ': Ipxe config successfully created.\n' +
                     'ID: ' + config.id + '\n' +
                     'Name: ' + config.name + '\n' +
                     'Description: ' + config.description + '\n' +
                     'Default Entry: ' + config.defaultEntry + '\n' +
                     'Timeout: ' + config.timeout + '\n' +
                     'Default Config: ' + config.isDefault,
        userId: req.user.id
      })
      action = 'created'
    } else if (req.params.id > 0) {
      config = await db.config.findOne({ where: { id: req.params.id } })
      if (!config) return HttpResponse.notFound(req.params.id).send(res)
      else {
        await config.update(req.body.data)
        log({
          category: 'IPXECONFIG_EDIT',
          description: '[' + config.id + '] ' + config.name + ': Ipxe config successfully edited.\n' +
                       'ID: ' + config.id + '\n' +
                       'Name: ' + config.name + '\n' +
                       'Description: ' + config.description + '\n' +
                       'Default Entry: ' + config.defaultEntry + '\n' +
                       'Timeout: ' + config.timeout + '\n' +
                       'Default Config: ' + config.isDefault,
          userId: req.user.id
        })
      }
    } else {
      return HttpResponse.invalidId().send(res)
    }
    await config.setEntries([])
    if (req.body.entries.length > 0) {
      const promises = []
      req.body.entries.forEach((entry, index) => {
        promises.push(config.addEntry(entry.id, { through: { sortValue: index, customName: entry.customName, keyBind: entry.keyBind } }))
      })
      await Promise.all(promises)
    }
    HttpResponse.success(action, 'ipxe entry', config.id).send(res)
  }
})

// ############################################################################
// ###########################  PUT requests  #################################

router.putAsync('/:id/groups', async (req, res) => {
  if (!(req.params.id > 0)) return HttpResponse.invalidId().send(res)
  if (!Array.isArray(req.body.ids)) return HttpResponse.invalidBodyValue('ids', 'an array').send(res)
  const config = await db.config.findOne({ where: { id: req.params.id } })
  if (config) {
    await config.setGroups(req.body.ids)
    HttpResponse.success('set', 'clients of ipxe config', config.id).send(res)
    log({
      category: 'IPXECONFIG_SET_GROUPS',
      description: '[' + config.id + '] ' + config.name + ': ' + req.body.ids.length + ' groups successfully set.\n' +
                   'ID: ' + config.id + '\n' +
                   'Name: ' + config.name + '\n' +
                   'Description: ' + config.description + '\n' +
                   'Default Entry: ' + config.defaultEntry + '\n' +
                   'Timeout: ' + config.timeout + '\n' +
                   'Default Config: ' + config.isDefault + '\n' +
                   'Groups: ' + req.body.ids,
      userId: req.user.id
    })
  } else {
    HttpResponse.notFound(req.params.id).send(res)
  }
})

router.putAsync('/:id/clients', async (req, res) => {
  if (!(req.params.id > 0)) return HttpResponse.invalidId().send(res)
  if (!Array.isArray(req.body.ids)) return HttpResponse.invalidBodyValue('ids', 'an array').send(res)
  const config = await db.config.findOne({ where: { id: req.params.id } })
  if (config) {
    await config.setClients(req.body.ids)
    log({
      category: 'IPXECONFIG_SET_CLIENTS',
      description: '[' + config.id + '] ' + config.name + ': ' + req.body.ids.length + ' clients successfully set.\n' +
                   'ID: ' + config.id + '\n' +
                   'Name: ' + config.name + '\n' +
                   'Description: ' + config.description + '\n' +
                   'Default Entry: ' + config.defaultEntry + '\n' +
                   'Timeout: ' + config.timeout + '\n' +
                   'Default Config: ' + config.isDefault + '\n' +
                   'Clients: ' + req.body.ids,
      userId: req.user.id
    })
    HttpResponse.success('set', 'clients of ipxe config', config.id).send(res)
  } else {
    HttpResponse.notFound(req.params.id).send(res)
  }
})

router.putAsync('/:id/default', async (req, res) => {
  if (!(req.params.id > 0)) return HttpResponse.invalidId().send(res)
  const config = await db.config.findOne({ where: { id: req.params.id } })
  const oldDefault = await db.config.findOne({ where: { isDefault: true } })
  if (config) {
    await db.config.update({ isDefault: false }, { where: { isDefault: true } })
    await config.update({ isDefault: true })
    log({
      category: 'IPXECONFIG_SET_DEFAULT',
      description: '[' + config.id + '] ' + config.name + ': Config successfully set as default.\n' +
                   'Old Default: [' + oldDefault.id + '] ' + oldDefault.name + '\n' +
                   'New Default: [' + config.id + '] ' + config.name,
      userId: req.user.id
    })
    HttpResponse.success('set as default:', 'config', config.id).send(res)
  } else {
    HttpResponse.notFound(req.params.id).send(res)
  }
})

// ############################################################################
// ##########################  DELETE requests  ###############################

router.deleteAsync('/:id', async (req, res) => {
  if (!(req.params.id > 0)) return HttpResponse.invalidId().send(res)
  const config = await db.config.findOne({ where: { id: req.params.id } })
  const count = await db.config.destroy({ where: { id: req.params.id } })

  if (count) {
    log({
      category: 'IPXECONFIG_DELETE',
      description: '[' + config.id + '] ' + config.name + ': Ipxe config successfully deleted.\n' +
                   'ID: ' + config.id + '\n' +
                   'Name: ' + config.name + '\n' +
                   'Description: ' + config.description + '\n' +
                   'Default Entry: ' + config.defaultEntry + '\n' +
                   'Timeout: ' + config.timeout + '\n' +
                   'Default Config: ' + config.isDefault,
      userId: req.user.id
    })
    HttpResponse.success('deleted', 'config', req.params.id).send(res)
  } else HttpResponse.notFound(req.params.id).send(res)
})

// ############################################################################
// ############################################################################

module.exports.router = router