mirror of
https://gitee.com/samwaf/SamWaf.git
synced 2025-12-06 06:58:54 +08:00
增加账号管理和日志的基本内容
This commit is contained in:
@@ -14,6 +14,8 @@ type APIGroup struct {
|
||||
WafAntiCCApi
|
||||
WafBlockIpApi
|
||||
WafBlockUrlApi
|
||||
WafAccountApi
|
||||
WafAccountLogApi
|
||||
}
|
||||
|
||||
var APIGroupAPP = new(APIGroup)
|
||||
@@ -29,4 +31,7 @@ var (
|
||||
|
||||
wafIpBlockService = waf_service.WafBlockIpServiceApp
|
||||
wafUrlBlockService = waf_service.WafBlockUrlServiceApp
|
||||
|
||||
wafAccountService = waf_service.WafAccountServiceApp
|
||||
wafAccountLogService = waf_service.WafAccountLogServiceApp
|
||||
)
|
||||
|
||||
94
api/waf_account.go
Normal file
94
api/waf_account.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"SamWaf/model/common/response"
|
||||
"SamWaf/model/request"
|
||||
"errors"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type WafAccountApi struct {
|
||||
}
|
||||
|
||||
func (w *WafAccountApi) AddApi(c *gin.Context) {
|
||||
var req request.WafAccountAddReq
|
||||
err := c.ShouldBind(&req)
|
||||
if err == nil {
|
||||
err = wafAccountService.CheckIsExistApi(req)
|
||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
err = wafAccountService.AddApi(req)
|
||||
if err == nil {
|
||||
response.OkWithMessage("添加成功", c)
|
||||
} else {
|
||||
|
||||
response.FailWithMessage("添加失败", c)
|
||||
}
|
||||
return
|
||||
} else {
|
||||
response.FailWithMessage("当前数据已经存在", c)
|
||||
return
|
||||
}
|
||||
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
func (w *WafAccountApi) GetDetailApi(c *gin.Context) {
|
||||
var req request.WafAccountDetailReq
|
||||
err := c.ShouldBind(&req)
|
||||
if err == nil {
|
||||
bean := wafAccountService.GetDetailApi(req)
|
||||
response.OkWithDetailed(bean, "获取成功", c)
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
func (w *WafAccountApi) GetListApi(c *gin.Context) {
|
||||
var req request.WafAccountSearchReq
|
||||
err := c.ShouldBind(&req)
|
||||
if err == nil {
|
||||
beans, total, _ := wafAccountService.GetListApi(req)
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: beans,
|
||||
Total: total,
|
||||
PageIndex: req.PageIndex,
|
||||
PageSize: req.PageSize,
|
||||
}, "获取成功", c)
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
func (w *WafAccountApi) DelAccountApi(c *gin.Context) {
|
||||
var req request.WafAccountDelReq
|
||||
err := c.ShouldBind(&req)
|
||||
if err == nil {
|
||||
err = wafAccountService.DelApi(req)
|
||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
response.FailWithMessage("请检测参数", c)
|
||||
} else if err != nil {
|
||||
response.FailWithMessage("发生错误", c)
|
||||
} else {
|
||||
response.FailWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WafAccountApi) ModifyAccountApi(c *gin.Context) {
|
||||
var req request.WafAccountEditReq
|
||||
err := c.ShouldBind(&req)
|
||||
if err == nil {
|
||||
err = wafAccountService.ModifyApi(req)
|
||||
if err != nil {
|
||||
response.FailWithMessage("编辑发生错误", c)
|
||||
} else {
|
||||
response.OkWithMessage("编辑成功", c)
|
||||
}
|
||||
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
36
api/waf_account_log.go
Normal file
36
api/waf_account_log.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"SamWaf/model/common/response"
|
||||
"SamWaf/model/request"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type WafAccountLogApi struct {
|
||||
}
|
||||
|
||||
func (w *WafAccountLogApi) GetDetailApi(c *gin.Context) {
|
||||
var req request.WafAccountLogDetailReq
|
||||
err := c.ShouldBind(&req)
|
||||
if err == nil {
|
||||
bean := wafAccountLogService.GetDetailApi(req)
|
||||
response.OkWithDetailed(bean, "获取成功", c)
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
func (w *WafAccountLogApi) GetListApi(c *gin.Context) {
|
||||
var req request.WafAccountLogSearchReq
|
||||
err := c.ShouldBind(&req)
|
||||
if err == nil {
|
||||
beans, total, _ := wafAccountLogService.GetListApi(req)
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: beans,
|
||||
Total: total,
|
||||
PageIndex: req.PageIndex,
|
||||
PageSize: req.PageSize,
|
||||
}, "获取成功", c)
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,9 @@ func InitDb() {
|
||||
//抵抗CC
|
||||
db.AutoMigrate(&model.AntiCC{})
|
||||
|
||||
//waf自生账号
|
||||
db.AutoMigrate(&model.Account{})
|
||||
db.AutoMigrate(&model.AccountLog{})
|
||||
global.GWAF_LOCAL_DB.Callback().Query().Before("gorm:query").Register("tenant_plugin:before_query", before_query)
|
||||
|
||||
//重启需要删除无效规则
|
||||
|
||||
@@ -25,7 +25,8 @@ func InitRouter(r *gin.Engine) {
|
||||
router.ApiGroupApp.InitAntiCCRouter(RouterGroup)
|
||||
router.ApiGroupApp.InitBlockIpRouter(RouterGroup)
|
||||
router.ApiGroupApp.InitBlockUrlRouter(RouterGroup)
|
||||
|
||||
router.ApiGroupApp.InitAccountRouter(RouterGroup)
|
||||
router.ApiGroupApp.InitAccountLogRouter(RouterGroup)
|
||||
}
|
||||
func Cors() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
19
localwaf/src/apis/account.ts
Normal file
19
localwaf/src/apis/account.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import request from '@/utils/request'
|
||||
//查询所有账号列表
|
||||
export function account_list_api(params) {
|
||||
return request({
|
||||
url: 'account/list',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//查询所有账号操作日志列表
|
||||
export function account_log_list_api(params) {
|
||||
return request({
|
||||
url: 'account_log/list',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
514
localwaf/src/pages/waf/account/index.vue
Normal file
514
localwaf/src/pages/waf/account/index.vue
Normal file
@@ -0,0 +1,514 @@
|
||||
<template>
|
||||
<div>
|
||||
<t-card class="list-card-container">
|
||||
<t-row justify="space-between">
|
||||
<div class="left-operation-container">
|
||||
<t-button @click="handleAddAccount"> 新建账号 </t-button>
|
||||
<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>
|
||||
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
|
||||
</template>
|
||||
</t-table>
|
||||
</div>
|
||||
<div>
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</t-card>
|
||||
|
||||
<!-- 新建账号弹窗 -->
|
||||
<t-dialog header="新建账号" :visible.sync="addFormVisible" :width="680" :footer="false">
|
||||
<div slot="body">
|
||||
<!-- 表单内容 -->
|
||||
<t-form :data="formData" ref="form" :rules="rules" @submit="onSubmit" :labelWidth="100">
|
||||
<t-form-item label="登录账号" name="login_account">
|
||||
<t-input :style="{ width: '480px' }" v-model="formData.login_account" placeholder="请输入登录账号"></t-input>
|
||||
</t-form-item>
|
||||
<t-form-item label="登录密码" name="login_password">
|
||||
<t-input :style="{ width: '480px' }" v-model="formData.login_password" placeholder="请输入登录密码"></t-input>
|
||||
</t-form-item>
|
||||
<t-form-item label="状态" name="rate">
|
||||
<t-input-number :style="{ width: '480px' }" v-model="formData.status" placeholder="请输入状态"></t-input-number>
|
||||
</t-form-item>
|
||||
<t-form-item label="备注" name="remarks">
|
||||
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" placeholder="请输入备注内容" name="remarks">
|
||||
</t-textarea>
|
||||
</t-form-item>
|
||||
<t-form-item style="float: right">
|
||||
<t-button variant="outline" @click="onClickCloseBtn">取消</t-button>
|
||||
<t-button theme="primary" type="submit">确定</t-button>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
</div>
|
||||
</t-dialog>
|
||||
|
||||
<!-- 编辑账号弹窗 -->
|
||||
<t-dialog header="编辑账号" :visible.sync="editFormVisible" :width="680" :footer="false">
|
||||
<div slot="body">
|
||||
<!-- 表单内容 -->
|
||||
<t-form :data="formEditData" ref="form" :rules="rules" @submit="onSubmitEdit" :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="login_password">
|
||||
<t-input :style="{ width: '480px' }" v-model="formEditData.login_password" placeholder="请输入登录密码"></t-input>
|
||||
</t-form-item>
|
||||
<t-form-item label="状态" name="status">
|
||||
<t-input-number :style="{ width: '480px' }" v-model="formEditData.status" placeholder="请输入状态"></t-input-number>
|
||||
</t-form-item>
|
||||
<t-form-item label="备注" name="remarks">
|
||||
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" placeholder="请输入内容" name="remarks">
|
||||
</t-textarea>
|
||||
</t-form-item>
|
||||
<t-form-item style="float: right">
|
||||
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
|
||||
<t-button theme="primary" type="submit">确定</t-button>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
</div>
|
||||
</t-dialog>
|
||||
|
||||
<t-dialog header="确认删除当前所选数据?" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
|
||||
:onCancel="onCancel">
|
||||
</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 {
|
||||
account_list_api
|
||||
} from '@/apis/account';
|
||||
|
||||
|
||||
import {
|
||||
SSL_STATUS,
|
||||
GUARD_STATUS,
|
||||
CONTRACT_STATUS,
|
||||
CONTRACT_STATUS_OPTIONS,
|
||||
CONTRACT_TYPES,
|
||||
CONTRACT_PAYMENT_TYPES
|
||||
} from '@/constants';
|
||||
|
||||
const INITIAL_DATA = {
|
||||
login_account: '',
|
||||
login_password: '',
|
||||
status: 1,
|
||||
remarks: '',
|
||||
};
|
||||
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: {
|
||||
login_account: [{
|
||||
required: true,
|
||||
message: '请输入登录账号',
|
||||
type: 'error'
|
||||
}],
|
||||
login_password: [{
|
||||
required: true,
|
||||
message: '请输入登录密码',
|
||||
type: 'error'
|
||||
}],
|
||||
},
|
||||
textareaValue: '',
|
||||
prefix,
|
||||
dataLoading: false,
|
||||
data: [], //列表数据信息
|
||||
detail_data: [], //加载详情信息用于编辑
|
||||
selectedRowKeys: [],
|
||||
value: 'first',
|
||||
columns: [{
|
||||
colKey: 'row-select',
|
||||
type: 'multiple',
|
||||
width: 64,
|
||||
fixed: 'left'
|
||||
},
|
||||
{
|
||||
title: '登录账号',
|
||||
align: 'left',
|
||||
width: 250,
|
||||
ellipsis: true,
|
||||
colKey: 'login_account',
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
title: '登录密码',
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
colKey: 'login_password',
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
colKey: 'remarks',
|
||||
},
|
||||
{
|
||||
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,
|
||||
};
|
||||
},
|
||||
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(){
|
||||
/* let that = this;
|
||||
allhost().then((res) => {
|
||||
let resdata = res
|
||||
console.log(resdata)
|
||||
if (resdata.code === 0) {
|
||||
that.host_options = resdata.data;
|
||||
}
|
||||
})
|
||||
.catch((e: Error) => {
|
||||
console.log(e);
|
||||
}) */
|
||||
},
|
||||
getList(keyword) {
|
||||
let that = this
|
||||
this.$request
|
||||
.get('/account/list', {
|
||||
params: {
|
||||
pageSize: that.pagination.pageSize,
|
||||
pageIndex: that.pagination.current,
|
||||
login_account: '',
|
||||
}
|
||||
})
|
||||
.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('list',id)
|
||||
this.$router.push({
|
||||
path: '/account/detail',
|
||||
query: {
|
||||
id: id,
|
||||
},
|
||||
}, );
|
||||
},
|
||||
handleClickEdit(e) {
|
||||
console.log(e)
|
||||
const {
|
||||
id
|
||||
} = e.row
|
||||
console.log(id)
|
||||
this.editFormVisible = true
|
||||
this.getDetail(id)
|
||||
},
|
||||
handleAddAccount() {
|
||||
//添加
|
||||
this.addFormVisible = true
|
||||
this.formData = {
|
||||
login_account: '',
|
||||
login_password: '',
|
||||
remarks: '',
|
||||
status:1,
|
||||
};
|
||||
},
|
||||
onSubmit({
|
||||
result,
|
||||
firstError
|
||||
}): void {
|
||||
let that = this
|
||||
if (!firstError) {
|
||||
|
||||
let postdata = {
|
||||
...that.formData
|
||||
}
|
||||
this.$request
|
||||
.post('/account/add', {
|
||||
...postdata
|
||||
})
|
||||
.then((res) => {
|
||||
let resdata = res
|
||||
console.log(resdata)
|
||||
if (resdata.code === 0) {
|
||||
that.$message.success(resdata.msg);
|
||||
that.addFormVisible = false;
|
||||
that.pagination.current = 1
|
||||
that.getList("")
|
||||
} else {
|
||||
that.$message.warning(resdata.msg);
|
||||
}
|
||||
})
|
||||
.catch((e: Error) => {
|
||||
console.log(e);
|
||||
})
|
||||
.finally(() => {});
|
||||
} else {
|
||||
console.log('Errors: ', result);
|
||||
that.$message.warning(firstError);
|
||||
}
|
||||
},
|
||||
onSubmitEdit({
|
||||
result,
|
||||
firstError
|
||||
}): void {
|
||||
let that = this
|
||||
if (!firstError) {
|
||||
|
||||
let postdata = {
|
||||
...that.formEditData
|
||||
}
|
||||
this.$request
|
||||
.post('/account/edit', {
|
||||
...postdata
|
||||
})
|
||||
.then((res) => {
|
||||
let resdata = res
|
||||
console.log(resdata)
|
||||
if (resdata.code === 0) {
|
||||
that.$message.success(resdata.msg);
|
||||
that.editFormVisible = false;
|
||||
that.pagination.current = 1
|
||||
that.getList("")
|
||||
} else {
|
||||
that.$message.warning(resdata.msg);
|
||||
}
|
||||
})
|
||||
.catch((e: Error) => {
|
||||
console.log(e);
|
||||
})
|
||||
.finally(() => {});
|
||||
} else {
|
||||
console.log('Errors: ', result);
|
||||
that.$message.warning(firstError);
|
||||
}
|
||||
},
|
||||
onClickCloseBtn(): void {
|
||||
this.formVisible = false;
|
||||
this.formData = {};
|
||||
},
|
||||
onClickCloseEditBtn(): void {
|
||||
this.editFormVisible = false;
|
||||
this.formEditData = {};
|
||||
},
|
||||
handleClickDelete(row) {
|
||||
console.log(row)
|
||||
this.deleteIdx = row.rowIndex;
|
||||
this.confirmVisible = true;
|
||||
},
|
||||
onConfirmDelete() {
|
||||
this.confirmVisible = false;
|
||||
console.log('delete', this.data)
|
||||
console.log('delete', this.data[this.deleteIdx])
|
||||
let {
|
||||
id
|
||||
} = this.data[this.deleteIdx]
|
||||
let that = this
|
||||
this.$request
|
||||
.get('/account/del', {
|
||||
params: {
|
||||
id: id,
|
||||
}
|
||||
})
|
||||
.then((res) => {
|
||||
let resdata = res
|
||||
console.log(resdata)
|
||||
if (resdata.code === 0) {
|
||||
|
||||
that.pagination.current = 1
|
||||
that.getList("")
|
||||
that.$message.success(resdata.msg);
|
||||
} else {
|
||||
that.$message.warning(resdata.msg);
|
||||
}
|
||||
})
|
||||
.catch((e: Error) => {
|
||||
console.log(e);
|
||||
})
|
||||
.finally(() => {});
|
||||
|
||||
|
||||
this.resetIdx();
|
||||
},
|
||||
onCancel() {
|
||||
this.resetIdx();
|
||||
},
|
||||
resetIdx() {
|
||||
this.deleteIdx = -1;
|
||||
},
|
||||
getDetail(id) {
|
||||
let that = this
|
||||
this.$request
|
||||
.get('/account/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>
|
||||
106
localwaf/src/pages/waf/accountlog/detail/index.less
Normal file
106
localwaf/src/pages/waf/accountlog/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/accountlog/detail/index.vue
Normal file
148
localwaf/src/pages/waf/accountlog/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>
|
||||
351
localwaf/src/pages/waf/accountlog/index.vue
Normal file
351
localwaf/src/pages/waf/accountlog/index.vue
Normal file
@@ -0,0 +1,351 @@
|
||||
<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 {
|
||||
account_log_list_api
|
||||
} from '@/apis/account';
|
||||
|
||||
|
||||
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: '操作账号',
|
||||
align: 'left',
|
||||
width: 250,
|
||||
ellipsis: true,
|
||||
colKey: 'login_account',
|
||||
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(){
|
||||
/* let that = this;
|
||||
allhost().then((res) => {
|
||||
let resdata = res
|
||||
console.log(resdata)
|
||||
if (resdata.code === 0) {
|
||||
that.host_options = resdata.data;
|
||||
}
|
||||
})
|
||||
.catch((e: Error) => {
|
||||
console.log(e);
|
||||
}) */
|
||||
},
|
||||
getList(keyword) {
|
||||
let that = this
|
||||
this.$request
|
||||
.get('/account_log/list', {
|
||||
params: {
|
||||
pageSize: that.pagination.pageSize,
|
||||
pageIndex: that.pagination.current,
|
||||
login_account: '',
|
||||
}
|
||||
})
|
||||
.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('/account_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>
|
||||
@@ -25,6 +25,29 @@ export default [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/account',
|
||||
name: 'account',
|
||||
component: Layout,
|
||||
redirect: '/account',
|
||||
meta: { title: '账号', icon: ViewModuleIcon },
|
||||
children: [
|
||||
{
|
||||
path: 'Account',
|
||||
name: 'Account',
|
||||
component: () => import('@/pages/waf/account/index.vue'),
|
||||
meta: { title: '账号管理' },
|
||||
},
|
||||
{
|
||||
path: 'AccountLog',
|
||||
name: 'AccountLog',
|
||||
component: () => import('@/pages/waf/accountlog/index.vue'),
|
||||
meta: { title: '账号操作日志' },
|
||||
},
|
||||
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/waf-host',
|
||||
name: 'wafhost',
|
||||
@@ -82,7 +105,7 @@ export default [
|
||||
component: () => import('@/pages/waf/urlwhite/detail/index.vue'),
|
||||
meta: { title: 'Url白名单详情', hidden: true},
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
path: 'wafipBlocklist',
|
||||
name: 'WafIpBlockList',
|
||||
|
||||
25
model/account.go
Normal file
25
model/account.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type Account struct {
|
||||
Id string `gorm:"primary_key" json:"id"`
|
||||
UserCode string `json:"user_code"` //用户码(主要键)
|
||||
TenantId string `json:"tenant_id"` //租户ID(主要键)
|
||||
LoginAccount string `json:"login_account"` //登录账号
|
||||
LoginPassword string `json:"login_password"` //密码md5加密
|
||||
Status int `json:"status"` //状态
|
||||
Remarks string `json:"remarks"` //备注
|
||||
CreateTime time.Time `json:"create_time"` //创建时间
|
||||
LastUpdateTime time.Time `json:"last_update_time"` //上次更新时间
|
||||
}
|
||||
|
||||
type AccountLog struct {
|
||||
Id string `gorm:"primary_key" json:"id"`
|
||||
UserCode string `json:"user_code"` //用户码(主要键)
|
||||
TenantId string `json:"tenant_id"` //租户ID(主要键)
|
||||
LoginAccount string `json:"login_account"` //登录账号
|
||||
OpType string `json:"op_type"` //操作类型
|
||||
OpContent string `json:"op_content"` //操作内容
|
||||
CreateTime time.Time `json:"create_time"` //创建时间
|
||||
}
|
||||
8
model/request/waf_account_add_req.go
Normal file
8
model/request/waf_account_add_req.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package request
|
||||
|
||||
type WafAccountAddReq struct {
|
||||
LoginAccount string `json:"login_account" form:"login_account"` //登录账号
|
||||
LoginPassword string `json:"login_password" form:"login_password"` //密码md5加密
|
||||
Status int `json:"status" form:"status" ` //状态
|
||||
Remarks string `json:"remarks" form:"remarks" ` //备注
|
||||
}
|
||||
5
model/request/waf_account_del_req.go
Normal file
5
model/request/waf_account_del_req.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package request
|
||||
|
||||
type WafAccountDelReq struct {
|
||||
Id string `json:"id" form:"id"` //唯一键
|
||||
}
|
||||
5
model/request/waf_account_detail_req.go
Normal file
5
model/request/waf_account_detail_req.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package request
|
||||
|
||||
type WafAccountDetailReq struct {
|
||||
Id string `json:"id" form:"id"` //唯一键
|
||||
}
|
||||
9
model/request/waf_account_edit_req.go
Normal file
9
model/request/waf_account_edit_req.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package request
|
||||
|
||||
type WafAccountEditReq struct {
|
||||
Id string `json:"id"`
|
||||
LoginAccount string `json:"login_account" form:"login_account"` //登录账号(TODO 账号是否能随便改)
|
||||
LoginPassword string `json:"login_password" form:"login_password"` //密码md5加密
|
||||
Status int `json:"status" form:"status" ` //状态
|
||||
Remarks string `json:"remarks" form:"remarks" ` //备注
|
||||
}
|
||||
5
model/request/waf_account_log_detail_req.go
Normal file
5
model/request/waf_account_log_detail_req.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package request
|
||||
|
||||
type WafAccountLogDetailReq struct {
|
||||
Id string `json:"id" form:"id"` //唯一键
|
||||
}
|
||||
8
model/request/waf_account_log_search.go
Normal file
8
model/request/waf_account_log_search.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package request
|
||||
|
||||
import "SamWaf/model/common/request"
|
||||
|
||||
type WafAccountLogSearchReq struct {
|
||||
LoginAccount string `json:"login_account" form:"login_account"` //登录账号
|
||||
request.PageInfo
|
||||
}
|
||||
8
model/request/waf_account_search.go
Normal file
8
model/request/waf_account_search.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package request
|
||||
|
||||
import "SamWaf/model/common/request"
|
||||
|
||||
type WafAccountSearchReq struct {
|
||||
LoginAccount string `json:"login_account" form:"login_account"` //登录账号
|
||||
request.PageInfo
|
||||
}
|
||||
@@ -12,6 +12,8 @@ type ApiGroup struct {
|
||||
AntiCCRouter
|
||||
BlockIpRouter
|
||||
BlockUrlRouter
|
||||
AccountRouter
|
||||
AccountLogRouter
|
||||
}
|
||||
|
||||
var ApiGroupApp = new(ApiGroup)
|
||||
|
||||
19
router/waf_account.go
Normal file
19
router/waf_account.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"SamWaf/api"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AccountRouter struct {
|
||||
}
|
||||
|
||||
func (receiver *AccountRouter) InitAccountRouter(group *gin.RouterGroup) {
|
||||
api := api.APIGroupAPP.WafAccountApi
|
||||
router := group.Group("")
|
||||
router.GET("/samwaf/account/list", api.GetListApi)
|
||||
router.GET("/samwaf/account/detail", api.GetDetailApi)
|
||||
router.POST("/samwaf/account/add", api.AddApi)
|
||||
router.GET("/samwaf/account/del", api.DelAccountApi)
|
||||
router.POST("/samwaf/account/edit", api.ModifyAccountApi)
|
||||
}
|
||||
16
router/waf_account_log.go
Normal file
16
router/waf_account_log.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"SamWaf/api"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AccountLogRouter struct {
|
||||
}
|
||||
|
||||
func (receiver *AccountLogRouter) InitAccountLogRouter(group *gin.RouterGroup) {
|
||||
api := api.APIGroupAPP.WafAccountLogApi
|
||||
router := group.Group("")
|
||||
router.GET("/samwaf/account_log/list", api.GetListApi)
|
||||
router.GET("/samwaf/account_log/detail", api.GetDetailApi)
|
||||
}
|
||||
77
service/waf_service/waf_account.go
Normal file
77
service/waf_service/waf_account.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package waf_service
|
||||
|
||||
import (
|
||||
"SamWaf/global"
|
||||
"SamWaf/model"
|
||||
"SamWaf/model/request"
|
||||
"errors"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"time"
|
||||
)
|
||||
|
||||
type WafAccountService struct{}
|
||||
|
||||
var WafAccountServiceApp = new(WafAccountService)
|
||||
|
||||
func (receiver *WafAccountService) AddApi(req request.WafAccountAddReq) error {
|
||||
var bean = &model.Account{
|
||||
Id: uuid.NewV4().String(),
|
||||
UserCode: global.GWAF_USER_CODE,
|
||||
TenantId: global.GWAF_TENANT_ID,
|
||||
LoginAccount: req.LoginAccount,
|
||||
LoginPassword: req.LoginPassword,
|
||||
Status: req.Status,
|
||||
Remarks: req.Remarks,
|
||||
CreateTime: time.Now(),
|
||||
LastUpdateTime: time.Now(),
|
||||
}
|
||||
global.GWAF_LOCAL_DB.Debug().Create(bean)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (receiver *WafAccountService) CheckIsExistApi(req request.WafAccountAddReq) error {
|
||||
return global.GWAF_LOCAL_DB.First(&model.Account{}, "login_account = ? ", req.LoginAccount).Error
|
||||
}
|
||||
func (receiver *WafAccountService) ModifyApi(req request.WafAccountEditReq) error {
|
||||
var bean model.Account
|
||||
global.GWAF_LOCAL_DB.Debug().Where("login_account = ?", req.LoginAccount).Find(&bean)
|
||||
if bean.Id != "" && bean.LoginAccount != req.LoginAccount {
|
||||
return errors.New("当前数据已经存在")
|
||||
}
|
||||
beanMap := map[string]interface{}{
|
||||
"LoginAccount": req.LoginAccount,
|
||||
"LoginPassword": req.LoginPassword,
|
||||
"Status": req.Status,
|
||||
"Remarks": req.Remarks,
|
||||
"last_update_time": time.Now(),
|
||||
}
|
||||
err := global.GWAF_LOCAL_DB.Debug().Model(model.Account{}).Where("id = ?", req.Id).Updates(beanMap).Error
|
||||
|
||||
return err
|
||||
}
|
||||
func (receiver *WafAccountService) GetDetailApi(req request.WafAccountDetailReq) model.Account {
|
||||
var bean model.Account
|
||||
global.GWAF_LOCAL_DB.Debug().Where("id=?", req.Id).Find(&bean)
|
||||
return bean
|
||||
}
|
||||
func (receiver *WafAccountService) GetDetailByIdApi(id string) model.Account {
|
||||
var bean model.Account
|
||||
global.GWAF_LOCAL_DB.Debug().Where("id=?", id).Find(&bean)
|
||||
return bean
|
||||
}
|
||||
func (receiver *WafAccountService) GetListApi(req request.WafAccountSearchReq) ([]model.Account, int64, error) {
|
||||
var bean []model.Account
|
||||
var total int64 = 0
|
||||
global.GWAF_LOCAL_DB.Debug().Limit(req.PageSize).Offset(req.PageSize * (req.PageIndex - 1)).Find(&bean)
|
||||
global.GWAF_LOCAL_DB.Debug().Model(&model.Account{}).Count(&total)
|
||||
return bean, total, nil
|
||||
}
|
||||
func (receiver *WafAccountService) DelApi(req request.WafAccountDelReq) error {
|
||||
var bean model.Account
|
||||
err := global.GWAF_LOCAL_DB.Where("id = ?", req.Id).First(&bean).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = global.GWAF_LOCAL_DB.Where("id = ?", req.Id).Delete(model.Account{}).Error
|
||||
return err
|
||||
}
|
||||
24
service/waf_service/waf_account_log.go
Normal file
24
service/waf_service/waf_account_log.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package waf_service
|
||||
|
||||
import (
|
||||
"SamWaf/global"
|
||||
"SamWaf/model"
|
||||
"SamWaf/model/request"
|
||||
)
|
||||
|
||||
type WafAccountLogService struct{}
|
||||
|
||||
var WafAccountLogServiceApp = new(WafAccountLogService)
|
||||
|
||||
func (receiver *WafAccountLogService) GetDetailApi(req request.WafAccountLogDetailReq) model.AccountLog {
|
||||
var bean model.AccountLog
|
||||
global.GWAF_LOCAL_DB.Debug().Where("id=?", req.Id).Find(&bean)
|
||||
return bean
|
||||
}
|
||||
func (receiver *WafAccountLogService) GetListApi(req request.WafAccountLogSearchReq) ([]model.AccountLog, int64, error) {
|
||||
var bean []model.AccountLog
|
||||
var total int64 = 0
|
||||
global.GWAF_LOCAL_DB.Debug().Limit(req.PageSize).Offset(req.PageSize * (req.PageIndex - 1)).Find(&bean)
|
||||
global.GWAF_LOCAL_DB.Debug().Model(&model.AccountLog{}).Count(&total)
|
||||
return bean, total, nil
|
||||
}
|
||||
@@ -2,7 +2,9 @@ package utils
|
||||
|
||||
import (
|
||||
"SamWaf/model"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -63,3 +65,14 @@ func TimeToDayInt(t time.Time) int {
|
||||
day, _ := strconv.Atoi(t.Format("20060102"))
|
||||
return day
|
||||
}
|
||||
func GetPublicIP() string {
|
||||
conn, err := net.Dial("udp", "8.8.8.8:80")
|
||||
if err != nil {
|
||||
return "localhost"
|
||||
// log.Fatal(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
localAddr := conn.LocalAddr().String()
|
||||
idx := strings.LastIndex(localAddr, ":")
|
||||
return localAddr[0:idx]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user