diff --git a/handler/routes.go b/handler/routes.go
index 11ec048..780d463 100644
--- a/handler/routes.go
+++ b/handler/routes.go
@@ -988,6 +988,13 @@ func MachineIPAddresses() echo.HandlerFunc {
}
}
+// GetOrderedSubnetRanges handler to get the ordered list of subnet ranges
+func GetOrderedSubnetRanges() echo.HandlerFunc {
+ return func(c echo.Context) error {
+ return c.JSON(http.StatusOK, util.SubnetRangesOrder)
+ }
+}
+
// SuggestIPAllocation handler to get the list of ip address for client
func SuggestIPAllocation(db store.IStore) echo.HandlerFunc {
return func(c echo.Context) error {
@@ -1009,15 +1016,27 @@ func SuggestIPAllocation(db store.IStore) echo.HandlerFunc {
false, "Cannot suggest ip allocation: failed to get list of allocated ip addresses",
})
}
- for _, cidr := range server.Interface.Addresses {
- ip, err := util.GetAvailableIP(cidr, allocatedIPs)
+
+ sr := c.QueryParam("sr")
+ searchCIDRList := make([]string, 0)
+ found := false
+
+ // Use subnet range or default to interface addresses
+ if util.SubnetRanges[sr] != nil {
+ for _, cidr := range util.SubnetRanges[sr] {
+ searchCIDRList = append(searchCIDRList, cidr.String())
+ }
+ } else {
+ searchCIDRList = append(searchCIDRList, server.Interface.Addresses...)
+ }
+
+ for _, cidr := range searchCIDRList {
+ ip, err := util.GetAvailableIP(cidr, allocatedIPs, server.Interface.Addresses)
if err != nil {
log.Error("Failed to get available ip from a CIDR: ", err)
- return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{
- false,
- fmt.Sprintf("Cannot suggest ip allocation: failed to get available ip from network %s", cidr),
- })
+ continue
}
+ found = true
if strings.Contains(ip, ":") {
suggestedIPs = append(suggestedIPs, fmt.Sprintf("%s/128", ip))
} else {
@@ -1025,6 +1044,13 @@ func SuggestIPAllocation(db store.IStore) echo.HandlerFunc {
}
}
+ if !found {
+ return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{
+ false,
+ "Cannot suggest ip allocation: failed to get available ip. Try a different subnet or deallocate some ips.",
+ })
+ }
+
return c.JSON(http.StatusOK, suggestedIPs)
}
}
diff --git a/main.go b/main.go
index 4996d89..5f6e341 100644
--- a/main.go
+++ b/main.go
@@ -233,6 +233,7 @@ func main() {
app.GET(util.BasePath+"/api/clients", handler.GetClients(db), handler.ValidSession)
app.GET(util.BasePath+"/api/client/:id", handler.GetClient(db), handler.ValidSession)
app.GET(util.BasePath+"/api/machine-ips", handler.MachineIPAddresses(), handler.ValidSession)
+ app.GET(util.BasePath+"/api/subnet-ranges", handler.GetOrderedSubnetRanges(), handler.ValidSession)
app.GET(util.BasePath+"/api/suggest-client-ips", handler.SuggestIPAllocation(db), handler.ValidSession)
app.POST(util.BasePath+"/api/apply-wg-config", handler.ApplyServerConfig(db, tmplDir), handler.ValidSession, handler.ContentTypeJson)
app.GET(util.BasePath+"/wake_on_lan_hosts", handler.GetWakeOnLanHosts(db), handler.ValidSession)
diff --git a/templates/base.html b/templates/base.html
index c2fa367..bca6ee6 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -209,6 +209,12 @@
+
+
+
+
@@ -368,7 +374,36 @@
$(document).ready(function () {
- $.ajax({
+
+ addGlobalStyle(`
+ .toast-top-right-fix {
+ top: 67px;
+ right: 12px;
+ }
+ `, 'toastrToastStyleFix')
+
+ toastr.options.closeDuration = 100;
+ // toastr.options.timeOut = 10000;
+ toastr.options.positionClass = 'toast-top-right-fix';
+
+ updateApplyConfigVisibility()
+
+ });
+
+ function addGlobalStyle(css, id) {
+ if (!document.querySelector('#' + id)) {
+ let head = document.head
+ if (!head) { return }
+ let style = document.createElement('style')
+ style.type = 'text/css'
+ style.id = id
+ style.innerHTML = css
+ head.appendChild(style)
+ }
+ }
+
+ function updateApplyConfigVisibility() {
+ $.ajax({
cache: false,
method: 'GET',
url: '{{.basePath}}/test-hash',
@@ -388,8 +423,7 @@
toastr.error(responseJson['message']);
}
});
-
- });
+ }
// populateClient function for render new client info
@@ -466,19 +500,32 @@
// updateIPAllocationSuggestion function for automatically fill
// the IP Allocation input with suggested ip addresses
- function updateIPAllocationSuggestion() {
+ function updateIPAllocationSuggestion(forceDefault = false) {
+ let subnetRange = $("#subnet_ranges").select2('val');
+
+ if (forceDefault || !subnetRange || subnetRange.length === 0) {
+ subnetRange = '__default_any__'
+ }
$.ajax({
cache: false,
method: 'GET',
- url: '{{.basePath}}/api/suggest-client-ips',
+ url: `{{.basePath}}/api/suggest-client-ips?sr=${subnetRange}`,
dataType: 'json',
contentType: "application/json",
success: function(data) {
+ const allocated_ips = $("#client_allocated_ips").val().split(",");
+ allocated_ips.forEach(function (item, index) {
+ $('#client_allocated_ips').removeTag(escape(item));
+ })
data.forEach(function (item, index) {
$('#client_allocated_ips').addTag(item);
})
},
error: function(jqXHR, exception) {
+ const allocated_ips = $("#client_allocated_ips").val().split(",");
+ allocated_ips.forEach(function (item, index) {
+ $('#client_allocated_ips').removeTag(escape(item));
+ })
const responseJson = jQuery.parseJSON(jqXHR.responseText);
toastr.error(responseJson['message']);
}
@@ -565,10 +612,17 @@
$("#client_preshared_key").val("");
$("#client_allocated_ips").importTags('');
$("#client_extra_allowed_ips").importTags('');
- updateIPAllocationSuggestion();
+ updateSubnetRangesList();
+ updateIPAllocationSuggestion(true);
});
});
+ // handle subnet range select
+ $('#subnet_ranges').on('select2:select', function (e) {
+ // console.log('Selected Option: ', $("#subnet_ranges").select2('val'));
+ updateIPAllocationSuggestion();
+ });
+
// apply_config_confirm button event
$(document).ready(function () {
$("#apply_config_confirm").click(function () {
@@ -579,6 +633,7 @@
dataType: 'json',
contentType: "application/json",
success: function(data) {
+ updateApplyConfigVisibility()
$("#modal_apply_config").modal('hide');
toastr.success('Applied config successfully');
},
diff --git a/templates/clients.html b/templates/clients.html
index 8b4e4ab..c7a6c96 100644
--- a/templates/clients.html
+++ b/templates/clients.html
@@ -260,6 +260,25 @@ Wireguard Clients
const divElement = document.getElementById("paused_" + clientID);
divElement.style.visibility = "visible";
}
+
+ function updateSubnetRangesList() {
+ $.getJSON("{{.basePath}}/api/subnet-ranges", null, function(data) {
+ console.log(data);
+ $("#subnet_ranges option").remove();
+ $("#subnet_ranges").append(
+ $("")
+ .text("Any")
+ .val("__default_any__")
+ );
+ $.each(data, function(index, item) {
+ $("#subnet_ranges").append(
+ $("")
+ .text(item)
+ .val(item)
+ );
+ });
+ });
+ }