mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-03 12:20:28 +08:00
增加ip2region库管理
This commit is contained in:
@@ -172,6 +172,18 @@ func (this *RPCClient) MessageRPC() pb.MessageServiceClient {
|
||||
return pb.NewMessageServiceClient(this.pickConn())
|
||||
}
|
||||
|
||||
func (this *RPCClient) IPLibraryRPC() pb.IPLibraryServiceClient {
|
||||
return pb.NewIPLibraryServiceClient(this.pickConn())
|
||||
}
|
||||
|
||||
func (this *RPCClient) FileRPC() pb.FileServiceClient {
|
||||
return pb.NewFileServiceClient(this.pickConn())
|
||||
}
|
||||
|
||||
func (this *RPCClient) FileChunkRPC() pb.FileChunkServiceClient {
|
||||
return pb.NewFileChunkServiceClient(this.pickConn())
|
||||
}
|
||||
|
||||
// 构造Admin上下文
|
||||
func (this *RPCClient) Context(adminId int64) context.Context {
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -64,6 +64,11 @@ func (this *ComponentHelper) createLeftMenus(secondMenuItem string) (items []map
|
||||
"url": "/servers/components/ssl",
|
||||
"isActive": secondMenuItem == "ssl",
|
||||
})
|
||||
items = append(items, maps.Map{
|
||||
"name": "IP库",
|
||||
"url": "/servers/components/ip-library",
|
||||
"isActive": secondMenuItem == "ip-library",
|
||||
})
|
||||
/**items = append(items, maps.Map{
|
||||
"name": "Gzip规则",
|
||||
"url": "/servers/components/gzip",
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package iplibrary
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
LibraryId int64
|
||||
}) {
|
||||
_, err := this.RPC().IPLibraryRPC().DeleteIPLibrary(this.AdminContext(), &pb.DeleteIPLibraryRequest{IpLibraryId: params.LibraryId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package iplibrary
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DownloadAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DownloadAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *DownloadAction) RunGet(params struct {
|
||||
LibraryId int64
|
||||
}) {
|
||||
libraryResp, err := this.RPC().IPLibraryRPC().FindEnabledIPLibrary(this.AdminContext(), &pb.FindEnabledIPLibraryRequest{IpLibraryId: params.LibraryId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if libraryResp.IpLibrary == nil || libraryResp.IpLibrary.File == nil {
|
||||
this.NotFound("ipLibrary", params.LibraryId)
|
||||
return
|
||||
}
|
||||
|
||||
file := libraryResp.IpLibrary.File
|
||||
chunkIdsResp, err := this.RPC().FileChunkRPC().FindAllFileChunkIds(this.AdminContext(), &pb.FindAllFileChunkIdsRequest{FileId: file.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
|
||||
this.AddHeader("Content-Disposition", "attachment; filename=\""+file.Filename+"\";")
|
||||
for _, chunkId := range chunkIdsResp.FileChunkIds {
|
||||
chunkResp, err := this.RPC().FileChunkRPC().DownloadFileChunk(this.AdminContext(), &pb.DownloadFileChunkRequest{FileChunkId: chunkId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if chunkResp.FileChunk != nil {
|
||||
this.Write(chunkResp.FileChunk.Data)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package iplibrary
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Helper struct {
|
||||
}
|
||||
|
||||
func NewHelper() *Helper {
|
||||
return &Helper{}
|
||||
}
|
||||
|
||||
func (this *Helper) BeforeAction(action *actions.ActionObject) {
|
||||
if action.Request.Method != http.MethodGet {
|
||||
return
|
||||
}
|
||||
|
||||
action.Data["mainTab"] = "component"
|
||||
action.Data["secondMenuItem"] = "ip-library"
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package iplibrary
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.FirstMenu("index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
Type string
|
||||
}) {
|
||||
if len(params.Type) == 0 {
|
||||
params.Type = serverconfigs.IPLibraryTypes[0].GetString("code")
|
||||
}
|
||||
|
||||
this.Data["types"] = serverconfigs.IPLibraryTypes
|
||||
this.Data["selectedType"] = params.Type
|
||||
|
||||
// 列表
|
||||
listResp, err := this.RPC().IPLibraryRPC().FindAllEnabledIPLibrariesWithType(this.AdminContext(), &pb.FindAllEnabledIPLibrariesWithTypeRequest{Type: params.Type})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
libraryMaps := []maps.Map{}
|
||||
for _, library := range listResp.IpLibraries {
|
||||
var fileMap maps.Map = nil
|
||||
if library.File != nil {
|
||||
fileMap = maps.Map{
|
||||
"id": library.File.Id,
|
||||
"filename": library.File.Filename,
|
||||
"sizeMB": fmt.Sprintf("%.2f", float64(library.File.Size)/1024/1024),
|
||||
}
|
||||
}
|
||||
|
||||
libraryMaps = append(libraryMaps, maps.Map{
|
||||
"id": library.Id,
|
||||
"file": fileMap,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", library.CreatedAt),
|
||||
})
|
||||
}
|
||||
this.Data["libraries"] = libraryMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package iplibrary
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/componentutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth()).
|
||||
Helper(NewHelper()).
|
||||
Helper(componentutils.NewComponentHelper()).
|
||||
Prefix("/servers/components/ip-library").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/uploadPopup", new(UploadPopupAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
Get("/download", new(DownloadAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package iplibrary
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"io"
|
||||
)
|
||||
|
||||
type UploadPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UploadPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UploadPopupAction) RunGet(params struct{}) {
|
||||
this.Data["types"] = serverconfigs.IPLibraryTypes
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UploadPopupAction) RunPost(params struct {
|
||||
Type string
|
||||
File *actions.File
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
libraryType := serverconfigs.FindIPLibraryWithType(params.Type)
|
||||
if libraryType == nil {
|
||||
this.Fail("错误的IP类型")
|
||||
}
|
||||
|
||||
if params.File == nil {
|
||||
this.Fail("请选择要上传的文件")
|
||||
}
|
||||
|
||||
if params.File.Size == 0 {
|
||||
this.Fail("文件内容不能为空")
|
||||
}
|
||||
|
||||
if params.File.Ext != libraryType.GetString("ext") {
|
||||
this.Fail("IP库文件扩展名错误,应该为:" + libraryType.GetString("ext"))
|
||||
}
|
||||
|
||||
reader, err := params.File.OriginFile.Open()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
_ = reader.Close()
|
||||
}()
|
||||
|
||||
// 创建文件
|
||||
fileResp, err := this.RPC().FileRPC().CreateFile(this.AdminContext(), &pb.CreateFileRequest{
|
||||
Filename: params.File.Filename,
|
||||
Size: params.File.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
fileId := fileResp.FileId
|
||||
|
||||
// 上传内容
|
||||
buf := make([]byte, 512*1024)
|
||||
for {
|
||||
n, err := reader.Read(buf)
|
||||
if n > 0 {
|
||||
_, err = this.RPC().FileChunkRPC().CreateFileChunk(this.AdminContext(), &pb.CreateFileChunkRequest{
|
||||
FileId: fileId,
|
||||
Data: buf[:n],
|
||||
})
|
||||
if err != nil {
|
||||
this.Fail("上传失败:" + err.Error())
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
this.Fail("上传失败:" + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// 置为已完成
|
||||
_, err = this.RPC().FileRPC().UpdateFileFinished(this.AdminContext(), &pb.UpdateFileFinishedRequest{FileId: fileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
|
||||
// 保存
|
||||
_, err = this.RPC().IPLibraryRPC().CreateIPLibrary(this.AdminContext(), &pb.CreateIPLibraryRequest{
|
||||
Type: params.Type,
|
||||
FileId: fileId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/groups"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/ip-library"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/log"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/ssl"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/waf"
|
||||
|
||||
39
web/views/@default/servers/components/ip-library/index.html
Normal file
39
web/views/@default/servers/components/ip-library/index.html
Normal file
@@ -0,0 +1,39 @@
|
||||
{$layout}
|
||||
{$template "/left_menu"}
|
||||
|
||||
<div class="right-box">
|
||||
<first-menu>
|
||||
<menu-item v-for="type in types" :href="'/servers/components/ip-library?type=' + type.code" :active="type.code == selectedType">{{type.name}}</menu-item>
|
||||
<span class="item">|</span>
|
||||
<a href="" class="item" @click.prevent="upload()">[上传]</a>
|
||||
</first-menu>
|
||||
|
||||
<p class="comment" v-if="libraries.length == 0">暂时还没有IP库。</p>
|
||||
<div v-if="libraries.length > 0">
|
||||
<div class="margin"></div>
|
||||
<table class="ui table selectable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>文件名</th>
|
||||
<th>文件尺寸</th>
|
||||
<th>上传时间</th>
|
||||
<th class="two op">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="library in libraries">
|
||||
<td>
|
||||
<span v-if="library.file != null">{{library.file.filename}}</span>
|
||||
<span v-else>-</span>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="library.file != null">{{library.file.sizeMB}}MB</span>
|
||||
<span v-else>-</span>
|
||||
</td>
|
||||
<td>{{library.createdTime}}</td>
|
||||
<td>
|
||||
<a :href="'/servers/components/ip-library/download?libraryId=' + library.id" target="_blank">下载</a> <a href="" @click.prevent="deleteLibrary(library.id)">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
24
web/views/@default/servers/components/ip-library/index.js
Normal file
24
web/views/@default/servers/components/ip-library/index.js
Normal file
@@ -0,0 +1,24 @@
|
||||
Tea.context(function () {
|
||||
this.upload = function () {
|
||||
teaweb.popup("/servers/components/ip-library/uploadPopup", {
|
||||
callback: function () {
|
||||
teaweb.success("上传成功", function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.deleteLibrary = function (libraryId) {
|
||||
let that = this
|
||||
teaweb.confirm("确定要删除此IP库吗?", function () {
|
||||
that.$post(".delete")
|
||||
.params({
|
||||
"libraryId": libraryId
|
||||
})
|
||||
.success(function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,25 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>上传IP库</h3>
|
||||
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success" data-tea-timeout="120" data-tea-before="before" data-tea-done="done">
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td>IP库类型 *</td>
|
||||
<td>
|
||||
<select name="type" class="ui dropdown auto-width" @change="changeType()" v-model="selectedTypeCode">
|
||||
<option v-for="type in types" :value="type.code">{{type.name}}</option>
|
||||
</select>
|
||||
<p class="comment">{{selectedTypeDescription}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="title">选择IP库文件 *</td>
|
||||
<td>
|
||||
<input type="file" name="file" :accept="selectedTypeExt"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<submit-btn v-if="!isRequesting"></submit-btn>
|
||||
<button class="ui button disabled" type="button" v-if="isRequesting">上传中...</button>
|
||||
</form>
|
||||
@@ -0,0 +1,28 @@
|
||||
Tea.context(function () {
|
||||
this.isRequesting = false
|
||||
this.selectedTypeCode = this.types[0].code
|
||||
this.selectedTypeDescription = this.types[0].description
|
||||
this.selectedTypeExt = this.types[0].ext
|
||||
|
||||
this.success = NotifyPopup
|
||||
|
||||
this.before = function () {
|
||||
this.isRequesting = true
|
||||
}
|
||||
|
||||
this.done = function () {
|
||||
this.isRequesting = false
|
||||
}
|
||||
|
||||
this.changeType = function () {
|
||||
let that = this
|
||||
let selectedType = this.types.$find(function (k, v) {
|
||||
return v.code == that.selectedTypeCode
|
||||
})
|
||||
if (selectedType == null) {
|
||||
return
|
||||
}
|
||||
this.selectedTypeDescription = selectedType.description
|
||||
this.selectedTypeExt = selectedType.ext
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user