/* global __appdir */ const path = require('path') const ExternalBackends = require(path.join(__appdir, 'lib', 'external-backends')) const db = require(path.join(__appdir, 'lib', 'sequelize')) const log = require(path.join(__appdir, 'lib', 'log')) module.exports = { addClient, getDhcp, updateClient, deleteClients, uploadFiles } async function addClient (client) { // Get all backends and call addClient for each instance. const backends = await db.backend.findAll({ include: [{ association: 'mappedGroups', where: { id: client.parents }, required: false }] }) var result = [] for (let b in backends) { const backend = backends[b] const ba = new ExternalBackends() const instance = ba.getInstance(backend.type) var tmpClient = JSON.parse(JSON.stringify(client)) // Convert the parent group ids to the external backend parentIds. If multiple -> conflict if (client.parents) { const elements = backend.mappedGroups if (elements.length > 1) { // Conflict occured! const conflict = await db.conflict.create({ description: 'Multiple parents found' }) // Add backend to the conflict. conflict.createObject({ objectType: 'BACKEND', objectId: backend.id }) // Add the groups to the conflict. for (let element of elements) { conflict.createObject({ objectType: 'GROUP', objectId: element.id }) } } else if (elements.length === 1) tmpClient['parentId'] = elements[0].backend_x_group.externalId } let addClient = await instance.addClient(backend.credentials, tmpClient) addClient.backendId = backend.id if (addClient.succes) { // If the object was created we need to make the objectid / external id mapping. const clientDb = await db.client.findOne({ where: { id: client.id } }) backend.addMappedClients(clientDb, { through: { externalId: addClient.id, externalType: addClient.type } }) } if (addClient.error && addClient.error !== 'NOT_IMPLEMENTED_EXCEPTION') log({ category: 'ERROR_BACKEND', description: `[${addClient.backendId}] ${addClient.error}: ${addClient.message}`, clientId: client.id }) result.push(addClient) } return result } async function updateClient (client) { // Get all backends and call addClient for each instance. const backends = await db.backend.findAll({ include: [ { association: 'mappedGroups', where: { id: client.parents }, required: false }, { association: 'mappedClients', where: { id: client.id }, required: false } ] }) let result = [] for (let b in backends) { const backend = backends[b] const ba = new ExternalBackends() const instance = ba.getInstance(backend.type) var tmpClient = JSON.parse(JSON.stringify(client)) // Get the external clientid. const exid = backend.mappedClients[0] // If there is no external id, there is no client in the backend to update. if (exid) tmpClient.id = exid.backend_x_client.externalId else continue // Convert the parent group ids to the external backend parentIds. If multiple -> conflict if (client.parents) { const elements = backend.mappedGroups if (elements.length > 1) { // Conflict occured! const conflict = await db.conflict.create({ description: 'Multiple parents found' }) // Add backend to the conflict. conflict.createObject({ objectType: 'BACKEND', objectId: backend.id }) // Add the groups to the conflict. for (let element of elements) { conflict.createObject({ objectType: 'GROUP', objectId: element.id }) } } else if (elements.length === 1) tmpClient['parentId'] = elements[0].backend_x_group.externalId else if (elements.length === 0) tmpClient['parentId'] = null } try { let updateClient = await instance.updateClient(backend.credentials, tmpClient) updateClient.backendId = backend.id // If mappings is set the backend id to external id has to be updated. Mappings is a list of oldId, newId object pairs. if (updateClient.mappings) { for (let index in updateClient.mappings) { const mapping = updateClient.mappings[index] if (mapping.newId.Error) console.log(mapping.newId) else { const clientDb = await db.client.findOne({ where: { id: client.id } }) // Update the mapping. await backend.removeMappedClients(clientDb) let data = { externalId: mapping.newId } if (mapping.newType) data.externalType = mapping.newType await backend.addMappedClients(clientDb, { through: data }) } } } result.push(updateClient) } catch (error) { console.log(error) } } return result } async function deleteClients (clientids, backendIds) { // Get all backends and call deleteClient for each instance. const backends = await db.backend.findAll({ where: { id: { [db.Op.in]: backendIds }, '$clientMappings.clientid$': clientids }, include: ['clientMappings'] }) let deleteResponses = [] for (let backend of backends) { const ba = new ExternalBackends() const instance = ba.getInstance(backend.type) let objectsToDelete = backend.clientMappings.map(x => x.externalId) // If there are objects to delete -> delete them. if (objectsToDelete.length > 0) { let backendDeleteErrors = await instance.deleteObjects(backend.credentials, objectsToDelete) backendDeleteErrors = backendDeleteErrors.map(errors => ({ ...errors, backendId: backend.id, backendType: backend.type })) deleteResponses = [...deleteResponses, ...backendDeleteErrors] for (let err of backendDeleteErrors) { log({ category: `ERROR_BACKEND_${err.backendType.toUpperCase()}_OBJECT_DELETION`, description: `[${err.backendType}] Deletion of object ${err.id} (external backend id) in backend ${err.backendType} failed with error: \n ${err.message}` }) } } } return deleteResponses } async function uploadFiles (clientId, files) { const backends = await db.backend.findAll({ include: ['mappedClients'] }) let results = [] for (let b in backends) { const backend = backends[b] const ba = new ExternalBackends() const instance = ba.getInstance(backend.type) let exid = backend.mappedClients.find(y => y.id === parseInt(clientId)) if (exid) exid = exid.backend_x_client.externalId results.push(await instance.uploadFiles(backend.credentials, exid, files)) } return results } async function getDhcp () { const backends = await db.backend.findAll() let dhcp = false for (let b in backends) { const backend = backends[b] const ba = new ExternalBackends() const instance = ba.getInstance(backend.type) const isDHCP = await instance.isDhcp(backend.credentials) if (isDHCP) { // Check weather the backend is active let checkConnection try { checkConnection = await instance.checkConnection(backend.credentials) } catch (e) { continue } if (checkConnection.error) continue if (!dhcp) dhcp = { instance: instance, backend: backend } else { // Conflict occured! const conflict = await db.conflict.create({ description: 'Multiple active dhcp backends found' }) // Add both backends to the conflict. conflict.createObject({ objectType: 'BACKEND', objectId: backend.id }) conflict.createObject({ objectType: 'BACKEND', objectId: dhcp.backend.id }) return false } } } return dhcp }