vdir.html 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. <div class="standardContainer">
  2. <div class="ui basic segment">
  3. <h2>Virtual Directory</h2>
  4. <p>A virtual directory is a consolidated view of multiple directories that provides a unified entry point for users to access disparate sources.</p>
  5. </div>
  6. <div id="currentVirtualDirectoryAttachingHost" class="ui basic segment">
  7. Select a host / routing rule to start editing Virtual Directory
  8. </div>
  9. <div class="ui stackable grid">
  10. <div class="six wide column">
  11. <h4>Select a Target Host / Site</h4>
  12. <p>Attach Virtual Directory routing rule to root proxy router</p>
  13. <div class="ui checkbox">
  14. <input type="checkbox" id="useRootProxyRouterForVdir" onchange="handleVdirAttachTargetChange(this);">
  15. <label>Root Proxy Router<br>
  16. <small>Only applicable when Default Site is set to "Reverse Proxy" mode</small></label>
  17. </div>
  18. <div class="ui horizontal divider">OR</div>
  19. <p>Create Virtual Directory routing in existing host / routing rule entries</p>
  20. <div class="ui fluid search selection dropdown">
  21. <input type="hidden" id="vdirBaseRoutingRule" name="vdirBaseRoutingRule" onchange="handleVdirAttachTargetChange();">
  22. <i class="dropdown icon"></i>
  23. <div class="default text">Select a host to edit</div>
  24. <div class="menu" id="hostDomainList">
  25. </div>
  26. </div>
  27. </div>
  28. <div class="ten wide column">
  29. <h4>Edit Virtual Directory Routing Rules</h4>
  30. <p>The following are the list of Virtual Directories currently handled by the host router above</p>
  31. <div style="width: 100%; overflow-x: auto; margin-bottom: 1em;">
  32. <table class="ui celled sortable basic unstackable compact table">
  33. <thead>
  34. <tr>
  35. <th>Virtual Directory</th>
  36. <th>Destination</th>
  37. <th class="no-sort" style="min-width: 7.2em;">Actions</th>
  38. </tr>
  39. </thead>
  40. <tbody id="vdirList">
  41. <tr>
  42. <td data-label="" colspan="3">No Selected Host</td>
  43. </tr>
  44. </tbody>
  45. </table>
  46. </div>
  47. <button class="ui icon right floated basic button" onclick="reloadVdirList();"><i class="green refresh icon"></i> Refresh</button>
  48. <br><br>
  49. <div class="ui divider"></div>
  50. <div id="newVDSection" class="disabled section">
  51. <h4>New Virtual Directory Rule</h4>
  52. <form class="ui form">
  53. <div class="field">
  54. <label>Matching Path Prefix</label>
  55. <input type="text" id="virtualDirectoryPath" placeholder="/mysite/">
  56. <small>Path that follows your select host / domain, e.g. <code>/mysite/</code> as path prefix will forward all request that matches <code>mydomain.com/mysite/*</code></small>
  57. </div>
  58. <div class="field">
  59. <label>Target IP Address or Domain Name with port</label>
  60. <input type="text" id="virtualDirectoryDomain" onchange="updateVDTargetTLSState();">
  61. <small>E.g. 192.168.0.101:8000 or example.com</small>
  62. </div>
  63. <div class="field">
  64. <div class="ui checkbox">
  65. <input type="checkbox" id="vdReqTls">
  66. <label>Proxy Target require TLS Connection <br><small>(i.e. Your proxy target starts with https://)</small></label>
  67. </div>
  68. </div>
  69. <!-- Advance configs -->
  70. <div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
  71. <div id="advanceProxyRules" class="ui fluid accordion">
  72. <div class="title">
  73. <i class="dropdown icon"></i>
  74. Advance Settings
  75. </div>
  76. <div class="content">
  77. <p></p>
  78. <div class="field">
  79. <div class="ui checkbox">
  80. <input type="checkbox" id="vdSkipTLSValidation">
  81. <label>Ignore TLS/SSL Verification Error<br><small>For targets that is using self-signed, expired certificate (Not Recommended)</small></label>
  82. </div>
  83. </div>
  84. </div>
  85. </div>
  86. </div>
  87. <button class="ui basic button" onclick="addVdirToHost(); event.preventDefault();"><i class="green add icon"></i> Create Virtual Directory</button>
  88. </form>
  89. </div>
  90. </div>
  91. </div>
  92. <br><br>
  93. </div>
  94. <script>
  95. //Virtual directories functions
  96. //Initialize the list of hosts that can be used to attach vdirs config
  97. function initVdirList(){
  98. //Load the hosts into the dropdown
  99. $("#hostDomainList").html("");
  100. $.get("/api/proxy/list?type=host", function(data){
  101. if (data.error != undefined){
  102. msgbox(data.error, false);
  103. }else{
  104. if (data.length == 0){
  105. //No hosts found
  106. }else{
  107. data.forEach(proxyEndpoint => {
  108. let domain = proxyEndpoint.RootOrMatchingDomain;
  109. $("#hostDomainList").append(`<div class="item" data-value="${domain}">${domain}</div>`);
  110. });
  111. //Update the dropdown events
  112. $("#vdirBaseRoutingRule").parent().dropdown();
  113. }
  114. }
  115. });
  116. }
  117. function handleVdirAttachTargetChange(targetCheckbox=undefined){
  118. if (targetCheckbox != undefined && targetCheckbox.checked){
  119. $("#vdirBaseRoutingRule").parent().addClass("disabled");
  120. //Load the vdir list for root
  121. loadVdirList("root");
  122. $("#newVDSection").removeClass("disabled");
  123. }else{
  124. $("#vdirBaseRoutingRule").parent().removeClass("disabled");
  125. let selectedEndpointRule = $("#vdirBaseRoutingRule").val();
  126. if (selectedEndpointRule != ""){
  127. loadVdirList(selectedEndpointRule);
  128. $("#newVDSection").removeClass("disabled");
  129. }else{
  130. $("#newVDSection").addClass("disabled");
  131. }
  132. }
  133. }
  134. //List the Vdir of the given endpoint, use "root" for root router
  135. function loadVdirList(endpoint){
  136. $("#currentVirtualDirectoryAttachingHost").html(`Editing Host: ${endpoint}`);
  137. let reqURL = "/api/proxy/vdir/list?type=host&ep=" + endpoint;
  138. if (endpoint == "root"){
  139. //Load root endpoint vdir list
  140. reqURL = "/api/proxy/vdir/list?type=root";
  141. }
  142. $.get(reqURL, function(data){
  143. if (data.error != undefined){
  144. msgbox(data.error, false);
  145. }else{
  146. $("#vdirList").html("");
  147. if (data.length == 0){
  148. //No virtual directory for this host
  149. $("#vdirList").append(`<tr>
  150. <td data-label="" colspan="3"><i class="green check circle icon"></i> No Virtual Directory Routing Rule</td>
  151. </tr>`);
  152. }else{
  153. //List the vdirs
  154. console.log(data);
  155. data.forEach(vdir => {
  156. if (vdir.RequireTLS){
  157. tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
  158. if (vdir.SkipCertValidations){
  159. tlsIcon = `<i class="yellow lock icon" title="TLS/SSL mode without verification"></i>`
  160. }
  161. }
  162. let payload = JSON.stringify(vdir).hexEncode();
  163. $("#vdirList").append(`<tr vdirid="${vdir.MatchingPath.hexEncode()}" class="vdirEntry" payload="${payload}">
  164. <td data-label="" editable="false" >${vdir.MatchingPath}</td>
  165. <td data-label="" editable="true" datatype="domain">${vdir.Domain} ${tlsIcon}</td>
  166. <td class="center aligned" editable="true" datatype="action" data-label="">
  167. <button class="ui circular mini basic icon button editBtn" onclick='editVdir("${vdir.MatchingPath}", "${endpoint}")'><i class="edit icon"></i></button>
  168. <button class="ui circular mini red basic icon button" onclick='deleteVdir("${vdir.MatchingPath}", "${endpoint}")'><i class="trash icon"></i></button>
  169. </td>
  170. </tr>`);
  171. })
  172. }
  173. }
  174. });
  175. }
  176. //Check if the entered domain require TLS
  177. function updateVDTargetTLSState(){
  178. var targetDomain = $("#virtualDirectoryDomain").val().trim();
  179. if (targetDomain != ""){
  180. $.ajax({
  181. url: "/api/proxy/tlscheck",
  182. data: {url: targetDomain},
  183. success: function(data){
  184. if (data.error != undefined){
  185. }else if (data == "https"){
  186. $("#vdReqTls").parent().checkbox("set checked");
  187. }else if (data == "http"){
  188. $("#vdReqTls").parent().checkbox("set unchecked");
  189. }
  190. }
  191. });
  192. }
  193. }
  194. function reloadVdirList(){
  195. if ($("#useRootProxyRouterForVdir")[0].checked){
  196. loadVdirList("root");
  197. return;
  198. }
  199. let endpoint = $("#vdirBaseRoutingRule").val().trim();
  200. if (endpoint != ""){
  201. loadVdirList(endpoint);
  202. }
  203. }
  204. //Create a virtual directory routing rule and attach to this endpoint
  205. function addVdirToHost(){
  206. var matchingPath = $("#virtualDirectoryPath").val().trim();
  207. var targetDomain = $("#virtualDirectoryDomain").val().trim();
  208. var reqTLS = $("#vdReqTls")[0].checked;
  209. var skipTLSValidation = $("#vdSkipTLSValidation")[0].checked;
  210. //Validate the input data
  211. if (matchingPath == ""){
  212. $("#virtualDirectoryPath").parent().addClass('error');
  213. return;
  214. }else{
  215. $("#virtualDirectoryPath").parent().removeClass('error');
  216. }
  217. if (targetDomain == ""){
  218. $("#virtualDirectoryDomain").parent().addClass('error');
  219. return;
  220. }else{
  221. $("#virtualDirectoryDomain").parent().removeClass('error');
  222. }
  223. //Check if we are editing host
  224. let epType = "host";
  225. let endpoint = "root";
  226. if ($("#useRootProxyRouterForVdir")[0].checked){
  227. //Editing root virtual directory
  228. epType = "root";
  229. }else{
  230. //Editing hosts virtual directory
  231. endpoint = $("#vdirBaseRoutingRule").val().trim();
  232. }
  233. //Create a virtual directory endpoint
  234. $.ajax({
  235. url: "/api/proxy/vdir/add",
  236. method: "POST",
  237. data: {
  238. "type": epType,
  239. "endpoint": endpoint,
  240. "path": matchingPath,
  241. "domain":targetDomain,
  242. "reqTLS":reqTLS,
  243. "skipValid":skipTLSValidation,
  244. },
  245. success: function(data){
  246. if (data.error != undefined){
  247. msgbox(data.error, false);
  248. }else{
  249. msgbox("New Virtual Directory rule added");
  250. reloadVdirList();
  251. resetVdirForm();
  252. }
  253. },
  254. error: function(){
  255. msgbox("Add Virtual Directory failed due to unknown reasons", false);
  256. }
  257. })
  258. }
  259. //Reset the vdir form
  260. function resetVdirForm(){
  261. $("#virtualDirectoryPath").val("");
  262. $("#virtualDirectoryDomain").val("");
  263. $("#vdReqTls").parent().checkbox("set unchecked");
  264. $("#vdSkipTLSValidation").parent().checkbox("set unchecked");
  265. }
  266. //Remove Vdir
  267. function deleteVdir(matchingPath, endpoint){
  268. var epType = "host";
  269. var path = $("#vdirBaseRoutingRule").val().trim();
  270. if (endpoint == "root"){
  271. eptype = "root";
  272. path = "";
  273. }
  274. $.ajax({
  275. url: "/api/proxy/vdir/del",
  276. method: "POST",
  277. data: {
  278. "type":epType,
  279. "vdir": matchingPath,
  280. "path": path
  281. },
  282. success: function(data){
  283. if (data.error != undefined){
  284. msgbox(data.error, false);
  285. }else{
  286. msgbox("Virtual Directory rule removed", true);
  287. reloadVdirList();
  288. }
  289. }
  290. })
  291. }
  292. function editVdir(matchingPath, ept){
  293. let targetDOM = $(".vdirEntry[vdirid='" + matchingPath.hexEncode() + "']")
  294. let payload = $(targetDOM).attr("payload").hexDecode();
  295. payload = JSON.parse(payload);
  296. console.log(payload);
  297. $(targetDOM).find("td[editable='true']").each(function(){
  298. let datatype = $(this).attr("datatype");
  299. let column = $(this);
  300. if (datatype == "domain"){
  301. let domain = payload.Domain;
  302. //Target require TLS for proxying
  303. let tls = payload.RequireTLS;
  304. if (tls){
  305. tls = "checked";
  306. }else{
  307. tls = "";
  308. }
  309. //Require TLS validation
  310. let skipTLSValidation = payload.SkipCertValidations;
  311. let checkstate = "";
  312. if (skipTLSValidation){
  313. checkstate = "checked";
  314. }
  315. input = `
  316. <div class="ui mini fluid input">
  317. <input type="text" class="Domain" value="${domain}">
  318. </div>
  319. <div class="ui checkbox" style="margin-top: 0.4em;">
  320. <input type="checkbox" class="RequireTLS" ${tls}>
  321. <label>Require TLS<br>
  322. <small>Proxy target require HTTPS connection</small></label>
  323. </div><br>
  324. <div class="ui checkbox" style="margin-top: 0.4em;">
  325. <input type="checkbox" class="SkipCertValidations" ${checkstate}>
  326. <label>Skip Verification<br>
  327. <small>Check this if proxy target is using self signed certificates</small></label>
  328. </div>
  329. `;
  330. column.empty().append(input);
  331. }else if (datatype == 'action'){
  332. column.empty().append(`
  333. <button title="Save" onclick="saveVdirInlineEdit('${payload.MatchingPath.hexEncode()}');" class="ui basic small icon circular button inlineEditActionBtn"><i class="ui green save icon"></i></button>
  334. <button title="Cancel" onclick="exitVdirInlineEdit();" class="ui basic small icon circular button inlineEditActionBtn"><i class="ui remove icon"></i></button>
  335. `);
  336. }
  337. });
  338. }
  339. function saveVdirInlineEdit(mathingPath){
  340. mathingPath = mathingPath.hexDecode();
  341. //Load new setting from inline editor
  342. let newDomain = $("#vdirList").find(".Domain").val();
  343. let requireTLS = $("#vdirList").find(".RequireTLS")[0].checked;
  344. let skipValidation = $("#vdirList").find(".SkipCertValidations")[0].checked;
  345. console.log(mathingPath, newDomain, requireTLS, skipValidation)
  346. }
  347. function exitVdirInlineEdit(){
  348. reloadVdirList();
  349. }
  350. //Bind on tab switch events
  351. tabSwitchEventBind["vdir"] = function(){
  352. initVdirList();
  353. }
  354. </script>