operation_permission_seed.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package initialize
  2. import (
  3. "errors"
  4. "fmt"
  5. "gorm.io/gorm"
  6. "wails-app/internal/dao"
  7. "wails-app/internal/global"
  8. )
  9. // EnsureOperationPermissions upgrades both new and existing databases with the
  10. // API catalogue and Casbin policies required by the entry/exit operation page.
  11. func EnsureOperationPermissions() error {
  12. db := global.GVA_DB
  13. if db == nil {
  14. return nil
  15. }
  16. apis := []dao.SysApi{
  17. {Path: "/device-provisioning/discover", Description: "自动发现局域网设备", ApiGroup: "设备接入", Method: "POST"},
  18. {Path: "/device-provisioning/discoveries", Description: "查询自动发现设备", ApiGroup: "设备接入", Method: "GET"},
  19. {Path: "/device-provisioning/:device_id/identity", Description: "读取自动发现设备身份", ApiGroup: "设备接入", Method: "POST"},
  20. {Path: "/device-provisioning/manual/identity", Description: "读取手工IP设备身份", ApiGroup: "设备接入", Method: "POST"},
  21. {Path: "/device-provisioning/:device_id/verify", Description: "确认设备证书和配对码", ApiGroup: "设备接入", Method: "POST"},
  22. {Path: "/device-provisioning/:device_id/provision", Description: "下发设备MQTT配置", ApiGroup: "设备接入", Method: "POST"},
  23. {Path: "/device-provisioning/:device_id/status", Description: "查询设备接入状态", ApiGroup: "设备接入", Method: "GET"},
  24. {Path: "/device-images/upload", Description: "边缘设备上传车辆抓拍图片", ApiGroup: "设备接入", Method: "POST"},
  25. {Path: "/vehicle/entry", Description: "车辆入场", ApiGroup: "进出场操作", Method: "POST"},
  26. {Path: "/vehicle/operation/context", Description: "查询车辆操作上下文", ApiGroup: "进出场操作", Method: "POST"},
  27. {Path: "/vehicle/passage", Description: "统一车辆通行", ApiGroup: "进出场操作", Method: "POST"},
  28. {Path: "/channel/events", Description: "查询通道事件", ApiGroup: "进出场操作", Method: "GET"},
  29. {Path: "/parking/gate/devices", Description: "查询道闸设备", ApiGroup: "进出场操作", Method: "GET"},
  30. {Path: "/parking/gate/open", Description: "人工开闸", ApiGroup: "进出场操作", Method: "POST"},
  31. {Path: "/parking/gate/close", Description: "人工关闸", ApiGroup: "进出场操作", Method: "POST"},
  32. {Path: "/parking/camera/streams", Description: "查询摄像头实时流", ApiGroup: "进出场操作", Method: "GET"},
  33. {Path: "/ticket-machine/button", Description: "票机按钮入场", ApiGroup: "进出场操作", Method: "POST"},
  34. }
  35. for _, api := range apis {
  36. var existing dao.SysApi
  37. err := db.Where("path = ? AND method = ?", api.Path, api.Method).First(&existing).Error
  38. if errors.Is(err, gorm.ErrRecordNotFound) {
  39. err = db.Create(&api).Error
  40. }
  41. if err != nil {
  42. return fmt.Errorf("初始化进出场API %s %s 失败: %w", api.Method, api.Path, err)
  43. }
  44. }
  45. if err := db.Exec(`CREATE TABLE IF NOT EXISTS casbin_rule (
  46. id INTEGER PRIMARY KEY AUTOINCREMENT,
  47. ptype TEXT, v0 TEXT, v1 TEXT, v2 TEXT, v3 TEXT, v4 TEXT, v5 TEXT
  48. )`).Error; err != nil {
  49. return fmt.Errorf("初始化Casbin规则表失败: %w", err)
  50. }
  51. for _, role := range []string{"618", "888", "9527"} {
  52. for _, rule := range [][2]string{
  53. {"/vehicle/entry", "POST"},
  54. {"/vehicle/operation/context", "POST"},
  55. {"/vehicle/passage", "POST"},
  56. {"/channel/events", "GET"},
  57. {"/parking/gate/devices", "GET"},
  58. {"/parking/gate/open", "POST"},
  59. {"/parking/gate/close", "POST"},
  60. {"/parking/camera/streams", "GET"},
  61. {"/ticket-machine/button", "POST"},
  62. } {
  63. if err := ensureCasbinRule(role, rule[0], rule[1]); err != nil {
  64. return fmt.Errorf("初始化角色%s进出场权限失败: %w", role, err)
  65. }
  66. }
  67. }
  68. for _, rule := range [][2]string{
  69. {"/device-provisioning/discover", "POST"},
  70. {"/device-provisioning/discoveries", "GET"},
  71. {"/device-provisioning/:device_id/identity", "POST"},
  72. {"/device-provisioning/manual/identity", "POST"},
  73. {"/device-provisioning/:device_id/verify", "POST"},
  74. {"/device-provisioning/:device_id/provision", "POST"},
  75. {"/device-provisioning/:device_id/status", "GET"},
  76. } {
  77. if err := ensureCasbinRule("888", rule[0], rule[1]); err != nil {
  78. return fmt.Errorf("初始化管理员设备接入权限失败: %w", err)
  79. }
  80. }
  81. debugAPIs := []dao.SysApi{
  82. {Path: "/ticket-machine/test", Description: "票机业务链路测试", ApiGroup: "开发调试", Method: "POST"},
  83. {Path: "/ticket-machine/debug", Description: "票机原始打印测试", ApiGroup: "开发调试", Method: "POST"},
  84. {Path: "/ticket-machine/usb-list", Description: "枚举票机设备", ApiGroup: "开发调试", Method: "GET"},
  85. {Path: "/channel/test-event", Description: "模拟通道事件", ApiGroup: "开发调试", Method: "POST"},
  86. }
  87. for _, api := range debugAPIs {
  88. var existing dao.SysApi
  89. err := db.Where("path = ? AND method = ?", api.Path, api.Method).First(&existing).Error
  90. if errors.Is(err, gorm.ErrRecordNotFound) {
  91. err = db.Create(&api).Error
  92. }
  93. if err != nil {
  94. return fmt.Errorf("初始化调试API %s %s 失败: %w", api.Method, api.Path, err)
  95. }
  96. }
  97. for _, role := range []string{"888", "9527"} {
  98. for _, rule := range [][2]string{
  99. {"/ticket-machine/test", "POST"},
  100. {"/ticket-machine/debug", "POST"},
  101. {"/ticket-machine/usb-list", "GET"},
  102. {"/channel/test-event", "POST"},
  103. } {
  104. if err := ensureCasbinRule(role, rule[0], rule[1]); err != nil {
  105. return fmt.Errorf("初始化角色%s调试权限失败: %w", role, err)
  106. }
  107. }
  108. }
  109. legacyDebugRoutes := [][2]string{
  110. {"/ticket-machine/test", "GET"},
  111. {"/ticket-machine/debug", "GET"},
  112. {"/channel/test-event", "GET"},
  113. }
  114. for _, route := range legacyDebugRoutes {
  115. if err := db.Unscoped().Where("path = ? AND method = ?", route[0], route[1]).Delete(&dao.SysApi{}).Error; err != nil {
  116. return fmt.Errorf("清理旧调试API %s %s 失败: %w", route[1], route[0], err)
  117. }
  118. if err := db.Exec("DELETE FROM casbin_rule WHERE v1 = ? AND v2 = ?", route[0], route[1]).Error; err != nil {
  119. return fmt.Errorf("清理旧调试权限 %s %s 失败: %w", route[1], route[0], err)
  120. }
  121. }
  122. for _, api := range debugAPIs {
  123. if err := db.Exec("DELETE FROM casbin_rule WHERE v0 = ? AND v1 = ? AND v2 = ?", "618", api.Path, api.Method).Error; err != nil {
  124. return fmt.Errorf("撤销操作员调试权限 %s %s 失败: %w", api.Method, api.Path, err)
  125. }
  126. }
  127. return nil
  128. }