mirror of https://github.com/h44z/wg-portal.git
				
				
				
			
		
			
				
	
	
		
			270 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			270 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Go
		
	
	
	
| package server
 | |
| 
 | |
| import (
 | |
| 	"net/http"
 | |
| 	"net/url"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/gin-gonic/gin"
 | |
| 	"github.com/h44z/wg-portal/internal/users"
 | |
| 	"github.com/sirupsen/logrus"
 | |
| 	"golang.org/x/crypto/bcrypt"
 | |
| 	"gorm.io/gorm"
 | |
| )
 | |
| 
 | |
| func (s *Server) GetAdminUsersIndex(c *gin.Context) {
 | |
| 	currentSession := GetSessionData(c)
 | |
| 
 | |
| 	sort := c.Query("sort")
 | |
| 	if sort != "" {
 | |
| 		if currentSession.SortedBy["users"] != sort {
 | |
| 			currentSession.SortedBy["users"] = sort
 | |
| 			currentSession.SortDirection["users"] = "asc"
 | |
| 		} else {
 | |
| 			if currentSession.SortDirection["users"] == "asc" {
 | |
| 				currentSession.SortDirection["users"] = "desc"
 | |
| 			} else {
 | |
| 				currentSession.SortDirection["users"] = "asc"
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if err := UpdateSessionData(c, currentSession); err != nil {
 | |
| 			s.GetHandleError(c, http.StatusInternalServerError, "sort error", "failed to save session")
 | |
| 			return
 | |
| 		}
 | |
| 		c.Redirect(http.StatusSeeOther, "/admin/users/")
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	search, searching := c.GetQuery("search")
 | |
| 	if searching {
 | |
| 		currentSession.Search["users"] = search
 | |
| 
 | |
| 		if err := UpdateSessionData(c, currentSession); err != nil {
 | |
| 			s.GetHandleError(c, http.StatusInternalServerError, "search error", "failed to save session")
 | |
| 			return
 | |
| 		}
 | |
| 		c.Redirect(http.StatusSeeOther, "/admin/users/")
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	dbUsers := s.users.GetFilteredAndSortedUsersUnscoped(currentSession.SortedBy["users"], currentSession.SortDirection["users"], currentSession.Search["users"])
 | |
| 
 | |
| 	c.HTML(http.StatusOK, "admin_user_index.html", struct {
 | |
| 		Route      string
 | |
| 		Alerts     []FlashData
 | |
| 		Session    SessionData
 | |
| 		Static     StaticData
 | |
| 		Users      []users.User
 | |
| 		TotalUsers int
 | |
| 		Device     Device
 | |
| 	}{
 | |
| 		Route:      c.Request.URL.Path,
 | |
| 		Alerts:     GetFlashes(c),
 | |
| 		Session:    currentSession,
 | |
| 		Static:     s.getStaticData(),
 | |
| 		Users:      dbUsers,
 | |
| 		TotalUsers: len(s.users.GetUsers()),
 | |
| 		Device:     s.peers.GetDevice(),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (s *Server) GetAdminUsersEdit(c *gin.Context) {
 | |
| 	user := s.users.GetUserUnscoped(c.Query("pkey"))
 | |
| 
 | |
| 	currentSession, err := s.setFormInSession(c, *user)
 | |
| 	if err != nil {
 | |
| 		s.GetHandleError(c, http.StatusInternalServerError, "Session error", err.Error())
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	c.HTML(http.StatusOK, "admin_edit_user.html", struct {
 | |
| 		Route   string
 | |
| 		Alerts  []FlashData
 | |
| 		Session SessionData
 | |
| 		Static  StaticData
 | |
| 		User    users.User
 | |
| 		Device  Device
 | |
| 		Epoch   time.Time
 | |
| 	}{
 | |
| 		Route:   c.Request.URL.Path,
 | |
| 		Alerts:  GetFlashes(c),
 | |
| 		Session: currentSession,
 | |
| 		Static:  s.getStaticData(),
 | |
| 		User:    currentSession.FormData.(users.User),
 | |
| 		Device:  s.peers.GetDevice(),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (s *Server) PostAdminUsersEdit(c *gin.Context) {
 | |
| 	currentUser := s.users.GetUserUnscoped(c.Query("pkey"))
 | |
| 	if currentUser == nil {
 | |
| 		SetFlashMessage(c, "invalid user", "danger")
 | |
| 		c.Redirect(http.StatusSeeOther, "/admin/users/")
 | |
| 		return
 | |
| 	}
 | |
| 	urlEncodedKey := url.QueryEscape(c.Query("pkey"))
 | |
| 
 | |
| 	currentSession := GetSessionData(c)
 | |
| 	var formUser users.User
 | |
| 	if currentSession.FormData != nil {
 | |
| 		formUser = currentSession.FormData.(users.User)
 | |
| 	}
 | |
| 	if err := c.ShouldBind(&formUser); err != nil {
 | |
| 		_ = s.updateFormInSession(c, formUser)
 | |
| 		SetFlashMessage(c, "failed to bind form data: "+err.Error(), "danger")
 | |
| 		c.Redirect(http.StatusSeeOther, "/admin/users/edit?pkey="+urlEncodedKey+"&formerr=bind")
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	if formUser.Password != "" {
 | |
| 		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(formUser.Password), bcrypt.DefaultCost)
 | |
| 		if err != nil {
 | |
| 			_ = s.updateFormInSession(c, formUser)
 | |
| 			SetFlashMessage(c, "failed to hash admin password", "danger")
 | |
| 			c.Redirect(http.StatusSeeOther, "/admin/users/edit?pkey="+urlEncodedKey+"&formerr=bind")
 | |
| 			return
 | |
| 		}
 | |
| 		formUser.Password = string(hashedPassword)
 | |
| 	} else {
 | |
| 		formUser.Password = currentUser.Password
 | |
| 	}
 | |
| 
 | |
| 	disabled := c.PostForm("isdisabled") != ""
 | |
| 	if disabled {
 | |
| 		formUser.DeletedAt = gorm.DeletedAt{
 | |
| 			Time:  time.Now(),
 | |
| 			Valid: true,
 | |
| 		}
 | |
| 	} else {
 | |
| 		formUser.DeletedAt = gorm.DeletedAt{}
 | |
| 	}
 | |
| 	formUser.IsAdmin = c.PostForm("isadmin") == "true"
 | |
| 
 | |
| 	// Update peers
 | |
| 	if disabled != currentUser.DeletedAt.Valid {
 | |
| 		if disabled {
 | |
| 			// disable all peers for the given user
 | |
| 			for _, peer := range s.peers.GetPeersByMail(currentUser.Email) {
 | |
| 				now := time.Now()
 | |
| 				peer.DeactivatedAt = &now
 | |
| 				if err := s.UpdatePeer(peer, now); err != nil {
 | |
| 					logrus.Errorf("failed to update deactivated peer %s: %v", peer.PublicKey, err)
 | |
| 				}
 | |
| 			}
 | |
| 		} else {
 | |
| 			// enable all peers for the given user
 | |
| 			for _, peer := range s.peers.GetPeersByMail(currentUser.Email) {
 | |
| 				now := time.Now()
 | |
| 				peer.DeactivatedAt = nil
 | |
| 				if err := s.UpdatePeer(peer, now); err != nil {
 | |
| 					logrus.Errorf("failed to update activated peer %s: %v", peer.PublicKey, err)
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Update in database
 | |
| 	if err := s.users.UpdateUser(&formUser); err != nil {
 | |
| 		_ = s.updateFormInSession(c, formUser)
 | |
| 		SetFlashMessage(c, "failed to update user: "+err.Error(), "danger")
 | |
| 		c.Redirect(http.StatusSeeOther, "/admin/users/edit?pkey="+urlEncodedKey+"&formerr=update")
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	SetFlashMessage(c, "changes applied successfully", "success")
 | |
| 	c.Redirect(http.StatusSeeOther, "/admin/users/edit?pkey="+urlEncodedKey)
 | |
| }
 | |
| 
 | |
| func (s *Server) GetAdminUsersCreate(c *gin.Context) {
 | |
| 	user := users.User{}
 | |
| 
 | |
| 	currentSession, err := s.setFormInSession(c, user)
 | |
| 	if err != nil {
 | |
| 		s.GetHandleError(c, http.StatusInternalServerError, "Session error", err.Error())
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	c.HTML(http.StatusOK, "admin_edit_user.html", struct {
 | |
| 		Route   string
 | |
| 		Alerts  []FlashData
 | |
| 		Session SessionData
 | |
| 		Static  StaticData
 | |
| 		User    users.User
 | |
| 		Device  Device
 | |
| 		Epoch   time.Time
 | |
| 	}{
 | |
| 		Route:   c.Request.URL.Path,
 | |
| 		Alerts:  GetFlashes(c),
 | |
| 		Session: currentSession,
 | |
| 		Static:  s.getStaticData(),
 | |
| 		User:    currentSession.FormData.(users.User),
 | |
| 		Device:  s.peers.GetDevice(),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (s *Server) PostAdminUsersCreate(c *gin.Context) {
 | |
| 	currentSession := GetSessionData(c)
 | |
| 	var formUser users.User
 | |
| 	if currentSession.FormData != nil {
 | |
| 		formUser = currentSession.FormData.(users.User)
 | |
| 	}
 | |
| 	if err := c.ShouldBind(&formUser); err != nil {
 | |
| 		_ = s.updateFormInSession(c, formUser)
 | |
| 		SetFlashMessage(c, "failed to bind form data: "+err.Error(), "danger")
 | |
| 		c.Redirect(http.StatusSeeOther, "/admin/users/create?formerr=bind")
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	if formUser.Password != "" {
 | |
| 		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(formUser.Password), bcrypt.DefaultCost)
 | |
| 		if err != nil {
 | |
| 			SetFlashMessage(c, "failed to hash admin password", "danger")
 | |
| 			c.Redirect(http.StatusSeeOther, "/admin/users/create?formerr=bind")
 | |
| 			return
 | |
| 		}
 | |
| 		formUser.Password = string(hashedPassword)
 | |
| 	} else {
 | |
| 		_ = s.updateFormInSession(c, formUser)
 | |
| 		SetFlashMessage(c, "invalid password", "danger")
 | |
| 		c.Redirect(http.StatusSeeOther, "/admin/users/create?formerr=create")
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	disabled := c.PostForm("isdisabled") != ""
 | |
| 	if disabled {
 | |
| 		formUser.DeletedAt = gorm.DeletedAt{
 | |
| 			Time:  time.Now(),
 | |
| 			Valid: true,
 | |
| 		}
 | |
| 	} else {
 | |
| 		formUser.DeletedAt = gorm.DeletedAt{}
 | |
| 	}
 | |
| 	formUser.IsAdmin = c.PostForm("isadmin") == "true"
 | |
| 	formUser.Source = users.UserSourceDatabase
 | |
| 	if err := s.users.CreateUser(&formUser); err != nil {
 | |
| 		formUser.CreatedAt = time.Time{} // reset created time
 | |
| 		_ = s.updateFormInSession(c, formUser)
 | |
| 		SetFlashMessage(c, "failed to add user: "+err.Error(), "danger")
 | |
| 		c.Redirect(http.StatusSeeOther, "/admin/users/create?formerr=create")
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Check if user already has a peer setup, if not create one
 | |
| 	if s.config.Core.CreateDefaultPeer {
 | |
| 		peers := s.peers.GetPeersByMail(formUser.Email)
 | |
| 		if len(peers) == 0 { // Create vpn peer
 | |
| 			err := s.CreatePeer(Peer{
 | |
| 				Identifier: formUser.Firstname + " " + formUser.Lastname + " (Default)",
 | |
| 				Email:      formUser.Email,
 | |
| 				CreatedBy:  formUser.Email,
 | |
| 				UpdatedBy:  formUser.Email,
 | |
| 			})
 | |
| 			logrus.Errorf("Failed to automatically create vpn peer for %s: %v", formUser.Email, err)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	SetFlashMessage(c, "user created successfully", "success")
 | |
| 	c.Redirect(http.StatusSeeOther, "/admin/users/")
 | |
| }
 |