From bb60a59b82f90f11837288fda4ee57d5664fd5b2 Mon Sep 17 00:00:00 2001 From: Udo Walter Date: Sun, 1 Dec 2019 18:24:39 +0000 Subject: [configloader] enabled new configloader --- server/api/configloader.js | 310 +-------------------------------------------- 1 file changed, 3 insertions(+), 307 deletions(-) (limited to 'server/api') diff --git a/server/api/configloader.js b/server/api/configloader.js index dc3a29d..699f16b 100644 --- a/server/api/configloader.js +++ b/server/api/configloader.js @@ -9,7 +9,7 @@ const url = config.https.host + ':' + config.https.port const configHelper = require(path.join(__appdir, 'lib', 'confighelper')) const log = require(path.join(__appdir, 'lib', 'log')) -noAuthRouter.getAsync(['/test/group/:id', '/test/group/'], async (req, res) => { +noAuthRouter.getAsync('/groups/:id', async (req, res) => { const list = req.query.list !== undefined && req.query.list !== 'false' const group = await db.group.findOne({ where: { id: req.params.id } }) const config = await configHelper.getGroupConfig(group, list) @@ -22,7 +22,7 @@ noAuthRouter.getAsync(['/test/group/:id', '/test/group/'], async (req, res) => { } }) -noAuthRouter.getAsync(['/test/:uuid', '/test/'], async (req, res) => { +noAuthRouter.getAsync(['/:uuid', '/'], async (req, res) => { const list = req.query.list !== undefined && req.query.list !== 'false' const client = await db.client.findOne({ where: { uuid: req.params.uuid } }) const config = await configHelper.getConfig(client, list) @@ -32,7 +32,7 @@ noAuthRouter.getAsync(['/test/:uuid', '/test/'], async (req, res) => { description: 'Client booted iPXE config [' + config.id + '] ' + config.name + '.\n' + 'Client UUID: ' + req.params.uuid + '\n' + 'Config ID: ' + config.id + '\n' + - 'Config Name: ' + config.name, + 'Config Name: ' + config.name } if (client) logEntry.clientId = client.id log(logEntry) @@ -43,308 +43,4 @@ noAuthRouter.getAsync(['/test/:uuid', '/test/'], async (req, res) => { } }) -// if client in db -> load script (default if none is found), else load registration script -noAuthRouter.getAsync('/:uuid', async (req, res) => { - const uuid = req.params.uuid - res.setHeader('content-type', 'text/plain') - - var client = await db.client.findOne({ where: { uuid: uuid }, include: ['groups', 'events'] }) - - // client not known, start registration - if (client === null) { - await sendFilePromise(res, path.join(__appdir, 'ipxe', 'registration.ipxe')) - return - } - - // Client is in db, check for registration hooks. - if (client.registrationState !== null) { - // client is in registration state, load scripts - var hook = await db.registrationhook.findOne({ where: { id: client.registrationState } }) - if (hook.type === 'IPXE') res.send(hook.script) - else if (hook.type === 'BASH') await sendFilePromise(res, path.join(__appdir, 'ipxe', 'minilinux.ipxe')) - return - } - - var events = [] - var blacklist = [] - var importantEvents = [] - var groupIds = [] - var result - - for (let i = 0; i < client.events.length; i++) { - var times = JSON.parse(client.events[i].times) - var intime = checkEventNow(times) - if (intime) { - if (client.events[i].client_x_event.blacklist) blacklist.push(client.events[i].id) - else if (client.events[i].important) importantEvents.push(client.events[i]) - else events.push(client.events[i]) - } - } - - importantEvents = importantEvents.filter(e => !blacklist.includes(e.id)) - importantEvents = importantEvents.map(e => e.configId) - importantEvents = importantEvents.filter(c => c !== null) - importantEvents = importantEvents.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) - if (importantEvents.length === 1) { - result = await createIpxeScript(importantEvents[0]) - res.send(result) - return - } - if (importantEvents.length > 1) { - result = await createDynamicMenu(importantEvents) - res.send(result) - return - } - - events = events.filter(e => !blacklist.includes(e.id)) - events = events.map(e => e.configId) - events = events.filter(c => c !== null) - events = events.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) - - groupIds = client.groups.map(x => x.id) - - var response = await fetchParentConfigs(groupIds, blacklist) - - if (response.ids.length > 0) { - // Check if there is an important event - if (response.type === 'important') { - if (response.ids.length === 1) return res.send(await createIpxeScript(response.ids[0])) - if (response.ids.length > 1) return res.send(await createDynamicMenu(response.ids)) - } - // No important event, use client event if existent - if (events.length === 1) return res.send(await createIpxeScript(events[0])) - if (events.length > 1) return res.send(await createDynamicMenu(events)) - - // No client event, use events of lowest parents - if (response.type === 'event') { - if (response.ids.length === 1) return res.send(await createIpxeScript(response.ids[0])) - if (response.ids.length > 1) return res.send(await createDynamicMenu(response.ids)) - } - - // No events, use client config - if (client.configId !== null) return res.send(await createIpxeScript(client.configId)) - - // No client config, use configs of lowest parents - if (response.type === 'config') { - if (response.ids.length === 1) return res.send(await createIpxeScript(response.ids[0])) - if (response.ids.length > 1) return res.send(await createDynamicMenu(response.ids)) - } - } else { - if (events.length === 1) return res.send(await createIpxeScript(events[0])) - if (events.length > 1) return res.send(await createDynamicMenu(events)) - - if (client.configId !== null) return res.send(await createIpxeScript(client.configId)) - } - // No config found, use default config - // await sendFilePromise(res, path.join(__appdir, 'ipxe', 'default.ipxe')) - res.send(configHelper.getDefaultConfig(client)) -}) - -// 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) - }) -}) - -function checkEventNow (times) { - var now = new Date() - var start = new Date(times.start) - var end = new Date(times.end) - if (!times.repetitive) { - if (start < now && now < end) return true - } - - if (times.repetitive) { - var startSplit = times.start.split(' ') - var startHourMinutes = startSplit[1].split(':').map(x => parseInt(x, 10)) - var endSplit = times.end.split(' ') - var endHourMinutes = endSplit[1].split(':').map(x => parseInt(x, 10)) - - var startAtDay = new Date() - var endAtDay = new Date() - var overnight = false - startAtDay.setHours(startHourMinutes[0], startHourMinutes[1], 0, 0) - endAtDay.setHours(endHourMinutes[0], endHourMinutes[1], 0, 0) - - if (endAtDay > now && startAtDay > now && endAtDay < startAtDay) { - var yesterday = new Date(now) - yesterday.setDate(yesterday.getDate() - 1) - if (checkEventInterval(start, yesterday, times.intervalType, times.interval)) { - startAtDay.setDate(startAtDay.getDate() - 1) - overnight = true - } else return false - } else if (endAtDay < now && startAtDay > now) endAtDay.setDate(endAtDay.getDate() + 1) - else if (endAtDay < now && startAtDay < now && endAtDay < startAtDay) endAtDay.setDate(endAtDay.getDate() + 1) - - if (!(times.monthMap[now.getMonth()] && (overnight ? times.dayMap[((yesterday.getDay() + 6) % 7)] : times.dayMap[((now.getDay() + 6) % 7)]) && start < now && now < end && startAtDay <= now && now < endAtDay)) return false - - return (overnight ? true : checkEventInterval(start, now, times.intervalType, times.interval)) - } - return false -} - -function dateDiffInDays (a, b) { - const utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate()) - const utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate()) - return Math.floor((utc2 - utc1) / (1000 * 3600 * 24)) -} - -function checkEventInterval (startDate, now, type, interval) { - if (type === 'day') { - let dateDiff = dateDiffInDays(startDate, now) - if (dateDiff % interval === 0) return true - } else if (type === 'week') { - var startDay = (startDate.getDay() + 6) % 7 - var nowDay = (now.getDay() + 6) % 7 - let diff = startDay - nowDay - var nowSameDayAsStart = new Date() - nowSameDayAsStart.setDate(nowSameDayAsStart.getDate() + diff) - let dateDiff = dateDiffInDays(startDate, nowSameDayAsStart) - if (dateDiff % (7 * interval) === 0) return true - } else if (type === 'month') { - if (startDate.getFullYear() !== now.getFullYear()) { - var monthDiff = (12 - startDate.getMonth()) + (12 * (now.getFullYear() - startDate.getFullYear() - 1)) + now.getMonth() - if (!(monthDiff % interval === 0)) return false - } else if (!((now.getMonth() - startDate.getMonth()) % interval === 0)) return false - startDate.setFullYear(now.getFullYear()) - startDate.setMonth(now.getMonth()) - if (startDate.getMonth() !== now.getMonth()) startDate.setDate(0) - if (startDate.getDate() === now.getDate()) return true - } -} - -async function fetchParentConfigs (groupIds, blacklist) { - if (groupIds.length === 0) return { 'ids': [], 'type': '' } - - var importantEvents = [] - var events = [] - var configs = [] - var parentIds = [] - var newBlacklist = blacklist.slice(0) - - var groups = await db.group.findAll({ where: { id: groupIds }, include: ['parents', 'events'] }) - for (let i = 0; i < groups.length; i++) { - configs.push(groups[i].configId) - // groups[i].map(g => g.parents.map(p => p.id)) - for (let j = 0; j < groups[i].parents.length; j++) { - parentIds.push(groups[i].parents[j].id) - } - for (let j = 0; j < groups[i].events.length; j++) { - var times = JSON.parse(groups[i].events[j].times) - var intime = checkEventNow(times) - if (intime) { - if (groups[i].events[j].group_x_event.blacklist) newBlacklist.push(groups[i].events[j].id) - else if (groups[i].events[j].important) importantEvents.push(groups[i].events[j]) - else events.push(groups[i].events[j]) - } - } - } - - importantEvents = importantEvents.filter(e => !newBlacklist.includes(e.id)) - importantEvents = importantEvents.map(e => e.configId) - importantEvents = importantEvents.filter(c => c !== null) - importantEvents = importantEvents.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) - if (importantEvents.length > 0) return { 'ids': importantEvents, 'type': 'important' } - - var response = await fetchParentConfigs(parentIds, newBlacklist) - - if (response.type === 'important') return response - - events = events.filter(e => !newBlacklist.includes(e.id)) - events = events.map(e => e.configId) - events = events.filter(c => c !== null) - events = events.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) - if (events.length > 0) return { 'ids': events, 'type': 'event' } - - if (response.type === 'event') return response - - configs = configs.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) - configs = configs.filter(c => c !== null) - if (configs.length > 0) return { 'ids': configs, 'type': 'config' } - - if (response.type === 'config') return response - - return { 'ids': [], 'type': '' } -} - -// 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://' + url + '/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 - }) -} - -function sendFilePromise (res, file) { - return new Promise((resolve, reject) => { - res.sendFile(file, {}, err => { - if (err) console.log(err) - resolve() - }) - }) -} - module.exports.noAuthRouter = noAuthRouter -- cgit v1.2.3-55-g7522