diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go index 56152c23..eecf546e 100644 --- a/internal/rpc/rpc_client.go +++ b/internal/rpc/rpc_client.go @@ -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() diff --git a/internal/web/actions/default/servers/components/componentutils/component_helper.go b/internal/web/actions/default/servers/components/componentutils/component_helper.go index 20d7f194..51a1b5f4 100644 --- a/internal/web/actions/default/servers/components/componentutils/component_helper.go +++ b/internal/web/actions/default/servers/components/componentutils/component_helper.go @@ -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", diff --git a/internal/web/actions/default/servers/components/ip-library/delete.go b/internal/web/actions/default/servers/components/ip-library/delete.go new file mode 100644 index 00000000..4d010aef --- /dev/null +++ b/internal/web/actions/default/servers/components/ip-library/delete.go @@ -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() +} diff --git a/internal/web/actions/default/servers/components/ip-library/download.go b/internal/web/actions/default/servers/components/ip-library/download.go new file mode 100644 index 00000000..ac6a4d85 --- /dev/null +++ b/internal/web/actions/default/servers/components/ip-library/download.go @@ -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) + } + } +} diff --git a/internal/web/actions/default/servers/components/ip-library/helper.go b/internal/web/actions/default/servers/components/ip-library/helper.go new file mode 100644 index 00000000..af605922 --- /dev/null +++ b/internal/web/actions/default/servers/components/ip-library/helper.go @@ -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" +} diff --git a/internal/web/actions/default/servers/components/ip-library/index.go b/internal/web/actions/default/servers/components/ip-library/index.go new file mode 100644 index 00000000..cafac9c4 --- /dev/null +++ b/internal/web/actions/default/servers/components/ip-library/index.go @@ -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() +} diff --git a/internal/web/actions/default/servers/components/ip-library/init.go b/internal/web/actions/default/servers/components/ip-library/init.go new file mode 100644 index 00000000..7e8bbd22 --- /dev/null +++ b/internal/web/actions/default/servers/components/ip-library/init.go @@ -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() + }) +} diff --git a/internal/web/actions/default/servers/components/ip-library/uploadPopup.go b/internal/web/actions/default/servers/components/ip-library/uploadPopup.go new file mode 100644 index 00000000..0f2a613c --- /dev/null +++ b/internal/web/actions/default/servers/components/ip-library/uploadPopup.go @@ -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() +} diff --git a/internal/web/import.go b/internal/web/import.go index bd7ea7ff..4a13f7ff 100644 --- a/internal/web/import.go +++ b/internal/web/import.go @@ -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" diff --git a/web/views/@default/servers/components/ip-library/index.html b/web/views/@default/servers/components/ip-library/index.html new file mode 100644 index 00000000..e28fdcca --- /dev/null +++ b/web/views/@default/servers/components/ip-library/index.html @@ -0,0 +1,39 @@ +{$layout} +{$template "/left_menu"} + +
+ + {{type.name}} + | + [上传] + + +

暂时还没有IP库。

+
+
+ + + + + + + + + + + + + + + +
文件名文件尺寸上传时间操作
+ {{library.file.filename}} + - + + {{library.file.sizeMB}}MB + - + {{library.createdTime}} + 下载   删除 +
+
+
\ No newline at end of file diff --git a/web/views/@default/servers/components/ip-library/index.js b/web/views/@default/servers/components/ip-library/index.js new file mode 100644 index 00000000..b7d1dd7a --- /dev/null +++ b/web/views/@default/servers/components/ip-library/index.js @@ -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() + }) + }) + } +}) \ No newline at end of file diff --git a/web/views/@default/servers/components/ip-library/uploadPopup.html b/web/views/@default/servers/components/ip-library/uploadPopup.html new file mode 100644 index 00000000..c6a179af --- /dev/null +++ b/web/views/@default/servers/components/ip-library/uploadPopup.html @@ -0,0 +1,25 @@ +{$layout "layout_popup"} + +

上传IP库

+ +
+ + + + + + + + + +
IP库类型 * + +

{{selectedTypeDescription}}

+
选择IP库文件 * + +
+ + +
\ No newline at end of file diff --git a/web/views/@default/servers/components/ip-library/uploadPopup.js b/web/views/@default/servers/components/ip-library/uploadPopup.js new file mode 100644 index 00000000..6d259683 --- /dev/null +++ b/web/views/@default/servers/components/ip-library/uploadPopup.js @@ -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 + } +}) \ No newline at end of file