mirror of
https://github.com/h44z/wg-portal.git
synced 2025-12-14 10:36:18 +00:00
WIP: new user management and authentication system, use go 1.16 embed
This commit is contained in:
269
internal/server/handlers_user.go
Normal file
269
internal/server/handlers_user.go
Normal file
@@ -0,0 +1,269 @@
|
||||
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/")
|
||||
}
|
||||
Reference in New Issue
Block a user