mirror of https://github.com/h44z/wg-portal.git
				
				
				
			
		
			
				
	
	
		
			152 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
| package server
 | |
| 
 | |
| import (
 | |
| 	"net/http"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/pkg/errors"
 | |
| 
 | |
| 	"github.com/gin-gonic/gin"
 | |
| 	"github.com/h44z/wg-portal/internal/authentication"
 | |
| 	"github.com/h44z/wg-portal/internal/users"
 | |
| 	"github.com/sirupsen/logrus"
 | |
| 	csrf "github.com/utrack/gin-csrf"
 | |
| )
 | |
| 
 | |
| 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 all available auth backends
 | |
| 	user, err := s.checkAuthentication(username, password)
 | |
| 	if err != nil {
 | |
| 		s.GetHandleError(c, http.StatusInternalServerError, "login error", err.Error())
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Check if user is authenticated
 | |
| 	if 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, "/")
 | |
| }
 | |
| 
 | |
| func (s *Server) checkAuthentication(username, password string) (*users.User, error) {
 | |
| 	var user *users.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
 | |
| 		}
 | |
| 
 | |
| 		// Login succeeded
 | |
| 		user = s.users.GetUser(authEmail)
 | |
| 		if user != nil {
 | |
| 			break // user exists, nothing more to do...
 | |
| 		}
 | |
| 
 | |
| 		// create new user in the database (or reactivate him)
 | |
| 		userData, err := provider.GetUserModel(&authentication.AuthContext{
 | |
| 			Username: username,
 | |
| 		})
 | |
| 		if err != nil {
 | |
| 			return nil, errors.Wrap(err, "failed to get user model")
 | |
| 		}
 | |
| 		if err := s.CreateUser(users.User{
 | |
| 			Email:     userData.Email,
 | |
| 			Source:    users.UserSource(provider.GetName()),
 | |
| 			IsAdmin:   userData.IsAdmin,
 | |
| 			Firstname: userData.Firstname,
 | |
| 			Lastname:  userData.Lastname,
 | |
| 			Phone:     userData.Phone,
 | |
| 		}, s.wg.Cfg.GetDefaultDeviceName()); err != nil {
 | |
| 			return nil, errors.Wrap(err, "failed to update user data")
 | |
| 		}
 | |
| 
 | |
| 		user = s.users.GetUser(authEmail)
 | |
| 		break
 | |
| 	}
 | |
| 
 | |
| 	return user, nil
 | |
| }
 |