mirror of
https://github.com/DJSundog/wg-portal.git
synced 2025-02-19 17:13:44 -05:00
390 lines
10 KiB
Go
390 lines
10 KiB
Go
package server
|
|
|
|
import (
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func (s *Server) GetIndex(c *gin.Context) {
|
|
c.HTML(http.StatusOK, "index.html", gin.H{
|
|
"route": c.Request.URL.Path,
|
|
"session": s.getSessionData(c),
|
|
"static": s.getStaticData(),
|
|
})
|
|
}
|
|
|
|
func (s *Server) HandleError(c *gin.Context, code int, message, details string) {
|
|
// TODO: if json
|
|
//c.JSON(code, gin.H{"error": message, "details": details})
|
|
|
|
c.HTML(code, "error.html", gin.H{
|
|
"data": gin.H{
|
|
"Code": strconv.Itoa(code),
|
|
"Message": message,
|
|
"Details": details,
|
|
},
|
|
"route": c.Request.URL.Path,
|
|
"session": s.getSessionData(c),
|
|
"static": s.getStaticData(),
|
|
})
|
|
}
|
|
|
|
func (s *Server) GetAdminIndex(c *gin.Context) {
|
|
device := s.users.GetDevice()
|
|
users := s.users.GetAllUsers()
|
|
|
|
c.HTML(http.StatusOK, "admin_index.html", struct {
|
|
Route string
|
|
Session SessionData
|
|
Static StaticData
|
|
Peers []User
|
|
Device Device
|
|
}{
|
|
Route: c.Request.URL.Path,
|
|
Session: s.getSessionData(c),
|
|
Static: s.getStaticData(),
|
|
Peers: users,
|
|
Device: device,
|
|
})
|
|
}
|
|
|
|
func (s *Server) GetAdminEditInterface(c *gin.Context) {
|
|
device := s.users.GetDevice()
|
|
users := s.users.GetAllUsers()
|
|
|
|
c.HTML(http.StatusOK, "admin_edit_interface.html", struct {
|
|
Route string
|
|
Alerts AlertData
|
|
Session SessionData
|
|
Static StaticData
|
|
Peers []User
|
|
Device Device
|
|
}{
|
|
Route: c.Request.URL.Path,
|
|
Alerts: s.getAlertData(c),
|
|
Session: s.getSessionData(c),
|
|
Static: s.getStaticData(),
|
|
Peers: users,
|
|
Device: device,
|
|
})
|
|
}
|
|
|
|
func (s *Server) PostAdminEditInterface(c *gin.Context) {
|
|
device := s.users.GetDevice()
|
|
var err error
|
|
|
|
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")
|
|
return
|
|
}
|
|
|
|
// Update WireGuard device
|
|
err = s.wg.UpdateDevice(device.DeviceName, device.GetDeviceConfig())
|
|
if err != nil {
|
|
s.setAlert(c, "failed to update device in WireGuard: "+err.Error(), "danger")
|
|
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
|
return
|
|
}
|
|
|
|
// Update in database
|
|
err = s.users.UpdateDevice(device)
|
|
if err != nil {
|
|
s.setAlert(c, "failed to update device in database: "+err.Error(), "danger")
|
|
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
|
return
|
|
}
|
|
|
|
s.setAlert(c, "changes applied successfully", "success")
|
|
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
|
}
|
|
|
|
func (s *Server) GetAdminEditPeer(c *gin.Context) {
|
|
device := s.users.GetDevice()
|
|
user := s.users.GetUserByKey(c.Query("pkey"))
|
|
|
|
c.HTML(http.StatusOK, "admin_edit_client.html", struct {
|
|
Route string
|
|
Alerts AlertData
|
|
Session SessionData
|
|
Static StaticData
|
|
Peer User
|
|
Device Device
|
|
}{
|
|
Route: c.Request.URL.Path,
|
|
Alerts: s.getAlertData(c),
|
|
Session: s.getSessionData(c),
|
|
Static: s.getStaticData(),
|
|
Peer: user,
|
|
Device: device,
|
|
})
|
|
}
|
|
|
|
func (s *Server) PostAdminEditPeer(c *gin.Context) {
|
|
user := s.users.GetUserByKey(c.Query("pkey"))
|
|
urlEncodedKey := url.QueryEscape(c.Query("pkey"))
|
|
var err error
|
|
|
|
user.Identifier = c.PostForm("identifier")
|
|
if user.Identifier == "" {
|
|
s.setAlert(c, "invalid identifier, must not be empty", "danger")
|
|
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
|
return
|
|
}
|
|
|
|
user.Email = c.PostForm("mail")
|
|
if user.Email == "" {
|
|
s.setAlert(c, "invalid email, must not be empty", "danger")
|
|
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
|
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/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") != ""
|
|
now := time.Now()
|
|
if disabled && user.DeactivatedAt == nil {
|
|
user.DeactivatedAt = &now
|
|
} else if !disabled {
|
|
user.DeactivatedAt = nil
|
|
}
|
|
|
|
// Update WireGuard device
|
|
if user.DeactivatedAt == &now {
|
|
err = s.wg.RemovePeer(user.PublicKey)
|
|
if err != nil {
|
|
s.setAlert(c, "failed to remove peer in WireGuard: "+err.Error(), "danger")
|
|
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
|
return
|
|
}
|
|
} else if user.DeactivatedAt == nil && user.Peer != nil {
|
|
err = s.wg.UpdatePeer(user.GetPeerConfig())
|
|
if err != nil {
|
|
s.setAlert(c, "failed to update peer in WireGuard: "+err.Error(), "danger")
|
|
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
|
return
|
|
}
|
|
} else if user.DeactivatedAt == nil && user.Peer == nil {
|
|
err = s.wg.AddPeer(user.GetPeerConfig())
|
|
if err != nil {
|
|
s.setAlert(c, "failed to add peer in WireGuard: "+err.Error(), "danger")
|
|
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
|
return
|
|
}
|
|
}
|
|
|
|
// Update in database
|
|
err = s.users.UpdateUser(user)
|
|
if err != nil {
|
|
s.setAlert(c, "failed to update user in database: "+err.Error(), "danger")
|
|
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
|
return
|
|
}
|
|
|
|
s.setAlert(c, "changes applied successfully", "success")
|
|
c.Redirect(http.StatusSeeOther, "/admin/peer/edit?pkey="+urlEncodedKey)
|
|
}
|
|
|
|
func (s *Server) GetAdminCreatePeer(c *gin.Context) {
|
|
device := s.users.GetDevice()
|
|
user := s.users.GetUserByKey(c.Query("pkey"))
|
|
|
|
c.HTML(http.StatusOK, "admin_edit_client.html", struct {
|
|
Route string
|
|
Alerts AlertData
|
|
Session SessionData
|
|
Static StaticData
|
|
Peer User
|
|
Device Device
|
|
}{
|
|
Route: c.Request.URL.Path,
|
|
Alerts: s.getAlertData(c),
|
|
Session: s.getSessionData(c),
|
|
Static: s.getStaticData(),
|
|
Peer: user,
|
|
Device: device,
|
|
})
|
|
}
|
|
|
|
func (s *Server) PostAdminCreatePeer(c *gin.Context) {
|
|
device := s.users.GetDevice()
|
|
var err error
|
|
|
|
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")
|
|
return
|
|
}
|
|
|
|
// Update WireGuard device
|
|
err = s.wg.UpdateDevice(device.DeviceName, device.GetDeviceConfig())
|
|
if err != nil {
|
|
s.setAlert(c, "failed to update device in WireGuard: "+err.Error(), "danger")
|
|
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
|
return
|
|
}
|
|
|
|
// Update in database
|
|
err = s.users.UpdateDevice(device)
|
|
if err != nil {
|
|
s.setAlert(c, "failed to update device in database: "+err.Error(), "danger")
|
|
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
|
return
|
|
}
|
|
|
|
s.setAlert(c, "changes applied successfully", "success")
|
|
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
|
}
|
|
|
|
func (s *Server) GetUserQRCode(c *gin.Context) {
|
|
user := s.users.GetUserByKey(c.Query("pkey"))
|
|
png, err := user.GetQRCode()
|
|
if err != nil {
|
|
s.HandleError(c, http.StatusInternalServerError, "QRCode error", err.Error())
|
|
return
|
|
}
|
|
c.Data(http.StatusOK, "image/png", png)
|
|
return
|
|
}
|