mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-09-06 17:46:23 +00:00
feat(audit): add localized security audit logs (#5462)
This commit is contained in:
@@ -64,6 +64,7 @@ const (
|
||||
LogTypeSystem = 4
|
||||
LogTypeError = 5
|
||||
LogTypeRefund = 6
|
||||
LogTypeLogin = 7
|
||||
)
|
||||
|
||||
func formatUserLogs(logs []*Log, startIdx int) {
|
||||
@@ -74,6 +75,8 @@ func formatUserLogs(logs []*Log, startIdx int) {
|
||||
if otherMap != nil {
|
||||
// Remove admin-only debug fields.
|
||||
delete(otherMap, "admin_info")
|
||||
// Remove operation-audit details (operator/route info), admin-only.
|
||||
delete(otherMap, "audit_info")
|
||||
// delete(otherMap, "reject_reason")
|
||||
delete(otherMap, "stream_status")
|
||||
}
|
||||
@@ -130,6 +133,74 @@ func RecordLogWithAdminInfo(userId int, logType int, content string, adminInfo m
|
||||
}
|
||||
}
|
||||
|
||||
// buildOpField 构建语言无关的操作描述(写入 Other.op)。
|
||||
// 前端依据 action(稳定操作标识) + params(结构化参数) 在渲染期用 i18n 本地化展示,
|
||||
// 因此不在数据库中存储自然语言句子。
|
||||
func buildOpField(action string, params map[string]interface{}) map[string]interface{} {
|
||||
op := map[string]interface{}{
|
||||
"action": action,
|
||||
}
|
||||
if len(params) > 0 {
|
||||
op["params"] = params
|
||||
}
|
||||
return op
|
||||
}
|
||||
|
||||
// RecordLoginLog 记录用户登录成功的审计日志(type=LogTypeLogin)。
|
||||
// username 由调用方传入(登录流程已持有用户对象),避免额外的数据库查询。
|
||||
// content 为英文兜底文本(用于导出/经典前端);action+params 供前端本地化渲染。
|
||||
// extra 可携带 login_method、user_agent 等附加信息(普通用户可见)。
|
||||
func RecordLoginLog(userId int, username string, content string, ip string, action string, params map[string]interface{}, extra map[string]interface{}) {
|
||||
other := map[string]interface{}{}
|
||||
for k, v := range extra {
|
||||
other[k] = v
|
||||
}
|
||||
other["op"] = buildOpField(action, params)
|
||||
log := &Log{
|
||||
UserId: userId,
|
||||
Username: username,
|
||||
CreatedAt: common.GetTimestamp(),
|
||||
Type: LogTypeLogin,
|
||||
Content: content,
|
||||
Ip: ip,
|
||||
Other: common.MapToJsonStr(other),
|
||||
}
|
||||
if err := LOG_DB.Create(log).Error; err != nil {
|
||||
common.SysLog("failed to record login log: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// RecordOperationAuditLog 记录管理/高危操作审计日志(type=LogTypeManage)。
|
||||
// logUserId 为日志归属者(面向用户的操作如额度调整归属目标用户,资源类操作如渠道/系统设置归属操作者),
|
||||
// username 内部按 logUserId 查询。content 为英文兜底文本(导出/经典前端用)。
|
||||
// action+params 写入 Other.op,供前端本地化渲染(普通用户可见,不含敏感信息)。
|
||||
// adminInfo 存放操作者身份(写入 Other.admin_info,普通用户查询时剥离);
|
||||
// auditInfo 存放路由/方法/结果等中间件兜底信息(写入 Other.audit_info,普通用户查询时剥离)。
|
||||
func RecordOperationAuditLog(logUserId int, content string, ip string, action string, params map[string]interface{}, adminInfo map[string]interface{}, auditInfo map[string]interface{}) {
|
||||
username, _ := GetUsernameById(logUserId, false)
|
||||
other := map[string]interface{}{
|
||||
"op": buildOpField(action, params),
|
||||
}
|
||||
if len(adminInfo) > 0 {
|
||||
other["admin_info"] = adminInfo
|
||||
}
|
||||
if len(auditInfo) > 0 {
|
||||
other["audit_info"] = auditInfo
|
||||
}
|
||||
log := &Log{
|
||||
UserId: logUserId,
|
||||
Username: username,
|
||||
CreatedAt: common.GetTimestamp(),
|
||||
Type: LogTypeManage,
|
||||
Content: content,
|
||||
Ip: ip,
|
||||
Other: common.MapToJsonStr(other),
|
||||
}
|
||||
if err := LOG_DB.Create(log).Error; err != nil {
|
||||
common.SysLog("failed to record operation audit log: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func RecordTopupLog(userId int, content string, callerIp string, paymentMethod string, callbackPaymentMethod string) {
|
||||
username, _ := GetUsernameById(userId, false)
|
||||
adminInfo := map[string]interface{}{
|
||||
|
||||
Reference in New Issue
Block a user