53fa259284
Deploy Server / release-deploy-server (push) Successful in 40s
会话/设备管理后端:user_sessions 会话表、JWT 加 sid 校验、按平台类限并发登录、 登录失败锁定、修复禁用账号仍可凭 refresh 续期漏洞、/auth/ping、/auth/logout、 GET /sessions、DELETE /sessions/:id(管理员强制下线)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
53 lines
1.4 KiB
Go
53 lines
1.4 KiB
Go
package handler
|
||
|
||
import (
|
||
"errors"
|
||
"net/http"
|
||
"strconv"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"gorm.io/gorm"
|
||
|
||
"github.com/wangjia/jiu/backend/internal/middleware"
|
||
"github.com/wangjia/jiu/backend/internal/service"
|
||
"github.com/wangjia/jiu/backend/internal/util"
|
||
)
|
||
|
||
type SessionHandler struct {
|
||
svc *service.AuthService
|
||
}
|
||
|
||
func NewSessionHandler(svc *service.AuthService) *SessionHandler {
|
||
return &SessionHandler{svc: svc}
|
||
}
|
||
|
||
// List GET /api/v1/sessions —— 列出本店在线会话(所有登录用户只读)
|
||
func (h *SessionHandler) List(c *gin.Context) {
|
||
shopID := middleware.GetShopID(c)
|
||
views, err := h.svc.ListSessions(shopID, middleware.GetSID(c))
|
||
if err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
return
|
||
}
|
||
util.RespondSuccess(c, views)
|
||
}
|
||
|
||
// ForceLogout DELETE /api/v1/sessions/:id —— 强制下线(仅 admin/superadmin,挂 AdminOnly)
|
||
func (h *SessionHandler) ForceLogout(c *gin.Context) {
|
||
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||
if err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid session id"})
|
||
return
|
||
}
|
||
shopID := middleware.GetShopID(c)
|
||
if err := h.svc.ForceLogout(shopID, id); err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
c.JSON(http.StatusNotFound, gin.H{"error": "session not found"})
|
||
return
|
||
}
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
return
|
||
}
|
||
util.RespondSuccess(c, gin.H{"ok": true})
|
||
}
|