package initialize import ( "errors" "fmt" "gorm.io/gorm" "wails-app/internal/dao" "wails-app/internal/global" ) // EnsureOperationPermissions upgrades both new and existing databases with the // API catalogue and Casbin policies required by the entry/exit operation page. func EnsureOperationPermissions() error { db := global.GVA_DB if db == nil { return nil } apis := []dao.SysApi{ {Path: "/vehicle/entry", Description: "车辆入场", ApiGroup: "进出场操作", Method: "POST"}, {Path: "/vehicle/operation/context", Description: "查询车辆操作上下文", ApiGroup: "进出场操作", Method: "POST"}, {Path: "/vehicle/passage", Description: "统一车辆通行", ApiGroup: "进出场操作", Method: "POST"}, {Path: "/channel/events", Description: "查询通道事件", ApiGroup: "进出场操作", Method: "GET"}, {Path: "/parking/gate/devices", Description: "查询道闸设备", ApiGroup: "进出场操作", Method: "GET"}, {Path: "/parking/gate/open", Description: "人工开闸", ApiGroup: "进出场操作", Method: "POST"}, {Path: "/parking/gate/close", Description: "人工关闸", ApiGroup: "进出场操作", Method: "POST"}, {Path: "/ticket-machine/button", Description: "票机按钮入场", ApiGroup: "进出场操作", Method: "POST"}, } for _, api := range apis { var existing dao.SysApi err := db.Where("path = ? AND method = ?", api.Path, api.Method).First(&existing).Error if errors.Is(err, gorm.ErrRecordNotFound) { err = db.Create(&api).Error } if err != nil { return fmt.Errorf("初始化进出场API %s %s 失败: %w", api.Method, api.Path, err) } } if err := db.Exec(`CREATE TABLE IF NOT EXISTS casbin_rule ( id INTEGER PRIMARY KEY AUTOINCREMENT, ptype TEXT, v0 TEXT, v1 TEXT, v2 TEXT, v3 TEXT, v4 TEXT, v5 TEXT )`).Error; err != nil { return fmt.Errorf("初始化Casbin规则表失败: %w", err) } for _, role := range []string{"618", "888", "9527"} { for _, rule := range [][2]string{ {"/vehicle/entry", "POST"}, {"/vehicle/operation/context", "POST"}, {"/vehicle/passage", "POST"}, {"/channel/events", "GET"}, {"/parking/gate/devices", "GET"}, {"/parking/gate/open", "POST"}, {"/parking/gate/close", "POST"}, {"/ticket-machine/button", "POST"}, } { if err := ensureCasbinRule(role, rule[0], rule[1]); err != nil { return fmt.Errorf("初始化角色%s进出场权限失败: %w", role, err) } } } debugAPIs := []dao.SysApi{ {Path: "/ticket-machine/test", Description: "票机业务链路测试", ApiGroup: "开发调试", Method: "POST"}, {Path: "/ticket-machine/debug", Description: "票机原始打印测试", ApiGroup: "开发调试", Method: "POST"}, {Path: "/ticket-machine/usb-list", Description: "枚举票机设备", ApiGroup: "开发调试", Method: "GET"}, {Path: "/channel/test-event", Description: "模拟通道事件", ApiGroup: "开发调试", Method: "POST"}, } for _, api := range debugAPIs { var existing dao.SysApi err := db.Where("path = ? AND method = ?", api.Path, api.Method).First(&existing).Error if errors.Is(err, gorm.ErrRecordNotFound) { err = db.Create(&api).Error } if err != nil { return fmt.Errorf("初始化调试API %s %s 失败: %w", api.Method, api.Path, err) } } for _, role := range []string{"888", "9527"} { for _, rule := range [][2]string{ {"/ticket-machine/test", "POST"}, {"/ticket-machine/debug", "POST"}, {"/ticket-machine/usb-list", "GET"}, {"/channel/test-event", "POST"}, } { if err := ensureCasbinRule(role, rule[0], rule[1]); err != nil { return fmt.Errorf("初始化角色%s调试权限失败: %w", role, err) } } } legacyDebugRoutes := [][2]string{ {"/ticket-machine/test", "GET"}, {"/ticket-machine/debug", "GET"}, {"/channel/test-event", "GET"}, } for _, route := range legacyDebugRoutes { if err := db.Unscoped().Where("path = ? AND method = ?", route[0], route[1]).Delete(&dao.SysApi{}).Error; err != nil { return fmt.Errorf("清理旧调试API %s %s 失败: %w", route[1], route[0], err) } if err := db.Exec("DELETE FROM casbin_rule WHERE v1 = ? AND v2 = ?", route[0], route[1]).Error; err != nil { return fmt.Errorf("清理旧调试权限 %s %s 失败: %w", route[1], route[0], err) } } for _, api := range debugAPIs { if err := db.Exec("DELETE FROM casbin_rule WHERE v0 = ? AND v1 = ? AND v2 = ?", "618", api.Path, api.Method).Error; err != nil { return fmt.Errorf("撤销操作员调试权限 %s %s 失败: %w", api.Method, api.Path, err) } } return nil }