mirror of
https://github.com/lkmio/gb-cms.git
synced 2025-12-24 11:51:52 +08:00
feat: 支持统计操作日志
This commit is contained in:
153
api/api.go
153
api/api.go
@@ -3,8 +3,10 @@ package api
|
||||
import (
|
||||
"gb-cms/common"
|
||||
"gb-cms/dao"
|
||||
"gb-cms/log"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/websocket"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
@@ -12,8 +14,9 @@ import (
|
||||
)
|
||||
|
||||
type ApiServer struct {
|
||||
router *mux.Router
|
||||
upgrader *websocket.Upgrader
|
||||
router *mux.Router
|
||||
upgrader *websocket.Upgrader
|
||||
actionNames map[string]string
|
||||
}
|
||||
|
||||
type InviteParams struct {
|
||||
@@ -108,7 +111,7 @@ type QueryDeviceChannel struct {
|
||||
Filter string `json:"filter"`
|
||||
|
||||
Priority int `json:"priority"` // 报警参数
|
||||
Method int `json:"method"`
|
||||
Method string `json:"method"`
|
||||
StartTime string `json:"starttime"`
|
||||
EndTime string `json:"endtime"`
|
||||
}
|
||||
@@ -176,6 +179,22 @@ type DeviceInfo struct {
|
||||
Latitude float64 `json:"latitude"`
|
||||
}
|
||||
|
||||
type responseRecorder struct {
|
||||
http.ResponseWriter
|
||||
statusCode int
|
||||
body []byte
|
||||
}
|
||||
|
||||
func (r *responseRecorder) WriteHeader(statusCode int) {
|
||||
r.statusCode = statusCode
|
||||
r.ResponseWriter.WriteHeader(statusCode)
|
||||
}
|
||||
|
||||
func (r *responseRecorder) Write(b []byte) (int, error) {
|
||||
r.body = append(r.body, b...)
|
||||
return r.ResponseWriter.Write(b)
|
||||
}
|
||||
|
||||
type Empty struct {
|
||||
}
|
||||
|
||||
@@ -189,7 +208,8 @@ func init() {
|
||||
},
|
||||
},
|
||||
|
||||
router: mux.NewRouter(),
|
||||
actionNames: make(map[string]string, 32),
|
||||
router: mux.NewRouter(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,6 +246,12 @@ func withVerify2(onSuccess func(w http.ResponseWriter, req *http.Request), onFai
|
||||
}
|
||||
}
|
||||
|
||||
// 注册带统计的api
|
||||
func (api *ApiServer) registerStatisticsHandler(actionName, path string, handler func(http.ResponseWriter, *http.Request)) {
|
||||
api.router.HandleFunc(path, handler)
|
||||
api.actionNames[path] = actionName
|
||||
}
|
||||
|
||||
func StartApiServer(addr string) {
|
||||
apiServer.router.HandleFunc("/api/v1/hook/on_play", common.WithJsonParams(apiServer.OnPlay, &PlayDoneParams{}))
|
||||
apiServer.router.HandleFunc("/api/v1/hook/on_play_done", common.WithJsonParams(apiServer.OnPlayDone, &PlayDoneParams{}))
|
||||
@@ -236,60 +262,61 @@ func StartApiServer(addr string) {
|
||||
apiServer.router.HandleFunc("/api/v1/hook/on_record", common.WithJsonParams(apiServer.OnRecord, &RecordParams{}))
|
||||
apiServer.router.HandleFunc("/api/v1/hook/on_started", apiServer.OnStarted)
|
||||
|
||||
apiServer.router.HandleFunc("/api/v1/stream/start", withVerify(common.WithFormDataParams(apiServer.OnStreamStart, InviteParams{}))) // 实时预览
|
||||
apiServer.router.HandleFunc("/api/v1/stream/stop", withVerify(common.WithFormDataParams(apiServer.OnCloseLiveStream, InviteParams{}))) // 关闭实时预览
|
||||
apiServer.router.HandleFunc("/api/v1/playback/start", withVerify(common.WithFormDataParams(apiServer.OnPlaybackStart, InviteParams{}))) // 回放/下载
|
||||
apiServer.router.HandleFunc("/api/v1/playback/stop", withVerify(common.WithFormDataParams(apiServer.OnCloseStream, StreamIDParams{}))) // 关闭回放/下载
|
||||
apiServer.router.HandleFunc("/api/v1/playback/control", withVerify(common.WithFormDataParams(apiServer.OnPlaybackControl, StreamIDParams{}))) // 回放控制
|
||||
apiServer.registerStatisticsHandler("开始预览", "/api/v1/stream/start", withVerify(common.WithFormDataParams(apiServer.OnStreamStart, InviteParams{}))) // 实时预览
|
||||
apiServer.registerStatisticsHandler("停止预览", "/api/v1/stream/stop", withVerify(common.WithFormDataParams(apiServer.OnCloseLiveStream, InviteParams{}))) // 关闭实时预览
|
||||
apiServer.registerStatisticsHandler("开始回放/下载", "/api/v1/playback/start", withVerify(common.WithFormDataParams(apiServer.OnPlaybackStart, InviteParams{}))) // 回放/下载
|
||||
apiServer.registerStatisticsHandler("停止回放/下载", "/api/v1/playback/stop", withVerify(common.WithFormDataParams(apiServer.OnCloseStream, StreamIDParams{}))) // 关闭回放/下载
|
||||
apiServer.registerStatisticsHandler("回放控制", "/api/v1/playback/control", withVerify(common.WithFormDataParams(apiServer.OnPlaybackControl, StreamIDParams{}))) // 回放控制
|
||||
|
||||
apiServer.router.HandleFunc("/api/v1/device/list", withVerify(common.WithQueryStringParams(apiServer.OnDeviceList, QueryDeviceChannel{}))) // 查询设备列表
|
||||
apiServer.router.HandleFunc("/api/v1/device/channeltree", withVerify(common.WithQueryStringParams(apiServer.OnDeviceTree, QueryDeviceChannel{}))) // 设备树
|
||||
apiServer.router.HandleFunc("/api/v1/device/channellist", withVerify(common.WithQueryStringParams(apiServer.OnChannelList, QueryDeviceChannel{}))) // 查询通道列表
|
||||
apiServer.router.HandleFunc("/api/v1/device/fetchcatalog", withVerify(common.WithQueryStringParams(apiServer.OnCatalogQuery, QueryDeviceChannel{}))) // 更新通道
|
||||
apiServer.router.HandleFunc("/api/v1/device/remove", withVerify(common.WithFormDataParams(apiServer.OnDeviceRemove, DeleteDevice{}))) // 删除设备
|
||||
apiServer.router.HandleFunc("/api/v1/device/setmediatransport", withVerify(common.WithFormDataParams(apiServer.OnDeviceMediaTransportSet, SetMediaTransportReq{}))) // 设置设备媒体传输模式
|
||||
apiServer.router.HandleFunc("/api/v1/device/list", withVerify(common.WithQueryStringParams(apiServer.OnDeviceList, QueryDeviceChannel{}))) // 查询设备列表
|
||||
apiServer.router.HandleFunc("/api/v1/device/channeltree", withVerify(common.WithQueryStringParams(apiServer.OnDeviceTree, QueryDeviceChannel{}))) // 设备树
|
||||
apiServer.router.HandleFunc("/api/v1/device/channellist", withVerify(common.WithQueryStringParams(apiServer.OnChannelList, QueryDeviceChannel{}))) // 查询通道列表
|
||||
apiServer.registerStatisticsHandler("手动刷新通道", "/api/v1/device/fetchcatalog", withVerify(common.WithQueryStringParams(apiServer.OnCatalogQuery, QueryDeviceChannel{}))) // 更新通道
|
||||
apiServer.registerStatisticsHandler("删除设备", "/api/v1/device/remove", withVerify(common.WithFormDataParams(apiServer.OnDeviceRemove, DeleteDevice{}))) // 删除设备
|
||||
apiServer.registerStatisticsHandler("设置设备媒体传输模式", "/api/v1/device/setmediatransport", withVerify(common.WithFormDataParams(apiServer.OnDeviceMediaTransportSet, SetMediaTransportReq{}))) // 设置设备媒体传输模式
|
||||
|
||||
apiServer.router.HandleFunc("/api/v1/playback/recordlist", withVerify(common.WithQueryStringParams(apiServer.OnRecordList, QueryRecordParams{}))) // 查询录像列表
|
||||
apiServer.registerStatisticsHandler("查询录像列表", "/api/v1/playback/recordlist", withVerify(common.WithQueryStringParams(apiServer.OnRecordList, QueryRecordParams{}))) // 查询录像列表
|
||||
apiServer.router.HandleFunc("/api/v1/stream/info", withVerify(apiServer.OnStreamInfo))
|
||||
apiServer.router.HandleFunc("/api/v1/playback/streaminfo", withVerify(apiServer.OnStreamInfo))
|
||||
apiServer.router.HandleFunc("/api/v1/device/session/list", withVerify(common.WithQueryStringParams(apiServer.OnSessionList, QueryDeviceChannel{}))) // 推流列表
|
||||
apiServer.router.HandleFunc("/api/v1/device/session/stop", withVerify(common.WithFormDataParams(apiServer.OnSessionStop, StreamIDParams{}))) // 关闭流
|
||||
apiServer.router.HandleFunc("/api/v1/device/setchannelid", withVerify(common.WithFormDataParams(apiServer.OnCustomChannelSet, CustomChannel{}))) // 自定义通道ID
|
||||
|
||||
apiServer.router.HandleFunc("/api/v1/playback/seek", common.WithJsonResponse(apiServer.OnSeekPlayback, &SeekParams{})) // 回放seek
|
||||
apiServer.router.HandleFunc("/api/v1/control/ptz", withVerify(common.WithFormDataParams(apiServer.OnPTZControl, QueryRecordParams{}))) // 云台控制
|
||||
apiServer.router.HandleFunc("/api/v1/playback/seek", common.WithJsonResponse(apiServer.OnSeekPlayback, &SeekParams{})) // 回放seek
|
||||
apiServer.registerStatisticsHandler("云台控制", "/api/v1/control/ptz", withVerify(common.WithFormDataParams(apiServer.OnPTZControl, QueryRecordParams{}))) // 云台控制
|
||||
|
||||
apiServer.router.HandleFunc("/api/v1/cascade/list", withVerify(common.WithQueryStringParams(apiServer.OnPlatformList, QueryDeviceChannel{}))) // 级联设备列表
|
||||
apiServer.router.HandleFunc("/api/v1/cascade/save", withVerify(common.WithFormDataParams(apiServer.OnPlatformAdd, LiveGBSCascade{}))) // 添加级联设备
|
||||
apiServer.router.HandleFunc("/api/v1/cascade/setenable", withVerify(common.WithFormDataParams(apiServer.OnEnableSet, SetEnable{}))) // 添加级联设备
|
||||
apiServer.router.HandleFunc("/api/v1/cascade/remove", withVerify(common.WithFormDataParams(apiServer.OnPlatformRemove, SetEnable{}))) // 删除级联设备
|
||||
apiServer.registerStatisticsHandler("添加级联设备", "/api/v1/cascade/save", withVerify(common.WithFormDataParams(apiServer.OnPlatformAdd, LiveGBSCascade{}))) // 添加级联设备
|
||||
apiServer.registerStatisticsHandler("设置级联设备状态", "/api/v1/cascade/setenable", withVerify(common.WithFormDataParams(apiServer.OnEnableSet, SetEnable{}))) // 使能级联设备
|
||||
apiServer.registerStatisticsHandler("删除级联设备", "/api/v1/cascade/remove", withVerify(common.WithFormDataParams(apiServer.OnPlatformRemove, SetEnable{}))) // 删除级联设备
|
||||
apiServer.router.HandleFunc("/api/v1/cascade/channellist", withVerify(common.WithQueryStringParams(apiServer.OnPlatformChannelList, QueryCascadeChannelList{}))) // 级联设备通道列表
|
||||
|
||||
apiServer.router.HandleFunc("/api/v1/cascade/savechannels", withVerify(apiServer.OnPlatformChannelBind)) // 级联绑定通道
|
||||
apiServer.router.HandleFunc("/api/v1/cascade/removechannels", withVerify(apiServer.OnPlatformChannelUnbind)) // 级联解绑通道
|
||||
apiServer.router.HandleFunc("/api/v1/cascade/setshareallchannel", withVerify(common.WithFormDataParams(apiServer.OnShareAllChannel, SetEnable{}))) // 开启或取消级联所有通道
|
||||
apiServer.router.HandleFunc("/api/v1/cascade/pushcatalog", withVerify(common.WithFormDataParams(apiServer.OnCatalogPush, SetEnable{}))) // 推送目录
|
||||
apiServer.router.HandleFunc("/api/v1/device/setinfo", withVerify(common.WithFormDataParams(apiServer.OnDeviceInfoSet, DeviceInfo{}))) // 编辑设备信息
|
||||
apiServer.router.HandleFunc("/api/v1/alarm/list", withVerify(common.WithQueryStringParams(apiServer.OnAlarmList, QueryDeviceChannel{}))) // 报警查询
|
||||
apiServer.router.HandleFunc("/api/v1/alarm/remove", withVerify(common.WithFormDataParams(apiServer.OnAlarmRemove, SetEnable{}))) // 删除报警
|
||||
apiServer.router.HandleFunc("/api/v1/alarm/clear", withVerify(common.WithFormDataParams(apiServer.OnAlarmClear, Empty{}))) // 清空报警
|
||||
apiServer.router.HandleFunc("/api/v1/cascade/savechannels", withVerify(apiServer.OnPlatformChannelBind)) // 级联绑定通道
|
||||
apiServer.router.HandleFunc("/api/v1/cascade/removechannels", withVerify(apiServer.OnPlatformChannelUnbind)) // 级联解绑通道
|
||||
apiServer.router.HandleFunc("/api/v1/cascade/setshareallchannel", withVerify(common.WithFormDataParams(apiServer.OnShareAllChannel, SetEnable{}))) // 开启或取消级联所有通道
|
||||
apiServer.registerStatisticsHandler("推送目录", "/api/v1/cascade/pushcatalog", withVerify(common.WithFormDataParams(apiServer.OnCatalogPush, SetEnable{}))) // 推送目录
|
||||
apiServer.registerStatisticsHandler("编辑设备信息", "/api/v1/device/setinfo", withVerify(common.WithFormDataParams(apiServer.OnDeviceInfoSet, DeviceInfo{}))) // 编辑设备信息
|
||||
apiServer.router.HandleFunc("/api/v1/alarm/list", withVerify(common.WithQueryStringParams(apiServer.OnAlarmList, QueryDeviceChannel{}))) // 报警查询
|
||||
apiServer.registerStatisticsHandler("删除报警", "/api/v1/alarm/remove", withVerify(common.WithFormDataParams(apiServer.OnAlarmRemove, SetEnable{}))) // 删除报警
|
||||
apiServer.registerStatisticsHandler("清空报警", "/api/v1/alarm/clear", withVerify(common.WithFormDataParams(apiServer.OnAlarmClear, Empty{}))) // 清空报警
|
||||
apiServer.router.HandleFunc("/api/v1/log/list", withVerify(common.WithQueryStringParams(apiServer.OnLogList, QueryDeviceChannel{}))) // 操作日志
|
||||
apiServer.router.HandleFunc("/api/v1/log/clear", withVerify(common.WithQueryStringParams(apiServer.OnLogClear, Empty{}))) // 操作日志
|
||||
|
||||
// 暂未开发
|
||||
apiServer.router.HandleFunc("/api/v1/sms/list", withVerify(func(w http.ResponseWriter, req *http.Request) {})) // 流媒体服务器列表
|
||||
apiServer.router.HandleFunc("/api/v1/cloudrecord/querychannels", withVerify(func(w http.ResponseWriter, req *http.Request) {})) // 云端录像
|
||||
apiServer.router.HandleFunc("/api/v1/user/list", withVerify(func(w http.ResponseWriter, req *http.Request) {})) // 用户管理
|
||||
apiServer.router.HandleFunc("/api/v1/log/list", withVerify(func(w http.ResponseWriter, req *http.Request) {})) // 操作日志
|
||||
apiServer.router.HandleFunc("/api/v1/getbaseconfig", withVerify(common.WithFormDataParams(apiServer.OnGetBaseConfig, Empty{})))
|
||||
apiServer.router.HandleFunc("/api/v1/setbaseconfig", withVerify(common.WithFormDataParams(apiServer.OnSetBaseConfig, Empty{})))
|
||||
apiServer.router.HandleFunc("/api/v1/gm/cert/list", withVerify(func(w http.ResponseWriter, req *http.Request) {}))
|
||||
apiServer.router.HandleFunc("/api/v1/getrequestkey", withVerify(func(w http.ResponseWriter, req *http.Request) {}))
|
||||
|
||||
apiServer.router.HandleFunc("/api/v1/record/start", withVerify(apiServer.OnRecordStart)) // 开启录制
|
||||
apiServer.router.HandleFunc("/api/v1/record/stop", withVerify(apiServer.OnRecordStop)) // 关闭录制
|
||||
apiServer.registerStatisticsHandler("开始录制", "/api/v1/record/start", withVerify(apiServer.OnRecordStart)) // 开启录制
|
||||
apiServer.registerStatisticsHandler("结束录制", "/api/v1/record/stop", withVerify(apiServer.OnRecordStop)) // 关闭录制
|
||||
|
||||
apiServer.router.HandleFunc("/api/v1/broadcast/invite", common.WithJsonResponse(apiServer.OnBroadcast, &BroadcastParams{Setup: &common.DefaultSetupType})) // 发起语音广播
|
||||
apiServer.router.HandleFunc("/api/v1/broadcast/hangup", common.WithJsonResponse(apiServer.OnHangup, &BroadcastParams{})) // 挂断广播会话
|
||||
apiServer.router.HandleFunc("/api/v1/control/ws-talk/{device}/{channel}", withVerify(apiServer.OnTalk)) // 一对一语音对讲
|
||||
apiServer.registerStatisticsHandler("发起对讲", "/api/v1/control/ws-talk/{device}/{channel}", withVerify(apiServer.OnTalk)) // 一对一语音对讲
|
||||
|
||||
apiServer.router.HandleFunc("/api/v1/jt/device/add", common.WithJsonResponse(apiServer.OnVirtualDeviceAdd, &dao.JTDeviceModel{}))
|
||||
apiServer.router.HandleFunc("/api/v1/jt/device/edit", common.WithJsonResponse(apiServer.OnVirtualDeviceEdit, &dao.JTDeviceModel{}))
|
||||
@@ -299,7 +326,7 @@ func StartApiServer(addr string) {
|
||||
apiServer.router.HandleFunc("/api/v1/jt/channel/add", common.WithJsonResponse(apiServer.OnVirtualChannelAdd, &dao.ChannelModel{}))
|
||||
apiServer.router.HandleFunc("/api/v1/jt/channel/edit", common.WithJsonResponse(apiServer.OnVirtualChannelEdit, &dao.ChannelModel{}))
|
||||
apiServer.router.HandleFunc("/api/v1/jt/channel/remove", common.WithJsonResponse(apiServer.OnVirtualChannelRemove, &dao.ChannelModel{}))
|
||||
apiServer.router.HandleFunc("/logout", func(writer http.ResponseWriter, req *http.Request) {
|
||||
apiServer.registerStatisticsHandler("退出登录", "/api/v1/logout", func(writer http.ResponseWriter, req *http.Request) {
|
||||
cookie, err := req.Cookie("token")
|
||||
if err == nil {
|
||||
TokenManager.Remove(cookie.Value)
|
||||
@@ -311,6 +338,64 @@ func StartApiServer(addr string) {
|
||||
|
||||
registerLiveGBSApi()
|
||||
|
||||
apiServer.router.Use(func(handler http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
now := time.Now()
|
||||
name, ok := apiServer.actionNames[r.URL.Path]
|
||||
recorder := &responseRecorder{ResponseWriter: w}
|
||||
handler.ServeHTTP(recorder, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
end := time.Now()
|
||||
var address string
|
||||
if common.Config.IP2RegionEnable {
|
||||
host, _, _ := net.SplitHostPort(r.RemoteAddr)
|
||||
region, err := common.IP2Region(host)
|
||||
if err == nil {
|
||||
address = region
|
||||
} else {
|
||||
log.Sugar.Errorf("IP2Region error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// /api/v1/login
|
||||
var username = "admin"
|
||||
if r.URL.Path == "/api/v1/login" {
|
||||
username = r.FormValue("username")
|
||||
}
|
||||
|
||||
var status = "OK"
|
||||
if recorder.statusCode == 0 {
|
||||
recorder.statusCode = http.StatusOK
|
||||
}
|
||||
|
||||
if recorder.statusCode != http.StatusOK {
|
||||
status = string(recorder.body)
|
||||
}
|
||||
|
||||
model := dao.LogModel{
|
||||
Name: name,
|
||||
Scheme: "HTTP",
|
||||
Method: r.Method,
|
||||
RequestURI: r.URL.Path,
|
||||
RemoteAddr: r.RemoteAddr,
|
||||
RemoteRegion: address,
|
||||
Status: status,
|
||||
StatusCode: recorder.statusCode,
|
||||
StartAt: now.Format("2006-01-02 15:04:05"),
|
||||
Duration: int(end.Sub(now).Seconds()),
|
||||
Username: username,
|
||||
}
|
||||
|
||||
err := dao.Log.Save(&model)
|
||||
if err != nil {
|
||||
log.Sugar.Errorf("Save log error: %v", err)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// 前端路由
|
||||
htmlRoot := "./html/"
|
||||
fileServer := http.FileServer(http.Dir(htmlRoot))
|
||||
|
||||
@@ -30,7 +30,7 @@ func (api *ApiServer) OnAlarmList(q *QueryDeviceChannel, _ http.ResponseWriter,
|
||||
conditions["alarm_priority"] = q.Priority
|
||||
}
|
||||
|
||||
if q.Method > 0 {
|
||||
if q.Method != "" {
|
||||
conditions["alarm_method"] = q.Method
|
||||
}
|
||||
|
||||
|
||||
@@ -115,8 +115,8 @@ func registerLiveGBSApi() {
|
||||
},
|
||||
}
|
||||
|
||||
apiServer.router.HandleFunc("/api/v1/login", common.WithFormDataParams(apiServer.OnLogin, LoginReq{}))
|
||||
apiServer.router.HandleFunc("/api/v1/modifypassword", withVerify(common.WithFormDataParams(apiServer.OnModifyPassword, ModifyPasswordReq{})))
|
||||
apiServer.registerStatisticsHandler("登录", "/api/v1/login", common.WithFormDataParams(apiServer.OnLogin, LoginReq{}))
|
||||
apiServer.registerStatisticsHandler("修改密码", "/api/v1/modifypassword", withVerify(common.WithFormDataParams(apiServer.OnModifyPassword, ModifyPasswordReq{})))
|
||||
|
||||
apiServer.router.HandleFunc("/api/v1/dashboard/auth", withVerify(func(writer http.ResponseWriter, request *http.Request) {
|
||||
response := struct {
|
||||
|
||||
@@ -236,3 +236,38 @@ func (api *ApiServer) OnSetBaseConfig(baseConfig *BaseConfig, _ http.ResponseWri
|
||||
common.Config = newConfig
|
||||
return "OK", nil
|
||||
}
|
||||
|
||||
func (api *ApiServer) OnLogList(q *QueryDeviceChannel, _ http.ResponseWriter, _ *http.Request) (interface{}, error) {
|
||||
if q.Limit < 1 {
|
||||
q.Limit = 10
|
||||
}
|
||||
|
||||
v := struct {
|
||||
LogCount int
|
||||
LogList interface{}
|
||||
LogRegion bool
|
||||
LogReserveDays int
|
||||
}{
|
||||
LogRegion: common.Config.IP2RegionEnable,
|
||||
LogReserveDays: common.Config.LogReserveDays,
|
||||
}
|
||||
|
||||
query, i, err := dao.Log.Query(q.Limit, (q.Start/q.Limit)+1, q.Keyword, q.Sort, q.Order, q.Method, q.StartTime, q.EndTime)
|
||||
if err != nil {
|
||||
log.Sugar.Errorf("查询操作日志失败: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v.LogCount = i
|
||||
v.LogList = query
|
||||
return &v, err
|
||||
}
|
||||
|
||||
func (api *ApiServer) OnLogClear(_ *Empty, _ http.ResponseWriter, _ *http.Request) (interface{}, error) {
|
||||
if err := dao.Log.Clear(); err != nil {
|
||||
log.Sugar.Errorf("清除操作日志失败: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return "OK", nil
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ type Config_ struct {
|
||||
SubscribeExpires int `json:"subscribe_expires"`
|
||||
PositionReserveDays int `json:"position_reserve_days"`
|
||||
AlarmReserveDays int `json:"alarm_reserve_days"`
|
||||
LogReserveDays int `json:"log_reserve_days"`
|
||||
|
||||
MediaServer string `json:"media_server"`
|
||||
PreferStreamFmt string `json:"prefer_stream_fmt"`
|
||||
@@ -78,6 +79,7 @@ func ParseConfig(path string) (*Config_, error) {
|
||||
SubscribeExpires: load.Section("sip").Key("subscribe_expires").MustInt(),
|
||||
PositionReserveDays: load.Section("sip").Key("position_reserve_days").MustInt(),
|
||||
AlarmReserveDays: load.Section("sip").Key("alarm_reserve_days").MustInt(),
|
||||
LogReserveDays: load.Section("sip").Key("log_reserve_days").MustInt(),
|
||||
MediaServer: load.Section("sip").Key("media_server").String(),
|
||||
PreferStreamFmt: load.Section("sip").Key("prefer_stream_fmt").String(),
|
||||
InviteTimeout: load.Section("sip").Key("invite_timeout").MustInt(),
|
||||
|
||||
@@ -26,6 +26,9 @@ func LoadIP2RegionDB(path string) error {
|
||||
}
|
||||
|
||||
func IP2Region(ip string) (string, error) {
|
||||
if strings.HasPrefix(ip, "127.") || strings.HasPrefix(ip, "192.") || strings.HasPrefix(ip, "10.") || strings.HasPrefix(ip, "172.") || strings.HasPrefix(ip, "::1") {
|
||||
return "内网IP", nil
|
||||
}
|
||||
// 3、查询
|
||||
region, err := searcher.SearchByStr(ip)
|
||||
if err != nil {
|
||||
|
||||
@@ -15,6 +15,8 @@ alive_expires = 180
|
||||
position_reserve_days = 7
|
||||
# 报警记录保留天数, 0-不保存
|
||||
alarm_reserve_days = 3
|
||||
# 操作时间保留天数, 0-不保存
|
||||
log_reserve_days = 3
|
||||
# invite超时时间, 单位秒
|
||||
invite_timeout = 10
|
||||
# udp/passive/active, 优先级小于设备的setup字段
|
||||
|
||||
170
dao/log.go
Normal file
170
dao/log.go
Normal file
@@ -0,0 +1,170 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type LogModel struct {
|
||||
GBModel
|
||||
Name string `json:"Name"`
|
||||
Scheme string `json:"Scheme"`
|
||||
Method string `json:"Method"`
|
||||
RequestURI string `json:"RequestURI"`
|
||||
RemoteAddr string `json:"RemoteAddr"`
|
||||
RemoteRegion string `json:"RemoteRegion"`
|
||||
Status string `json:"Status"`
|
||||
StatusCode int `json:"StatusCode"`
|
||||
StartAt string `json:"StartAt"`
|
||||
Duration int `json:"Duration"`
|
||||
Username string `json:"Username"`
|
||||
ExtInfo string `json:"ExtInfo"`
|
||||
Description string `json:"Description"`
|
||||
}
|
||||
|
||||
func (l *LogModel) TableName() string {
|
||||
return "lkm_log"
|
||||
}
|
||||
|
||||
type daoLog struct {
|
||||
}
|
||||
|
||||
func (l *daoLog) Save(log *LogModel) error {
|
||||
return db.Create(log).Error
|
||||
}
|
||||
|
||||
func (l *daoLog) Query(pageSize, pageNumber int, keywords, sort, order, method, startTime, endTime string) ([]*LogModel, int, error) {
|
||||
//Name string `json:"Name"`
|
||||
//Scheme string `json:"Scheme"`
|
||||
//Method string `json:"Method"`
|
||||
//RequestURI string `json:"RequestURI"`
|
||||
//RemoteAddr string `json:"RemoteAddr"`
|
||||
//RemoteRegion string `json:"RemoteRegion"`
|
||||
//Status string `json:"Status"`
|
||||
//StatusCode int `json:"StatusCode"`
|
||||
//StartAt time.Time `json:"StartAt"`
|
||||
//Duration int `json:"Duration"`
|
||||
//Username string `json:"Username"`
|
||||
//ExtInfo string `json:"ExtInfo"`
|
||||
//Description string `json:"Description"`
|
||||
|
||||
var conditions []clause.Expression
|
||||
|
||||
if method != "" {
|
||||
conditions = append(conditions, clause.Eq{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "method"},
|
||||
Value: method,
|
||||
})
|
||||
}
|
||||
|
||||
// 时间范围查询
|
||||
if startTime != "" && endTime != "" {
|
||||
conditions = append(conditions, gorm.Expr("start_at BETWEEN ? AND ?", startTime, endTime))
|
||||
}
|
||||
|
||||
// 匹配所有字段
|
||||
if keywords != "" {
|
||||
orConditions := clause.OrConditions{}
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "name"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "scheme"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "method"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "request_uri"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "remote_addr"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "remote_region"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "status"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "username"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "ext_info"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "description"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "status_code"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "start_at"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "duration"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
|
||||
orConditions.Exprs = append(orConditions.Exprs, clause.Like{
|
||||
Column: clause.Column{Table: clause.CurrentTable, Name: "created_at"},
|
||||
Value: "%" + keywords + "%",
|
||||
})
|
||||
conditions = append(conditions, orConditions)
|
||||
}
|
||||
|
||||
// 查询总数
|
||||
var total int64
|
||||
if db.Model(&LogModel{}).Select("id").Clauses(conditions...).Count(&total).Error != nil {
|
||||
return nil, 0, fmt.Errorf("查询日志总数失败")
|
||||
} else if total < 1 {
|
||||
return nil, 0, nil
|
||||
}
|
||||
|
||||
// 转小写下划线
|
||||
switch strings.ToLower(sort) {
|
||||
case "startat":
|
||||
sort = "start_at"
|
||||
case "duration":
|
||||
sort = "duration"
|
||||
}
|
||||
|
||||
// 分页查询
|
||||
var logs []*LogModel
|
||||
if db.Model(&LogModel{}).Clauses(conditions...).Offset((pageNumber-1)*pageSize).Limit(pageSize).Order(fmt.Sprintf("%s %s", sort, order)).Find(&logs).Error != nil {
|
||||
return nil, 0, fmt.Errorf("查询日志列表失败")
|
||||
}
|
||||
|
||||
return logs, int(total), nil
|
||||
}
|
||||
|
||||
func (l *daoLog) Clear() error {
|
||||
return DBTransaction(func(tx *gorm.DB) error {
|
||||
return tx.Exec("DELETE FROM lkm_log;").Error
|
||||
})
|
||||
}
|
||||
|
||||
func (l *daoLog) DeleteExpired(expireTime time.Time) error {
|
||||
return DBTransaction(func(tx *gorm.DB) error {
|
||||
tx.Delete(&LogModel{}, "created_at < ?", expireTime.Format("2006-01-02 15:04:05"))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -28,6 +28,7 @@ var (
|
||||
Dialog = &daoDialog{}
|
||||
Position = &daoPosition{}
|
||||
Alarm = &daoAlarm{}
|
||||
Log = &daoLog{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -87,6 +88,8 @@ func init() {
|
||||
panic(err)
|
||||
} else if err = db.AutoMigrate(&AlarmModel{}); err != nil {
|
||||
panic(err)
|
||||
} else if err = db.AutoMigrate(&LogModel{}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
StartSaveTask()
|
||||
|
||||
@@ -238,9 +238,16 @@ func Start() {
|
||||
now := time.Now()
|
||||
alarmExpireTime := now.AddDate(0, 0, -common.Config.AlarmReserveDays)
|
||||
positionExpireTime := now.AddDate(0, 0, -common.Config.PositionReserveDays)
|
||||
logExpireTime := now.AddDate(0, 0, -common.Config.LogReserveDays)
|
||||
|
||||
// 删除过期的操作记录
|
||||
err := dao.Log.DeleteExpired(logExpireTime)
|
||||
if err != nil {
|
||||
log.Sugar.Errorf("删除过期的操作记录失败 err: %s", err.Error())
|
||||
}
|
||||
|
||||
// 删除过期的报警记录
|
||||
err := dao.Alarm.DeleteExpired(alarmExpireTime)
|
||||
err = dao.Alarm.DeleteExpired(alarmExpireTime)
|
||||
if err != nil {
|
||||
log.Sugar.Errorf("删除过期的报警记录失败 err: %s", err.Error())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user