1.4.5.2
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
// 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/langs/codes"
|
||||
"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 {
|
||||
AdminId int64
|
||||
}) {
|
||||
this.Data["adminId"] = params.AdminId
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
AdminId 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{
|
||||
AdminId: params.AdminId,
|
||||
Description: params.Description,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
defer this.CreateLogInfo(codes.UserAccessKey_LogCreateUserAccessKey, accessKeyIdResp.UserAccessKeyId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package accesskeys
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
AccessKeyId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.UserAccessKey_LogDeleteUserAccessKey, params.AccessKeyId)
|
||||
|
||||
_, err := this.RPC().UserAccessKeyRPC().DeleteUserAccessKey(this.AdminContext(), &pb.DeleteUserAccessKeyRequest{UserAccessKeyId: params.AccessKeyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -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/admins/adminutils"
|
||||
"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 {
|
||||
AdminId int64
|
||||
}) {
|
||||
err := adminutils.InitAdmin(this.Parent(), params.AdminId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
accessKeysResp, err := this.RPC().UserAccessKeyRPC().FindAllEnabledUserAccessKeys(this.AdminContext(), &pb.FindAllEnabledUserAccessKeysRequest{AdminId: params.AdminId})
|
||||
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()
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package accesskeys
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"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(codes.UserAccessKey_LogUpdateUserAccessKeyIsOn, 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()
|
||||
}
|
||||
85
EdgeAdmin/internal/web/actions/default/admins/admin.go
Normal file
85
EdgeAdmin/internal/web/actions/default/admins/admin.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package admins
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type AdminAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *AdminAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *AdminAction) RunGet(params struct {
|
||||
AdminId int64
|
||||
}) {
|
||||
adminResp, err := this.RPC().AdminRPC().FindEnabledAdmin(this.AdminContext(), &pb.FindEnabledAdminRequest{AdminId: params.AdminId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
admin := adminResp.Admin
|
||||
if admin == nil {
|
||||
this.NotFound("admin", params.AdminId)
|
||||
return
|
||||
}
|
||||
|
||||
// AccessKey数量
|
||||
countAccessKeyResp, err := this.RPC().UserAccessKeyRPC().CountAllEnabledUserAccessKeys(this.AdminContext(), &pb.CountAllEnabledUserAccessKeysRequest{AdminId: params.AdminId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
countAccessKeys := countAccessKeyResp.Count
|
||||
|
||||
this.Data["admin"] = maps.Map{
|
||||
"id": admin.Id,
|
||||
"fullname": admin.Fullname,
|
||||
"username": admin.Username,
|
||||
"isOn": admin.IsOn,
|
||||
"isSuper": admin.IsSuper,
|
||||
"canLogin": admin.CanLogin,
|
||||
"hasWeakPassword": admin.HasWeakPassword,
|
||||
"countAccessKeys": countAccessKeys,
|
||||
}
|
||||
|
||||
// 权限
|
||||
moduleMaps := []maps.Map{}
|
||||
for _, m := range configloaders.AllModuleMaps(this.LangCode()) {
|
||||
code := m.GetString("code")
|
||||
isChecked := false
|
||||
for _, module := range admin.Modules {
|
||||
if module.Code == code {
|
||||
isChecked = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if isChecked {
|
||||
moduleMaps = append(moduleMaps, m)
|
||||
}
|
||||
}
|
||||
this.Data["modules"] = moduleMaps
|
||||
|
||||
// OTP
|
||||
this.Data["otp"] = nil
|
||||
if admin.OtpLogin != nil && admin.OtpLogin.IsOn {
|
||||
loginParams := maps.Map{}
|
||||
err = json.Unmarshal(admin.OtpLogin.ParamsJSON, &loginParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["otp"] = maps.Map{
|
||||
"isOn": true,
|
||||
"params": loginParams,
|
||||
}
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package adminutils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// InitAdmin 查找管理员基本信息
|
||||
func InitAdmin(p *actionutils.ParentAction, adminId int64) error {
|
||||
// 管理员信息
|
||||
resp, err := p.RPC().AdminRPC().FindEnabledAdmin(p.AdminContext(), &pb.FindEnabledAdminRequest{AdminId: adminId})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.Admin == nil {
|
||||
return errors.New("not found admin")
|
||||
}
|
||||
var admin = resp.Admin
|
||||
|
||||
// AccessKey数量
|
||||
countAccessKeysResp, err := p.RPC().UserAccessKeyRPC().CountAllEnabledUserAccessKeys(p.AdminContext(), &pb.CountAllEnabledUserAccessKeysRequest{
|
||||
AdminId: adminId,
|
||||
UserId: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Data["admin"] = maps.Map{
|
||||
"id": admin.Id,
|
||||
"username": admin.Username,
|
||||
"fullname": admin.Fullname,
|
||||
"countAccessKeys": countAccessKeysResp.Count,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
128
EdgeAdmin/internal/web/actions/default/admins/createPopup.go
Normal file
128
EdgeAdmin/internal/web/actions/default/admins/createPopup.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package admins
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/xlzd/gotp"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||
this.Data["modules"] = configloaders.AllModuleMaps(this.LangCode())
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Fullname string
|
||||
Username string
|
||||
Pass1 string
|
||||
Pass2 string
|
||||
ModuleCodes []string
|
||||
IsSuper bool
|
||||
CanLogin bool
|
||||
|
||||
// OTP
|
||||
OtpOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
params.Must.
|
||||
Field("fullname", params.Fullname).
|
||||
Require("请输入系统用户全名")
|
||||
|
||||
params.Must.
|
||||
Field("username", params.Username).
|
||||
Require("请输入登录用户名").
|
||||
Match(`^[a-zA-Z0-9_]+$`, "用户名中只能包含英文、数字或下划线")
|
||||
|
||||
existsResp, err := this.RPC().AdminRPC().CheckAdminUsername(this.AdminContext(), &pb.CheckAdminUsernameRequest{
|
||||
AdminId: 0,
|
||||
Username: params.Username,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if existsResp.Exists {
|
||||
this.FailField("username", "此用户名已经被别的系统用户使用,请换一个")
|
||||
}
|
||||
|
||||
params.Must.
|
||||
Field("pass1", params.Pass1).
|
||||
Require("请输入登录密码").
|
||||
Field("pass2", params.Pass2).
|
||||
Require("请输入确认登录密码")
|
||||
if params.Pass1 != params.Pass2 {
|
||||
this.FailField("pass2", "两次输入的密码不一致")
|
||||
}
|
||||
|
||||
modules := []*systemconfigs.AdminModule{}
|
||||
for _, code := range params.ModuleCodes {
|
||||
modules = append(modules, &systemconfigs.AdminModule{
|
||||
Code: code,
|
||||
AllowAll: true,
|
||||
Actions: nil, // TODO 后期再开放细粒度控制
|
||||
})
|
||||
}
|
||||
modulesJSON, err := json.Marshal(modules)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().AdminRPC().CreateAdmin(this.AdminContext(), &pb.CreateAdminRequest{
|
||||
Username: params.Username,
|
||||
Password: params.Pass1,
|
||||
Fullname: params.Fullname,
|
||||
ModulesJSON: modulesJSON,
|
||||
IsSuper: params.IsSuper,
|
||||
CanLogin: params.CanLogin,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// OTP
|
||||
if params.OtpOn {
|
||||
_, err = this.RPC().LoginRPC().UpdateLogin(this.AdminContext(), &pb.UpdateLoginRequest{Login: &pb.Login{
|
||||
Id: 0,
|
||||
Type: "otp",
|
||||
ParamsJSON: maps.Map{
|
||||
"secret": gotp.RandomSecret(16), // TODO 改成可以设置secret长度
|
||||
}.AsJSON(),
|
||||
IsOn: true,
|
||||
AdminId: createResp.AdminId,
|
||||
UserId: 0,
|
||||
}})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
defer this.CreateLogInfo(codes.Admin_LogCreateAdmin, createResp.AdminId)
|
||||
|
||||
// 通知更改
|
||||
err = configloaders.NotifyAdminModuleMappingChange()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
33
EdgeAdmin/internal/web/actions/default/admins/delete.go
Normal file
33
EdgeAdmin/internal/web/actions/default/admins/delete.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package admins
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
AdminId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.Admin_LogDeleteAdmin, params.AdminId)
|
||||
|
||||
_, err := this.RPC().AdminRPC().DeleteAdmin(this.AdminContext(), &pb.DeleteAdminRequest{AdminId: params.AdminId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 通知更改
|
||||
err = configloaders.NotifyAdminModuleMappingChange()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
63
EdgeAdmin/internal/web/actions/default/admins/index.go
Normal file
63
EdgeAdmin/internal/web/actions/default/admins/index.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package admins
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"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("", "", "")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
Keyword string
|
||||
HasWeakPassword bool
|
||||
}) {
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["hasWeakPassword"] = params.HasWeakPassword
|
||||
|
||||
countResp, err := this.RPC().AdminRPC().CountAllEnabledAdmins(this.AdminContext(), &pb.CountAllEnabledAdminsRequest{
|
||||
Keyword: params.Keyword,
|
||||
HasWeakPassword: params.HasWeakPassword,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var page = this.NewPage(countResp.Count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
adminsResp, err := this.RPC().AdminRPC().ListEnabledAdmins(this.AdminContext(), &pb.ListEnabledAdminsRequest{
|
||||
Keyword: params.Keyword,
|
||||
HasWeakPassword: params.HasWeakPassword,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var adminMaps = []maps.Map{}
|
||||
for _, admin := range adminsResp.Admins {
|
||||
adminMaps = append(adminMaps, maps.Map{
|
||||
"id": admin.Id,
|
||||
"isOn": admin.IsOn,
|
||||
"isSuper": admin.IsSuper,
|
||||
"username": admin.Username,
|
||||
"fullname": admin.Fullname,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", admin.CreatedAt),
|
||||
"otpLoginIsOn": admin.OtpLogin != nil && admin.OtpLogin.IsOn,
|
||||
"canLogin": admin.CanLogin,
|
||||
"hasWeakPassword": admin.HasWeakPassword,
|
||||
})
|
||||
}
|
||||
this.Data["admins"] = adminMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
32
EdgeAdmin/internal/web/actions/default/admins/init.go
Normal file
32
EdgeAdmin/internal/web/actions/default/admins/init.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package admins
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/admins/accesskeys"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeAdmin)).
|
||||
Data("teaMenu", "admins").
|
||||
Prefix("/admins").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
GetPost("/update", new(UpdateAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
Get("/admin", new(AdminAction)).
|
||||
Get("/otpQrcode", new(OtpQrcodeAction)).
|
||||
Post("/options", new(OptionsAction)).
|
||||
|
||||
// AccessKeys
|
||||
Prefix("/admins/accesskeys").
|
||||
Get("", new(accesskeys.IndexAction)).
|
||||
GetPost("/createPopup", new(accesskeys.CreatePopupAction)).
|
||||
Post("/delete", new(accesskeys.DeleteAction)).
|
||||
Post("/updateIsOn", new(accesskeys.UpdateIsOnAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
40
EdgeAdmin/internal/web/actions/default/admins/options.go
Normal file
40
EdgeAdmin/internal/web/actions/default/admins/options.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package admins
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// 系统用户选项
|
||||
// 组件中需要用到的系统用户选项
|
||||
type OptionsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *OptionsAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *OptionsAction) RunPost(params struct{}) {
|
||||
// TODO 实现关键词搜索
|
||||
adminsResp, err := this.RPC().AdminRPC().ListEnabledAdmins(this.AdminContext(), &pb.ListEnabledAdminsRequest{
|
||||
Offset: 0,
|
||||
Size: 1000,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
adminMaps := []maps.Map{}
|
||||
for _, admin := range adminsResp.Admins {
|
||||
adminMaps = append(adminMaps, maps.Map{
|
||||
"id": admin.Id,
|
||||
"name": admin.Fullname,
|
||||
"username": admin.Username,
|
||||
})
|
||||
}
|
||||
this.Data["admins"] = adminMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
81
EdgeAdmin/internal/web/actions/default/admins/otpQrcode.go
Normal file
81
EdgeAdmin/internal/web/actions/default/admins/otpQrcode.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package admins
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/otputils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"github.com/skip2/go-qrcode"
|
||||
"github.com/xlzd/gotp"
|
||||
)
|
||||
|
||||
type OtpQrcodeAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *OtpQrcodeAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *OtpQrcodeAction) RunGet(params struct {
|
||||
AdminId int64
|
||||
Download bool
|
||||
}) {
|
||||
loginResp, err := this.RPC().LoginRPC().FindEnabledLogin(this.AdminContext(), &pb.FindEnabledLoginRequest{
|
||||
AdminId: params.AdminId,
|
||||
Type: "otp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var login = loginResp.Login
|
||||
if login == nil || !login.IsOn {
|
||||
this.NotFound("adminLogin", params.AdminId)
|
||||
return
|
||||
}
|
||||
|
||||
var loginParams = maps.Map{}
|
||||
err = json.Unmarshal(login.ParamsJSON, &loginParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var secret = loginParams.GetString("secret")
|
||||
|
||||
// 当前用户信息
|
||||
adminResp, err := this.RPC().AdminRPC().FindEnabledAdmin(this.AdminContext(), &pb.FindEnabledAdminRequest{AdminId: params.AdminId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var admin = adminResp.Admin
|
||||
if admin == nil {
|
||||
this.NotFound("admin", params.AdminId)
|
||||
return
|
||||
}
|
||||
|
||||
uiConfig, err := configloaders.LoadAdminUIConfig()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var url = gotp.NewDefaultTOTP(secret).ProvisioningUri(admin.Username, uiConfig.AdminSystemName)
|
||||
|
||||
data, err := qrcode.Encode(otputils.FixIssuer(url), qrcode.Medium, 256)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if params.Download {
|
||||
var filename = "OTP-ADMIN-" + admin.Username + ".png"
|
||||
this.AddHeader("Content-Disposition", "attachment; filename=\""+filename+"\";")
|
||||
}
|
||||
this.AddHeader("Content-Type", "image/png")
|
||||
this.AddHeader("Content-Length", types.String(len(data)))
|
||||
_, _ = this.Write(data)
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package recipients
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||
// node clusters
|
||||
nodeClustersResp, err := this.RPC().NodeClusterRPC().FindAllEnabledNodeClusters(this.AdminContext(), &pb.FindAllEnabledNodeClustersRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var nodeClusterMaps = []maps.Map{}
|
||||
for _, nodeCluster := range nodeClustersResp.NodeClusters {
|
||||
nodeClusterMaps = append(nodeClusterMaps, maps.Map{
|
||||
"id": nodeCluster.Id,
|
||||
"name": nodeCluster.Name,
|
||||
})
|
||||
}
|
||||
this.Data["nodeClusters"] = nodeClusterMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
AdminId int64
|
||||
InstanceId int64
|
||||
User string
|
||||
|
||||
TelegramToken string
|
||||
|
||||
GroupIds string
|
||||
Description string
|
||||
|
||||
TimeFromHour string
|
||||
TimeFromMinute string
|
||||
TimeFromSecond string
|
||||
|
||||
TimeToHour string
|
||||
TimeToMinute string
|
||||
TimeToSecond string
|
||||
|
||||
NodeClusterIds []int64
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
params.Must.
|
||||
Field("adminId", params.AdminId).
|
||||
Gt(0, "请选择系统用户").
|
||||
Field("instanceId", params.InstanceId).
|
||||
Gt(0, "请选择媒介")
|
||||
|
||||
var groupIds = utils.SplitNumbers(params.GroupIds)
|
||||
|
||||
var digitReg = regexp.MustCompile(`^\d+$`)
|
||||
|
||||
var timeFrom = ""
|
||||
if digitReg.MatchString(params.TimeFromHour) && digitReg.MatchString(params.TimeFromMinute) && digitReg.MatchString(params.TimeFromSecond) {
|
||||
timeFrom = params.TimeFromHour + ":" + params.TimeFromMinute + ":" + params.TimeFromSecond
|
||||
}
|
||||
|
||||
var timeTo = ""
|
||||
if digitReg.MatchString(params.TimeToHour) && digitReg.MatchString(params.TimeToMinute) && digitReg.MatchString(params.TimeToSecond) {
|
||||
timeTo = params.TimeToHour + ":" + params.TimeToMinute + ":" + params.TimeToSecond
|
||||
}
|
||||
|
||||
resp, err := this.RPC().MessageRecipientRPC().CreateMessageRecipient(this.AdminContext(), &pb.CreateMessageRecipientRequest{
|
||||
AdminId: params.AdminId,
|
||||
MessageMediaInstanceId: params.InstanceId,
|
||||
User: params.User,
|
||||
MessageRecipientGroupIds: groupIds,
|
||||
Description: params.Description,
|
||||
TimeFrom: timeFrom,
|
||||
TimeTo: timeTo,
|
||||
NodeClusterIds: params.NodeClusterIds,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
defer this.CreateLogInfo(codes.MessageRecipient_LogCreateMessageRecipient, resp.MessageRecipientId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package recipients
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
RecipientId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.MessageRecipient_LogDeleteMessageRecipient, params.RecipientId)
|
||||
|
||||
_, err := this.RPC().MessageRecipientRPC().DeleteMessageRecipient(this.AdminContext(), &pb.DeleteMessageRecipientRequest{MessageRecipientId: params.RecipientId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package groups
|
||||
|
||||
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{}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Name string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入分组名称")
|
||||
|
||||
_, err := this.RPC().MessageRecipientGroupRPC().CreateMessageRecipientGroup(this.AdminContext(), &pb.CreateMessageRecipientGroupRequest{Name: params.Name})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package groups
|
||||
|
||||
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 {
|
||||
GroupId int64
|
||||
}) {
|
||||
_, err := this.RPC().MessageRecipientGroupRPC().DeleteMessageRecipientGroup(this.AdminContext(), &pb.DeleteMessageRecipientGroupRequest{MessageRecipientGroupId: params.GroupId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package groups
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "group")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
groupsResp, err := this.RPC().MessageRecipientGroupRPC().FindAllEnabledMessageRecipientGroups(this.AdminContext(), &pb.FindAllEnabledMessageRecipientGroupsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
groupMaps := []maps.Map{}
|
||||
for _, group := range groupsResp.MessageRecipientGroups {
|
||||
groupMaps = append(groupMaps, maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
"isOn": group.IsOn,
|
||||
})
|
||||
}
|
||||
this.Data["groups"] = groupMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package groups
|
||||
|
||||
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.AdminModuleCodeAdmin)).
|
||||
Data("teaMenu", "admins").
|
||||
Data("teaSubMenu", "recipients").
|
||||
Prefix("/admins/recipients/groups").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
GetPost("/updatePopup", new(UpdatePopupAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
Get("/selectPopup", new(SelectPopupAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package groups
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type SelectPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *SelectPopupAction) RunGet(params struct {
|
||||
GroupIds string
|
||||
}) {
|
||||
selectedGroupIds := utils.SplitNumbers(params.GroupIds)
|
||||
|
||||
groupsResp, err := this.RPC().MessageRecipientGroupRPC().FindAllEnabledMessageRecipientGroups(this.AdminContext(), &pb.FindAllEnabledMessageRecipientGroupsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
groupMaps := []maps.Map{}
|
||||
for _, group := range groupsResp.MessageRecipientGroups {
|
||||
if lists.ContainsInt64(selectedGroupIds, group.Id) {
|
||||
continue
|
||||
}
|
||||
groupMaps = append(groupMaps, maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
"isOn": group.IsOn,
|
||||
})
|
||||
}
|
||||
this.Data["groups"] = groupMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package groups
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
GroupId int64
|
||||
}) {
|
||||
groupResp, err := this.RPC().MessageRecipientGroupRPC().FindEnabledMessageRecipientGroup(this.AdminContext(), &pb.FindEnabledMessageRecipientGroupRequest{MessageRecipientGroupId: params.GroupId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
group := groupResp.MessageRecipientGroup
|
||||
if group == nil {
|
||||
this.NotFound("messageRecipientGroup", params.GroupId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["group"] = maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
"isOn": group.IsOn,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
GroupId int64
|
||||
Name string
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入分组名称")
|
||||
|
||||
_, err := this.RPC().MessageRecipientGroupRPC().UpdateMessageRecipientGroup(this.AdminContext(), &pb.UpdateMessageRecipientGroupRequest{
|
||||
MessageRecipientGroupId: params.GroupId,
|
||||
Name: params.Name,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package recipients
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "recipient")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
}) {
|
||||
// TODO 增加系统用户、媒介类型等条件搜索
|
||||
countResp, err := this.RPC().MessageRecipientRPC().CountAllEnabledMessageRecipients(this.AdminContext(), &pb.CountAllEnabledMessageRecipientsRequest{
|
||||
AdminId: 0,
|
||||
MediaType: "",
|
||||
MessageRecipientGroupId: 0,
|
||||
Keyword: "",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
count := countResp.Count
|
||||
page := this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
recipientsResp, err := this.RPC().MessageRecipientRPC().ListEnabledMessageRecipients(this.AdminContext(), &pb.ListEnabledMessageRecipientsRequest{
|
||||
AdminId: 0,
|
||||
MediaType: "",
|
||||
MessageRecipientGroupId: 0,
|
||||
Keyword: "",
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
recipientMaps := []maps.Map{}
|
||||
for _, recipient := range recipientsResp.MessageRecipients {
|
||||
if recipient.Admin == nil {
|
||||
continue
|
||||
}
|
||||
if recipient.MessageMediaInstance == nil {
|
||||
continue
|
||||
}
|
||||
recipientMaps = append(recipientMaps, maps.Map{
|
||||
"id": recipient.Id,
|
||||
"admin": maps.Map{
|
||||
"id": recipient.Admin.Id,
|
||||
"fullname": recipient.Admin.Fullname,
|
||||
"username": recipient.Admin.Username,
|
||||
},
|
||||
"groups": recipient.MessageRecipientGroups,
|
||||
"isOn": recipient.IsOn,
|
||||
"instance": maps.Map{
|
||||
"name": recipient.MessageMediaInstance.Name,
|
||||
},
|
||||
"user": recipient.User,
|
||||
"description": recipient.Description,
|
||||
})
|
||||
}
|
||||
this.Data["recipients"] = recipientMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package recipients
|
||||
|
||||
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.AdminModuleCodeAdmin)).
|
||||
Data("teaMenu", "admins").
|
||||
Data("teaSubMenu", "recipients").
|
||||
Prefix("/admins/recipients").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
GetPost("/update", new(UpdateAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
Post("/mediaOptions", new(MediaOptionsAction)).
|
||||
Get("/recipient", new(RecipientAction)).
|
||||
GetPost("/test", new(TestAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
package instances
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/monitorconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Name string
|
||||
MediaType string
|
||||
|
||||
EmailSmtp string
|
||||
EmailUsername string
|
||||
EmailPassword string
|
||||
EmailFrom string
|
||||
|
||||
WebHookURL string
|
||||
WebHookMethod string
|
||||
WebHookHeaderNames []string
|
||||
WebHookHeaderValues []string
|
||||
WebHookContentType string
|
||||
WebHookParamNames []string
|
||||
WebHookParamValues []string
|
||||
WebHookBody string
|
||||
|
||||
ScriptType string
|
||||
ScriptPath string
|
||||
ScriptLang string
|
||||
ScriptCode string
|
||||
ScriptCwd string
|
||||
ScriptEnvNames []string
|
||||
ScriptEnvValues []string
|
||||
|
||||
DingTalkWebHookURL string
|
||||
|
||||
QyWeixinCorporateId string
|
||||
QyWeixinAgentId string
|
||||
QyWeixinAppSecret string
|
||||
QyWeixinTextFormat string
|
||||
|
||||
QyWeixinRobotWebHookURL string
|
||||
QyWeixinRobotTextFormat string
|
||||
|
||||
AliyunSmsSign string
|
||||
AliyunSmsTemplateCode string
|
||||
AliyunSmsTemplateVarNames []string
|
||||
AliyunSmsTemplateVarValues []string
|
||||
AliyunSmsAccessKeyId string
|
||||
AliyunSmsAccessKeySecret string
|
||||
|
||||
TelegramToken string
|
||||
TelegramProxyScheme string
|
||||
TelegramProxyHost string
|
||||
|
||||
RateMinutes int32
|
||||
RateCount int32
|
||||
|
||||
HashLife int32
|
||||
|
||||
Description string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入媒介名称").
|
||||
Field("mediaType", params.MediaType).
|
||||
Require("请选择媒介类型")
|
||||
|
||||
options := maps.Map{}
|
||||
|
||||
switch params.MediaType {
|
||||
case "email":
|
||||
params.Must.
|
||||
Field("emailSmtp", params.EmailSmtp).
|
||||
Require("请输入SMTP地址").
|
||||
Field("emailUsername", params.EmailUsername).
|
||||
Require("请输入邮箱账号").
|
||||
Field("emailPassword", params.EmailPassword).
|
||||
Require("请输入密码或授权码")
|
||||
|
||||
options["smtp"] = params.EmailSmtp
|
||||
options["username"] = params.EmailUsername
|
||||
options["password"] = params.EmailPassword
|
||||
options["from"] = params.EmailFrom
|
||||
case "webHook":
|
||||
params.Must.
|
||||
Field("webHookURL", params.WebHookURL).
|
||||
Require("请输入URL地址").
|
||||
Match("(?i)^(http|https)://", "URL地址必须以http或https开头").
|
||||
Field("webHookMethod", params.WebHookMethod).
|
||||
Require("请选择请求方法")
|
||||
|
||||
options["url"] = params.WebHookURL
|
||||
options["method"] = params.WebHookMethod
|
||||
options["contentType"] = params.WebHookContentType
|
||||
|
||||
headers := []maps.Map{}
|
||||
if len(params.WebHookHeaderNames) > 0 {
|
||||
for index, name := range params.WebHookHeaderNames {
|
||||
if index < len(params.WebHookHeaderValues) {
|
||||
headers = append(headers, maps.Map{
|
||||
"name": name,
|
||||
"value": params.WebHookHeaderValues[index],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
options["headers"] = headers
|
||||
|
||||
if params.WebHookContentType == "params" {
|
||||
webHookParams := []maps.Map{}
|
||||
for index, name := range params.WebHookParamNames {
|
||||
if index < len(params.WebHookParamValues) {
|
||||
webHookParams = append(webHookParams, maps.Map{
|
||||
"name": name,
|
||||
"value": params.WebHookParamValues[index],
|
||||
})
|
||||
}
|
||||
}
|
||||
options["params"] = webHookParams
|
||||
} else if params.WebHookContentType == "body" {
|
||||
options["body"] = params.WebHookBody
|
||||
}
|
||||
case "script":
|
||||
if params.ScriptType == "path" {
|
||||
params.Must.
|
||||
Field("scriptPath", params.ScriptPath).
|
||||
Require("请输入脚本路径")
|
||||
} else if params.ScriptType == "code" {
|
||||
params.Must.
|
||||
Field("scriptCode", params.ScriptCode).
|
||||
Require("请输入脚本代码")
|
||||
} else {
|
||||
params.Must.
|
||||
Field("scriptPath", params.ScriptPath).
|
||||
Require("请输入脚本路径")
|
||||
}
|
||||
|
||||
options["scriptType"] = params.ScriptType
|
||||
options["path"] = params.ScriptPath
|
||||
options["scriptLang"] = params.ScriptLang
|
||||
options["script"] = params.ScriptCode
|
||||
options["cwd"] = params.ScriptCwd
|
||||
|
||||
env := []maps.Map{}
|
||||
for index, envName := range params.ScriptEnvNames {
|
||||
if index < len(params.ScriptEnvValues) {
|
||||
env = append(env, maps.Map{
|
||||
"name": envName,
|
||||
"value": params.ScriptEnvValues[index],
|
||||
})
|
||||
}
|
||||
}
|
||||
options["env"] = env
|
||||
case "dingTalk":
|
||||
params.Must.
|
||||
Field("dingTalkWebHookURL", params.DingTalkWebHookURL).
|
||||
Require("请输入Hook地址").
|
||||
Match("^https:", "Hook地址必须以https://开头")
|
||||
|
||||
options["webHookURL"] = params.DingTalkWebHookURL
|
||||
case "qyWeixin":
|
||||
params.Must.
|
||||
Field("qyWeixinCorporateId", params.QyWeixinCorporateId).
|
||||
Require("请输入企业ID").
|
||||
Field("qyWeixinAgentId", params.QyWeixinAgentId).
|
||||
Require("请输入应用AgentId").
|
||||
Field("qyWeixinSecret", params.QyWeixinAppSecret).
|
||||
Require("请输入应用Secret")
|
||||
|
||||
options["corporateId"] = params.QyWeixinCorporateId
|
||||
options["agentId"] = params.QyWeixinAgentId
|
||||
options["appSecret"] = params.QyWeixinAppSecret
|
||||
options["textFormat"] = params.QyWeixinTextFormat
|
||||
case "qyWeixinRobot":
|
||||
params.Must.
|
||||
Field("qyWeixinRobotWebHookURL", params.QyWeixinRobotWebHookURL).
|
||||
Require("请输入WebHook地址").
|
||||
Match("^https:", "WebHook地址必须以https://开头")
|
||||
|
||||
options["webHookURL"] = params.QyWeixinRobotWebHookURL
|
||||
options["textFormat"] = params.QyWeixinRobotTextFormat
|
||||
case "aliyunSms":
|
||||
params.Must.
|
||||
Field("aliyunSmsSign", params.AliyunSmsSign).
|
||||
Require("请输入签名名称").
|
||||
Field("aliyunSmsTemplateCode", params.AliyunSmsTemplateCode).
|
||||
Require("请输入模板CODE").
|
||||
Field("aliyunSmsAccessKeyId", params.AliyunSmsAccessKeyId).
|
||||
Require("请输入AccessKey ID").
|
||||
Field("aliyunSmsAccessKeySecret", params.AliyunSmsAccessKeySecret).
|
||||
Require("请输入AccessKey Secret")
|
||||
|
||||
options["sign"] = params.AliyunSmsSign
|
||||
options["templateCode"] = params.AliyunSmsTemplateCode
|
||||
options["accessKeyId"] = params.AliyunSmsAccessKeyId
|
||||
options["accessKeySecret"] = params.AliyunSmsAccessKeySecret
|
||||
|
||||
variables := []maps.Map{}
|
||||
for index, name := range params.AliyunSmsTemplateVarNames {
|
||||
if index < len(params.AliyunSmsTemplateVarValues) {
|
||||
variables = append(variables, maps.Map{
|
||||
"name": name,
|
||||
"value": params.AliyunSmsTemplateVarValues[index],
|
||||
})
|
||||
}
|
||||
}
|
||||
options["variables"] = variables
|
||||
case "telegram":
|
||||
// token
|
||||
params.Must.
|
||||
Field("telegramToken", params.TelegramToken).
|
||||
Require("请输入机器人Token").
|
||||
Match(`^\w+:[\w-_]+$`, "机器人Token格式错误,请修正")
|
||||
|
||||
options["token"] = params.TelegramToken
|
||||
|
||||
// proxy
|
||||
var telegramScheme = params.TelegramProxyScheme
|
||||
var telegramProxyHost = params.TelegramProxyHost
|
||||
|
||||
if len(telegramScheme) > 0 && len(telegramProxyHost) > 0 {
|
||||
// 检查是否为url
|
||||
if regexp.MustCompile(`^\w+://`).MatchString(telegramProxyHost) {
|
||||
u, err := url.Parse(telegramProxyHost)
|
||||
if err == nil {
|
||||
telegramScheme = u.Scheme
|
||||
telegramProxyHost = u.Host
|
||||
}
|
||||
}
|
||||
|
||||
var slashIndex = strings.Index(telegramProxyHost, "/")
|
||||
if slashIndex >= 0 {
|
||||
telegramProxyHost = telegramProxyHost[:slashIndex]
|
||||
}
|
||||
|
||||
options["proxyURL"] = telegramScheme + "://" + telegramProxyHost
|
||||
}
|
||||
default:
|
||||
this.Fail("错误的媒介类型")
|
||||
}
|
||||
|
||||
optionsJSON, err := json.Marshal(options)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var rateConfig = &monitorconfigs.RateConfig{
|
||||
Minutes: params.RateMinutes,
|
||||
Count: params.RateCount,
|
||||
}
|
||||
rateJSON, err := json.Marshal(rateConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := this.RPC().MessageMediaInstanceRPC().CreateMessageMediaInstance(this.AdminContext(), &pb.CreateMessageMediaInstanceRequest{
|
||||
Name: params.Name,
|
||||
MediaType: params.MediaType,
|
||||
ParamsJSON: optionsJSON,
|
||||
Description: params.Description,
|
||||
RateJSON: rateJSON,
|
||||
HashLife: params.HashLife,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
defer this.CreateLogInfo(codes.MessageMediaInstance_LogCreateMessageMediaInstance, resp.MessageMediaInstanceId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package instances
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
InstanceId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.MessageMediaInstance_LogDeleteMessageMediaInstance, params.InstanceId)
|
||||
|
||||
_, err := this.RPC().MessageMediaInstanceRPC().DeleteMessageMediaInstance(this.AdminContext(), &pb.DeleteMessageMediaInstanceRequest{MessageMediaInstanceId: params.InstanceId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package instances
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "instance")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
}) {
|
||||
// TODO 增加系统用户、媒介类型等条件搜索
|
||||
countResp, err := this.RPC().MessageMediaInstanceRPC().CountAllEnabledMessageMediaInstances(this.AdminContext(), &pb.CountAllEnabledMessageMediaInstancesRequest{
|
||||
MediaType: "",
|
||||
Keyword: "",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
count := countResp.Count
|
||||
page := this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
instancesResp, err := this.RPC().MessageMediaInstanceRPC().ListEnabledMessageMediaInstances(this.AdminContext(), &pb.ListEnabledMessageMediaInstancesRequest{
|
||||
MediaType: "",
|
||||
Keyword: "",
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
instanceMaps := []maps.Map{}
|
||||
for _, instance := range instancesResp.MessageMediaInstances {
|
||||
if instance.MessageMedia == nil {
|
||||
continue
|
||||
}
|
||||
instanceMaps = append(instanceMaps, maps.Map{
|
||||
"id": instance.Id,
|
||||
"name": instance.Name,
|
||||
"isOn": instance.IsOn,
|
||||
"media": maps.Map{
|
||||
"name": instance.MessageMedia.Name,
|
||||
},
|
||||
"description": instance.Description,
|
||||
})
|
||||
}
|
||||
this.Data["instances"] = instanceMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package instances
|
||||
|
||||
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.AdminModuleCodeAdmin)).
|
||||
Data("teaMenu", "admins").
|
||||
Data("teaSubMenu", "instances").
|
||||
Prefix("/admins/recipients/instances").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
GetPost("/update", new(UpdateAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
Get("/instance", new(InstanceAction)).
|
||||
GetPost("/test", new(TestAction)).
|
||||
Post("/options", new(OptionsAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package instances
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/monitorconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type InstanceAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *InstanceAction) Init() {
|
||||
this.Nav("", "", "instance")
|
||||
}
|
||||
|
||||
func (this *InstanceAction) RunGet(params struct {
|
||||
InstanceId int64
|
||||
}) {
|
||||
instanceResp, err := this.RPC().MessageMediaInstanceRPC().FindEnabledMessageMediaInstance(this.AdminContext(), &pb.FindEnabledMessageMediaInstanceRequest{MessageMediaInstanceId: params.InstanceId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var instance = instanceResp.MessageMediaInstance
|
||||
if instance == nil || instance.MessageMedia == nil {
|
||||
this.NotFound("messageMediaInstance", params.InstanceId)
|
||||
return
|
||||
}
|
||||
|
||||
// 参数
|
||||
var mediaParams = maps.Map{}
|
||||
if len(instance.ParamsJSON) > 0 {
|
||||
err = json.Unmarshal(instance.ParamsJSON, &mediaParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 隐藏密码
|
||||
if mediaParams.Has("password") {
|
||||
var password = mediaParams.Get("password")
|
||||
if password != nil {
|
||||
passwordString, ok := password.(string)
|
||||
if ok {
|
||||
mediaParams["password"] = strings.Repeat("*", len(passwordString))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 频率
|
||||
var rateConfig = &monitorconfigs.RateConfig{}
|
||||
if len(instance.RateJSON) > 0 {
|
||||
err = json.Unmarshal(instance.RateJSON, rateConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["instance"] = maps.Map{
|
||||
"id": instance.Id,
|
||||
"name": instance.Name,
|
||||
"isOn": instance.IsOn,
|
||||
"media": maps.Map{
|
||||
"type": instance.MessageMedia.Type,
|
||||
"name": instance.MessageMedia.Name,
|
||||
},
|
||||
"description": instance.Description,
|
||||
"params": mediaParams,
|
||||
"rate": rateConfig,
|
||||
"hashLife": instance.HashLife,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package instances
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// OptionsAction 媒介类型选项
|
||||
type OptionsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *OptionsAction) RunPost(params struct{}) {
|
||||
resp, err := this.RPC().MessageMediaInstanceRPC().ListEnabledMessageMediaInstances(this.AdminContext(), &pb.ListEnabledMessageMediaInstancesRequest{
|
||||
Offset: 0,
|
||||
Size: 1000,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
instanceMaps := []maps.Map{}
|
||||
for _, instance := range resp.MessageMediaInstances {
|
||||
instanceMaps = append(instanceMaps, maps.Map{
|
||||
"id": instance.Id,
|
||||
"name": instance.Name,
|
||||
"description": instance.Description,
|
||||
"media": maps.Map{
|
||||
"type": instance.MessageMedia.Type,
|
||||
"name": instance.MessageMedia.Name,
|
||||
"userDescription": instance.MessageMedia.UserDescription,
|
||||
},
|
||||
})
|
||||
}
|
||||
this.Data["instances"] = instanceMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package instances
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type TestAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *TestAction) Init() {
|
||||
this.Nav("", "", "test")
|
||||
}
|
||||
|
||||
func (this *TestAction) RunGet(params struct {
|
||||
InstanceId int64
|
||||
}) {
|
||||
instanceResp, err := this.RPC().MessageMediaInstanceRPC().FindEnabledMessageMediaInstance(this.AdminContext(), &pb.FindEnabledMessageMediaInstanceRequest{MessageMediaInstanceId: params.InstanceId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
instance := instanceResp.MessageMediaInstance
|
||||
if instance == nil || instance.MessageMedia == nil {
|
||||
this.NotFound("messageMediaInstance", params.InstanceId)
|
||||
return
|
||||
}
|
||||
|
||||
mediaParams := maps.Map{}
|
||||
if len(instance.ParamsJSON) > 0 {
|
||||
err = json.Unmarshal(instance.ParamsJSON, &mediaParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["instance"] = maps.Map{
|
||||
"id": instance.Id,
|
||||
"isOn": instance.IsOn,
|
||||
"media": maps.Map{
|
||||
"type": instance.MessageMedia.Type,
|
||||
"name": instance.MessageMedia.Name,
|
||||
"userDescription": instance.MessageMedia.UserDescription,
|
||||
},
|
||||
"description": instance.Description,
|
||||
"params": mediaParams,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *TestAction) RunPost(params struct {
|
||||
InstanceId int64
|
||||
Subject string
|
||||
Body string
|
||||
User string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
params.Must.
|
||||
Field("instanceId", params.InstanceId).
|
||||
Gt(0, "请选择正确的媒介")
|
||||
|
||||
resp, err := this.RPC().MessageTaskRPC().SendMessageTask(this.AdminContext(), &pb.SendMessageTaskRequest{
|
||||
MessageMediaInstanceId: params.InstanceId,
|
||||
User: params.User,
|
||||
Subject: params.Subject,
|
||||
Body: params.Body,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["result"] = maps.Map{
|
||||
"isOk": resp.IsOk,
|
||||
"error": resp.Error,
|
||||
"response": resp.Response,
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
package instances
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/monitorconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type UpdateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateAction) Init() {
|
||||
this.Nav("", "", "update")
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunGet(params struct {
|
||||
InstanceId int64
|
||||
}) {
|
||||
instanceResp, err := this.RPC().MessageMediaInstanceRPC().FindEnabledMessageMediaInstance(this.AdminContext(), &pb.FindEnabledMessageMediaInstanceRequest{MessageMediaInstanceId: params.InstanceId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var instance = instanceResp.MessageMediaInstance
|
||||
if instance == nil || instance.MessageMedia == nil {
|
||||
this.NotFound("messageMediaInstance", params.InstanceId)
|
||||
return
|
||||
}
|
||||
|
||||
var mediaParams = maps.Map{}
|
||||
if len(instance.ParamsJSON) > 0 {
|
||||
err = json.Unmarshal(instance.ParamsJSON, &mediaParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// telegram parameters
|
||||
this.Data["telegramProxyScheme"] = "socks5"
|
||||
this.Data["telegramProxyHost"] = ""
|
||||
if instance.MessageMedia != nil && instance.MessageMedia.Type == "telegram" {
|
||||
var proxyURL = mediaParams.GetString("proxyURL")
|
||||
var reg = regexp.MustCompile(`^(\w+)://(.+)$`)
|
||||
if reg.MatchString(proxyURL) {
|
||||
var matches = reg.FindStringSubmatch(proxyURL)
|
||||
if len(matches) > 2 {
|
||||
this.Data["telegramProxyScheme"] = matches[1]
|
||||
this.Data["telegramProxyHost"] = matches[2]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var rateConfig = &monitorconfigs.RateConfig{}
|
||||
if len(instance.RateJSON) > 0 {
|
||||
err = json.Unmarshal(instance.RateJSON, rateConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["instance"] = maps.Map{
|
||||
"id": instance.Id,
|
||||
"name": instance.Name,
|
||||
"isOn": instance.IsOn,
|
||||
"media": maps.Map{
|
||||
"type": instance.MessageMedia.Type,
|
||||
"name": instance.MessageMedia.Name,
|
||||
},
|
||||
"description": instance.Description,
|
||||
"params": mediaParams,
|
||||
"rate": rateConfig,
|
||||
"hashLife": instance.HashLife,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunPost(params struct {
|
||||
InstanceId int64
|
||||
Name string
|
||||
MediaType string
|
||||
|
||||
EmailSmtp string
|
||||
EmailUsername string
|
||||
EmailPassword string
|
||||
EmailFrom string
|
||||
|
||||
WebHookURL string
|
||||
WebHookMethod string
|
||||
WebHookHeaderNames []string
|
||||
WebHookHeaderValues []string
|
||||
WebHookContentType string
|
||||
WebHookParamNames []string
|
||||
WebHookParamValues []string
|
||||
WebHookBody string
|
||||
|
||||
ScriptType string
|
||||
ScriptPath string
|
||||
ScriptLang string
|
||||
ScriptCode string
|
||||
ScriptCwd string
|
||||
ScriptEnvNames []string
|
||||
ScriptEnvValues []string
|
||||
|
||||
DingTalkWebHookURL string
|
||||
|
||||
QyWeixinCorporateId string
|
||||
QyWeixinAgentId string
|
||||
QyWeixinAppSecret string
|
||||
QyWeixinTextFormat string
|
||||
|
||||
QyWeixinRobotWebHookURL string
|
||||
QyWeixinRobotTextFormat string
|
||||
|
||||
AliyunSmsSign string
|
||||
AliyunSmsTemplateCode string
|
||||
AliyunSmsTemplateVarNames []string
|
||||
AliyunSmsTemplateVarValues []string
|
||||
AliyunSmsAccessKeyId string
|
||||
AliyunSmsAccessKeySecret string
|
||||
|
||||
TelegramToken string
|
||||
TelegramProxyScheme string
|
||||
TelegramProxyHost string
|
||||
|
||||
GroupIds string
|
||||
Description string
|
||||
IsOn bool
|
||||
|
||||
RateMinutes int32
|
||||
RateCount int32
|
||||
|
||||
HashLife int32
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.MessageMediaInstance_LogUpdateMessageMediaInstance, params.InstanceId)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入媒介名称").
|
||||
Field("mediaType", params.MediaType).
|
||||
Require("请选择媒介类型")
|
||||
|
||||
options := maps.Map{}
|
||||
|
||||
switch params.MediaType {
|
||||
case "email":
|
||||
params.Must.
|
||||
Field("emailSmtp", params.EmailSmtp).
|
||||
Require("请输入SMTP地址").
|
||||
Field("emailUsername", params.EmailUsername).
|
||||
Require("请输入邮箱账号").
|
||||
Field("emailPassword", params.EmailPassword).
|
||||
Require("请输入密码或授权码")
|
||||
|
||||
options["smtp"] = params.EmailSmtp
|
||||
options["username"] = params.EmailUsername
|
||||
options["password"] = params.EmailPassword
|
||||
options["from"] = params.EmailFrom
|
||||
case "webHook":
|
||||
params.Must.
|
||||
Field("webHookURL", params.WebHookURL).
|
||||
Require("请输入URL地址").
|
||||
Match("(?i)^(http|https)://", "URL地址必须以http或https开头").
|
||||
Field("webHookMethod", params.WebHookMethod).
|
||||
Require("请选择请求方法")
|
||||
|
||||
options["url"] = params.WebHookURL
|
||||
options["method"] = params.WebHookMethod
|
||||
options["contentType"] = params.WebHookContentType
|
||||
|
||||
headers := []maps.Map{}
|
||||
if len(params.WebHookHeaderNames) > 0 {
|
||||
for index, name := range params.WebHookHeaderNames {
|
||||
if index < len(params.WebHookHeaderValues) {
|
||||
headers = append(headers, maps.Map{
|
||||
"name": name,
|
||||
"value": params.WebHookHeaderValues[index],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
options["headers"] = headers
|
||||
|
||||
if params.WebHookContentType == "params" {
|
||||
webHookParams := []maps.Map{}
|
||||
for index, name := range params.WebHookParamNames {
|
||||
if index < len(params.WebHookParamValues) {
|
||||
webHookParams = append(webHookParams, maps.Map{
|
||||
"name": name,
|
||||
"value": params.WebHookParamValues[index],
|
||||
})
|
||||
}
|
||||
}
|
||||
options["params"] = webHookParams
|
||||
} else if params.WebHookContentType == "body" {
|
||||
options["body"] = params.WebHookBody
|
||||
}
|
||||
case "script":
|
||||
if params.ScriptType == "path" {
|
||||
params.Must.
|
||||
Field("scriptPath", params.ScriptPath).
|
||||
Require("请输入脚本路径")
|
||||
} else if params.ScriptType == "code" {
|
||||
params.Must.
|
||||
Field("scriptCode", params.ScriptCode).
|
||||
Require("请输入脚本代码")
|
||||
} else {
|
||||
params.Must.
|
||||
Field("scriptPath", params.ScriptPath).
|
||||
Require("请输入脚本路径")
|
||||
}
|
||||
|
||||
options["scriptType"] = params.ScriptType
|
||||
options["path"] = params.ScriptPath
|
||||
options["scriptLang"] = params.ScriptLang
|
||||
options["script"] = params.ScriptCode
|
||||
options["cwd"] = params.ScriptCwd
|
||||
|
||||
env := []maps.Map{}
|
||||
for index, envName := range params.ScriptEnvNames {
|
||||
if index < len(params.ScriptEnvValues) {
|
||||
env = append(env, maps.Map{
|
||||
"name": envName,
|
||||
"value": params.ScriptEnvValues[index],
|
||||
})
|
||||
}
|
||||
}
|
||||
options["env"] = env
|
||||
case "dingTalk":
|
||||
params.Must.
|
||||
Field("dingTalkWebHookURL", params.DingTalkWebHookURL).
|
||||
Require("请输入Hook地址").
|
||||
Match("^https:", "Hook地址必须以https://开头")
|
||||
|
||||
options["webHookURL"] = params.DingTalkWebHookURL
|
||||
case "qyWeixin":
|
||||
params.Must.
|
||||
Field("qyWeixinCorporateId", params.QyWeixinCorporateId).
|
||||
Require("请输入企业ID").
|
||||
Field("qyWeixinAgentId", params.QyWeixinAgentId).
|
||||
Require("请输入应用AgentId").
|
||||
Field("qyWeixinSecret", params.QyWeixinAppSecret).
|
||||
Require("请输入应用Secret")
|
||||
|
||||
options["corporateId"] = params.QyWeixinCorporateId
|
||||
options["agentId"] = params.QyWeixinAgentId
|
||||
options["appSecret"] = params.QyWeixinAppSecret
|
||||
options["textFormat"] = params.QyWeixinTextFormat
|
||||
case "qyWeixinRobot":
|
||||
params.Must.
|
||||
Field("qyWeixinRobotWebHookURL", params.QyWeixinRobotWebHookURL).
|
||||
Require("请输入WebHook地址").
|
||||
Match("^https:", "WebHook地址必须以https://开头")
|
||||
|
||||
options["webHookURL"] = params.QyWeixinRobotWebHookURL
|
||||
options["textFormat"] = params.QyWeixinRobotTextFormat
|
||||
case "aliyunSms":
|
||||
params.Must.
|
||||
Field("aliyunSmsSign", params.AliyunSmsSign).
|
||||
Require("请输入签名名称").
|
||||
Field("aliyunSmsTemplateCode", params.AliyunSmsTemplateCode).
|
||||
Require("请输入模板CODE").
|
||||
Field("aliyunSmsAccessKeyId", params.AliyunSmsAccessKeyId).
|
||||
Require("请输入AccessKey ID").
|
||||
Field("aliyunSmsAccessKeySecret", params.AliyunSmsAccessKeySecret).
|
||||
Require("请输入AccessKey Secret")
|
||||
|
||||
options["sign"] = params.AliyunSmsSign
|
||||
options["templateCode"] = params.AliyunSmsTemplateCode
|
||||
options["accessKeyId"] = params.AliyunSmsAccessKeyId
|
||||
options["accessKeySecret"] = params.AliyunSmsAccessKeySecret
|
||||
|
||||
variables := []maps.Map{}
|
||||
for index, name := range params.AliyunSmsTemplateVarNames {
|
||||
if index < len(params.AliyunSmsTemplateVarValues) {
|
||||
variables = append(variables, maps.Map{
|
||||
"name": name,
|
||||
"value": params.AliyunSmsTemplateVarValues[index],
|
||||
})
|
||||
}
|
||||
}
|
||||
options["variables"] = variables
|
||||
case "telegram":
|
||||
params.Must.
|
||||
Field("telegramToken", params.TelegramToken).
|
||||
Require("请输入机器人Token").
|
||||
Match(`^\w+:[\w-_]+$`, "机器人Token格式错误,请修正")
|
||||
options["token"] = params.TelegramToken
|
||||
|
||||
// proxy
|
||||
var telegramScheme = params.TelegramProxyScheme
|
||||
var telegramProxyHost = params.TelegramProxyHost
|
||||
|
||||
if len(telegramScheme) > 0 && len(telegramProxyHost) > 0 {
|
||||
// 检查是否为url
|
||||
if regexp.MustCompile(`^\w+://`).MatchString(telegramProxyHost) {
|
||||
u, err := url.Parse(telegramProxyHost)
|
||||
if err == nil {
|
||||
telegramScheme = u.Scheme
|
||||
telegramProxyHost = u.Host
|
||||
}
|
||||
}
|
||||
|
||||
var slashIndex = strings.Index(telegramProxyHost, "/")
|
||||
if slashIndex >= 0 {
|
||||
telegramProxyHost = telegramProxyHost[:slashIndex]
|
||||
}
|
||||
|
||||
options["proxyURL"] = telegramScheme + "://" + telegramProxyHost
|
||||
}
|
||||
default:
|
||||
this.Fail("错误的媒介类型")
|
||||
}
|
||||
|
||||
optionsJSON, err := json.Marshal(options)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var rateConfig = &monitorconfigs.RateConfig{
|
||||
Minutes: params.RateMinutes,
|
||||
Count: params.RateCount,
|
||||
}
|
||||
rateJSON, err := json.Marshal(rateConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().MessageMediaInstanceRPC().UpdateMessageMediaInstance(this.AdminContext(), &pb.UpdateMessageMediaInstanceRequest{
|
||||
MessageMediaInstanceId: params.InstanceId,
|
||||
Name: params.Name,
|
||||
MediaType: params.MediaType,
|
||||
ParamsJSON: optionsJSON,
|
||||
Description: params.Description,
|
||||
RateJSON: rateJSON,
|
||||
HashLife: params.HashLife,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package logs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"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("", "", "log")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
countResp, err := this.RPC().MessageTaskLogRPC().CountMessageTaskLogs(this.AdminContext(), &pb.CountMessageTaskLogsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var page = this.NewPage(countResp.Count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
logsResp, err := this.RPC().MessageTaskLogRPC().ListMessageTaskLogs(this.AdminContext(), &pb.ListMessageTaskLogsRequest{
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var logMaps = []maps.Map{}
|
||||
for _, log := range logsResp.MessageTaskLogs {
|
||||
if log.MessageTask.MessageRecipient != nil {
|
||||
log.MessageTask.User = log.MessageTask.MessageRecipient.User
|
||||
}
|
||||
logMaps = append(logMaps, maps.Map{
|
||||
"task": maps.Map{
|
||||
"id": log.MessageTask.Id,
|
||||
"user": log.MessageTask.User,
|
||||
"subject": log.MessageTask.Subject,
|
||||
"body": log.MessageTask.Body,
|
||||
"instance": maps.Map{
|
||||
"id": log.MessageTask.MessageMediaInstance.Id,
|
||||
"name": log.MessageTask.MessageMediaInstance.Name,
|
||||
},
|
||||
},
|
||||
"isOk": log.IsOk,
|
||||
"error": log.Error,
|
||||
"response": log.Response,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", log.CreatedAt),
|
||||
})
|
||||
}
|
||||
this.Data["logs"] = logMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package logs
|
||||
|
||||
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.AdminModuleCodeAdmin)).
|
||||
Data("teaMenu", "admins").
|
||||
Data("teaSubMenu", "recipients").
|
||||
Prefix("/admins/recipients/logs").
|
||||
Get("", new(IndexAction)).
|
||||
Post("/updateTaskStatus", new(UpdateTaskStatusAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type UpdateTaskStatusAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateTaskStatusAction) RunPost(params struct {
|
||||
TaskId int64
|
||||
Status int32
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.MessageTask_LogUpdateMessageTaskStatus, params.TaskId, pb.UpdateMessageTaskStatusRequest_MessageTaskStatusNone)
|
||||
|
||||
_, err := this.RPC().MessageTaskRPC().UpdateMessageTaskStatus(this.AdminContext(), &pb.UpdateMessageTaskStatusRequest{
|
||||
MessageTaskId: params.TaskId,
|
||||
Status: pb.UpdateMessageTaskStatusRequest_Status(params.Status),
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package recipients
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// 媒介类型选项
|
||||
type MediaOptionsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *MediaOptionsAction) RunPost(params struct{}) {
|
||||
resp, err := this.RPC().MessageMediaRPC().FindAllMessageMedias(this.AdminContext(), &pb.FindAllMessageMediasRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
mediaMaps := []maps.Map{}
|
||||
for _, media := range resp.MessageMedias {
|
||||
mediaMaps = append(mediaMaps, maps.Map{
|
||||
"id": media.Id,
|
||||
"type": media.Type,
|
||||
"name": media.Name,
|
||||
"description": media.Description,
|
||||
})
|
||||
}
|
||||
this.Data["medias"] = mediaMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package receivers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
ReceiverId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.MessageReceiver_LogDeleteReceiver, params.ReceiverId)
|
||||
|
||||
_, err := this.RPC().MessageReceiverRPC().DeleteMessageReceiver(this.AdminContext(), &pb.DeleteMessageReceiverRequest{MessageReceiverId: params.ReceiverId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package receivers
|
||||
|
||||
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.AdminModuleCodeAdmin)).
|
||||
Data("teaMenu", "admins").
|
||||
Prefix("/admins/recipients/receivers").
|
||||
Post("/delete", new(DeleteAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package recipients
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type RecipientAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *RecipientAction) Init() {
|
||||
this.Nav("", "", "recipient")
|
||||
}
|
||||
|
||||
func (this *RecipientAction) RunGet(params struct {
|
||||
RecipientId int64
|
||||
}) {
|
||||
recipientResp, err := this.RPC().MessageRecipientRPC().FindEnabledMessageRecipient(this.AdminContext(), &pb.FindEnabledMessageRecipientRequest{MessageRecipientId: params.RecipientId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var recipient = recipientResp.MessageRecipient
|
||||
if recipient == nil || recipient.Admin == nil || recipient.MessageMediaInstance == nil {
|
||||
this.NotFound("messageRecipient", params.RecipientId)
|
||||
return
|
||||
}
|
||||
|
||||
// 已关联的接收者
|
||||
receiversResp, err := this.RPC().MessageReceiverRPC().FindAllEnabledMessageReceiversWithMessageRecipientId(this.AdminContext(), &pb.FindAllEnabledMessageReceiversWithMessageRecipientIdRequest{
|
||||
MessageRecipientId: params.RecipientId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// node clusters
|
||||
var nodeClusterMaps = []maps.Map{}
|
||||
for _, receiver := range receiversResp.MessageReceivers {
|
||||
if receiver.Role == nodeconfigs.NodeRoleNode && receiver.ClusterId > 0 && receiver.NodeId == 0 && receiver.ServerId == 0 {
|
||||
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: receiver.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var cluster = clusterResp.NodeCluster
|
||||
if cluster != nil {
|
||||
nodeClusterMaps = append(nodeClusterMaps, maps.Map{
|
||||
"receiverId": receiver.Id,
|
||||
"id": cluster.Id,
|
||||
"name": cluster.Name,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["nodeClusters"] = nodeClusterMaps
|
||||
|
||||
this.Data["recipient"] = maps.Map{
|
||||
"id": recipient.Id,
|
||||
"admin": maps.Map{
|
||||
"id": recipient.Admin.Id,
|
||||
"fullname": recipient.Admin.Fullname,
|
||||
"username": recipient.Admin.Username,
|
||||
},
|
||||
"groups": recipient.MessageRecipientGroups,
|
||||
"isOn": recipient.IsOn,
|
||||
"instance": maps.Map{
|
||||
"id": recipient.MessageMediaInstance.Id,
|
||||
"name": recipient.MessageMediaInstance.Name,
|
||||
"description": recipient.MessageMediaInstance.Description,
|
||||
},
|
||||
"user": recipient.User,
|
||||
"description": recipient.Description,
|
||||
"timeFrom": recipient.TimeFrom,
|
||||
"timeTo": recipient.TimeTo,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
TaskId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.MessageTask_LogDeleteMessageTask, params.TaskId)
|
||||
|
||||
_, err := this.RPC().MessageTaskRPC().DeleteMessageTask(this.AdminContext(), &pb.DeleteMessageTaskRequest{MessageTaskId: params.TaskId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"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("", "", "task")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
Status int32
|
||||
}) {
|
||||
this.Data["status"] = params.Status
|
||||
if params.Status > 3 {
|
||||
params.Status = 0
|
||||
}
|
||||
|
||||
countWaitingResp, err := this.RPC().MessageTaskRPC().CountMessageTasksWithStatus(this.AdminContext(), &pb.CountMessageTasksWithStatusRequest{Status: pb.CountMessageTasksWithStatusRequest_MessageTaskStatusNone})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var countWaiting = countWaitingResp.Count
|
||||
this.Data["countWaiting"] = countWaiting
|
||||
|
||||
countFailedResp, err := this.RPC().MessageTaskRPC().CountMessageTasksWithStatus(this.AdminContext(), &pb.CountMessageTasksWithStatusRequest{Status: pb.CountMessageTasksWithStatusRequest_MessageTaskStatusFailed})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var countFailed = countFailedResp.Count
|
||||
this.Data["countFailed"] = countFailed
|
||||
|
||||
// 列表
|
||||
var total = int64(0)
|
||||
switch params.Status {
|
||||
case 0:
|
||||
total = countWaiting
|
||||
case 3:
|
||||
total = countFailed
|
||||
}
|
||||
page := this.NewPage(total)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
var taskMaps = []maps.Map{}
|
||||
tasksResp, err := this.RPC().MessageTaskRPC().ListMessageTasksWithStatus(this.AdminContext(), &pb.ListMessageTasksWithStatusRequest{
|
||||
Status: pb.ListMessageTasksWithStatusRequest_Status(params.Status),
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
for _, task := range tasksResp.MessageTasks {
|
||||
var resultMap = maps.Map{}
|
||||
var result = task.Result
|
||||
if result != nil {
|
||||
resultMap = maps.Map{
|
||||
"isOk": result.IsOk,
|
||||
"error": result.Error,
|
||||
"response": result.Response,
|
||||
}
|
||||
}
|
||||
|
||||
//var recipients = []string{}
|
||||
var user = ""
|
||||
var instanceMap maps.Map
|
||||
if task.MessageRecipient != nil {
|
||||
user = task.MessageRecipient.User
|
||||
if task.MessageRecipient.MessageMediaInstance != nil {
|
||||
instanceMap = maps.Map{
|
||||
"id": task.MessageRecipient.MessageMediaInstance.Id,
|
||||
"name": task.MessageRecipient.MessageMediaInstance.Name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
taskMaps = append(taskMaps, maps.Map{
|
||||
"id": task.Id,
|
||||
"subject": task.Subject,
|
||||
"body": task.Body,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", task.CreatedAt),
|
||||
"result": resultMap,
|
||||
"status": task.Status,
|
||||
"user": user,
|
||||
"instance": instanceMap,
|
||||
})
|
||||
}
|
||||
this.Data["tasks"] = taskMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package tasks
|
||||
|
||||
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.AdminModuleCodeAdmin)).
|
||||
Data("teaMenu", "admins").
|
||||
Data("teaSubMenu", "recipients").
|
||||
Prefix("/admins/recipients/tasks").
|
||||
Get("", new(IndexAction)).
|
||||
Post("/taskInfo", new(TaskInfoAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type TaskInfoAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *TaskInfoAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *TaskInfoAction) RunPost(params struct {
|
||||
TaskId int64
|
||||
}) {
|
||||
resp, err := this.RPC().MessageTaskRPC().FindEnabledMessageTask(this.AdminContext(), &pb.FindEnabledMessageTaskRequest{MessageTaskId: params.TaskId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if resp.MessageTask == nil {
|
||||
this.NotFound("messageTask", params.TaskId)
|
||||
return
|
||||
}
|
||||
|
||||
result := resp.MessageTask.Result
|
||||
this.Data["status"] = resp.MessageTask.Status
|
||||
this.Data["result"] = maps.Map{
|
||||
"isOk": result.IsOk,
|
||||
"response": result.Response,
|
||||
"error": result.Error,
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
114
EdgeAdmin/internal/web/actions/default/admins/recipients/test.go
Normal file
114
EdgeAdmin/internal/web/actions/default/admins/recipients/test.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package recipients
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type TestAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *TestAction) Init() {
|
||||
this.Nav("", "", "test")
|
||||
}
|
||||
|
||||
func (this *TestAction) RunGet(params struct {
|
||||
RecipientId int64
|
||||
}) {
|
||||
recipientResp, err := this.RPC().MessageRecipientRPC().FindEnabledMessageRecipient(this.AdminContext(), &pb.FindEnabledMessageRecipientRequest{MessageRecipientId: params.RecipientId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
recipient := recipientResp.MessageRecipient
|
||||
if recipient == nil || recipient.Admin == nil || recipient.MessageMediaInstance == nil {
|
||||
this.NotFound("messageRecipient", params.RecipientId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["recipient"] = maps.Map{
|
||||
"id": recipient.Id,
|
||||
"admin": maps.Map{
|
||||
"id": recipient.Admin.Id,
|
||||
"fullname": recipient.Admin.Fullname,
|
||||
"username": recipient.Admin.Username,
|
||||
},
|
||||
"instance": maps.Map{
|
||||
"id": recipient.MessageMediaInstance.Id,
|
||||
"name": recipient.MessageMediaInstance.Name,
|
||||
"description": recipient.MessageMediaInstance.Description,
|
||||
},
|
||||
"user": recipient.User,
|
||||
}
|
||||
|
||||
instanceResp, err := this.RPC().MessageMediaInstanceRPC().FindEnabledMessageMediaInstance(this.AdminContext(), &pb.FindEnabledMessageMediaInstanceRequest{MessageMediaInstanceId: recipient.MessageMediaInstance.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
instance := instanceResp.MessageMediaInstance
|
||||
if instance == nil || instance.MessageMedia == nil {
|
||||
this.NotFound("messageMediaInstance", recipient.MessageMediaInstance.Id)
|
||||
return
|
||||
}
|
||||
|
||||
mediaParams := maps.Map{}
|
||||
if len(instance.ParamsJSON) > 0 {
|
||||
err = json.Unmarshal(instance.ParamsJSON, &mediaParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["instance"] = maps.Map{
|
||||
"id": instance.Id,
|
||||
"isOn": instance.IsOn,
|
||||
"media": maps.Map{
|
||||
"type": instance.MessageMedia.Type,
|
||||
"name": instance.MessageMedia.Name,
|
||||
"userDescription": instance.MessageMedia.UserDescription,
|
||||
},
|
||||
"description": instance.Description,
|
||||
"params": mediaParams,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *TestAction) RunPost(params struct {
|
||||
InstanceId int64
|
||||
Subject string
|
||||
Body string
|
||||
User string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
params.Must.
|
||||
Field("instanceId", params.InstanceId).
|
||||
Gt(0, "请选择正确的媒介")
|
||||
|
||||
resp, err := this.RPC().MessageTaskRPC().SendMessageTask(this.AdminContext(), &pb.SendMessageTaskRequest{
|
||||
MessageMediaInstanceId: params.InstanceId,
|
||||
User: params.User,
|
||||
Subject: params.Subject,
|
||||
Body: params.Body,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["result"] = maps.Map{
|
||||
"isOk": resp.IsOk,
|
||||
"error": resp.Error,
|
||||
"response": resp.Response,
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
package recipients
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type UpdateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateAction) Init() {
|
||||
this.Nav("", "", "update")
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunGet(params struct {
|
||||
RecipientId int64
|
||||
}) {
|
||||
recipientResp, err := this.RPC().MessageRecipientRPC().FindEnabledMessageRecipient(this.AdminContext(), &pb.FindEnabledMessageRecipientRequest{MessageRecipientId: params.RecipientId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var recipient = recipientResp.MessageRecipient
|
||||
if recipient == nil || recipient.Admin == nil || recipient.MessageMediaInstance == nil {
|
||||
this.NotFound("messageRecipient", params.RecipientId)
|
||||
return
|
||||
}
|
||||
|
||||
var timeFromHour = ""
|
||||
var timeFromMinute = ""
|
||||
var timeFromSecond = ""
|
||||
|
||||
if len(recipient.TimeFrom) > 0 {
|
||||
var pieces = strings.Split(recipient.TimeFrom, ":")
|
||||
timeFromHour = pieces[0]
|
||||
timeFromMinute = pieces[1]
|
||||
timeFromSecond = pieces[2]
|
||||
}
|
||||
|
||||
var timeToHour = ""
|
||||
var timeToMinute = ""
|
||||
var timeToSecond = ""
|
||||
if len(recipient.TimeTo) > 0 {
|
||||
var pieces = strings.Split(recipient.TimeTo, ":")
|
||||
timeToHour = pieces[0]
|
||||
timeToMinute = pieces[1]
|
||||
timeToSecond = pieces[2]
|
||||
}
|
||||
|
||||
this.Data["recipient"] = maps.Map{
|
||||
"id": recipient.Id,
|
||||
"admin": maps.Map{
|
||||
"id": recipient.Admin.Id,
|
||||
"fullname": recipient.Admin.Fullname,
|
||||
"username": recipient.Admin.Username,
|
||||
},
|
||||
"groups": recipient.MessageRecipientGroups,
|
||||
"isOn": recipient.IsOn,
|
||||
"instance": maps.Map{
|
||||
"id": recipient.MessageMediaInstance.Id,
|
||||
"name": recipient.MessageMediaInstance.Name,
|
||||
},
|
||||
"user": recipient.User,
|
||||
"description": recipient.Description,
|
||||
"timeFromHour": timeFromHour,
|
||||
"timeFromMinute": timeFromMinute,
|
||||
"timeFromSecond": timeFromSecond,
|
||||
"timeToHour": timeToHour,
|
||||
"timeToMinute": timeToMinute,
|
||||
"timeToSecond": timeToSecond,
|
||||
}
|
||||
|
||||
// receivers
|
||||
var nodeClusterIds []int64
|
||||
|
||||
receiversResp, err := this.RPC().MessageReceiverRPC().FindAllEnabledMessageReceiversWithMessageRecipientId(this.AdminContext(), &pb.FindAllEnabledMessageReceiversWithMessageRecipientIdRequest{MessageRecipientId: params.RecipientId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
for _, receiver := range receiversResp.MessageReceivers {
|
||||
if receiver.Role == nodeconfigs.NodeRoleNode {
|
||||
if receiver.ClusterId > 0 && receiver.NodeId == 0 && receiver.ServerId == 0 {
|
||||
nodeClusterIds = append(nodeClusterIds, receiver.ClusterId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// node clusters
|
||||
nodeClustersResp, err := this.RPC().NodeClusterRPC().FindAllEnabledNodeClusters(this.AdminContext(), &pb.FindAllEnabledNodeClustersRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var nodeClusterMaps = []maps.Map{}
|
||||
for _, nodeCluster := range nodeClustersResp.NodeClusters {
|
||||
nodeClusterMaps = append(nodeClusterMaps, maps.Map{
|
||||
"id": nodeCluster.Id,
|
||||
"name": nodeCluster.Name,
|
||||
"isChecked": lists.ContainsInt64(nodeClusterIds, nodeCluster.Id),
|
||||
})
|
||||
}
|
||||
this.Data["nodeClusters"] = nodeClusterMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunPost(params struct {
|
||||
RecipientId int64
|
||||
|
||||
AdminId int64
|
||||
User string
|
||||
InstanceId int64
|
||||
|
||||
GroupIds string
|
||||
Description string
|
||||
IsOn bool
|
||||
|
||||
TimeFromHour string
|
||||
TimeFromMinute string
|
||||
TimeFromSecond string
|
||||
|
||||
TimeToHour string
|
||||
TimeToMinute string
|
||||
TimeToSecond string
|
||||
|
||||
NodeClusterIds []int64
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.MessageRecipient_LogUpdateMessageRecipient, params.RecipientId)
|
||||
|
||||
params.Must.
|
||||
Field("adminId", params.AdminId).
|
||||
Gt(0, "请选择系统用户").
|
||||
Field("instanceId", params.InstanceId).
|
||||
Gt(0, "请选择媒介")
|
||||
|
||||
groupIds := utils.SplitNumbers(params.GroupIds)
|
||||
|
||||
var digitReg = regexp.MustCompile(`^\d+$`)
|
||||
|
||||
var timeFrom = ""
|
||||
if digitReg.MatchString(params.TimeFromHour) && digitReg.MatchString(params.TimeFromMinute) && digitReg.MatchString(params.TimeFromSecond) {
|
||||
timeFrom = params.TimeFromHour + ":" + params.TimeFromMinute + ":" + params.TimeFromSecond
|
||||
}
|
||||
|
||||
var timeTo = ""
|
||||
if digitReg.MatchString(params.TimeToHour) && digitReg.MatchString(params.TimeToMinute) && digitReg.MatchString(params.TimeToSecond) {
|
||||
timeTo = params.TimeToHour + ":" + params.TimeToMinute + ":" + params.TimeToSecond
|
||||
}
|
||||
|
||||
_, err := this.RPC().MessageRecipientRPC().UpdateMessageRecipient(this.AdminContext(), &pb.UpdateMessageRecipientRequest{
|
||||
MessageRecipientId: params.RecipientId,
|
||||
AdminId: params.AdminId,
|
||||
MessageMediaInstanceId: params.InstanceId,
|
||||
User: params.User,
|
||||
MessageRecipientGroupIds: groupIds,
|
||||
Description: params.Description,
|
||||
IsOn: params.IsOn,
|
||||
TimeFrom: timeFrom,
|
||||
TimeTo: timeTo,
|
||||
NodeClusterIds: params.NodeClusterIds,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
215
EdgeAdmin/internal/web/actions/default/admins/update.go
Normal file
215
EdgeAdmin/internal/web/actions/default/admins/update.go
Normal file
@@ -0,0 +1,215 @@
|
||||
package admins
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/xlzd/gotp"
|
||||
)
|
||||
|
||||
type UpdateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateAction) Init() {
|
||||
this.Nav("", "", "update")
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunGet(params struct {
|
||||
AdminId int64
|
||||
}) {
|
||||
adminResp, err := this.RPC().AdminRPC().FindEnabledAdmin(this.AdminContext(), &pb.FindEnabledAdminRequest{AdminId: params.AdminId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var admin = adminResp.Admin
|
||||
if admin == nil {
|
||||
this.NotFound("admin", params.AdminId)
|
||||
return
|
||||
}
|
||||
|
||||
// OTP认证
|
||||
var otpLoginIsOn = false
|
||||
if admin.OtpLogin != nil {
|
||||
otpLoginIsOn = admin.OtpLogin.IsOn
|
||||
}
|
||||
|
||||
// AccessKey数量
|
||||
countAccessKeyResp, err := this.RPC().UserAccessKeyRPC().CountAllEnabledUserAccessKeys(this.AdminContext(), &pb.CountAllEnabledUserAccessKeysRequest{AdminId: params.AdminId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var countAccessKeys = countAccessKeyResp.Count
|
||||
|
||||
this.Data["admin"] = maps.Map{
|
||||
"id": admin.Id,
|
||||
"fullname": admin.Fullname,
|
||||
"username": admin.Username,
|
||||
"isOn": admin.IsOn,
|
||||
"isSuper": admin.IsSuper,
|
||||
"canLogin": admin.CanLogin,
|
||||
"otpLoginIsOn": otpLoginIsOn,
|
||||
"countAccessKeys": countAccessKeys,
|
||||
}
|
||||
|
||||
// 权限
|
||||
var moduleMaps = configloaders.AllModuleMaps(this.LangCode())
|
||||
for _, m := range moduleMaps {
|
||||
code := m.GetString("code")
|
||||
isChecked := false
|
||||
for _, module := range admin.Modules {
|
||||
if module.Code == code {
|
||||
isChecked = true
|
||||
break
|
||||
}
|
||||
}
|
||||
m["isChecked"] = isChecked
|
||||
}
|
||||
this.Data["modules"] = moduleMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunPost(params struct {
|
||||
AdminId int64
|
||||
|
||||
Fullname string
|
||||
Username string
|
||||
Pass1 string
|
||||
Pass2 string
|
||||
ModuleCodes []string
|
||||
IsOn bool
|
||||
IsSuper bool
|
||||
CanLogin bool
|
||||
|
||||
// OTP
|
||||
OtpOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.Admin_LogUpdateAdmin, params.AdminId)
|
||||
|
||||
params.Must.
|
||||
Field("fullname", params.Fullname).
|
||||
Require("请输入系统用户全名")
|
||||
|
||||
params.Must.
|
||||
Field("username", params.Username).
|
||||
Require("请输入登录用户名").
|
||||
Match(`^[a-zA-Z0-9_]+$`, "用户名中只能包含英文、数字或下划线")
|
||||
|
||||
existsResp, err := this.RPC().AdminRPC().CheckAdminUsername(this.AdminContext(), &pb.CheckAdminUsernameRequest{
|
||||
AdminId: params.AdminId,
|
||||
Username: params.Username,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if existsResp.Exists {
|
||||
this.FailField("username", "此用户名已经被别的系统用户使用,请换一个")
|
||||
}
|
||||
|
||||
if len(params.Pass1) > 0 {
|
||||
params.Must.
|
||||
Field("pass1", params.Pass1).
|
||||
Require("请输入登录密码").
|
||||
Field("pass2", params.Pass2).
|
||||
Require("请输入确认登录密码")
|
||||
if params.Pass1 != params.Pass2 {
|
||||
this.FailField("pass2", "两次输入的密码不一致")
|
||||
}
|
||||
}
|
||||
|
||||
modules := []*systemconfigs.AdminModule{}
|
||||
for _, code := range params.ModuleCodes {
|
||||
modules = append(modules, &systemconfigs.AdminModule{
|
||||
Code: code,
|
||||
AllowAll: true,
|
||||
Actions: nil, // TODO 后期再开放细粒度控制
|
||||
})
|
||||
}
|
||||
modulesJSON, err := json.Marshal(modules)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().AdminRPC().UpdateAdmin(this.AdminContext(), &pb.UpdateAdminRequest{
|
||||
AdminId: params.AdminId,
|
||||
Username: params.Username,
|
||||
Password: params.Pass1,
|
||||
Fullname: params.Fullname,
|
||||
ModulesJSON: modulesJSON,
|
||||
IsSuper: params.IsSuper,
|
||||
IsOn: params.IsOn,
|
||||
CanLogin: params.CanLogin,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 修改OTP
|
||||
otpLoginResp, err := this.RPC().LoginRPC().FindEnabledLogin(this.AdminContext(), &pb.FindEnabledLoginRequest{
|
||||
AdminId: params.AdminId,
|
||||
Type: "otp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
{
|
||||
otpLogin := otpLoginResp.Login
|
||||
if params.OtpOn {
|
||||
if otpLogin == nil {
|
||||
otpLogin = &pb.Login{
|
||||
Id: 0,
|
||||
Type: "otp",
|
||||
ParamsJSON: maps.Map{
|
||||
"secret": gotp.RandomSecret(16), // TODO 改成可以设置secret长度
|
||||
}.AsJSON(),
|
||||
IsOn: true,
|
||||
AdminId: params.AdminId,
|
||||
UserId: 0,
|
||||
}
|
||||
} else {
|
||||
// 如果已经有了,就覆盖,这样可以保留既有的参数
|
||||
otpLogin.IsOn = true
|
||||
}
|
||||
|
||||
_, err = this.RPC().LoginRPC().UpdateLogin(this.AdminContext(), &pb.UpdateLoginRequest{Login: otpLogin})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
_, err = this.RPC().LoginRPC().UpdateLogin(this.AdminContext(), &pb.UpdateLoginRequest{Login: &pb.Login{
|
||||
Type: "otp",
|
||||
IsOn: false,
|
||||
AdminId: params.AdminId,
|
||||
}})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 通知更改
|
||||
err = configloaders.NotifyAdminModuleMappingChange()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user