mirror of
https://gitee.com/samwaf/SamWaf.git
synced 2025-12-06 06:58:54 +08:00
增加系统日志
This commit is contained in:
@@ -17,6 +17,7 @@ type APIGroup struct {
|
||||
WafAccountApi
|
||||
WafAccountLogApi
|
||||
WafLoginApi
|
||||
WafSysLogApi
|
||||
}
|
||||
|
||||
var APIGroupAPP = new(APIGroup)
|
||||
@@ -36,4 +37,6 @@ var (
|
||||
wafAccountService = waf_service.WafAccountServiceApp
|
||||
wafAccountLogService = waf_service.WafAccountLogServiceApp
|
||||
wafTokenInfoService = waf_service.WafTokenInfoServiceApp
|
||||
|
||||
wafSysLogService = waf_service.WafSysLogServiceApp
|
||||
)
|
||||
|
||||
36
api/waf_sys_log.go
Normal file
36
api/waf_sys_log.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"SamWaf/model/common/response"
|
||||
"SamWaf/model/request"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type WafSysLogApi struct {
|
||||
}
|
||||
|
||||
func (w *WafSysLogApi) GetDetailApi(c *gin.Context) {
|
||||
var req request.WafSysLogDetailReq
|
||||
err := c.ShouldBind(&req)
|
||||
if err == nil {
|
||||
bean := wafSysLogService.GetDetailApi(req)
|
||||
response.OkWithDetailed(bean, "获取成功", c)
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
func (w *WafSysLogApi) GetListApi(c *gin.Context) {
|
||||
var req request.WafSysLogSearchReq
|
||||
err := c.ShouldBind(&req)
|
||||
if err == nil {
|
||||
beans, total, _ := wafSysLogService.GetListApi(req)
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: beans,
|
||||
Total: total,
|
||||
PageIndex: req.PageIndex,
|
||||
PageSize: req.PageSize,
|
||||
}, "获取成功", c)
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
10
localwaf/src/apis/syslog.ts
Normal file
10
localwaf/src/apis/syslog.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
//查询所有系统操作日志列表
|
||||
export function sys_log_list_api(params) {
|
||||
return request({
|
||||
url: 'sys_log/list',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
<t-button variant="base" theme="default" :disabled="!selectedRowKeys.length"> 导出日志 </t-button>
|
||||
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
|
||||
</div>
|
||||
<t-input v-model="searchValue" class="search-input" placeholder="请输入你需要搜索的攻击日志" clearable>
|
||||
<t-input v-model="searchValue" class="search-input" placeholder="请输入你需要搜索的日志" clearable>
|
||||
<template #suffix-icon>
|
||||
<search-icon size="20px" />
|
||||
</template>
|
||||
|
||||
106
localwaf/src/pages/waf/syslog/detail/index.less
Normal file
106
localwaf/src/pages/waf/syslog/detail/index.less
Normal file
@@ -0,0 +1,106 @@
|
||||
@import '@/style/variables.less';
|
||||
|
||||
.detail-base {
|
||||
/deep/ .t-card {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
/deep/ .t-card__title {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&-info-steps {
|
||||
padding-top: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.info-block {
|
||||
column-count: 2;
|
||||
|
||||
.info-item {
|
||||
padding: 12px 0;
|
||||
display: flex;
|
||||
color: var(--td-text-color-primary);
|
||||
|
||||
h1 {
|
||||
width: 200px;
|
||||
font-weight: normal;
|
||||
font-size: @font-size-base;
|
||||
color: var(--td-text-color-secondary);
|
||||
text-align: left;
|
||||
line-height: 22px;
|
||||
|
||||
@media (max-width: @screen-sm-max) {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
i {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: @border-radius-50;
|
||||
background: var(--td-success-color-5);
|
||||
}
|
||||
|
||||
.inProgress {
|
||||
color: var(--td-success-color-5);
|
||||
}
|
||||
|
||||
.pdf {
|
||||
color: var(--td-brand-color);
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-info-block {
|
||||
.info-item {
|
||||
padding: 12px 0;
|
||||
display: flex;
|
||||
|
||||
h1 {
|
||||
width: 84px;
|
||||
font-family: PingFangSC-Regular;
|
||||
font-size: 14px;
|
||||
color: var(--td-text-color-secondary);
|
||||
text-align: left;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
span {
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
i {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: @border-radius-50;
|
||||
background: var(--td-success-color-5);
|
||||
}
|
||||
|
||||
.green {
|
||||
color: var(--td-success-color-5);
|
||||
}
|
||||
|
||||
.blue {
|
||||
color: var(--td-brand-color-8);
|
||||
}
|
||||
}
|
||||
}
|
||||
148
localwaf/src/pages/waf/syslog/detail/index.vue
Normal file
148
localwaf/src/pages/waf/syslog/detail/index.vue
Normal file
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
|
||||
<div class="detail-base">
|
||||
<t-card title="网站详情">
|
||||
<div class="info-block">
|
||||
|
||||
<div class="info-item">
|
||||
<h1> 创建时间</h1>
|
||||
<span>
|
||||
{{ detail_data.create_time }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<h1> 网站</h1>
|
||||
<span>
|
||||
{{ detail_data.host }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<h1> 网站端口</h1>
|
||||
<span>
|
||||
{{ detail_data.port }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<h1> 加密证书</h1>
|
||||
<span>
|
||||
{{ detail_data.ssl }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<h1> 后端系统类型</h1>
|
||||
<span>
|
||||
{{ detail_data.remote_system }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<h1> 后端系统应用类型</h1>
|
||||
<span>
|
||||
{{ detail_data.remote_app }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<h1> 后端域名</h1>
|
||||
<span>
|
||||
{{ detail_data.remote_host }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<h1> 后端端口</h1>
|
||||
<span>
|
||||
{{ detail_data.remote_port }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</t-card>
|
||||
<t-card title="最近配置记录" class="container-base-margin-top">
|
||||
|
||||
<t-list :split="true">
|
||||
<t-list-item>
|
||||
<t-list-item-meta title="请求头" :description="detail_data.header"></t-list-item-meta>
|
||||
</t-list-item>
|
||||
<t-list-item>
|
||||
<t-list-item-meta title="请求用户浏览器" :description="detail_data.user_agent"></t-list-item-meta>
|
||||
</t-list-item>
|
||||
<t-list-item>
|
||||
<t-list-item-meta title="请求cookies" :description="detail_data.cookies"></t-list-item-meta>
|
||||
</t-list-item>
|
||||
<t-list-item>
|
||||
<t-list-item-meta title="请求BODY" :description="detail_data.body"></t-list-item-meta>
|
||||
</t-list-item>
|
||||
</t-list>
|
||||
</t-card>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import {
|
||||
prefix
|
||||
} from '@/config/global';
|
||||
import model from '@/service/service-detail-base';
|
||||
|
||||
export default {
|
||||
name: 'WafHostDetail',
|
||||
data() {
|
||||
return {
|
||||
prefix,
|
||||
baseInfoData: model.getBaseInfoData(),
|
||||
detail_data: {}
|
||||
};
|
||||
},
|
||||
beforeRouteUpdate(to, from) {
|
||||
console.log('beforeRouteUpdate')
|
||||
},
|
||||
mounted() {
|
||||
console.log('----mounted----')
|
||||
this.getDetail(this.$route.query.code);
|
||||
},
|
||||
beforeCreate() {
|
||||
console.log('----beforeCreate----')
|
||||
},
|
||||
created() {
|
||||
console.log('----created----')
|
||||
},
|
||||
beforeMount() {
|
||||
console.log('----beforeMount----')
|
||||
},
|
||||
beforeUpdate() {
|
||||
console.log('----beforeUpdate----')
|
||||
},
|
||||
updated() {
|
||||
console.log('----updated----')
|
||||
},
|
||||
watch: {
|
||||
'$route.query.code'(newVal, oldVal) {
|
||||
console.log('route.query.code changed', newVal, oldVal)
|
||||
this.getDetail(newVal)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getDetail(id) {
|
||||
let that = this
|
||||
this.$request
|
||||
.get('/wafhost/host/detail', {
|
||||
params: {
|
||||
CODE: id,
|
||||
}
|
||||
})
|
||||
.then((res) => {
|
||||
let resdata = res
|
||||
console.log(resdata)
|
||||
if (resdata.code === 0) {
|
||||
that.detail_data = resdata.data;
|
||||
|
||||
}
|
||||
})
|
||||
.catch((e: Error) => {
|
||||
console.log(e);
|
||||
})
|
||||
.finally(() => {});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import './index';
|
||||
</style>
|
||||
333
localwaf/src/pages/waf/syslog/index.vue
Normal file
333
localwaf/src/pages/waf/syslog/index.vue
Normal file
@@ -0,0 +1,333 @@
|
||||
<template>
|
||||
<div>
|
||||
<t-card class="list-card-container">
|
||||
<t-row justify="space-between">
|
||||
<div class="left-operation-container">
|
||||
<t-button variant="base" theme="default" :disabled="!selectedRowKeys.length"> 导出日志 </t-button>
|
||||
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
|
||||
</div>
|
||||
<t-input v-model="searchValue" class="search-input" placeholder="请输入你需要搜索的日志" clearable>
|
||||
<template #suffix-icon>
|
||||
<search-icon size="20px" />
|
||||
</template>
|
||||
</t-input>
|
||||
</t-row>
|
||||
|
||||
<div class="table-container">
|
||||
<t-table :columns="columns" :data="data" :rowKey="rowKey" :verticalAlign="verticalAlign" :hover="hover"
|
||||
:pagination="pagination" :selected-row-keys="selectedRowKeys" :loading="dataLoading"
|
||||
@page-change="rehandlePageChange" @change="rehandleChange" @select-change="rehandleSelectChange"
|
||||
:headerAffixedTop="true" :headerAffixProps="{ offsetTop: offsetTop, container: getContainer }">
|
||||
|
||||
|
||||
|
||||
<template #op="slotProps">
|
||||
<!-- <a class="t-button-link" @click="handleClickDetail(slotProps)">详情</a>-->
|
||||
<a class="t-button-link" @click="handleClickEdit(slotProps)">详情</a>
|
||||
</template>
|
||||
</t-table>
|
||||
</div>
|
||||
<div>
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</t-card>
|
||||
|
||||
<!-- 编辑Url白名单弹窗 -->
|
||||
<t-dialog header="查看日志" :visible.sync="editFormVisible" :width="680" :footer="false">
|
||||
<div slot="body">
|
||||
<!-- 表单内容 -->
|
||||
<t-form :data="formEditData" ref="form" :rules="rules" :labelWidth="100">
|
||||
<t-form-item label="操作账号" name="login_account">
|
||||
<t-input :style="{ width: '480px' }" v-model="formEditData.login_account" placeholder="操作账号"></t-input>
|
||||
</t-form-item>
|
||||
<t-form-item label="操作类型" name="op_type">
|
||||
<t-input :style="{ width: '480px' }" v-model="formEditData.op_type" placeholder="请输入操作类型"></t-input>
|
||||
</t-form-item>
|
||||
|
||||
<t-form-item label="操作备注" name="op_content">
|
||||
<t-textarea :style="{ width: '480px' }" v-model="formEditData.op_content" placeholder="请输入备注" name="op_content">
|
||||
</t-textarea>
|
||||
</t-form-item>
|
||||
<t-form-item style="float: right">
|
||||
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
</div>
|
||||
</t-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import {
|
||||
SearchIcon
|
||||
} from 'tdesign-icons-vue';
|
||||
import Trend from '@/components/trend/index.vue';
|
||||
import {
|
||||
prefix
|
||||
} from '@/config/global';
|
||||
import {
|
||||
sys_log_list_api
|
||||
} from '@/apis/syslog';
|
||||
|
||||
|
||||
import {
|
||||
SSL_STATUS,
|
||||
GUARD_STATUS,
|
||||
CONTRACT_STATUS,
|
||||
CONTRACT_STATUS_OPTIONS,
|
||||
CONTRACT_TYPES,
|
||||
CONTRACT_PAYMENT_TYPES
|
||||
} from '@/constants';
|
||||
|
||||
const INITIAL_DATA = {
|
||||
login_account: '',
|
||||
op_type: '',
|
||||
op_content: '',
|
||||
};
|
||||
export default Vue.extend({
|
||||
name: 'ListBase',
|
||||
components: {
|
||||
SearchIcon,
|
||||
Trend,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
addFormVisible: false,
|
||||
editFormVisible: false,
|
||||
guardVisible: false,
|
||||
confirmVisible: false,
|
||||
formData: {
|
||||
...INITIAL_DATA
|
||||
},
|
||||
formEditData: {
|
||||
...INITIAL_DATA
|
||||
},
|
||||
rules: {
|
||||
},
|
||||
textareaValue: '',
|
||||
prefix,
|
||||
dataLoading: false,
|
||||
data: [], //列表数据信息
|
||||
detail_data: [], //加载详情信息用于编辑
|
||||
selectedRowKeys: [],
|
||||
value: 'first',
|
||||
columns: [{
|
||||
colKey: 'row-select',
|
||||
type: 'multiple',
|
||||
width: 64,
|
||||
fixed: 'left'
|
||||
},
|
||||
{
|
||||
title: '操作类型',
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
colKey: 'op_type',
|
||||
},
|
||||
{
|
||||
title: '操作内容',
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
colKey: 'op_content',
|
||||
},
|
||||
{
|
||||
title: '添加时间',
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
colKey: 'create_time',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
fixed: 'right',
|
||||
width: 200,
|
||||
colKey: 'op',
|
||||
title: '操作',
|
||||
},
|
||||
],
|
||||
rowKey: 'code',
|
||||
tableLayout: 'auto',
|
||||
verticalAlign: 'top',
|
||||
hover: true,
|
||||
rowClassName: (rowKey: string) => `${rowKey}-class`,
|
||||
// 与pagination对齐
|
||||
pagination: {
|
||||
total: 0,
|
||||
current: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
searchValue: '',
|
||||
//索引区域
|
||||
deleteIdx: -1,
|
||||
guardStatusIdx :-1,
|
||||
//主机列表
|
||||
host_options:[]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
confirmBody() {
|
||||
if (this.deleteIdx > -1) {
|
||||
const {
|
||||
url
|
||||
} = this.data?. [this.deleteIdx];
|
||||
return `删除后,${url}的数据将被删除,且无法恢复`;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
offsetTop() {
|
||||
return this.$store.state.setting.isUseTabsRouter ? 48 : 0;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getList("")
|
||||
this.loadHostList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
loadHostList(){
|
||||
},
|
||||
getList(keyword) {
|
||||
let that = this
|
||||
this.$request
|
||||
.get('/sys_log/list', {
|
||||
params: {
|
||||
pageSize: that.pagination.pageSize,
|
||||
pageIndex: that.pagination.current,
|
||||
op_type: '',
|
||||
op_content: '',
|
||||
}
|
||||
})
|
||||
.then((res) => {
|
||||
let resdata = res
|
||||
console.log(resdata)
|
||||
if (resdata.code === 0) {
|
||||
|
||||
this.data = resdata.data.list;
|
||||
this.data_attach = []
|
||||
console.log('getList',this.data)
|
||||
this.pagination = {
|
||||
...this.pagination,
|
||||
total: resdata.data.total,
|
||||
};
|
||||
}
|
||||
})
|
||||
.catch((e: Error) => {
|
||||
console.log(e);
|
||||
})
|
||||
.finally(() => {
|
||||
this.dataLoading = false;
|
||||
});
|
||||
this.dataLoading = true;
|
||||
},
|
||||
getContainer() {
|
||||
return document.querySelector('.tdesign-starter-layout');
|
||||
},
|
||||
rehandlePageChange(curr, pageInfo) {
|
||||
console.log('分页变化', curr, pageInfo);
|
||||
this.pagination.current = curr.current
|
||||
if (this.pagination.pageSize != curr.pageSize) {
|
||||
this.pagination.current = 1
|
||||
this.pagination.pageSize = curr.pageSize
|
||||
}
|
||||
this.getList("")
|
||||
},
|
||||
rehandleSelectChange(selectedRowKeys: number[]) {
|
||||
this.selectedRowKeys = selectedRowKeys;
|
||||
},
|
||||
rehandleChange(changeParams, triggerAndData) {
|
||||
console.log('统一Change', changeParams, triggerAndData);
|
||||
},
|
||||
handleClickDetail(e) {
|
||||
console.log(e)
|
||||
const {
|
||||
id
|
||||
} = e.row
|
||||
console.log('hostlist',id)
|
||||
this.$router.push({
|
||||
path: '/waf-host/anticc/detail',
|
||||
query: {
|
||||
id: id,
|
||||
},
|
||||
}, );
|
||||
},
|
||||
handleClickEdit(e) {
|
||||
console.log(e)
|
||||
const {
|
||||
id
|
||||
} = e.row
|
||||
console.log(id)
|
||||
this.editFormVisible = true
|
||||
this.getDetail(id)
|
||||
},
|
||||
onClickCloseBtn(): void {
|
||||
this.formVisible = false;
|
||||
this.formData = {};
|
||||
},
|
||||
onClickCloseEditBtn(): void {
|
||||
this.editFormVisible = false;
|
||||
this.formEditData = {};
|
||||
},
|
||||
onCancel() {
|
||||
this.resetIdx();
|
||||
},
|
||||
resetIdx() {
|
||||
this.deleteIdx = -1;
|
||||
},
|
||||
getDetail(id) {
|
||||
let that = this
|
||||
this.$request
|
||||
.get('/sys_log/detail', {
|
||||
params: {
|
||||
id: id,
|
||||
}
|
||||
})
|
||||
.then((res) => {
|
||||
let resdata = res
|
||||
console.log(resdata)
|
||||
if (resdata.code === 0) {
|
||||
that.detail_data = resdata.data;
|
||||
that.formEditData = {
|
||||
...that.detail_data
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((e: Error) => {
|
||||
console.log(e);
|
||||
})
|
||||
.finally(() => {});
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '@/style/variables';
|
||||
|
||||
.payment-col {
|
||||
display: flex;
|
||||
|
||||
.trend-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.left-operation-container {
|
||||
padding: 0 0 6px 0;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.selected-count {
|
||||
display: inline-block;
|
||||
margin-left: 8px;
|
||||
color: var(--td-text-color-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 360px;
|
||||
}
|
||||
|
||||
.t-button+.t-button {
|
||||
margin-left: @spacer;
|
||||
}
|
||||
</style>
|
||||
@@ -48,6 +48,25 @@ export default [
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
path: '/sys',
|
||||
name: 'sys',
|
||||
component: Layout,
|
||||
redirect: '/sys',
|
||||
meta: { title: '系统设置', icon: ViewModuleIcon },
|
||||
children: [
|
||||
{
|
||||
path: 'SysLog',
|
||||
name: 'SysLog',
|
||||
component: () => import('@/pages/waf/syslog/index.vue'),
|
||||
meta: { title: '系统操作日志' },
|
||||
},
|
||||
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
path: '/waf-host',
|
||||
name: 'wafhost',
|
||||
|
||||
5
model/request/waf_sys_log_detail_req.go
Normal file
5
model/request/waf_sys_log_detail_req.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package request
|
||||
|
||||
type WafSysLogDetailReq struct {
|
||||
Id string `json:"id" form:"id"` //唯一键
|
||||
}
|
||||
9
model/request/waf_sys_log_search.go
Normal file
9
model/request/waf_sys_log_search.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package request
|
||||
|
||||
import "SamWaf/model/common/request"
|
||||
|
||||
type WafSysLogSearchReq struct {
|
||||
OpType string `json:"op_type" form:"op_type"` //操作类型
|
||||
OpContent string `json:"op_content" form:"op_content"` //操作内容
|
||||
request.PageInfo
|
||||
}
|
||||
12
model/waf_sys.go
Normal file
12
model/waf_sys.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type WafSysLog struct {
|
||||
Id string `gorm:"primary_key" json:"id"`
|
||||
UserCode string `json:"user_code"` //用户码(主要键)
|
||||
TenantId string `json:"tenant_id"` //租户ID(主要键)
|
||||
OpType string `json:"op_type"` //操作类型
|
||||
OpContent string `json:"op_content"` //操作内容
|
||||
CreateTime time.Time `json:"create_time"` //创建时间
|
||||
}
|
||||
@@ -15,6 +15,7 @@ type ApiGroup struct {
|
||||
AccountRouter
|
||||
AccountLogRouter
|
||||
LoginOutRouter
|
||||
SysLogRouter
|
||||
}
|
||||
type PublicApiGroup struct {
|
||||
LoginRouter
|
||||
|
||||
16
router/waf_sys_log.go
Normal file
16
router/waf_sys_log.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"SamWaf/api"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type SysLogRouter struct {
|
||||
}
|
||||
|
||||
func (receiver *SysLogRouter) InitSysLogRouter(group *gin.RouterGroup) {
|
||||
api := api.APIGroupAPP.WafSysLogApi
|
||||
router := group.Group("")
|
||||
router.GET("/samwaf/sys_log/list", api.GetListApi)
|
||||
router.GET("/samwaf/sys_log/detail", api.GetDetailApi)
|
||||
}
|
||||
24
service/waf_service/waf_sys_log.go
Normal file
24
service/waf_service/waf_sys_log.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package waf_service
|
||||
|
||||
import (
|
||||
"SamWaf/global"
|
||||
"SamWaf/model"
|
||||
"SamWaf/model/request"
|
||||
)
|
||||
|
||||
type WafSysLogService struct{}
|
||||
|
||||
var WafSysLogServiceApp = new(WafSysLogService)
|
||||
|
||||
func (receiver *WafSysLogService) GetDetailApi(req request.WafSysLogDetailReq) model.WafSysLog {
|
||||
var bean model.WafSysLog
|
||||
global.GWAF_LOCAL_LOG_DB.Debug().Where("id=?", req.Id).Find(&bean)
|
||||
return bean
|
||||
}
|
||||
func (receiver *WafSysLogService) GetListApi(req request.WafSysLogSearchReq) ([]model.WafSysLog, int64, error) {
|
||||
var bean []model.WafSysLog
|
||||
var total int64 = 0
|
||||
global.GWAF_LOCAL_LOG_DB.Debug().Limit(req.PageSize).Offset(req.PageSize * (req.PageIndex - 1)).Find(&bean)
|
||||
global.GWAF_LOCAL_LOG_DB.Debug().Model(&model.WafSysLog{}).Count(&total)
|
||||
return bean, total, nil
|
||||
}
|
||||
@@ -57,6 +57,7 @@ func InitDb() {
|
||||
logDB.AutoMigrate(&model.StatsIPCityDay{})
|
||||
logDB.AutoMigrate(&innerbean.WebLog{})
|
||||
logDB.AutoMigrate(&model.AccountLog{})
|
||||
logDB.AutoMigrate(&model.WafSysLog{})
|
||||
global.GWAF_LOCAL_LOG_DB.Callback().Query().Before("gorm:query").Register("tenant_plugin:before_query", before_query)
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ func InitRouter(r *gin.Engine) {
|
||||
router.ApiGroupApp.InitAccountRouter(RouterGroup)
|
||||
router.ApiGroupApp.InitAccountLogRouter(RouterGroup)
|
||||
router.ApiGroupApp.InitLoginOutRouter(RouterGroup)
|
||||
router.ApiGroupApp.InitSysLogRouter(RouterGroup)
|
||||
}
|
||||
PublicRouterGroup := r.Group("")
|
||||
router.PublicApiGroupApp.InitLoginRouter(PublicRouterGroup)
|
||||
|
||||
@@ -519,6 +519,17 @@ func (waf *WafEngine) Start_WAF() {
|
||||
waf.HostCode[hosts[i].Code] = hosts[i].Host + ":" + strconv.Itoa(hosts[i].Port)
|
||||
|
||||
}
|
||||
|
||||
wafSysLog := &model.WafSysLog{
|
||||
Id: uuid.NewV4().String(),
|
||||
UserCode: global.GWAF_USER_CODE,
|
||||
TenantId: global.GWAF_TENANT_ID,
|
||||
OpType: "信息",
|
||||
OpContent: "WAF启动",
|
||||
CreateTime: time.Now(),
|
||||
}
|
||||
global.GWAF_LOCAL_LOG_DB.Create(wafSysLog)
|
||||
|
||||
for _, v := range waf.ServerOnline {
|
||||
go func(innruntime innerbean.ServerRunTime) {
|
||||
|
||||
@@ -547,6 +558,16 @@ func (waf *WafEngine) Start_WAF() {
|
||||
if err == http.ErrServerClosed {
|
||||
zlog.Info("[HTTPServer] https server has been close, cause:[%v]", err)
|
||||
} else {
|
||||
//TODO 记录如果https 端口被占用的情况 记录日志 且应该推送websocket
|
||||
wafSysLog := model.WafSysLog{
|
||||
Id: uuid.NewV4().String(),
|
||||
UserCode: global.GWAF_USER_CODE,
|
||||
TenantId: global.GWAF_TENANT_ID,
|
||||
OpType: "系统运行错误",
|
||||
OpContent: "HTTPS端口被占用: " + strconv.Itoa(innruntime.Port) + ",请检查",
|
||||
CreateTime: time.Time{},
|
||||
}
|
||||
global.GWAF_LOCAL_LOG_DB.Create(wafSysLog)
|
||||
zlog.Error("[HTTPServer] https server start fail, cause:[%v]", err)
|
||||
}
|
||||
zlog.Info("server https shutdown")
|
||||
@@ -571,6 +592,16 @@ func (waf *WafEngine) Start_WAF() {
|
||||
if err == http.ErrServerClosed {
|
||||
zlog.Warn("[HTTPServer] http server has been close, cause:[%v]", err)
|
||||
} else {
|
||||
//TODO 记录如果http 端口被占用的情况 记录日志 且应该推送websocket
|
||||
wafSysLog := model.WafSysLog{
|
||||
Id: uuid.NewV4().String(),
|
||||
UserCode: global.GWAF_USER_CODE,
|
||||
TenantId: global.GWAF_TENANT_ID,
|
||||
OpType: "系统运行错误",
|
||||
OpContent: "HTTP端口被占用: " + strconv.Itoa(innruntime.Port) + ",请检查",
|
||||
CreateTime: time.Time{},
|
||||
}
|
||||
global.GWAF_LOCAL_LOG_DB.Create(wafSysLog)
|
||||
zlog.Error("[HTTPServer] http server start fail, cause:[%v]", err)
|
||||
}
|
||||
zlog.Info("server http shutdown")
|
||||
@@ -589,6 +620,15 @@ func (waf *WafEngine) CLoseWAF() {
|
||||
zlog.Debug("关闭 recover ", e)
|
||||
}
|
||||
}()
|
||||
wafSysLog := &model.WafSysLog{
|
||||
Id: uuid.NewV4().String(),
|
||||
UserCode: global.GWAF_USER_CODE,
|
||||
TenantId: global.GWAF_TENANT_ID,
|
||||
OpType: "信息",
|
||||
OpContent: "WAF关闭",
|
||||
CreateTime: time.Now(),
|
||||
}
|
||||
global.GWAF_LOCAL_LOG_DB.Create(wafSysLog)
|
||||
waf.EngineCurrentStatus = 0
|
||||
for _, v := range waf.ServerOnline {
|
||||
if v.Svr != nil {
|
||||
|
||||
Reference in New Issue
Block a user