mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-06 23:57:21 +02:00

- Moved virtual directory into host routing object - Generalized root and hosts routing struct - Optimized UI
311 lines
14 KiB
HTML
311 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<!-- Notes: This should be open in its original path-->
|
|
<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>
|
|
</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;
|
|
}
|
|
$.ajax({
|
|
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");
|
|
$.ajax({
|
|
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(){
|
|
$.ajax({
|
|
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> |