From d9130d6d568bf34f66a0f724cfd21f801e4ea52e Mon Sep 17 00:00:00 2001 From: mlogclub Date: Sat, 2 May 2026 20:48:44 +0800 Subject: [PATCH] fix(ticket): remove obsolete ticket permissions --- ...008_sync_lightweight_ticket_permissions.go | 35 ++++++++ .../notification_permissions_test.go | 88 +++++++++++++++++++ 2 files changed, 123 insertions(+) diff --git a/internal/migration/000008_sync_lightweight_ticket_permissions.go b/internal/migration/000008_sync_lightweight_ticket_permissions.go index 58f99ce..91ecc9a 100644 --- a/internal/migration/000008_sync_lightweight_ticket_permissions.go +++ b/internal/migration/000008_sync_lightweight_ticket_permissions.go @@ -13,6 +13,9 @@ func init() { if err := resetLightweightTicketData(ctx.Tx); err != nil { return err } + if err := deleteObsoleteTicketPermissions(ctx.Tx); err != nil { + return err + } permissions, err := ensurePermissions(ctx.Tx) if err != nil { @@ -29,6 +32,38 @@ func init() { }) } +func deleteObsoleteTicketPermissions(tx *gorm.DB) error { + codes := obsoleteTicketPermissionCodes() + if len(codes) == 0 { + return nil + } + permissionIDs := tx.Model(&models.Permission{}).Select("id").Where("code IN ?", codes) + if err := tx.Where("permission_id IN (?)", permissionIDs).Delete(&models.RolePermission{}).Error; err != nil { + return err + } + permissionIDs = tx.Model(&models.Permission{}).Select("id").Where("code IN ?", codes) + if err := tx.Where("permission_id IN (?)", permissionIDs).Delete(&models.UserPermission{}).Error; err != nil { + return err + } + return tx.Where("code IN ?", codes).Delete(&models.Permission{}).Error +} + +func obsoleteTicketPermissionCodes() []string { + return []string{ + "ticket.reply", + "ticket.close", + "ticket.reopen", + "ticketResolutionCode.view", + "ticketResolutionCode.create", + "ticketResolutionCode.update", + "ticketResolutionCode.delete", + "ticketPriorityConfig.view", + "ticketPriorityConfig.create", + "ticketPriorityConfig.update", + "ticketPriorityConfig.delete", + } +} + func resetLightweightTicketData(tx *gorm.DB) error { for _, table := range lightweightTicketResetTables(tx) { if !tx.Migrator().HasTable(table) { diff --git a/internal/migration/notification_permissions_test.go b/internal/migration/notification_permissions_test.go index 6add982..f44ebb5 100644 --- a/internal/migration/notification_permissions_test.go +++ b/internal/migration/notification_permissions_test.go @@ -83,6 +83,70 @@ func TestLightweightTicketMigrationResetDeletesTicketData(t *testing.T) { assertTableCount(t, db, &models.TicketNoSequence{}, 0) } +func TestLightweightTicketMigrationDeletesObsoletePermissions(t *testing.T) { + db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=shared"), &gorm.Config{ + NamingStrategy: schema.NamingStrategy{ + TablePrefix: "t_", + SingularTable: true, + }, + }) + if err != nil { + t.Fatalf("open sqlite db: %v", err) + } + sqlDB, err := db.DB() + if err != nil { + t.Fatalf("get sqlite db: %v", err) + } + t.Cleanup(func() { + _ = sqlDB.Close() + }) + + if err := db.AutoMigrate(&models.Permission{}, &models.RolePermission{}, &models.UserPermission{}); err != nil { + t.Fatalf("AutoMigrate() error = %v", err) + } + + now := time.Now() + legacyPermission := &models.Permission{ + Name: "回复工单", + Code: "ticket.reply", + Type: "api", + GroupName: "ticket", + AuditFields: models.AuditFields{CreatedAt: now, UpdatedAt: now}, + } + currentPermission := &models.Permission{ + Name: "查看工单", + Code: "ticket.view", + Type: "api", + GroupName: "ticket", + AuditFields: models.AuditFields{CreatedAt: now, UpdatedAt: now}, + } + if err := db.Create(legacyPermission).Error; err != nil { + t.Fatalf("create legacy permission error = %v", err) + } + if err := db.Create(currentPermission).Error; err != nil { + t.Fatalf("create current permission error = %v", err) + } + if err := db.Create(&models.RolePermission{RoleID: 1, PermissionID: legacyPermission.ID, AuditFields: models.AuditFields{CreatedAt: now, UpdatedAt: now}}).Error; err != nil { + t.Fatalf("create legacy role permission error = %v", err) + } + if err := db.Create(&models.UserPermission{UserID: 1, PermissionID: legacyPermission.ID, Effect: 1, AuditFields: models.AuditFields{CreatedAt: now, UpdatedAt: now}}).Error; err != nil { + t.Fatalf("create legacy user permission error = %v", err) + } + if err := db.Create(&models.RolePermission{RoleID: 1, PermissionID: currentPermission.ID, AuditFields: models.AuditFields{CreatedAt: now, UpdatedAt: now}}).Error; err != nil { + t.Fatalf("create current role permission error = %v", err) + } + + if err := deleteObsoleteTicketPermissions(db); err != nil { + t.Fatalf("deleteObsoleteTicketPermissions() error = %v", err) + } + + assertPermissionCodeCount(t, db, "ticket.reply", 0) + assertPermissionCodeCount(t, db, "ticket.view", 1) + assertPermissionRelationCount(t, db, &models.RolePermission{}, legacyPermission.ID, 0) + assertPermissionRelationCount(t, db, &models.UserPermission{}, legacyPermission.ID, 0) + assertPermissionRelationCount(t, db, &models.RolePermission{}, currentPermission.ID, 1) +} + func assertTableCount(t *testing.T, db *gorm.DB, model any, expected int64) { t.Helper() @@ -94,3 +158,27 @@ func assertTableCount(t *testing.T, db *gorm.DB, model any, expected int64) { t.Fatalf("expected %T count %d, got %d", model, expected, count) } } + +func assertPermissionCodeCount(t *testing.T, db *gorm.DB, code string, expected int64) { + t.Helper() + + var count int64 + if err := db.Model(&models.Permission{}).Where("code = ?", code).Count(&count).Error; err != nil { + t.Fatalf("count permission %s error = %v", code, err) + } + if count != expected { + t.Fatalf("expected permission %s count %d, got %d", code, expected, count) + } +} + +func assertPermissionRelationCount(t *testing.T, db *gorm.DB, model any, permissionID int64, expected int64) { + t.Helper() + + var count int64 + if err := db.Model(model).Where("permission_id = ?", permissionID).Count(&count).Error; err != nil { + t.Fatalf("count %T permission %d error = %v", model, permissionID, err) + } + if count != expected { + t.Fatalf("expected %T permission %d count %d, got %d", model, permissionID, expected, count) + } +}