package repository import ( "context" "github.com/Caknoooo/go-gin-clean-starter/database/entities" "github.com/google/uuid" "gorm.io/gorm" "gorm.io/gorm/clause" ) // UserRepository interface { // Register(ctx context.Context, tx *gorm.DB, user entities.M_User) (entities.M_User, error) // GetUserById(ctx context.Context, tx *gorm.DB, userId string) (entities.M_User, error) // GetUserByEmail(ctx context.Context, tx *gorm.DB, email string) (entities.M_User, error) // CheckEmail(ctx context.Context, tx *gorm.DB, email string) (entities.M_User, bool, error) // Update(ctx context.Context, tx *gorm.DB, user entities.M_User) (entities.M_User, error) // Delete(ctx context.Context, tx *gorm.DB, userId string) error // SwitchRole(ctx context.Context, tx *gorm.DB, userId string, roleId string) (entities.M_User, error) // } type RoleRepository interface { CreateRole(ctx context.Context, tx *gorm.DB, role entities.M_Role) (entities.M_Role, error) GetRoleByID(ctx context.Context, tx *gorm.DB, id string) (entities.M_Role, error) UpdateRole(ctx context.Context, tx *gorm.DB, role entities.M_Role) (entities.M_Role, error) DeleteRole(ctx context.Context, tx *gorm.DB, id string) error AssignPermissionsToRole(ctx context.Context, tx *gorm.DB, roleId string, permissions []string) error RemovePermissionsFromRole(ctx context.Context, tx *gorm.DB, roleId string, permissions []string) error AssignRoleToUser(ctx context.Context, tx *gorm.DB, userId string, roleId string) error RemoveRoleFromUser(ctx context.Context, tx *gorm.DB, userId string, roleId string) error GetRolesByUserID(ctx context.Context, tx *gorm.DB, userId string) ([]entities.M_Role, error) CheckRoleName(ctx context.Context, tx *gorm.DB, name string) (entities.M_Role, bool, error) AssignMenusToRole(ctx context.Context, tx *gorm.DB, roleId string, menus []string) error RemoveMenusFromRole(ctx context.Context, tx *gorm.DB, roleId string, menus []string) error GetAll(ctx context.Context, tx *gorm.DB) ([]entities.M_Role, error) } type roleRepository struct { db *gorm.DB } // GetAll implements RoleRepository. func (r *roleRepository) GetAll(ctx context.Context, tx *gorm.DB) ([]entities.M_Role, error) { if tx == nil { tx = r.db } var roles []entities.M_Role if err := tx.WithContext(ctx). Preload("Client"). Preload("Permissions"). Preload("Menus"). Find(&roles).Error; err != nil { return nil, err } return roles, nil } // AssignMenusToRole implements RoleRepository. func (r *roleRepository) AssignMenusToRole(ctx context.Context, tx *gorm.DB, roleId string, menus []string) error { if tx == nil { tx = r.db } roleUUID, err := uuid.Parse(roleId) if err != nil { return err } var roleMenus []entities.M_Role_Menu for _, menuId := range menus { menuUUID, err := uuid.Parse(menuId) if err != nil { return err } roleMenus = append(roleMenus, entities.M_Role_Menu{ RoleID: roleUUID, MenuID: menuUUID, }) } // Use Create with OnConflict to avoid duplicate entries if err := tx.WithContext(ctx).Clauses( clause.OnConflict{DoNothing: true}, ).Create(&roleMenus).Error; err != nil { return err } return nil } // RemoveMenusFromRole implements RoleRepository. func (r *roleRepository) RemoveMenusFromRole(ctx context.Context, tx *gorm.DB, roleId string, menus []string) error { if tx == nil { tx = r.db } roleUUID, err := uuid.Parse(roleId) if err != nil { return err } menuUUIDs := make([]uuid.UUID, 0, len(menus)) for _, menuId := range menus { menuUUID, err := uuid.Parse(menuId) if err != nil { return err } menuUUIDs = append(menuUUIDs, menuUUID) } if err := tx.WithContext(ctx). Where("role_id = ? AND menu_id IN ?", roleUUID, menuUUIDs). Delete(&entities.M_Role_Menu{}).Error; err != nil { return err } return nil } // CheckRoleName implements RoleRepository. func (r *roleRepository) CheckRoleName(ctx context.Context, tx *gorm.DB, name string) (entities.M_Role, bool, error) { if tx == nil { tx = r.db } var role entities.M_Role if err := tx.WithContext(ctx).Where("name = ?", name).First(&role).Error; err != nil { if err == gorm.ErrRecordNotFound { return entities.M_Role{}, false, nil } return entities.M_Role{}, false, err } return role, true, nil } // AssignPermissionsToRole implements RoleRepository. func (r *roleRepository) AssignPermissionsToRole(ctx context.Context, tx *gorm.DB, roleId string, permissions []string) error { if tx == nil { tx = r.db } if err := tx.WithContext(ctx).Model(&entities.M_Role{}).Where("id = ?", roleId).Update("permissions", gorm.Expr("array_cat(permissions, ?)", permissions)).Error; err != nil { return err } return nil } func (r *roleRepository) AssignRoleToUser(ctx context.Context, tx *gorm.DB, userId string, roleId string) error { if tx == nil { tx = r.db } userUUID, err := uuid.Parse(userId) if err != nil { return err } roleUUID, err := uuid.Parse(roleId) if err != nil { return err } var count int64 if err := tx.WithContext(ctx). Model(&entities.M_User_Role{}). Where("user_id = ? AND role_id = ?", userUUID, roleUUID). Count(&count).Error; err != nil { return err } if count > 0 { return nil } userRole := entities.M_User_Role{ UserID: userUUID, RoleID: roleUUID, } // Insert ke tabel user_roles, bukan update ke M_User if err := tx.WithContext(ctx).Create(&userRole).Error; err != nil { return err } return nil } // CreateRole implements RoleRepository. func (r *roleRepository) CreateRole(ctx context.Context, tx *gorm.DB, role entities.M_Role) (entities.M_Role, error) { if tx == nil { tx = r.db } if err := tx.WithContext(ctx).Create(&role).Error; err != nil { return entities.M_Role{}, err } return role, nil } // DeleteRole implements RoleRepository. func (r *roleRepository) DeleteRole(ctx context.Context, tx *gorm.DB, id string) error { if tx == nil { tx = r.db } if err := tx.WithContext(ctx).Where("id = ?", id).Delete(&entities.M_Role{}).Error; err != nil { return err } return nil } // GetRoleByID implements RoleRepository. func (r *roleRepository) GetRoleByID(ctx context.Context, tx *gorm.DB, id string) (entities.M_Role, error) { if tx == nil { tx = r.db } var role entities.M_Role if err := tx.WithContext(ctx). Preload("Client"). Preload("Permissions"). Preload("Menus"). Preload("Menus.Parent"). Where("id = ?", id). First(&role).Error; err != nil { return entities.M_Role{}, err } return role, nil } // GetRolesByUserID implements RoleRepository. func (r *roleRepository) GetRolesByUserID(ctx context.Context, tx *gorm.DB, userId string) ([]entities.M_Role, error) { if tx == nil { tx = r.db } var roles []entities.M_Role if err := tx.WithContext(ctx). Model(&entities.M_Role{}). Joins("JOIN m_user_roles ur ON ur.role_id = m_roles.id"). Where("ur.user_id = ?", userId). Preload("Client"). Preload("Permissions"). Find(&roles).Error; err != nil { return nil, err } return roles, nil } // RemovePermissionsFromRole implements RoleRepository. func (r *roleRepository) RemovePermissionsFromRole(ctx context.Context, tx *gorm.DB, roleId string, permissions []string) error { if tx == nil { tx = r.db } if err := tx.WithContext(ctx).Model(&entities.M_Role{}).Where("id = ?", roleId).Update("permissions", gorm.Expr("array_remove(permissions, ?)", permissions)).Error; err != nil { return err } return nil } // RemoveRoleFromUser implements RoleRepository. func (r *roleRepository) RemoveRoleFromUser(ctx context.Context, tx *gorm.DB, userId string, roleId string) error { if tx == nil { tx = r.db } userUUID, err := uuid.Parse(userId) if err != nil { return err } roleUUID, err := uuid.Parse(roleId) if err != nil { return err } var count int64 if err := tx.WithContext(ctx). Model(&entities.M_User_Role{}). Where("user_id = ? AND role_id = ?", userUUID, roleUUID). Count(&count).Error; err != nil { return err } if count > 0 { return nil } userRole := entities.M_User_Role{ UserID: userUUID, RoleID: roleUUID, } // Delete ke tabel user_roles, bukan update ke M_User if err := tx.WithContext(ctx).Delete(&userRole).Error; err != nil { return err } return nil } // UpdateRole implements RoleRepository. func (r *roleRepository) UpdateRole(ctx context.Context, tx *gorm.DB, role entities.M_Role) (entities.M_Role, error) { if tx == nil { tx = r.db } if err := tx.WithContext(ctx).Updates(&role).Error; err != nil { return entities.M_Role{}, err } return role, nil } func NewRoleRepository(db *gorm.DB) RoleRepository { return &roleRepository{ db: db, } }