Files
jiu/backend/internal/model/user_session.go
T
wangjia ca7595b113 feat(backend): 出入库汇总近30天滚动窗口 + 跨租户安全加固
- summaryBounds:本月/近30天滚动双口径(stock-in/out Summary ?window=rolling30)
- security(SEC-001):新增 ownership.go ensureShopRef 写入侧防线(stock-in/out/finance/
  盘点建单的 warehouse/partner/product 外键归属校验);读取侧全部 Preload 补
  shop_id 作用域,finance Summary JOIN 补租户条件;回归测试 CrossTenantRefs
- security(SEC-002):release 模式 JWT 密钥为空/默认值时拒绝启动
- gofmt 对齐若干 model/cmd 文件

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-03 09:57:52 +08:00

47 lines
2.4 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 model
import "time"
// UserSession 服务端登录会话。JWT 的 sid claim 指向此表一行,
// 用于支持登出/踢人/在线状态监控(JWT 本身无状态,无法撤销)。
type UserSession struct {
ID uint64 `gorm:"primaryKey;autoIncrement" json:"id"`
ShopID uint64 `gorm:"not null;index:idx_session_shop_user" json:"shop_id"`
UserID uint64 `gorm:"not null;index:idx_session_shop_user" json:"user_id"`
SID string `gorm:"column:sid;size:64;not null;uniqueIndex" json:"sid"` // 嵌入 JWT
DeviceID string `gorm:"size:255" json:"device_id"`
DeviceName string `gorm:"size:255" json:"device_name"`
Platform string `gorm:"size:50" json:"platform"` // windows|macos|linux|android|ios|web
PlatformClass string `gorm:"size:20;index" json:"platform_class"` // desktop|mobile|web
IP string `gorm:"size:64" json:"ip"`
UserAgent string `gorm:"size:512" json:"user_agent"`
// RefreshJTI 当前有效 refresh token 的 jti,用于「轮换 + 重用检测」:
// 每次续期轮换此值,若 refresh 携带的 jti 与之不符即判定为旧 token 重放(盗用),吊销整条会话。
RefreshJTI string `gorm:"column:refresh_jti;size:64" json:"-"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
// LastSeenAt 手工维护(Login 建行赋值、心跳/refresh 显式 Update)。
// 故意用 autoCreateTime(建行给默认、之后不被 ORM 自动改);切勿改成 autoUpdateTime
// 否则 revoke/cleanup 等任意 Updates 都会把已撤销会话误刷成「刚活跃」。
LastSeenAt time.Time `gorm:"autoCreateTime" json:"last_seen_at"`
RevokedAt *time.Time `gorm:"index" json:"revoked_at,omitempty"`
RevokedReason string `gorm:"size:30" json:"revoked_reason,omitempty"` // kicked|logout|admin|disabled|reuse|pwd_reset
RevokedBy *uint64 `gorm:"column:revoked_by" json:"revoked_by,omitempty"` // 吊销操作人 user_id;系统/自助吊销为 NULL
RefreshExpAt time.Time `json:"refresh_exp_at"`
}
func (UserSession) TableName() string { return "user_sessions" }
// PlatformClass 把具体平台归类,用于按类限并发。
func PlatformClass(platform string) string {
switch platform {
case "android", "ios":
return "mobile"
case "web":
return "web"
case "windows", "macos", "linux":
return "desktop"
default:
return "desktop" // 未知平台按桌面端处理
}
}