diff --git a/internal/web/actions/default/servers/accesslogs/createPopup.go b/internal/web/actions/default/servers/accesslogs/createPopup.go new file mode 100644 index 00000000..02a6bd71 --- /dev/null +++ b/internal/web/actions/default/servers/accesslogs/createPopup.go @@ -0,0 +1,179 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package ipbox + +import ( + "encoding/json" + "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" + "github.com/iwind/TeaGo/cmd" +) + +type CreatePopupAction struct { + actionutils.ParentAction +} + +func (this *CreatePopupAction) Init() { + this.Nav("", "", "") +} + +func (this *CreatePopupAction) RunGet(params struct{}) { + this.Data["types"] = serverconfigs.FindAllAccessLogStorageTypes() + this.Data["syslogPriorities"] = serverconfigs.AccessLogSyslogStoragePriorities + + this.Show() +} + +func (this *CreatePopupAction) RunPost(params struct { + Name string + Type string + + // file + FilePath string + FileAutoCreate bool + + // es + EsEndpoint string + EsIndex string + EsMappingType string + EsUsername string + EsPassword string + + // mysql + MysqlHost string + MysqlPort int + MysqlUsername string + MysqlPassword string + MysqlDatabase string + MysqlTable string + MysqlLogField string + + // tcp + TcpNetwork string + TcpAddr string + + // syslog + SyslogProtocol string + SyslogServerAddr string + SyslogServerPort int + SyslogSocket string + SyslogTag string + SyslogPriority int + + // command + CommandCommand string + CommandArgs string + CommandDir string + + IsPublic bool + + Must *actions.Must + CSRF *actionutils.CSRF +}) { + var policyId int64 = 0 + defer func() { + this.CreateLogInfo("创建访问日志策略 %d", policyId) + }() + + params.Must. + Field("name", params.Name). + Require("请输入日志策略的名称"). + Field("type", params.Type). + Require("请选择存储类型") + + var options interface{} = nil + switch params.Type { + case serverconfigs.AccessLogStorageTypeFile: + params.Must. + Field("filePath", params.FilePath). + Require("请输入日志文件路径") + + storage := new(serverconfigs.AccessLogFileStorageConfig) + storage.Path = params.FilePath + storage.AutoCreate = params.FileAutoCreate + options = storage + case serverconfigs.AccessLogStorageTypeES: + params.Must. + Field("esEndpoint", params.EsEndpoint). + Require("请输入Endpoint"). + Field("esIndex", params.EsIndex). + Require("请输入Index名称"). + Field("esMappingType", params.EsMappingType). + Require("请输入Mapping名称") + + storage := new(serverconfigs.AccessLogESStorageConfig) + storage.Endpoint = params.EsEndpoint + storage.Index = params.EsIndex + storage.MappingType = params.EsMappingType + storage.Username = params.EsUsername + storage.Password = params.EsPassword + options = storage + case serverconfigs.AccessLogStorageTypeTCP: + params.Must. + Field("tcpNetwork", params.TcpNetwork). + Require("请选择网络协议"). + Field("tcpAddr", params.TcpAddr). + Require("请输入网络地址") + + storage := new(serverconfigs.AccessLogTCPStorageConfig) + storage.Network = params.TcpNetwork + storage.Addr = params.TcpAddr + options = storage + case serverconfigs.AccessLogStorageTypeSyslog: + switch params.SyslogProtocol { + case serverconfigs.AccessLogSyslogStorageProtocolTCP, serverconfigs.AccessLogSyslogStorageProtocolUDP: + params.Must. + Field("syslogServerAddr", params.SyslogServerAddr). + Require("请输入网络地址") + case serverconfigs.AccessLogSyslogStorageProtocolSocket: + params.Must. + Field("syslogSocket", params.SyslogSocket). + Require("请输入Socket路径") + } + + storage := new(serverconfigs.AccessLogSyslogStorageConfig) + storage.Protocol = params.SyslogProtocol + storage.ServerAddr = params.SyslogServerAddr + storage.ServerPort = params.SyslogServerPort + storage.Socket = params.SyslogSocket + storage.Tag = params.SyslogTag + storage.Priority = params.SyslogPriority + options = storage + case serverconfigs.AccessLogStorageTypeCommand: + params.Must. + Field("commandCommand", params.CommandCommand). + Require("请输入可执行命令") + + storage := new(serverconfigs.AccessLogCommandStorageConfig) + storage.Command = params.CommandCommand + storage.Args = cmd.ParseArgs(params.CommandArgs) + storage.Dir = params.CommandDir + options = storage + } + + if options == nil { + this.Fail("找不到选择的存储类型") + } + + optionsJSON, err := json.Marshal(options) + if err != nil { + this.ErrorPage(err) + return + } + createResp, err := this.RPC().HTTPAccessLogPolicyRPC().CreateHTTPAccessLogPolicy(this.AdminContext(), &pb.CreateHTTPAccessLogPolicyRequest{ + Name: params.Name, + Type: params.Type, + OptionsJSON: optionsJSON, + CondsJSON: nil, // TODO + IsPublic: params.IsPublic, + }) + if err != nil { + this.ErrorPage(err) + return + } + policyId = createResp.HttpAccessLogPolicyId + + this.Success() +} diff --git a/internal/web/actions/default/servers/accesslogs/delete.go b/internal/web/actions/default/servers/accesslogs/delete.go new file mode 100644 index 00000000..0b7631b7 --- /dev/null +++ b/internal/web/actions/default/servers/accesslogs/delete.go @@ -0,0 +1,26 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package ipbox + +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 { + PolicyId int64 +}) { + defer this.CreateLogInfo("删除访问日志策略 %d", params.PolicyId) + + _, err := this.RPC().HTTPAccessLogPolicyRPC().DeleteHTTPAccessLogPolicy(this.AdminContext(), &pb.DeleteHTTPAccessLogPolicyRequest{HttpAccessLogPolicyId: params.PolicyId}) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/servers/accesslogs/index.go b/internal/web/actions/default/servers/accesslogs/index.go new file mode 100644 index 00000000..ab47f60f --- /dev/null +++ b/internal/web/actions/default/servers/accesslogs/index.go @@ -0,0 +1,57 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package ipbox + +import ( + "encoding/json" + "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" +) + +type IndexAction struct { + actionutils.ParentAction +} + +func (this *IndexAction) Init() { + this.Nav("", "", "index") +} + +func (this *IndexAction) RunGet(params struct{}) { + countResp, err := this.RPC().HTTPAccessLogPolicyRPC().CountAllEnabledHTTPAccessLogPolicies(this.AdminContext(), &pb.CountAllEnabledHTTPAccessLogPoliciesRequest{}) + if err != nil { + this.ErrorPage(err) + return + } + page := this.NewPage(countResp.Count) + this.Data["page"] = page.AsHTML() + + policiesResp, err := this.RPC().HTTPAccessLogPolicyRPC().ListEnabledHTTPAccessLogPolicies(this.AdminContext(), &pb.ListEnabledHTTPAccessLogPoliciesRequest{ + Offset: page.Offset, + Size: page.Size, + }) + var policyMaps = []maps.Map{} + for _, policy := range policiesResp.HttpAccessLogPolicies { + var optionsMap = maps.Map{} + if len(policy.OptionsJSON) > 0 { + err = json.Unmarshal(policy.OptionsJSON, &optionsMap) + if err != nil { + this.ErrorPage(err) + return + } + } + policyMaps = append(policyMaps, maps.Map{ + "id": policy.Id, + "name": policy.Name, + "type": policy.Type, + "typeName": serverconfigs.FindAccessLogStorageTypeName(policy.Type), + "isOn": policy.IsOn, + "isPublic": policy.IsPublic, + "options": optionsMap, + }) + } + this.Data["policies"] = policyMaps + + this.Show() +} diff --git a/internal/web/actions/default/servers/accesslogs/init.go b/internal/web/actions/default/servers/accesslogs/init.go new file mode 100644 index 00000000..9a8d28a8 --- /dev/null +++ b/internal/web/actions/default/servers/accesslogs/init.go @@ -0,0 +1,26 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package ipbox + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/configloaders" + "github.com/TeaOSLab/EdgeAdmin/internal/web/helpers" + "github.com/iwind/TeaGo" +) + +func init() { + TeaGo.BeforeStart(func(server *TeaGo.Server) { + server. + Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)). + Prefix("/servers/accesslogs"). + Data("teaMenu", "servers"). + Data("teaSubMenu", "accesslog"). + Get("", new(IndexAction)). + GetPost("/createPopup", new(CreatePopupAction)). + Get("/policy", new(PolicyAction)). + GetPost("/test", new(TestAction)). + GetPost("/update", new(UpdateAction)). + Post("/delete", new(DeleteAction)). + EndAll() + }) +} diff --git a/internal/web/actions/default/servers/accesslogs/policy.go b/internal/web/actions/default/servers/accesslogs/policy.go new file mode 100644 index 00000000..2eab6f7b --- /dev/null +++ b/internal/web/actions/default/servers/accesslogs/policy.go @@ -0,0 +1,36 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package ipbox + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/accesslogs/policyutils" + "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" +) + +type PolicyAction struct { + actionutils.ParentAction +} + +func (this *PolicyAction) Init() { + this.Nav("", "", "policy") +} + +func (this *PolicyAction) RunGet(params struct { + PolicyId int64 +}) { + err := policyutils.InitPolicy(this.Parent(), params.PolicyId) + if err != nil { + this.ErrorPage(err) + return + } + + var policyMap = this.Data.GetMap("policy") + if policyMap.GetString("type") == serverconfigs.AccessLogStorageTypeSyslog { + this.Data["syslogPriorityName"] = serverconfigs.FindAccessLogSyslogStoragePriorityName(policyMap.GetMap("options").GetInt("priority")) + } else { + this.Data["syslogPriorityName"] = "" + } + + this.Show() +} diff --git a/internal/web/actions/default/servers/accesslogs/policyutils/utils.go b/internal/web/actions/default/servers/accesslogs/policyutils/utils.go new file mode 100644 index 00000000..54953685 --- /dev/null +++ b/internal/web/actions/default/servers/accesslogs/policyutils/utils.go @@ -0,0 +1,49 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package policyutils + +import ( + "encoding/json" + "errors" + "github.com/TeaOSLab/EdgeAdmin/internal/rpc" + "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" + "github.com/iwind/TeaGo/types" +) + +// InitPolicy 初始化访问日志策略 +func InitPolicy(parent *actionutils.ParentAction, policyId int64) error { + rpcClient, err := rpc.SharedRPC() + if err != nil { + return err + } + policyResp, err := rpcClient.HTTPAccessLogPolicyRPC().FindEnabledHTTPAccessLogPolicy(parent.AdminContext(), &pb.FindEnabledHTTPAccessLogPolicyRequest{HttpAccessLogPolicyId: policyId}) + if err != nil { + return err + } + var policy = policyResp.HttpAccessLogPolicy + if policy == nil { + return errors.New("can not find policy '" + types.String(policyId) + "'") + } + + var options = maps.Map{} + if len(policy.OptionsJSON) > 0 { + err = json.Unmarshal(policy.OptionsJSON, &options) + if err != nil { + return err + } + } + + parent.Data["policy"] = maps.Map{ + "id": policy.Id, + "name": policy.Name, + "type": policy.Type, + "typeName": serverconfigs.FindAccessLogStorageTypeName(policy.Type), + "isOn": policy.IsOn, + "isPublic": policy.IsPublic, + "options": options, + } + return nil +} diff --git a/internal/web/actions/default/servers/accesslogs/test.go b/internal/web/actions/default/servers/accesslogs/test.go new file mode 100644 index 00000000..47cf62c5 --- /dev/null +++ b/internal/web/actions/default/servers/accesslogs/test.go @@ -0,0 +1,57 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package ipbox + +import ( + "encoding/json" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/accesslogs/policyutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/actions" +) + +type TestAction struct { + actionutils.ParentAction +} + +func (this *TestAction) Init() { + this.Nav("", "", "test") +} + +func (this *TestAction) RunGet(params struct { + PolicyId int64 +}) { + err := policyutils.InitPolicy(this.Parent(), params.PolicyId) + if err != nil { + this.ErrorPage(err) + return + } + + this.Show() +} + +func (this *TestAction) RunPost(params struct { + PolicyId int64 + BodyJSON []byte + + Must *actions.Must +}) { + defer this.CreateLogInfo("测试向访问日志策略 %d 写入数据", params.PolicyId) + + var accessLog = &pb.HTTPAccessLog{} + err := json.Unmarshal(params.BodyJSON, accessLog) + if err != nil { + this.Fail("发送内容不是有效的JSON:" + err.Error()) + } + + _, err = this.RPC().HTTPAccessLogPolicyRPC().WriteHTTPAccessLogPolicy(this.AdminContext(), &pb.WriteHTTPAccessLogPolicyRequest{ + HttpAccessLogPolicyId: params.PolicyId, + HttpAccessLog: accessLog, + }) + if err != nil { + this.Fail("发送失败:" + err.Error()) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/servers/accesslogs/update.go b/internal/web/actions/default/servers/accesslogs/update.go new file mode 100644 index 00000000..f686584e --- /dev/null +++ b/internal/web/actions/default/servers/accesslogs/update.go @@ -0,0 +1,195 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package ipbox + +import ( + "encoding/json" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/accesslogs/policyutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" + "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/cmd" +) + +type UpdateAction struct { + actionutils.ParentAction +} + +func (this *UpdateAction) Init() { + this.Nav("", "", "update") +} + +func (this *UpdateAction) RunGet(params struct { + PolicyId int64 +}) { + err := policyutils.InitPolicy(this.Parent(), params.PolicyId) + if err != nil { + this.ErrorPage(err) + return + } + + this.Data["types"] = serverconfigs.FindAllAccessLogStorageTypes() + this.Data["syslogPriorities"] = serverconfigs.AccessLogSyslogStoragePriorities + + this.Show() +} + +func (this *UpdateAction) RunPost(params struct { + PolicyId int64 + Name string + + // file + FilePath string + FileAutoCreate bool + + // es + EsEndpoint string + EsIndex string + EsMappingType string + EsUsername string + EsPassword string + + // mysql + MysqlHost string + MysqlPort int + MysqlUsername string + MysqlPassword string + MysqlDatabase string + MysqlTable string + MysqlLogField string + + // tcp + TcpNetwork string + TcpAddr string + + // syslog + SyslogProtocol string + SyslogServerAddr string + SyslogServerPort int + SyslogSocket string + SyslogTag string + SyslogPriority int + + // command + CommandCommand string + CommandArgs string + CommandDir string + + IsOn bool + IsPublic bool + + Must *actions.Must + CSRF *actionutils.CSRF +}) { + defer this.CreateLogInfo("修改访问日志策略 %d", params.PolicyId) + + policyResp, err := this.RPC().HTTPAccessLogPolicyRPC().FindEnabledHTTPAccessLogPolicy(this.AdminContext(), &pb.FindEnabledHTTPAccessLogPolicyRequest{HttpAccessLogPolicyId: params.PolicyId}) + if err != nil { + this.ErrorPage(err) + return + } + var policy = policyResp.HttpAccessLogPolicy + if policy == nil { + this.Fail("找不到要修改的策略") + return + } + + params.Must. + Field("name", params.Name). + Require("请输入日志策略的名称") + + var options interface{} = nil + switch policy.Type { + case serverconfigs.AccessLogStorageTypeFile: + params.Must. + Field("filePath", params.FilePath). + Require("请输入日志文件路径") + + storage := new(serverconfigs.AccessLogFileStorageConfig) + storage.Path = params.FilePath + storage.AutoCreate = params.FileAutoCreate + options = storage + case serverconfigs.AccessLogStorageTypeES: + params.Must. + Field("esEndpoint", params.EsEndpoint). + Require("请输入Endpoint"). + Field("esIndex", params.EsIndex). + Require("请输入Index名称"). + Field("esMappingType", params.EsMappingType). + Require("请输入Mapping名称") + + storage := new(serverconfigs.AccessLogESStorageConfig) + storage.Endpoint = params.EsEndpoint + storage.Index = params.EsIndex + storage.MappingType = params.EsMappingType + storage.Username = params.EsUsername + storage.Password = params.EsPassword + options = storage + case serverconfigs.AccessLogStorageTypeTCP: + params.Must. + Field("tcpNetwork", params.TcpNetwork). + Require("请选择网络协议"). + Field("tcpAddr", params.TcpAddr). + Require("请输入网络地址") + + storage := new(serverconfigs.AccessLogTCPStorageConfig) + storage.Network = params.TcpNetwork + storage.Addr = params.TcpAddr + options = storage + case serverconfigs.AccessLogStorageTypeSyslog: + switch params.SyslogProtocol { + case serverconfigs.AccessLogSyslogStorageProtocolTCP, serverconfigs.AccessLogSyslogStorageProtocolUDP: + params.Must. + Field("syslogServerAddr", params.SyslogServerAddr). + Require("请输入网络地址") + case serverconfigs.AccessLogSyslogStorageProtocolSocket: + params.Must. + Field("syslogSocket", params.SyslogSocket). + Require("请输入Socket路径") + } + + storage := new(serverconfigs.AccessLogSyslogStorageConfig) + storage.Protocol = params.SyslogProtocol + storage.ServerAddr = params.SyslogServerAddr + storage.ServerPort = params.SyslogServerPort + storage.Socket = params.SyslogSocket + storage.Tag = params.SyslogTag + storage.Priority = params.SyslogPriority + options = storage + case serverconfigs.AccessLogStorageTypeCommand: + params.Must. + Field("commandCommand", params.CommandCommand). + Require("请输入可执行命令") + + storage := new(serverconfigs.AccessLogCommandStorageConfig) + storage.Command = params.CommandCommand + storage.Args = cmd.ParseArgs(params.CommandArgs) + storage.Dir = params.CommandDir + options = storage + } + + if options == nil { + this.Fail("找不到选择的存储类型") + } + + optionsJSON, err := json.Marshal(options) + if err != nil { + this.ErrorPage(err) + return + } + _, err = this.RPC().HTTPAccessLogPolicyRPC().UpdateHTTPAccessLogPolicy(this.AdminContext(), &pb.UpdateHTTPAccessLogPolicyRequest{ + HttpAccessLogPolicyId: params.PolicyId, + Name: params.Name, + OptionsJSON: optionsJSON, + CondsJSON: nil, // TODO + IsOn: params.IsOn, + IsPublic: params.IsPublic, + }) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/servers/server/settings/accessLog/index.go b/internal/web/actions/default/servers/server/settings/accessLog/index.go index cc46e2c4..1764c671 100644 --- a/internal/web/actions/default/servers/server/settings/accessLog/index.go +++ b/internal/web/actions/default/servers/server/settings/accessLog/index.go @@ -7,7 +7,6 @@ import ( "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" "github.com/iwind/TeaGo/actions" - "github.com/iwind/TeaGo/maps" ) type IndexAction struct { @@ -31,22 +30,6 @@ func (this *IndexAction) RunGet(params struct { this.Data["webId"] = webConfig.Id this.Data["accessLogConfig"] = webConfig.AccessLogRef - // 可选的缓存策略 - policiesResp, err := this.RPC().HTTPAccessLogPolicyRPC().FindAllEnabledHTTPAccessLogPolicies(this.AdminContext(), &pb.FindAllEnabledHTTPAccessLogPoliciesRequest{}) - if err != nil { - this.ErrorPage(err) - return - } - policyMaps := []maps.Map{} - for _, policy := range policiesResp.AccessLogPolicies { - policyMaps = append(policyMaps, maps.Map{ - "id": policy.Id, - "name": policy.Name, - "isOn": policy.IsOn, // TODO 这里界面上显示是否开启状态 - }) - } - this.Data["accessLogPolicies"] = policyMaps - // 通用变量 this.Data["fields"] = serverconfigs.HTTPAccessLogFields this.Data["defaultFieldCodes"] = serverconfigs.HTTPAccessLogDefaultFieldsCodes diff --git a/internal/web/actions/default/servers/server/settings/locations/accessLog/index.go b/internal/web/actions/default/servers/server/settings/locations/accessLog/index.go index 45d44fdd..ccee155e 100644 --- a/internal/web/actions/default/servers/server/settings/locations/accessLog/index.go +++ b/internal/web/actions/default/servers/server/settings/locations/accessLog/index.go @@ -6,7 +6,6 @@ import ( "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" "github.com/iwind/TeaGo/actions" - "github.com/iwind/TeaGo/maps" ) type IndexAction struct { @@ -28,22 +27,6 @@ func (this *IndexAction) RunGet(params struct { this.Data["webId"] = webConfig.Id this.Data["accessLogConfig"] = webConfig.AccessLogRef - // 可选的缓存策略 - policiesResp, err := this.RPC().HTTPAccessLogPolicyRPC().FindAllEnabledHTTPAccessLogPolicies(this.AdminContext(), &pb.FindAllEnabledHTTPAccessLogPoliciesRequest{}) - if err != nil { - this.ErrorPage(err) - return - } - policyMaps := []maps.Map{} - for _, policy := range policiesResp.AccessLogPolicies { - policyMaps = append(policyMaps, maps.Map{ - "id": policy.Id, - "name": policy.Name, - "isOn": policy.IsOn, // TODO 这里界面上显示是否开启状态 - }) - } - this.Data["accessLogPolicies"] = policyMaps - // 通用变量 this.Data["fields"] = serverconfigs.HTTPAccessLogFields this.Data["defaultFieldCodes"] = serverconfigs.HTTPAccessLogDefaultFieldsCodes diff --git a/internal/web/helpers/user_must_auth.go b/internal/web/helpers/user_must_auth.go index 7e06d5e0..203ca48c 100644 --- a/internal/web/helpers/user_must_auth.go +++ b/internal/web/helpers/user_must_auth.go @@ -194,6 +194,12 @@ func (this *userMustAuth) modules(adminId int64) []maps.Map { "url": "/servers/components/waf", "code": "waf", }, + { + "name": "日志策略", + "url": "/servers/accesslogs", + "code": "accesslog", + "isOn": teaconst.IsPlus, + }, { "name": "IP名单", "url": "/servers/iplists", diff --git a/internal/web/import.go b/internal/web/import.go index 71bfd264..479554e0 100644 --- a/internal/web/import.go +++ b/internal/web/import.go @@ -54,6 +54,7 @@ import ( // 服务相关 _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers" + _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/accesslogs" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/certs" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache" diff --git a/web/public/js/components/common/source-code-box.js b/web/public/js/components/common/source-code-box.js index 4253a464..a007a4f3 100644 --- a/web/public/js/components/common/source-code-box.js +++ b/web/public/js/components/common/source-code-box.js @@ -1,8 +1,13 @@ let sourceCodeBoxIndex = 0 Vue.component("source-code-box", { - props: ["type", "id"], + props: ["name", "type", "id", "read-only"], mounted: function () { + let readOnly = this.readOnly + if (typeof readOnly != "boolean") { + readOnly = true + } + console.log("readonly:", readOnly) // TODO let box = document.getElementById("source-code-box-" + this.index) let valueBox = document.getElementById(this.valueBoxId) let value = "" @@ -15,7 +20,7 @@ Vue.component("source-code-box", { theme: "idea", lineNumbers: true, value: "", - readOnly: true, + readOnly: readOnly, showCursorWhenSelecting: true, height: "auto", //scrollbarStyle: null, @@ -49,6 +54,6 @@ Vue.component("source-code-box", { }, template: `
- +
` }) \ No newline at end of file diff --git a/web/public/js/components/server/http-access-log-config-box.js b/web/public/js/components/server/http-access-log-config-box.js index 215d1828..0edefde7 100644 --- a/web/public/js/components/server/http-access-log-config-box.js +++ b/web/public/js/components/server/http-access-log-config-box.js @@ -1,12 +1,11 @@ Vue.component("http-access-log-config-box", { - props: ["v-access-log-config", "v-fields", "v-default-field-codes", "v-access-log-policies", "v-is-location"], + props: ["v-access-log-config", "v-fields", "v-default-field-codes", "v-is-location"], data: function () { let that = this // 初始化 setTimeout(function () { that.changeFields() - that.changePolicy() }, 100) let accessLog = { @@ -19,9 +18,6 @@ Vue.component("http-access-log-config-box", { status4: true, status5: true, - storageOnly: false, - storagePolicies: [], - firewallOnly: false } if (this.vAccessLogConfig != null) { @@ -35,9 +31,6 @@ Vue.component("http-access-log-config-box", { v.isChecked = accessLog.fields.$contains(v.code) } }) - this.vAccessLogPolicies.forEach(function (v) { - v.isChecked = accessLog.storagePolicies.$contains(v.id) - }) return { accessLog: accessLog @@ -50,13 +43,6 @@ Vue.component("http-access-log-config-box", { }).map(function (v) { return v.code }) - }, - changePolicy: function () { - this.accessLog.storagePolicies = this.vAccessLogPolicies.filter(function (v) { - return v.isChecked - }).map(function (v) { - return v.id - }) } }, template: `
@@ -110,28 +96,6 @@ Vue.component("http-access-log-config-box", {
- - 选择输出的日志策略 - - 暂时还没有缓存策略。 -
-
- - -
-
- - - - 是否只输出到日志策略 - -
- - -
-

选中表示只输出日志到日志策略,而停止默认的日志存储。

- - diff --git a/web/public/js/components/server/metric-charts.js b/web/public/js/components/server/metric-charts.js index 9cc50aad..b508a42f 100644 --- a/web/public/js/components/server/metric-charts.js +++ b/web/public/js/components/server/metric-charts.js @@ -345,17 +345,19 @@ Vue.component("metric-chart", { ] }) - // IP相关操作 - if (this.item.keys != null && this.item.keys.$contains("${remoteAddr}")) { - let that = this - chart.on("click", function (args) { - let index = that.item.keys.$indexesOf("${remoteAddr}")[0] - let value = that.stats[args.dataIndex].keys[index] - teaweb.popup("/servers/ipbox?ip=" + value, { - width: "50em", - height: "30em" + if (this.item.keys != null) { + // IP相关操作 + if (this.item.keys.$contains("${remoteAddr}")) { + let that = this + chart.on("click", function (args) { + let index = that.item.keys.$indexesOf("${remoteAddr}")[0] + let value = that.stats[args.dataIndex].keys[index] + teaweb.popup("/servers/ipbox?ip=" + value, { + width: "50em", + height: "30em" + }) }) - }) + } } }, renderTable: function (chart) { diff --git a/web/views/@default/servers/accesslogs/@menu.html b/web/views/@default/servers/accesslogs/@menu.html new file mode 100644 index 00000000..53299f35 --- /dev/null +++ b/web/views/@default/servers/accesslogs/@menu.html @@ -0,0 +1,6 @@ + + 策略列表 + [创建策略] + | + + \ No newline at end of file diff --git a/web/views/@default/servers/accesslogs/@policy_menu.html b/web/views/@default/servers/accesslogs/@policy_menu.html new file mode 100644 index 00000000..e86218fd --- /dev/null +++ b/web/views/@default/servers/accesslogs/@policy_menu.html @@ -0,0 +1,7 @@ + + 策略列表 + | + "{{policy.name}}"详情 + 测试 + 修改 + \ No newline at end of file diff --git a/web/views/@default/servers/accesslogs/createPopup.html b/web/views/@default/servers/accesslogs/createPopup.html new file mode 100644 index 00000000..b31d600f --- /dev/null +++ b/web/views/@default/servers/accesslogs/createPopup.html @@ -0,0 +1,216 @@ +{$layout "layout_popup"} + +

创建策略

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
策略名称 * + +
存储类型 * + +
日志文件路径 * + +

+ 存储日志的文件路径,文件名中支持变量: + 年:${year} + 月:${month} + 周:${week} + 日:${day} + 时:${hour} + 分:${minute} + 秒:${second} + 年月日:${date},比如/var/log/web-access-${date}.log。 +

+
是否自动创建目录 +
+ + +
+

选中后,如果文件目录不存在时可以自动创建。

+
Endpoint * + +

ES HTTP接口地址,类似于192.168.1.100:9200

+
Index * + +

Index名称,支持变量: + 年:${year} + 月:${month} + 周:${week} + 日:${day} + 时:${hour} + 分:${minute} + 秒:${second} + 年月日:${date}

+
Mapping Type * + +

Mapping名称,支持变量: + 年:${year} + 月:${month} + 周:${week} + 日:${day} + 时:${hour} + 分:${minute} + 秒:${second} + 年月日:${date}

+
认证用户名 + +

配置了认证后才需要填写。

+
认证密码 + +

配置了认证后才需要填写。

+
网络协议 * + +
网络地址 * + +

接收日志的网络地址

+
网络协议 + +
网络地址 * + +

IP地址或主机名,不包括端口。

+
端口 + +
Socket路径 * + +
标签(Tag) + +

选填项。

+
优先级(Priority) + +

选填项。

+
可执行命令 * + +

不带参数的可执行命令地址

+
参数 + +

执行命令需要的参数

+
工作目录 + +

命令执行所在的工作目录

+
是否公用 + +

选中后表示自动将此策略应用于所有集群,同时只会有一个公用策略。

+
+ +
\ No newline at end of file diff --git a/web/views/@default/servers/accesslogs/createPopup.js b/web/views/@default/servers/accesslogs/createPopup.js new file mode 100644 index 00000000..737c356b --- /dev/null +++ b/web/views/@default/servers/accesslogs/createPopup.js @@ -0,0 +1,8 @@ +Tea.context(function () { + this.type = "" + + /** + * syslog + */ + this.syslogProtocol = "none" +}) \ No newline at end of file diff --git a/web/views/@default/servers/accesslogs/index.html b/web/views/@default/servers/accesslogs/index.html new file mode 100644 index 00000000..96b11b09 --- /dev/null +++ b/web/views/@default/servers/accesslogs/index.html @@ -0,0 +1,44 @@ +{$layout} +{$template "menu"} + +

暂时还没有访问日志策略。

+ + + + + + + + + + + + + + + + + + +
策略名称类型主要参数状态操作
{{policy.name}} +
+ 公用 +
+
{{policy.typeName}} + - + Endpoint: {{policy.options.endpoint}} + 文件路径:{{policy.options.path}} + 网络地址:{{policy.options.addr}} + 可执行命令:{{policy.options.command}} + + TCP {{policy.options.serverAddr}} + UDP {{policy.options.serverAddr}} + SOCK {{policy.options.socket}} + + + + + 详情   删除 +
+ +
\ No newline at end of file diff --git a/web/views/@default/servers/accesslogs/index.js b/web/views/@default/servers/accesslogs/index.js new file mode 100644 index 00000000..2964c1e0 --- /dev/null +++ b/web/views/@default/servers/accesslogs/index.js @@ -0,0 +1,20 @@ +Tea.context(function () { + this.createPolicy = function () { + teaweb.popup(Tea.url(".createPopup", {}), { + height: "24em", + callback: NotifyReloadSuccess("保存成功") + }) + } + + this.deletePolicy = function (policyId) { + teaweb.confirm("确定要删除这个日志策略吗?", function () { + this.$post(".delete") + .params({ + policyId: policyId + }) + .success(function () { + teaweb.successRefresh("保存成功") + }) + }) + } +}) \ No newline at end of file diff --git a/web/views/@default/servers/accesslogs/policy.html b/web/views/@default/servers/accesslogs/policy.html new file mode 100644 index 00000000..01ad8b2a --- /dev/null +++ b/web/views/@default/servers/accesslogs/policy.html @@ -0,0 +1,173 @@ +{$layout} +{$template "policy_menu"} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
策略名称 + {{policy.name}} +
状态 + +
存储类型 + {{policy.typeName}} +
日志文件路径 + {{policy.options.path}} +
是否自动创建目录 + Y + N +
Endpoint + {{policy.options.endpoint}} +
Index + {{policy.options.index}} +
Mapping Type + {{policy.options.mappingType}} +
认证用户名 + {{policy.options.username}} + 没有填写。 +
认证密码 + {{policy.options.password}} + 没有填写。 +
网络协议 + {{policy.options.network.toUpperCase()}} +
网络地址 + {{policy.options.addr}} +
网络协议 + [无] + TCP + UDP + Unix Socket +
网络地址 + {{policy.options.serverAddr}} +
端口 + {{policy.options.serverPort}} +
Socket路径 + {{policy.options.socket}} +
标签(Tag) + {{policy.options.tag}} + 没有设置 +
优先级(Priority) + {{syslogPriorityName}} +
可执行命令 + {{policy.options.command}} +
参数 +
+ {{arg}} +
+ 没有设置参数。 +
工作目录 + {{policy.options.dir}} + 没有设置工作目录。 +
是否公用 + Y + N +
\ No newline at end of file diff --git a/web/views/@default/servers/accesslogs/test.html b/web/views/@default/servers/accesslogs/test.html new file mode 100644 index 00000000..faa235fc --- /dev/null +++ b/web/views/@default/servers/accesslogs/test.html @@ -0,0 +1,18 @@ +{$layout "layout"} +{$template "/code_editor"} +{$template "policy_menu"} + +
+ + + + + + +
发送内容 + { + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36" +} +
+ +
\ No newline at end of file diff --git a/web/views/@default/servers/accesslogs/test.js b/web/views/@default/servers/accesslogs/test.js new file mode 100644 index 00000000..c4473fc4 --- /dev/null +++ b/web/views/@default/servers/accesslogs/test.js @@ -0,0 +1,5 @@ +Tea.context(function () { + this.success = function () { + teaweb.success("发送成功") + } +}) \ No newline at end of file diff --git a/web/views/@default/servers/accesslogs/update.html b/web/views/@default/servers/accesslogs/update.html new file mode 100644 index 00000000..30de3fca --- /dev/null +++ b/web/views/@default/servers/accesslogs/update.html @@ -0,0 +1,222 @@ +{$layout} +{$template "policy_menu"} + +

修改策略

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
策略名称 * + +
存储类型 * + {{policy.typeName}} +
日志文件路径 * + +

+ 存储日志的文件路径,文件名中支持变量: + 年:${year} + 月:${month} + 周:${week} + 日:${day} + 时:${hour} + 分:${minute} + 秒:${second} + 年月日:${date},比如/var/log/web-access-${date}.log。 +

+
是否自动创建目录 +
+ + +
+

选中后,如果文件目录不存在时可以自动创建。

+
Endpoint * + +

ES HTTP接口地址,类似于192.168.1.100:9200

+
Index * + +

Index名称,支持变量: + 年:${year} + 月:${month} + 周:${week} + 日:${day} + 时:${hour} + 分:${minute} + 秒:${second} + 年月日:${date}

+
Mapping Type * + +

Mapping名称,支持变量: + 年:${year} + 月:${month} + 周:${week} + 日:${day} + 时:${hour} + 分:${minute} + 秒:${second} + 年月日:${date}

+
认证用户名 + +

配置了认证后才需要填写。

+
认证密码 + +

配置了认证后才需要填写。

+
网络协议 * + +
网络地址 * + +

接收日志的网络地址

+
网络协议 + +
网络地址 * + +

IP地址或主机名,不包括端口。

+
端口 + +
Socket路径 * + +
标签(Tag) + +

选填项。

+
优先级(Priority) + +

选填项。

+
可执行命令 * + +

不带参数的可执行命令地址

+
参数 + +

执行命令需要的参数

+
工作目录 + +

命令执行所在的工作目录

+
是否公用 + +

选中后表示自动将此策略应用于所有集群,同时只会有一个公用策略。

+
是否启用 + +
+ +
\ No newline at end of file diff --git a/web/views/@default/servers/accesslogs/update.js b/web/views/@default/servers/accesslogs/update.js new file mode 100644 index 00000000..ba3b4a69 --- /dev/null +++ b/web/views/@default/servers/accesslogs/update.js @@ -0,0 +1,24 @@ +Tea.context(function () { + this.success = NotifySuccess("html:保存成功
新的配置将会在1分钟之内生效", ".policy", {policyId: this.policy.id}) + + this.type = this.policy.type + + + /** + * syslog + */ + this.syslogProtocol = this.policy.options.protocol + + /** + * command + */ + if (this.policy.type == "command") { + let args = this.policy.options.args + if (args == null) { + args = "" + } else { + args = args.join(" ") + } + this.policy.options.args = args + } +}) \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/accessLog/index.html b/web/views/@default/servers/server/settings/accessLog/index.html index 67da3909..02a20c31 100644 --- a/web/views/@default/servers/server/settings/accessLog/index.html +++ b/web/views/@default/servers/server/settings/accessLog/index.html @@ -8,8 +8,7 @@ + :v-default-field-codes="defaultFieldCodes"> \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/locations/accessLog/index.html b/web/views/@default/servers/server/settings/locations/accessLog/index.html index 2002b272..20276982 100644 --- a/web/views/@default/servers/server/settings/locations/accessLog/index.html +++ b/web/views/@default/servers/server/settings/locations/accessLog/index.html @@ -13,7 +13,6 @@ :v-access-log-config="accessLogConfig" :v-fields="fields" :v-default-field-codes="defaultFieldCodes" - :v-access-log-policies="accessLogPolicies" :v-is-location="true">