mirror of https://github.com/h44z/wg-portal.git
				
				
				
			
		
			
				
	
	
		
			156 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
package server
 | 
						|
 | 
						|
import (
 | 
						|
	"net/http"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	csrf "github.com/utrack/gin-csrf"
 | 
						|
 | 
						|
	"github.com/gin-gonic/gin"
 | 
						|
	"github.com/h44z/wg-portal/internal/authentication"
 | 
						|
	"github.com/h44z/wg-portal/internal/users"
 | 
						|
	"github.com/sirupsen/logrus"
 | 
						|
)
 | 
						|
 | 
						|
func (s *Server) GetLogin(c *gin.Context) {
 | 
						|
	currentSession := GetSessionData(c)
 | 
						|
	if currentSession.LoggedIn {
 | 
						|
		c.Redirect(http.StatusSeeOther, "/") // already logged in
 | 
						|
	}
 | 
						|
 | 
						|
	authError := c.DefaultQuery("err", "")
 | 
						|
	errMsg := "Unknown error occurred, try again!"
 | 
						|
	switch authError {
 | 
						|
	case "missingdata":
 | 
						|
		errMsg = "Invalid login data retrieved, please fill out all fields and try again!"
 | 
						|
	case "authfail":
 | 
						|
		errMsg = "Authentication failed!"
 | 
						|
	case "loginreq":
 | 
						|
		errMsg = "Login required!"
 | 
						|
	}
 | 
						|
 | 
						|
	c.HTML(http.StatusOK, "login.html", gin.H{
 | 
						|
		"error":   authError != "",
 | 
						|
		"message": errMsg,
 | 
						|
		"static":  s.getStaticData(),
 | 
						|
		"Csrf":    csrf.GetToken(c),
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func (s *Server) PostLogin(c *gin.Context) {
 | 
						|
	currentSession := GetSessionData(c)
 | 
						|
	if currentSession.LoggedIn {
 | 
						|
		// already logged in
 | 
						|
		c.Redirect(http.StatusSeeOther, "/")
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	username := strings.ToLower(c.PostForm("username"))
 | 
						|
	password := c.PostForm("password")
 | 
						|
 | 
						|
	// Validate form input
 | 
						|
	if strings.Trim(username, " ") == "" || strings.Trim(password, " ") == "" {
 | 
						|
		c.Redirect(http.StatusSeeOther, "/auth/login?err=missingdata")
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// Check user database for an matching entry
 | 
						|
	var loginProvider authentication.AuthProvider
 | 
						|
	email := ""
 | 
						|
	user := s.users.GetUser(username) // retrieve active candidate user from db
 | 
						|
	if user != nil {                  // existing user
 | 
						|
		loginProvider = s.auth.GetProvider(string(user.Source))
 | 
						|
		if loginProvider == nil {
 | 
						|
			s.GetHandleError(c, http.StatusInternalServerError, "login error", "login provider unavailable")
 | 
						|
			return
 | 
						|
		}
 | 
						|
		authEmail, err := loginProvider.Login(&authentication.AuthContext{
 | 
						|
			Username: username,
 | 
						|
			Password: password,
 | 
						|
		})
 | 
						|
		if err == nil {
 | 
						|
			email = authEmail
 | 
						|
		}
 | 
						|
	} else { // possible new user
 | 
						|
		// Check all available auth backends
 | 
						|
		for _, provider := range s.auth.GetProvidersForType(authentication.AuthProviderTypePassword) {
 | 
						|
			// try to log in to the given provider
 | 
						|
			authEmail, err := provider.Login(&authentication.AuthContext{
 | 
						|
				Username: username,
 | 
						|
				Password: password,
 | 
						|
			})
 | 
						|
			if err != nil {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			email = authEmail
 | 
						|
			loginProvider = provider
 | 
						|
 | 
						|
			// create new user in the database (or reactivate him)
 | 
						|
			userData, err := loginProvider.GetUserModel(&authentication.AuthContext{
 | 
						|
				Username: email,
 | 
						|
			})
 | 
						|
			if err != nil {
 | 
						|
				s.GetHandleError(c, http.StatusInternalServerError, "login error", err.Error())
 | 
						|
				return
 | 
						|
			}
 | 
						|
			if err := s.CreateUser(users.User{
 | 
						|
				Email:     userData.Email,
 | 
						|
				Source:    users.UserSource(loginProvider.GetName()),
 | 
						|
				IsAdmin:   userData.IsAdmin,
 | 
						|
				Firstname: userData.Firstname,
 | 
						|
				Lastname:  userData.Lastname,
 | 
						|
				Phone:     userData.Phone,
 | 
						|
			}, s.wg.Cfg.GetDefaultDeviceName()); err != nil {
 | 
						|
				s.GetHandleError(c, http.StatusInternalServerError, "login error", "failed to update user data")
 | 
						|
				return
 | 
						|
			}
 | 
						|
 | 
						|
			user = s.users.GetUser(username)
 | 
						|
			break
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Check if user is authenticated
 | 
						|
	if email == "" || loginProvider == nil || user == nil {
 | 
						|
		c.Redirect(http.StatusSeeOther, "/auth/login?err=authfail")
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// Set authenticated session
 | 
						|
	sessionData := GetSessionData(c)
 | 
						|
	sessionData.LoggedIn = true
 | 
						|
	sessionData.IsAdmin = user.IsAdmin
 | 
						|
	sessionData.Email = user.Email
 | 
						|
	sessionData.Firstname = user.Firstname
 | 
						|
	sessionData.Lastname = user.Lastname
 | 
						|
	sessionData.DeviceName = s.wg.Cfg.DeviceNames[0]
 | 
						|
 | 
						|
	// Check if user already has a peer setup, if not create one
 | 
						|
	if err := s.CreateUserDefaultPeer(user.Email, s.wg.Cfg.GetDefaultDeviceName()); err != nil {
 | 
						|
		// Not a fatal error, just log it...
 | 
						|
		logrus.Errorf("failed to automatically create vpn peer for %s: %v", sessionData.Email, err)
 | 
						|
	}
 | 
						|
 | 
						|
	if err := UpdateSessionData(c, sessionData); err != nil {
 | 
						|
		s.GetHandleError(c, http.StatusInternalServerError, "login error", "failed to save session")
 | 
						|
		return
 | 
						|
	}
 | 
						|
	c.Redirect(http.StatusSeeOther, "/")
 | 
						|
}
 | 
						|
 | 
						|
func (s *Server) GetLogout(c *gin.Context) {
 | 
						|
	currentSession := GetSessionData(c)
 | 
						|
 | 
						|
	if !currentSession.LoggedIn { // Not logged in
 | 
						|
		c.Redirect(http.StatusSeeOther, "/")
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if err := DestroySessionData(c); err != nil {
 | 
						|
		s.GetHandleError(c, http.StatusInternalServerError, "logout error", "failed to destroy session")
 | 
						|
		return
 | 
						|
	}
 | 
						|
	c.Redirect(http.StatusSeeOther, "/")
 | 
						|
}
 |