feat(admin): 用户管理增强 - CSV 批量导入用户、批量状态/组操作、登录审计日志
Build and Deploy / build-and-deploy (push) Canceled after 0s
Build and Deploy / build-and-deploy (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cloudreve/Cloudreve/v4/application/dependency"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type (
|
||||
LoginAuditListService struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
UserID *int `json:"user_id,omitempty"`
|
||||
IP string `json:"ip"`
|
||||
Status string `json:"status"` // success / fail / 空 全部
|
||||
Username string `json:"username"`
|
||||
StartTime string `json:"start_time"` // RFC3339
|
||||
EndTime string `json:"end_time"` // RFC3339
|
||||
}
|
||||
LoginAuditListParamCtx struct{}
|
||||
|
||||
LoginAuditDailyStatsService struct {
|
||||
Start string `json:"start" form:"start"` // RFC3339 或 YYYY-MM-DD
|
||||
End string `json:"end" form:"end"`
|
||||
Days int `json:"days" form:"days"` // 优先用此参数,默认7天
|
||||
}
|
||||
LoginAuditDailyStatsParamCtx struct{}
|
||||
)
|
||||
|
||||
func parseTimeRange(start, end string, defaultDays int) (time.Time, time.Time) {
|
||||
now := time.Now().Truncate(24 * time.Hour)
|
||||
endTime := now
|
||||
startTime := endTime.AddDate(0, 0, -(defaultDays - 1))
|
||||
|
||||
if start != "" {
|
||||
if t, err := time.ParseInLocation(time.RFC3339, start, time.Local); err == nil {
|
||||
startTime = t.Truncate(24 * time.Hour)
|
||||
} else if t, err := time.ParseInLocation("2006-01-02", start, time.Local); err == nil {
|
||||
startTime = t
|
||||
}
|
||||
}
|
||||
if end != "" {
|
||||
if t, err := time.ParseInLocation(time.RFC3339, end, time.Local); err == nil {
|
||||
endTime = t.Truncate(24 * time.Hour)
|
||||
} else if t, err := time.ParseInLocation("2006-01-02", end, time.Local); err == nil {
|
||||
endTime = t
|
||||
}
|
||||
}
|
||||
|
||||
// 如果 days > 0 优先
|
||||
if defaultDays > 0 && start == "" && end == "" {
|
||||
endTime = now
|
||||
startTime = endTime.AddDate(0, 0, -(defaultDays - 1))
|
||||
}
|
||||
|
||||
return startTime, endTime
|
||||
}
|
||||
|
||||
// List 分页查询登录审计
|
||||
func (s *LoginAuditListService) List(c *gin.Context) (*inventory.LoginAuditListResult, error) {
|
||||
dep := dependency.FromContext(c)
|
||||
client := dep.LoginAuditClient()
|
||||
|
||||
page := s.Page
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
pageSize := s.PageSize
|
||||
if pageSize < 1 {
|
||||
pageSize = 20
|
||||
}
|
||||
if pageSize > 500 {
|
||||
pageSize = 500
|
||||
}
|
||||
|
||||
args := &inventory.LoginAuditListArgs{
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
UserID: s.UserID,
|
||||
IP: s.IP,
|
||||
Username: s.Username,
|
||||
}
|
||||
switch s.Status {
|
||||
case "success":
|
||||
st := inventory.LoginAuditStatusSuccess
|
||||
args.Status = &st
|
||||
case "fail":
|
||||
st := inventory.LoginAuditStatusFail
|
||||
args.Status = &st
|
||||
}
|
||||
|
||||
if s.StartTime != "" {
|
||||
if t, err := time.ParseInLocation(time.RFC3339, s.StartTime, time.Local); err == nil {
|
||||
args.StartTime = &t
|
||||
} else if t, err := time.ParseInLocation("2006-01-02", s.StartTime, time.Local); err == nil {
|
||||
args.StartTime = &t
|
||||
}
|
||||
}
|
||||
if s.EndTime != "" {
|
||||
if t, err := time.ParseInLocation(time.RFC3339, s.EndTime, time.Local); err == nil {
|
||||
args.EndTime = &t
|
||||
} else if t, err := time.ParseInLocation("2006-01-02", s.EndTime, time.Local); err == nil {
|
||||
// end_time 是该日的结束(+1 day,左闭右开)
|
||||
t = t.AddDate(0, 0, 1)
|
||||
args.EndTime = &t
|
||||
}
|
||||
}
|
||||
|
||||
return client.List(c.Request.Context(), args)
|
||||
}
|
||||
|
||||
// DailyStats 每日登录统计
|
||||
func (s *LoginAuditDailyStatsService) DailyStats(c *gin.Context) ([]inventory.LoginAuditDailyItem, error) {
|
||||
dep := dependency.FromContext(c)
|
||||
client := dep.LoginAuditClient()
|
||||
|
||||
days := s.Days
|
||||
if days < 1 {
|
||||
days = 7
|
||||
}
|
||||
if days > 365 {
|
||||
days = 365
|
||||
}
|
||||
start, end := parseTimeRange(s.Start, s.End, days)
|
||||
|
||||
return client.DailyStats(c.Request.Context(), start, end)
|
||||
}
|
||||
Reference in New Issue
Block a user