summaryrefslogblamecommitdiffstats
path: root/server/lib/external-backends/backendhelper.js
blob: e63f37f3984d6e279e60d2f4dc3ee59c751e5bb4 (plain) (tree)
1
2
3
4
5
6
7
8
9
10


                                                                                 

                                                           
 
                                                                                 


                                                           
                                                                                                                                           

                 

                               





                                                                                              
                                           










                                                                                            



                                                                                             
     

                                                                            
 




                                                                                                                 
     
 
                                                                                                                                                                                                                     






                                                           





                                                                                      








                                                      
                                         
                                                                               
                                                             
                 


                                                                                              
                                           










                                                                                            



                                                                                             
     
 


















                                                                                                                             
 



                               
   


               
                                                      
                                                              






                                             
 


                                 

                                                 

                                                                       
                                                     






                                                                                                                                
                                                                     





                                                                                                                                                                   
 
 












                                                                              
 











                                                             
                                            





                                                                             

                                         


                                                                
                                                                                                         









                                                                                   
/* 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 })
        }
      }

      // Nevertheless use the first one as "primary" parent
      if (elements.length > 0) 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 })
        }
      }

      // Use first parent as parent
      if (elements.length > 1) tmpClient['parentId'] = elements[0].backend_x_group.externalId
    }

    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()}`,
          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
}