mirror of
https://github.com/DJSundog/wg-portal.git
synced 2024-11-27 09:00:03 -05:00
wip: create/update/...
This commit is contained in:
parent
ea65e6b43c
commit
cc06019738
@ -34,10 +34,12 @@
|
|||||||
|
|
||||||
<form method="post" enctype="multipart/form-data">
|
<form method="post" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="uid" value="{{.Peer.UID}}">
|
<input type="hidden" name="uid" value="{{.Peer.UID}}">
|
||||||
|
<input type="hidden" name="privkey" value="{{.Peer.PrivateKey}}">
|
||||||
|
<input type="hidden" name="presharedkey" value="{{.Peer.PresharedKey}}">
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group col-md-12">
|
||||||
<label for="inputServerPublicKey">Public Key</label>
|
<label for="inputServerPublicKey">Public Key</label>
|
||||||
<input type="text" name="pkey" disabled class="form-control" id="inputServerPublicKey" value="{{.Peer.PublicKey}}">
|
<input type="text" name="pubkey" readonly class="form-control" id="inputServerPublicKey" value="{{.Peer.PublicKey}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
|
@ -30,11 +30,12 @@
|
|||||||
|
|
||||||
<form method="post" enctype="multipart/form-data">
|
<form method="post" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="device" value="{{.Device.DeviceName}}">
|
<input type="hidden" name="device" value="{{.Device.DeviceName}}">
|
||||||
|
<input type="hidden" name="privkey" value="{{.Device.PrivateKey}}">
|
||||||
<h3>Server's interface configuration</h3>
|
<h3>Server's interface configuration</h3>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group col-md-12">
|
||||||
<label for="inputServerPublicKey">Public Key</label>
|
<label for="inputServerPublicKey">Public Key</label>
|
||||||
<input type="text" name="pubkey" disabled class="form-control" id="inputServerPublicKey" value="{{.Device.PublicKey}}">
|
<input type="text" name="pubkey" readonly class="form-control" id="inputServerPublicKey" value="{{.Device.PublicKey}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
<body id="page-top">
|
<body id="page-top">
|
||||||
{{template "prt_nav.html" .}}
|
{{template "prt_nav.html" .}}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>WireGuard VPN Administration</h1>
|
<h1 class="mt-2">WireGuard VPN Administration</h1>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
@ -77,9 +77,16 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div></div>
|
<div class="mt-4 row">
|
||||||
|
<div class="col-sm-10 col-12">
|
||||||
<h2>Current VPN Users</h2>
|
<h2>Current VPN Users</h2>
|
||||||
<div class="table-responsive">
|
</div>
|
||||||
|
<div class="col-sm-2 col-12">
|
||||||
|
<a href="/admin/peer/create" title="Add a LDAP user" class="btn btn-primary pull-right"><i class="fa fa-fw fa-user-plus"></i></a>
|
||||||
|
<a href="/admin/peer/create" title="Manual add a user" class="btn btn-primary pull-right"><i class="fa fa-fw fa-plus"></i>M</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 table-responsive">
|
||||||
<table class="table table-sm" id="userTable">
|
<table class="table table-sm" id="userTable">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
1
go.mod
1
go.mod
@ -7,6 +7,7 @@ require (
|
|||||||
github.com/gin-gonic/contrib v0.0.0-20201005132743-ca038bbf2944
|
github.com/gin-gonic/contrib v0.0.0-20201005132743-ca038bbf2944
|
||||||
github.com/gin-gonic/gin v1.6.3
|
github.com/gin-gonic/gin v1.6.3
|
||||||
github.com/go-ldap/ldap/v3 v3.2.4
|
github.com/go-ldap/ldap/v3 v3.2.4
|
||||||
|
github.com/go-playground/validator/v10 v10.2.0
|
||||||
github.com/gorilla/sessions v1.2.1 // indirect
|
github.com/gorilla/sessions v1.2.1 // indirect
|
||||||
github.com/kelseyhightower/envconfig v1.4.0
|
github.com/kelseyhightower/envconfig v1.4.0
|
||||||
github.com/sirupsen/logrus v1.7.0
|
github.com/sirupsen/logrus v1.7.0
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// BroadcastAddr returns the last address in the given network, or the broadcast address.
|
// BroadcastAddr returns the last address in the given network, or the broadcast address.
|
||||||
func BroadcastAddr(n *net.IPNet) net.IP {
|
func BroadcastAddr(n *net.IPNet) net.IP {
|
||||||
@ -35,3 +38,20 @@ func IsIPv6(address string) bool {
|
|||||||
}
|
}
|
||||||
return ip.To4() == nil
|
return ip.To4() == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseIPList(lst string) []string {
|
||||||
|
ips := strings.Split(lst, ",")
|
||||||
|
validatedIPs := make([]string, 0, len(ips))
|
||||||
|
for i := range ips {
|
||||||
|
ips[i] = strings.TrimSpace(ips[i])
|
||||||
|
if ips[i] != "" {
|
||||||
|
validatedIPs = append(validatedIPs, ips[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return validatedIPs
|
||||||
|
}
|
||||||
|
|
||||||
|
func IPListToString(lst []string) string {
|
||||||
|
return strings.Join(lst, ", ")
|
||||||
|
}
|
||||||
|
@ -38,6 +38,7 @@ type SessionData struct {
|
|||||||
Search string
|
Search string
|
||||||
AlertData string
|
AlertData string
|
||||||
AlertType string
|
AlertType string
|
||||||
|
FormData interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type AlertData struct {
|
type AlertData struct {
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/h44z/wg-portal/internal/common"
|
||||||
|
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -77,72 +80,22 @@ func (s *Server) GetAdminEditInterface(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) PostAdminEditInterface(c *gin.Context) {
|
func (s *Server) PostAdminEditInterface(c *gin.Context) {
|
||||||
device := s.users.GetDevice()
|
var formDevice Device
|
||||||
var err error
|
if err := c.ShouldBind(&formDevice); err != nil {
|
||||||
|
s.setAlert(c, "failed to bind form data: "+err.Error(), "danger")
|
||||||
device.ListenPort, err = strconv.Atoi(c.PostForm("port"))
|
|
||||||
if err != nil {
|
|
||||||
s.setAlert(c, "invalid port: "+err.Error(), "danger")
|
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ipField := c.PostForm("ip")
|
|
||||||
ips := strings.Split(ipField, ",")
|
|
||||||
validatedIPs := make([]string, 0, len(ips))
|
|
||||||
for i := range ips {
|
|
||||||
ips[i] = strings.TrimSpace(ips[i])
|
|
||||||
if ips[i] != "" {
|
|
||||||
validatedIPs = append(validatedIPs, ips[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(validatedIPs) == 0 {
|
|
||||||
s.setAlert(c, "invalid ip address", "danger")
|
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
device.IPs = validatedIPs
|
|
||||||
|
|
||||||
device.Endpoint = c.PostForm("endpoint")
|
|
||||||
|
|
||||||
dnsField := c.PostForm("dns")
|
|
||||||
dns := strings.Split(dnsField, ",")
|
|
||||||
validatedDNS := make([]string, 0, len(dns))
|
|
||||||
for i := range dns {
|
|
||||||
dns[i] = strings.TrimSpace(dns[i])
|
|
||||||
if dns[i] != "" {
|
|
||||||
validatedDNS = append(validatedDNS, dns[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
device.DNS = validatedDNS
|
|
||||||
|
|
||||||
allowedIPField := c.PostForm("allowedip")
|
|
||||||
allowedIP := strings.Split(allowedIPField, ",")
|
|
||||||
validatedAllowedIP := make([]string, 0, len(allowedIP))
|
|
||||||
for i := range allowedIP {
|
|
||||||
allowedIP[i] = strings.TrimSpace(allowedIP[i])
|
|
||||||
if allowedIP[i] != "" {
|
|
||||||
validatedAllowedIP = append(validatedAllowedIP, allowedIP[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
device.AllowedIPs = validatedAllowedIP
|
|
||||||
|
|
||||||
device.Mtu, err = strconv.Atoi(c.PostForm("mtu"))
|
|
||||||
if err != nil {
|
|
||||||
s.setAlert(c, "invalid MTU: "+err.Error(), "danger")
|
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
device.PersistentKeepalive, err = strconv.Atoi(c.PostForm("keepalive"))
|
|
||||||
if err != nil {
|
|
||||||
s.setAlert(c, "invalid PersistentKeepalive: "+err.Error(), "danger")
|
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Clean list input
|
||||||
|
formDevice.IPs = common.ParseIPList(formDevice.IPsStr)
|
||||||
|
formDevice.AllowedIPs = common.ParseIPList(formDevice.AllowedIPsStr)
|
||||||
|
formDevice.DNS = common.ParseIPList(formDevice.DNSStr)
|
||||||
|
formDevice.IPsStr = common.IPListToString(formDevice.IPs)
|
||||||
|
formDevice.AllowedIPsStr = common.IPListToString(formDevice.AllowedIPs)
|
||||||
|
formDevice.DNSStr = common.IPListToString(formDevice.DNS)
|
||||||
|
|
||||||
// Update WireGuard device
|
// Update WireGuard device
|
||||||
err = s.wg.UpdateDevice(device.DeviceName, device.GetDeviceConfig())
|
err := s.wg.UpdateDevice(formDevice.DeviceName, formDevice.GetDeviceConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setAlert(c, "failed to update device in WireGuard: "+err.Error(), "danger")
|
s.setAlert(c, "failed to update device in WireGuard: "+err.Error(), "danger")
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
||||||
@ -150,7 +103,7 @@ func (s *Server) PostAdminEditInterface(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update in database
|
// Update in database
|
||||||
err = s.users.UpdateDevice(device)
|
err = s.users.UpdateDevice(formDevice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setAlert(c, "failed to update device in database: "+err.Error(), "danger")
|
s.setAlert(c, "failed to update device in database: "+err.Error(), "danger")
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
||||||
@ -183,77 +136,47 @@ func (s *Server) GetAdminEditPeer(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) PostAdminEditPeer(c *gin.Context) {
|
func (s *Server) PostAdminEditPeer(c *gin.Context) {
|
||||||
user := s.users.GetUserByKey(c.Query("pkey"))
|
currentUser := s.users.GetUserByKey(c.Query("pkey"))
|
||||||
urlEncodedKey := url.QueryEscape(c.Query("pkey"))
|
urlEncodedKey := url.QueryEscape(c.Query("pkey"))
|
||||||
var err error
|
|
||||||
|
|
||||||
user.Identifier = c.PostForm("identifier")
|
var formUser User
|
||||||
if user.Identifier == "" {
|
if err := c.ShouldBind(&formUser); err != nil {
|
||||||
s.setAlert(c, "invalid identifier, must not be empty", "danger")
|
s.setAlert(c, "failed to bind form data: "+err.Error(), "danger")
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Email = c.PostForm("mail")
|
// Clean list input
|
||||||
if user.Email == "" {
|
formUser.IPs = common.ParseIPList(formUser.IPsStr)
|
||||||
s.setAlert(c, "invalid email, must not be empty", "danger")
|
formUser.AllowedIPs = common.ParseIPList(formUser.AllowedIPsStr)
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
formUser.IPsStr = common.IPListToString(formUser.IPs)
|
||||||
return
|
formUser.AllowedIPsStr = common.IPListToString(formUser.AllowedIPs)
|
||||||
}
|
|
||||||
|
|
||||||
ipField := c.PostForm("ip")
|
|
||||||
ips := strings.Split(ipField, ",")
|
|
||||||
validatedIPs := make([]string, 0, len(ips))
|
|
||||||
for i := range ips {
|
|
||||||
ips[i] = strings.TrimSpace(ips[i])
|
|
||||||
if ips[i] != "" {
|
|
||||||
validatedIPs = append(validatedIPs, ips[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(validatedIPs) == 0 {
|
|
||||||
s.setAlert(c, "invalid ip address", "danger")
|
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user.IPs = validatedIPs
|
|
||||||
|
|
||||||
allowedIPField := c.PostForm("allowedip")
|
|
||||||
allowedIP := strings.Split(allowedIPField, ",")
|
|
||||||
validatedAllowedIP := make([]string, 0, len(allowedIP))
|
|
||||||
for i := range allowedIP {
|
|
||||||
allowedIP[i] = strings.TrimSpace(allowedIP[i])
|
|
||||||
if allowedIP[i] != "" {
|
|
||||||
validatedAllowedIP = append(validatedAllowedIP, allowedIP[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
user.AllowedIPs = validatedAllowedIP
|
|
||||||
|
|
||||||
user.IgnorePersistentKeepalive = c.PostForm("ignorekeepalive") != ""
|
|
||||||
disabled := c.PostForm("isdisabled") != ""
|
disabled := c.PostForm("isdisabled") != ""
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
if disabled && user.DeactivatedAt == nil {
|
if disabled && currentUser.DeactivatedAt == nil {
|
||||||
user.DeactivatedAt = &now
|
formUser.DeactivatedAt = &now
|
||||||
} else if !disabled {
|
} else if !disabled {
|
||||||
user.DeactivatedAt = nil
|
formUser.DeactivatedAt = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update WireGuard device
|
// Update WireGuard device
|
||||||
if user.DeactivatedAt == &now {
|
if formUser.DeactivatedAt == &now {
|
||||||
err = s.wg.RemovePeer(user.PublicKey)
|
err := s.wg.RemovePeer(formUser.PublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setAlert(c, "failed to remove peer in WireGuard: "+err.Error(), "danger")
|
s.setAlert(c, "failed to remove peer in WireGuard: "+err.Error(), "danger")
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else if user.DeactivatedAt == nil && user.Peer != nil {
|
} else if formUser.DeactivatedAt == nil && currentUser.Peer != nil {
|
||||||
err = s.wg.UpdatePeer(user.GetPeerConfig())
|
err := s.wg.UpdatePeer(formUser.GetPeerConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setAlert(c, "failed to update peer in WireGuard: "+err.Error(), "danger")
|
s.setAlert(c, "failed to update peer in WireGuard: "+err.Error(), "danger")
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else if user.DeactivatedAt == nil && user.Peer == nil {
|
} else if formUser.DeactivatedAt == nil && currentUser.Peer == nil {
|
||||||
err = s.wg.AddPeer(user.GetPeerConfig())
|
err := s.wg.AddPeer(formUser.GetPeerConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setAlert(c, "failed to add peer in WireGuard: "+err.Error(), "danger")
|
s.setAlert(c, "failed to add peer in WireGuard: "+err.Error(), "danger")
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
||||||
@ -262,7 +185,7 @@ func (s *Server) PostAdminEditPeer(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update in database
|
// Update in database
|
||||||
err = s.users.UpdateUser(user)
|
err := s.users.UpdateUser(formUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setAlert(c, "failed to update user in database: "+err.Error(), "danger")
|
s.setAlert(c, "failed to update user in database: "+err.Error(), "danger")
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
||||||
@ -278,6 +201,20 @@ func (s *Server) GetAdminCreatePeer(c *gin.Context) {
|
|||||||
user := User{}
|
user := User{}
|
||||||
user.AllowedIPsStr = device.AllowedIPsStr
|
user.AllowedIPsStr = device.AllowedIPsStr
|
||||||
user.IPsStr = "" // TODO: add a valid ip here
|
user.IPsStr = "" // TODO: add a valid ip here
|
||||||
|
psk, err := wgtypes.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
s.HandleError(c, http.StatusInternalServerError, "Preshared key generation error", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
key, err := wgtypes.GeneratePrivateKey()
|
||||||
|
if err != nil {
|
||||||
|
s.HandleError(c, http.StatusInternalServerError, "Private key generation error", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user.PresharedKey = psk.String()
|
||||||
|
user.PrivateKey = key.String()
|
||||||
|
user.PublicKey = key.PublicKey().String()
|
||||||
|
user.UID = fmt.Sprintf("u%x", md5.Sum([]byte(user.PublicKey)))
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "admin_edit_client.html", struct {
|
c.HTML(http.StatusOK, "admin_edit_client.html", struct {
|
||||||
Route string
|
Route string
|
||||||
@ -297,68 +234,28 @@ func (s *Server) GetAdminCreatePeer(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) PostAdminCreatePeer(c *gin.Context) {
|
func (s *Server) PostAdminCreatePeer(c *gin.Context) {
|
||||||
user := User{}
|
var formUser User
|
||||||
key, err := wgtypes.GeneratePrivateKey()
|
if err := c.ShouldBind(&formUser); err != nil {
|
||||||
if err != nil {
|
s.setAlert(c, "failed to bind form data: "+err.Error(), "danger")
|
||||||
s.HandleError(c, http.StatusInternalServerError, "Private key generation error", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user.PrivateKey = key.String()
|
|
||||||
user.PublicKey = key.PublicKey().String()
|
|
||||||
|
|
||||||
user.Identifier = c.PostForm("identifier")
|
|
||||||
if user.Identifier == "" {
|
|
||||||
s.setAlert(c, "invalid identifier, must not be empty", "danger")
|
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/peer/create")
|
c.Redirect(http.StatusSeeOther, "/admin/peer/create")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Email = c.PostForm("mail")
|
// Clean list input
|
||||||
if user.Email == "" {
|
formUser.IPs = common.ParseIPList(formUser.IPsStr)
|
||||||
s.setAlert(c, "invalid email, must not be empty", "danger")
|
formUser.AllowedIPs = common.ParseIPList(formUser.AllowedIPsStr)
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/peer/create")
|
formUser.IPsStr = common.IPListToString(formUser.IPs)
|
||||||
return
|
formUser.AllowedIPsStr = common.IPListToString(formUser.AllowedIPs)
|
||||||
}
|
|
||||||
|
|
||||||
ipField := c.PostForm("ip")
|
|
||||||
ips := strings.Split(ipField, ",")
|
|
||||||
validatedIPs := make([]string, 0, len(ips))
|
|
||||||
for i := range ips {
|
|
||||||
ips[i] = strings.TrimSpace(ips[i])
|
|
||||||
if ips[i] != "" {
|
|
||||||
validatedIPs = append(validatedIPs, ips[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(validatedIPs) == 0 {
|
|
||||||
s.setAlert(c, "invalid ip address", "danger")
|
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/peer/create")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user.IPs = validatedIPs
|
|
||||||
|
|
||||||
allowedIPField := c.PostForm("allowedip")
|
|
||||||
allowedIP := strings.Split(allowedIPField, ",")
|
|
||||||
validatedAllowedIP := make([]string, 0, len(allowedIP))
|
|
||||||
for i := range allowedIP {
|
|
||||||
allowedIP[i] = strings.TrimSpace(allowedIP[i])
|
|
||||||
if allowedIP[i] != "" {
|
|
||||||
validatedAllowedIP = append(validatedAllowedIP, allowedIP[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
user.AllowedIPs = validatedAllowedIP
|
|
||||||
|
|
||||||
user.IgnorePersistentKeepalive = c.PostForm("ignorekeepalive") != ""
|
|
||||||
disabled := c.PostForm("isdisabled") != ""
|
disabled := c.PostForm("isdisabled") != ""
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
if disabled && user.DeactivatedAt == nil {
|
if disabled {
|
||||||
user.DeactivatedAt = &now
|
formUser.DeactivatedAt = &now
|
||||||
} else if !disabled {
|
|
||||||
user.DeactivatedAt = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update WireGuard device
|
// Update WireGuard device
|
||||||
if user.DeactivatedAt == nil {
|
if formUser.DeactivatedAt == nil {
|
||||||
err = s.wg.AddPeer(user.GetPeerConfig())
|
err := s.wg.AddPeer(formUser.GetPeerConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setAlert(c, "failed to add peer in WireGuard: "+err.Error(), "danger")
|
s.setAlert(c, "failed to add peer in WireGuard: "+err.Error(), "danger")
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/peer/create")
|
c.Redirect(http.StatusSeeOther, "/admin/peer/create")
|
||||||
@ -367,7 +264,7 @@ func (s *Server) PostAdminCreatePeer(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update in database
|
// Update in database
|
||||||
err = s.users.CreateUser(user)
|
err := s.users.CreateUser(formUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setAlert(c, "failed to add user in database: "+err.Error(), "danger")
|
s.setAlert(c, "failed to add user in database: "+err.Error(), "danger")
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/peer/create")
|
c.Redirect(http.StatusSeeOther, "/admin/peer/create")
|
||||||
|
@ -10,6 +10,10 @@ import (
|
|||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
|
|
||||||
"github.com/h44z/wg-portal/internal/wireguard"
|
"github.com/h44z/wg-portal/internal/wireguard"
|
||||||
|
|
||||||
"github.com/h44z/wg-portal/internal/common"
|
"github.com/h44z/wg-portal/internal/common"
|
||||||
@ -22,6 +26,42 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
// CUSTOM VALIDATORS ----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
var cidrList validator.Func = func(fl validator.FieldLevel) bool {
|
||||||
|
cidrListStr := fl.Field().String()
|
||||||
|
|
||||||
|
cidrList := common.ParseIPList(cidrListStr)
|
||||||
|
for i := range cidrList {
|
||||||
|
_, _, err := net.ParseCIDR(cidrList[i])
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var ipList validator.Func = func(fl validator.FieldLevel) bool {
|
||||||
|
ipListStr := fl.Field().String()
|
||||||
|
|
||||||
|
ipList := common.ParseIPList(ipListStr)
|
||||||
|
for i := range ipList {
|
||||||
|
ip := net.ParseIP(ipList[i])
|
||||||
|
if ip == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
|
||||||
|
v.RegisterValidation("cidrlist", cidrList)
|
||||||
|
v.RegisterValidation("iplist", ipList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// USER ----------------------------------------------------------------------------------------
|
// USER ----------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@ -31,19 +71,19 @@ type User struct {
|
|||||||
LdapUser *ldap.UserCacheHolderEntry `gorm:"-"` // optional, it is still possible to have users without ldap
|
LdapUser *ldap.UserCacheHolderEntry `gorm:"-"` // optional, it is still possible to have users without ldap
|
||||||
Config string `gorm:"-"`
|
Config string `gorm:"-"`
|
||||||
|
|
||||||
UID string // uid for html identification
|
UID string `form:"uid" binding:"alphanum"` // uid for html identification
|
||||||
IsOnline bool `gorm:"-"`
|
IsOnline bool `gorm:"-"`
|
||||||
Identifier string // Identifier AND Email make a WireGuard peer unique
|
Identifier string `form:"identifier" binding:"required,lt=64"` // Identifier AND Email make a WireGuard peer unique
|
||||||
Email string `gorm:"index"`
|
Email string `gorm:"index" form:"mail" binding:"required,email"`
|
||||||
|
|
||||||
IgnorePersistentKeepalive bool
|
IgnorePersistentKeepalive bool `form:"ignorekeepalive"`
|
||||||
PresharedKey string
|
PresharedKey string `form:"presharedkey" binding:"omitempty,base64"`
|
||||||
AllowedIPsStr string
|
AllowedIPsStr string `form:"allowedip" binding:"cidrlist"`
|
||||||
IPsStr string
|
IPsStr string `form:"ip" binding:"cidrlist"`
|
||||||
AllowedIPs []string `gorm:"-"` // IPs that are used in the client config file
|
AllowedIPs []string `gorm:"-"` // IPs that are used in the client config file
|
||||||
IPs []string `gorm:"-"` // The IPs of the client
|
IPs []string `gorm:"-"` // The IPs of the client
|
||||||
PrivateKey string
|
PrivateKey string `form:"privkey" binding:"omitempty,base64"`
|
||||||
PublicKey string `gorm:"primaryKey"`
|
PublicKey string `gorm:"primaryKey" form:"pubkey" binding:"required,base64"`
|
||||||
|
|
||||||
DeactivatedAt *time.Time
|
DeactivatedAt *time.Time
|
||||||
CreatedBy string
|
CreatedBy string
|
||||||
@ -128,23 +168,23 @@ func (u User) IsValid() bool {
|
|||||||
type Device struct {
|
type Device struct {
|
||||||
Interface *wgtypes.Device `gorm:"-"`
|
Interface *wgtypes.Device `gorm:"-"`
|
||||||
|
|
||||||
DeviceName string `gorm:"primaryKey"`
|
DeviceName string `form:"device" gorm:"primaryKey" binding:"required,alphanum"`
|
||||||
PrivateKey string
|
PrivateKey string `form:"privkey" binding:"base64"`
|
||||||
PublicKey string
|
PublicKey string `form:"pubkey" binding:"required,base64"`
|
||||||
PersistentKeepalive int
|
PersistentKeepalive int `form:"keepalive" binding:"gte=0"`
|
||||||
ListenPort int
|
ListenPort int `form:"port" binding:"required,gt=0"`
|
||||||
Mtu int
|
Mtu int `form:"mtu" binding:"gte=0,lte=1500"`
|
||||||
Endpoint string
|
Endpoint string `form:"endpoint" binding:"required,hostname_port"`
|
||||||
AllowedIPsStr string
|
AllowedIPsStr string `form:"allowedip" binding:"cidrlist"`
|
||||||
IPsStr string
|
IPsStr string `form:"ip" binding:"required,cidrlist"`
|
||||||
AllowedIPs []string `gorm:"-"` // IPs that are used in the client config file
|
AllowedIPs []string `gorm:"-"` // IPs that are used in the client config file
|
||||||
IPs []string `gorm:"-"` // The IPs of the client
|
IPs []string `gorm:"-"` // The IPs of the client
|
||||||
DNSStr string
|
DNSStr string `form:"dns" binding:"iplist"`
|
||||||
DNS []string `gorm:"-"` // The DNS servers of the client
|
DNS []string `gorm:"-"` // The DNS servers of the client
|
||||||
PreUp string
|
PreUp string `form:"preup"`
|
||||||
PostUp string
|
PostUp string `form:"postup"`
|
||||||
PreDown string
|
PreDown string `form:"predown"`
|
||||||
PostDown string
|
PostDown string `form:"postdown"`
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user