func (s *Server) UpdatePeer(peer wireguard.Peer, updateTime time.Time) error {
	currentPeer := s.peers.GetPeerByKey(peer.PublicKey)
	dev := s.peers.GetDevice(peer.DeviceName)
	var err error
	switch {
	case peer.DeactivatedAt != nil && *peer.DeactivatedAt == updateTime:
		err = s.wg.RemovePeer(peer.DeviceName, peer.PublicKey)
	case peer.DeactivatedAt == nil && currentPeer.Peer != nil:
		err = s.wg.UpdatePeer(peer.DeviceName, peer.GetConfig(&dev))
	case peer.DeactivatedAt == nil && currentPeer.Peer == nil:
		err = s.wg.AddPeer(peer.DeviceName, peer.GetConfig(&dev))
	}
	if err != nil {
		return errors.WithMessage(err, "failed to update WireGuard peer")
	}
	peer.UID = fmt.Sprintf("u%x", md5.Sum([]byte(peer.PublicKey)))
	if err := s.peers.UpdatePeer(peer); err != nil {
		return errors.WithMessage(err, "failed to update peer")
	}
	return s.WriteWireGuardConfigFile(peer.DeviceName)
}
UpdatePeer updates the physical WireGuard interface and the database.
package server
import (
	"crypto/md5"
	"fmt"
	"io/ioutil"
	"path"
	"syscall"
	"time"
	"github.com/h44z/wg-portal/internal/users"
	"github.com/h44z/wg-portal/internal/wireguard"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"golang.org/x/crypto/bcrypt"
	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
	"gorm.io/gorm"
)
func (s *Server) PrepareNewPeer(device string) (wireguard.Peer, error) {
	dev := s.peers.GetDevice(device)
	deviceIPs := dev.GetIPAddresses()
	peer := wireguard.Peer{}
	peer.IsNew = true
	switch dev.Type {
	case wireguard.DeviceTypeServer:
		peerIPs := make([]string, len(deviceIPs))
		for i := range deviceIPs {
			freeIP, err := s.peers.GetAvailableIp(device, deviceIPs[i])
			if err != nil {
				return wireguard.Peer{}, errors.WithMessage(err, "failed to get available IP addresses")
			}
			peerIPs[i] = freeIP
		}
		peer.SetIPAddresses(peerIPs...)
		psk, err := wgtypes.GenerateKey()
		if err != nil {
			return wireguard.Peer{}, errors.Wrap(err, "failed to generate key")
		}
		key, err := wgtypes.GeneratePrivateKey()
		if err != nil {
			return wireguard.Peer{}, errors.Wrap(err, "failed to generate private key")
		}
		peer.PresharedKey = psk.String()
		peer.PrivateKey = key.String()
		peer.PublicKey = key.PublicKey().String()
		peer.UID = fmt.Sprintf("u%x", md5.Sum([]byte(peer.PublicKey)))
		peer.Endpoint = dev.DefaultEndpoint
		peer.DNSStr = dev.DNSStr
		peer.PersistentKeepalive = dev.DefaultPersistentKeepalive
		peer.AllowedIPsStr = dev.DefaultAllowedIPsStr
		peer.Mtu = dev.Mtu
		peer.DeviceName = device
	case wireguard.DeviceTypeClient:
		peer.UID = "newendpoint"
	}
	return peer, nil
}
func (s *Server) CreatePeerByEmail(device, email, identifierSuffix string, disabled bool) error {
	user := s.users.GetUser(email)
	peer, err := s.PrepareNewPeer(device)
	if err != nil {
		return errors.WithMessage(err, "failed to prepare new peer")
	}
	peer.Email = email
	if user != nil {
		peer.Identifier = fmt.Sprintf("%s %s (%s)", user.Firstname, user.Lastname, identifierSuffix)
	} else {
		peer.Identifier = fmt.Sprintf("%s (%s)", email, identifierSuffix)
	}
	now := time.Now()
	if disabled {
		peer.DeactivatedAt = &now
	}
	return s.CreatePeer(device, peer)
}
func (s *Server) CreatePeer(device string, peer wireguard.Peer) error {
	dev := s.peers.GetDevice(device)
	deviceIPs := dev.GetIPAddresses()
	peerIPs := peer.GetIPAddresses()
	peer.AllowedIPsStr = dev.DefaultAllowedIPsStr
	if len(peerIPs) == 0 && dev.Type == wireguard.DeviceTypeServer {
		peerIPs = make([]string, len(deviceIPs))
		for i := range deviceIPs {
			freeIP, err := s.peers.GetAvailableIp(device, deviceIPs[i])
			if err != nil {
				return errors.WithMessage(err, "failed to get available IP addresses")
			}
			peerIPs[i] = freeIP
		}
		peer.SetIPAddresses(peerIPs...)
	}
	if peer.PrivateKey == "" && dev.Type == wireguard.DeviceTypeServer {  
		psk, err := wgtypes.GenerateKey()
		if err != nil {
			return errors.Wrap(err, "failed to generate key")
		}
		key, err := wgtypes.GeneratePrivateKey()
		if err != nil {
			return errors.Wrap(err, "failed to generate private key")
		}
		peer.PresharedKey = psk.String()
		peer.PrivateKey = key.String()
		peer.PublicKey = key.PublicKey().String()
	}
	peer.DeviceName = dev.DeviceName
	peer.UID = fmt.Sprintf("u%x", md5.Sum([]byte(peer.PublicKey)))
	if peer.DeactivatedAt == nil {
		if err := s.wg.AddPeer(device, peer.GetConfig(&dev)); err != nil {
			return errors.WithMessage(err, "failed to add WireGuard peer")
		}
	}
	if err := s.peers.CreatePeer(peer); err != nil {
		return errors.WithMessage(err, "failed to create peer")
	}
	return s.WriteWireGuardConfigFile(device)
}