/* global __appdir */ var path = require('path') var db = require(path.join(__appdir, 'lib', 'sequelize')) var io = require(path.join(__appdir, 'lib', 'socketio')) const backendHelper = require(path.join(__appdir, 'lib', 'external-backends', 'backendhelper')) 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')) const groupHelper = require(path.join(__appdir, 'lib', 'grouphelper')) // Permission check middleware router.all(['', '/:id'], async (req, res, next) => { switch (req.method) { case 'GET': if (!await req.user.hasPermission('clients.view')) return res.status(403).send({ error: 'Missing permission', permission: 'clients.view' }) break case 'POST': case 'DELETE': if (!await req.user.hasPermission('clients.edit')) return res.status(403).send({ error: 'Missing permission', permission: 'clients.edit' }) break default: return res.status(400).send() } next() }) // ############################################################################ // ########################### GET requests ################################# router.getAsync('', async (req, res) => { const includePaths = req.query.path !== undefined && req.query.path !== 'false' const include = includePaths ? ['groups'] : [] let clients = await db.client.findAll({ order: [['name', 'ASC']], include }) if (includePaths) clients = await groupHelper.addPathsToClients(clients, false) res.send(clients) }) router.getAsync('/:id', async (req, res) => { if (!(req.params.id > 0)) return HttpResponse.invalidId().send(res) const client = await db.client.findOne({ where: { id: req.params.id }, include: ['groups', 'config'] }) if (client) res.status(200).send(client) 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 client to delete. if (req.body.ids.length > 1) { await log({ category: 'CLIENT_BATCH_DELETE', description: 'Batch deletion of ' + req.body.ids.length + ' clients initiated by user.', user, userId: req.user.id }) } // Delete objects from the selected external backends const deletedBackendObjects = await backendHelper.deleteClients(req.body.ids, req.body.backendIds) const externalDeletionErrors = deletedBackendObjects.filter(x => x.error !== undefined) let deletionCounter = 0 // Delete every client on its own, to get a better log for (let index in req.body.ids) { const client = await db.client.findOne({ where: { id: req.body.ids[index] } }) const count = await db.client.destroy({ where: { id: req.body.ids[index] } }) if (count !== 1) { await log({ category: 'ERROR_CLIENT_DELETE', description: 'Client could not be deleted.', client, user, userId: req.user.id }) } else { await log({ category: 'CLIENT_DELETE', description: 'Client successfully deleted.', client, user, userId: req.user.id }) deletionCounter++ } } if (req.body.ids.length > 1) { log({ category: 'CLIENT_BATCH_DELETE', description: deletionCounter + '/' + req.body.ids.length + ' clients successfully deleted.', user, userId: req.user.id }) } if (externalDeletionErrors.length <= 0) HttpResponse.successBatch('deleted', 'client', deletionCounter).send(res) else HttpResponse.warningBatch('deleted', 'client', deletionCounter, req.body.ids.length, externalDeletionErrors).send(res) } else { let client let action = 'updated' let backendClient = { id: req.params.id, name: req.body.data.name, type: 'CLIENT', uuid: req.body.data.uuid, parents: req.body.groupIds, networks: [ { ip: req.body.data.ip, mac: req.body.data.mac } ] } if (req.params.id === undefined) { client = await db.client.create(req.body.data) action = 'created' io.in('broadcast newClient').emit('notifications newAlert', { type: 'info', text: 'New client!' }) log({ category: 'CLIENT_CREATE', description: 'Client successfully created.', clientId: client.id, userId: req.user.id }) // Add client to the backends backendClient.id = client.id backendHelper.addClient(backendClient) } else if (req.params.id > 0) { client = await db.client.findOne({ where: { id: req.params.id } }) if (!client) return HttpResponse.notFound(req.params.id).send(res) else { await client.update(req.body.data) log({ category: 'CLIENT_EDIT', description: 'Client successfully edited.', clientId: client.id, userId: req.user.id }) } backendHelper.updateClient(backendClient) } else { return HttpResponse.invalidId().send(res) } await client.setGroups(req.body.groupIds) HttpResponse.success(action, 'client', client.id).send(res) } }) // ############################################################################ // ########################## DELETE requests ############################### router.deleteAsync('/:id', async (req, res) => { const client = db.client.findOne({ where: { id: req.params.id } }) const count = await db.client.destroy({ where: { id: req.params.id } }) if (count) { log({ category: 'CLIENT_DELETE', description: 'Client successfully deleted.', client, userId: req.user.id }) HttpResponse.success('deleted', 'client', req.params.id).send(res) } else HttpResponse.notFound(req.params.id).send(res) }) // ############################################################################ // ############################################################################ module.exports.router = router