kra-new/internal/data/repository/migrations.go

175 lines
5.7 KiB
Go

package system
import (
"errors"
"kra/pkg/database/migration"
"gorm.io/gorm"
)
// Migrations returns schema steps owned by the built-in system module.
// Administrators, menus, APIs, and policies are created only by SeedSystem
// during the explicit first-install flow.
func Migrations() []migration.Step {
return []migration.Step{
{
ID: "202608200002_system_schema",
Migrate: func(db *gorm.DB) error {
return migration.CreateMissingTables(db,
&userPO{}, &authorityPO{}, &menuPO{}, &userAuthorityPO{}, &authorityMenuPO{}, &menuParameterPO{},
&apiPO{}, &ignoredAPIPO{}, &authorityAPIPO{}, &casbinRulePO{}, &menuButtonPO{}, &authorityButtonPO{},
&departmentPO{}, &positionPO{}, &userDepartmentPO{}, &userPositionPO{}, &authorityDepartmentPO{},
&dictionaryPO{}, &dictionaryDetailPO{}, &parameterPO{}, &apiTokenPO{}, &jwtBlacklistPO{}, &SecurityConfigPO{},
&versionPO{}, &exportTemplatePO{}, &exportConditionPO{}, &exportJoinPO{},
&operationPO{}, &loginLogPO{}, &dataAccessLogPO{}, &errorRecordPO{},
&taskPO{}, &taskLogPO{}, &mediaPO{}, &categoryPO{}, &uploadSessionPO{}, &uploadChunkPO{},
&announcementPO{},
)
},
},
{ID: "202608210002_communication_surface", Migrate: ensureCommunicationSurface},
{ID: "202608210003_communication_test_surface", Migrate: ensureCommunicationTestSurface},
}
}
func ensureCommunicationSurface(db *gorm.DB) error {
if db == nil || !db.Migrator().HasTable(&menuPO{}) || !db.Migrator().HasTable(&apiPO{}) {
return nil
}
return db.Transaction(func(tx *gorm.DB) error {
var parent menuPO
if err := tx.Where("name = ?", "extensions").First(&parent).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil
}
return err
}
menu := menuPO{
MenuLevel: 1,
ParentID: parent.ID,
Path: "integrationConfig",
Name: "integrationConfig",
Component: "view/systemTools/integration/config.vue",
Title: "通信集成",
Icon: "connection",
Sort: 8,
}
var current menuPO
err := tx.Where("name = ?", menu.Name).First(&current).Error
switch {
case errors.Is(err, gorm.ErrRecordNotFound):
if err = tx.Create(&menu).Error; err != nil {
return err
}
case err != nil:
return err
default:
if err = tx.Model(&current).Updates(map[string]any{
"menu_level": menu.MenuLevel,
"parent_id": menu.ParentID,
"path": menu.Path,
"component": menu.Component,
"title": menu.Title,
"icon": menu.Icon,
"sort": menu.Sort,
}).Error; err != nil {
return err
}
menu.ID = current.ID
}
apis := []apiPO{
{Path: "/integration/configs/:kind", Method: "GET", APIGroup: "集成配置", Description: "按类型获取集成配置"},
{Path: "/integration/configs/:kind/:provider", Method: "GET", APIGroup: "集成配置", Description: "获取指定集成配置"},
{Path: "/integration/configs/:kind/:provider", Method: "PUT", APIGroup: "集成配置", Description: "保存集成配置"},
{Path: "/integration/configs/:kind/:provider/test", Method: "POST", APIGroup: "集成配置", Description: "测试通信集成连接"},
{Path: "/integration/configs/:kind/:provider", Method: "DELETE", APIGroup: "集成配置", Description: "删除集成配置"},
}
for _, api := range apis {
if err := tx.Where("path = ? AND method = ?", api.Path, api.Method).FirstOrCreate(&api).Error; err != nil {
return err
}
}
if !tx.Migrator().HasTable(&authorityPO{}) || !tx.Migrator().HasTable(&authorityMenuPO{}) || !tx.Migrator().HasTable(&casbinRulePO{}) {
return nil
}
var authority authorityPO
if err := tx.Where("authority_id = ?", 888).First(&authority).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil
}
return err
}
var linkCount int64
if err := tx.Model(&authorityMenuPO{}).Where("sys_authority_authority_id = ? AND sys_base_menu_id = ?", authority.AuthorityID, menu.ID).Count(&linkCount).Error; err != nil {
return err
}
if linkCount == 0 {
if err := tx.Create(&authorityMenuPO{SysAuthorityAuthorityID: authority.AuthorityID, SysBaseMenuID: menu.ID}).Error; err != nil {
return err
}
}
for _, api := range apis {
exists, err := policyExists(tx, authority.AuthorityID, api.Path, api.Method)
if err != nil {
return err
}
if !exists {
rule := newPolicyRule(authority.AuthorityID, api.Path, api.Method)
if err := tx.Create(&rule).Error; err != nil {
return err
}
}
}
return nil
})
}
func ensureCommunicationTestSurface(db *gorm.DB) error {
if db == nil || !db.Migrator().HasTable(&menuPO{}) || !db.Migrator().HasTable(&apiPO{}) {
return nil
}
return db.Transaction(func(tx *gorm.DB) error {
var existingMenus int64
if err := tx.Model(&menuPO{}).Where("name IN ?", []string{"extensions", "integrationConfig"}).Count(&existingMenus).Error; err != nil {
return err
}
if existingMenus == 0 {
return nil
}
api := apiPO{
Path: "/integration/configs/:kind/:provider/test",
Method: "POST",
APIGroup: "集成配置",
Description: "测试通信集成连接",
}
if err := tx.Where("path = ? AND method = ?", api.Path, api.Method).FirstOrCreate(&api).Error; err != nil {
return err
}
if !tx.Migrator().HasTable(&authorityPO{}) || !tx.Migrator().HasTable(&casbinRulePO{}) {
return nil
}
var authority authorityPO
if err := tx.Where("authority_id = ?", 888).First(&authority).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil
}
return err
}
exists, err := policyExists(tx, authority.AuthorityID, api.Path, api.Method)
if err != nil {
return err
}
if exists {
return nil
}
rule := newPolicyRule(authority.AuthorityID, api.Path, api.Method)
return tx.Create(&rule).Error
})
}