feat: integrate OA activation workflows and business migration
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
package business
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
datasystem "kra/internal/data/system"
|
||||
"kra/internal/modules/surface"
|
||||
"kra/pkg/module"
|
||||
)
|
||||
|
||||
func migrateActivationSurface(db *gorm.DB) error {
|
||||
if !db.Migrator().HasTable("sys_authorities") {
|
||||
return nil
|
||||
}
|
||||
var roots int64
|
||||
if err := db.Table("sys_authorities").Where("authority_id=888 AND deleted_at IS NULL").Count(&roots).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if roots == 0 {
|
||||
return nil
|
||||
}
|
||||
if db.Migrator().HasTable("sys_base_menus") {
|
||||
if err := db.Table("sys_base_menus").Where("name=?", "sw_ChannelActivationList").Update("title", "激活列表").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
apis := surface.APIsForPrefix("/sw/promoteActivePool/", 0)
|
||||
if err := datasystem.EnsureAdminSurface(db, module.Surface{APIs: apis}, 888); err != nil {
|
||||
return err
|
||||
}
|
||||
// 申请绑定与流失记录对各级商务开放,升级旧的仅三级菜单授权。
|
||||
if db.Migrator().HasTable("sys_authority_menus") && db.Migrator().HasTable("sys_base_menus") {
|
||||
if err := db.Exec(`INSERT INTO sys_authority_menus(sys_authority_authority_id,sys_base_menu_id)
|
||||
SELECT a.authority_id,m.id FROM sys_authorities a CROSS JOIN sys_base_menus m
|
||||
WHERE a.business_level IN (1,2,3) AND a.deleted_at IS NULL AND m.deleted_at IS NULL
|
||||
AND m.name IN ('sw_ChannelActivationList','sw_BusMgmt')
|
||||
AND NOT EXISTS (SELECT 1 FROM sys_authority_menus x WHERE x.sys_authority_authority_id=a.authority_id AND x.sys_base_menu_id=m.id)`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return datasystem.GrantMenuAPIs(db, "sw_ChannelActivationList", apis)
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package business
|
||||
|
||||
import (
|
||||
"github.com/glebarez/sqlite"
|
||||
"gorm.io/gorm"
|
||||
datasystem "kra/internal/data/system"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestActivationUpgradeGivesAllBusinessLevelsApplicationAccess(t *testing.T) {
|
||||
db, err := gorm.Open(sqlite.Open(filepath.Join(t.TempDir(), "surface.db")), &gorm.Config{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pool, _ := db.DB()
|
||||
defer pool.Close()
|
||||
for _, step := range datasystem.Migrations() {
|
||||
if err := step.Migrate(db); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for _, sql := range []string{"INSERT INTO sys_authorities(authority_id,business_level) VALUES(888,NULL),(41,1),(57,2),(83,3),(100,NULL)", "INSERT INTO sys_base_menus(id,name,title) VALUES(1,'sw_BusMgmt','商务管理'),(2,'sw_ChannelActivationList','渠道激活')"} {
|
||||
if err := db.Exec(sql).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for i := 0; i < 2; i++ {
|
||||
if err := migrateActivationSurface(db); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
var count int64
|
||||
if err := db.Table("sys_authority_menus").Where("sys_base_menu_id=2 AND sys_authority_authority_id IN (41,57,83)").Count(&count).Error; err != nil || count != 3 {
|
||||
t.Fatalf("business menu access %d: %v", count, err)
|
||||
}
|
||||
if err := db.Table("casbin_rule").Where("v0 IN ('41','57','83') AND v1='/sw/promoteActivePool/apply' AND v2='POST'").Count(&count).Error; err != nil || count != 3 {
|
||||
t.Fatalf("application grants %d: %v", count, err)
|
||||
}
|
||||
if err := db.Table("casbin_rule").Where("v0='100' AND v1='/sw/promoteActivePool/apply'").Count(&count).Error; err != nil || count != 0 {
|
||||
t.Fatal("unrelated role received grant")
|
||||
}
|
||||
}
|
||||
@@ -106,6 +106,7 @@ func Definition() module.Definition {
|
||||
})
|
||||
}})
|
||||
migrations = append(migrations, migration.Step{ID: "202611050021_business_alert_surface", Migrate: migrateAlertSurface})
|
||||
migrations = append(migrations, migration.Step{ID: "202611060025_business_activation_surface", Migrate: migrateActivationSurface})
|
||||
definition := module.Definition{Name: "business", Migrations: migrations, Prerequisites: databusiness.CheckPrerequisites, ValidateSchema: databusiness.CheckSchema, TimedTasks: append([]module.TimedTask{alertDetectionTask}, tasks...), Surface: module.Surface{
|
||||
Menus: []module.Menu{
|
||||
alertExemptionMenu,
|
||||
@@ -119,7 +120,7 @@ func Definition() module.Definition {
|
||||
{Name: "sw_RegistrationDetails", Path: "RegistrationDetails", ParentName: "sw_DataAnalysis", Component: "view/sw/RegistrationDetails.vue", Title: "注册明细", Icon: databusiness.MenuIcon("sw_RegistrationDetails"), Sort: 3},
|
||||
{Name: "sw_RechargeDetails", Path: "RechargeDetails", ParentName: "sw_DataAnalysis", Component: "view/sw/RechargeDetails.vue", Title: "充值明细", Icon: databusiness.MenuIcon("sw_RechargeDetails"), Sort: 2},
|
||||
{Name: "sw_ChannelList", Path: "ChannelList", ParentName: "sw_BusMgmt", Component: "view/sw/ChannelList.vue", Title: "渠道列表", Icon: databusiness.MenuIcon("sw_ChannelList"), Sort: 2},
|
||||
{Name: "sw_ChannelActivationList", Path: "ChannelActivationList", ParentName: "sw_BusMgmt", Component: "view/sw/ChannelActivationList.vue", Title: "渠道激活", Icon: databusiness.MenuIcon("sw_ChannelActivationList"), Sort: 3},
|
||||
{Name: "sw_ChannelActivationList", Path: "ChannelActivationList", ParentName: "sw_BusMgmt", Component: "view/sw/ChannelActivationList.vue", Title: "激活列表", Icon: databusiness.MenuIcon("sw_ChannelActivationList"), Sort: 3},
|
||||
{Name: "sw_AlertList", Path: "AlertList", ParentName: "sw_AlertCenter", Component: "view/sw/AlertList.vue", Title: "预警列表", Icon: databusiness.MenuIcon("sw_AlertList"), Sort: 1},
|
||||
{Name: "sw_AlertCenter", Path: "sw-AlertCenter", Component: "view/routerHolder.vue", Title: "预警中心", Icon: databusiness.MenuIcon("sw_AlertCenter"), Sort: 4},
|
||||
{Name: "sw_AlertRules", Path: "AlertRules", ParentName: "sw_AlertCenter", Component: "view/sw/AlertRules.vue", Title: "预警规则", Icon: databusiness.MenuIcon("sw_AlertRules"), Sort: 2},
|
||||
|
||||
@@ -25,16 +25,16 @@ func TestCatalogContainsBuiltInModulesInDependencyOrder(t *testing.T) {
|
||||
t.Fatalf("definition[%d] = %q, want %q", index, got, name)
|
||||
}
|
||||
}
|
||||
if got := catalog.MigrationSteps(); len(got) != 39 {
|
||||
t.Fatalf("module migrations = %d, want 39", len(got))
|
||||
if got := catalog.MigrationSteps(); len(got) != 41 {
|
||||
t.Fatalf("module migrations = %d, want 41", len(got))
|
||||
}
|
||||
var menus, apis int
|
||||
for _, definition := range catalog.Definitions {
|
||||
menus += len(definition.Surface.Menus)
|
||||
apis += len(definition.Surface.APIs)
|
||||
}
|
||||
if menus != 21 || apis != 90 {
|
||||
t.Fatalf("admin surface = %d menus/%d APIs, want 21/90", menus, apis)
|
||||
if menus != 21 || apis != 94 {
|
||||
t.Fatalf("admin surface = %d menus/%d APIs, want 21/94", menus, apis)
|
||||
}
|
||||
if got := catalog.DefaultTimedTasks(); len(got) != 5 {
|
||||
t.Fatalf("default timed tasks = %d, want 5", len(got))
|
||||
|
||||
Reference in New Issue
Block a user