package middleware import ( "netidhub-saas-be/app/database" "netidhub-saas-be/app/database/entity" "github.com/gofiber/fiber/v2" ) type MenuActionAccessMiddleware struct { DB *database.Database } func NewMenuActionAccessMiddleware(db *database.Database) *MenuActionAccessMiddleware { return &MenuActionAccessMiddleware{ DB: db, } } // CheckMenuAccess middleware untuk validasi akses user_level ke menu tertentu func (m *MenuActionAccessMiddleware) CheckMenuAccess(menuId uint) fiber.Handler { return func(c *fiber.Ctx) error { // Get user from context userCtx := c.Locals("user") if userCtx == nil { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "success": false, "code": 401, "messages": []string{"User tidak terautentikasi"}, }) } user, ok := userCtx.(*entity.Users) if !ok || user == nil { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "success": false, "code": 401, "messages": []string{"User tidak valid"}, }) } // Get user role untuk mendapatkan user_level_id var userRole entity.UserRoles if err := m.DB.DB.Where("id = ?", user.UserRoleId).First(&userRole).Error; err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "success": false, "code": 500, "messages": []string{"Error mendapatkan user role"}, "error": err.Error(), }) } userLevelId := userRole.UserLevelId // Check akses user_level ke menu var access entity.UserLevelMenuAccesses err := m.DB.DB.Where( "user_level_id = ? AND menu_id = ? AND is_active = ? AND can_access = ?", userLevelId, menuId, true, true, ).First(&access).Error if err != nil { // Jika tidak ada record, berarti tidak ada akses return c.Status(fiber.StatusForbidden).JSON(fiber.Map{ "success": false, "code": 403, "messages": []string{"Anda tidak memiliki akses ke menu ini"}, "user_level_id": userLevelId, "menu_id": menuId, }) } // Set menu ke context c.Locals("menu_id", menuId) c.Locals("user_level_id", userLevelId) return c.Next() } } // CheckMenuActionAccess middleware untuk validasi akses user_level ke action tertentu di dalam menu func (m *MenuActionAccessMiddleware) CheckMenuActionAccess(menuId uint, actionCode string) fiber.Handler { return func(c *fiber.Ctx) error { // Get user from context userCtx := c.Locals("user") if userCtx == nil { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "success": false, "code": 401, "messages": []string{"User tidak terautentikasi"}, }) } user, ok := userCtx.(*entity.Users) if !ok || user == nil { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "success": false, "code": 401, "messages": []string{"User tidak valid"}, }) } // Get user role untuk mendapatkan user_level_id var userRole entity.UserRoles if err := m.DB.DB.Where("id = ?", user.UserRoleId).First(&userRole).Error; err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "success": false, "code": 500, "messages": []string{"Error mendapatkan user role"}, "error": err.Error(), }) } userLevelId := userRole.UserLevelId // First, check if user has access to the menu var menuAccess entity.UserLevelMenuAccesses err := m.DB.DB.Where( "user_level_id = ? AND menu_id = ? AND is_active = ? AND can_access = ?", userLevelId, menuId, true, true, ).First(&menuAccess).Error if err != nil { return c.Status(fiber.StatusForbidden).JSON(fiber.Map{ "success": false, "code": 403, "messages": []string{"Anda tidak memiliki akses ke menu ini"}, "user_level_id": userLevelId, "menu_id": menuId, }) } // Then, check if user has access to the specific action var actionAccess entity.UserLevelMenuActionAccesses err = m.DB.DB.Where( "user_level_id = ? AND menu_id = ? AND action_code = ? AND is_active = ? AND can_access = ?", userLevelId, menuId, actionCode, true, true, ).First(&actionAccess).Error if err != nil { return c.Status(fiber.StatusForbidden).JSON(fiber.Map{ "success": false, "code": 403, "messages": []string{"Anda tidak memiliki akses untuk melakukan action ini"}, "user_level_id": userLevelId, "menu_id": menuId, "action_code": actionCode, }) } // Set to context c.Locals("menu_id", menuId) c.Locals("action_code", actionCode) c.Locals("user_level_id", userLevelId) return c.Next() } }