mirror of
https://github.com/AlistGo/alist.git
synced 2025-12-19 11:00:06 +08:00
* feat(auth): Improved device session management logic - Replaced the `userID` parameter with the `user` object to support operations with more user attributes. - Introduced `SessionTTL` and `MaxDevices` properties in the `Handle` and `EnsureActiveOnLogin` functions to support user-defined settings. - Adjusted the session creation and verification logic in `session.go` to support user-defined device count and session duration. - Added help documentation in `setting.go` to explain the configuration purposes of `MaxDevices` and `DeviceSessionTTL`. - Added optional `MaxDevices` and `SessionTTL` properties to the user entity in `user.go` and persisted these settings across user updates. - Modified the device handling logic in `webdav.go` to adapt to the new user object parameters. * feat(session): Added session cleanup functionality - Added the `/clean` route to the route for session cleanup - Added the `DeleteInactiveSessions` method to support deleting inactive sessions by user ID - Added the `DeleteSessionByID` method to delete a specific session by session ID - Defined the `CleanSessionsReq` request structure to support passing a user ID or session ID - Implemented the `CleanSessions` interface logic to perform corresponding session cleanup operations based on the request parameters * feat(session): Added session list functionality with usernames - Added the `SessionWithUser` structure, which includes `Session` and `Username` fields. - Added the `ListSessionsWithUser` function, which queries and returns a list of sessions with usernames. - Used a `JOIN` operation to join the session and user tables to retrieve the username associated with each session. - Changed `ListSessions` to `ListSessionsWithUser` to ensure that the username is retrieved. * feat(webdav): Enhanced WebDAV authentication logic - Added logic for generating device keys based on the Client-Id, prioritizing those obtained from the request header. - If the Client-Id is missing, attempts to obtain it from the cookie. If that still doesn't exist, generates a random suffix for the client IP address as an identifier. - Stores the generated Client-Id in a cookie to ensure consistency across subsequent requests. - Use the device.EnsureActiveOnLogin method instead of the original Handle method to reactivate inactive sessions.
129 lines
2.9 KiB
Go
129 lines
2.9 KiB
Go
package handles
|
|
|
|
import (
|
|
"github.com/alist-org/alist/v3/internal/db"
|
|
"github.com/alist-org/alist/v3/internal/model"
|
|
"github.com/alist-org/alist/v3/server/common"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type SessionResp struct {
|
|
SessionID string `json:"session_id"`
|
|
UserID uint `json:"user_id,omitempty"`
|
|
Username string `json:"username,omitempty"`
|
|
LastActive int64 `json:"last_active"`
|
|
Status int `json:"status"`
|
|
UA string `json:"ua"`
|
|
IP string `json:"ip"`
|
|
}
|
|
|
|
func ListMySessions(c *gin.Context) {
|
|
user := c.MustGet("user").(*model.User)
|
|
sessions, err := db.ListSessionsByUser(user.ID)
|
|
if err != nil {
|
|
common.ErrorResp(c, err, 500)
|
|
return
|
|
}
|
|
resp := make([]SessionResp, len(sessions))
|
|
for i, s := range sessions {
|
|
resp[i] = SessionResp{
|
|
SessionID: s.DeviceKey,
|
|
LastActive: s.LastActive,
|
|
Status: s.Status,
|
|
UA: s.UserAgent,
|
|
IP: s.IP,
|
|
}
|
|
}
|
|
common.SuccessResp(c, resp)
|
|
}
|
|
|
|
type EvictSessionReq struct {
|
|
SessionID string `json:"session_id"`
|
|
}
|
|
|
|
type CleanSessionsReq struct {
|
|
UserID *uint `json:"user_id"`
|
|
SessionID string `json:"session_id"`
|
|
}
|
|
|
|
func EvictMySession(c *gin.Context) {
|
|
var req EvictSessionReq
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
common.ErrorResp(c, err, 400)
|
|
return
|
|
}
|
|
user := c.MustGet("user").(*model.User)
|
|
if _, err := db.GetSession(user.ID, req.SessionID); err != nil {
|
|
common.ErrorResp(c, err, 400)
|
|
return
|
|
}
|
|
if err := db.MarkInactive(req.SessionID); err != nil {
|
|
common.ErrorResp(c, err, 500)
|
|
return
|
|
}
|
|
common.SuccessResp(c)
|
|
}
|
|
|
|
func ListSessions(c *gin.Context) {
|
|
sessions, err := db.ListSessionsWithUser()
|
|
if err != nil {
|
|
common.ErrorResp(c, err, 500)
|
|
return
|
|
}
|
|
resp := make([]SessionResp, len(sessions))
|
|
for i, s := range sessions {
|
|
resp[i] = SessionResp{
|
|
SessionID: s.DeviceKey,
|
|
UserID: s.UserID,
|
|
Username: s.Username,
|
|
LastActive: s.LastActive,
|
|
Status: s.Status,
|
|
UA: s.UserAgent,
|
|
IP: s.IP,
|
|
}
|
|
}
|
|
common.SuccessResp(c, resp)
|
|
}
|
|
|
|
func EvictSession(c *gin.Context) {
|
|
var req EvictSessionReq
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
common.ErrorResp(c, err, 400)
|
|
return
|
|
}
|
|
if err := db.MarkInactive(req.SessionID); err != nil {
|
|
common.ErrorResp(c, err, 500)
|
|
return
|
|
}
|
|
common.SuccessResp(c)
|
|
}
|
|
|
|
func CleanSessions(c *gin.Context) {
|
|
var req CleanSessionsReq
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
common.ErrorResp(c, err, 400)
|
|
return
|
|
}
|
|
if req.SessionID != "" {
|
|
if err := db.DeleteSessionByID(req.SessionID); err != nil {
|
|
common.ErrorResp(c, err, 500)
|
|
return
|
|
}
|
|
common.SuccessResp(c)
|
|
return
|
|
}
|
|
if req.UserID != nil {
|
|
if err := db.DeleteInactiveSessions(req.UserID); err != nil {
|
|
common.ErrorResp(c, err, 500)
|
|
return
|
|
}
|
|
common.SuccessResp(c)
|
|
return
|
|
}
|
|
if err := db.DeleteInactiveSessions(nil); err != nil {
|
|
common.ErrorResp(c, err, 500)
|
|
return
|
|
}
|
|
common.SuccessResp(c)
|
|
}
|