summaryrefslogtreecommitdiffstats
path: root/modules-available/serversetup-bwlp/page.inc.php
diff options
context:
space:
mode:
authorSimon Rettberg2018-06-12 17:15:44 +0200
committerSimon Rettberg2018-06-12 17:15:44 +0200
commit2e78eec281815d6ba42ff2cf7c3a937abe6d83c5 (patch)
treed98495500354de9b735b31c64e02856eeb179098 /modules-available/serversetup-bwlp/page.inc.php
parent[inc/Database] Method to return single-column queries as array (diff)
downloadslx-admin-2e78eec281815d6ba42ff2cf7c3a937abe6d83c5.tar.gz
slx-admin-2e78eec281815d6ba42ff2cf7c3a937abe6d83c5.tar.xz
slx-admin-2e78eec281815d6ba42ff2cf7c3a937abe6d83c5.zip
[serversetup-bwlp] Start rewrite as purely iPXE-based
Diffstat (limited to 'modules-available/serversetup-bwlp/page.inc.php')
-rw-r--r--modules-available/serversetup-bwlp/page.inc.php300
1 files changed, 281 insertions, 19 deletions
diff --git a/modules-available/serversetup-bwlp/page.inc.php b/modules-available/serversetup-bwlp/page.inc.php
index 52b3afe4..4207bd53 100644
--- a/modules-available/serversetup-bwlp/page.inc.php
+++ b/modules-available/serversetup-bwlp/page.inc.php
@@ -17,6 +17,12 @@ class Page_ServerSetup extends Page
Util::redirect('?do=Main');
}
+ if (Request::any('bla') == 'blu') {
+ IPxe::importLegacyMenu();
+ IPxe::importPxeMenus('/srv/openslx/tftp/pxelinux.cfg');
+ die('DONE');
+ }
+
if (Request::any('action') === 'getimage') {
User::assertPermission("download");
$this->handleGetImage();
@@ -44,16 +50,45 @@ class Page_ServerSetup extends Page
$this->updatePxeMenu();
}
+ if ($action === 'savebootentry') {
+ User::assertPermission('ipxe.bootentry.edit');
+ $this->saveBootEntry();
+ }
+
+ if ($action === 'savemenu') {
+ User::assertPermission('ipxe.menu.edit');
+ $this->saveMenu();
+ }
+
if (Request::isPost()) {
Util::redirect('?do=serversetup');
}
User::assertPermission('access-page');
+
+ if (User::hasPermission('ipxe.*')) {
+ Dashboard::addSubmenu('?do=serversetup&show=menu', Dictionary::translate('submenu_menu', true));
+ }
+ if (User::hasPermission('edit.address')) {
+ Dashboard::addSubmenu('?do=serversetup&show=address', Dictionary::translate('submenu_address', true));
+ }
+ if (User::hasPermission('download')) {
+ Dashboard::addSubmenu('?do=serversetup&show=download', Dictionary::translate('submenu_download', true));
+ }
+ if (Request::get('show') === false) {
+ $subs = Dashboard::getSubmenus();
+ if (empty($subs)) {
+ User::assertPermission('download');
+ } else {
+ Util::redirect($subs[0]['url']);
+ }
+ }
}
protected function doRender()
{
Render::addTemplate("heading");
+
$task = Property::get('ipxe-task-id');
if ($task !== false) {
$task = Taskmanager::status($task);
@@ -65,32 +100,143 @@ class Page_ServerSetup extends Page
Render::addTemplate('ipxe_update', array('taskid' => $task['id']));
}
- Permission::addGlobalTags($perms, null, ['edit.menu', 'edit.address', 'download']);
+ switch (Request::get('show')) {
+ case 'editbootentry':
+ User::assertPermission('ipxe.bootentry.edit');
+ $this->showEditBootEntry();
+ break;
+ case 'editmenu':
+ User::assertPermission('ipxe.menu.view');
+ $this->showEditMenu();
+ break;
+ case 'download':
+ User::assertPermission('download');
+ $this->showDownload();
+ break;
+ case 'menu':
+ User::assertPermission('ipxe.menu.view');
+ $this->showMenuList();
+ break;
+ default:
+ Util::redirect('?do=serversetup');
+ break;
+ }
+ }
+
+ private function showDownload()
+ {
+ // TODO: Make nicer, support more variants (taskmanager-plugin)
+ Render::addTemplate('download');
+ }
+
+ private function showMenuList()
+ {
+ $allowedEdit = User::getAllowedLocations('ipxe.menu.edit');
+
+ // TODO Permission::addGlobalTags($perms, null, ['edit.menu', 'edit.address', 'download']);
+
+ $res = Database::simpleQuery("SELECT m.menuid, m.title, m.isdefault, GROUP_CONCAT(l.locationid) AS locations
+ FROM serversetup_menu m LEFT JOIN serversetup_menu_location l USING (menuid) GROUP BY menuid ORDER BY title");
+ $table = [];
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ if (empty($row['locations'])) {
+ $locations = [];
+ $row['allowEdit'] = in_array(0, $allowedEdit);
+ } else {
+ $locations = explode(',', $row['locations']);
+ $row['allowEdit'] = empty(array_diff($locations, $allowedEdit));
+ }
+ $row['locationCount'] = empty($locations) ? '' : count($locations);
+ $table[] = $row;
+ }
- Render::addTemplate('ipaddress', array(
- 'ips' => $this->taskStatus['data']['addresses'],
- 'chooseHintClass' => $this->hasIpSet ? '' : 'alert alert-danger',
- 'editAllowed' => User::hasPermission("edit.address"),
- 'perms' => $perms,
+ Render::addTemplate('menu-list', array(
+ 'table' => $table,
));
- $data = $this->currentMenu;
- if (!User::hasPermission('edit.menu')) {
- unset($data['masterpasswordclear']);
+ }
+
+ private function hasMenuPermission($menuid, $permission)
+ {
+ $allowedEditLocations = User::getAllowedLocations($permission);
+ $allowEdit = in_array(0, $allowedEditLocations);
+ if (!$allowEdit) {
+ // Get locations
+ $locations = Database::queryColumnArray('SELECT locationid FROM serversetup_menu_location
+ WHERE menuid = :menuid', compact('menuid'));
+ if (!empty($locations)) {
+ $allowEdit = count(array_diff($locations, $allowedEditLocations)) === 0;
+ }
}
- if (!isset($data['defaultentry'])) {
- $data['defaultentry'] = 'net';
+ return $allowEdit;
+ }
+
+ private function showEditMenu()
+ {
+ $id = Request::get('id', false, 'int');
+ $menu = Database::queryFirst("SELECT menuid, timeoutms, title, defaultentryid, isdefault
+ FROM serversetup_menu WHERE menuid = :id", compact('id'));
+ if ($menu === false) {
+ Message::addError('invalid-menu-id', $id);
+ Util::redirect('?do=serversetup&show=menu');
}
- if ($data['defaultentry'] === 'net') {
- $data['active-net'] = 'checked';
+ if (!$this->hasMenuPermission($id, 'ipxe.menu.edit')) {
+ $menu['readonly'] = 'readonly';
+ $menu['disabled'] = 'disabled';
+ $menu['plainpass'] = '';
}
- if ($data['defaultentry'] === 'hdd') {
- $data['active-hdd'] = 'checked';
+ $menu['timeout'] = round($menu['timeoutms'] / 1000);
+ $menu['entries'] = Database::queryAll("SELECT menuentryid, entryid, hotkey, title, hidden, sortval, plainpass FROM
+ serversetup_menuentry WHERE menuid = :id", compact('id'));
+ $keyList = array_map(function ($item) { return ['key' => $item]; }, MenuEntry::getKeyList());
+ $entryList = Database::queryAll("SELECT entryid, title, hotkey FROM serversetup_bootentry ORDER BY title ASC");
+ foreach ($menu['entries'] as &$entry) {
+ $entry['isdefault'] = ($entry['menuentryid'] == $menu['defaultentryid']);
+ $entry['keys'] = $keyList;
+ foreach ($entry['keys'] as &$key) {
+ if ($key['key'] === $entry['hotkey']) {
+ $key['selected'] = 'selected'; // TODO: plainpass only when permissions
+ }
+ }
+ $entry['entrylist'] = $entryList;
+ foreach ($entry['entrylist'] as &$item) {
+ if ($item['entryid'] == $entry['entryid']) {
+ $item['selected'] = 'selected';
+ }
+ if (empty($item['title'])) {
+ $item['title'] = $item['entryid'];
+ }
+ }
}
- if ($data['defaultentry'] === 'custom') {
- $data['active-custom'] = 'checked';
+ // TODO: Make assigned locations editable
+ Permission::addGlobalTags($menu['perms'], 0, ['ipxe.menu.edit']);
+ Render::addTemplate('menu-edit', $menu);
+ }
+
+ private function showEditBootEntry()
+ {
+ $params = [];
+ $id = Request::get('id', false, 'string');
+ if ($id === false) {
+ $params['exec_checked'] = 'checked';
+ $params['entryid'] = 'u-' . dechex(mt_rand(0x1000, 0xffff)) . '-' . dechex(time());
+ } else {
+ // Query existing entry
+ $row = Database::queryFirst('SELECT entryid, title, builtin, data FROM serversetup_bootentry
+ WHERE entryid = :id LIMIT 1', ['id' => $id]);
+ if ($row === false) {
+ Message::addError('invalid-boot-entry', $id);
+ Util::redirect('?do=serversetup');
+ }
+ $entry = BootEntry::fromJson($row['data']);
+ if ($entry === null) {
+ Message::addError('unknown-boot-entry-type', $id);
+ Util::redirect('?do=serversetup');
+ }
+ $entry->addFormFields($params);
+ $params['title'] = $row['title'];
+ $params['oldentryid'] = $params['entryid'] = $row['entryid'];
}
- $data['perms'] = $perms;
- Render::addTemplate('ipxe', $data);
+ Render::addTemplate('ipxe-new-boot-entry', $params);
}
// -----------------------------------------------------------------------------------------------
@@ -131,6 +277,76 @@ class Page_ServerSetup extends Page
return true;
}
+ private function saveMenu()
+ {
+ $id = Request::post('menuid', false, 'int');
+ if ($id === false) {
+ Message::addError('main.parameter-missing', 'menuid');
+ return;
+ }
+ $menu = Database::queryFirst("SELECT m.menuid, GROUP_CONCAT(l.locationid) AS locations
+ FROM serversetup_menu m
+ LEFT JOIN serversetup_menu_location l USING (menuid)
+ WHERE menuid = :id", compact('id'));
+ if ($menu === false) {
+ Message::addError('no-such-menu', $id);
+ return;
+ }
+ if (!$this->hasMenuPermission($id, 'ipxe.menu.edit')) {
+ Message::addError('locations.no-permission-location', 'TODO');
+ return;
+ }
+ // TODO: Validate new locations to be saved (and actually save them)
+
+ Database::exec('UPDATE serversetup_menu SET title = :title, timeoutms = :timeoutms
+ WHERE menuid = :menuid', [
+ 'menuid' => $id,
+ 'title' => IPxe::sanitizeIpxeString(Request::post('title', '', 'string')),
+ 'timeoutms' => abs(Request::post('timeoutms', 0, 'int') * 1000),
+ ]);
+ if (User::hasPermission('ipxe.menu.edit', 0)) {
+ Database::exec('UPDATE serversetup_menu SET isdefault = (menuid = :menuid)', ['menuid' => $id]);
+ }
+
+ $keepIds = [];
+ $entries = Request::post('entry', false, 'array');
+ foreach ($entries as $key => $entry) {
+ $params = [
+ 'entryid' => $entry['entryid'], // TODO validate
+ 'hotkey' => MenuEntry::filterKeyName($entry['hotkey']),
+ 'title' => IPxe::sanitizeIpxeString($entry['title']),
+ 'hidden' => (int)$entry['hidden'],
+ 'sortval' => (int)$entry['sortval'],
+ 'plainpass' => $entry['plainpass'],
+ 'menuid' => $menu['menuid'],
+ ];
+ if (is_numeric($key)) {
+ $keepIds[] = $key;
+ $params['menuentryid'] = $key;
+ $params['md5pass'] = IPxe::makeMd5Pass($entry['plainpass'], $key);
+ $ret = Database::exec('UPDATE serversetup_menuentry
+ SET entryid = :entryid, hotkey = :hotkey, title = :title, hidden = :hidden, sortval = :sortval,
+ plainpass = :plainpass, md5pass = :md5pass
+ WHERE menuid = :menuid AND menuentryid = :menuentryid', $params, true);
+ } else {
+ $ret = Database::exec("INSERT INTO serversetup_menuentry
+ (menuid, entryid, hotkey, title, hidden, sortval, plainpass, md5pass)
+ VALUES (:menuid, :entryid, :hotkey, :title, :hidden, :sortval, :plainpass, '')", $params, true);
+ if ($ret && !empty($entry['plainpass'])) {
+ $key = Database::lastInsertId();
+ Database::exec('UPDATE serversetup_menuentry SET md5pass = :md5pass WHERE menuentryid = :id', [
+ 'md5pass' => IPxe::makeMd5Pass($entry['plainpass'], $key),
+ 'key' => $id,
+ ]);
+ }
+ }
+ if ($ret === false) {
+ Message::addWarning('error-saving-entry', $entry['title'], Database::lastError());
+ }
+ }
+ Message::addSuccess('menu-saved');
+ }
+
private function updateLocalAddress()
{
$newAddress = Request::post('ip', 'none');
@@ -184,4 +400,50 @@ class Page_ServerSetup extends Page
exit;
}
+ private function saveBootEntry()
+ {
+ $oldEntryId = Request::post('entryid', false, 'string');
+ $newId = Request::post('newid', false, 'string');
+ if (!preg_match('/^[a-z0-9\-_]{1,16}$/', $newId)) {
+ Message::addError('main.parameter-empty', 'newid');
+ return;
+ }
+ $data = Request::post('entry', false);
+ if (!is_array($data)) {
+ Message::addError('missing-entry-data');
+ return;
+ }
+ $type = Request::post('type', false, 'string');
+ if ($type === 'exec') {
+ $entry = BootEntry::newStandardBootEntry($data);
+ } elseif ($type === 'script') {
+ $entry = BootEntry::newCustomBootEntry($data);
+ } else {
+ Message::addError('unknown-entry-type', $type);
+ return;
+ }
+ if ($entry === null) {
+ Message::addError('main.empty-field');
+ return;
+ }
+ $params = [
+ 'entryid' => $newId,
+ 'title' => Request::post('title', '', 'string'),
+ 'data' => json_encode($entry->toArray()),
+ ];
+ // New or update?
+ if (empty($oldEntryId)) {
+ // New entry
+ Database::exec('INSERT INTO serversetup_bootentry (entryid, title, builtin, data)
+ VALUES (:entryid, :title, 0, :data)', $params);
+ Message::addSuccess('boot-entry-created', $newId);
+ } else {
+ // Edit existing entry
+ $params['oldid'] = $oldEntryId;
+ Database::exec('UPDATE serversetup_bootentry SET entryid = :entryid, title = :title, data = :data
+ WHERE entryid = :oldid AND builtin = 0', $params);
+ Message::addSuccess('boot-entry-updated', $newId);
+ }
+ }
+
}