mirror of https://github.com/Xhofe/alist
commit
a11e4cfb31
|
@ -26,9 +26,11 @@ func DeleteSession(userID uint, deviceKey string) error {
|
||||||
return errors.WithStack(db.Where("user_id = ? AND device_key = ?", userID, deviceKey).Delete(&model.Session{}).Error)
|
return errors.WithStack(db.Where("user_id = ? AND device_key = ?", userID, deviceKey).Delete(&model.Session{}).Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CountSessionsByUser(userID uint) (int64, error) {
|
func CountActiveSessionsByUser(userID uint) (int64, error) {
|
||||||
var count int64
|
var count int64
|
||||||
err := db.Model(&model.Session{}).Where("user_id = ?", userID).Count(&count).Error
|
err := db.Model(&model.Session{}).
|
||||||
|
Where("user_id = ? AND status = ?", userID, model.SessionActive).
|
||||||
|
Count(&count).Error
|
||||||
return count, errors.WithStack(err)
|
return count, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,25 @@ func Handle(userID uint, deviceKey, ua, ip string) error {
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
sess, err := db.GetSession(userID, deviceKey)
|
sess, err := db.GetSession(userID, deviceKey)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// reactivate existing session if it was inactive
|
if sess.Status == model.SessionInactive {
|
||||||
|
max := setting.GetInt(conf.MaxDevices, 0)
|
||||||
|
if max > 0 {
|
||||||
|
count, cerr := db.CountActiveSessionsByUser(userID)
|
||||||
|
if cerr != nil {
|
||||||
|
return cerr
|
||||||
|
}
|
||||||
|
if count >= int64(max) {
|
||||||
|
policy := setting.GetStr(conf.DeviceEvictPolicy, "deny")
|
||||||
|
if policy == "evict_oldest" {
|
||||||
|
if oldest, gerr := db.GetOldestSession(userID); gerr == nil {
|
||||||
|
_ = db.DeleteSession(userID, oldest.DeviceKey)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return errors.WithStack(errs.TooManyDevices)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
sess.Status = model.SessionActive
|
sess.Status = model.SessionActive
|
||||||
sess.LastActive = now
|
sess.LastActive = now
|
||||||
sess.UserAgent = ua
|
sess.UserAgent = ua
|
||||||
|
@ -38,7 +56,7 @@ func Handle(userID uint, deviceKey, ua, ip string) error {
|
||||||
|
|
||||||
max := setting.GetInt(conf.MaxDevices, 0)
|
max := setting.GetInt(conf.MaxDevices, 0)
|
||||||
if max > 0 {
|
if max > 0 {
|
||||||
count, err := db.CountSessionsByUser(userID)
|
count, err := db.CountActiveSessionsByUser(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/alist-org/alist/v3/internal/session"
|
"github.com/alist-org/alist/v3/internal/session"
|
||||||
"github.com/alist-org/alist/v3/internal/setting"
|
"github.com/alist-org/alist/v3/internal/setting"
|
||||||
"github.com/alist-org/alist/v3/server/common"
|
"github.com/alist-org/alist/v3/server/common"
|
||||||
|
"github.com/alist-org/alist/v3/server/middlewares"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/pquerna/otp/totp"
|
"github.com/pquerna/otp/totp"
|
||||||
)
|
)
|
||||||
|
@ -82,13 +83,18 @@ func loginHash(c *gin.Context, req *LoginReq) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// generate device session
|
||||||
|
if !middlewares.HandleSession(c, user) {
|
||||||
|
return
|
||||||
|
}
|
||||||
// generate token
|
// generate token
|
||||||
token, err := common.GenerateToken(user)
|
token, err := common.GenerateToken(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 400, true)
|
common.ErrorResp(c, err, 400, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
common.SuccessResp(c, gin.H{"token": token})
|
key := c.GetString("device_key")
|
||||||
|
common.SuccessResp(c, gin.H{"token": token, "device_key": key})
|
||||||
loginCache.Del(ip)
|
loginCache.Del(ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ func Auth(c *gin.Context) {
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !handleSession(c, admin) {
|
if !HandleSession(c, admin) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Debugf("use admin token: %+v", admin)
|
log.Debugf("use admin token: %+v", admin)
|
||||||
|
@ -54,7 +54,7 @@ func Auth(c *gin.Context) {
|
||||||
}
|
}
|
||||||
guest.RolesDetail = roles
|
guest.RolesDetail = roles
|
||||||
}
|
}
|
||||||
if !handleSession(c, guest) {
|
if !HandleSession(c, guest) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Debugf("use empty token: %+v", guest)
|
log.Debugf("use empty token: %+v", guest)
|
||||||
|
@ -93,14 +93,15 @@ func Auth(c *gin.Context) {
|
||||||
}
|
}
|
||||||
user.RolesDetail = roles
|
user.RolesDetail = roles
|
||||||
}
|
}
|
||||||
if !handleSession(c, user) {
|
if !HandleSession(c, user) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Debugf("use login token: %+v", user)
|
log.Debugf("use login token: %+v", user)
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleSession(c *gin.Context, user *model.User) bool {
|
// HandleSession verifies device sessions and stores context values.
|
||||||
|
func HandleSession(c *gin.Context, user *model.User) bool {
|
||||||
clientID := c.GetHeader("Client-Id")
|
clientID := c.GetHeader("Client-Id")
|
||||||
if clientID == "" {
|
if clientID == "" {
|
||||||
clientID = c.Query("client_id")
|
clientID = c.Query("client_id")
|
||||||
|
|
Loading…
Reference in New Issue