summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2014-05-20 19:20:02 +0200
committerSimon Rettberg2014-05-20 19:20:02 +0200
commit4a8725b8dcac3bd0e7afe463968d281e4cf8df6c (patch)
tree8d1374edd2a1e74ed3a99813210ca84e999fb82c
parentOO style modules (diff)
downloadslx-admin-4a8725b8dcac3bd0e7afe463968d281e4cf8df6c.tar.gz
slx-admin-4a8725b8dcac3bd0e7afe463968d281e4cf8df6c.tar.xz
slx-admin-4a8725b8dcac3bd0e7afe463968d281e4cf8df6c.zip
JS Stuff for Taskmanager interaction
More work on AD wizard
-rw-r--r--apis/taskmanager.inc.php22
-rw-r--r--inc/message.inc.php1
-rw-r--r--inc/render.inc.php8
-rw-r--r--inc/taskmanager.inc.php29
-rw-r--r--modules/sysconfig.inc.php31
-rw-r--r--modules/sysconfig/addmodule.inc.php16
-rw-r--r--modules/sysconfig/addmodule_ad.inc.php89
-rw-r--r--script/custom.js19
-rw-r--r--script/taskmanager.js141
-rw-r--r--templates/sysconfig/ad-checkconnection.html42
-rw-r--r--templates/sysconfig/ad-finish.html28
-rw-r--r--templates/sysconfig/ad-start.html1
12 files changed, 401 insertions, 26 deletions
diff --git a/apis/taskmanager.inc.php b/apis/taskmanager.inc.php
new file mode 100644
index 00000000..5994c018
--- /dev/null
+++ b/apis/taskmanager.inc.php
@@ -0,0 +1,22 @@
+<?php
+
+require_once 'inc/taskmanager.inc.php';
+
+if (!is_array($_POST['ids'])) {
+ die('{"error" : "No Task ids given in POST data."}');
+}
+
+$return = array();
+foreach ($_POST['ids'] as $id) {
+ $status = Taskmanager::status($id);
+ if ($status === false) {
+ $return[] = array('id' => $id, 'error' => 'No connection to TaskManager');
+ continue;
+ }
+ $return[] = $status;
+ if (!isset($status['statusCode']) || ($status['statusCode'] !== TASK_WAITING && $status['statusCode'] !== TASK_PROCESSING)) {
+ Taskmanager::release($id);
+ }
+}
+
+echo json_encode(array('tasks' => $return));
diff --git a/inc/message.inc.php b/inc/message.inc.php
index 6c95764c..8a3b5d4e 100644
--- a/inc/message.inc.php
+++ b/inc/message.inc.php
@@ -30,6 +30,7 @@ $error_text = array(
'error-extract' => 'Konnte Archiv nicht nach {{0}} entpacken - {{1}}',
'module-added' => 'Modul erfolgreich hinzugefügt',
'taskmanager-error' => 'Verbindung zum Taskmanager fehlgeschlagen',
+ 'taskmanager-format' => 'Taskmanager hat ungültige Daten zurückgeliefert',
'task-error' => 'Ausführung fehlgeschlagen: {{0}}',
);
diff --git a/inc/render.inc.php b/inc/render.inc.php
index dff32798..cf0958c2 100644
--- a/inc/render.inc.php
+++ b/inc/render.inc.php
@@ -45,12 +45,16 @@ class Render
<link href="style/bootstrap.min.css" rel="stylesheet" media="screen">
<link href="style/bootstrap-tagsinput.css" rel="stylesheet" media="screen">
<link href="style/default.css" rel="stylesheet" media="screen">
+ <script type="text/javascript">
+ var TOKEN = "' . Session::get('token') . '";
+ </script>
+ </body>
',
self::$header
,
' </head>
<body>
- <div class="container">
+ <div class="container" id="mainpage">
',
self::$body
,
@@ -58,7 +62,7 @@ class Render
<script src="script/jquery.js"></script>
<script src="script/bootstrap.min.js"></script>
<script src="script/bootstrap-tagsinput.min.js"></script>
- <script src="script/custom.js"></script></body>
+ <script src="script/taskmanager.js"></script>
</html>'
;
if ($zip) {
diff --git a/inc/taskmanager.inc.php b/inc/taskmanager.inc.php
index f2f337be..3353050f 100644
--- a/inc/taskmanager.inc.php
+++ b/inc/taskmanager.inc.php
@@ -12,21 +12,40 @@ class Taskmanager
{
if (self::$sock !== false) return;
self::$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
- socket_set_option(self::$sock, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 0, 'usec' => 100000));
- socket_set_option(self::$sock, SOL_SOCKET, SO_SNDTIMEO, array('sec' => 0, 'usec' => 100000));
+ socket_set_option(self::$sock, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 0, 'usec' => 300000));
+ socket_set_option(self::$sock, SOL_SOCKET, SO_SNDTIMEO, array('sec' => 0, 'usec' => 200000));
socket_connect(self::$sock, '127.0.0.1', 9215);
}
- public static function submit($task, $data, $async)
+ public static function submit($task, $data, $async = false)
{
self::init();
$seq = (string)mt_rand();
- $data = json_encode($data);
+ if (empty($data)) {
+ $data = '{}';
+ } else {
+ $data = json_encode($data);
+ }
$message = "$seq, $task, $data";
$sent = socket_send(self::$sock, $message, strlen($message), 0);
+ if ($sent != strlen($message)) {
+ Message::addError('taskmanager-error');
+ return false;
+ }
if ($async) return true;
$reply = self::readReply($seq);
- if (!is_array($reply)) return false;
+ if ($reply === false) {
+ Message::addError('taskmanager-error');
+ return false;
+ }
+ if (!is_array($reply)) {
+ Message::addError('taskmanager-format');
+ return false;
+ }
+ if ($reply['statusCode'] === NO_SUCH_TASK) {
+ Message::addError('task-error', 'Ungültiger Task: ' . $task);
+ return false;
+ }
return $reply;
}
diff --git a/modules/sysconfig.inc.php b/modules/sysconfig.inc.php
index 28fc6a50..f177f0f1 100644
--- a/modules/sysconfig.inc.php
+++ b/modules/sysconfig.inc.php
@@ -7,18 +7,11 @@ class Page_SysConfig extends Page
{
User::load();
- // Read request vars
$action = Request::any('action', 'list');
- $step = Request::any('step', 0);
// Action: "addmodule" (upload new module)
if ($action === 'addmodule') {
- if ($step === 0) $step = 'AddModule_Start';
- require_once 'modules/sysconfig/addmodule.inc.php';
- foreach (glob('modules/sysconfig/addmodule_*.inc.php') as $file) {
- require_once $file;
- }
- AddModule_Base::setStep($step);
+ $this->initAddModule();
AddModule_Base::preprocess();
}
@@ -67,6 +60,17 @@ class Page_SysConfig extends Page
break;
}
}
+
+ protected function doAjax()
+ {
+ $action = Request::any('action', 'list');
+
+ // Action: "addmodule" (upload new module)
+ if ($action === 'addmodule') {
+ $this->initAddModule();
+ AddModule_Base::ajax();
+ }
+ }
private function rr_list_configs()
{
@@ -83,5 +87,16 @@ class Page_SysConfig extends Page
}
Render::addTemplate('page-sysconfig-main', array('modules' => $modules, 'token' => Session::get('token')));
}
+
+ private function initAddModule()
+ {
+ $step = Request::any('step', 0);
+ if ($step === 0) $step = 'AddModule_Start';
+ require_once 'modules/sysconfig/addmodule.inc.php';
+ foreach (glob('modules/sysconfig/addmodule_*.inc.php') as $file) {
+ require_once $file;
+ }
+ AddModule_Base::setStep($step);
+ }
}
diff --git a/modules/sysconfig/addmodule.inc.php b/modules/sysconfig/addmodule.inc.php
index 924f18fa..883c196f 100644
--- a/modules/sysconfig/addmodule.inc.php
+++ b/modules/sysconfig/addmodule.inc.php
@@ -81,6 +81,14 @@ abstract class AddModule_Base
// void
}
+ /**
+ * Handle ajax stuff
+ */
+ protected function ajaxInternal()
+ {
+ // void
+ }
+
public static function preprocess()
{
if (self::$instance === false) {
@@ -96,6 +104,14 @@ abstract class AddModule_Base
}
self::$instance->renderInternal();
}
+
+ public static function ajax()
+ {
+ if (self::$instance === false) {
+ Util::traceError('No step instance yet');
+ }
+ self::$instance->ajaxInternal();
+ }
}
diff --git a/modules/sysconfig/addmodule_ad.inc.php b/modules/sysconfig/addmodule_ad.inc.php
index abc55df5..ab897096 100644
--- a/modules/sysconfig/addmodule_ad.inc.php
+++ b/modules/sysconfig/addmodule_ad.inc.php
@@ -14,13 +14,15 @@ class AdModule_Start extends AddModule_Base
protected function renderInternal()
{
- Session::set('ad_stuff', false);
+ Session::set('ad_check', false);
+ Session::save();
Render::addDialog('Active Directory Authentifizierung', false, 'sysconfig/ad-start', array(
'step' => 'AdModule_CheckConnection',
'server' => Request::post('server'),
'searchbase' => Request::post('searchbase'),
'binddn' => Request::post('binddn'),
'bindpw' => Request::post('bindpw'),
+ 'token' => Session::get('token')
));
}
@@ -28,9 +30,8 @@ class AdModule_Start extends AddModule_Base
class AdModule_CheckConnection extends AddModule_Base
{
-
- private $taskId = false;
-
+ private $taskIds;
+
protected function preprocessInternal()
{
$server = Request::post('server');
@@ -39,19 +40,87 @@ class AdModule_CheckConnection extends AddModule_Base
$bindpw = Request::post('bindpw');
if (empty($server) || empty($searchbase) || empty($binddn)) {
Message::addError('empty-field');
- AddModule_Base::setStep('AdModule_Start');
+ AddModule_Base::setStep('AdModule_Start'); // Continues with AdModule_Start for render()
return;
}
- $this->taskId = 'ad_' . mt_rand() . '-' . microtime(true);
- Taskmanager::submit('LdapSearch', array(
+ /*
+ $data = Taskmanager::submit('LdapSearch', array(
'id' => $this->taskId,
'uri' => ''
- ), true);
+ ));
+ */
+ $ldapSearch = Taskmanager::submit('DummyTask', array());
+ if (isset($ldapSearch['id'])) {
+ $dummy = Taskmanager::submit('DummyTask', array('parentTask' => $ldapSearch['id']));
+ }
+ if (!isset($ldapSearch['id']) || !isset($dummy['id'])) {
+ AddModule_Base::setStep('AdModule_Start'); // Continues with AdModule_Start for render()
+ return;
+ }
+ $this->taskIds = array(
+ 'tm-search' => $ldapSearch['id'],
+ 'tm-dummy' => $dummy['id']
+ );
}
protected function renderInternal()
{
- Message::addInfo('missing-file');
+ Render::addDialog('Active Directory Authentifizierung', false, 'sysconfig/ad-checkconnection',
+ array_merge($this->taskIds, array(
+ 'server' => Request::post('server'),
+ 'searchbase' => Request::post('searchbase'),
+ 'binddn' => Request::post('binddn'),
+ 'bindpw' => Request::post('bindpw'),
+ 'token' => Session::get('token'),
+ 'step' => 'AdModule_Finish'
+ ))
+ );
+ }
+
+}
+
+class AdModule_Finish extends AddModule_Base
+{
+
+ private $taskIds;
+
+ protected function preprocessInternal()
+ {
+ $data = json_encode(array(
+ 'server' => Request::post('server'),
+ 'searchbase' => Request::post('searchbase'),
+ 'binddn' => Request::post('binddn'),
+ 'bindpw' => Request::post('bindpw'),
+ ));
+ Database::exec("INSERT INTO configtgz_module (title, moduletype, filename, contents) "
+ . " VALUES (:title, 'AD_AUTH', '', :content)", array(
+ 'title' => 'AD: ' . Request::post('server'),
+ 'content' => $data));
+ $id = Database::lastInsertId();
+ $name = CONFIG_TGZ_LIST_DIR . '/modules/AD_AUTH_id_' . $id . '.' . mt_rand() . '.tgz';
+ Database::exec("UPDATE configtgz_module SET filename = :filename WHERE moduleid = :id LIMIT 1", array(
+ 'id' => $id,
+ 'filename' => $name
+ ));
+ $tgz = Taskmanager::submit('DummyTask', array());
+ if (isset($tgz['id'])) {
+ $ldadp = Taskmanager::submit('DummyTask', array('parentTask' => $tgz['id']));
+ }
+ if (!isset($tgz['id']) || !isset($ldadp['id'])) {
+ AddModule_Base::setStep('AdModule_Start'); // Continues with AdModule_Start for render()
+ return;
+ }
+ $this->taskIds = array(
+ 'tm-module' => $tgz['id'],
+ 'tm-ldadp' => $ldadp['id']
+ );
}
-} \ No newline at end of file
+ protected function renderInternal()
+ {
+ Render::addDialog('Active Directory Authentifizierung', false, 'sysconfig/ad-finish',
+ $this->taskIds
+ );
+ }
+
+}
diff --git a/script/custom.js b/script/custom.js
index 3269749e..12e760af 100644
--- a/script/custom.js
+++ b/script/custom.js
@@ -1,3 +1,4 @@
+/*
function loadContent(elem, source)
{
$(elem).html('<div class="progress progress-striped active"><div class="progress-bar" style="width:100%"><span class="sr-only">In Progress....</span></div></div>');
@@ -14,4 +15,20 @@ function selectDir(obj)
if (text.substr(0, dirname.length) !== dirname) return;
$(this).parent().find('.fileBox')[0].checked = obj.checked;
});
-} \ No newline at end of file
+}
+*/
+
+function updater(url, postdata, callback)
+{
+ var updateTimer = setInterval(function () {
+ if (typeof $ === 'undefined')
+ return;
+ $.post(url, postdata, function (data, status) {
+ if (!callback(data, status))
+ clearInterval(updateTimer);
+ }, 'json').fail(function (jqXHR, textStatus, errorThrown) {
+ if (!callback(errorThrown, textStatus))
+ clearInterval(updateTimer);
+ });
+ }, 1000);
+}
diff --git a/script/taskmanager.js b/script/taskmanager.js
new file mode 100644
index 00000000..da3a0586
--- /dev/null
+++ b/script/taskmanager.js
@@ -0,0 +1,141 @@
+var tmItems = false;
+var tmErrors = 0;
+var TM_MAX_ERRORS = 5;
+
+function tmInit()
+{
+ tmItems = $("div[data-tm-id]");
+ if (tmItems.length === 0) return;
+ tmItems.each(function(i, item) {
+ item = $(item);
+ if (item.is('[data-tm-progress]')) {
+ item.append('<div class="data-tm-progress"><div class="progress"><div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%"></div></div></div>');
+ }
+ if (item.is('[data-tm-log]')) {
+ item.append('<pre class="data-tm-log" />');
+ }
+ item.prepend('<span class="data-tm-icon" />');
+ });
+ setTimeout(tmUpdate, 100);
+}
+
+function tmUpdate()
+{
+ var active = [];
+ tmItems.each(function(i, item) {
+ item = $(item);
+ var id = item.attr('data-tm-id');
+ if (typeof id === 'undefined' || id === false || id === '') return;
+ active.push(id);
+ });
+ if (active.length === 0) return;
+ $.post('api.php?do=taskmanager', { 'ids[]' : active, token : TOKEN }, function (data, status) {
+ // POST success
+ if (tmResult(data, status)) {
+ setTimeout(tmUpdate, 1000);
+ }
+ }, 'json').fail(function (jqXHR, textStatus, errorThrown) {
+ // POST failure
+ console.log("TaskManager Error: " + textStatus + " - " + errorThrown);
+ if (++tmErrors < TM_MAX_ERRORS) setTimeout(tmUpdate, 2000);
+ });
+}
+
+function tmResult(data, status)
+{
+ // Bail out on error
+ if (typeof data.error !== 'undefined') {
+ $('#mainpage').prepend($('<div class="alert alert-danger"/>').append(document.createTextNode(data.error)));
+ console.log("Error ERROR");
+ return false;
+ }
+ // No task list is also bad
+ if (typeof data.tasks === 'undefined') {
+ $('#mainpage').prepend('<div class="alert alert-danger">Internal Error #67452</div>');
+ console.log("Error UNEXPECTED");
+ return false;
+ }
+ var lastRunOnError = (tmErrors > TM_MAX_ERRORS);
+ // Let's continue handling stuff
+ var counter = 0;
+ for (var idx in data.tasks) {
+ var task = data.tasks[idx];
+ if (!task.id) continue;
+ counter++;
+ if (lastRunOnError) {
+ task.statusCode = 'TASK_ERROR';
+ } else if (task.error) {
+ ++tmErrors;
+ continue;
+ } else if (tmErrors > 0) {
+ --tmErrors;
+ }
+ var obj = $('div[data-tm-id="' + task.id + '"]');
+ if (!obj) continue;
+ if (task.statusCode === 'TASK_FINISHED') {
+ obj.attr('data-tm-id', '');
+ }
+ var icon = obj.find('.data-tm-icon');
+ if (icon) {
+ if (typeof task.statusCode === 'undefined') {
+ icon.attr('class', 'data-tm-icon glyphicon glyphicon-question-sign');
+ } else if (task.statusCode === 'TASK_WAITING') {
+ icon.attr('class', 'data-tm-icon glyphicon glyphicon-pause');
+ } else if (task.statusCode === 'TASK_PROCESSING') {
+ icon.attr('class', 'data-tm-icon glyphicon glyphicon-play');
+ } else if (task.statusCode === 'TASK_FINISHED') {
+ icon.attr('class', 'data-tm-icon glyphicon glyphicon-ok');
+ } else if (task.statusCode === 'TASK_ERROR') {
+ icon.attr('class', 'data-tm-icon glyphicon glyphicon-remove');
+ } else {
+ icon.attr('class', 'data-tm-icon glyphicon glyphicon-trash');
+ }
+ }
+ var progress = obj.find('.data-tm-progress');
+ if (progress) {
+ var pKey = obj.attr('data-tm-progress');
+ if (task.data && task.data[pKey]) {
+ tmSetProgress(progress, task.data[pKey], task.statusCode);
+ } else {
+ tmSetProgress(progress, false, task.statusCode);
+ }
+ }
+ var log = obj.find('.data-tm-log');
+ if (log) {
+ var lKey = obj.attr('data-tm-log');
+ if (task.data && task.data[lKey]) {
+ log.text(task.data[lKey]);
+ }
+ }
+ var cb = obj.attr('data-tm-callback');
+ if (cb && window[cb]) {
+ window[cb](task);
+ }
+ }
+ if (lastRunOnError) {
+ $('#mainpage').prepend($('<div class="alert alert-danger"/>').append(document.createTextNode(task.error)));
+ return false;
+ }
+ return counter > 0;
+}
+
+function tmSetProgress(elem, percent, status)
+{
+ var outer = '', inner = '';
+ if (status === 'TASK_PROCESSING') {
+ outer = ' active';
+ } else if (status === 'TASK_ERROR') {
+ inner = ' progress-bar-danger';
+ } else if (status === 'TASK_FINISHED') {
+ inner = ' progress-bar-success';
+ }
+ elem.find('.progress').attr('class', 'progress progress-striped' + outer);
+ var bar = elem.find('.progress-bar');
+ bar.attr('class', 'progress-bar' + inner);
+ if (percent !== false) {
+ bar.attr('aria-valuenow', percent);
+ bar.attr('style', 'width: ' + percent + '%');
+ }
+}
+
+tmInit();
diff --git a/templates/sysconfig/ad-checkconnection.html b/templates/sysconfig/ad-checkconnection.html
new file mode 100644
index 00000000..91b5881e
--- /dev/null
+++ b/templates/sysconfig/ad-checkconnection.html
@@ -0,0 +1,42 @@
+<p>
+ Die Verbindung zum angegebenen AD-Server wird nun überprüft. Bitte haben Sie einen Moment Geduld.
+</p>
+
+<div id="zeug">
+ <div data-tm-id="{{tm-search}}" data-tm-progress="progress">LDAP Test-Query</div>
+ <div data-tm-id="{{tm-dummy}}" data-tm-progress="progress" data-tm-callback="ldapCb">Dummy</div>
+</div>
+<br>
+<div class="pull-left">
+ <form role="form" method="post" action="?do=SysConfig&amp;action=addmodule&amp;step=AdModule_Start">
+ <input type="hidden" name="token" value="{{token}}">
+ <input name="server" value="{{server}}" type="hidden">
+ <input name="searchbase" value="{{searchbase}}" type="hidden">
+ <input name="binddn" value="{{binddn}}" type="hidden">
+ <input name="bindpw" value="{{bindpw}}" type="hidden">
+ <button type="submit" class="btn btn-primary">&laquo; Zurück</button>
+ </form>
+</div>
+<div class="pull-right">
+ <form role="form" method="post" action="?do=SysConfig&amp;action=addmodule&amp;step={{step}}">
+ <input type="hidden" name="token" value="{{token}}">
+ <input name="server" value="{{server}}" type="hidden">
+ <input name="searchbase" value="{{searchbase}}" type="hidden">
+ <input name="binddn" value="{{binddn}}" type="hidden">
+ <input name="bindpw" value="{{bindpw}}" type="hidden">
+ <button id="nextbutton" type="submit" class="btn btn-primary">Überspringen &raquo;</button>
+ </form>
+</div>
+<script type="text/javascript">
+function ldapCb(task)
+{
+ if (!task || !task.statusCode)
+ return;
+ if (task.statusCode === 'TASK_FINISHED') {
+ $('#nextbutton').html('Weiter &raquo;');
+ }
+ if (task.statusCode === 'TASK_ERROR' || task.statusCode === 'PARENT_FAILED') {
+ $('#nextbutton').html('Trotzdem weiter &raquo;');
+ }
+}
+</script>
diff --git a/templates/sysconfig/ad-finish.html b/templates/sysconfig/ad-finish.html
new file mode 100644
index 00000000..f20a2ce1
--- /dev/null
+++ b/templates/sysconfig/ad-finish.html
@@ -0,0 +1,28 @@
+<p>
+ Der AD-Proxy wird nun konfiguriert und gestartet...
+</p>
+
+<div id="zeug">
+ <div data-tm-id="{{tm-tgz}}" data-tm-log="message">Konfiguration erzeugen</div>
+ <div data-tm-id="{{tm-ldadp}}" data-tm-log="message" data-tm-callback="ldapCb">ldadp starten</div>
+</div>
+<br>
+<div id="back" class="pull-left" style="display:none">
+ <a href="?do=SysConfig&amp;action=addmodule&amp;step=AdModule_Start" class="btn btn-primary">Assistent neustarten</a>
+</div>
+<div id="finish" class="pull-right" style="display:none">
+ <a href="?do=SysConfig" class="btn btn-primary">Zur Systemkonfiguration</a>
+</div>
+<script type="text/javascript">
+function ldapCb(task)
+{
+ if (!task || !task.statusCode)
+ return;
+ if (task.statusCode === 'TASK_FINISHED') {
+ $('#finish').attr('style', '');
+ }
+ if (task.statusCode === 'TASK_ERROR' || task.statusCode === 'PARENT_FAILED') {
+ $('#back').attr('style', '');
+ }
+}
+</script>
diff --git a/templates/sysconfig/ad-start.html b/templates/sysconfig/ad-start.html
index 0ce4bbf3..f3d8235a 100644
--- a/templates/sysconfig/ad-start.html
+++ b/templates/sysconfig/ad-start.html
@@ -16,6 +16,7 @@
</p>
<form role="form" method="post" action="?do=SysConfig&amp;action=addmodule&amp;step={{step}}">
+ <input type="hidden" name="token" value="{{token}}">
<div class="input-group">
<span class="input-group-addon slx-ga">Server</span>
<input name="server" value="{{server}}" type="text" class="form-control" placeholder="dc0.institution.example.com">