Subversion Repositories oidplus

Rev

Rev 57 | Rev 95 | Go to most recent revision | View as "text/javascript" | Blame | Compare with Previous | 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.icon ? '<img src="'+data.icon+'" width="48" height="48" alt="'+data.title.htmlentities()+'"> ' : '') +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.                         if (data.icon) {
  100.                                 $('#real_title').html('<img src="'+data.icon+'" width="48" height="48" alt="'+data.title.htmlentities()+'"> ' + data.title.htmlentities());
  101.                         } else {
  102.                                 $('#real_title').html(data.title.htmlentities());
  103.                         }
  104.                         $('#real_content').html(data.text);
  105.                         document.title = combine_systemtitle_and_pagetitle(system_title, data.title);
  106.                         current_node = id;
  107.                 })
  108.                 .catch(function(error) {
  109.                         console.error(error);
  110.                 });
  111.         })
  112.         .catch(function(error) {
  113.                 console.error(error);
  114.         });
  115.  
  116.         // $('#content_window').show();
  117. }
  118.  
  119. function updateDesc() {
  120.         $.ajax({
  121.                 url:"action.php",
  122.                 method:"POST",
  123.                 data: {
  124.                         action:"Update2",
  125.                         id:current_node,
  126.                         title:(document.getElementById('titleedit') ? document.getElementById('titleedit').value : null),
  127.                         //description:(document.getElementById('description') ? document.getElementById('description').value : null)
  128.                         description:tinyMCE.get('description').getContent()
  129.                 },
  130.                 success:function(data) {
  131.                         if (data != "OK") {
  132.                                 alert("Error: " + data);
  133.                         } else {
  134.                                 alert("Update OK");
  135.                                 //reloadContent();
  136.                                 $('#oidtree').jstree("refresh");
  137.                                 var h1s = document.getElementsByTagName("h1");
  138.                                 for (var i = 0; i < h1s.length; i++) {
  139.                                         var h1 = h1s[i];
  140.                                         h1.innerHTML = document.getElementById('titleedit').value.htmlentities();
  141.                                 }
  142.                                 document.title = combine_systemtitle_and_pagetitle(system_title, document.getElementById('titleedit').value);
  143.  
  144.                                 var mce = tinymce.get('description');
  145.                                 if (mce != null) mce.isNotDirty = 1;
  146.                         }
  147.                 }
  148.         });
  149. }
  150.  
  151. function crudActionSendInvitation(origin, email) {
  152.         // document.location = '?goto=oidplus:invite_ra$'+email+'$'+origin;
  153.  
  154.         openOidInPanel('oidplus:invite_ra$'+email+'$'+origin);
  155.  
  156. }
  157.  
  158. function crudActionInsert(parent) {
  159.         $.ajax({
  160.                 url:"action.php",
  161.                 method:"POST",
  162.                 data:{
  163.                         action:"Insert",
  164.                         id:document.getElementById('id').value,
  165.                         ra_email:document.getElementById('ra_email').value,
  166.                         asn1ids:(document.getElementById('asn1ids') ? document.getElementById('asn1ids').value : null),
  167.                         iris:(document.getElementById('iris') ? document.getElementById('iris').value : null),
  168.                         confidential:(document.getElementById('hide') ? document.getElementById('hide').checked : null),
  169.                         parent:parent
  170.                 },
  171.                 success:function(data) {
  172.                         if (data == "OK") {
  173.                                 //alert("Insert OK");
  174.                                 reloadContent();
  175.                                 // TODO: auf reloadContent() verzichten. stattdessen nur tree links aktualisieren, und rechts eine neue zeile zur tabelle hinzufügen
  176.                         } else if (data == "OK (RaNotInDatabase)") {
  177.                                 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?")) {
  178.                                         crudActionSendInvitation(parent, document.getElementById('ra_email').value);
  179.                                 } else {
  180.                                         reloadContent();
  181.                                         // TODO: auf reloadContent() verzichten. stattdessen nur tree links aktualisieren, und rechts eine neue zeile zur tabelle hinzufügen
  182.                                 }
  183.                         } else {
  184.                                 alert("Error: " + data);
  185.                         }
  186.                 }
  187.         });
  188. }
  189.  
  190. function crudActionUpdate(id, parent) {
  191.         $.ajax({
  192.                 url:"action.php",
  193.                 method:"POST",
  194.                 data: {
  195.                         action:"Update",
  196.                         id:id,
  197.                         ra_email:document.getElementById('ra_email_'+id).value,
  198.                         asn1ids:(document.getElementById('asn1ids_'+id) ? document.getElementById('asn1ids_'+id).value : null),
  199.                         iris:(document.getElementById('iris_'+id) ? document.getElementById('iris_'+id).value : null),
  200.                         confidential:(document.getElementById('hide_'+id) ? document.getElementById('hide_'+id).checked : null),
  201.                         parent:parent
  202.                 },
  203.                 success:function(data) {
  204.                         if (data == "OK") {
  205.                                 alert("Update OK");
  206.                                 // reloadContent();
  207.                                 $('#oidtree').jstree("refresh");
  208.                         } else if (data == "OK (RaNotInDatabase)") {
  209.                                 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?")) {
  210.                                         crudActionSendInvitation(parent, document.getElementById('ra_email_'+id).value);
  211.                                 } else {
  212.                                         // reloadContent();
  213.                                         $('#oidtree').jstree("refresh");
  214.                                 }
  215.                         } else {
  216.                                 alert("Error: " + data);
  217.                         }
  218.                 }
  219.         });
  220. }
  221.  
  222. function crudActionDelete(id, parent) {
  223.         if(!window.confirm("Are you sure that you want to delete "+id+"?")) return false;
  224.  
  225.         $.ajax({
  226.                 url:"action.php",
  227.                 method:"POST",
  228.                 data: {
  229.                         action:"Delete",
  230.                         id:id,
  231.                         parent:parent
  232.                 },
  233.                 success:function(data) {
  234.                         if (data != "OK") {
  235.                                 alert("Error: " + data);
  236.                         } else {
  237.                                 reloadContent();
  238.                                 // TODO: auf reloadContent() verzichten. stattdessen nur tree links aktualisieren, und rechts die zeile aus der tabelle löschen
  239.                         }
  240.                 }
  241.         });
  242. }
  243.  
  244. function deleteRa(email, goto) {
  245.         if(!window.confirm("Are you really sure that you want to delete "+email+"? (The OIDs stay active)")) return false;
  246.  
  247.         $.ajax({
  248.                 url:"action.php",
  249.                 method:"POST",
  250.                 data: {
  251.                         action:"delete_ra",
  252.                         email:email,
  253.                 },
  254.                 success:function(data) {
  255.                         if (data != "OK") {
  256.                                 alert("Error: " + data);
  257.                         } else {
  258.                                 alert("Done.");
  259.                                 if (goto != null) document.location = '?goto=' + goto;
  260.                                 // reloadContent();
  261.                         }
  262.                 }
  263.         });
  264. }
  265.  
  266. function raLogout(email) {
  267.         if(!window.confirm("Are you sure that you want to logout?")) return false;
  268.  
  269.         $.ajax({
  270.                 url:"action.php",
  271.                 method:"POST",
  272.                 data: {
  273.                         action:"ra_logout",
  274.                         email:email,
  275.                 },
  276.                 success:function(data) {
  277.                         if (data != "OK") {
  278.                                 alert("Error: " + data);
  279.                         } else {
  280.                                 document.location = '?goto=oidplus:system';
  281.                                 // reloadContent();
  282.                         }
  283.                 }
  284.         });
  285. }
  286.  
  287. function raLogin(email, password) {
  288.         $.ajax({
  289.                 url:"action.php",
  290.                 method:"POST",
  291.                 data: {
  292.                         action:"ra_login",
  293.                         email:email,
  294.                         password:password,
  295.                         captcha: document.getElementsByClassName('g-recaptcha').length > 0 ? grecaptcha.getResponse() : null
  296.                 },
  297.                 success:function(data) {
  298.                         if (data != "OK") {
  299.                                 alert("Error: " + data);
  300.                                 grecaptcha.reset();
  301.                         } else {
  302.                                 document.location = '?goto=oidplus:system';
  303.                                 // reloadContent();
  304.                         }
  305.                 }
  306.         });
  307. }
  308.  
  309. function adminLogin(password) {
  310.         $.ajax({
  311.                 url:"action.php",
  312.                 method:"POST",
  313.                 data: {
  314.                         action:"admin_login",
  315.                         password:password,
  316.                         captcha: document.getElementsByClassName('g-recaptcha').length > 0 ? grecaptcha.getResponse() : null
  317.                 },
  318.                 success:function(data) {
  319.                         if (data != "OK") {
  320.                                 alert("Error: " + data);
  321.                                 grecaptcha.reset();
  322.                         } else {
  323.                                 document.location = '?goto=oidplus:system';
  324.                                 // reloadContent();
  325.                         }
  326.                 }
  327.         });
  328. }
  329.  
  330. function adminLogout() {
  331.         if(!window.confirm("Are you sure that you want to logout?")) return false;
  332.  
  333.         $.ajax({
  334.                 url:"action.php",
  335.                 method:"POST",
  336.                 data: {
  337.                         action:"admin_logout",
  338.                 },
  339.                 success:function(data) {
  340.                         if (data != "OK") {
  341.                                 alert("Error: " + data);
  342.                         } else {
  343.                                 document.location = '?goto=oidplus:system';
  344.                                 // reloadContent();
  345.                         }
  346.                 }
  347.         });
  348. }
  349.  
  350. function openAndSelectNode(childID, parentID) {
  351.         if ($('#oidtree').jstree(true).get_node(parentID)) {
  352.                 $('#oidtree').jstree('open_node', '#'+parentID, function(e, data) { // open parent node
  353.                         if ($('#oidtree').jstree(true).get_node(childID)) { // is the child there?
  354.                                 $('#oidtree').jstree('deselect_all').jstree('select_node', '#'+childID); // select it
  355.                         } else {
  356.                                 // This can happen if the content page contains brand new items which are not in the treeview yet
  357.                                 document.location = "?goto="+encodeURI(childID);
  358.                         }
  359.                 }, true);
  360.         } else {
  361.                 // This should usually not happen
  362.                 document.location = "?goto="+encodeURI(childID);
  363.         }
  364. }
  365.  
  366. $(window).on("popstate", function(e) {
  367.         popstate_running = true;
  368.         try {
  369.                 var data = e.originalEvent.state;
  370.  
  371.                 current_node = data.node_id;
  372.                 $('#oidtree').jstree('deselect_all').jstree('select_node', data.node_id); // TODO: search and open the nodes
  373.                 $('#real_title').html(data.titleHTML);
  374.                 $('#real_content').html(data.textHTML);
  375.                 $('#static_link').attr("href", data.staticlinkHREF);
  376.                 document.title = combine_systemtitle_and_pagetitle(system_title, data.titleHTML.html_entity_decode());
  377.         } catch (err) {
  378.                 popstate_running = false;
  379.         } finally {
  380.                 popstate_running = false;
  381.         }
  382. });
  383.  
  384. $(document).ready(function () {
  385.         // --- JsTree
  386.  
  387.         $('#oidtree')
  388.         .jstree({
  389.                 plugins: ['massload','search','conditionalselect'],
  390.                 'core' : {
  391.                         'data' : {
  392.                                 "url" : getTreeLoadURL(),
  393.                                 "data" : function (node) {
  394.                                         return { "id" : node.id };
  395.                                 }
  396.                         },
  397.                         "multiple": false
  398.                 },
  399.                 'conditionalselect' : function (node) {
  400.                         if (node.original.conditionalselect !== undefined) {
  401.                                 return eval(node.original.conditionalselect);
  402.                         } else {
  403.                                 return true; // allow select
  404.                         }
  405.                 },
  406.         })
  407.         .on('ready.jstree', function (e, data) {
  408.                 var url = new URL(window.location.href);
  409.                 var goto = url.searchParams.get("goto");
  410.                 if (goto == null) goto = "oidplus:system"; // the page was not called with ?goto=...
  411.  
  412.                 // 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)
  413.                 // But then we need to set the history state manually
  414.                 current_node = goto;
  415.                 window.history.replaceState({"node_id":goto, "titleHTML":$('#real_title').html(), "textHTML":$('#real_content').html(), "staticlinkHREF":"?goto="+encodeURI(goto)}, $('#real_title').html(), '?goto='+encodeURI(goto));
  416.  
  417.                 if (goto != null) data.instance.select_node([goto]);
  418.         })
  419.         .on('select_node.jstree', function (node, selected, event) {
  420.                 var id = selected.node.id;
  421.                 if (current_node != id) {
  422.                         openOidInPanel(id);
  423.                 }
  424.         });
  425.  
  426.         // --- Layout
  427.  
  428.         $('body').layout({
  429.                 north__size: 40,
  430.                 north__slidable: false,
  431.                 north__closable: false,
  432.                 north__resizable: false,
  433.                 west__size:                     450,
  434.                 west__spacing_closed:           20,
  435.                 west__togglerLength_closed:     230,
  436.                 west__togglerAlign_closed:      "top",
  437.                 west__togglerContent_closed:"O<br>B<br>J<br>E<br>C<br>T<br><br>T<BR>R<BR>E<BR>E",
  438.                 west__togglerTip_closed:        "Open & Pin Menu",
  439.                 west__sliderTip:                "Slide Open Menu",
  440.                 west__slideTrigger_open:        "mouseover",
  441.                 center__maskContents:           true // IMPORTANT - enable iframe masking
  442.         });
  443. });
  444.  
  445. function inviteFormOnSubmit() {
  446.         $.ajax({
  447.                 url: "action.php",
  448.                 type: "POST",
  449.                 data: {
  450.                         action: "invite_ra",
  451.                         email: $("#email").val(),
  452.                         captcha: document.getElementsByClassName('g-recaptcha').length > 0 ? grecaptcha.getResponse() : null
  453.                 },
  454.                 success: function(data) {
  455.                         if (data != "OK") {
  456.                                 alert("Error: " + data);
  457.                                 grecaptcha.reset();
  458.                         } else {
  459.                                 alert("The RA has been invited via email.");
  460.                                 document.location = '?goto='+$("#origin").val();
  461.                                 //reloadContent();
  462.                         }
  463.                 }
  464.         });
  465.         return false;
  466. }
  467.  
  468. function activateRaFormOnSubmit() {
  469.         $.ajax({
  470.                 url: "action.php",
  471.                 type: "POST",
  472.                 data: {
  473.                         action: "activate_ra",
  474.                         email: $("#email").val(),
  475.                         auth: $("#auth").val(),
  476.                         password1: $("#password1").val(),
  477.                         password2: $("#password2").val(),
  478.                         timestamp: $("#timestamp").val()
  479.                 },
  480.                 success: function(data) {
  481.                         if (data != "OK") {
  482.                                 alert("Error: " + data);
  483.                         } else {
  484.                                 alert("Registration successful! You can now log in.");
  485.                                 document.location = '?goto=oidplus:login';
  486.                                 //reloadContent();
  487.                         }
  488.                 }
  489.         });
  490.         return false;
  491. }
  492.  
  493. function forgotPasswordFormOnSubmit() {
  494.         $.ajax({
  495.                 url: "action.php",
  496.                 type: "POST",
  497.                 data: {
  498.                         action: "forgot_password",
  499.                         email: $("#email").val(),
  500.                         captcha: document.getElementsByClassName('g-recaptcha').length > 0 ? grecaptcha.getResponse() : null
  501.                 },
  502.                 success: function(data) {
  503.                         if (data != "OK") {
  504.                                 alert("Error: " + data);
  505.                                 grecaptcha.reset();
  506.                         } else {
  507.                                 alert("E-Mail sent.");
  508.                                 document.location = '?goto=oidplus:login';
  509.                                 //reloadContent();
  510.                         }
  511.                 }
  512.         });
  513.         return false;
  514. }
  515.  
  516. function resetPasswordFormOnSubmit() {
  517.         $.ajax({
  518.                 url: "action.php",
  519.                 type: "POST",
  520.                 data: {
  521.                         action: "reset_password",
  522.                         email: $("#email").val(),
  523.                         auth: $("#auth").val(),
  524.                         password1: $("#password1").val(),
  525.                         password2: $("#password2").val(),
  526.                         timestamp: $("#timestamp").val()
  527.                 },
  528.                 success: function(data) {
  529.                         if (data != "OK") {
  530.                                 alert("Error: " + data);
  531.                         } else {
  532.                                 alert("Password sucessfully changed. You can now log in.");
  533.                                 document.location = '?goto=oidplus:login';
  534.                                 //reloadContent();
  535.                         }
  536.                 }
  537.         });
  538.         return false;
  539. }
  540.