Subversion Repositories oidplus

Rev

Rev 6 | View as "text/javascript" | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * OIDplus 2.0
  3.  * Copyright 2019 Daniel Marschall, ViaThinkSoft
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17.  
  18. /*jshint esversion: 6 */
  19.  
  20. // $('#html').jstree();
  21.  
  22. current_node = "";
  23. popstate_running = false;
  24.  
  25. system_title = "";
  26.  
  27. String.prototype.explode = function (separator, limit) {
  28.         // https://stackoverflow.com/questions/4514323/javascript-equivalent-to-php-explode
  29.         const array = this.split(separator);
  30.         if (limit !== undefined && array.length >= limit) {
  31.                 array.push(array.splice(limit - 1).join(separator));
  32.         }
  33.         return array;
  34. };
  35.  
  36. String.prototype.htmlentities = function () {
  37.         return this.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
  38. };
  39.  
  40. String.prototype.html_entity_decode = function () {
  41.         return $('<textarea />').html(this).text();
  42. };
  43.  
  44. function combine_systemtitle_and_pagetitle(systemtitle, pagetitle) {
  45.         if (systemtitle == pagetitle) {
  46.                 return systemtitle;
  47.         } else {
  48.                 return systemtitle + ' - ' + pagetitle;
  49.         }
  50. }
  51.  
  52. function getTreeLoadURL() {
  53.         var url = new URL(window.location.href);
  54.         var goto = url.searchParams.get("goto");
  55.         return (goto != null) ? "treeload.php?goto="+encodeURI(goto) : "treeload.php";
  56. }
  57.  
  58. function reloadContent() {
  59.         // document.location = '?goto='+encodeURI(current_node);
  60.         openOidInPanel(current_node);
  61.         $('#oidtree').jstree("refresh");
  62. }
  63.  
  64. function openOidInPanel(id, unselect=false) {
  65.         console.log("openOidInPanel("+id+", "+unselect+")");
  66.  
  67.         if (unselect) {
  68.                 $('#oidtree').jstree('deselect_all');
  69.         }
  70.  
  71.         // $('#content_window').hide();
  72.         document.title = "";
  73.         $('#real_title').html("&nbsp;");
  74.         $('#real_content').html("Loading...");
  75.         $('#static_link').attr("href", "?goto="+encodeURI(id));
  76.  
  77.         if (popstate_running) return; // To avoid that the jstree selection during popstate() won't trigger another page load
  78.  
  79.         // Normal opening of a description
  80.         fetch('get_description.php?id='+id)
  81.         .then(function(response) {
  82.                 response.json()
  83.                 .then(function(data) {
  84.                         data.id = id;
  85.  
  86.                         document.title = combine_systemtitle_and_pagetitle(system_title, data.title);
  87.                         var state = {
  88.                                 "node_id":id,
  89.                                 "titleHTML":data.title.htmlentities(),
  90.                                 "textHTML":data.text,
  91.                                 "staticlinkHREF":"?goto="+encodeURI(id)
  92.                         };
  93.                         if (current_node != id) {
  94.                                 window.history.pushState(state, data.title, "?goto="+encodeURI(id));
  95.                         } else {
  96.                                 window.history.replaceState(state, data.title, "?goto="+encodeURI(id));
  97.                         }
  98.  
  99.                         $('#real_title').html(data.title.htmlentities());
  100.                         $('#real_content').html(data.text);
  101.                         document.title = combine_systemtitle_and_pagetitle(system_title, data.title);
  102.                         current_node = id;
  103.                 })
  104.                 .catch(function(error) {
  105.                         console.error(error);
  106.                 });
  107.         })
  108.         .catch(function(error) {
  109.                 console.error(error);
  110.         });
  111.  
  112.         // $('#content_window').show();
  113. }
  114.  
  115. function updateDesc() {
  116.         $.ajax({
  117.                 url:"action.php",
  118.                 method:"POST",
  119.                 data: {
  120.                         action:"Update2",
  121.                         id:current_node,
  122.                         title:(document.getElementById('titleedit') ? document.getElementById('titleedit').value : null),
  123.                         //description:(document.getElementById('description') ? document.getElementById('description').value : null)
  124.                         description:tinyMCE.get('description').getContent()
  125.                 },
  126.                 success:function(data) {
  127.                         if (data != "OK") {
  128.                                 alert("Error: " + data);
  129.                         } else {
  130.                                 alert("Update OK");
  131.                                 //reloadContent();
  132.                                 $('#oidtree').jstree("refresh");
  133.                                 var h1s = document.getElementsByTagName("h1");
  134.                                 for (var i = 0; i < h1s.length; i++) {
  135.                                         var h1 = h1s[i];
  136.                                         h1.innerHTML = document.getElementById('titleedit').value.htmlentities();
  137.                                 }
  138.                                 document.title = combine_systemtitle_and_pagetitle(system_title, document.getElementById('titleedit').value);
  139.  
  140.                                 var mce = tinymce.get('description');
  141.                                 if (mce != null) mce.isNotDirty = 1;
  142.                         }
  143.                 }
  144.         });
  145. }
  146.  
  147. function crudActionSendInvitation(origin, email) {
  148.         // document.location = '?goto=oidplus:invite_ra$'+email+'$'+origin;
  149.  
  150.         openOidInPanel('oidplus:invite_ra$'+email+'$'+origin);
  151.  
  152. }
  153.  
  154. function crudActionInsert(parent) {
  155.         $.ajax({
  156.                 url:"action.php",
  157.                 method:"POST",
  158.                 data:{
  159.                         action:"Insert",
  160.                         id:document.getElementById('id').value,
  161.                         ra_email:document.getElementById('ra_email').value,
  162.                         asn1ids:(document.getElementById('asn1ids') ? document.getElementById('asn1ids').value : null),
  163.                         iris:(document.getElementById('iris') ? document.getElementById('iris').value : null),
  164.                         confidential:(document.getElementById('hide') ? document.getElementById('hide').checked : null),
  165.                         parent:parent
  166.                 },
  167.                 success:function(data) {
  168.                         if (data == "OK") {
  169.                                 //alert("Insert OK");
  170.                                 reloadContent();
  171.                                 // TODO: auf reloadContent() verzichten. stattdessen nur tree links aktualisieren, und rechts eine neue zeile zur tabelle hinzufügen
  172.                         } else if (data == "OK (RaNotInDatabase)") {
  173.                                 if (confirm("Update OK. However, the email address you have entered ("+document.getElementById('ra_email').value+") is not in our system. Do you want to send an invitation, so that the RA can register an account to manage their OIDs?")) {
  174.                                         crudActionSendInvitation(parent, document.getElementById('ra_email').value);
  175.                                 } else {
  176.                                         reloadContent();
  177.                                         // TODO: auf reloadContent() verzichten. stattdessen nur tree links aktualisieren, und rechts eine neue zeile zur tabelle hinzufügen
  178.                                 }
  179.                         } else {
  180.                                 alert("Error: " + data);
  181.                         }
  182.                 }
  183.         });
  184. }
  185.  
  186. function crudActionUpdate(id, parent) {
  187.         $.ajax({
  188.                 url:"action.php",
  189.                 method:"POST",
  190.                 data: {
  191.                         action:"Update",
  192.                         id:id,
  193.                         ra_email:document.getElementById('ra_email_'+id).value,
  194.                         asn1ids:(document.getElementById('asn1ids_'+id) ? document.getElementById('asn1ids_'+id).value : null),
  195.                         iris:(document.getElementById('iris_'+id) ? document.getElementById('iris_'+id).value : null),
  196.                         confidential:(document.getElementById('hide_'+id) ? document.getElementById('hide_'+id).checked : null),
  197.                         parent:parent
  198.                 },
  199.                 success:function(data) {
  200.                         if (data == "OK") {
  201.                                 alert("Update OK");
  202.                                 // reloadContent();
  203.                                 $('#oidtree').jstree("refresh");
  204.                         } else if (data == "OK (RaNotInDatabase)") {
  205.                                 if (confirm("Update OK. However, the email address you have entered ("+document.getElementById('ra_email_'+id).value+") is not in our system. Do you want to send an invitation, so that the RA can register an account to manage their OIDs?")) {
  206.                                         crudActionSendInvitation(parent, document.getElementById('ra_email_'+id).value);
  207.                                 } else {
  208.                                         // reloadContent();
  209.                                         $('#oidtree').jstree("refresh");
  210.                                 }
  211.                         } else {
  212.                                 alert("Error: " + data);
  213.                         }
  214.                 }
  215.         });
  216. }
  217.  
  218. function crudActionDelete(id, parent) {
  219.         if(!window.confirm("Are you sure that you want to delete "+id+"?")) return false;
  220.  
  221.         $.ajax({
  222.                 url:"action.php",
  223.                 method:"POST",
  224.                 data: {
  225.                         action:"Delete",
  226.                         id:id,
  227.                         parent:parent
  228.                 },
  229.                 success:function(data) {
  230.                         if (data != "OK") {
  231.                                 alert("Error: " + data);
  232.                         } else {
  233.                                 reloadContent();
  234.                                 // TODO: auf reloadContent() verzichten. stattdessen nur tree links aktualisieren, und rechts die zeile aus der tabelle löschen
  235.                         }
  236.                 }
  237.         });
  238. }
  239.  
  240. function deleteRa(email, goto) {
  241.         if(!window.confirm("Are you really sure that you want to delete "+email+"? (The OIDs stay active)")) return false;
  242.  
  243.         $.ajax({
  244.                 url:"action.php",
  245.                 method:"POST",
  246.                 data: {
  247.                         action:"delete_ra",
  248.                         email:email,
  249.                 },
  250.                 success:function(data) {
  251.                         if (data != "OK") {
  252.                                 alert("Error: " + data);
  253.                         } else {
  254.                                 alert("Done.");
  255.                                 if (goto != null) document.location = '?goto=' + goto;
  256.                                 // reloadContent();
  257.                         }
  258.                 }
  259.         });
  260. }
  261.  
  262. function raLogout(email) {
  263.         if(!window.confirm("Are you sure that you want to logout?")) return false;
  264.  
  265.         $.ajax({
  266.                 url:"action.php",
  267.                 method:"POST",
  268.                 data: {
  269.                         action:"ra_logout",
  270.                         email:email,
  271.                 },
  272.                 success:function(data) {
  273.                         if (data != "OK") {
  274.                                 alert("Error: " + data);
  275.                         } else {
  276.                                 document.location = '?goto=oidplus:system';
  277.                                 // reloadContent();
  278.                         }
  279.                 }
  280.         });
  281. }
  282.  
  283. function raLogin(email, password) {
  284.         $.ajax({
  285.                 url:"action.php",
  286.                 method:"POST",
  287.                 data: {
  288.                         action:"ra_login",
  289.                         email:email,
  290.                         password:password,
  291.                         captcha: document.getElementsByClassName('g-recaptcha').length > 0 ? grecaptcha.getResponse() : null
  292.                 },
  293.                 success:function(data) {
  294.                         if (data != "OK") {
  295.                                 alert("Error: " + data);
  296.                                 grecaptcha.reset();
  297.                         } else {
  298.                                 document.location = '?goto=oidplus:system';
  299.                                 // reloadContent();
  300.                         }
  301.                 }
  302.         });
  303. }
  304.  
  305. function adminLogin(password) {
  306.         $.ajax({
  307.                 url:"action.php",
  308.                 method:"POST",
  309.                 data: {
  310.                         action:"admin_login",
  311.                         password:password,
  312.                         captcha: document.getElementsByClassName('g-recaptcha').length > 0 ? grecaptcha.getResponse() : null
  313.                 },
  314.                 success:function(data) {
  315.                         if (data != "OK") {
  316.                                 alert("Error: " + data);
  317.                                 grecaptcha.reset();
  318.                         } else {
  319.                                 document.location = '?goto=oidplus:system';
  320.                                 // reloadContent();
  321.                         }
  322.                 }
  323.         });
  324. }
  325.  
  326. function adminLogout() {
  327.         if(!window.confirm("Are you sure that you want to logout?")) return false;
  328.  
  329.         $.ajax({
  330.                 url:"action.php",
  331.                 method:"POST",
  332.                 data: {
  333.                         action:"admin_logout",
  334.                 },
  335.                 success:function(data) {
  336.                         if (data != "OK") {
  337.                                 alert("Error: " + data);
  338.                         } else {
  339.                                 document.location = '?goto=oidplus:system';
  340.                                 // reloadContent();
  341.                         }
  342.                 }
  343.         });
  344. }
  345.  
  346. function openAndSelectNode(childID, parentID) {
  347.         if ($('#oidtree').jstree(true).get_node(parentID)) {
  348.                 $('#oidtree').jstree('open_node', '#'+parentID, function(e, data) { // open parent node
  349.                         if ($('#oidtree').jstree(true).get_node(childID)) { // is the child there?
  350.                                 $('#oidtree').jstree('deselect_all').jstree('select_node', '#'+childID); // select it
  351.                         } else {
  352.                                 // This can happen if the content page contains brand new items which are not in the treeview yet
  353.                                 document.location = "?goto="+encodeURI(childID);
  354.                         }
  355.                 }, true);
  356.         } else {
  357.                 // This should usually not happen
  358.                 document.location = "?goto="+encodeURI(childID);
  359.         }
  360. }
  361.  
  362. $(window).on("popstate", function(e) {
  363.         popstate_running = true;
  364.         try {
  365.                 var data = e.originalEvent.state;
  366.  
  367.                 current_node = data.node_id;
  368.                 $('#oidtree').jstree('deselect_all').jstree('select_node', data.node_id); // TODO: search and open the nodes
  369.                 $('#real_title').html(data.titleHTML);
  370.                 $('#real_content').html(data.textHTML);
  371.                 $('#static_link').attr("href", data.staticlinkHREF);
  372.                 document.title = combine_systemtitle_and_pagetitle(system_title, data.titleHTML.html_entity_decode());
  373.         } catch (err) {
  374.                 popstate_running = false;
  375.         } finally {
  376.                 popstate_running = false;
  377.         }
  378. });
  379.  
  380. $(document).ready(function () {
  381.         // --- JsTree
  382.  
  383.         $('#oidtree')
  384.         .jstree({
  385.                 plugins: ['massload','search','conditionalselect'],
  386.                 'core' : {
  387.                         'data' : {
  388.                                 "url" : getTreeLoadURL(),
  389.                                 "data" : function (node) {
  390.                                         return { "id" : node.id };
  391.                                 }
  392.                         },
  393.                         "multiple": false
  394.                 },
  395.                 'conditionalselect' : function (node) {
  396.                         var id = node.id;
  397.  
  398.                         if (id.explode('$', 2)[0] == 'oidplus:dummy') {
  399.                                 // Nothing to do here
  400.                                 // node can either bei "ra:<emailAddress" or "ra:admin"
  401.                                 // TODO: it would be much better if the mouse cursor would not show a hand
  402.                         } else if (id.explode('$', 2)[0] == 'oidplus:logout') {
  403.                                 var email = id.explode('$', 2)[1];
  404.                                 if (email == 'admin') {
  405.                                         adminLogout();
  406.                                 } else {
  407.                                         raLogout(email);
  408.                                 }
  409.                                 return false;
  410.                         } else if (id.explode('$', 2)[0] == 'oidplus:raroot') {
  411.                                 // Function "Jump to RA root"
  412.                                 $('#content_window').html('');
  413.                                 document.location = '?goto='+encodeURI(id.explode('$', 2)[1]);
  414.                         } else {
  415.                                 return true;
  416.                         }
  417.                 },
  418.         })
  419.         .on('ready.jstree', function (e, data) {
  420.                 var url = new URL(window.location.href);
  421.                 var goto = url.searchParams.get("goto");
  422.                 if (goto == null) goto = "oidplus:system"; // the page was not called with ?goto=...
  423.  
  424.                 // By setting current_node, select_node() will not cause get_description.php to load (since we already loaded the first static content via PHP, for search engines mainly)
  425.                 // But then we need to set the history state manually
  426.                 current_node = goto;
  427.                 window.history.replaceState({"node_id":goto, "titleHTML":$('#real_title').html(), "textHTML":$('#real_content').html(), "staticlinkHREF":"?goto="+encodeURI(goto)}, $('#real_title').html(), '?goto='+encodeURI(goto));
  428.  
  429.                 if (goto != null) data.instance.select_node([goto]);
  430.         })
  431.         .on('select_node.jstree', function (node, selected, event) {
  432.                 var id = selected.node.id;
  433.                 if (current_node != id) {
  434.                         openOidInPanel(id);
  435.                 }
  436.         });
  437.  
  438.         // --- Layout
  439.  
  440.         $('body').layout({
  441.                 north__size: 40,
  442.                 north__slidable: false,
  443.                 north__closable: false,
  444.                 north__resizable: false,
  445.                 west__size:                     450,
  446.                 west__spacing_closed:           20,
  447.                 west__togglerLength_closed:     230,
  448.                 west__togglerAlign_closed:      "top",
  449.                 west__togglerContent_closed:"O<br>B<br>J<br>E<br>C<br>T<br><br>T<BR>R<BR>E<BR>E",
  450.                 west__togglerTip_closed:        "Open & Pin Menu",
  451.                 west__sliderTip:                "Slide Open Menu",
  452.                 west__slideTrigger_open:        "mouseover",
  453.                 center__maskContents:           true // IMPORTANT - enable iframe masking
  454.         });
  455. });
  456.  
  457. function inviteFormOnSubmit() {
  458.         $.ajax({
  459.                 url: "action.php",
  460.                 type: "POST",
  461.                 data: {
  462.                         action: "invite_ra",
  463.                         email: $("#email").val(),
  464.                         captcha: document.getElementsByClassName('g-recaptcha').length > 0 ? grecaptcha.getResponse() : null
  465.                 },
  466.                 success: function(data) {
  467.                         if (data != "OK") {
  468.                                 alert("Error: " + data);
  469.                                 grecaptcha.reset();
  470.                         } else {
  471.                                 alert("The RA has been invited via email.");
  472.                                 document.location = '?goto='+$("#origin").val();
  473.                                 //reloadContent();
  474.                         }
  475.                 }
  476.         });
  477.         return false;
  478. }
  479.  
  480. function activateRaFormOnSubmit() {
  481.         $.ajax({
  482.                 url: "action.php",
  483.                 type: "POST",
  484.                 data: {
  485.                         action: "activate_ra",
  486.                         email: $("#email").val(),
  487.                         auth: $("#auth").val(),
  488.                         password1: $("#password1").val(),
  489.                         password2: $("#password2").val(),
  490.                         timestamp: $("#timestamp").val()
  491.                 },
  492.                 success: function(data) {
  493.                         if (data != "OK") {
  494.                                 alert("Error: " + data);
  495.                         } else {
  496.                                 alert("Registration successful! You can now log in.");
  497.                                 document.location = '?goto=oidplus:login';
  498.                                 //reloadContent();
  499.                         }
  500.                 }
  501.         });
  502.         return false;
  503. }
  504.  
  505. function forgotPasswordFormOnSubmit() {
  506.         $.ajax({
  507.                 url: "action.php",
  508.                 type: "POST",
  509.                 data: {
  510.                         action: "forgot_password",
  511.                         email: $("#email").val(),
  512.                         captcha: document.getElementsByClassName('g-recaptcha').length > 0 ? grecaptcha.getResponse() : null
  513.                 },
  514.                 success: function(data) {
  515.                         if (data != "OK") {
  516.                                 alert("Error: " + data);
  517.                                 grecaptcha.reset();
  518.                         } else {
  519.                                 alert("E-Mail sent.");
  520.                                 document.location = '?goto=oidplus:login';
  521.                                 //reloadContent();
  522.                         }
  523.                 }
  524.         });
  525.         return false;
  526. }
  527.  
  528. function resetPasswordFormOnSubmit() {
  529.         $.ajax({
  530.                 url: "action.php",
  531.                 type: "POST",
  532.                 data: {
  533.                         action: "reset_password",
  534.                         email: $("#email").val(),
  535.                         auth: $("#auth").val(),
  536.                         password1: $("#password1").val(),
  537.                         password2: $("#password2").val(),
  538.                         timestamp: $("#timestamp").val()
  539.                 },
  540.                 success: function(data) {
  541.                         if (data != "OK") {
  542.                                 alert("Error: " + data);
  543.                         } else {
  544.                                 alert("Password sucessfully changed. You can now log in.");
  545.                                 document.location = '?goto=oidplus:login';
  546.                                 //reloadContent();
  547.                         }
  548.                 }
  549.         });
  550.         return false;
  551. }
  552.