/* global __appdir */ const path = require('path') const db = require(path.join(__appdir, 'lib', 'sequelize')) const groupUtil = require(path.join(__appdir, 'lib', 'grouputil')) 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')) // ############################################################################ // ########################### 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'] }) 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 groupUtil.getAllChildren([group]) }) else res.status(200).send(group) } else { return httpResponse.notFound(res, req.params.id) } } 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(res, true) } }) // ############################################################################ // ########################## 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(res, 'ids', 'an array') const count = await db.group.destroy({ where: { id: req.body.ids } }) httpResponse.successBatch(res, 'deleted', 'group', count) } 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(res, req.params.id) else await group.update(req.body.data) } else { return httpResponse.invalidId(res) } if (group) { 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(res, action, 'group', group.id) } } }) router.postAsync('/:id/subgroups', async (req, res) => { if (!(req.params.id > 0)) return httpResponse.invalidId(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(res, 'removed', 'subgroup', count) } else { const count = await group.addSubgroups(req.body.ids) httpResponse.successBatch(res, 'added', 'subgroup', count) } } else { httpResponse.notFound(res, req.params.id) } }) router.postAsync('/:id/clients', async (req, res) => { if (!(req.params.id > 0)) return httpResponse.invalidId(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.removeClients(req.body.ids) httpResponse.successBatch(res, 'removed', 'client', count) } else { const count = await group.addClients(req.body.ids) httpResponse.successBatch(res, 'added', 'client', count) } } else { httpResponse.notFound(res, req.params.id) } }) // ############################################################################ // ########################## DELETE requests ############################### router.delete('/:id', async (req, res) => { if (!(req.params.id > 0)) return httpResponse.invalidId(res) const count = await db.group.destroy({ where: { id: req.params.id } }) if (count) httpResponse.success(res, 'deleted', 'group', req.params.id) else httpResponse.notFound(res, req.params.id) }) // ############################################################################ // ############################################################################ module.exports.router = router