summaryrefslogblamecommitdiffstats
path: root/server/api/groups.js
blob: 633b63d085754e0053df4f06132ff897a21e1fad (plain) (tree)
1
2
3
4
5
6
7
8
9
                     

                                                           
                                                                      
                                                                
                                  
                                                   
                                            
                                                                        
                                                                                               
 










                                                                               
                                                                                                                                            
                

                                              

                                                          
        
                                                                                                                    

                                      
                                                           
     
                                     




                                                                                             
          
                                          
   

  

                                                                               
 

                                                                       
                                                                                                       
                                                                         
                                                                  

             




                                                  
                                                                                             
                                                                       

                                            
                                               
     









                                                                                              
          













                                                                                        
         



                                                 
       
     
                               
                                                             
   
  
 
                                                        
                                                                     



                                                                         
                                                                       
            
                                                          
                                                                     
     
          
                                                  

   
 
                                                      
                                                                     

                                                                        
                      

                                                                         
                                                                     

                                                        
                                                                   






                                                                

          
                                                  

   
 

                                                                               
 
                                           
                                                                     
                                                                        

                                                                              
  
 

                                                                               
 
                              
/* global __appdir */
const path = require('path')
const db = require(path.join(__appdir, 'lib', 'sequelize'))
const groupHelper = require(path.join(__appdir, 'lib', 'grouphelper'))
const ipHelper = require(path.join(__appdir, 'lib', 'iphelper'))
const express = require('express')
const { decorateApp } = require('@awaitjs/express')
const router = decorateApp(express.Router())
const HttpResponse = require(path.join(__appdir, 'lib', 'httpresponse'))
const backendHelper = require(path.join(__appdir, 'lib', 'external-backends', 'backendhelper'))

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

router.getAsync('', async (req, res) => {
  const groups = await db.group.findAll({ order: [['name', 'ASC']] })
  res.send(groups)
})

router.getAsync('/:id', async (req, res) => {
  const all = req.query.all !== undefined && req.query.all !== 'false'
  if (req.params.id > 0) {
    let group = await db.group.findOne({ where: { id: req.params.id }, include: ['parents', 'ipranges', 'subgroups', 'clients', 'config'] })
    if (group) {
      // Convert ipranges in readable strings.
      group.ipranges.forEach(iprange => {
        iprange.startIp = ipHelper.toIPv4(iprange.startIp)
        iprange.endIp = ipHelper.toIPv4(iprange.endIp)
      })
      if (all) res.status(200).send({ ...group.get({ plain: true }), ...await groupHelper.getAllChildren([group]) })
      else res.status(200).send(group)
    } else {
      return HttpResponse.notFound(req.params.id).send(res)
    }
  } else if (req.params.id === '0') {
    const [subgroups, clients] = await Promise.all([
      db.group.findAll(all ? {} : { where: { '$parents.id$': null }, include: ['parents'] }),
      db.client.findAll(all ? {} : { where: { '$groups.id$': null }, include: ['groups'] })
    ])
    res.send({ id: 0, subgroups, clients })
  } else {
    HttpResponse.invalidId(true).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 count = await db.group.destroy({ where: { id: req.body.ids } })
    HttpResponse.successBatch('deleted', 'group', count).send(res)
  } else {
    let group
    let action = 'updated'
    if (req.params.id === undefined) {
      group = await db.group.create(req.body.data)
      action = 'created'
    } else if (req.params.id > 0) {
      group = await db.group.findOne({ where: { id: req.params.id }, include: ['ipranges'] })
      if (!group) return HttpResponse.notFound(req.params.id).send(res)
      else await group.update(req.body.data)
    } else {
      return HttpResponse.invalidId().send(res)
    }
    const promises = []
    // Set group parents
    if (Array.isArray(req.body.parentIds)) promises.push(group.setParents(req.body.parentIds))
    // Update, create or destroy ipranges
    if (Array.isArray(req.body.ipranges)) {
      // Get the ipranges of the group an create a id -> iprange map of them
      const iprangeIdMap = {}
      if (group.ipranges) {
        group.ipranges.forEach(iprange => {
          iprangeIdMap[iprange.id] = iprange
        })
      }
      // Update existing ipranges and create the new ones
      req.body.ipranges.forEach(iprange => {
        // Convert valid ip addresses to integer values.
        if (!ipHelper.isIPv4(iprange.startIp) || !ipHelper.isIPv4(iprange.endIp)) return
        iprange.startIp = ipHelper.toDecimal(iprange.startIp)
        iprange.endIp = ipHelper.toDecimal(iprange.endIp)
        if (iprange.id) {
          if (iprangeIdMap[iprange.id]) {
            promises.push(iprangeIdMap[iprange.id].update(iprange))
            delete iprangeIdMap[iprange.id]
          }
        } else {
          promises.push(group.createIprange(iprange))
        }
      })
      // Destroy the deleted ipranges
      for (let id in iprangeIdMap) {
        promises.push(iprangeIdMap[id].destroy())
      }
    }
    await Promise.all(promises)
    HttpResponse.success(action, 'group', group.id).send(res)
  }
})

router.postAsync('/:id/subgroups', async (req, res) => {
  if (!(req.params.id > 0)) return HttpResponse.invalidId().send(res)
  const group = await db.group.findOne({ where: { id: req.params.id } })
  if (group) {
    if (req.query.delete !== undefined && req.query.delete !== 'false') {
      const count = await group.removeSubgroups(req.body.ids)
      HttpResponse.successBatch('removed', 'subgroup', count).send(res)
    } else {
      const count = await group.addSubgroups(req.body.ids)
      HttpResponse.successBatch('added', 'subgroup', count).send(res)
    }
  } else {
    HttpResponse.notFound(req.params.id).send(res)
  }
})

router.postAsync('/:id/clients', async (req, res) => {
  if (!(req.params.id > 0)) return HttpResponse.invalidId().send(res)
  const group = await db.group.findOne({ where: { id: req.params.id } })
  if (group) {
    let groupid = null
    if (req.query.delete !== undefined && req.query.delete !== 'false') {
      const count = await group.removeClients(req.body.ids)
      HttpResponse.successBatch('removed', 'client', count).send(res)
    } else {
      const count = await group.addClients(req.body.ids)
      HttpResponse.successBatch('added', 'client', count).send(res)
      groupid = group.id
    }

    // Update each client backend
    for (let index in req.body.ids) {
      const id = req.body.ids[index]
      backendHelper.updateClient({ id: id, parents: [groupid] })
    }
  } else {
    HttpResponse.notFound(req.params.id).send(res)
  }
})

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

router.delete('/:id', async (req, res) => {
  if (!(req.params.id > 0)) return HttpResponse.invalidId().send(res)
  const count = await db.group.destroy({ where: { id: req.params.id } })
  if (count) HttpResponse.success('deleted', 'group', req.params.id).send(res)
  else HttpResponse.notFound(req.params.id).send(res)
})

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

module.exports.router = router