package version import ( "fmt" "runtime" "gorm.io/gorm" "gorm.io/gorm/clause" "git.ilapage.cn/ila/yovision/Sense/server/app/sense/credential" deviceModels "git.ilapage.cn/ila/yovision/Sense/server/app/sense/device/models" "git.ilapage.cn/ila/yovision/Sense/server/cmd/migrate/migration" migrationModels "git.ilapage.cn/ila/yovision/Sense/server/cmd/migrate/migration/models" common "git.ilapage.cn/ila/yovision/Sense/server/common/models" ) type deviceCasbinRule struct { ID uint `gorm:"primaryKey;autoIncrement"` Ptype string `gorm:"size:512;uniqueIndex:unique_index"` V0 string `gorm:"size:512;uniqueIndex:unique_index"` V1 string `gorm:"size:512;uniqueIndex:unique_index"` V2 string `gorm:"size:512;uniqueIndex:unique_index"` V3 string `gorm:"size:512;uniqueIndex:unique_index"` V4 string `gorm:"size:512;uniqueIndex:unique_index"` V5 string `gorm:"size:512;uniqueIndex:unique_index"` } func (deviceCasbinRule) TableName() string { return "casbin_rule" } func init() { _, fileName, _, _ := runtime.Caller(0) migration.Migrate.SetVersion(migration.GetFilename(fileName), migrateSenseDeviceLedger) } func migrateSenseDeviceLedger(db *gorm.DB, version string) error { return db.Transaction(func(tx *gorm.DB) error { if err := tx.AutoMigrate(&deviceModels.Device{}, &credential.DeviceCredential{}, &deviceCasbinRule{}); err != nil { return err } page, err := ensureDeviceMenu(tx, migrationModels.SysMenu{ MenuName: "SenseDeviceManage", Title: "设备管理", Icon: "monitor", Path: "/sense/devices", MenuType: "C", Permission: "sense:device:list", ParentId: 0, Component: "/sense/device/index", Sort: 5, Visible: "0", IsFrame: "1", }) if err != nil { return err } buttons := make([]migrationModels.SysMenu, 0, 4) for index, definition := range []struct{ name, title, action, permission string }{ {"SenseDeviceAdd", "新增设备", "POST", "sense:device:add"}, {"SenseDeviceEdit", "编辑设备", "PUT", "sense:device:edit"}, {"SenseDeviceDisable", "停用设备", "PUT", "sense:device:disable"}, {"SenseDeviceCredential", "更新设备凭据", "PUT", "sense:device:credential"}, } { button, err := ensureDeviceMenu(tx, migrationModels.SysMenu{ MenuName: definition.name, Title: definition.title, MenuType: "F", Action: definition.action, Permission: definition.permission, ParentId: page.MenuId, Paths: fmt.Sprintf("/0/%d", page.MenuId), Sort: index + 1, Visible: "1", IsFrame: "1", }) if err != nil { return err } buttons = append(buttons, button) } if err = attachDeviceRole(tx, "implementation_operator", append([]migrationModels.SysMenu{page}, buttons...)); err != nil { return err } if err = attachDeviceRole(tx, "site_admin", append([]migrationModels.SysMenu{page}, buttons...)); err != nil { return err } if err = attachDeviceRole(tx, "viewer", []migrationModels.SysMenu{page}); err != nil { return err } readPolicies := [][2]string{{"/api/v1/devices", "GET"}, {"/api/v1/devices/:id", "GET"}} writePolicies := [][2]string{{"/api/v1/devices", "POST"}, {"/api/v1/devices/:id", "PUT"}, {"/api/v1/devices/:id/disable", "PUT"}, {"/api/v1/devices/:id/credentials", "PUT"}} for _, role := range []string{"implementation_operator", "site_admin", "viewer"} { policies := append([][2]string{}, readPolicies...) if role != "viewer" { policies = append(policies, writePolicies...) } for _, policy := range policies { rule := deviceCasbinRule{Ptype: "p", V0: role, V1: policy[0], V2: policy[1]} if err = tx.Clauses(clause.OnConflict{DoNothing: true}).Create(&rule).Error; err != nil { return err } } } return tx.Create(&common.Migration{Version: version}).Error }) } func ensureDeviceMenu(tx *gorm.DB, desired migrationModels.SysMenu) (migrationModels.SysMenu, error) { var menu migrationModels.SysMenu err := tx.Where("menu_name = ?", desired.MenuName).First(&menu).Error if err != nil && err != gorm.ErrRecordNotFound { return menu, err } if err == gorm.ErrRecordNotFound { menu = desired if err = tx.Create(&menu).Error; err != nil { return menu, err } } paths := desired.Paths if desired.ParentId == 0 { paths = fmt.Sprintf("/0/%d", menu.MenuId) } err = tx.Model(&menu).Updates(map[string]any{ "title": desired.Title, "icon": desired.Icon, "path": desired.Path, "paths": paths, "menu_type": desired.MenuType, "action": desired.Action, "permission": desired.Permission, "parent_id": desired.ParentId, "component": desired.Component, "sort": desired.Sort, "visible": desired.Visible, "is_frame": desired.IsFrame, }).Error return menu, err } func attachDeviceRole(tx *gorm.DB, roleKey string, menus []migrationModels.SysMenu) error { var role migrationModels.SysRole if err := tx.Where("role_key = ?", roleKey).First(&role).Error; err != nil { return err } return tx.Model(&role).Association("SysMenu").Append(menus) }