mirror of
				https://github.com/eduardogsilva/wireguard_webadmin.git
				synced 2025-10-31 10:36:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			218 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| {% extends "base.html" %}
 | |
| 
 | |
| {% block content %}
 | |
| {% if wireguard_instances %}
 | |
| <div class="card card-primary card-outline">
 | |
|     
 | |
|     <div class="card-body">
 | |
|         <ul class="nav nav-tabs"  role="tablist">
 | |
|             {% for wgconf in wireguard_instances %}
 | |
|             <li class="nav-item">
 | |
|                 <a class="nav-link {%if wgconf == current_instance%}active{%endif%}" href="/peer/list/?uuid={{wgconf.uuid}}" role="tab" >
 | |
|                     wg{{wgconf.instance_id}} {%if wgconf.name %}({{wgconf.name}}){%endif%}
 | |
|                 </a>
 | |
|             </li>
 | |
|             {% endfor %}
 | |
|             
 | |
|           </ul>
 | |
|         <div class="tab-content" id="custom-content-below-tabContent">
 | |
|             <div class="tab-pane fade show active" id="custom-content-below-home" role="tabpanel" aria-labelledby="custom-content-below-home-tab">
 | |
|                 <div class="row">
 | |
|                     {% for peer in peer_list %}
 | |
|                     <div class="col-md-6" id="peer-{{ peer.public_key }}">
 | |
|                         <div class="callout">
 | |
|                             <div class="d-flex justify-content-between align-items-start">
 | |
|                                 <h5>
 | |
|                                     {% if peer.name %}
 | |
|                                     {{ peer.name}}
 | |
|                                     {% else %}
 | |
|                                     {{ peer.public_key|slice:":16" }}{% if peer.public_key|length > 16 %}...{% endif %}
 | |
|                                     {% endif %}
 | |
|                                 </h5><span>
 | |
|                                 <a href="javascript:void(0);" onclick="openImageLightbox('/tools/download_peer_config/?uuid={{ peer.uuid }}&format=qrcode');"><i class="fas fa-qrcode"></i></a>
 | |
|                                 <a href="/tools/download_peer_config/?uuid={{ peer.uuid }}"><i class="fas fa-download"></i></a>
 | |
|                                 <a href="/peer/manage/?peer={{ peer.uuid }}"><i class="far fa-edit"></i></a></span>
 | |
|                             </div>
 | |
|                             {% comment %}This needs to be improved{% endcomment %}
 | |
|                             <p>
 | |
|                                 <b>Transfer:</b> <span id="peer-transfer-{{ peer.public_key }}"></span><br>
 | |
|                                 <b>Latest Handshake:</b> <span id="peer-latest-handshake-{{ peer.public_key }}"></span> <span style="display: none;" id="peer-stored-latest-handshake-{{ peer.public_key }}">{% if peer.peerstatus.last_handshake %}{{ peer.peerstatus.last_handshake|date:"U" }}{% else %}0{% endif %}</span><br>
 | |
|                                 <b>Endpoints:</b> <span id="peer-endpoints-{{ peer.public_key }}"></span><br>
 | |
|                                 <b>Allowed IPs: </b><span id="peer-allowed-ips-{{ peer.public_key }}">
 | |
|                                     {% for address in peer.peerallowedip_set.all %}
 | |
|                                         {% if address.priority == 0 and address.config_file == 'server' %}{{ address }}{% endif %}
 | |
|                                     {% endfor %}
 | |
|                                     {% for address in peer.peerallowedip_set.all %}
 | |
|                                         {% if address.priority >= 1 and address.config_file == 'server' %}{{ address }}{% endif %}
 | |
|                                     {% endfor %}
 | |
|                                 </span>
 | |
|                             </p>
 | |
|                         </div>
 | |
|                         
 | |
|                         
 | |
|                     </div>
 | |
| 
 | |
|                     {% endfor %}
 | |
| 
 | |
|                 </div>
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|                 <a class="btn btn-primary" href="/peer/manage/?instance={{ current_instance.uuid}}">Create Peer</a>
 | |
|                 <a class="btn btn-outline-primary disabled" href="/peer/import_peers/?instance={{ current_instance.uuid}}" title='teste'>Import peers</a>
 | |
|                 </div>
 | |
|         </div>
 | |
|       
 | |
|     </div>
 | |
| </div>
 | |
|     <script>
 | |
|         function openCommandDialog(element) {
 | |
|             var command = element.getAttribute('data-command');
 | |
|             var confirmation = prompt("Please type 'delete wg{{ current_instance.instance_id }}' to remove the configuration.");
 | |
|             if (confirmation) {
 | |
|                 var url = "?uuid={{current_instance.uuid}}&action=delete&confirmation=" + encodeURIComponent(confirmation);
 | |
|                 window.location.href = url;
 | |
|             }
 | |
|         }
 | |
|     </script>
 | |
| {% else %}
 | |
| 
 | |
| <div class="alert alert-warning" role="alert">
 | |
|     <h4 class="alert-heading">No WireGuard Instances Found</h4>
 | |
|     <p>There are no WireGuard instances configured. You can add a new instance by clicking the button below.</p>
 | |
| </div>
 | |
| <p>
 | |
|     <a href="/server/manage/" class="btn btn-primary">Add WireGuard Instance</a>
 | |
| </p>
 | |
| {% endif %}
 | |
| 
 | |
| 
 | |
| 
 | |
| {% endblock %}
 | |
| 
 | |
| 
 | |
| {% block custom_page_scripts %}
 | |
| 
 | |
| <script>
 | |
|     document.addEventListener('DOMContentLoaded', function() {
 | |
|         //const fetchWireguardStatus = async () => {
 | |
|         //    try {
 | |
|         //        const response = await fetch('/api/wireguard_status/');
 | |
|         //        const data = await response.json();
 | |
|         //        updateUI(data);
 | |
|         //    } catch (error) {
 | |
|         //        console.error('Error fetching Wireguard status:', error);
 | |
|         //    }
 | |
|         //};
 | |
|         const fetchWireguardStatus = async () => {
 | |
|             try {
 | |
|                 const response = await fetch('/api/wireguard_status/');
 | |
|                 let data = await response.json();
 | |
| 
 | |
|                 // if latest-handshakes is 0, use the stored value
 | |
|                 for (const [interfaceName, peers] of Object.entries(data)) {
 | |
|                     for (const [peerId, peerInfo] of Object.entries(peers)) {
 | |
|                         const peerElementId = `peer-stored-latest-handshake-${peerId}`;
 | |
|                         const storedHandshakeElement = document.getElementById(peerElementId);
 | |
|                         if (peerInfo['latest-handshakes'] === '0' && storedHandshakeElement) {
 | |
|                             peerInfo['latest-handshakes'] = storedHandshakeElement.textContent;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|         
 | |
|                 updateUI(data);
 | |
|             } catch (error) {
 | |
|                 console.error('Error fetching Wireguard status:', error);
 | |
|             }
 | |
|         };
 | |
|     
 | |
|         fetchWireguardStatus();
 | |
|         setInterval(fetchWireguardStatus, {{ current_instance.peer_list_refresh_interval }} * 1000);
 | |
|     });
 | |
|     
 | |
|     const updateUI = (data) => {
 | |
|         for (const [interfaceName, peers] of Object.entries(data)) {
 | |
|             for (const [peerId, peerInfo] of Object.entries(peers)) {
 | |
|                 const peerDiv = document.getElementById(`peer-${peerId}`);
 | |
|                 if (peerDiv) {
 | |
|                     updatePeerInfo(peerDiv, peerId, peerInfo);
 | |
|                     updateCalloutClass(peerDiv, peerInfo['latest-handshakes']);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     };
 | |
|     
 | |
|     const updatePeerInfo = (peerDiv, peerId, peerInfo) => {
 | |
|         const escapedPeerId = peerId.replace(/([!"#$%&'()*+,.\/:;<=>?@[\]^`{|}~])/g, '\\$1');
 | |
|         const transfer = peerDiv.querySelector(`#peer-transfer-${escapedPeerId}`);
 | |
|         const latestHandshake = peerDiv.querySelector(`#peer-latest-handshake-${escapedPeerId}`);
 | |
|         const endpoints = peerDiv.querySelector(`#peer-endpoints-${escapedPeerId}`);
 | |
|         const allowedIps = peerDiv.querySelector(`#peer-allowed-ips-${escapedPeerId}`);
 | |
|     
 | |
|         transfer.textContent = `${convertBytes(peerInfo.transfer.tx)} TX, ${convertBytes(peerInfo.transfer.rx)} RX`;
 | |
|         latestHandshake.textContent = `${peerInfo['latest-handshakes'] !== '0' ? new Date(parseInt(peerInfo['latest-handshakes']) * 1000).toLocaleString() : '0'}`;
 | |
|         endpoints.textContent = `${peerInfo.endpoints}`;
 | |
|         checkAllowedIps(allowedIps, peerInfo['allowed-ips']);
 | |
|     };
 | |
|     
 | |
|     const convertBytes = (bytes) => {
 | |
|         if (bytes === 0) return '0 Bytes';
 | |
|         const k = 1024;
 | |
|         const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
 | |
|         const i = Math.floor(Math.log(bytes) / Math.log(k));
 | |
|         return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
 | |
|     };
 | |
|     
 | |
|     const checkAllowedIps = (allowedIpsElement, allowedIpsApiResponse) => {
 | |
|         const apiIps = allowedIpsApiResponse[0].split(' ');
 | |
|         const htmlIpsText = allowedIpsElement.textContent.trim();
 | |
|         const htmlIpsArray = htmlIpsText.match(/\b(?:\d{1,3}\.){3}\d{1,3}\/\d{1,2}\b/g);
 | |
|     
 | |
|         allowedIpsElement.innerHTML = '';
 | |
|         htmlIpsArray.forEach((ip, index, array) => {
 | |
|             const ipSpan = document.createElement('span');
 | |
|             ipSpan.textContent = ip;
 | |
|             allowedIpsElement.appendChild(ipSpan);
 | |
| 
 | |
|             if (!apiIps.includes(ip)) {
 | |
|                 ipSpan.style.color = 'red';
 | |
|                 ipSpan.style.textDecoration = 'underline';
 | |
|                 ipSpan.title = 'This address does not appear in the wg show command output, likely indicating that another peer has an IP overlapping this network or that the configuration file is outdated.';
 | |
|             }
 | |
| 
 | |
|             if (index < array.length - 1) {
 | |
|                 allowedIpsElement.appendChild(document.createTextNode(', '));
 | |
|             }
 | |
|         });
 | |
|     };
 | |
|     
 | |
|     const updateCalloutClass = (peerDiv, latestHandshake) => {
 | |
|         const calloutDiv = peerDiv.querySelector('.callout');
 | |
|         calloutDiv.classList.remove('callout-success', 'callout-info', 'callout-warning', 'callout-danger');
 | |
|         const handshakeAge = Date.now() / 1000 - parseInt(latestHandshake);
 | |
|     
 | |
|         if (latestHandshake === '0') {
 | |
|             calloutDiv.classList.add('callout-danger');
 | |
|         } else if (handshakeAge < 600) {
 | |
|             calloutDiv.classList.add('callout-success');
 | |
|         } else if (handshakeAge < 1800) {
 | |
|             calloutDiv.classList.add('callout-info');
 | |
|         } else if (handshakeAge < 21600) {
 | |
|             calloutDiv.classList.add('callout-warning');
 | |
|         }
 | |
|     
 | |
|         calloutDiv.style.transition = 'all 5s';
 | |
|     };
 | |
|     </script>
 | |
| 
 | |
| <script>
 | |
|     function openImageLightbox(url) {
 | |
|       window.open(url, 'Image', 'width=500,height=500,toolbar=0,location=0,menubar=0');
 | |
|     }
 | |
| </script>
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| {% endblock %} |