新增审计日志的搜索功能

This commit is contained in:
lanrenwo 2022-07-25 09:23:58 +08:00
parent e761c1e111
commit b8c3d33f2e
5 changed files with 218 additions and 5 deletions

View File

@ -14,15 +14,13 @@ func SetAuditList(w http.ResponseWriter, r *http.Request) {
if page < 1 { if page < 1 {
page = 1 page = 1
} }
var datas []dbdata.AccessAudit var datas []dbdata.AccessAudit
count := dbdata.CountAll(&dbdata.AccessAudit{}) session := dbdata.GetAuditSession(r.FormValue("search"))
err := dbdata.Find(&datas, dbdata.PageSize, page) count, err := dbdata.FindAndCount(session, &datas, dbdata.PageSize, page)
if err != nil && !dbdata.CheckErrNotFound(err) { if err != nil && !dbdata.CheckErrNotFound(err) {
RespError(w, RespInternalErr, err) RespError(w, RespInternalErr, err)
return return
} }
data := map[string]interface{}{ data := map[string]interface{}{
"count": count, "count": count,
"page_size": dbdata.PageSize, "page_size": dbdata.PageSize,

51
server/dbdata/audit.go Normal file
View File

@ -0,0 +1,51 @@
package dbdata
import (
"encoding/json"
"xorm.io/xorm"
)
type SearchCon struct {
Username string `json:"username"`
Src string `json:"src"`
Dst string `json:"dst"`
DstPort string `json:"dst_port"`
AccessProto string `json:"access_proto"`
Date []string `json:"date"`
Info string `json:"info"`
}
func GetAuditSession(search string) *xorm.Session {
session := xdb.Where("1=1")
if search == "" {
return session
}
var searchData SearchCon
err := json.Unmarshal([]byte(search), &searchData)
if err != nil {
return session
}
if searchData.Username != "" {
session.And("username = ?", searchData.Username)
}
if searchData.Src != "" {
session.And("src = ?", searchData.Src)
}
if searchData.Dst != "" {
session.And("dst = ?", searchData.Dst)
}
if searchData.DstPort != "" {
session.And("dst_port = ?", searchData.DstPort)
}
if searchData.AccessProto != "" {
session.And("access_proto = ?", searchData.AccessProto)
}
if len(searchData.Date) > 0 && searchData.Date[0] != "" {
session.And("created_at BETWEEN ? AND ?", searchData.Date[0], searchData.Date[1])
}
if searchData.Info != "" {
session.And("info LIKE ?", "%"+searchData.Info+"%")
}
return session
}

View File

@ -0,0 +1,43 @@
package dbdata
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestSearchAudit(t *testing.T) {
ast := assert.New(t)
preIpData()
defer closeIpdata()
currDateVal := "2022-07-24 00:00:00"
CreatedAt, _ := time.Parse("2006-01-02 15:04:05", currDateVal)
dataTest := AccessAudit{
Username: "Test",
Protocol: 6,
Src: "10.10.1.5",
SrcPort: 0,
Dst: "172.217.160.68",
DstPort: 80,
AccessProto: 4,
Info: "www.google.com",
CreatedAt: CreatedAt,
}
err := Add(dataTest)
ast.Nil(err)
var datas []AccessAudit
searchFormat := `{"username": "%s", "src":"%s", "dst": "%s", "dst_port":"%d","access_proto":"%d","info":"%s","date":["%s","%s"]}`
search := fmt.Sprintf(searchFormat, dataTest.Username, dataTest.Src, dataTest.Dst, dataTest.DstPort, dataTest.AccessProto, dataTest.Info, currDateVal, currDateVal)
session := GetAuditSession(search)
count, _ := FindAndCount(session, &datas, PageSize, 0)
ast.Equal(count, int64(1))
ast.Equal(datas[0].Username, dataTest.Username)
ast.Equal(datas[0].Dst, dataTest.Dst)
}

View File

@ -3,6 +3,8 @@ package dbdata
import ( import (
"errors" "errors"
"reflect" "reflect"
"xorm.io/xorm"
) )
const PageSize = 10 const PageSize = 10
@ -82,3 +84,12 @@ func Prefix(fieldName string, prefix string, data interface{}, limit, page int)
start := (page - 1) * limit start := (page - 1) * limit
return where.Limit(limit, start).Find(data) return where.Limit(limit, start).Find(data)
} }
func FindAndCount(session *xorm.Session, data interface{}, limit, page int) (int64, error) {
if limit == 0 {
return session.FindAndCount(data)
}
start := (page - 1) * limit
totalCount, err := session.Limit(limit, start).FindAndCount(data)
return totalCount, err
}

View File

@ -1,6 +1,56 @@
<template> <template>
<div> <div>
<el-card> <el-card>
<el-form :model="searchForm" :rules="rules" ref="searchForm" :inline="true" class="form-inner-error">
<el-form-item label="用户名:" prop="username">
<el-input size="small" v-model="searchForm.username" style="width: 130px" @keydown.enter.native="searchEnterFun"></el-input>
</el-form-item>
<el-form-item label="源IP地址:" prop="src">
<el-input size="small" v-model="searchForm.src" style="width: 130px" @keydown.enter.native="searchEnterFun"></el-input>
</el-form-item>
<el-form-item label="目的IP地址:" prop="dst">
<el-input size="small" v-model="searchForm.dst" style="width: 130px" @keydown.enter.native="searchEnterFun"></el-input>
</el-form-item>
<el-form-item label="目的端口:" prop="dst_port">
<el-input size="small" v-model="searchForm.dst_port" style="width: 80px" @keydown.enter.native="searchEnterFun"></el-input>
</el-form-item>
<el-form-item label="访问协议:">
<el-select size="small" v-model="searchForm.access_proto" style="width: 100px">
<el-option v-for="(item,index) in access_proto" :key="index" :label="item.text" :value="item.value">
</el-option>
</el-select>
</el-form-item>
<div>
<el-form-item label="日期范围:">
<el-date-picker
v-model="searchForm.date"
type="datetimerange"
size="small"
value-format="yyyy-MM-dd HH:mm:ss"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期">
>
</el-date-picker>
</el-form-item>
<el-form-item label="详情:">
<el-input size="small" v-model="searchForm.info" placeholder="请输入关键字" style="width: 200px" @keydown.enter.native="searchEnterFun"></el-input>
</el-form-item>
<el-form-item>
<el-button
size="small"
type="primary"
icon="el-icon-search"
@click="handleSearch">搜索
</el-button>
<el-button
size="small"
icon="el-icon-refresh"
@click="rest">重置搜索
</el-button>
</el-form-item>
</div>
</el-form>
<el-table <el-table
ref="multipleTable" ref="multipleTable"
@ -102,8 +152,9 @@ export default {
this.$emit('update:route_path', this.$route.path) this.$emit('update:route_path', this.$route.path)
this.$emit('update:route_name', ['基础信息', '审计日志']) this.$emit('update:route_name', ['基础信息', '审计日志'])
}, },
mounted() { mounted() {
this.getData(1) this.getData(1)
this.setSearchData()
}, },
data() { data() {
return { return {
@ -111,13 +162,55 @@ export default {
count: 10, count: 10,
nowIndex: 0, nowIndex: 0,
accessProtoArr:["", "UDP", "TCP", "HTTPS", "HTTP"], accessProtoArr:["", "UDP", "TCP", "HTTPS", "HTTP"],
defSearchForm: {username:'', src:'', dst:'', dst_port:'', access_proto:'', info:'', date:["",""]},
searchForm: {},
access_proto: [
{ text: '请选择', value: '' },
{ text: 'UDP', value: '1' },
{ text: 'TCP', value: '2' },
{ text: 'HTTPS', value: '3' },
{ text: 'HTTP', value: '4' },
],
rules: {
username: [
{max: 30, message: '长度小于 30 个字符', trigger: 'blur'}
],
src: [
{ message: '请输入正确的IP地址', validator: this.validateIP, trigger: 'blur' },
],
dst: [
{ message: '请输入正确的IP地址', validator: this.validateIP, trigger: 'blur' },
],
},
} }
}, },
methods: { methods: {
setSearchData() {
this.searchForm = JSON.parse(JSON.stringify(this.defSearchForm));
},
handleSearch() {
this.$refs["searchForm"].validate((valid) => {
if (!valid) {
console.log('error submit!!');
return false;
}
this.getData(1)
})
},
searchEnterFun(e) {
var keyCode = window.event ? e.keyCode : e.which;
if (keyCode == 13) {
this.handleSearch()
}
},
getData(p) { getData(p) {
if (! this.searchForm.date) {
this.searchForm.date = ["", ""];
}
axios.get('/set/audit/list', { axios.get('/set/audit/list', {
params: { params: {
page: p, page: p,
search: this.searchForm,
} }
}).then(resp => { }).then(resp => {
var data = resp.data.data var data = resp.data.data
@ -158,6 +251,23 @@ export default {
} }
return this.accessProtoArr[access_proto] return this.accessProtoArr[access_proto]
}, },
rest() {
console.log("rest");
this.setSearchData();
this.handleSearch();
},
validateIP(rule, value, callback) {
if (value === '' || typeof value === 'undefined' || value == null) {
callback()
} else {
const reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
if ((!reg.test(value)) && value !== '') {
callback(new Error('请输入正确的IP地址'))
} else {
callback()
}
}
},
}, },
} }
</script> </script>