fix: 补 .gitattributes(CRLF for .bat) + README 端口 19540 + 提交 console 锁文件

This commit is contained in:
AskaEth committed 2026-09-09 20:57:58 +08:00
1 parent c121111f51
commit b80c64a115
39 files changed
+4217 -345

No files matched your search

+44 -9
View File
@@ -9,6 +9,9 @@ import (
"time"
"github.com/coder/websocket"
"git.yeij.top/AskaEth/Scoreboard/server/internal/auth"
"git.yeij.top/AskaEth/Scoreboard/server/internal/middleware"
)
// 默认参数;现场可通过 Set* 调整。
@@ -210,14 +213,26 @@ func (h *Hub) Handler() http.Handler {
h.mu.Unlock()
defer h.connWG.Done()
h.serve(conn, r.RemoteAddr)
// 身份只认会话:/ws 必须被 Authenticate 中间件包住,否则一律按 guest 处理。
role, userID := wsIdentity(r.Context())
h.serve(conn, r.RemoteAddr, role, userID)
})
}
func (h *Hub) serve(conn *websocket.Conn, remoteAddr string) {
// wsIdentity 从请求上下文取会话身份并折算成实时层角色。
// 未登录(guest)只能进大屏房间;recorder/admin 才有管理端房间的订阅权。
func wsIdentity(ctx context.Context) (string, int64) {
u := middleware.User(ctx)
if u == nil || !u.Role.Allows(auth.RoleRecorder) {
return RoleDisplay, 0
}
return RoleAdmin, u.ID
}
func (h *Hub) serve(conn *websocket.Conn, remoteAddr, sessionRole string, sessionUserID int64) {
conn.SetReadLimit(1 << 20)
c := newClient(h, conn, remoteAddr)
c := newClient(h, conn, remoteAddr, sessionRole, sessionUserID)
h.addClient(c)
ctx, cancel := context.WithCancel(h.ctx)
@@ -293,22 +308,42 @@ func (h *Hub) roomClients(room string) []*client {
return out
}
// handleHello 只信任会话身份:客户端自报的 role/userId 会被忽略,
// 管理端房间必须由登录会话授予,未登录连接请求管理端直接断开。
func (h *Hub) handleHello(ctx context.Context, c *client, p helloPayload) {
if p.Role != RoleDisplay && p.Role != RoleAdmin {
c.mu.Lock()
sessionRole, sessionUserID := c.sessionRole, c.sessionUserID
c.mu.Unlock()
if p.Role != "" && p.Role != RoleDisplay && p.Role != RoleAdmin {
h.log.Debug("hello 角色非法", "role", p.Role, "remote", c.remoteAddr)
c.stop(websocket.StatusPolicyViolation, "role 非法")
return
}
if p.Role == RoleAdmin && sessionRole != RoleAdmin {
h.log.Warn("未登录连接请求管理端房间,已断开", "remote", c.remoteAddr)
c.stop(websocket.StatusPolicyViolation, "无权订阅管理端房间")
return
}
// 不写 role 时按会话上限走;显式 role=display 允许管理端用户降级成大屏。
role := sessionRole
if p.Role == RoleDisplay {
role = RoleDisplay
}
c.mu.Lock()
c.role = p.Role
c.userID = p.UserID
c.role = role
c.userID = 0
if role == RoleAdmin {
c.userID = sessionUserID
}
c.mu.Unlock()
if p.Role == RoleAdmin {
if role == RoleAdmin {
rooms := []string{RoomAdmin}
if p.UserID > 0 {
rooms = append(rooms, AdminRoom(p.UserID))
if c.userID > 0 {
rooms = append(rooms, AdminRoom(c.userID))
}
h.join(c, rooms...)
} else {