diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go index c6818677..d4bf2157 100644 --- a/internal/rpc/rpc_client.go +++ b/internal/rpc/rpc_client.go @@ -336,6 +336,10 @@ func (this *RPCClient) UserBillRPC() pb.UserBillServiceClient { return pb.NewUserBillServiceClient(this.pickConn()) } +func (this *RPCClient) UserAccessKeyRPC() pb.UserAccessKeyServiceClient { + return pb.NewUserAccessKeyServiceClient(this.pickConn()) +} + func (this *RPCClient) LoginRPC() pb.LoginServiceClient { return pb.NewLoginServiceClient(this.pickConn()) } diff --git a/internal/web/actions/default/users/accesskeys/createPopup.go b/internal/web/actions/default/users/accesskeys/createPopup.go new file mode 100644 index 00000000..6cc7e7cd --- /dev/null +++ b/internal/web/actions/default/users/accesskeys/createPopup.go @@ -0,0 +1,49 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package accesskeys + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/actions" +) + +type CreatePopupAction struct { + actionutils.ParentAction +} + +func (this *CreatePopupAction) Init() { + this.Nav("", "", "") +} + +func (this *CreatePopupAction) RunGet(params struct { + UserId int64 +}) { + this.Data["userId"] = params.UserId + this.Show() +} + +func (this *CreatePopupAction) RunPost(params struct { + UserId int64 + Description string + + Must *actions.Must + CSRF *actionutils.CSRF +}) { + params.Must. + Field("description", params.Description). + Require("请输入备注") + + accessKeyIdResp, err := this.RPC().UserAccessKeyRPC().CreateUserAccessKey(this.AdminContext(), &pb.CreateUserAccessKeyRequest{ + UserId: params.UserId, + Description: params.Description, + }) + if err != nil { + this.ErrorPage(err) + return + } + + defer this.CreateLogInfo("创建AccessKey %d", accessKeyIdResp.UserAccessKeyId) + + this.Success() +} diff --git a/internal/web/actions/default/users/accesskeys/delete.go b/internal/web/actions/default/users/accesskeys/delete.go new file mode 100644 index 00000000..fd84da1c --- /dev/null +++ b/internal/web/actions/default/users/accesskeys/delete.go @@ -0,0 +1,24 @@ +package accesskeys + +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 { + AccessKeyId int64 +}) { + defer this.CreateLogInfo("删除AccessKey %d", params.AccessKeyId) + + _, err := this.RPC().UserAccessKeyRPC().DeleteUserAccessKey(this.AdminContext(), &pb.DeleteUserAccessKeyRequest{UserAccessKeyId: params.AccessKeyId}) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/users/accesskeys/index.go b/internal/web/actions/default/users/accesskeys/index.go new file mode 100644 index 00000000..267ccaee --- /dev/null +++ b/internal/web/actions/default/users/accesskeys/index.go @@ -0,0 +1,54 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package accesskeys + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/users/userutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/maps" + timeutil "github.com/iwind/TeaGo/utils/time" +) + +type IndexAction struct { + actionutils.ParentAction +} + +func (this *IndexAction) Init() { + this.Nav("", "", "accessKey") +} + +func (this *IndexAction) RunGet(params struct { + UserId int64 +}) { + err := userutils.InitUser(this.Parent(), params.UserId) + if err != nil { + this.ErrorPage(err) + return + } + + accessKeysResp, err := this.RPC().UserAccessKeyRPC().FindAllEnabledUserAccessKeys(this.AdminContext(), &pb.FindAllEnabledUserAccessKeysRequest{UserId: params.UserId}) + if err != nil { + this.ErrorPage(err) + return + } + + accessKeyMaps := []maps.Map{} + for _, accessKey := range accessKeysResp.UserAccessKeys { + var accessedTime string + if accessKey.AccessedAt > 0 { + accessedTime = timeutil.FormatTime("Y-m-d H:i:s", accessKey.AccessedAt) + } + accessKeyMaps = append(accessKeyMaps, maps.Map{ + "id": accessKey.Id, + "isOn": accessKey.IsOn, + "uniqueId": accessKey.UniqueId, + "secret": accessKey.Secret, + "description": accessKey.Description, + "accessedTime": accessedTime, + }) + } + this.Data["accessKeys"] = accessKeyMaps + + this.Show() +} diff --git a/internal/web/actions/default/users/accesskeys/updateIsOn.go b/internal/web/actions/default/users/accesskeys/updateIsOn.go new file mode 100644 index 00000000..7720cecf --- /dev/null +++ b/internal/web/actions/default/users/accesskeys/updateIsOn.go @@ -0,0 +1,28 @@ +package accesskeys + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" +) + +type UpdateIsOnAction struct { + actionutils.ParentAction +} + +func (this *UpdateIsOnAction) RunPost(params struct { + AccessKeyId int64 + IsOn bool +}) { + defer this.CreateLogInfo("设置AccessKey %d 启用状态", params.AccessKeyId) + + _, err := this.RPC().UserAccessKeyRPC().UpdateUserAccessKeyIsOn(this.AdminContext(), &pb.UpdateUserAccessKeyIsOnRequest{ + UserAccessKeyId: params.AccessKeyId, + IsOn: params.IsOn, + }) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/users/init.go b/internal/web/actions/default/users/init.go index 3776f131..b08ad8f2 100644 --- a/internal/web/actions/default/users/init.go +++ b/internal/web/actions/default/users/init.go @@ -2,6 +2,7 @@ package users import ( "github.com/TeaOSLab/EdgeAdmin/internal/configloaders" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/users/accessKeys" "github.com/TeaOSLab/EdgeAdmin/internal/web/helpers" "github.com/iwind/TeaGo" ) @@ -18,6 +19,14 @@ func init() { GetPost("/update", new(UpdateAction)). Post("/delete", new(DeleteAction)). GetPost("/features", new(FeaturesAction)). + + // AccessKeys + Prefix("/users/accessKeys"). + Get("", new(accesskeys.IndexAction)). + GetPost("/createPopup", new(accesskeys.CreatePopupAction)). + Post("/delete", new(accesskeys.DeleteAction)). + Post("/updateIsOn", new(accesskeys.UpdateIsOnAction)). + EndAll() }) } diff --git a/web/views/@default/users/@user_menu.html b/web/views/@default/users/@user_menu.html index fe9b5c47..8f2b4b29 100644 --- a/web/views/@default/users/@user_menu.html +++ b/web/views/@default/users/@user_menu.html @@ -4,4 +4,5 @@ {{user.fullname}}  ({{user.username}}) 修改 功能 + API AccessKey \ No newline at end of file diff --git a/web/views/@default/users/accesskeys/createPopup.html b/web/views/@default/users/accesskeys/createPopup.html new file mode 100644 index 00000000..3a31d63e --- /dev/null +++ b/web/views/@default/users/accesskeys/createPopup.html @@ -0,0 +1,20 @@ +{$layout "layout_popup"} + +

创建新AccessKey

+ +
+ + + + + + + + +
备注 * + +

描述AccessKey的用途等。

+
+ + +
\ No newline at end of file diff --git a/web/views/@default/users/accesskeys/index.html b/web/views/@default/users/accesskeys/index.html new file mode 100644 index 00000000..3deb5835 --- /dev/null +++ b/web/views/@default/users/accesskeys/index.html @@ -0,0 +1,39 @@ +{$layout} +{$template "../user_menu"} + + + [创建AccessKey] + + +

暂时还没有AccessKey。

+ + + + + + + + + + + + + + + + + + + + +
AccessKey IDAccessKey密钥备注最后访问状态操作
{{accessKey.uniqueId}}{{accessKey.secret}}{{accessKey.description}} + {{accessKey.accessedTime}} + 尚无访问 + + 已启用 + 已禁用 + + 禁用 + 启用 +   删除 +
\ No newline at end of file diff --git a/web/views/@default/users/accesskeys/index.js b/web/views/@default/users/accesskeys/index.js new file mode 100644 index 00000000..93080b3a --- /dev/null +++ b/web/views/@default/users/accesskeys/index.js @@ -0,0 +1,41 @@ +Tea.context(function () { + this.createAccessKey = function () { + teaweb.popup("/users/accessKeys/createPopup?userId=" + this.user.id, { + callback: function () { + teaweb.success("保存成功", function () { + teaweb.reload() + }) + } + }) + } + + this.updateAccessKeyIsOn = function (accessKeyId, isOn) { + let that = this + + let message = "" + if (isOn) { + message = "确定要启用此AccessKey吗?" + } else { + message = "确定要禁用此AccessKey吗?" + } + teaweb.confirm(message, function () { + that.$post(".updateIsOn") + .params({ + accessKeyId: accessKeyId, + isOn: isOn ? 1 : 0 + }) + .refresh() + }) + } + + this.deleteAccessKey = function (accessKeyId) { + let that = this + teaweb.confirm("确定要删除此AccessKey吗?", function () { + that.$post(".delete") + .params({ + accessKeyId: accessKeyId + }) + .refresh() + }) + } +}) \ No newline at end of file