diff --git a/src/bean/vo/request/dict.go b/src/bean/vo/request/dict.go index cf79837d842b89e817deae2dd7d7d18f0921b798..632dc6d07919239d9a6ebb8a10a8af93484d801b 100644 --- a/src/bean/vo/request/dict.go +++ b/src/bean/vo/request/dict.go @@ -20,7 +20,7 @@ type AddDictReq struct { Class int `json:"class" form:"class" binding:"required,oneof=1 2 3 4 5 6 7 8 9 10 11 12 13 14"` //组件分类(1开发语言与版本 2中间件类型与中间件 3云组件类型 4模块类型 5所属区域 6操作系统 7对象类型 8SQL类型 9调研评估结果 10任务阶段 11测试文档类型 12验收问题类型 13Q&A问题类型 14文档类型) ParentId string `json:"parent_id" form:"parent_id"` //父级ID Name string `json:"name" form:"name" binding:"required"` //字典标签 - Status int `json:"status" form:"status" binding:"oneof=0 1"` //是否启用(1:启用 2:禁用) + Status int `json:"status" form:"status" binding:"oneof=0 1 2"` //是否启用(1:启用 2:禁用) Description string `json:"description" form:"description" binding:"lte=200"` //描述 MinVal string `json:"min_val" form:"min_val"` //最大值 MaxVal string `json:"max_val" form:"max_val"` //最小值 @@ -31,7 +31,7 @@ type UpdateDictReq struct { Id string `json:"id" form:"id" binding:"required"` //组件ID ParentId string `json:"parent_id" form:"parent_id"` //父级ID Name string `json:"name" form:"name" binding:"required"` //字典标签 - Status int `json:"status" form:"status" binding:"oneof=0 1"` //是否启用(1:启用 2:禁用) + Status int `json:"status" form:"status" binding:"oneof=0 1 2"` //是否启用(1:启用 2:禁用) Description string `json:"description" form:"description" binding:"lte=200"` //描述 MinVal string `json:"min_val" form:"min_val"` //最大值 MaxVal string `json:"max_val" form:"max_val"` //最小值 @@ -44,7 +44,7 @@ type DictManageListReq struct { Id string `json:"id" form:"id" binding:"required"` //组件ID ParentId string `json:"parent_id" form:"parent_id"` //父级ID Name string `json:"name" form:"name" binding:"required"` //字典标签 - Status int `json:"status" form:"status" binding:"oneof=0 1"` //是否启用(1:启用 2:禁用) + Status int `json:"status" form:"status" binding:"oneof=0 1 2"` //是否启用(1:启用 2:禁用) Description string `json:"description" form:"description" binding:"lte=200"` //描述 MinVal string `json:"min_val" form:"min_val"` //最大值 MaxVal string `json:"max_val" form:"max_val"` //最小值 diff --git a/src/bean/vo/request/log_management.go b/src/bean/vo/request/log_management.go new file mode 100644 index 0000000000000000000000000000000000000000..9d236cc6cad147093be8c63eb43ad5393373810a --- /dev/null +++ b/src/bean/vo/request/log_management.go @@ -0,0 +1,29 @@ +package request + +type LogManagementListReq struct { + Pagination //分页参数 + Search string `json:"search" form:"search"` // 搜素 + //IsAdmin int `json:"is_admin" form:"is_admin"` // 用户类型 (1.业务系统账号 2.组织管理员账号 3.平台用户账号 4.超级管理员) + StartAt string `json:"start_at" form:"start_at"` // 开始时间 + EndAt string `json:"end_at" form:"end_at"` // 结束时间 + Active int `json:"active" form:"active"` // 活跃度 1: 低 2:中 3: 高 + PwdLevel int `json:"pwd_level" form:"pwd_level"` // 密码强度 1低2中3高 +} + +type LogUserBehaviorListReq struct { + Pagination //分页参数 + Search string `json:"search" form:"search"` // 搜素 + //IsAdmin int `json:"is_admin" form:"is_admin"` // 用户类型 (1.业务系统账号 2.组织管理员账号 3.平台用户账号 4.超级管理员) + StartAt string `json:"start_at" form:"start_at"` // 开始时间 + EndAt string `json:"end_at" form:"end_at"` // 结束时间 + OperateType string `json:"operate_type" form:"operate_type"` // 操作类型 + ReqMethod int `json:"req_method" form:"req_method"` // 请求方式 + OperateStatus int `json:"operate_status" form:"operate_status"` // 操作状态 +} + +type SystemLogListReq struct { + Pagination //分页参数 + Search string `json:"search" form:"search"` // 搜素 + Index string `json:"index" form:"index"` //索引名称 + Level string `json:"level" form:"level"` //级别 +} diff --git a/src/bean/vo/request/page.go b/src/bean/vo/request/page.go index c570b08800f861c9ecd816292f0b976434edf371..92a0a702a97dbed149971f85d6c2e92f7404c388 100644 --- a/src/bean/vo/request/page.go +++ b/src/bean/vo/request/page.go @@ -19,3 +19,13 @@ func (p Pagination) GetPageSize() int { } return p.PageSize } + +func (p Pagination) GetOffset() int { + if p.Page == 0 { + p.Page = 1 + } + if p.PageSize == 0 { + p.PageSize = 15 + } + return (p.Page - 1) * p.PageSize +} diff --git a/src/bean/vo/response/log_management.go b/src/bean/vo/response/log_management.go new file mode 100644 index 0000000000000000000000000000000000000000..2ccb30d7973b5679318685e611f79d64a492e6cb --- /dev/null +++ b/src/bean/vo/response/log_management.go @@ -0,0 +1,174 @@ +package response + +import ( + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime" +) + +type LogManagementRep struct { + Id int32 `json:"id" xorm:"pk autoincr" ` // id + OrganizationId string `json:"organization_id" xorm:"organization_id"` // 所属组织 + Name string `json:"name"` // 所属组织名称 + SystemAccount string `json:"system_account" xorm:"system_account"` // 系统账号 + ContactPhone string `json:"contact_phone" xorm:"contact_phone"` // 联系人电话 + //IsAdmin string `json:"is_admin" xorm:"is_admin"` // 用户类型 (1.业务系统账号 2.组织管理员账号 3.平台用户账号 4.超级管理员) + LastAccessTimes jsontime.Time `json:"-" xorm:"last_access_time"` // 用户最后访问时间 + LastAccessTime jsontime.Time `json:"last_access_time" xorm:"-"` // 用户最后访问时间 + Active string `json:"active"` // 活跃度 高:小于等于7天,中:大于7天小于一个月,低:大于等于一个月 1: 低 2:中 3: 高 + PwdLevel string `json:"pwd_level"` // 密码强度 1低2中3高 + PwdIsUsed int `json:"pwd_is_used"` // 密码使用时长 + CreatedTime jsontime.Time `json:"created_time" xorm:"created_time" ` // 创建时间 +} + +type SystemUserBehaviorList struct { + Xh int64 `json:"xh" xorm:"id"` + Id string `json:"id" xorm:"-"` // 主键id + UserId int `json:"user_id"` // 系统用户id + OrganizationId string `json:"organization_id"` // 组织uuid + SystemModule string `json:"system_module"` // 系统模块 + OperateType string `json:"operate_type"` // 操作类型 + ReqMethod int `json:"req_method"` // 请求方式 + OperateStatus int `json:"operate_status"` // 操作状态 + OperateIp string `json:"operate_ip"` // 操作ip信息 + OperateAddr string `json:"operate_addr"` // 操作地点 + CreatedTime jsontime.Time `json:"created_time" xorm:"created"` // 操作时间 + IsDeleted int `json:"is_deleted"` // 是否删除 + OperateMethod string `json:"operate_method"` // 操作方法函数名 + ResFields string `json:"res_fields"` // 返回参数 + ReqParam string `json:"req_param"` // 请求参数 + ReqUrl string `json:"req_url"` // 请求地址 + AppId string `json:"app_id"` // appId + SystemAccount string `json:"system_account"` // 系统账号 + Phone string `json:"-" xorm:"phone"` // 手机号 + //IsAdmin int `json:"is_admin"` // 用户类型 + OrgName string `json:"org_name"` // 组织 +} + +type LogUserBehaviorDetailRep struct { + Id int `json:"id" xorm:"pk autoincr"` // 主键id + UserId int `json:"user_id"` // 系统用户id + OrganizationId string `json:"organization_id"` // 组织uuid + SystemModule string `json:"system_module"` // 系统模块 + OperateType string `json:"operate_type"` // 操作类型 + ReqMethod int `json:"req_method"` // 请求方式 + ReqMethodStr string `json:"req_method_str" xorm:"-"` + OperateStatus int `json:"operate_status"` // 操作状态 + OperateStatusStr string `json:"operate_status_str" xorm:"-"` + OperateIp string `json:"operate_ip"` // 操作ip信息 + OperateAddr string `json:"operate_addr"` // 操作地点 + CreatedTime jsontime.Time `json:"created_time" xorm:"created"` // 操作时间 + OperateMethod string `json:"operate_method"` // 操作方法函数名 + ResFields string `json:"res_fields"` // 返回参数 + ReqParam string `json:"req_param"` // 请求参数 + ReqUrl string `json:"req_url"` // 请求地址 + AppId string `json:"app_id"` // appId + SystemAccount string `json:"system_account"` // 系统账号 + Phone string `json:"phone"` // 手机号 + //IsAdmin int `json:"-"` // 用户类型 + //UserType string `json:"user_type" xorm:"-"` + OrgName string `json:"org_name"` // 组织 +} + +type SystemUserBehaviorInfo struct { + Total map[string]interface{} `json:"total"` + Hits []BehaviorSourceData `json:"hits"` +} + +type BehaviorSourceData struct { + Id string `json:"_id"` + Source SystemUserBehaviorEs `json:"_source"` +} + +type SystemUserBehaviorEs struct { + Id string `json:"id"` + Xh int64 `json:"xh"` + UserId int `json:"user_id"` // 系统用户id + OrganizationId string `json:"organization_id"` // 组织uuid + SystemModule string `json:"system_module"` // 系统模块 + OperateType string `json:"operate_type"` // 操作类型 + ReqMethod int `json:"req_method"` // 请求方式 + OperateStatus int `json:"operate_status"` // 操作状态 + OperateIp string `json:"operate_ip"` // 操作ip信息 + OperateAddr string `json:"operate_addr"` // 操作地点 + CreatedTime string `json:"created_time" xorm:"created"` // 操作时间 + CreatedTimeUnix int64 `json:"created_time_unix"` // 操作时间戳(用于排序统计) + IsDeleted int `json:"is_deleted"` // 是否删除 + OperateMethod string `json:"operate_method"` // 操作方法函数名 + ResFields string `json:"res_fields"` // 返回参数 + ReqParam string `json:"req_param"` // 请求参数 + ReqUrl string `json:"req_url"` // 请求地址 + AppId string `json:"app_id"` // appId + SystemAccount string `json:"system_account"` // 系统账号 + Phone string `json:"phone" xorm:"phone"` // 手机号 + IsAdmin int `json:"is_admin"` // 用户类型 + OrgName string `json:"org_name"` // 组织 +} + +type SystemUserBehaviorToEs struct { + UserId int `json:"user_id"` // 系统用户id + OrganizationId string `json:"organization_id"` // 组织uuid + SystemModule string `json:"system_module"` // 系统模块 + OperateType string `json:"operate_type"` // 操作类型 + ReqMethod int `json:"req_method"` // 请求方式 + OperateStatus int `json:"operate_status"` // 操作状态 + OperateIp string `json:"operate_ip"` // 操作ip信息 + OperateAddr string `json:"operate_addr"` // 操作地点 + CreatedTime string `json:"created_time" xorm:"created"` // 操作时间 + CreatedTimeUnix int64 `json:"created_time_unix"` // 操作时间戳(用于排序统计) + IsDeleted int `json:"is_deleted"` // 是否删除 + OperateMethod string `json:"operate_method"` // 操作方法函数名 + ResFields string `json:"res_fields"` // 返回参数 + ReqParam string `json:"req_param"` // 请求参数 + ReqUrl string `json:"req_url"` // 请求地址 + AppId string `json:"app_id"` // appId + SystemAccount string `json:"system_account"` // 系统账号 + Phone string `json:"phone" xorm:"phone"` // 手机号 + //IsAdmin int `json:"is_admin"` // 用户类型 + OrgName string `json:"org_name"` // 组织 +} + +type SystemUserInfoEs struct { + SystemAccount string `json:"system_account"` // 系统账号 + Phone string `json:"-" xorm:"phone"` // 手机号 + //IsAdmin int `json:"is_admin"` // 用户类型 + OrgName string `json:"org_name"` // 组织 +} + +type BehaviorEsListInfo struct { + Total map[string]interface{} `json:"total"` + Hits []SourceData `json:"hits"` +} + +type SourceData struct { + Id string `json:"_id"` + Source SystemUserBehaviorList `json:"_source"` +} + +type SystemLogTree struct { + Id int `json:"id"` + Name string `json:"name"` + Value string `json:"value"` +} + +type SystemLogEsListInfo struct { + Hits []SystemLogSourceData `json:"hits"` +} + +type SystemLogSourceData struct { + Id string `json:"_id"` + Source SystemLogEsList `json:"_source"` +} + +type SystemLogEsList struct { + Level string `json:"level"` + Timestamp string `json:"timestamp"` + Msg string `json:"msg"` + Status int `json:"status"` + Method string `json:"method"` + Path string `json:"path"` + Query string `json:"query"` + Ip string `json:"ip"` + UserAgent string `json:"user-agent"` + Errors string `json:"errors"` + Cost int `json:"cost"` + TimeUnit int64 `json:"time_unit"` +} diff --git a/src/common/tools/xlsxSheet.go b/src/common/tools/xlsxSheet.go new file mode 100644 index 0000000000000000000000000000000000000000..0716032c7b673d95e2a038e81ae4f1b953f6d65c --- /dev/null +++ b/src/common/tools/xlsxSheet.go @@ -0,0 +1,44 @@ +/** + * @Author: Y + * @Description: + * @File: xlsxSheet + * @Version: 1.0.0 + * @Date: 2023/2/23 15:34 + */ + +package tools + +import ( + "errors" + "github.com/tealeg/xlsx" +) + +type XlsxRow struct { + Row *xlsx.Row + Data []string +} + +func NewRow(row *xlsx.Row, data []string) *XlsxRow { + return &XlsxRow{ + Row: row, + Data: data, + } +} +func (row *XlsxRow) SetRowTitle() error { + return generateRow(row.Row, row.Data) +} + +func (row *XlsxRow) GenerateRow() error { + return generateRow(row.Row, row.Data) +} + +func generateRow(row *xlsx.Row, rowStr []string) error { + if rowStr == nil { + return errors.New("no data to generate xlsx!") + } + for _, v := range rowStr { + cell := row.AddCell() + cell.SetString(v) + } + return nil +} diff --git a/src/controller/log_management.go b/src/controller/log_management.go index f3d55fae11432be8767b9487418e913abc55961c..b5add52f29222d04ae1972a9629d473a6e216b6b 100644 --- a/src/controller/log_management.go +++ b/src/controller/log_management.go @@ -1,14 +1,17 @@ package controller import ( + "fmt" "github.com/gin-gonic/gin" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/router/middleware/header" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/service" + "strings" ) // 系统日志树 -func GetSystemLoggerTree(c *gin.Context) { +func GetSystemLoggerList(c *gin.Context) { search := c.Query("logTime") svc := service.LogManagement{User: header.GetUser(c)} if dir, err := svc.GetSysLogDir(search); err != nil { @@ -20,7 +23,7 @@ func GetSystemLoggerTree(c *gin.Context) { // 系统日志 func GetSystemLog(c *gin.Context) { - name := c.Param("name") + name := c.Query("name") search := c.Query("search") logLevel := c.Query("logLevel") svc := service.LogManagement{User: header.GetUser(c)} @@ -31,7 +34,84 @@ func GetSystemLog(c *gin.Context) { } } -// 用户账户审计列表 +// 用户行为审计列表 +func LogUserBehaviorList(c *gin.Context) { + params := request.LogUserBehaviorListReq{} + // 绑定分页数据 + if err := c.ShouldBindQuery(¶ms); err != nil { + SendJsonResponse(c, resp.InvalidParam.WithError(err), nil) + return + } + + svc := service.LogManagement{User: header.GetUser(c)} + var ( + list interface{} + count int64 + err error + ) + + list, count, err = svc.LogUserBehaviorList(¶ms) + if err != nil { + SendJsonResponse(c, err, nil) + return + + } + SendJsonPageResponse(c, nil, list, count) +} + +// 用户行为审计列表导出 +func LogUserBehaviorListExport(c *gin.Context) { + params := request.LogUserBehaviorListReq{} + // 绑定分页数据 + if err := c.ShouldBindQuery(¶ms); err != nil { + SendJsonResponse(c, resp.InvalidParam.WithError(err), nil) + return + } + // 分页数据初始化 limit page Offset + + svc := service.LogManagement{User: header.GetUser(c)} + file, fileName, err := svc.LogUserBehaviorListExport(¶ms) + if err != nil { + SendJsonResponse(c, err, nil) + return + } + c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName)) //fmt.Sprintf("attachment; filename=%s", filename)对下载的文件重命名 + c.Writer.Header().Add("Content-Type", "application/octet-stream") + c.Writer.Header().Add("Content-Transfer-Encoding", "binary") + _ = file.Write(c.Writer) +} + +func LogUserBehaviorDetail(c *gin.Context) { + id := c.Param("id") + if id == "" { + SendJsonResponse(c, resp.InvalidParam.WithData("id必填"), nil) + return + } + svc := service.LogManagement{User: header.GetUser(c)} + data, err := svc.LogUserBehaviorDetail(id) + if err != nil { + SendJsonResponse(c, err, nil) + return + } + SendJsonResponse(c, nil, data) +} + +func LogUserBehaviorDelete(c *gin.Context) { + ids := strings.Split(c.Query("ids"), ",") + if len(ids) == 0 { + SendJsonResponse(c, resp.InvalidParam.WithData("id必填"), nil) + return + } + svc := service.LogManagement{User: header.GetUser(c)} + err := svc.LogUserBehaviorDelete(ids) + if err != nil { + SendJsonResponse(c, err, nil) + return + } + SendJsonResponse(c, nil, "删除成功") +} + +//用户账户审计列表 //func LogUserAccountAuditList(c *gin.Context) { // params := request.LogManagementListReq{} // // 绑定分页数据 @@ -72,88 +152,3 @@ func GetSystemLog(c *gin.Context) { // _ = file.Write(c.Writer) // //} -// -//// 用户行为审计列表 -//func LogUserBehaviorList(c *gin.Context) { -// params := request.LogUserBehaviorListReq{} -// // 绑定分页数据 -// if err := c.ShouldBindQuery(¶ms); err != nil { -// SendJsonResponse(c, res.ParamsParserError.ErrorDetail(err), nil) -// return -// } -// // 分页数据初始化 limit page Offset -// params.PageInfo = params.PageInfo.InitPage() -// svc := service.LogManagement{User: util.GetContextUser(c)} -// var ( -// list interface{} -// count int64 -// err error -// ) -// //是否ES查询用户行为审计信息 -// if conf.Options.IsBehaviorToES { -// list, count, err = svc.LogUserBehaviorListEs(¶ms) -// if err != nil { -// SendJsonResponse(c, err, nil) -// return -// } -// } else { -// list, count, err = svc.LogUserBehaviorList(¶ms) -// if err != nil { -// SendJsonResponse(c, err, nil) -// return -// } -// } -// SendJsonPageResponse(c, nil, list, count) -//} -// -//// 用户行为审计列表导出 -//func LogUserBehaviorListExport(c *gin.Context) { -// params := request.LogUserBehaviorListReq{} -// // 绑定分页数据 -// if err := c.ShouldBindQuery(¶ms); err != nil { -// SendJsonResponse(c, res.ParamsParserError.ErrorDetail(err), nil) -// return -// } -// // 分页数据初始化 limit page Offset -// params.PageInfo = params.PageInfo.InitPage() -// svc := service.LogManagement{User: util.GetContextUser(c)} -// file, fileName, err := svc.LogUserBehaviorListExport(¶ms) -// if err != nil { -// SendJsonResponse(c, err, nil) -// return -// } -// c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName)) //fmt.Sprintf("attachment; filename=%s", filename)对下载的文件重命名 -// c.Writer.Header().Add("Content-Type", "application/octet-stream") -// c.Writer.Header().Add("Content-Transfer-Encoding", "binary") -// _ = file.Write(c.Writer) -//} -// -//func LogUserBehaviorDetail(c *gin.Context) { -// id := c.Param("id") -// if id == "" { -// SendJsonResponse(c, res.ParamsMissError.ErrorDetail(errors.New("id必填")), nil) -// return -// } -// svc := service.LogManagement{User: util.GetContextUser(c)} -// data, err := svc.LogUserBehaviorDetail(id) -// if err != nil { -// SendJsonResponse(c, err, nil) -// return -// } -// SendJsonResponse(c, nil, data) -//} -// -//func LogUserBehaviorDelete(c *gin.Context) { -// ids := strings.Split(c.Query("ids"), ",") -// if len(ids) == 0 { -// SendJsonResponse(c, res.ParamsMissError.ErrorDetail(errors.New("ids必填")), nil) -// return -// } -// svc := service.LogManagement{User: util.GetContextUser(c)} -// err := svc.LogUserBehaviorDelete(ids) -// if err != nil { -// SendJsonResponse(c, err, nil) -// return -// } -// SendJsonResponse(c, nil, "删除成功") -//} diff --git a/src/pkg/beagle/jsontime/jsonTime.go b/src/pkg/beagle/jsontime/jsonTime.go index 1412c815961fe4c37056d6f202d3e35fdd7fbaa7..b6171b921fee8bff40f2464f6ccd127a1c673b6e 100644 --- a/src/pkg/beagle/jsontime/jsonTime.go +++ b/src/pkg/beagle/jsontime/jsonTime.go @@ -12,6 +12,19 @@ import ( var CSTZone = time.FixedZone("CST", 8*3600) // 固定东八区(CST: China Standard Time) +const ( + LocalDateTimeFormat string = "2006-01-02 15:04:05" + LocalDateTimeFormat1 string = "2006/01/02 15:04:05" + LocalDateTimeFormatUTC string = "2006-01-02T15:04:05" + LocalDateTimeFormatUTCZ string = "2006-01-02T15:04:05Z" + LocalDateFormat string = "2006-01-02" + LocalDateFormatEs string = "20060102150405" + LocalDateFormat1 string = `20060102` + LocalMonthFormat string = "2006-01" + LocalMonthFormat1 string = "2006.01" + LocalTimeFormat string = "15:04:05" +) + // Time 自定义时间 // 设置当前时间: jsonDate := Time(time.Now()) type Time time.Time diff --git a/src/router/logmanagementrouter.go b/src/router/logmanagementrouter.go index 999614ea6ffa1eb8b956194b1a895819e1eedea1..ea7d1bd68871d573a18421d726829e86e08c6c43 100644 --- a/src/router/logmanagementrouter.go +++ b/src/router/logmanagementrouter.go @@ -5,33 +5,37 @@ import ( "github.com/gin-gonic/gin" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/controller" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/router/middleware/header" ) // 初始化日志管理路由 func InitLogManagementRouter(e *gin.Engine) { - logger := e.Group(fmt.Sprintf("%s/log", conf.Options.Prefix), header.SetContext) + logger := e.Group(fmt.Sprintf("%s/log", conf.Options.Prefix)) { systemLog := logger.Group("/system", header.SetContext) { - systemLog.GET("tree", controller.GetSystemLoggerTree) //系统日志树 + systemLog.GET("list", controller.GetSystemLoggerList) //系统日志树 systemLog.GET("log", controller.GetSystemLog) //系统日志 } - //userAccountAudit := logger.Group("/userAccountAudit", header.SetUserToContext) + + userBehavior := logger.Group("userBehavior", header.SetContext) + { + //用户行为审计: + userBehavior.GET("list", controller.LogUserBehaviorList, header.AddLogMiddleware("用户行为审计", "/list", constant.OpTypeIntMap[constant.Find])) //用户行为审计列表 + userBehavior.GET("list/export", controller.LogUserBehaviorListExport, header.AddLogMiddleware("用户行为审计", "/export", constant.OpTypeIntMap[constant.Export])) //用户行为审计列表导出 + userBehavior.GET("detail/:id", controller.LogUserBehaviorDetail) //用户行为审计详情 + userBehavior.DELETE("delete", controller.LogUserBehaviorDelete) //用户行为审计删除 + } + + //userAccountAudit := logger.Group("/userAccountAudit", header.SetContext) //{ // //用户账户审计: - // userAccountAudit.GET("list", controller.LogUserAccountAuditList, log.AddLogMiddleware("用户账户审计", "/list", constant.OpTypeIntMap[constant.Find])) //用户账户审计列表 - // userAccountAudit.GET("list/export", controller.LogUserAccountAuditExport, log.AddLogMiddleware("用户账户审计", "/export", constant.OpTypeIntMap[constant.Export])) //用户账户审计列表导出 + // userAccountAudit.GET("list", controller.LogUserAccountAuditList, header.AddLogMiddleware("用户账户审计", "/list", constant.OpTypeIntMap[constant.Find])) //用户账户审计列表 + // userAccountAudit.GET("list/export", controller.LogUserAccountAuditExport, header.AddLogMiddleware("用户账户审计", "/export", constant.OpTypeIntMap[constant.Export])) //用户账户审计列表导出 // //} - //userBehavior := logger.Group("userBehavior", header.SetUserToContext) - //{ - // //用户行为审计: - // userBehavior.GET("list", controller.LogUserBehaviorList, log.AddLogMiddleware("用户行为审计", "/list", constant.OpTypeIntMap[constant.Find])) //用户行为审计列表 - // userBehavior.GET("list/export", controller.LogUserBehaviorListExport, log.AddLogMiddleware("用户行为审计", "/export", constant.OpTypeIntMap[constant.Export])) //用户行为审计列表导出 - // userBehavior.GET("detail/:id", controller.LogUserBehaviorDetail) //用户行为审计详情 - // userBehavior.DELETE("delete", controller.LogUserBehaviorDelete) //用户行为审计删除 - //} + } } diff --git a/src/service/log_management.go b/src/service/log_management.go index 2c2b6bdea8a323ed73c3d922d4efb323e664727d..b8f325633adbe253cbc5e7cb268a8053c49442cd 100644 --- a/src/service/log_management.go +++ b/src/service/log_management.go @@ -2,12 +2,23 @@ package service import ( "bufio" + "errors" "fmt" + "github.com/spf13/cast" + "github.com/tealeg/xlsx" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/tools" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/util" "os" "sort" + "strconv" "strings" "time" @@ -87,6 +98,140 @@ func (s *LogManagement) GetSysLog(logLevel, search, logName string) ([]string, e return logArr, nil } +// 用户行为审计列表 +func (s *LogManagement) LogUserBehaviorList(params *request.LogUserBehaviorListReq) (list []response.SystemUserBehaviorList, total int64, err error) { + db, err := client.GetDbClient() + if err != nil { + err = resp.DbConnectError.ErrorDetail(err) + return nil, 0, err + } + modelObj := db.Table("system_user_behavior").Alias("sub") + modelObj.Join("INNER", []string{"system_user", "su"}, "sub.user_id = su.id") + modelObj.Join("INNER", []string{"system_organization_tree", "sot"}, "sot.organization_id = su.organization_id") + modelObj.Select("sub.*, su.system_account, su.phone, sot.name as org_name") + // 条件查询 + if params.Search != "" { + keyword := util.SpecialEscape(params.Search) + modelObj.Where("system_account like ? or system_module like ? or operate_addr like ?", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%") + } + // 上次访问时间 + if params.StartAt != "" && params.EndAt != "" { + applyEndTime, timeErr := time.Parse(jsontime.LocalDateFormat, params.EndAt) + if timeErr != nil { + conf.Logger.Error("时间转换错误", zap.Error(timeErr)) + return nil, 0, resp.DbSelectError.ErrorDetail(timeErr) + } + EndAt := applyEndTime.AddDate(0, 0, 1).Format(jsontime.LocalDateFormat) + modelObj.Where("last_access_time >= ? and last_access_time < ?", params.StartAt, EndAt) + } + // 操作类型 + if params.OperateType != "" { + modelObj.Where("operate_type = ?", params.OperateType) + } + // 请求方式 + if params.ReqMethod != 0 { + modelObj.Where("req_method = ?", params.ReqMethod) + } + // 操作状态 + if params.OperateStatus != 0 { + modelObj.Where("operate_status = ?", params.OperateStatus) + } + total, err = modelObj.OrderBy("created_time desc").Limit(params.GetPageSize(), params.GetOffset()).FindAndCount(&list) + if err != nil { + conf.Logger.Error("查询用户行为审计列表失败", zap.Error(err)) + err = resp.DbSelectError.WithError(errors.New("查询用户行为审计列表失败")) + return nil, 0, err + } + return list, total, nil +} + +// 用户行为审计导出 +func (s *LogManagement) LogUserBehaviorListExport(params *request.LogUserBehaviorListReq) (xlFile *xlsx.File, fileName string, err error) { + xlFile = xlsx.NewFile() + sheet, err := xlFile.AddSheet("sheet") + if err != nil { + return nil, "", resp.AddSheetError.ErrorDetail(err) + } + titleRow := sheet.AddRow() + tmp := []string{ + "序号", "账号", "手机号", "所属组织", "系统模块", "操作类型", "请求方式", "操作状态", "操作地址", "操作地点", "请求地址", "请求参数", "操作方法", "返回参数", "操作时间", + } + xlsRow2 := tools.NewRow(titleRow, tmp) + err = xlsRow2.SetRowTitle() + if err != nil { + return + } + var ( + list []response.SystemUserBehaviorList + total int64 + ) + + list, total, err = s.LogUserBehaviorList(params) + + if err != nil { + return nil, "", resp.DbSelectError.ErrorDetail(err) + } + if total == 0 { + return nil, "", resp.DbSelectError.ErrorDetail(errors.New("没有可导出的数据")) + } + fileName = "用户行为审计" + ".xlsx" + id := 0 + for _, detail := range list { + id += 1 + currentRow := sheet.AddRow() + var tmp = []string{ + strconv.Itoa(id), detail.SystemAccount, detail.Phone, detail.OrgName, detail.SystemModule, detail.OperateType, + constant.HttpMethodStrMap[detail.ReqMethod], constant.OperateStatusStrMap[detail.OperateStatus], detail.OperateIp, detail.OperateAddr, + detail.ReqUrl, detail.ReqParam, constant.HttpMethodStrMap[detail.ReqMethod], detail.ResFields, cast.ToString(detail.CreatedTime), + } + newRow := tools.NewRow(currentRow, tmp) + err := newRow.GenerateRow() + if err != nil { + return nil, "", resp.AddSheetError.ErrorDetail(err) + } + } + return +} + +// 用户行为审计详情 +func (s *LogManagement) LogUserBehaviorDetail(id string) (data *response.LogUserBehaviorDetailRep, err error) { + + db, err := client.GetDbClient() + if err != nil { + err = resp.DbConnectError.ErrorDetail(err) + return nil, err + } + data = new(response.LogUserBehaviorDetailRep) + modelObj := db.Table("system_user_behavior").Alias("sub") + modelObj.Join("INNER", []string{"system_user", "su"}, "sub.user_id = su.id") + modelObj.Join("INNER", []string{"system_organization_tree", "sot"}, "sot.organization_id = su.organization_id") + modelObj.Select("sub.*, su.system_account, su.phone, sot.name as org_name") + _, err = modelObj.Where("sub.id = ?", id).And("sub.is_deleted = 0").Get(data) + if err != nil { + conf.Logger.Error("获取用户行为审计详情失败", zap.Error(err)) + return nil, resp.DbSelectError.ErrorDetail(err) + } + data.OperateStatusStr = constant.OperateStatusStrMap[data.OperateStatus] + data.ReqMethodStr = constant.HttpMethodStrMap[data.ReqMethod] + //data.UserType = constant.UserTypeStrMap[data.IsAdmin] + return data, nil + +} + +func (s *LogManagement) LogUserBehaviorDelete(ids []string) (err error) { + + db, err := client.GetDbClient() + if err != nil { + return resp.DbConnectError.ErrorDetail(err) + } + _, err = db.Table("system_user_behavior").In("id", ids).Update(&map[string]interface{}{"is_deleted": 1}) + if err != nil { + return resp.DbDeleteError.ErrorDetail(err) + } + + return nil +} + //// LogUserAccountAuditList 行为日志列表 //func (s *LogManagement) LogUserAccountAuditList(params *request.LogManagementListReq) ([]response.LogManagementRep, int64, error) { // var logManagementRep = []response.LogManagementRep{} @@ -223,57 +368,6 @@ func (s *LogManagement) GetSysLog(logLevel, search, logName string) ([]string, e //} // //// 用户行为审计列表 -//func (s *LogManagement) LogUserBehaviorList(params *request.LogUserBehaviorListReq) (list []response.SystemUserBehaviorList, total int64, err error) { -// db, err := client.GetDbClient() -// if err != nil { -// err = res.DbConnectError.ErrorDetail(err) -// return nil, 0, err -// } -// modelObj := db.Table("system_user_behavior").Alias("sub") -// modelObj.Join("INNER", []string{"system_user", "su"}, "sub.system_id = su.system_id") -// modelObj.Join("INNER", []string{"system_organization_tree", "sot"}, "sot.organization_id = su.organization_id") -// modelObj.Select("sub.*, su.system_account, su.phone, su.is_admin, sot.name as org_name") -// // 条件查询 -// if params.Search != "" { -// keyword := util.SpecialEscape(params.Search) -// modelObj.Where("system_account ilike ? or system_module ilike ? or operate_addr ilike ?", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%") -// } -// // 用户类型 -// if params.IsAdmin != 0 { -// modelObj.Where("is_admin = ?", params.IsAdmin) -// } -// // 上次访问时间 -// if params.StartAt != "" && params.EndAt != "" { -// applyEndTime, timeErr := time.Parse(jsonTime.LocalDateFormat, params.EndAt) -// if timeErr != nil { -// conf.Logger.Error("时间转换错误", zap.Error(timeErr)) -// return nil, 0, res.DataFailError.ErrorDetail(timeErr) -// } -// EndAt := applyEndTime.AddDate(0, 0, 1).Format(jsonTime.LocalDateFormat) -// modelObj.Where("last_access_time >= ? and last_access_time < ?", params.StartAt, EndAt) -// } -// // 操作类型 -// if params.OperateType != "" { -// modelObj.Where("operate_type = ?", params.OperateType) -// } -// // 请求方式 -// if params.ReqMethod != 0 { -// modelObj.Where("req_method = ?", params.ReqMethod) -// } -// // 操作状态 -// if params.OperateStatus != 0 { -// modelObj.Where("operate_status = ?", params.OperateStatus) -// } -// total, err = modelObj.OrderBy("created_time desc").Limit(int(params.Limit), int(params.Offset)).FindAndCount(&list) -// if err != nil { -// conf.Logger.Error("查询用户行为审计列表失败", zap.Error(err)) -// err = res.DbSelectError.ErrorDetail(errors.New("查询用户行为审计列表失败")) -// return nil, 0, err -// } -// return list, total, nil -//} -// -//// 用户行为审计列表 //func (s *LogManagement) LogUserBehaviorListEs(params *request.LogUserBehaviorListReq) (list []response.SystemUserBehaviorList, total int64, err error) { // es, err := client.GetEsConnection(conf.EsDoc.Index) // if err != nil { @@ -363,163 +457,3 @@ func (s *LogManagement) GetSysLog(logLevel, search, logName string) ([]string, e // return list, total, nil //} // -//// 用户行为审计导出 -//func (s *LogManagement) LogUserBehaviorListExport(params *request.LogUserBehaviorListReq) (xlFile *xlsx.File, fileName string, err error) { -// xlFile = xlsx.NewFile() -// sheet, err := xlFile.AddSheet("sheet") -// if err != nil { -// return nil, "", res.AddSheetError.ErrorDetail(err) -// } -// titleRow := sheet.AddRow() -// tmp := []string{ -// "序号", "账号", "手机号", "用户类型", "所属组织", "系统模块", "操作类型", "请求方式", "操作状态", "操作地址", "操作地点", "请求地址", "请求参数", "操作方法", "返回参数", "操作时间", -// } -// xlsRow2 := tools.NewRow(titleRow, tmp) -// err = xlsRow2.SetRowTitle() -// if err != nil { -// return -// } -// var ( -// list []response.SystemUserBehaviorList -// total int64 -// ) -// if conf.Options.IsBehaviorToES { -// params.Page = 1 -// params.Limit = 20000 -// list, total, err = s.LogUserBehaviorListEs(params) -// -// } else { -// list, total, err = s.LogUserBehaviorList(params) -// } -// if err != nil { -// return nil, "", res.DbSelectError.ErrorDetail(err) -// } -// if total == 0 { -// return nil, "", res.DbSelectError.ErrorDetail(errors.New("没有可导出的数据")) -// } -// fileName = "用户行为审计" + ".xlsx" -// id := 0 -// for _, detail := range list { -// id += 1 -// currentRow := sheet.AddRow() -// var tmp = []string{ -// strconv.Itoa(id), detail.SystemAccount, detail.Phone, constant.UserTypeStrMap[detail.IsAdmin], detail.OrgName, detail.SystemModule, detail.OperateType, -// constant.HttpMethodStrMap[detail.ReqMethod], constant.OperateStatusStrMap[detail.OperateStatus], detail.OperateIp, detail.OperateAddr, -// detail.ReqUrl, detail.ReqParam, constant.HttpMethodStrMap[detail.ReqMethod], detail.ResFields, cast.ToString(detail.CreatedTime), -// } -// newRow := tools.NewRow(currentRow, tmp) -// err := newRow.GenerateRow() -// if err != nil { -// return nil, "", res.AddSheetError.ErrorDetail(err) -// } -// } -// return -//} -// -//// 用户行为审计详情 -//func (s *LogManagement) LogUserBehaviorDetail(id string) (data *response.LogUserBehaviorDetailRep, err error) { -// if !conf.Options.IsBehaviorToES { -// db, err := client.GetDbClient() -// if err != nil { -// err = res.DbConnectError.ErrorDetail(err) -// return nil, err -// } -// data = new(response.LogUserBehaviorDetailRep) -// modelObj := db.Table("system_user_behavior").Alias("sub") -// modelObj.Join("INNER", []string{"system_user", "su"}, "sub.system_id = su.system_id") -// modelObj.Join("INNER", []string{"system_organization_tree", "sot"}, "sot.organization_id = su.organization_id") -// modelObj.Select("sub.*, su.system_account, su.phone, su.is_admin, sot.name as org_name") -// _, err = modelObj.Where("sub.id = ?", id).And("sub.is_deleted = 0").Get(data) -// if err != nil { -// conf.Logger.Error("获取用户行为审计详情失败", zap.Error(err)) -// return nil, res.DbSelectError.ErrorDetail(err) -// } -// data.OperateStatusStr = constant.OperateStatusStrMap[data.OperateStatus] -// data.ReqMethodStr = constant.HttpMethodStrMap[data.ReqMethod] -// data.UserType = constant.UserTypeStrMap[data.IsAdmin] -// return data, nil -// } else { -// es, err := client.GetEsConnection(conf.EsDoc.Index) -// if err != nil { -// return nil, res.DbConnectError.ErrorDetail(err) -// } -// result := response.SystemUserBehaviorList{} -// searchResult, err := es.Conn.Get(). -// Index(conf.EsDoc.Index). -// Id(id). -// Do(context.Background()) -// if err != nil { -// return nil, res.DbSelectError.ErrorDetail(err) -// } -// err = json.Unmarshal(searchResult.Source, &result) -// if err != nil { -// return nil, res.JsonMarshalError.ErrorDetail(err) -// } -// data = new(response.LogUserBehaviorDetailRep) -// db, err := client.GetDbClient() -// if err != nil { -// err = res.DbConnectError.ErrorDetail(err) -// return nil, err -// } -// modelObj := db.Table("system_user").Alias("su") -// modelObj.Join("INNER", []string{"system_organization_tree", "sot"}, "sot.organization_id = su.organization_id") -// modelObj.Select("su.system_account, su.phone, su.is_admin, sot.name as org_name") -// _, err = modelObj.Where("su.system_id = ?", result.SystemId).Get(data) -// if err != nil { -// conf.Logger.Error("获取用户行为审计详情失败", zap.Error(err)) -// return nil, res.DbSelectError.ErrorDetail(err) -// } -// data.OperateStatusStr = constant.OperateStatusStrMap[data.OperateStatus] -// data.ReqMethodStr = constant.HttpMethodStrMap[data.ReqMethod] -// data.UserType = constant.UserTypeStrMap[data.IsAdmin] -// data = &response.LogUserBehaviorDetailRep{ -// Id: cast.ToInt(result.Id), -// SystemId: result.SystemId, -// OrganizationId: result.OrganizationId, -// SystemModule: result.SystemModule, -// OperateType: result.OperateType, -// ReqMethod: result.ReqMethod, -// OperateStatus: result.OperateStatus, -// OperateIp: result.OperateIp, -// OperateAddr: result.OperateAddr, -// CreatedTime: result.CreatedTime, -// OperateMethod: result.OperateMethod, -// ResFields: result.ResFields, -// ReqParam: result.ReqParam, -// ReqUrl: result.ReqUrl, -// AppId: result.AppId, -// SystemAccount: result.SystemAccount, -// IsAdmin: result.IsAdmin, -// } -// return data, nil -// } -//} -// -//func (s *LogManagement) LogUserBehaviorDelete(ids []string) (err error) { -// if conf.Options.IsBehaviorToES { -// es, err := client.GetEsConnection(conf.EsDoc.Index) -// if err != nil { -// return res.DbConnectError.ErrorDetail(err) -// } -// bulkService := es.Conn.Bulk().Index(conf.EsDoc.Index).Refresh("true") -// for i := range ids { -// req := elastic.NewBulkDeleteRequest().Id(ids[i]) -// bulkService.Add(req) -// } -// result, err := bulkService.Do(context.Background()) -// fmt.Println("success =>", result.Succeeded()) -// if err != nil { -// return res.DbDeleteError.ErrorDetail(err) -// } -// } else { -// db, err := client.GetDbClient() -// if err != nil { -// return res.DbConnectError.ErrorDetail(err) -// } -// _, err = db.Table("system_user_behavior").Update(&map[string]interface{}{"is_deleted": 1}) -// if err != nil { -// return res.DbDeleteError.ErrorDetail(err) -// } -// } -// return nil -//}