material_manage_system/cmd/server/main.go
文睿 张 5021b039c9 feat: 按公司隔离 WebSocket 订阅与事件投递
- 新增 POST /api/auth/websocket-ticket:需 JWT 与公司头,签发 30 秒有效的一次性随机票据
- /ws 握手消费票据并以数据库当前状态复核身份与公司授权,JWT 不进 URL
- Hub 注册/注销/投递选人统一由事件循环串行管理,消除 RLock 内 delete 的并发缺陷
- 事件携带 organization_id,仅投递同公司订阅者,投递前复核失败即关闭连接
- 统一广播签名为 (organizationID, action, orderID, data)
- 新增前端 companySocket 模块:按当前公司取票建连、切换/登出关旧连重连、消息校验组织与上下文版本
2026-10-09 13:39:45 +08:00

76 lines
2.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"log"
"os"
"path/filepath"
"github.com/gin-gonic/gin"
"github.com/wmms/wmms/internal/handler"
"github.com/wmms/wmms/internal/repository"
"github.com/wmms/wmms/pkg/database"
)
func main() {
dsn := os.Getenv("DB_DSN")
if dsn == "" {
dsn = "root:1234@tcp(localhost:3306)/wmms?charset=utf8mb4&parseTime=true"
}
err := database.Init(dsn)
if err != nil {
log.Fatalf("Failed to initialize database: %v", err)
}
defer database.Close()
// Initialize users table and create default users
if err := repository.InitUserTable(); err != nil {
log.Fatalf("Failed to initialize users table: %v", err)
}
if err := repository.CreateDefaultUsers(); err != nil {
log.Fatalf("Failed to create default users: %v", err)
}
// 申请表的数据库结构统一由 scripts/init.sql(空库)或增量 SQL(升级)管理;
// 服务启动只校验运行所需的组织列是否已到位,缺列时报明确的升级错误,不再建表。
appRepo := repository.NewApplicationRepository()
if err := appRepo.CheckApplicationSchema(); err != nil {
log.Fatalf("Failed to verify applications schema: %v", err)
}
r := gin.Default()
registerFrontendRoutes(r, "./frontend/dist")
// Serve uploaded files
r.Static("/uploads", "./uploads")
h := handler.NewHandler()
h.RegisterRoutes(r)
// WebSocket route
// 建连不走中间件:浏览器先凭 JWT 与公司头调用 /api/auth/websocket-ticket 换票,
// 再以 /ws?ticket=... 握手;HandleWebSocket 消费一次性票据并实时复核授权。
r.GET("/ws", handler.HandleWebSocket)
// 端口可通过 APP_PORT 覆盖,默认 8082,便于试用脚本探测空闲端口。
port := os.Getenv("APP_PORT")
if port == "" {
port = "8082"
}
addr := ":" + port
log.Printf("Server starting on %s", addr)
log.Println("Default users: admin/admin123, user/user123")
if err := r.Run(addr); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
}
func registerFrontendRoutes(r *gin.Engine, distDir string) {
r.Static("/web", distDir)
r.Static("/assets", filepath.Join(distDir, "assets"))
r.GET("/", func(c *gin.Context) {
c.File(filepath.Join(distDir, "index.html"))
})
}