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: `
+ +
+
+ {{user.username}} + +
+
+
+
+
+
+ +
+
+ +
+
+   + +
+
+
+
+ +
+
` +}) \ 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: `
- + @@ -57,24 +70,43 @@ Vue.component("http-auth-config-box", {
- -
+ +
+

认证方式

- + + - + - + + + + +
认证方法名称认证方法 参数 状态 操作
{{ref.authPolicy.name}} + {{methodName(ref.authPolicy.type)}} + + {{ref.authPolicy.params.users.length}}个用户 + + [{{ref.authPolicy.params.method}}] + {{ref.authPolicy.params.url}} + + + + + 修改   + 删除 +
- +
` diff --git a/web/views/@default/servers/server/settings/access/createPopup.html b/web/views/@default/servers/server/settings/access/createPopup.html index 0ffd23cc..220da6da 100644 --- a/web/views/@default/servers/server/settings/access/createPopup.html +++ b/web/views/@default/servers/server/settings/access/createPopup.html @@ -1,33 +1,80 @@ {$layout "layout_popup"} -

创建认证

+

创建认证方式

- +
- + - + - + + + + + + + + + + + + + - - + + + + + + + + +
名称 * - +
类型 *认证类型 * - + +

用户 * + +
+ 更多选项 +
认证领域名(Realm) + +
字符集 + +

类似于UTF-8

+
子请求URL * + +

可以是一个完整的URL,也可以是一个路径。

+
请求方法 + 同当前请求一致     + 自定义 +
+
+ +
+
diff --git a/web/views/@default/servers/server/settings/access/createPopup.js b/web/views/@default/servers/server/settings/access/createPopup.js index c8fe9515..fbd723d8 100644 --- a/web/views/@default/servers/server/settings/access/createPopup.js +++ b/web/views/@default/servers/server/settings/access/createPopup.js @@ -1,3 +1,32 @@ Tea.context(function () { this.success = NotifyPopup + + this.type = "" + this.authDescription = "" + + this.changeType = function () { + let that = this + let authType = this.authTypes.$find(function (k, v) { + return v.code == that.type + }) + if (authType != null) { + this.authDescription = authType.description + } else { + this.authDescription = "" + } + } + + /** + * 基本认证 + */ + this.moreBasicAuthOptionsVisible = false + + this.showMoreBasicAuthOptions = function () { + this.moreBasicAuthOptionsVisible = !this.moreBasicAuthOptionsVisible + } + + /** + * 子请求 + */ + this.subRequestFollowRequest = 1 }) \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/access/index.html b/web/views/@default/servers/server/settings/access/index.html index 2dbf3bcc..bfd895b9 100644 --- a/web/views/@default/servers/server/settings/access/index.html +++ b/web/views/@default/servers/server/settings/access/index.html @@ -4,6 +4,8 @@
+ + diff --git a/web/views/@default/servers/server/settings/access/index.js b/web/views/@default/servers/server/settings/access/index.js new file mode 100644 index 00000000..295a9aaf --- /dev/null +++ b/web/views/@default/servers/server/settings/access/index.js @@ -0,0 +1,3 @@ +Tea.context(function () { + this.success = NotifyReloadSuccess("保存成功") +}) \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/access/updatePopup.html b/web/views/@default/servers/server/settings/access/updatePopup.html new file mode 100644 index 00000000..c113a6b5 --- /dev/null +++ b/web/views/@default/servers/server/settings/access/updatePopup.html @@ -0,0 +1,85 @@ +{$layout "layout_popup"} + +

修改认证方式

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称 * + +
认证类型 * + {{policy.typeName}} +

+
用户 * + +
+ 更多选项 +
认证领域名(Realm) + +
字符集 + +

类似于utf-8

+
子请求URL * + +

可以是一个完整的URL,也可以是一个路径。

+
请求方法 + 同当前请求一致     + 自定义 +
+
+ +
+
是否启用
+ + +
\ No newline at end of file diff --git a/web/views/@default/servers/server/settings/access/updatePopup.js b/web/views/@default/servers/server/settings/access/updatePopup.js new file mode 100644 index 00000000..64e93738 --- /dev/null +++ b/web/views/@default/servers/server/settings/access/updatePopup.js @@ -0,0 +1,37 @@ +Tea.context(function () { + this.success = NotifyPopup + + this.type = this.policy.type + this.authDescription = "" + + this.$delay(function () { + this.changeType() + }) + + this.changeType = function () { + let that = this + let authType = this.authTypes.$find(function (k, v) { + return v.code == that.type + }) + if (authType != null) { + this.policy.typeName = authType.name + this.authDescription = authType.description + } else { + this.authDescription = "" + } + } + + /** + * 基本认证 + */ + this.moreBasicAuthOptionsVisible = false + + this.showMoreBasicAuthOptions = function () { + this.moreBasicAuthOptionsVisible = !this.moreBasicAuthOptionsVisible + } + + /** + * 子请求 + */ + this.subRequestFollowRequest = (this.policy.params.method != null && this.policy.params.method.length > 0) ? 0 : 1 +}) \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/locations/access/index.html b/web/views/@default/servers/server/settings/locations/access/index.html index bda437b6..f1f6456b 100644 --- a/web/views/@default/servers/server/settings/locations/access/index.html +++ b/web/views/@default/servers/server/settings/locations/access/index.html @@ -1,13 +1,16 @@ {$layout} - {$template "/left_menu"}
- {$template "../location_menu"} - {$template "../left_menu"} + {$template "../location_menu"} + {$template "../left_menu"} -
-
-

此功能暂未开放,敬请期待。

-
+
+
+ + + + +
+
\ No newline at end of file diff --git a/web/views/@default/servers/server/settings/locations/access/index.js b/web/views/@default/servers/server/settings/locations/access/index.js new file mode 100644 index 00000000..295a9aaf --- /dev/null +++ b/web/views/@default/servers/server/settings/locations/access/index.js @@ -0,0 +1,3 @@ +Tea.context(function () { + this.success = NotifyReloadSuccess("保存成功") +}) \ No newline at end of file