Subversion Repositories oidplus

Rev

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