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