diff --git a/cmd/subspace/config.go b/cmd/subspace/config.go index 5624ba2a..4e1ce2c6 100644 --- a/cmd/subspace/config.go +++ b/cmd/subspace/config.go @@ -210,18 +210,12 @@ func (c *Config) UpdateProfile(id string, fn func(*Profile) error) error { return c.save() } -func (c *Config) AddProfile(userID, name, platform string, ipspeer string, allowedips string) (Profile, error) { +func (c *Config) AddProfile(number int, userID, name, platform, ipspeer, allowedips string) (Profile, error) { c.Lock() defer c.Unlock() id := RandomString(16) - number := 2 // MUST start at 2 - for _, p := range c.Profiles { - if p.Number >= number { - number = p.Number + 1 - } - } profile := Profile{ ID: id, UserID: userID, diff --git a/cmd/subspace/handlers.go b/cmd/subspace/handlers.go index 31273fbe..48752149 100644 --- a/cmd/subspace/handlers.go +++ b/cmd/subspace/handlers.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "regexp" + "sort" "strings" "github.com/crewjam/saml/samlsp" @@ -412,7 +413,8 @@ func profileAddHandler(w *Web) { //if len(config.ListProfiles()) >= maxProfiles { // Check whether there is a room to assign new IP address or not. - if _, _, err := wgConfig.generateIPAddr(uint32(len(config.ListProfiles()))); err != nil { + firstFreeID := FindFirstFreeID(config.Profiles) + if _, _, err := wgConfig.generateIPAddr(firstFreeID); err != nil { w.Redirect("/?error=addprofile") return } @@ -422,7 +424,7 @@ func profileAddHandler(w *Web) { return } } - profile, err := config.AddProfile(userID, name, platform, ipspeer, allowedips) + profile, err := config.AddProfile(int(firstFreeID), userID, name, platform, ipspeer, allowedips) if err != nil { logger.Warn(err) w.Redirect("/?error=addprofile") diff --git a/cmd/subspace/helpers.go b/cmd/subspace/helpers.go new file mode 100644 index 00000000..4ab5a292 --- /dev/null +++ b/cmd/subspace/helpers.go @@ -0,0 +1,34 @@ +package main + +import "sort" + +func FindFirstFreeID(profiles []*Profile) uint32 { + profileIDs := getProfileIDs(profiles) + sort.Slice(profileIDs, func(i, j int) bool { + return profileIDs[i] < profileIDs[j] + }) + + const minID = 2 + if len(profileIDs) == 0 { + return minID + } + maxID := profileIDs[len(profileIDs)-1] + freeID := uint32(maxID + 1) + for i := minID; i < maxID; i++ { + if i != profileIDs[i-minID] { + freeID = uint32(i) + break + } + } + + return freeID +} + +func getProfileIDs(profiles []*Profile) []int { + var profileIDs = make([]int, len(profiles)) + for i, profile := range profiles { + profileIDs[i] = profile.Number + } + + return profileIDs +}