package middleware import ( "encoding/base64" "strconv" "strings" "time" "git.ma-al.com/goc_daniel/b2b/app/config" "git.ma-al.com/goc_daniel/b2b/app/model" "git.ma-al.com/goc_daniel/b2b/app/service/authService" constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data" "git.ma-al.com/goc_daniel/b2b/app/utils/localeExtractor" "github.com/gofiber/fiber/v3" ) // AuthMiddleware creates authentication middleware func AuthMiddleware() fiber.Handler { authService := authService.NewAuthService() return func(c fiber.Ctx) error { // Get token from Authorization header authHeader := c.Get("Authorization") if authHeader == "" { // Try to get from cookie authHeader = c.Cookies("access_token") if authHeader == "" { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "error": "authorization token required", }) } } else { // Extract token from "Bearer " parts := strings.Split(authHeader, " ") if len(parts) != 2 || parts[0] != "Bearer" { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "error": "invalid authorization header format", }) } authHeader = parts[1] } // Validate token claims, err := authService.ValidateToken(authHeader) if err != nil { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "error": "invalid or expired token", }) } // Get user from database user, err := authService.GetUserByID(claims.UserID) if err != nil { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "error": "user not found", }) } // Check if user is active if !user.IsActive { return c.Status(fiber.StatusForbidden).JSON(fiber.Map{ "error": "user account is inactive", }) } // Create locale. LangID is overwritten by auth Token var userLocale model.UserLocale userLocale.OriginalUser = user // Check if target user is present targetUserIDAttribute := c.Query("target_user_id") if targetUserIDAttribute == "" { userLocale.User = user c.Locals(constdata.USER_LOCALE, &userLocale) return c.Next() } // We now populate the target user if user.Role != model.RoleAdmin { return c.Status(fiber.StatusForbidden).JSON(fiber.Map{ "error": "admin access required", }) } targetUserID, err := strconv.Atoi(targetUserIDAttribute) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": "invalid target user id attribute", }) } // to verify target user, we use the same functionality as for verifying original user // Get target user from database user, err = authService.GetUserByID(uint(targetUserID)) if err != nil { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "error": "target user not found", }) } // Check if target user is active if !user.IsActive { return c.Status(fiber.StatusForbidden).JSON(fiber.Map{ "error": "target user account is inactive", }) } userLocale.User = user c.Locals(constdata.USER_LOCALE, &userLocale) return c.Next() } } // RequireAdmin creates admin-only middleware func RequireAdmin() fiber.Handler { return func(c fiber.Ctx) error { originalUserRole, ok := localeExtractor.GetOriginalUserRole(c) if !ok { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "error": "not authenticated", }) } if originalUserRole != model.RoleAdmin { return c.Status(fiber.StatusForbidden).JSON(fiber.Map{ "error": "admin access required", }) } return c.Next() } } // Webdav func Webdav() fiber.Handler { authService := authService.NewAuthService() return func(c fiber.Ctx) error { authHeader := c.Get("Authorization") if authHeader == "" { c.Set("WWW-Authenticate", `Basic realm="webdav"`) return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "error": "authorization token required", }) } if !strings.HasPrefix(authHeader, "Basic ") { c.Set("WWW-Authenticate", `Basic realm="webdav"`) return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "error": "invalid authorization token", }) } encoded := strings.TrimPrefix(authHeader, "Basic ") decoded, err := base64.StdEncoding.DecodeString(encoded) if err != nil { c.Set("WWW-Authenticate", `Basic realm="webdav"`) return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "error": "invalid authorization token", }) } credentials := strings.SplitN(string(decoded), ":", 2) rawToken := "" if len(credentials) == 1 { rawToken = credentials[0] } else if len(credentials) == 2 { rawToken = credentials[1] } if len(rawToken) != constdata.NBYTES_IN_WEBDAV_TOKEN*2 { c.Set("WWW-Authenticate", `Basic realm="webdav"`) return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "error": "invalid authorization token", }) } // we identify user based on this token. user, err := authService.GetUserByWebdavToken(rawToken) if err != nil { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "error": "user not found", }) } if user.WebdavExpires != nil && user.WebdavExpires.Before(time.Now()) { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "error": "invalid or expired token", }) } var userLocale model.UserLocale userLocale.OriginalUser = user userLocale.User = user c.Locals(constdata.USER_LOCALE, &userLocale) return c.Next() } } // GetConfig returns the app config func GetConfig() *config.Config { return config.Get() }