From 37d656999e229e94df69c0de91826214579448e4 Mon Sep 17 00:00:00 2001 From: Habib Fatkhul Rohman Date: Tue, 21 Oct 2025 20:05:14 +0700 Subject: [PATCH] feat: Implement seeders for menus, permissions, and role-permission associations --- database/entities/m_permissions_entity.go | 2 - database/entities/m_role_permission_entity.go | 3 +- database/seeder.go | 3 + database/seeders/json/menus.json | 57 ++++++++++ database/seeders/json/permissions.json | 50 +++++++++ database/seeders/json/role_permissions.json | 96 +++++++++++++++++ database/seeders/seeds/menu_seed.go | 102 ++++++++++++++++++ database/seeders/seeds/permission_seed.go | 65 +++++++++++ .../seeders/seeds/role_permission_seed.go | 59 ++++++++++ 9 files changed, 433 insertions(+), 4 deletions(-) create mode 100644 database/seeders/json/menus.json create mode 100644 database/seeders/json/permissions.json create mode 100644 database/seeders/json/role_permissions.json create mode 100644 database/seeders/seeds/menu_seed.go create mode 100644 database/seeders/seeds/permission_seed.go create mode 100644 database/seeders/seeds/role_permission_seed.go diff --git a/database/entities/m_permissions_entity.go b/database/entities/m_permissions_entity.go index e453b4d..a63a919 100644 --- a/database/entities/m_permissions_entity.go +++ b/database/entities/m_permissions_entity.go @@ -8,10 +8,8 @@ type M_Permissions struct { ID uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"` Name string `gorm:"type:varchar(100);not null" json:"name"` MenuID uuid.UUID `gorm:"type:uuid;not null;index" json:"menu_id"` - RoleID uuid.UUID `gorm:"type:uuid;not null;index" json:"role_id"` // <-- Add this line Menu M_Menu `gorm:"foreignKey:MenuID;references:ID"` - Role M_Role `gorm:"foreignKey:RoleID;references:ID"` FullAuditTrail } diff --git a/database/entities/m_role_permission_entity.go b/database/entities/m_role_permission_entity.go index c1e5001..07bea6d 100644 --- a/database/entities/m_role_permission_entity.go +++ b/database/entities/m_role_permission_entity.go @@ -5,11 +5,10 @@ import ( ) type M_Role_Permission struct { - ID uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"` RoleID uuid.UUID `gorm:"type:uuid;not null;index" json:"role_id"` PermissionID uuid.UUID `gorm:"type:uuid;not null;index" json:"permission_id"` - Role M_Role `gorm:"foreignKey:RoleID;references:ID"` + Role M_Role `gorm:"foreignKey:RoleID;references:ID"` Permission M_Permissions `gorm:"foreignKey:PermissionID;references:ID"` FullAuditTrail diff --git a/database/seeder.go b/database/seeder.go index 25f9411..fb56030 100644 --- a/database/seeder.go +++ b/database/seeder.go @@ -8,9 +8,12 @@ import ( func Seeder(db *gorm.DB) error { seeders := []func(*gorm.DB) error{ seeds.ListClientSeeder, + seeds.ListMenuSeeder, seeds.ListUserSeeder, seeds.ListRoleSeeder, seeds.ListUserRoleSeeder, + seeds.ListPermissionSeeder, + seeds.ListRolePermissionSeeder, } for _, seeder := range seeders { diff --git a/database/seeders/json/menus.json b/database/seeders/json/menus.json new file mode 100644 index 0000000..138dc56 --- /dev/null +++ b/database/seeders/json/menus.json @@ -0,0 +1,57 @@ +[ + { + "id": "c1a8f3b0-1234-4f7d-bc91-9b1f52e91a01", + "name": "Dashboard", + "icon_url": "/icons/dashboard.svg", + "url": "/dashboard", + "sequence": 1, + "mode": "desktop", + "table_name": "m_dashboard", + "status": "active", + "parent_id": null + }, + { + "id": "f7e1c5d2-5678-4b8a-bdf3-37b3a76c4e3a", + "name": "Users", + "icon_url": "/icons/users.svg", + "url": "/master/users", + "sequence": 2, + "mode": "desktop", + "table_name": "m_users", + "status": "active", + "parent_id": "c1a8f3b0-1234-4f7d-bc91-9b1f52e91a01" + }, + { + "id": "a2e5d6b4-9c1f-4c7b-b9a7-6f2a5d4b1a99", + "name": "Roles & Permissions", + "icon_url": "/icons/roles.svg", + "url": "/master/roles", + "sequence": 3, + "mode": "desktop", + "table_name": "m_roles", + "status": "active", + "parent_id": "c1a8f3b0-1234-4f7d-bc91-9b1f52e91a01" + }, + { + "id": "e9f6a2c7-8b1d-45ac-a0b3-6c8b52d8a5e3", + "name": "Products", + "icon_url": "/icons/products.svg", + "url": "/master/products", + "sequence": 4, + "mode": "desktop", + "table_name": "m_products", + "status": "active", + "parent_id": null + }, + { + "id": "d3b7e1f5-4c2a-496b-9e9a-2c9d7d3f6f1b", + "name": "Reports", + "icon_url": "/icons/reports.svg", + "url": "/reports", + "sequence": 5, + "mode": "desktop", + "table_name": "m_reports", + "status": "inactive", + "parent_id": null + } +] diff --git a/database/seeders/json/permissions.json b/database/seeders/json/permissions.json new file mode 100644 index 0000000..8dd1c8c --- /dev/null +++ b/database/seeders/json/permissions.json @@ -0,0 +1,50 @@ +[ + { + "name": "View-Dashboard", + "menu_name": "Dashboard" + }, + { + "name": "Create-User", + "menu_name": "Users" + }, + { + "name": "Edit-User", + "menu_name": "Users" + }, + { + "name": "Delete-User", + "menu_name": "Users" + }, + { + "name": "View-Roles", + "menu_name": "Roles & Permissions" + }, + { + "name": "Assign-Role-Permission", + "menu_name": "Roles & Permissions" + }, + { + "name": "View-Products", + "menu_name": "Products" + }, + { + "name": "Add-Product", + "menu_name": "Products" + }, + { + "name": "Edit-Product", + "menu_name": "Products" + }, + { + "name": "Delete-Product", + "menu_name": "Products" + }, + { + "name": "Generate-Report", + "menu_name": "Reports" + }, + { + "name": "Export-Report", + "menu_name": "Reports" + } +] diff --git a/database/seeders/json/role_permissions.json b/database/seeders/json/role_permissions.json new file mode 100644 index 0000000..ec546b2 --- /dev/null +++ b/database/seeders/json/role_permissions.json @@ -0,0 +1,96 @@ +[ + { + "role_name": "Super Admin", + "permission_name": "View-Dashboard" + }, + { + "role_name": "Super Admin", + "permission_name": "Create-User" + }, + { + "role_name": "Super Admin", + "permission_name": "Edit-User" + }, + { + "role_name": "Super Admin", + "permission_name": "Delete-User" + }, + { + "role_name": "Super Admin", + "permission_name": "View-Roles" + }, + { + "role_name": "Super Admin", + "permission_name": "Assign-Role-Permission" + }, + { + "role_name": "Super Admin", + "permission_name": "View-Products" + }, + { + "role_name": "Super Admin", + "permission_name": "Add-Product" + }, + { + "role_name": "Super Admin", + "permission_name": "Edit-Product" + }, + { + "role_name": "Super Admin", + "permission_name": "Delete-Product" + }, + { + "role_name": "Super Admin", + "permission_name": "Generate-Report" + }, + { + "role_name": "Super Admin", + "permission_name": "Export-Report" + }, + + { + "role_name": "Admin", + "permission_name": "View-Dashboard" + }, + { + "role_name": "Admin", + "permission_name": "Create-User" + }, + { + "role_name": "Admin", + "permission_name": "Edit-User" + }, + { + "role_name": "Admin", + "permission_name": "View-Roles" + }, + { + "role_name": "Admin", + "permission_name": "Assign-Role-Permission" + }, + { + "role_name": "Admin", + "permission_name": "View-Products" + }, + { + "role_name": "Admin", + "permission_name": "Add-Product" + }, + { + "role_name": "Admin", + "permission_name": "Edit-Product" + }, + { + "role_name": "Admin", + "permission_name": "Generate-Report" + }, + + { + "role_name": "User", + "permission_name": "View-Dashboard" + }, + { + "role_name": "User", + "permission_name": "View-Products" + } +] diff --git a/database/seeders/seeds/menu_seed.go b/database/seeders/seeds/menu_seed.go new file mode 100644 index 0000000..a3332af --- /dev/null +++ b/database/seeders/seeds/menu_seed.go @@ -0,0 +1,102 @@ +package seeds + +import ( + "encoding/json" + "fmt" + "io" + "os" + + "github.com/Caknoooo/go-gin-clean-starter/database/entities" + "github.com/google/uuid" + "gorm.io/gorm" +) + +// { +// "id": "d3b7e1f5-4c2a-496b-9e9a-2c9d7d3f6f1b", +// "name": "Reports", +// "icon_url": "/icons/reports.svg", +// "url": "/reports", +// "sequence": 5, +// "mode": "desktop", +// "table_name": "m_reports", +// "status": "inactive", +// "parent_id": null +// } +type MenuSeed struct { + ID string `json:"id"` + Name string `json:"name"` + IconUrl string `json:"icon_url"` + URL string `json:"url"` + Sequence int `json:"sequence"` + Mode string `json:"mode"` + TableName string `json:"table_name"` + Status string `json:"status"` + ParentID string `json:"parent_id"` +} + +func ListMenuSeeder(db *gorm.DB) error { + jsonFile, err := os.Open("./database/seeders/json/menus.json") + if err != nil { + fmt.Println("Error opening file:", err) + return err + } + + jsonData, err := io.ReadAll(jsonFile) + if err != nil { + fmt.Println("Error reading file:", err) + return err + } + + var listMenu []MenuSeed + if err := json.Unmarshal(jsonData, &listMenu); err != nil { + fmt.Println("Error unmarshalling JSON:", err) + return err + } + + hasTable := db.Migrator().HasTable(&entities.M_Menu{}) + if !hasTable { + fmt.Println("Creating table: M_Menu") + if err := db.Migrator().CreateTable(&entities.M_Menu{}); err != nil { + return err + } + } + for _, data := range listMenu { + var parentUUID *uuid.UUID + if data.ParentID != "" { + parsed, err := uuid.Parse(data.ParentID) + if err != nil { + fmt.Println("Error parsing ParentID:", err) + return err + } + parentUUID = &parsed + } + + menuID := uuid.Nil + if data.ID != "" { + parsedID, err := uuid.Parse(data.ID) + if err != nil { + fmt.Println("Error parsing Menu ID:", err) + return err + } + menuID = parsedID + } + + menu := entities.M_Menu{ + ID: menuID, + Name: data.Name, + IconUrl: data.IconUrl, + Url: data.URL, + Sequence: data.Sequence, + Mode: data.Mode, + TableName: data.TableName, + Status: data.Status, + ParentID: parentUUID, + } + + if err := db.Where("name = ?", data.Name).FirstOrCreate(&menu).Error; err != nil { + fmt.Println("Error seeding Menu:", err) + return err + } + } + return nil +} diff --git a/database/seeders/seeds/permission_seed.go b/database/seeders/seeds/permission_seed.go new file mode 100644 index 0000000..bdbf88b --- /dev/null +++ b/database/seeders/seeds/permission_seed.go @@ -0,0 +1,65 @@ +package seeds + +import ( + "encoding/json" + "fmt" + "io" + "os" + + "github.com/Caknoooo/go-gin-clean-starter/database/entities" + "gorm.io/gorm" +) + +type PermissionSeed struct { + ID string `json:"id"` + Name string `json:"name"` + MenuName string `json:"menu_name"` +} + +func ListPermissionSeeder(db *gorm.DB) error { + jsonFile, err := os.Open("./database/seeders/json/permissions.json") + if err != nil { + fmt.Println("Error opening file:", err) + return err + } + + jsonData, err := io.ReadAll(jsonFile) + if err != nil { + fmt.Println("Error reading file:", err) + return err + } + + var listPermission []PermissionSeed + if err := json.Unmarshal(jsonData, &listPermission); err != nil { + fmt.Println("Error unmarshalling JSON:", err) + return err + } + + hasTable := db.Migrator().HasTable(&entities.M_Permissions{}) + if !hasTable { + fmt.Println("Creating table: M_Permissions") + if err := db.Migrator().CreateTable(&entities.M_Permissions{}); err != nil { + return err + } + } + + for _, data := range listPermission { + var permission entities.M_Permissions + var menu entities.M_Menu + + if err := db.Where("name = ?", data.MenuName).First(&menu).Error; err != nil { + fmt.Println("Menu not found:", err) + return err // menu tidak ditemukan + } + + if err := db.FirstOrCreate(&permission, entities.M_Permissions{ + Name: data.Name, + MenuID: menu.ID, + }).Error; err != nil { + fmt.Println("Error seeding permission:", err) + return err + } + } + + return nil +} diff --git a/database/seeders/seeds/role_permission_seed.go b/database/seeders/seeds/role_permission_seed.go new file mode 100644 index 0000000..96fba91 --- /dev/null +++ b/database/seeders/seeds/role_permission_seed.go @@ -0,0 +1,59 @@ +package seeds + +import ( + "encoding/json" + "io" + "os" + + "github.com/Caknoooo/go-gin-clean-starter/database/entities" + "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +type RolePermissionSeed struct { + RoleName string `json:"role_name"` + PermissionName string `json:"permission_name"` +} + +func ListRolePermissionSeeder(db *gorm.DB) error { + jsonFile, err := os.Open("./database/seeders/json/role_permissions.json") + if err != nil { + return err + } + + jsonData, err := io.ReadAll(jsonFile) + if err != nil { + return err + } + + var listRolePermission []RolePermissionSeed + if err := json.Unmarshal(jsonData, &listRolePermission); err != nil { + return err + } + hasTable := db.Migrator().HasTable(&entities.M_Role_Permission{}) + if !hasTable { + if err := db.Migrator().CreateTable(&entities.M_Role_Permission{}); err != nil { + return err + } + } + for _, data := range listRolePermission { + var role entities.M_Role + var permission entities.M_Permissions + if err := db.Where("name = ?", data.RoleName).First(&role).Error; err != nil { + logrus.Error("Role not found: ", err) + return err // role tidak ditemukan + } + if err := db.Where("name = ?", data.PermissionName).First(&permission).Error; err != nil { + logrus.Error("Permission not found: ", err) + return err // permission tidak ditemukan + } + var rolePermission entities.M_Role_Permission + if err := db.FirstOrCreate(&rolePermission, entities.M_Role_Permission{ + RoleID: role.ID, + PermissionID: permission.ID, + }).Error; err != nil { + return err + } + } + return nil +}