1
0

basicAuthEditor.html 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <!-- Notes: This should be open in its original path-->
  5. <meta charset="utf-8">
  6. <link rel="stylesheet" href="../script/semantic/semantic.min.css">
  7. <script src="../script/jquery-3.6.0.min.js"></script>
  8. <script src="../script/semantic/semantic.min.js"></script>
  9. </head>
  10. <body>
  11. <br>
  12. <div class="ui container">
  13. <div class="ui header">
  14. <div class="content">
  15. Basic Auth Settings
  16. <div class="sub header" id="epname"></div>
  17. </div>
  18. </div>
  19. <div class="ui divider"></div>
  20. <h3 class="ui header">Basic Auth Credential</h3>
  21. <div class="scrolling content ui form">
  22. <div id="inlineEditBasicAuthCredentials" class="field">
  23. <p>Enter the username and password for allowing them to access this proxy endpoint</p>
  24. <table class="ui very basic compacted unstackable celled table">
  25. <thead>
  26. <tr>
  27. <th>Username</th>
  28. <th>Password</th>
  29. <th>Remove</th>
  30. </tr></thead>
  31. <tbody id="inlineEditBasicAuthCredentialTable">
  32. <tr>
  33. <td colspan="3"><i class="ui green circle check icon"></i> No Entered Credential</td>
  34. </tr>
  35. </tbody>
  36. </table>
  37. <div class="three small fields credentialEntry">
  38. <div class="field">
  39. <input id="inlineEditBasicAuthCredUsername" type="text" placeholder="Username" autocomplete="off">
  40. </div>
  41. <div class="field">
  42. <input id="inlineEditBasicAuthCredPassword" type="password" placeholder="Password" autocomplete="off">
  43. </div>
  44. <div class="field" >
  45. <button class="ui basic button" onclick="addCredentialsToEditingList();"><i class="green add icon"></i> Add Credential</button>
  46. </div>
  47. <div class="ui divider"></div>
  48. </div>
  49. </div>
  50. </div>
  51. <div class="ui divider"></div>
  52. <h3 class="ui header">Authentication Exclusion Paths</h3>
  53. <div class="scrolling content ui form">
  54. <p>Exclude specific directories / paths which contains the following subpath prefix from authentication. Useful if you are hosting services require remote API access.</p>
  55. <table class="ui very basic compacted unstackable celled table">
  56. <thead>
  57. <tr>
  58. <th>Path Prefix</th>
  59. <th>Remove</th>
  60. </tr></thead>
  61. <tbody id="exclusionPaths">
  62. <tr>
  63. <td colspan="2"><i class="ui green circle check icon"></i> No Path Excluded</td>
  64. </tr>
  65. </tbody>
  66. </table>
  67. <div class="field">
  68. <input id="newExclusionPath" type="text" placeholder="/public/api/" autocomplete="off">
  69. <small>Make sure you add the tailing slash for only selecting the files / folder inside that path.</small>
  70. </div>
  71. <div class="field" >
  72. <button class="ui basic button" onclick="addExceptionPath();"><i class="yellow add icon"></i> Add Exception</button>
  73. </div>
  74. <div class="field">
  75. <div class="ui basic message">
  76. <h4>How to use set excluded paths?</h4>
  77. <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>
  78. <code>/public/res/</code><br>
  79. <br>
  80. 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>
  81. <code>/public/res/photo.png</code><br>
  82. <code>/public/res/far/boo/</code></p>
  83. </div>
  84. </div>
  85. <div class="ui divider"></div>
  86. <div class="field" >
  87. <button class="ui basic button" style="float: right;" onclick="closeThisWrapper();">Close</button>
  88. </div>
  89. </div>
  90. <br><br><br><br>
  91. </div>
  92. <script>
  93. let editingCredentials = [];
  94. let editingEndpoint = {};
  95. if (window.location.hash.length > 1){
  96. let payloadHash = window.location.hash.substr(1);
  97. try{
  98. payloadHash = JSON.parse(decodeURIComponent(payloadHash));
  99. loadBasicAuthCredentials(payloadHash.ep);
  100. $("#epname").text(payloadHash.ep);
  101. editingEndpoint = payloadHash;
  102. }catch(ex){
  103. console.log("Unable to load endpoint data from hash")
  104. }
  105. }
  106. function loadBasicAuthCredentials(uuid){
  107. $.ajax({
  108. url: "/api/proxy/updateCredentials",
  109. method: "GET",
  110. data: {
  111. ep: uuid,
  112. },
  113. success: function(data){
  114. //Push the existing account to list
  115. for(var i = 0; i < data.length; i++){
  116. // Create a new credential object
  117. var credential = {
  118. username: data[i],
  119. password: ""
  120. };
  121. // Add the credential to the global credentials array
  122. editingCredentials.push(credential);
  123. }
  124. console.log(data);
  125. updateEditingCredentialList();
  126. }
  127. })
  128. }
  129. function addCredentialsToEditingList() {
  130. // Retrieve the username and password input values
  131. var username = $('#inlineEditBasicAuthCredUsername').val();
  132. var password = $('#inlineEditBasicAuthCredPassword').val();
  133. if(username == "" || password == ""){
  134. parent.msgbox("Username or password cannot be empty", false, 5000);
  135. return;
  136. }
  137. if (alreadyExists(username)){
  138. parent.msgbox("Credential with same username already exists", false, 5000);
  139. return;
  140. }
  141. // Create a new credential object
  142. var credential = {
  143. username: username,
  144. password: password
  145. };
  146. // Add the credential to the global credentials array
  147. editingCredentials.push(credential);
  148. // Clear the input fields
  149. $('#inlineEditBasicAuthCredUsername').val('');
  150. $('#inlineEditBasicAuthCredPassword').val('');
  151. // Update the table body with the credentials
  152. updateEditingCredentialList();
  153. //Save the table
  154. saveCredentials();
  155. }
  156. function addExceptionPath(){
  157. // Retrieve the username and password input values
  158. var newExclusionPathMatchingPrefix = $('#newExclusionPath').val().trim();
  159. if (newExclusionPathMatchingPrefix == ""){
  160. parent.msgbox("Matching prefix cannot be empty!", false, 5000);
  161. return;
  162. }
  163. $.ajax({
  164. url: "/api/proxy/auth/exceptions/add",
  165. data:{
  166. ep: editingEndpoint.ep,
  167. prefix: newExclusionPathMatchingPrefix
  168. },
  169. method: "POST",
  170. success: function(data){
  171. if (data.error != undefined){
  172. parent.msgbox(data.error, false, 5000);
  173. }else{
  174. initExceptionPaths();
  175. parent.msgbox("New exception path added", true);
  176. $('#newExclusionPath').val("");
  177. }
  178. }
  179. });
  180. }
  181. function removeExceptionPath(object){
  182. let matchingPrefix = $(object).attr("prefix");
  183. $.ajax({
  184. url: "/api/proxy/auth/exceptions/delete",
  185. data:{
  186. ep: editingEndpoint.ep,
  187. prefix: matchingPrefix
  188. },
  189. method: "POST",
  190. success: function(data){
  191. if (data.error != undefined){
  192. parent.msgbox(data.error, false, 5000);
  193. }else{
  194. initExceptionPaths();
  195. parent.msgbox("Exception path removed", true);
  196. }
  197. }
  198. });
  199. }
  200. //Load exception paths from server
  201. function initExceptionPaths(){
  202. $.get(`/api/proxy/auth/exceptions/list?ptype=${editingEndpoint.ept}&ep=${editingEndpoint.ep}`, function(data){
  203. if (data.error != undefined){
  204. parent.msgbox(data.error, false, 5000);
  205. }else{
  206. if (data.length == 0){
  207. $("#exclusionPaths").html(` <tr>
  208. <td colspan="2"><i class="ui green circle check icon"></i> No Path Excluded</td>
  209. </tr>`);
  210. }else{
  211. $("#exclusionPaths").html("");
  212. data.forEach(function(rule){
  213. $("#exclusionPaths").append(` <tr>
  214. <td>${rule.PathPrefix}</td>
  215. <td><button class="ui red basic mini icon button" onclick="removeExceptionPath(this);" prefix="${rule.PathPrefix}"><i class="ui red times icon"></i></button></td>
  216. </tr>`);
  217. })
  218. }
  219. }
  220. });
  221. }
  222. initExceptionPaths();
  223. function updateEditingCredentialList() {
  224. var tableBody = $('#inlineEditBasicAuthCredentialTable');
  225. tableBody.empty();
  226. if (editingCredentials.length === 0) {
  227. tableBody.append('<tr><td colspan="3"><i class="ui green circle check icon"></i> No Entered Credential</td></tr>');
  228. } else {
  229. for (var i = 0; i < editingCredentials.length; i++) {
  230. var credential = editingCredentials[i];
  231. var username = credential.username;
  232. var password = credential.password.replace(/./g, '*'); // Replace each character with '*'
  233. if (credential.password == ""){
  234. password = `<span style="color: #c9c9c9;"><i class="eye slash outline icon"></i> Hidden<span>`;
  235. }
  236. var row = '<tr>' +
  237. '<td>' + username + '</td>' +
  238. '<td>' + password + '</td>' +
  239. '<td><button class="ui basic button" onclick="removeCredentialFromEditingList(' + i + ');"><i class="red remove icon"></i> Remove</button></td>' +
  240. '</tr>';
  241. tableBody.append(row);
  242. }
  243. }
  244. }
  245. function removeCredentialFromEditingList(index) {
  246. // Remove the credential from the credentials array
  247. editingCredentials.splice(index, 1);
  248. // Update the table body
  249. updateEditingCredentialList();
  250. saveCredentials();
  251. }
  252. function alreadyExists(username){
  253. let isExists = false;
  254. editingCredentials.forEach(function(cred){
  255. if (cred.username == username){
  256. isExists = true;
  257. }
  258. });
  259. return isExists;
  260. }
  261. function closeThisWrapper(){
  262. parent.hideSideWrapper(true);
  263. }
  264. function saveCredentials(){
  265. $.ajax({
  266. url: "/api/proxy/updateCredentials",
  267. method: "POST",
  268. data: {
  269. ep: editingEndpoint.ep,
  270. creds: JSON.stringify(editingCredentials)
  271. },
  272. success: function(data){
  273. if (data.error != undefined){
  274. parent.msgbox(data.error, false, 6000);
  275. }else{
  276. parent.msgbox("Credentials Updated");
  277. //parent.hideSideWrapper(true);
  278. }
  279. }
  280. })
  281. }
  282. </script>
  283. </body>
  284. </html>