diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go index d4bf2157..4688fd84 100644 --- a/internal/rpc/rpc_client.go +++ b/internal/rpc/rpc_client.go @@ -228,6 +228,10 @@ func (this *RPCClient) HTTPFastcgiRPC() pb.HTTPFastcgiServiceClient { return pb.NewHTTPFastcgiServiceClient(this.pickConn()) } +func (this *RPCClient) HTTPAuthPolicyRPC() pb.HTTPAuthPolicyServiceClient { + return pb.NewHTTPAuthPolicyServiceClient(this.pickConn()) +} + func (this *RPCClient) SSLCertRPC() pb.SSLCertServiceClient { return pb.NewSSLCertServiceClient(this.pickConn()) } diff --git a/internal/web/actions/default/servers/server/settings/access/createPopup.go b/internal/web/actions/default/servers/server/settings/access/createPopup.go index 4642a31a..81758bb0 100644 --- a/internal/web/actions/default/servers/server/settings/access/createPopup.go +++ b/internal/web/actions/default/servers/server/settings/access/createPopup.go @@ -3,7 +3,10 @@ package access 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" ) @@ -16,12 +19,105 @@ func (this *CreatePopupAction) Init() { } func (this *CreatePopupAction) RunGet(params struct{}) { + this.Data["authTypes"] = serverconfigs.FindAllHTTPAuthTypes() this.Show() } func (this *CreatePopupAction) RunPost(params struct { + Name string + Type string + + // BasicAuth + HttpAuthBasicAuthUsersJSON []byte + BasicAuthRealm string + BasicAuthCharset string + + // SubRequest + SubRequestURL string + SubRequestMethod string + SubRequestFollowRequest bool + Must *actions.Must CSRF *actionutils.CSRF }) { + params.Must. + Field("name", params.Name). + Require("请输入名称"). + Field("type", params.Type). + Require("请输入认证类型") + var ref = &serverconfigs.HTTPAuthPolicyRef{IsOn: true} + var paramsJSON []byte + + switch params.Type { + case serverconfigs.HTTPAuthTypeBasicAuth: + users := []*serverconfigs.HTTPAuthBasicMethodUser{} + err := json.Unmarshal(params.HttpAuthBasicAuthUsersJSON, &users) + if err != nil { + this.ErrorPage(err) + return + } + if len(users) == 0 { + this.Fail("请添加至少一个用户") + } + method := &serverconfigs.HTTPAuthBasicMethod{ + Users: users, + Realm: params.BasicAuthRealm, + Charset: params.BasicAuthCharset, + } + methodJSON, err := json.Marshal(method) + if err != nil { + this.ErrorPage(err) + return + } + + paramsJSON = methodJSON + case serverconfigs.HTTPAuthTypeSubRequest: + params.Must.Field("subRequestURL", params.SubRequestURL). + Require("请输入子请求URL") + if params.SubRequestFollowRequest { + params.SubRequestMethod = "" + } + method := &serverconfigs.HTTPAuthSubRequestMethod{ + URL: params.SubRequestURL, + Method: params.SubRequestMethod, + } + methodJSON, err := json.Marshal(method) + if err != nil { + this.ErrorPage(err) + return + } + paramsJSON = methodJSON + default: + this.Fail("不支持的认证类型'" + params.Type + "'") + } + + var paramsMap map[string]interface{} + err := json.Unmarshal(paramsJSON, ¶msMap) + if err != nil { + this.ErrorPage(err) + return + } + + createResp, err := this.RPC().HTTPAuthPolicyRPC().CreateHTTPAuthPolicy(this.AdminContext(), &pb.CreateHTTPAuthPolicyRequest{ + Name: params.Name, + Type: params.Type, + ParamsJSON: paramsJSON, + }) + if err != nil { + this.ErrorPage(err) + return + } + defer this.CreateLogInfo("创建HTTP认证 %d", createResp.HttpAuthPolicyId) + ref.AuthPolicyId = createResp.HttpAuthPolicyId + ref.AuthPolicy = &serverconfigs.HTTPAuthPolicy{ + Id: createResp.HttpAuthPolicyId, + Name: params.Name, + IsOn: true, + Type: params.Type, + Params: paramsMap, + } + + this.Data["policyRef"] = ref + this.Success() } diff --git a/internal/web/actions/default/servers/server/settings/access/index.go b/internal/web/actions/default/servers/server/settings/access/index.go index 568f4567..bca6dada 100644 --- a/internal/web/actions/default/servers/server/settings/access/index.go +++ b/internal/web/actions/default/servers/server/settings/access/index.go @@ -1,8 +1,12 @@ package access import ( + "encoding/json" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" + "github.com/iwind/TeaGo/actions" ) type IndexAction struct { @@ -28,3 +32,45 @@ func (this *IndexAction) RunGet(params struct { this.Show() } + +func (this *IndexAction) RunPost(params struct { + WebId int64 + AuthJSON []byte + + Must *actions.Must + CSRF *actionutils.CSRF +}) { + defer this.CreateLogInfo("修改Web %d 的认证设置", params.WebId) + + var authConfig = &serverconfigs.HTTPAuthConfig{} + err := json.Unmarshal(params.AuthJSON, authConfig) + if err != nil { + this.ErrorPage(err) + return + } + err = authConfig.Init() + if err != nil { + this.Fail("配置校验失败:" + err.Error()) + } + + // 保存之前删除多于的配置信息 + for _, ref := range authConfig.PolicyRefs { + ref.AuthPolicy = nil + } + + configJSON, err := json.Marshal(authConfig) + if err != nil { + this.ErrorPage(err) + return + } + _, err = this.RPC().HTTPWebRPC().UpdateHTTPWebAuth(this.AdminContext(), &pb.UpdateHTTPWebAuthRequest{ + WebId: params.WebId, + AuthJSON: configJSON, + }) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/servers/server/settings/access/init.go b/internal/web/actions/default/servers/server/settings/access/init.go index 2f51fe60..588a6cd7 100644 --- a/internal/web/actions/default/servers/server/settings/access/init.go +++ b/internal/web/actions/default/servers/server/settings/access/init.go @@ -13,7 +13,7 @@ func init() { Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)). Helper(serverutils.NewServerHelper()). Prefix("/servers/server/settings/access"). - Get("", new(IndexAction)). + GetPost("", new(IndexAction)). GetPost("/createPopup", new(CreatePopupAction)). GetPost("/updatePopup", new(UpdatePopupAction)). EndAll() diff --git a/internal/web/actions/default/servers/server/settings/access/updatePopup.go b/internal/web/actions/default/servers/server/settings/access/updatePopup.go index 5dfbf14a..0453c314 100644 --- a/internal/web/actions/default/servers/server/settings/access/updatePopup.go +++ b/internal/web/actions/default/servers/server/settings/access/updatePopup.go @@ -2,7 +2,14 @@ package access -import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" +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/maps" +) type UpdatePopupAction struct { actionutils.ParentAction @@ -12,6 +19,149 @@ func (this *UpdatePopupAction) Init() { this.Nav("", "", "") } -func (this *UpdatePopupAction) RunGet(params struct{}) { +func (this *UpdatePopupAction) RunGet(params struct { + PolicyId int64 +}) { + this.Data["authTypes"] = serverconfigs.FindAllHTTPAuthTypes() + + policyResp, err := this.RPC().HTTPAuthPolicyRPC().FindEnabledHTTPAuthPolicy(this.AdminContext(), &pb.FindEnabledHTTPAuthPolicyRequest{HttpAuthPolicyId: params.PolicyId}) + if err != nil { + this.ErrorPage(err) + return + } + policy := policyResp.HttpAuthPolicy + if policy == nil { + this.NotFound("httpAuthPolicy", params.PolicyId) + return + } + + var authParams = map[string]interface{}{} + if len(policy.ParamsJSON) > 0 { + err = json.Unmarshal(policy.ParamsJSON, &authParams) + if err != nil { + this.ErrorPage(err) + return + } + } + this.Data["policy"] = maps.Map{ + "id": policy.Id, + "isOn": policy.IsOn, + "name": policy.Name, + "type": policy.Type, + "params": authParams, + } + this.Show() } + +func (this *UpdatePopupAction) RunPost(params struct { + PolicyId int64 + + Name string + IsOn bool + + // BasicAuth + HttpAuthBasicAuthUsersJSON []byte + BasicAuthRealm string + BasicAuthCharset string + + // SubRequest + SubRequestURL string + SubRequestMethod string + SubRequestFollowRequest bool + + Must *actions.Must + CSRF *actionutils.CSRF +}) { + defer this.CreateLogInfo("修改HTTP认证 %d", params.PolicyId) + + policyResp, err := this.RPC().HTTPAuthPolicyRPC().FindEnabledHTTPAuthPolicy(this.AdminContext(), &pb.FindEnabledHTTPAuthPolicyRequest{HttpAuthPolicyId: params.PolicyId}) + if err != nil { + this.ErrorPage(err) + return + } + policy := policyResp.HttpAuthPolicy + if policy == nil { + this.NotFound("httpAuthPolicy", params.PolicyId) + return + } + policyType := policy.Type + + params.Must. + Field("name", params.Name). + Require("请输入名称") + + var ref = &serverconfigs.HTTPAuthPolicyRef{IsOn: true} + var paramsJSON []byte + + switch policyType { + case serverconfigs.HTTPAuthTypeBasicAuth: + users := []*serverconfigs.HTTPAuthBasicMethodUser{} + err := json.Unmarshal(params.HttpAuthBasicAuthUsersJSON, &users) + if err != nil { + this.ErrorPage(err) + return + } + if len(users) == 0 { + this.Fail("请添加至少一个用户") + } + method := &serverconfigs.HTTPAuthBasicMethod{ + Users: users, + Realm: params.BasicAuthRealm, + Charset: params.BasicAuthCharset, + } + methodJSON, err := json.Marshal(method) + if err != nil { + this.ErrorPage(err) + return + } + + paramsJSON = methodJSON + case serverconfigs.HTTPAuthTypeSubRequest: + params.Must.Field("subRequestURL", params.SubRequestURL). + Require("请输入子请求URL") + if params.SubRequestFollowRequest { + params.SubRequestMethod = "" + } + method := &serverconfigs.HTTPAuthSubRequestMethod{ + URL: params.SubRequestURL, + Method: params.SubRequestMethod, + } + methodJSON, err := json.Marshal(method) + if err != nil { + this.ErrorPage(err) + return + } + paramsJSON = methodJSON + default: + this.Fail("不支持的认证类型'" + policyType + "'") + } + + var paramsMap map[string]interface{} + err = json.Unmarshal(paramsJSON, ¶msMap) + if err != nil { + this.ErrorPage(err) + return + } + + _, err = this.RPC().HTTPAuthPolicyRPC().UpdateHTTPAuthPolicy(this.AdminContext(), &pb.UpdateHTTPAuthPolicyRequest{ + HttpAuthPolicyId: params.PolicyId, + Name: params.Name, + ParamsJSON: paramsJSON, + IsOn: params.IsOn, + }) + if err != nil { + this.ErrorPage(err) + return + } + ref.AuthPolicy = &serverconfigs.HTTPAuthPolicy{ + Id: params.PolicyId, + Name: params.Name, + IsOn: params.IsOn, + Type: policyType, + Params: paramsMap, + } + + this.Data["policyRef"] = ref + this.Success() +} diff --git a/internal/web/actions/default/servers/server/settings/locations/access/index.go b/internal/web/actions/default/servers/server/settings/locations/access/index.go index 36a5c0e6..96f27747 100644 --- a/internal/web/actions/default/servers/server/settings/locations/access/index.go +++ b/internal/web/actions/default/servers/server/settings/locations/access/index.go @@ -1,7 +1,12 @@ package access import ( + "encoding/json" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" + "github.com/iwind/TeaGo/actions" ) type IndexAction struct { @@ -9,12 +14,63 @@ type IndexAction struct { } func (this *IndexAction) Init() { + this.Nav("", "setting", "index") + this.SecondMenu("access") } func (this *IndexAction) RunGet(params struct { - ServerId int64 + LocationId int64 }) { - // TODO + webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId) + if err != nil { + this.ErrorPage(err) + return + } + + this.Data["webId"] = webConfig.Id + this.Data["authConfig"] = webConfig.Auth this.Show() } + +func (this *IndexAction) RunPost(params struct { + WebId int64 + AuthJSON []byte + + Must *actions.Must + CSRF *actionutils.CSRF +}) { + defer this.CreateLogInfo("修改Web %d 的认证设置", params.WebId) + + var authConfig = &serverconfigs.HTTPAuthConfig{} + err := json.Unmarshal(params.AuthJSON, authConfig) + if err != nil { + this.ErrorPage(err) + return + } + err = authConfig.Init() + if err != nil { + this.Fail("配置校验失败:" + err.Error()) + } + + // 保存之前删除多于的配置信息 + for _, ref := range authConfig.PolicyRefs { + ref.AuthPolicy = nil + } + + configJSON, err := json.Marshal(authConfig) + if err != nil { + this.ErrorPage(err) + return + } + _, err = this.RPC().HTTPWebRPC().UpdateHTTPWebAuth(this.AdminContext(), &pb.UpdateHTTPWebAuthRequest{ + WebId: params.WebId, + AuthJSON: configJSON, + }) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/servers/server/settings/locations/access/init.go b/internal/web/actions/default/servers/server/settings/locations/access/init.go index 53958c11..86cf0a22 100644 --- a/internal/web/actions/default/servers/server/settings/locations/access/init.go +++ b/internal/web/actions/default/servers/server/settings/locations/access/init.go @@ -16,7 +16,7 @@ func init() { Helper(serverutils.NewServerHelper()). Data("tinyMenuItem", "access"). Prefix("/servers/server/settings/locations/access"). - Get("", new(IndexAction)). + GetPost("", new(IndexAction)). EndAll() }) } diff --git a/web/public/js/components/server/http-auth-basic-auth-user-box.js b/web/public/js/components/server/http-auth-basic-auth-user-box.js new file mode 100644 index 00000000..90a1ff93 --- /dev/null +++ b/web/public/js/components/server/http-auth-basic-auth-user-box.js @@ -0,0 +1,101 @@ +// 基本认证用户配置 +Vue.component("http-auth-basic-auth-user-box", { + props: ["v-users"], + data: function () { + let users = this.vUsers + if (users == null) { + users = [] + } + return { + users: users, + isAdding: false, + updatingIndex: -1, + + username: "", + password: "" + } + }, + methods: { + add: function () { + this.isAdding = true + this.username = "" + this.password = "" + + let that = this + setTimeout(function () { + that.$refs.username.focus() + }, 100) + }, + cancel: function () { + this.isAdding = false + this.updatingIndex = -1 + }, + confirm: function () { + let that = this + if (this.username.length == 0) { + teaweb.warn("请输入用户名", function () { + that.$refs.username.focus() + }) + return + } + if (this.password.length == 0) { + teaweb.warn("请输入密码", function () { + that.$refs.password.focus() + }) + return + } + if (this.updatingIndex < 0) { + this.users.push({ + username: this.username, + password: this.password + }) + } else { + this.users[this.updatingIndex].username = this.username + this.users[this.updatingIndex].password = this.password + } + this.cancel() + }, + update: function (index, user) { + this.updatingIndex = index + + this.isAdding = true + this.username = user.username + this.password = user.password + + let that = this + setTimeout(function () { + that.$refs.username.focus() + }, 100) + }, + remove: function (index) { + this.users.$remove(index) + } + }, + template: `
` +}) \ No newline at end of file diff --git a/web/public/js/components/server/http-auth-config-box.js b/web/public/js/components/server/http-auth-config-box.js index 621a3606..6d97db43 100644 --- a/web/public/js/components/server/http-auth-config-box.js +++ b/web/public/js/components/server/http-auth-config-box.js @@ -25,23 +25,36 @@ Vue.component("http-auth-config-box", { teaweb.popup("/servers/server/settings/access/createPopup", { callback: function (resp) { that.authConfig.policyRefs.push(resp.data.policyRef) - } + }, + height: "28em" }) }, update: function (index, policyId) { let that = this teaweb.popup("/servers/server/settings/access/updatePopup?policyId=" + policyId, { callback: function (resp) { - Vue.set(that.authConfig.policyRefs, index, resp.data.policyRef) - } + teaweb.success("保存成功", function () { + teaweb.reload() + }) + }, + height: "28em" }) }, - delete: function (index) { - that.authConfig.policyRefs.$remove(index) + remove: function (index) { + this.authConfig.policyRefs.$remove(index) + }, + methodName: function (methodType) { + switch (methodType) { + case "basicAuth": + return "BasicAuth" + case "subRequest": + return "子请求" + } + return "" } }, template: `