296 lines
8.3 KiB
Go
296 lines
8.3 KiB
Go
package middleware
|
|
|
|
import (
|
|
"netidhub-saas-be/app/database"
|
|
"netidhub-saas-be/app/database/entity"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
type ModuleAccessMiddleware struct {
|
|
DB *database.Database
|
|
}
|
|
|
|
func NewModuleAccessMiddleware(db *database.Database) *ModuleAccessMiddleware {
|
|
return &ModuleAccessMiddleware{
|
|
DB: db,
|
|
}
|
|
}
|
|
|
|
// CheckModuleAccess middleware untuk validasi akses user_level ke modul tertentu
|
|
// Menggunakan module_id atau path_url sebagai identifier
|
|
func (m *ModuleAccessMiddleware) CheckModuleAccess(moduleIdentifier interface{}) fiber.Handler {
|
|
return func(c *fiber.Ctx) error {
|
|
// Get user from context (diasumsikan sudah ada middleware auth yang set user ke 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"},
|
|
})
|
|
}
|
|
|
|
// Cast user dari context
|
|
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
|
|
|
|
// Dapatkan module berdasarkan identifier (bisa module_id atau path_url)
|
|
var module entity.MasterModules
|
|
var err error
|
|
|
|
switch v := moduleIdentifier.(type) {
|
|
case uint:
|
|
// Jika moduleIdentifier adalah ID
|
|
err = m.DB.DB.Where("id = ? AND is_active = ?", v, true).First(&module).Error
|
|
case string:
|
|
// Jika moduleIdentifier adalah path_url
|
|
err = m.DB.DB.Where("path_url = ? AND is_active = ?", v, true).First(&module).Error
|
|
default:
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
"success": false,
|
|
"code": 400,
|
|
"messages": []string{"Module identifier tidak valid"},
|
|
})
|
|
}
|
|
|
|
if err != nil {
|
|
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
|
|
"success": false,
|
|
"code": 404,
|
|
"messages": []string{"Module tidak ditemukan"},
|
|
})
|
|
}
|
|
|
|
// Check akses user_level ke module
|
|
var access entity.UserLevelModuleAccesses
|
|
err = m.DB.DB.Where(
|
|
"user_level_id = ? AND module_id = ? AND is_active = ?",
|
|
userLevelId,
|
|
module.ID,
|
|
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 modul ini"},
|
|
"user_level_id": userLevelId,
|
|
"module_id": module.ID,
|
|
"module_name": module.Name,
|
|
})
|
|
}
|
|
|
|
if !access.CanAccess {
|
|
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
|
|
"success": false,
|
|
"code": 403,
|
|
"messages": []string{"Akses ke modul ini ditolak"},
|
|
"user_level_id": userLevelId,
|
|
"module_id": module.ID,
|
|
"module_name": module.Name,
|
|
})
|
|
}
|
|
|
|
// Set module ke context untuk digunakan di handler
|
|
c.Locals("module", &module)
|
|
c.Locals("user_level_id", userLevelId)
|
|
|
|
return c.Next()
|
|
}
|
|
}
|
|
|
|
// CheckModuleAccessByPath middleware untuk validasi akses berdasarkan path yang sedang diakses
|
|
// Akan otomatis mencocokkan path dengan module.path_url
|
|
func (m *ModuleAccessMiddleware) CheckModuleAccessByPath() 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
|
|
currentPath := c.Path()
|
|
|
|
// Cari module berdasarkan path_url yang cocok
|
|
var module entity.MasterModules
|
|
err := m.DB.DB.Where("path_url = ? AND is_active = ?", currentPath, true).First(&module).Error
|
|
|
|
if err != nil {
|
|
// Jika module tidak ditemukan, bisa jadi path ini tidak perlu validasi modul
|
|
// Atau bisa langsung return error tergantung kebijakan
|
|
return c.Next() // Skip validation jika module tidak ditemukan
|
|
}
|
|
|
|
// Check akses user_level ke module
|
|
var access entity.UserLevelModuleAccesses
|
|
err = m.DB.DB.Where(
|
|
"user_level_id = ? AND module_id = ? AND is_active = ?",
|
|
userLevelId,
|
|
module.ID,
|
|
true,
|
|
).First(&access).Error
|
|
|
|
if err != nil || !access.CanAccess {
|
|
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
|
|
"success": false,
|
|
"code": 403,
|
|
"messages": []string{"Anda tidak memiliki akses ke halaman ini"},
|
|
"user_level_id": userLevelId,
|
|
"path": currentPath,
|
|
"module_name": module.Name,
|
|
})
|
|
}
|
|
|
|
// Set module ke context
|
|
c.Locals("module", &module)
|
|
c.Locals("user_level_id", userLevelId)
|
|
|
|
return c.Next()
|
|
}
|
|
}
|
|
|
|
// CheckMenuAccess middleware untuk validasi akses user_level ke menu beserta modul-modulnya
|
|
func (m *ModuleAccessMiddleware) 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
|
|
|
|
// Get menu
|
|
var menu entity.MasterMenus
|
|
if err := m.DB.DB.Where("id = ? AND is_active = ?", menuId, true).First(&menu).Error; err != nil {
|
|
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
|
|
"success": false,
|
|
"code": 404,
|
|
"messages": []string{"Menu tidak ditemukan"},
|
|
})
|
|
}
|
|
|
|
// Get semua modul yang ada di menu ini
|
|
var menuModules []entity.MenuModules
|
|
if err := m.DB.DB.Where("menu_id = ? AND is_active = ?", menuId, true).Find(&menuModules).Error; err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"success": false,
|
|
"code": 500,
|
|
"messages": []string{"Error mendapatkan menu modules"},
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
|
|
if len(menuModules) == 0 {
|
|
// Jika menu tidak punya modul, skip validasi
|
|
return c.Next()
|
|
}
|
|
|
|
// Check apakah user_level memiliki akses ke minimal satu modul di menu ini
|
|
hasAccess := false
|
|
for _, menuModule := range menuModules {
|
|
var access entity.UserLevelModuleAccesses
|
|
err := m.DB.DB.Where(
|
|
"user_level_id = ? AND module_id = ? AND is_active = ? AND can_access = ?",
|
|
userLevelId,
|
|
menuModule.ModuleId,
|
|
true,
|
|
true,
|
|
).First(&access).Error
|
|
|
|
if err == nil {
|
|
hasAccess = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !hasAccess {
|
|
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,
|
|
"menu_name": menu.Name,
|
|
})
|
|
}
|
|
|
|
// Set menu ke context
|
|
c.Locals("menu", &menu)
|
|
c.Locals("user_level_id", userLevelId)
|
|
|
|
return c.Next()
|
|
}
|
|
}
|