summaryrefslogblamecommitdiffstats
path: root/server/api/configloader.js
blob: 24226938880a2bb29cc781f3c365aaddb0369867 (plain) (tree)
1
2
3
4
5
6
7
8





                                                         
                                                                                           
                                          


                                             
                                                                                    
                          

                                              
                                                        






                                                                                                    







                                                            


                                                  
                                                      

























                                                                   
       
            
                                             



                                                                    
 



























                                                                                               
                                                           









                                                                
                                
                                                                                                                                    
                                                         












                                                          
                                                                                               











                                                                                                  
                                                 





                        




                                                                       
                         

                              
                                                                   




                                              
 


                                                


                                                                                                                    


                                                      
                        
 


                 
 
                                          
/* global __appdir */
const path = require('path')
var db = require(path.join(__appdir, 'lib', 'sequelize'))
var express = require('express')
var noAuthRouter = express.Router()

// if client in db -> load script (default if none is found), else load registration script
noAuthRouter.get('/:uuid', (req, res) => {
  const uuid = req.params.uuid
  res.setHeader('content-type', 'text/plain')

  db.client.findOne({ where: { uuid: uuid }, include: ['groups'] }).then(client => {
    if (client !== null) {
      // Check for registration hooks.
      if (client.registrationState !== null) {
        // client is in registration state, load scripts
        db.registrationhook.findOne({ where: { id: client.registrationState } }).then(hook => {
          if (hook.type === 'IPXE') res.send(hook.script)
          else if (hook.type === 'BASH') res.sendFile(path.join(__appdir, 'ipxe', 'minilinux.ipxe'))
        })
        return
      }

      // client is in db
      if (client.configId !== null) {
        // client has a config
        createIpxeScript(client.configId).then(response => {
          res.send(response)
        })
        return
      }
      // client has no config, check parent groups
      var parentIds = []
      var configIds = []
      for (var i = 0; i < client.groups.length; i++) {
        // gather parent ids
        parentIds.push(client.groups[i].id)
      }
      if (parentIds.length !== 0) {
        // client has a parent to look for
        checkGroupsForConfigs(parentIds).then(response => {
          configIds = response
          if (configIds.length === 1) {
          // only one parent has a config, load it
            createIpxeScript(configIds[0]).then(response => {
              res.send(response)
            })
            return
          } else if (configIds.length > 1) {
          // multiple parents have a config, make dynamic menu
            createDynamicMenu(configIds).then(response => {
              res.send(response)
            })
            return
          }
          // no parent has a config, load default
          res.sendFile(path.join(__appdir, 'ipxe', 'default.ipxe'))
        })
      } else {
        // no config given, load default
        res.sendFile(path.join(__appdir, 'ipxe', 'default.ipxe'))
      }
    } else {
      // client not known, start registration
      res.sendFile(path.join(__appdir, 'ipxe', 'registration.ipxe'))
    }
  })
})

// load config by given id
noAuthRouter.get('/getconfig/:configId', (req, res) => {
  const configId = req.params.configId
  res.setHeader('content-type', 'text/plain')

  createIpxeScript(configId).then(response => {
    res.send(response)
  })
})

// recursive iteration through the layers of parents until a config is found or no parents left
function checkGroupsForConfigs (groupIds) {
  var parentIds = []
  var configIds = []
  if (groupIds.length === 0) {
    return configIds
  }
  return db.group.findAll({ where: { id: groupIds }, include: ['parents'] }).then(groups => {
    groups.forEach(group => {
      group.parents.forEach(parent => {
        if (!parentIds.includes(parent.id)) {
          parentIds.push(parent.id)
        }
      })
      if (group.configId !== null && !configIds.includes(group.configId)) {
        configIds.push(group.configId)
      }
    })
    if (configIds.length !== 0 || parentIds.length === 0) {
      return configIds
    } else {
      return checkGroupsForConfigs(parentIds).then(response => {
        return response
      })
    }
  })
}

// create the config script from database
function createIpxeScript (id) {
  return db.config.findOne({ where: { id: id }, include: ['entries'], order: [[['entries'], 'sortValue', 'ASC']] }).then(config => {
    if (config.script !== null && config.script !== '') {
      return config.script
    }
    var script = ''
    var menuscript = ''
    script += '#!ipxe\r\n\r\n'
    script += ':start\r\n'
    script += 'menu ' + config.name + '\r\n'
    config.entries.forEach(entry => {
      script += 'item'
      if (entry.config_x_entry.keyBind !== null) {
        script += ' --key ' + entry.config_x_entry.keyBind
      }
      script += ' menuentry' + entry.id + ' '
      if (entry.config_x_entry.customName !== null && entry.config_x_entry.customName !== '') {
        script += entry.config_x_entry.customName
      } else {
        script += entry.name
      }
      script += '\r\n'
      menuscript += ':' + 'menuentry' + entry.id + '\r\n'
      menuscript += entry.script + '\r\n\r\n'
    })
    script += 'choose '
    if (config.defaultEntry !== null && config.timeout !== null) {
      script += '--default menuentry' + config.defaultEntry + ' --timeout ' + config.timeout + ' '
    }
    script += `target && goto \${target}\r\n\r\n`
    script += menuscript

    return script
  })
}

// create dynamic menu to load the different given configs for a client
function createDynamicMenu (ids) {
  return db.config.findAll({ where: { id: ids } }).then(configs => {
    var script = ''
    var menuscript = ''
    var defaultentry = ''
    script += '#!ipxe\r\n\r\n'
    script += ':start\r\n'
    script += 'menu ' + 'Choose one configuration to boot' + '\r\n'
    configs.forEach(config => {
      script += 'item '
      script += ' menuentry' + config.id + ' '
      script += config.name
      script += '\r\n'

      // Last script processed is default script
      defaultentry = 'menuentry' + config.id

      menuscript += ':' + 'menuentry' + config.id + '\r\n'
      menuscript += 'chain ' + 'https://bas.stfu-kthx.net:8888/api/configloader/getconfig/' + config.id + '\r\n\r\n'
    })
    script += 'choose --default ' + defaultentry + ' '
    script += '--timeout 15 '
    script += `target && goto \${target}\r\n\r\n`
    script += menuscript

    return script
  })
}

module.exports.noAuthRouter = noAuthRouter