Files
user-system/sdk/go/user-management/log.go
long-agent 765a50b7d4 fix: 生产安全修复 + Go SDK + CAS SSO框架
安全修复:
- CRITICAL: SSO重定向URL注入漏洞 - 修复redirect_uri白名单验证
- HIGH: SSO ClientSecret未验证 - 使用crypto/subtle.ConstantTimeCompare验证
- HIGH: 邮件验证码熵值过低(3字节) - 提升到6字节(48位熵)
- HIGH: 短信验证码熵值过低(4字节) - 提升到6字节
- HIGH: Goroutine使用已取消上下文 - auth_email.go使用独立context+超时
- HIGH: SQL LIKE查询注入风险 - permission/role仓库使用escapeLikePattern

新功能:
- Go SDK: sdk/go/user-management/ 完整SDK实现
- CAS SSO框架: internal/auth/cas.go CAS协议支持

其他:
- L1Cache实例问题修复 - AuthMiddleware共享l1Cache
- 设备指纹XSS防护 - 内存存储替代localStorage
- 响应格式协议中间件
- 导出无界查询修复
2026-04-03 17:38:31 +08:00

136 lines
3.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 userManagement
import (
"context"
"fmt"
"time"
)
// ListLoginLogsParams 登录日志查询参数
type ListLoginLogsParams struct {
Page int `json:"page"`
PageSize int `json:"page_size"`
UserID int64 `json:"user_id,omitempty"`
Status int `json:"status,omitempty"`
StartAt *time.Time `json:"start_at,omitempty"`
EndAt *time.Time `json:"end_at,omitempty"`
}
// ListOperationLogsParams 操作日志查询参数
type ListOperationLogsParams struct {
Page int `json:"page"`
PageSize int `json:"page_size"`
UserID int64 `json:"user_id,omitempty"`
Action string `json:"action,omitempty"`
Resource string `json:"resource,omitempty"`
StartAt *time.Time `json:"start_at,omitempty"`
EndAt *time.Time `json:"end_at,omitempty"`
}
// GetLoginLogs 获取登录日志列表
func (c *Client) GetLoginLogs(ctx context.Context, params *ListLoginLogsParams) (*PaginatedResponse, error) {
if params.Page <= 0 {
params.Page = 1
}
if params.PageSize <= 0 {
params.PageSize = 20
}
path := fmt.Sprintf("/api/v1/logs/login?page=%d&page_size=%d", params.Page, params.PageSize)
if params.UserID > 0 {
path += fmt.Sprintf("&user_id=%d", params.UserID)
}
if params.Status > 0 {
path += fmt.Sprintf("&status=%d", params.Status)
}
resp, err := c.doRequest(ctx, "GET", path, nil)
if err != nil {
return nil, err
}
var result PaginatedResponse
if err := c.parseResponse(resp, &result); err != nil {
return nil, err
}
return &result, nil
}
// GetOperationLogs 获取操作日志列表
func (c *Client) GetOperationLogs(ctx context.Context, params *ListOperationLogsParams) (*PaginatedResponse, error) {
if params.Page <= 0 {
params.Page = 1
}
if params.PageSize <= 0 {
params.PageSize = 20
}
path := fmt.Sprintf("/api/v1/logs/operation?page=%d&page_size=%d", params.Page, params.PageSize)
if params.UserID > 0 {
path += fmt.Sprintf("&user_id=%d", params.UserID)
}
if params.Action != "" {
path += "&action=" + params.Action
}
if params.Resource != "" {
path += "&resource=" + params.Resource
}
resp, err := c.doRequest(ctx, "GET", path, nil)
if err != nil {
return nil, err
}
var result PaginatedResponse
if err := c.parseResponse(resp, &result); err != nil {
return nil, err
}
return &result, nil
}
// ExportLoginLogsRequest 导出登录日志请求
type ExportLoginLogsRequest struct {
Format string `json:"format"` // "xlsx" or "csv"
UserID int64 `json:"user_id,omitempty"`
Status int `json:"status,omitempty"`
StartAt *time.Time `json:"start_at,omitempty"`
EndAt *time.Time `json:"end_at,omitempty"`
Fields string `json:"fields,omitempty"`
}
// ExportLoginLogs 导出登录日志(返回下载 URL
func (c *Client) ExportLoginLogs(ctx context.Context, req *ExportLoginLogsRequest) (string, error) {
resp, err := c.doRequest(ctx, "GET", "/api/v1/logs/login/export", req)
if err != nil {
return "", err
}
var result map[string]string
if err := c.parseResponse(resp, &result); err != nil {
return "", err
}
if url, ok := result["download_url"]; ok {
return url, nil
}
return "", nil
}
// GetStats 获取统计信息
func (c *Client) GetStats(ctx context.Context) (*Stats, error) {
resp, err := c.doRequest(ctx, "GET", "/api/v1/stats/dashboard", nil)
if err != nil {
return nil, err
}
var result Stats
if err := c.parseResponse(resp, &result); err != nil {
return nil, err
}
return &result, nil
}