<!DOCTYPE html> <html> <head> <!-- Notes: This should be open in its original path--> <meta charset="utf-8"> <meta name="zoraxy.csrf.Token" content="{{.csrfToken}}"> <link rel="stylesheet" href="../script/semantic/semantic.min.css"> <script src="../script/jquery-3.6.0.min.js"></script> <script src="../script/semantic/semantic.min.js"></script> <script src="../script/utils.js"></script> </head> <body> <br> <div class="ui container"> <div class="ui header"> <div class="content"> Basic Auth Settings <div class="sub header" id="epname"></div> </div> </div> <div class="ui divider"></div> <h3 class="ui header">Basic Auth Credential</h3> <div class="scrolling content ui form"> <div id="inlineEditBasicAuthCredentials" class="field"> <p>Enter the username and password for allowing them to access this proxy endpoint</p> <table class="ui very basic compacted unstackable celled table"> <thead> <tr> <th>Username</th> <th>Password</th> <th>Remove</th> </tr></thead> <tbody id="inlineEditBasicAuthCredentialTable"> <tr> <td colspan="3"><i class="ui green circle check icon"></i> No Entered Credential</td> </tr> </tbody> </table> <div class="three small fields credentialEntry"> <div class="field"> <input id="inlineEditBasicAuthCredUsername" type="text" placeholder="Username" autocomplete="off"> </div> <div class="field"> <input id="inlineEditBasicAuthCredPassword" type="password" placeholder="Password" autocomplete="off"> </div> <div class="field" > <button class="ui basic button" onclick="addCredentialsToEditingList();"><i class="green add icon"></i> Add Credential</button> </div> <div class="ui divider"></div> </div> </div> </div> <div class="ui divider"></div> <h3 class="ui header">Authentication Exclusion Paths</h3> <div class="scrolling content ui form"> <p>Exclude specific directories / paths which contains the following subpath prefix from authentication. Useful if you are hosting services require remote API access.</p> <table class="ui very basic compacted unstackable celled table"> <thead> <tr> <th>Path Prefix</th> <th>Remove</th> </tr></thead> <tbody id="exclusionPaths"> <tr> <td colspan="2"><i class="ui green circle check icon"></i> No Path Excluded</td> </tr> </tbody> </table> <div class="field"> <input id="newExclusionPath" type="text" placeholder="/public/api/" autocomplete="off"> <small>Make sure you add the tailing slash for only selecting the files / folder inside that path.</small> </div> <div class="field" > <button class="ui basic button" onclick="addExceptionPath();"><i class="yellow add icon"></i> Add Exception</button> </div> <div class="field"> <div class="ui basic message"> <h4>How to use set excluded paths?</h4> <p>All request URI that contains the given prefix will be allowed to bypass authentication and <b>the prefix must start with a slash.</b> For example, given the following prefix.<br> <code>/public/res/</code><br> <br> Zoraxy will allow authentication bypass of any subdirectories or resources under the /public/res/ directory. For example, the following paths access will be able to bypass basic auth mechanism under this setting.<br> <code>/public/res/photo.png</code><br> <code>/public/res/far/boo/</code></p> </div> </div> <div class="ui divider"></div> <div class="field" > <button class="ui basic button" style="float: right;" onclick="closeThisWrapper();">Close</button> </div> </div> <br><br><br><br> </div> <script> let editingCredentials = []; let editingEndpoint = {}; if (window.location.hash.length > 1){ let payloadHash = window.location.hash.substr(1); try{ payloadHash = JSON.parse(decodeURIComponent(payloadHash)); loadBasicAuthCredentials(payloadHash.ep); $("#epname").text(payloadHash.ep); editingEndpoint = payloadHash; }catch(ex){ console.log("Unable to load endpoint data from hash") } } function loadBasicAuthCredentials(uuid){ $.ajax({ url: "/api/proxy/updateCredentials", method: "GET", data: { ep: uuid, }, success: function(data){ //Push the existing account to list for(var i = 0; i < data.length; i++){ // Create a new credential object var credential = { username: data[i], password: "" }; // Add the credential to the global credentials array editingCredentials.push(credential); } console.log(data); updateEditingCredentialList(); } }) } function addCredentialsToEditingList() { // Retrieve the username and password input values var username = $('#inlineEditBasicAuthCredUsername').val(); var password = $('#inlineEditBasicAuthCredPassword').val(); if(username == "" || password == ""){ parent.msgbox("Username or password cannot be empty", false, 5000); return; } if (alreadyExists(username)){ parent.msgbox("Credential with same username already exists", false, 5000); return; } // Create a new credential object var credential = { username: username, password: password }; // Add the credential to the global credentials array editingCredentials.push(credential); // Clear the input fields $('#inlineEditBasicAuthCredUsername').val(''); $('#inlineEditBasicAuthCredPassword').val(''); // Update the table body with the credentials updateEditingCredentialList(); //Save the table saveCredentials(); } function addExceptionPath(){ // Retrieve the username and password input values var newExclusionPathMatchingPrefix = $('#newExclusionPath').val().trim(); if (newExclusionPathMatchingPrefix == ""){ parent.msgbox("Matching prefix cannot be empty!", false, 5000); return; } $.cjax({ url: "/api/proxy/auth/exceptions/add", data:{ ep: editingEndpoint.ep, prefix: newExclusionPathMatchingPrefix }, method: "POST", success: function(data){ if (data.error != undefined){ parent.msgbox(data.error, false, 5000); }else{ initExceptionPaths(); parent.msgbox("New exception path added", true); $('#newExclusionPath').val(""); } } }); } function removeExceptionPath(object){ let matchingPrefix = $(object).attr("prefix"); $.cjax({ url: "/api/proxy/auth/exceptions/delete", data:{ ep: editingEndpoint.ep, prefix: matchingPrefix }, method: "POST", success: function(data){ if (data.error != undefined){ parent.msgbox(data.error, false, 5000); }else{ initExceptionPaths(); parent.msgbox("Exception path removed", true); } } }); } //Load exception paths from server function initExceptionPaths(){ $.get(`/api/proxy/auth/exceptions/list?ptype=${editingEndpoint.ept}&ep=${editingEndpoint.ep}`, function(data){ if (data.error != undefined){ parent.msgbox(data.error, false, 5000); }else{ if (data.length == 0){ $("#exclusionPaths").html(` <tr> <td colspan="2"><i class="ui green circle check icon"></i> No Path Excluded</td> </tr>`); }else{ $("#exclusionPaths").html(""); data.forEach(function(rule){ $("#exclusionPaths").append(` <tr> <td>${rule.PathPrefix}</td> <td><button class="ui red basic mini icon button" onclick="removeExceptionPath(this);" prefix="${rule.PathPrefix}"><i class="ui red times icon"></i></button></td> </tr>`); }) } } }); } initExceptionPaths(); function updateEditingCredentialList() { var tableBody = $('#inlineEditBasicAuthCredentialTable'); tableBody.empty(); if (editingCredentials.length === 0) { tableBody.append('<tr><td colspan="3"><i class="ui green circle check icon"></i> No Entered Credential</td></tr>'); } else { for (var i = 0; i < editingCredentials.length; i++) { var credential = editingCredentials[i]; var username = credential.username; var password = credential.password.replace(/./g, '*'); // Replace each character with '*' if (credential.password == ""){ password = `<span style="color: #c9c9c9;"><i class="eye slash outline icon"></i> Hidden<span>`; } var row = '<tr>' + '<td>' + username + '</td>' + '<td>' + password + '</td>' + '<td><button class="ui basic button" onclick="removeCredentialFromEditingList(' + i + ');"><i class="red remove icon"></i> Remove</button></td>' + '</tr>'; tableBody.append(row); } } } function removeCredentialFromEditingList(index) { // Remove the credential from the credentials array editingCredentials.splice(index, 1); // Update the table body updateEditingCredentialList(); saveCredentials(); } function alreadyExists(username){ let isExists = false; editingCredentials.forEach(function(cred){ if (cred.username == username){ isExists = true; } }); return isExists; } function closeThisWrapper(){ parent.hideSideWrapper(true); } function saveCredentials(){ $.cjax({ url: "/api/proxy/updateCredentials", method: "POST", data: { ep: editingEndpoint.ep, creds: JSON.stringify(editingCredentials) }, success: function(data){ if (data.error != undefined){ parent.msgbox(data.error, false, 6000); }else{ parent.msgbox("Credentials Updated"); //parent.hideSideWrapper(true); } } }) } </script> </body> </html>