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 {
|
||||
UserId int64
|
||||
}) {
|
||||
this.Data["userId"] = params.UserId
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
UserId int64
|
||||
Description string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
params.Must.
|
||||
Field("description", params.Description).
|
||||
Require("请输入备注")
|
||||
|
||||
accessKeyIdResp, err := this.RPC().UserAccessKeyRPC().CreateUserAccessKey(this.AdminContext(), &pb.CreateUserAccessKeyRequest{
|
||||
UserId: params.UserId,
|
||||
Description: params.Description,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
defer this.CreateLogInfo(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/users/userutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "accessKey")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
UserId int64
|
||||
}) {
|
||||
err := userutils.InitUser(this.Parent(), params.UserId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
accessKeysResp, err := this.RPC().UserAccessKeyRPC().FindAllEnabledUserAccessKeys(this.AdminContext(), &pb.FindAllEnabledUserAccessKeysRequest{UserId: params.UserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
accessKeyMaps := []maps.Map{}
|
||||
for _, accessKey := range accessKeysResp.UserAccessKeys {
|
||||
var accessedTime string
|
||||
if accessKey.AccessedAt > 0 {
|
||||
accessedTime = timeutil.FormatTime("Y-m-d H:i:s", accessKey.AccessedAt)
|
||||
}
|
||||
accessKeyMaps = append(accessKeyMaps, maps.Map{
|
||||
"id": accessKey.Id,
|
||||
"isOn": accessKey.IsOn,
|
||||
"uniqueId": accessKey.UniqueId,
|
||||
"secret": accessKey.Secret,
|
||||
"description": accessKey.Description,
|
||||
"accessedTime": accessedTime,
|
||||
})
|
||||
}
|
||||
this.Data["accessKeys"] = accessKeyMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
179
EdgeAdmin/internal/web/actions/default/users/createPopup.go
Normal file
179
EdgeAdmin/internal/web/actions/default/users/createPopup.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"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/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"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.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Username string
|
||||
Pass1 string
|
||||
Pass2 string
|
||||
Fullname string
|
||||
Mobile string
|
||||
Tel string
|
||||
Email string
|
||||
Remark string
|
||||
ClusterId int64
|
||||
FeaturesType string
|
||||
|
||||
// OTP
|
||||
OtpOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var userId int64
|
||||
|
||||
defer func() {
|
||||
this.CreateLogInfo(codes.User_LogCreateUser, userId)
|
||||
}()
|
||||
|
||||
params.Must.
|
||||
Field("username", params.Username).
|
||||
Require("请输入用户名").
|
||||
Match(`^[a-zA-Z0-9_]+$`, "用户名中只能含有英文、数字和下划线")
|
||||
|
||||
checkUsernameResp, err := this.RPC().UserRPC().CheckUserUsername(this.AdminContext(), &pb.CheckUserUsernameRequest{
|
||||
UserId: 0,
|
||||
Username: params.Username,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if checkUsernameResp.Exists {
|
||||
this.FailField("username", "此用户名已经被占用,请换一个")
|
||||
}
|
||||
|
||||
params.Must.
|
||||
Field("pass1", params.Pass1).
|
||||
Require("请输入密码").
|
||||
Field("pass2", params.Pass2).
|
||||
Require("请再次输入确认密码").
|
||||
Equal(params.Pass1, "两次输入的密码不一致")
|
||||
|
||||
params.Must.
|
||||
Field("fullname", params.Fullname).
|
||||
Require("请输入全名")
|
||||
|
||||
if params.ClusterId <= 0 {
|
||||
this.Fail("请选择关联集群")
|
||||
}
|
||||
|
||||
if len(params.Mobile) > 0 {
|
||||
params.Must.
|
||||
Field("mobile", params.Mobile).
|
||||
Mobile("请输入正确的手机号")
|
||||
}
|
||||
if len(params.Email) > 0 {
|
||||
params.Must.
|
||||
Field("email", params.Email).
|
||||
Email("请输入正确的电子邮箱")
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().UserRPC().CreateUser(this.AdminContext(), &pb.CreateUserRequest{
|
||||
Username: params.Username,
|
||||
Password: params.Pass1,
|
||||
Fullname: params.Fullname,
|
||||
Mobile: params.Mobile,
|
||||
Tel: params.Tel,
|
||||
Email: params.Email,
|
||||
Remark: params.Remark,
|
||||
Source: "admin:" + numberutils.FormatInt64(this.AdminId()),
|
||||
NodeClusterId: params.ClusterId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
userId = createResp.UserId
|
||||
|
||||
// 功能
|
||||
if teaconst.IsPlus {
|
||||
if params.FeaturesType == "default" {
|
||||
resp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeUserRegisterConfig})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var config = userconfigs.DefaultUserRegisterConfig()
|
||||
if len(resp.ValueJSON) > 0 {
|
||||
err = json.Unmarshal(resp.ValueJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().UserRPC().UpdateUserFeatures(this.AdminContext(), &pb.UpdateUserFeaturesRequest{
|
||||
UserId: userId,
|
||||
FeatureCodes: config.Features,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else if params.FeaturesType == "all" {
|
||||
featuresResp, err := this.RPC().UserRPC().FindAllUserFeatureDefinitions(this.AdminContext(), &pb.FindAllUserFeatureDefinitionsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var featureCodes = []string{}
|
||||
for _, def := range featuresResp.Features {
|
||||
featureCodes = append(featureCodes, def.Code)
|
||||
}
|
||||
_, err = this.RPC().UserRPC().UpdateUserFeatures(this.AdminContext(), &pb.UpdateUserFeaturesRequest{
|
||||
UserId: userId,
|
||||
FeatureCodes: featureCodes,
|
||||
})
|
||||
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: 0,
|
||||
UserId: userId,
|
||||
}})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
27
EdgeAdmin/internal/web/actions/default/users/delete.go
Normal file
27
EdgeAdmin/internal/web/actions/default/users/delete.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package users
|
||||
|
||||
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 {
|
||||
UserId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.User_LogDeleteUser, params.UserId)
|
||||
|
||||
// TODO 检查用户是否有未完成的业务
|
||||
|
||||
_, err := this.RPC().UserRPC().DeleteUser(this.AdminContext(), &pb.DeleteUserRequest{UserId: params.UserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
79
EdgeAdmin/internal/web/actions/default/users/features.go
Normal file
79
EdgeAdmin/internal/web/actions/default/users/features.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/users/userutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type FeaturesAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *FeaturesAction) Init() {
|
||||
this.Nav("", "", "feature")
|
||||
}
|
||||
|
||||
func (this *FeaturesAction) RunGet(params struct {
|
||||
UserId int64
|
||||
}) {
|
||||
err := userutils.InitUser(this.Parent(), params.UserId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
featuresResp, err := this.RPC().UserRPC().FindAllUserFeatureDefinitions(this.AdminContext(), &pb.FindAllUserFeatureDefinitionsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
allFeatures := featuresResp.Features
|
||||
|
||||
userFeaturesResp, err := this.RPC().UserRPC().FindUserFeatures(this.AdminContext(), &pb.FindUserFeaturesRequest{UserId: params.UserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
userFeatureCodes := []string{}
|
||||
for _, userFeature := range userFeaturesResp.Features {
|
||||
userFeatureCodes = append(userFeatureCodes, userFeature.Code)
|
||||
}
|
||||
|
||||
featureMaps := []maps.Map{}
|
||||
for _, feature := range allFeatures {
|
||||
featureMaps = append(featureMaps, maps.Map{
|
||||
"name": feature.Name,
|
||||
"code": feature.Code,
|
||||
"description": feature.Description,
|
||||
"isChecked": lists.ContainsString(userFeatureCodes, feature.Code),
|
||||
})
|
||||
}
|
||||
this.Data["features"] = featureMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *FeaturesAction) RunPost(params struct {
|
||||
UserId int64
|
||||
Codes []string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.User_LogUpdateUserFeatures, params.UserId)
|
||||
|
||||
_, err := this.RPC().UserRPC().UpdateUserFeatures(this.AdminContext(), &pb.UpdateUserFeaturesRequest{
|
||||
UserId: params.UserId,
|
||||
FeatureCodes: params.Codes,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package identity
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/users/userutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type EnterpriseAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *EnterpriseAction) Init() {
|
||||
this.Nav("", "", "identity")
|
||||
}
|
||||
|
||||
func (this *EnterpriseAction) RunGet(params struct {
|
||||
UserId int64
|
||||
}) {
|
||||
err := userutils.InitUser(this.Parent(), params.UserId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
userIdentityResp, err := this.RPC().UserIdentityRPC().FindEnabledUserIdentityWithOrgType(this.AdminContext(), &pb.FindEnabledUserIdentityWithOrgTypeRequest{
|
||||
UserId: params.UserId,
|
||||
OrgType: userconfigs.UserIdentityOrgTypeEnterprise,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var identity = userIdentityResp.UserIdentity
|
||||
if identity == nil {
|
||||
this.Data["identity"] = nil
|
||||
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
|
||||
if identity.FileIds == nil {
|
||||
identity.FileIds = []int64{0}
|
||||
}
|
||||
var frontFileId int64 = 0
|
||||
if len(identity.FileIds) > 0 {
|
||||
frontFileId = identity.FileIds[0]
|
||||
}
|
||||
|
||||
this.Data["identity"] = maps.Map{
|
||||
"id": identity.Id,
|
||||
"realName": identity.RealName,
|
||||
"number": identity.Number,
|
||||
"fileIds": identity.FileIds,
|
||||
"frontFileId": frontFileId,
|
||||
"status": identity.Status,
|
||||
"rejectReason": identity.RejectReason,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package identity
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/users/userutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "identity")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
UserId int64
|
||||
}) {
|
||||
err := userutils.InitUser(this.Parent(), params.UserId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
userIdentityResp, err := this.RPC().UserIdentityRPC().FindEnabledUserIdentityWithOrgType(this.AdminContext(), &pb.FindEnabledUserIdentityWithOrgTypeRequest{
|
||||
UserId: params.UserId,
|
||||
OrgType: userconfigs.UserIdentityOrgTypeIndividual,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var identity = userIdentityResp.UserIdentity
|
||||
if identity == nil {
|
||||
this.Data["identity"] = nil
|
||||
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
|
||||
if identity.FileIds == nil {
|
||||
identity.FileIds = []int64{0, 0}
|
||||
}
|
||||
var backFileId int64 = 0
|
||||
var frontFileId int64 = 0
|
||||
if len(identity.FileIds) > 0 {
|
||||
backFileId = identity.FileIds[0]
|
||||
}
|
||||
if len(identity.FileIds) > 1 {
|
||||
frontFileId = identity.FileIds[1]
|
||||
}
|
||||
|
||||
this.Data["identity"] = maps.Map{
|
||||
"id": identity.Id,
|
||||
"realName": identity.RealName,
|
||||
"number": identity.Number,
|
||||
"fileIds": identity.FileIds,
|
||||
"backFileId": backFileId,
|
||||
"frontFileId": frontFileId,
|
||||
"status": identity.Status,
|
||||
"rejectReason": identity.RejectReason,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package identity
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type RejectAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *RejectAction) RunPost(params struct {
|
||||
UserId int64
|
||||
IdentityId int64
|
||||
Reason string
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.UserIdentity_LogRejectUserIdentity, params.UserId)
|
||||
|
||||
_, err := this.RPC().UserIdentityRPC().RejectUserIdentity(this.AdminContext(), &pb.RejectUserIdentityRequest{
|
||||
UserIdentityId: params.IdentityId,
|
||||
Reason: params.Reason,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package identity
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type ResetAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ResetAction) RunPost(params struct {
|
||||
UserId int64
|
||||
IdentityId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.UserIdentity_LogResetUserIdentity, params.UserId)
|
||||
|
||||
_, err := this.RPC().UserIdentityRPC().ResetUserIdentity(this.AdminContext(), &pb.ResetUserIdentityRequest{
|
||||
UserIdentityId: params.IdentityId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package identity
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type VerifyAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *VerifyAction) RunPost(params struct {
|
||||
UserId int64
|
||||
IdentityId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.UserIdentity_LogVerifyUserIdentity, params.UserId)
|
||||
|
||||
_, err := this.RPC().UserIdentityRPC().VerifyUserIdentity(this.AdminContext(), &pb.VerifyUserIdentityRequest{
|
||||
UserIdentityId: params.IdentityId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
99
EdgeAdmin/internal/web/actions/default/users/index.go
Normal file
99
EdgeAdmin/internal/web/actions/default/users/index.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package users
|
||||
|
||||
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
|
||||
Verifying bool
|
||||
MobileIsVerified int32 `default:"-1"`
|
||||
}) {
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["isVerifying"] = params.Verifying
|
||||
this.Data["mobileIsVerified"] = params.MobileIsVerified
|
||||
|
||||
// 未审核的总数量
|
||||
countVerifyingUsersResp, err := this.RPC().UserRPC().CountAllEnabledUsers(this.AdminContext(), &pb.CountAllEnabledUsersRequest{
|
||||
IsVerifying: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["countVerifyingUsers"] = countVerifyingUsersResp.Count
|
||||
|
||||
// 当前匹配的数量
|
||||
countResp, err := this.RPC().UserRPC().CountAllEnabledUsers(this.AdminContext(), &pb.CountAllEnabledUsersRequest{
|
||||
Keyword: params.Keyword,
|
||||
IsVerifying: params.Verifying,
|
||||
MobileIsVerified: params.MobileIsVerified,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
count := countResp.Count
|
||||
page := this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
usersResp, err := this.RPC().UserRPC().ListEnabledUsers(this.AdminContext(), &pb.ListEnabledUsersRequest{
|
||||
Keyword: params.Keyword,
|
||||
IsVerifying: params.Verifying,
|
||||
MobileIsVerified: params.MobileIsVerified,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var userMaps = []maps.Map{}
|
||||
for _, user := range usersResp.Users {
|
||||
var clusterMap maps.Map = nil
|
||||
if user.NodeCluster != nil {
|
||||
clusterMap = maps.Map{
|
||||
"id": user.NodeCluster.Id,
|
||||
"name": user.NodeCluster.Name,
|
||||
}
|
||||
}
|
||||
|
||||
isSubmittedResp, err := this.RPC().UserIdentityRPC().CheckUserIdentityIsSubmitted(this.AdminContext(), &pb.CheckUserIdentityIsSubmittedRequest{UserId: user.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var identityIsSubmitted = isSubmittedResp.IsSubmitted
|
||||
|
||||
userMaps = append(userMaps, maps.Map{
|
||||
"id": user.Id,
|
||||
"username": user.Username,
|
||||
"isOn": user.IsOn,
|
||||
"fullname": user.Fullname,
|
||||
"email": user.Email,
|
||||
"mobile": user.Mobile,
|
||||
"tel": user.Tel,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", user.CreatedAt),
|
||||
"cluster": clusterMap,
|
||||
"registeredIP": user.RegisteredIP,
|
||||
"isVerified": user.IsVerified,
|
||||
"isRejected": user.IsRejected,
|
||||
"identityIsSubmitted": identityIsSubmitted,
|
||||
"verifiedMobile": user.VerifiedMobile,
|
||||
})
|
||||
}
|
||||
this.Data["users"] = userMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
38
EdgeAdmin/internal/web/actions/default/users/init.go
Normal file
38
EdgeAdmin/internal/web/actions/default/users/init.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/users/accesskeys"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeUser)).
|
||||
Data("teaMenu", "users").
|
||||
Prefix("/users").
|
||||
Data("teaSubMenu", "users").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
|
||||
// 单个用户信息
|
||||
Get("/user", new(UserAction)).
|
||||
GetPost("/update", new(UpdateAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
GetPost("/features", new(FeaturesAction)).
|
||||
GetPost("/verifyPopup", new(VerifyPopupAction)).
|
||||
Get("/otpQrcode", new(OtpQrcodeAction)).
|
||||
|
||||
// AccessKeys
|
||||
Prefix("/users/accesskeys").
|
||||
Get("", new(accesskeys.IndexAction)).
|
||||
GetPost("/createPopup", new(accesskeys.CreatePopupAction)).
|
||||
Post("/delete", new(accesskeys.DeleteAction)).
|
||||
Post("/updateIsOn", new(accesskeys.UpdateIsOnAction)).
|
||||
|
||||
//
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
51
EdgeAdmin/internal/web/actions/default/users/init_plus.go
Normal file
51
EdgeAdmin/internal/web/actions/default/users/init_plus.go
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package users
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/users/identity"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/users/setting"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/users/user"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeUser)).
|
||||
Data("teaMenu", "users").
|
||||
|
||||
// 用户相关
|
||||
Prefix("/users/user").
|
||||
Data("teaSubMenu", "users").
|
||||
Get("/servers", new(user.ServersAction)).
|
||||
EndPrefix().
|
||||
|
||||
// 设置
|
||||
Prefix("/users/setting").
|
||||
Data("teaSubMenu", "setting").
|
||||
GetPost("", new(setting.IndexAction)).
|
||||
GetPost("/server", new(setting.ServerAction)).
|
||||
GetPost("/email", new(setting.EmailAction)).
|
||||
GetPost("/emailTest", new(setting.EmailTestAction)).
|
||||
GetPost("/sms", new(setting.SmsAction)).
|
||||
GetPost("/smsTest", new(setting.SmsTestAction)).
|
||||
EndPrefix().
|
||||
|
||||
// 实名认证
|
||||
Prefix("/users/identity").
|
||||
Data("teaSubMenu", "users").
|
||||
Get("", new(identity.IndexAction)).
|
||||
Get("/enterprise", new(identity.EnterpriseAction)).
|
||||
Post("/verify", new(identity.VerifyAction)).
|
||||
Post("/reject", new(identity.RejectAction)).
|
||||
Post("/reset", new(identity.ResetAction)).
|
||||
EndPrefix().
|
||||
|
||||
//
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
78
EdgeAdmin/internal/web/actions/default/users/otpQrcode.go
Normal file
78
EdgeAdmin/internal/web/actions/default/users/otpQrcode.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"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 {
|
||||
UserId int64
|
||||
Download bool
|
||||
}) {
|
||||
loginResp, err := this.RPC().LoginRPC().FindEnabledLogin(this.AdminContext(), &pb.FindEnabledLoginRequest{
|
||||
UserId: params.UserId,
|
||||
Type: "otp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var login = loginResp.Login
|
||||
if login == nil || !login.IsOn {
|
||||
this.NotFound("userLogin", params.UserId)
|
||||
return
|
||||
}
|
||||
|
||||
var loginParams = maps.Map{}
|
||||
err = json.Unmarshal(login.ParamsJSON, &loginParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var secret = loginParams.GetString("secret")
|
||||
|
||||
// 当前用户信息
|
||||
userResp, err := this.RPC().UserRPC().FindEnabledUser(this.AdminContext(), &pb.FindEnabledUserRequest{UserId: params.UserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var user = userResp.User
|
||||
if user == nil {
|
||||
this.NotFound("user", params.UserId)
|
||||
return
|
||||
}
|
||||
|
||||
productName, err := this.findProductName()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var url = gotp.NewDefaultTOTP(secret).ProvisioningUri(user.Username, productName)
|
||||
data, err := qrcode.Encode(otputils.FixIssuer(url), qrcode.Medium, 256)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if params.Download {
|
||||
var filename = "OTP-USER-" + user.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,18 @@
|
||||
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
|
||||
package users
|
||||
|
||||
import "github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
|
||||
func (this *OtpQrcodeAction) findProductName() (string, error) {
|
||||
uiConfig, err := configloaders.LoadAdminUIConfig()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var productName = uiConfig.ProductName
|
||||
if len(productName) == 0 {
|
||||
productName = "GoEdge用户"
|
||||
}
|
||||
return productName, nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package users
|
||||
|
||||
import "github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
|
||||
func (this *OtpQrcodeAction) findProductName() (string, error) {
|
||||
uiConfig, err := configloaders.LoadUserUIConfig()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var productName = uiConfig.ProductName
|
||||
if len(productName) == 0 {
|
||||
productName = "GoEdge用户"
|
||||
}
|
||||
return productName, nil
|
||||
}
|
||||
130
EdgeAdmin/internal/web/actions/default/users/setting/email.go
Normal file
130
EdgeAdmin/internal/web/actions/default/users/setting/email.go
Normal file
@@ -0,0 +1,130 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"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/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type EmailAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *EmailAction) Init() {
|
||||
this.Nav("", "", "email")
|
||||
}
|
||||
|
||||
func (this *EmailAction) RunGet(params struct{}) {
|
||||
config, err := configloaders.LoadUserSenderConfig()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if config == nil {
|
||||
this.ErrorPage(errors.New("'config' should not be nil"))
|
||||
return
|
||||
}
|
||||
|
||||
// 验证邮件
|
||||
if config.VerifyEmail == nil {
|
||||
config.VerifyEmail = userconfigs.NewEmailSenderConfig()
|
||||
}
|
||||
|
||||
// 通知邮件
|
||||
if config.NotifyEmail == nil {
|
||||
config.NotifyEmail = userconfigs.NewEmailSenderConfig()
|
||||
}
|
||||
|
||||
this.Data["config"] = config
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *EmailAction) RunPost(params struct {
|
||||
VerifyEmailJSON []byte
|
||||
NotifyEmailJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.User_LogUpdateUserEmailSettings)
|
||||
|
||||
config, err := configloaders.LoadUserSenderConfig()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var verifyEmailConfig = userconfigs.NewEmailSenderConfig()
|
||||
err = json.Unmarshal(params.VerifyEmailJSON, verifyEmailConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
config.VerifyEmail = verifyEmailConfig
|
||||
|
||||
if verifyEmailConfig.IsOn {
|
||||
params.Must.
|
||||
Field("verifyEmailJSONSmtpHost", verifyEmailConfig.SMTPHost).
|
||||
Require("请输入SMTP地址").
|
||||
Field("verifyEmailJSONSmtpPort", verifyEmailConfig.SMTPPort).
|
||||
Gt(0, "请输入正确的SMTP端口").
|
||||
Field("verifyEmailJSONUsername", verifyEmailConfig.Username).
|
||||
Require("请输入用户名").
|
||||
Field("verifyEmailJSONPassword", verifyEmailConfig.Password).
|
||||
Require("请输入密码").
|
||||
Field("verifyEmailJSONFromEmail", verifyEmailConfig.FromEmail).
|
||||
Require("请输入发件人Email").
|
||||
Email("发件人Email格式不正确")
|
||||
}
|
||||
|
||||
var notifyEmailConfig = userconfigs.NewEmailSenderConfig()
|
||||
err = json.Unmarshal(params.NotifyEmailJSON, notifyEmailConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
config.NotifyEmail = notifyEmailConfig
|
||||
|
||||
if notifyEmailConfig.IsOn {
|
||||
params.Must.
|
||||
Field("notifyEmailJSONSmtpHost", notifyEmailConfig.SMTPHost).
|
||||
Require("请输入SMTP地址").
|
||||
Field("notifyEmailJSONSmtpPort", notifyEmailConfig.SMTPPort).
|
||||
Gt(0, "请输入正确的SMTP端口").
|
||||
Field("notifyEmailJSONUsername", notifyEmailConfig.Username).
|
||||
Require("请输入用户名").
|
||||
Field("notifyEmailJSONPassword", notifyEmailConfig.Password).
|
||||
Require("请输入密码").
|
||||
Field("notifyEmailJSONFromEmail", notifyEmailConfig.FromEmail).
|
||||
Require("请输入发件人Email").
|
||||
Email("发件人Email格式不正确")
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().SysSettingRPC().UpdateSysSetting(this.AdminContext(), &pb.UpdateSysSettingRequest{
|
||||
Code: systemconfigs.SettingCodeUserSenderConfig,
|
||||
ValueJSON: configJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type EmailTestAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *EmailTestAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *EmailTestAction) RunGet(params struct{}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *EmailTestAction) RunPost(params struct {
|
||||
ConfigJSON []byte
|
||||
ToEmail string
|
||||
Subject string
|
||||
Body string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
if len(params.ConfigJSON) == 0 {
|
||||
this.Fail("读取不到邮件配置")
|
||||
return
|
||||
}
|
||||
|
||||
var config = userconfigs.NewEmailSenderConfig()
|
||||
err := json.Unmarshal(params.ConfigJSON, config)
|
||||
if err != nil {
|
||||
this.Fail("解析邮件配置出错:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if len(config.SMTPHost) == 0 {
|
||||
this.Fail("缺少SMTP地址")
|
||||
return
|
||||
}
|
||||
if config.SMTPPort <= 0 {
|
||||
this.Fail("缺少SMTP端口")
|
||||
return
|
||||
}
|
||||
if len(config.Username) == 0 {
|
||||
this.Fail("缺少用户名")
|
||||
return
|
||||
}
|
||||
if len(config.Password) == 0 {
|
||||
this.Fail("缺少密码")
|
||||
return
|
||||
}
|
||||
if len(config.FromEmail) == 0 {
|
||||
this.Fail("缺少发件人Email")
|
||||
return
|
||||
}
|
||||
params.Must.Field("fromEmail", config.FromEmail).
|
||||
Email("发件人Email格式不正确")
|
||||
|
||||
params.Must.
|
||||
Field("toEmail", params.ToEmail).
|
||||
Require("请输入收件人Email").
|
||||
Email("请输入正确的收件人Email").
|
||||
Field("subject", params.Subject).
|
||||
Require("请输入测试标题").
|
||||
Field("body", params.Body).
|
||||
Require("请输入测试内容")
|
||||
|
||||
// 发送测试
|
||||
_, err = this.RPC().MessageMediaRPC().SendMediaMessage(this.AdminContext(), &pb.SendMediaMessageRequest{
|
||||
MediaType: "email",
|
||||
OptionsJSON: maps.Map{
|
||||
"smtp": config.SMTPHost + ":" + types.String(config.SMTPPort),
|
||||
"username": config.Username,
|
||||
"password": config.Password,
|
||||
"from": config.FromEmail,
|
||||
"fromName": config.FromName,
|
||||
}.AsJSON(),
|
||||
User: params.ToEmail,
|
||||
Subject: params.Subject,
|
||||
Body: params.Body,
|
||||
})
|
||||
if err != nil {
|
||||
this.Fail("发送失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
172
EdgeAdmin/internal/web/actions/default/users/setting/index.go
Normal file
172
EdgeAdmin/internal/web/actions/default/users/setting/index.go
Normal file
@@ -0,0 +1,172 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"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/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
if !teaconst.IsPlus {
|
||||
this.RedirectURL("/users")
|
||||
return
|
||||
}
|
||||
|
||||
// 当前配置
|
||||
resp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeUserRegisterConfig})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var config = userconfigs.DefaultUserRegisterConfig()
|
||||
if len(resp.ValueJSON) > 0 {
|
||||
err = json.Unmarshal(resp.ValueJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.Data["config"] = config
|
||||
|
||||
// 功能列表
|
||||
var featureMaps = []maps.Map{}
|
||||
for _, feature := range userconfigs.FindAllUserFeatures() {
|
||||
featureMaps = append(featureMaps, maps.Map{
|
||||
"name": feature.Name,
|
||||
"description": feature.Description,
|
||||
"code": feature.Code,
|
||||
"isChecked": lists.ContainsString(config.Features, feature.Code),
|
||||
})
|
||||
}
|
||||
this.Data["features"] = featureMaps
|
||||
|
||||
// 当前高防
|
||||
this.Data["adIsVisible"] = plus.AllowComponent(plus.ComponentCodeAntiDDoS)
|
||||
|
||||
// 当前默认的智能DNS设置
|
||||
this.Data["nsIsVisible"] = plus.AllowComponent(plus.ComponentCodeNS)
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
IsOn bool
|
||||
ComplexPassword bool
|
||||
RequireVerification bool
|
||||
RequireIdentity bool
|
||||
|
||||
CheckClientRegion bool
|
||||
|
||||
EmailVerificationIsOn bool
|
||||
EmailVerificationShowNotice bool
|
||||
EmailVerificationCanLogin bool
|
||||
EmailVerificationSubject string
|
||||
EmailVerificationBody string
|
||||
|
||||
EmailResetPasswordIsOn bool
|
||||
EmailResetPasswordSubject string
|
||||
EmailResetPasswordBody string
|
||||
|
||||
MobileVerificationIsOn bool
|
||||
MobileVerificationShowNotice bool
|
||||
MobileVerificationCanLogin bool
|
||||
MobileVerificationForce bool
|
||||
MobileVerificationBody string
|
||||
|
||||
CdnIsOn bool
|
||||
ClusterId int64
|
||||
Features []string
|
||||
FeatureOp string
|
||||
|
||||
AdIsOn bool
|
||||
|
||||
NsIsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.User_LogUpdateUserGlobalSettings)
|
||||
|
||||
params.Must.
|
||||
Field("clusterId", params.ClusterId).
|
||||
Gt(0, "请选择一个集群")
|
||||
|
||||
var config = userconfigs.DefaultUserRegisterConfig()
|
||||
config.IsOn = params.IsOn
|
||||
config.ComplexPassword = params.ComplexPassword
|
||||
config.RequireVerification = params.RequireVerification
|
||||
config.RequireIdentity = params.RequireIdentity
|
||||
|
||||
config.CheckClientRegion = params.CheckClientRegion
|
||||
|
||||
config.EmailVerification.IsOn = params.EmailVerificationIsOn
|
||||
config.EmailVerification.CanLogin = params.EmailVerificationCanLogin
|
||||
config.EmailVerification.Subject = params.EmailVerificationSubject
|
||||
config.EmailVerification.Body = params.EmailVerificationBody
|
||||
config.EmailVerification.ShowNotice = params.EmailVerificationShowNotice
|
||||
|
||||
config.MobileVerification.IsOn = params.MobileVerificationIsOn
|
||||
config.MobileVerification.CanLogin = params.MobileVerificationCanLogin
|
||||
config.MobileVerification.Force = params.MobileVerificationForce
|
||||
config.MobileVerification.Body = params.MobileVerificationBody
|
||||
config.MobileVerification.ShowNotice = params.MobileVerificationShowNotice
|
||||
|
||||
config.EmailResetPassword.IsOn = params.EmailResetPasswordIsOn
|
||||
config.EmailResetPassword.Subject = params.EmailResetPasswordSubject
|
||||
config.EmailResetPassword.Body = params.EmailResetPasswordBody
|
||||
|
||||
config.CDNIsOn = params.CdnIsOn
|
||||
config.ClusterId = params.ClusterId
|
||||
config.Features = params.Features
|
||||
|
||||
config.ADIsOn = params.AdIsOn
|
||||
|
||||
config.NSIsOn = params.NsIsOn
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().SysSettingRPC().UpdateSysSetting(this.AdminContext(), &pb.UpdateSysSettingRequest{
|
||||
Code: systemconfigs.SettingCodeUserRegisterConfig,
|
||||
ValueJSON: configJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if params.FeatureOp != "keep" {
|
||||
_, err = this.RPC().UserRPC().UpdateAllUsersFeatures(this.AdminContext(), &pb.UpdateAllUsersFeaturesRequest{
|
||||
FeatureCodes: params.Features,
|
||||
Overwrite: params.FeatureOp == "overwrite",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
110
EdgeAdmin/internal/web/actions/default/users/setting/server.go
Normal file
110
EdgeAdmin/internal/web/actions/default/users/setting/server.go
Normal file
@@ -0,0 +1,110 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type ServerAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ServerAction) Init() {
|
||||
this.Nav("", "", "server")
|
||||
}
|
||||
|
||||
func (this *ServerAction) RunGet(params struct{}) {
|
||||
// 当前配置
|
||||
resp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeUserServerConfig})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var config = userconfigs.DefaultUserServerConfig()
|
||||
if len(resp.ValueJSON) > 0 {
|
||||
err = json.Unmarshal(resp.ValueJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["config"] = config
|
||||
|
||||
// 分组
|
||||
groupsResp, err := this.RPC().ServerGroupRPC().FindAllEnabledServerGroups(this.AdminContext(), &pb.FindAllEnabledServerGroupsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var groupMaps = []maps.Map{}
|
||||
for _, group := range groupsResp.ServerGroups {
|
||||
groupMaps = append(groupMaps, maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
})
|
||||
}
|
||||
this.Data["groups"] = groupMaps
|
||||
|
||||
// 缓存
|
||||
this.Data["defaultMaxCacheKeysPerTask"] = userconfigs.MaxCacheKeysPerTask
|
||||
this.Data["defaultMaxCacheKeysPerDay"] = userconfigs.MaxCacheKeysPerDay
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *ServerAction) RunPost(params struct {
|
||||
GroupId int64
|
||||
RequirePlan bool
|
||||
EnableStat bool
|
||||
|
||||
// 缓存相关
|
||||
PurgeMaxKeysPerTask int32
|
||||
PurgeMaxKeysPerDay int32
|
||||
|
||||
FetchMaxKeysPerTask int32
|
||||
FetchMaxKeysPerDay int32
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var config = userconfigs.DefaultUserServerConfig()
|
||||
config.GroupId = params.GroupId
|
||||
config.RequirePlan = params.RequirePlan
|
||||
config.EnableStat = params.EnableStat
|
||||
|
||||
if config.HTTPCacheTaskPurgeConfig != nil {
|
||||
config.HTTPCacheTaskPurgeConfig.MaxKeysPerTask = params.PurgeMaxKeysPerTask
|
||||
config.HTTPCacheTaskPurgeConfig.MaxKeysPerDay = params.PurgeMaxKeysPerDay
|
||||
}
|
||||
|
||||
if config.HTTPCacheTaskFetchConfig != nil {
|
||||
config.HTTPCacheTaskFetchConfig.MaxKeysPerTask = params.FetchMaxKeysPerTask
|
||||
config.HTTPCacheTaskFetchConfig.MaxKeysPerDay = params.FetchMaxKeysPerDay
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().SysSettingRPC().UpdateSysSetting(this.AdminContext(), &pb.UpdateSysSettingRequest{
|
||||
Code: systemconfigs.SettingCodeUserServerConfig,
|
||||
ValueJSON: configJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
259
EdgeAdmin/internal/web/actions/default/users/setting/sms.go
Normal file
259
EdgeAdmin/internal/web/actions/default/users/setting/sms.go
Normal file
@@ -0,0 +1,259 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"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/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type SmsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *SmsAction) Init() {
|
||||
this.Nav("", "", "sms")
|
||||
}
|
||||
|
||||
func (this *SmsAction) RunGet(params struct{}) {
|
||||
config, err := configloaders.LoadUserSenderConfig()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if config == nil {
|
||||
this.ErrorPage(errors.New("'config' should not be nil"))
|
||||
return
|
||||
}
|
||||
|
||||
// 验证短信
|
||||
if config.VerifySMS == nil {
|
||||
config.VerifySMS = userconfigs.NewSMSSenderConfig()
|
||||
}
|
||||
|
||||
// 通知短信
|
||||
if config.NotifySMS == nil {
|
||||
config.NotifySMS = userconfigs.NewSMSSenderConfig()
|
||||
}
|
||||
|
||||
this.Data["config"] = config
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *SmsAction) RunPost(params struct {
|
||||
VerifySMSJSON []byte
|
||||
NotifySMSJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.User_LogUpdateUserSmsSettings)
|
||||
|
||||
config, err := configloaders.LoadUserSenderConfig()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var verifySMSConfig = userconfigs.NewSMSSenderConfig()
|
||||
err = json.Unmarshal(params.VerifySMSJSON, verifySMSConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
config.VerifySMS = verifySMSConfig
|
||||
|
||||
if verifySMSConfig.IsOn {
|
||||
switch verifySMSConfig.Type {
|
||||
case userconfigs.SMSSenderWebHook:
|
||||
if verifySMSConfig.WebHookParams == nil {
|
||||
this.Fail("请配置HTTP接口相关参数")
|
||||
return
|
||||
}
|
||||
if len(verifySMSConfig.WebHookParams.URL) == 0 {
|
||||
this.Fail("请输入激活短信HTTP接口URL地址")
|
||||
return
|
||||
}
|
||||
if !regexp.MustCompile(`^(http|https)://`).MatchString(verifySMSConfig.WebHookParams.URL) {
|
||||
this.Fail("激活短信HTTP接口URL地址必须以http://或https://开头")
|
||||
return
|
||||
}
|
||||
case userconfigs.SMSSenderAliyunSMS:
|
||||
if verifySMSConfig.AliyunSMSParams == nil {
|
||||
this.Fail("请配置阿里云短信相关参数")
|
||||
return
|
||||
}
|
||||
if len(verifySMSConfig.AliyunSMSParams.Sign) == 0 {
|
||||
this.Fail("请输入签名名称")
|
||||
return
|
||||
}
|
||||
if len(verifySMSConfig.AliyunSMSParams.TemplateCode) == 0 {
|
||||
this.Fail("请输入模板CODE")
|
||||
return
|
||||
}
|
||||
if len(verifySMSConfig.AliyunSMSParams.CodeVarName) == 0 {
|
||||
this.Fail("请输入模板中验证码变量名称")
|
||||
return
|
||||
}
|
||||
if len(verifySMSConfig.AliyunSMSParams.AccessKeyId) == 0 {
|
||||
this.Fail("请输入AccessKey ID")
|
||||
return
|
||||
}
|
||||
if len(verifySMSConfig.AliyunSMSParams.AccessKeySecret) == 0 {
|
||||
this.Fail("请输入AccessKey Secret")
|
||||
return
|
||||
}
|
||||
case userconfigs.SMSSenderTencentSMS:
|
||||
if verifySMSConfig.TencentSMSParams == nil {
|
||||
this.Fail("请配置腾讯云短信相关参数")
|
||||
return
|
||||
}
|
||||
|
||||
var digitsReg = regexp.MustCompile(`^\d+$`)
|
||||
|
||||
if len(verifySMSConfig.TencentSMSParams.SDKAppId) == 0 {
|
||||
this.Fail("请输入SDK应用ID")
|
||||
return
|
||||
}
|
||||
if !digitsReg.MatchString(verifySMSConfig.TencentSMSParams.SDKAppId) {
|
||||
this.Fail("SDK应用ID是一组数字,请重新输入")
|
||||
return
|
||||
}
|
||||
if len(verifySMSConfig.TencentSMSParams.Sign) == 0 {
|
||||
this.Fail("请输入签名内容")
|
||||
return
|
||||
}
|
||||
if len(verifySMSConfig.TencentSMSParams.TemplateId) == 0 {
|
||||
this.Fail("请输入模板ID")
|
||||
return
|
||||
}
|
||||
if !digitsReg.MatchString(verifySMSConfig.TencentSMSParams.TemplateId) {
|
||||
this.Fail("正文模板ID是一组数字,请重新输入")
|
||||
return
|
||||
}
|
||||
if len(verifySMSConfig.TencentSMSParams.AccessKeyId) == 0 {
|
||||
this.Fail("请输入密钥SecretId")
|
||||
return
|
||||
}
|
||||
if len(verifySMSConfig.TencentSMSParams.AccessKeySecret) == 0 {
|
||||
this.Fail("请输入密钥SecretKey")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var notifySMSConfig = userconfigs.NewSMSSenderConfig()
|
||||
err = json.Unmarshal(params.NotifySMSJSON, notifySMSConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
config.NotifySMS = notifySMSConfig
|
||||
|
||||
if notifySMSConfig.IsOn {
|
||||
switch notifySMSConfig.Type {
|
||||
case userconfigs.SMSSenderWebHook:
|
||||
if notifySMSConfig.WebHookParams == nil {
|
||||
this.Fail("请配置HTTP接口相关参数")
|
||||
return
|
||||
}
|
||||
if len(notifySMSConfig.WebHookParams.URL) == 0 {
|
||||
this.Fail("请输入通知短信HTTP接口URL地址")
|
||||
return
|
||||
}
|
||||
if !regexp.MustCompile(`^(http|https)://`).MatchString(notifySMSConfig.WebHookParams.URL) {
|
||||
this.Fail("通知短信HTTP接口URL地址必须以http://或https://开头")
|
||||
return
|
||||
}
|
||||
case userconfigs.SMSSenderAliyunSMS:
|
||||
if notifySMSConfig.AliyunSMSParams == nil {
|
||||
this.Fail("请配置阿里云短信相关参数")
|
||||
return
|
||||
}
|
||||
if len(notifySMSConfig.AliyunSMSParams.Sign) == 0 {
|
||||
this.Fail("请输入签名名称")
|
||||
return
|
||||
}
|
||||
if len(notifySMSConfig.AliyunSMSParams.TemplateCode) == 0 {
|
||||
this.Fail("请输入模板CODE")
|
||||
return
|
||||
}
|
||||
if len(notifySMSConfig.AliyunSMSParams.CodeVarName) == 0 {
|
||||
this.Fail("请输入模板中验证码变量名称")
|
||||
return
|
||||
}
|
||||
if len(notifySMSConfig.AliyunSMSParams.AccessKeyId) == 0 {
|
||||
this.Fail("请输入AccessKey ID")
|
||||
return
|
||||
}
|
||||
if len(notifySMSConfig.AliyunSMSParams.AccessKeySecret) == 0 {
|
||||
this.Fail("请输入AccessKey Secret")
|
||||
return
|
||||
}
|
||||
case userconfigs.SMSSenderTencentSMS:
|
||||
if notifySMSConfig.TencentSMSParams == nil {
|
||||
this.Fail("请配置腾讯云短信相关参数")
|
||||
return
|
||||
}
|
||||
|
||||
var digitsReg = regexp.MustCompile(`^\d+$`)
|
||||
|
||||
if len(notifySMSConfig.TencentSMSParams.SDKAppId) == 0 {
|
||||
this.Fail("请输入SDK应用ID")
|
||||
return
|
||||
}
|
||||
if !digitsReg.MatchString(notifySMSConfig.TencentSMSParams.SDKAppId) {
|
||||
this.Fail("SDK应用ID是一组数字,请重新输入")
|
||||
return
|
||||
}
|
||||
if len(notifySMSConfig.TencentSMSParams.Sign) == 0 {
|
||||
this.Fail("请输入签名内容")
|
||||
return
|
||||
}
|
||||
if len(notifySMSConfig.TencentSMSParams.TemplateId) == 0 {
|
||||
this.Fail("请输入模板ID")
|
||||
return
|
||||
}
|
||||
if !digitsReg.MatchString(notifySMSConfig.TencentSMSParams.TemplateId) {
|
||||
this.Fail("正文模板ID是一组数字,请重新输入")
|
||||
return
|
||||
}
|
||||
if len(notifySMSConfig.TencentSMSParams.AccessKeyId) == 0 {
|
||||
this.Fail("请输入密钥SecretId")
|
||||
return
|
||||
}
|
||||
if len(notifySMSConfig.TencentSMSParams.AccessKeySecret) == 0 {
|
||||
this.Fail("请输入密钥SecretKey")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().SysSettingRPC().UpdateSysSetting(this.AdminContext(), &pb.UpdateSysSettingRequest{
|
||||
Code: systemconfigs.SettingCodeUserSenderConfig,
|
||||
ValueJSON: configJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
172
EdgeAdmin/internal/web/actions/default/users/setting/smsTest.go
Normal file
172
EdgeAdmin/internal/web/actions/default/users/setting/smsTest.go
Normal file
@@ -0,0 +1,172 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type SmsTestAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *SmsTestAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *SmsTestAction) RunGet(params struct{}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *SmsTestAction) RunPost(params struct {
|
||||
ConfigJSON []byte
|
||||
ToMobile string
|
||||
Body string
|
||||
Code string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
if len(params.ConfigJSON) == 0 {
|
||||
this.Fail("读取不到短信配置")
|
||||
return
|
||||
}
|
||||
|
||||
var config = userconfigs.NewSMSSenderConfig()
|
||||
err := json.Unmarshal(params.ConfigJSON, config)
|
||||
if err != nil {
|
||||
this.Fail("解析短信配置出错:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var paramsJSON []byte
|
||||
switch config.Type {
|
||||
case userconfigs.SMSSenderWebHook:
|
||||
if config.WebHookParams == nil {
|
||||
this.Fail("请配置HTTP接口相关参数")
|
||||
return
|
||||
}
|
||||
if len(config.WebHookParams.URL) == 0 {
|
||||
this.Fail("请输入短信HTTP接口URL地址")
|
||||
return
|
||||
}
|
||||
if !regexp.MustCompile(`^(http|https)://`).MatchString(config.WebHookParams.URL) {
|
||||
this.Fail("短信WebHook URL地址必须以http://或https://开头")
|
||||
return
|
||||
}
|
||||
|
||||
paramsJSON, err = json.Marshal(config.WebHookParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
case userconfigs.SMSSenderAliyunSMS:
|
||||
if config.AliyunSMSParams == nil {
|
||||
this.Fail("请配置阿里云短信相关参数")
|
||||
return
|
||||
}
|
||||
if len(config.AliyunSMSParams.Sign) == 0 {
|
||||
this.Fail("请输入签名名称")
|
||||
return
|
||||
}
|
||||
if len(config.AliyunSMSParams.TemplateCode) == 0 {
|
||||
this.Fail("请输入模板CODE")
|
||||
return
|
||||
}
|
||||
if len(config.AliyunSMSParams.CodeVarName) == 0 {
|
||||
this.Fail("请输入模板中验证码变量名称")
|
||||
return
|
||||
}
|
||||
if len(config.AliyunSMSParams.AccessKeyId) == 0 {
|
||||
this.Fail("请输入AccessKey ID")
|
||||
return
|
||||
}
|
||||
if len(config.AliyunSMSParams.AccessKeySecret) == 0 {
|
||||
this.Fail("请输入AccessKey Secret")
|
||||
return
|
||||
}
|
||||
|
||||
paramsJSON, err = json.Marshal(config.AliyunSMSParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
case userconfigs.SMSSenderTencentSMS:
|
||||
if config.TencentSMSParams == nil {
|
||||
this.Fail("请配置腾讯云短信相关参数")
|
||||
return
|
||||
}
|
||||
|
||||
var digitsReg = regexp.MustCompile(`^\d+$`)
|
||||
|
||||
if len(config.TencentSMSParams.SDKAppId) == 0 {
|
||||
this.Fail("请输入SDK应用ID")
|
||||
return
|
||||
}
|
||||
if !digitsReg.MatchString(config.TencentSMSParams.SDKAppId) {
|
||||
this.Fail("SDK应用ID是一组数字,请重新输入")
|
||||
return
|
||||
}
|
||||
if len(config.TencentSMSParams.Sign) == 0 {
|
||||
this.Fail("请输入签名内容")
|
||||
return
|
||||
}
|
||||
if len(config.TencentSMSParams.TemplateId) == 0 {
|
||||
this.Fail("请输入模板ID")
|
||||
return
|
||||
}
|
||||
if !digitsReg.MatchString(config.TencentSMSParams.TemplateId) {
|
||||
this.Fail("正文模板ID是一组数字,请重新输入")
|
||||
return
|
||||
}
|
||||
if len(config.TencentSMSParams.AccessKeyId) == 0 {
|
||||
this.Fail("请输入密钥SecretId")
|
||||
return
|
||||
}
|
||||
if len(config.TencentSMSParams.AccessKeySecret) == 0 {
|
||||
this.Fail("请输入密钥SecretKey")
|
||||
return
|
||||
}
|
||||
|
||||
paramsJSON, err = json.Marshal(config.TencentSMSParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
default:
|
||||
this.Fail("不支持渠道'" + config.Type + "'")
|
||||
}
|
||||
|
||||
params.Must.
|
||||
Field("toMobile", params.ToMobile).
|
||||
Require("请输入收信人手机号").
|
||||
Mobile("请输入正确的收信人手机号").
|
||||
Field("body", params.Body).
|
||||
Require("请输入测试内容")
|
||||
|
||||
// 发送测试
|
||||
resp, err := this.RPC().SMSSenderRPC().SendSMS(this.AdminContext(), &pb.SendSMSRequest{
|
||||
Mobile: params.ToMobile,
|
||||
Body: params.Body,
|
||||
Code: params.Code,
|
||||
Type: config.Type,
|
||||
ParamsJSON: paramsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.Fail("发送失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if !resp.IsOk {
|
||||
this.Fail("发送失败,结果:" + resp.Result)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
218
EdgeAdmin/internal/web/actions/default/users/update.go
Normal file
218
EdgeAdmin/internal/web/actions/default/users/update.go
Normal file
@@ -0,0 +1,218 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/users/userutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"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 {
|
||||
UserId int64
|
||||
}) {
|
||||
err := userutils.InitUser(this.Parent(), params.UserId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
userResp, err := this.RPC().UserRPC().FindEnabledUser(this.AdminContext(), &pb.FindEnabledUserRequest{UserId: params.UserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var user = userResp.User
|
||||
if user == nil {
|
||||
this.NotFound("user", params.UserId)
|
||||
return
|
||||
}
|
||||
|
||||
// AccessKey数量
|
||||
countAccessKeyResp, err := this.RPC().UserAccessKeyRPC().CountAllEnabledUserAccessKeys(this.AdminContext(), &pb.CountAllEnabledUserAccessKeysRequest{UserId: params.UserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var countAccessKeys = countAccessKeyResp.Count
|
||||
|
||||
// 是否有实名认证
|
||||
hasNewIndividualIdentity, hasNewEnterpriseIdentity, identityTag, err := userutils.CheckUserIdentity(this.RPC(), this.AdminContext(), params.UserId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// OTP认证
|
||||
var otpLoginIsOn = false
|
||||
if user.OtpLogin != nil {
|
||||
otpLoginIsOn = user.OtpLogin.IsOn
|
||||
}
|
||||
|
||||
this.Data["user"] = maps.Map{
|
||||
"id": user.Id,
|
||||
"username": user.Username,
|
||||
"fullname": user.Fullname,
|
||||
"email": user.Email,
|
||||
"tel": user.Tel,
|
||||
"remark": user.Remark,
|
||||
"mobile": user.Mobile,
|
||||
"isOn": user.IsOn,
|
||||
"countAccessKeys": countAccessKeys,
|
||||
"bandwidthAlgo": user.BandwidthAlgo,
|
||||
|
||||
// 实名认证
|
||||
"hasNewIndividualIdentity": hasNewIndividualIdentity,
|
||||
"hasNewEnterpriseIdentity": hasNewEnterpriseIdentity,
|
||||
"identityTag": identityTag,
|
||||
|
||||
// otp
|
||||
"otpLoginIsOn": otpLoginIsOn,
|
||||
}
|
||||
|
||||
this.Data["clusterId"] = 0
|
||||
if user.NodeCluster != nil {
|
||||
this.Data["clusterId"] = user.NodeCluster.Id
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunPost(params struct {
|
||||
UserId int64
|
||||
Username string
|
||||
Pass1 string
|
||||
Pass2 string
|
||||
Fullname string
|
||||
Mobile string
|
||||
Tel string
|
||||
Email string
|
||||
Remark string
|
||||
IsOn bool
|
||||
ClusterId int64
|
||||
BandwidthAlgo string
|
||||
|
||||
// OTP
|
||||
OtpOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.User_LogUpdateUser, params.UserId)
|
||||
|
||||
params.Must.
|
||||
Field("username", params.Username).
|
||||
Require("请输入用户名").
|
||||
Match(`^[a-zA-Z0-9_]+$`, "用户名中只能含有英文、数字和下划线")
|
||||
|
||||
checkUsernameResp, err := this.RPC().UserRPC().CheckUserUsername(this.AdminContext(), &pb.CheckUserUsernameRequest{
|
||||
UserId: params.UserId,
|
||||
Username: params.Username,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if checkUsernameResp.Exists {
|
||||
this.FailField("username", "此用户名已经被占用,请换一个")
|
||||
}
|
||||
|
||||
if len(params.Pass1) > 0 {
|
||||
params.Must.
|
||||
Field("pass1", params.Pass1).
|
||||
Require("请输入密码").
|
||||
Field("pass2", params.Pass2).
|
||||
Require("请再次输入确认密码").
|
||||
Equal(params.Pass1, "两次输入的密码不一致")
|
||||
}
|
||||
|
||||
params.Must.
|
||||
Field("fullname", params.Fullname).
|
||||
Require("请输入全名")
|
||||
|
||||
if len(params.Mobile) > 0 {
|
||||
params.Must.
|
||||
Field("mobile", params.Mobile).
|
||||
Mobile("请输入正确的手机号")
|
||||
}
|
||||
if len(params.Email) > 0 {
|
||||
params.Must.
|
||||
Field("email", params.Email).
|
||||
Email("请输入正确的电子邮箱")
|
||||
}
|
||||
|
||||
_, err = this.RPC().UserRPC().UpdateUser(this.AdminContext(), &pb.UpdateUserRequest{
|
||||
UserId: params.UserId,
|
||||
Username: params.Username,
|
||||
Password: params.Pass1,
|
||||
Fullname: params.Fullname,
|
||||
Mobile: params.Mobile,
|
||||
Tel: params.Tel,
|
||||
Email: params.Email,
|
||||
Remark: params.Remark,
|
||||
IsOn: params.IsOn,
|
||||
NodeClusterId: params.ClusterId,
|
||||
BandwidthAlgo: params.BandwidthAlgo,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 修改OTP
|
||||
otpLoginResp, err := this.RPC().LoginRPC().FindEnabledLogin(this.AdminContext(), &pb.FindEnabledLoginRequest{
|
||||
UserId: params.UserId,
|
||||
Type: "otp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
{
|
||||
var 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,
|
||||
UserId: params.UserId,
|
||||
}
|
||||
} 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,
|
||||
UserId: params.UserId,
|
||||
}})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
118
EdgeAdmin/internal/web/actions/default/users/user.go
Normal file
118
EdgeAdmin/internal/web/actions/default/users/user.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/users/userutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UserAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UserAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *UserAction) RunGet(params struct {
|
||||
UserId int64
|
||||
}) {
|
||||
err := userutils.InitUser(this.Parent(), params.UserId)
|
||||
if err != nil {
|
||||
if err == userutils.ErrUserNotFound {
|
||||
this.RedirectURL("/users")
|
||||
return
|
||||
}
|
||||
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
userResp, err := this.RPC().UserRPC().FindEnabledUser(this.AdminContext(), &pb.FindEnabledUserRequest{UserId: params.UserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var user = userResp.User
|
||||
if user == nil {
|
||||
this.NotFound("user", params.UserId)
|
||||
return
|
||||
}
|
||||
|
||||
var clusterMap maps.Map = nil
|
||||
if user.NodeCluster != nil {
|
||||
clusterMap = maps.Map{
|
||||
"id": user.NodeCluster.Id,
|
||||
"name": user.NodeCluster.Name,
|
||||
}
|
||||
}
|
||||
|
||||
// AccessKey数量
|
||||
countAccessKeyResp, err := this.RPC().UserAccessKeyRPC().CountAllEnabledUserAccessKeys(this.AdminContext(), &pb.CountAllEnabledUserAccessKeysRequest{UserId: params.UserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
countAccessKeys := countAccessKeyResp.Count
|
||||
|
||||
// IP地址
|
||||
var registeredRegion = ""
|
||||
if len(user.RegisteredIP) > 0 {
|
||||
var ipRegion = iplibrary.LookupIP(user.RegisteredIP)
|
||||
if ipRegion != nil && ipRegion.IsOk() {
|
||||
registeredRegion = ipRegion.Summary()
|
||||
}
|
||||
}
|
||||
|
||||
// 是否有实名认证
|
||||
hasNewIndividualIdentity, hasNewEnterpriseIdentity, identityTag, err := userutils.CheckUserIdentity(this.RPC(), this.AdminContext(), params.UserId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// OTP
|
||||
this.Data["otp"] = nil
|
||||
if user.OtpLogin != nil && user.OtpLogin.IsOn {
|
||||
loginParams := maps.Map{}
|
||||
err = json.Unmarshal(user.OtpLogin.ParamsJSON, &loginParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["otp"] = maps.Map{
|
||||
"isOn": true,
|
||||
"params": loginParams,
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["user"] = maps.Map{
|
||||
"id": user.Id,
|
||||
"username": user.Username,
|
||||
"fullname": user.Fullname,
|
||||
"email": user.Email,
|
||||
"verifiedEmail": user.VerifiedEmail,
|
||||
"tel": user.Tel,
|
||||
"remark": user.Remark,
|
||||
"mobile": user.Mobile,
|
||||
"isOn": user.IsOn,
|
||||
"cluster": clusterMap,
|
||||
"countAccessKeys": countAccessKeys,
|
||||
"isRejected": user.IsRejected,
|
||||
"rejectReason": user.RejectReason,
|
||||
"isVerified": user.IsVerified,
|
||||
"registeredIP": user.RegisteredIP,
|
||||
"registeredRegion": registeredRegion,
|
||||
"bandwidthAlgo": user.BandwidthAlgo,
|
||||
|
||||
// 实名认证
|
||||
"hasNewIndividualIdentity": hasNewIndividualIdentity,
|
||||
"hasNewEnterpriseIdentity": hasNewEnterpriseIdentity,
|
||||
"identityTag": identityTag,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
255
EdgeAdmin/internal/web/actions/default/users/user/servers.go
Normal file
255
EdgeAdmin/internal/web/actions/default/users/user/servers.go
Normal file
@@ -0,0 +1,255 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/users/userutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type ServersAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ServersAction) Init() {
|
||||
this.Nav("", "", "server")
|
||||
}
|
||||
|
||||
func (this *ServersAction) RunGet(params struct {
|
||||
UserId int64
|
||||
|
||||
ClusterId int64
|
||||
GroupId int64
|
||||
Keyword string
|
||||
AuditingFlag int32
|
||||
CheckDNS bool
|
||||
|
||||
TrafficOutOrder string
|
||||
}) {
|
||||
err := userutils.InitUser(this.Parent(), params.UserId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
this.Data["groupId"] = params.GroupId
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["auditingFlag"] = params.AuditingFlag
|
||||
this.Data["checkDNS"] = params.CheckDNS
|
||||
this.Data["hasOrder"] = len(params.TrafficOutOrder) > 0
|
||||
this.Data["userId"] = params.UserId
|
||||
|
||||
dashboardResp, err := this.RPC().UserRPC().ComposeUserDashboard(this.AdminContext(), &pb.ComposeUserDashboardRequest{UserId: params.UserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 单位
|
||||
userUIConfig, err := configloaders.LoadUserUIConfig()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["uiConfig"] = maps.Map{
|
||||
"showTrafficCharts": true,
|
||||
"showBandwidthCharts": true,
|
||||
"bandwidthUnit": systemconfigs.BandwidthUnitBit,
|
||||
}
|
||||
|
||||
if userUIConfig != nil {
|
||||
this.Data["uiConfig"] = maps.Map{
|
||||
"showTrafficCharts": userUIConfig.ShowTrafficCharts,
|
||||
"showBandwidthCharts": userUIConfig.ShowBandwidthCharts,
|
||||
"bandwidthUnit": systemconfigs.BandwidthUnitBit, // 强制使用比特单位
|
||||
}
|
||||
}
|
||||
|
||||
// 整体带宽统计
|
||||
var monthlyPeekBandwidthBytes = dashboardResp.MonthlyPeekBandwidthBytes
|
||||
var dailyPeekBandwidthBytes = dashboardResp.DailyPeekBandwidthBytes
|
||||
monthlyPeekBandwidthBytes *= 8
|
||||
dailyPeekBandwidthBytes *= 8
|
||||
this.Data["dashboard"] = maps.Map{
|
||||
"countServers": dashboardResp.CountServers,
|
||||
"monthlyTrafficBytes": dashboardResp.MonthlyTrafficBytes,
|
||||
"monthlyPeekBandwidthBits": monthlyPeekBandwidthBytes,
|
||||
"dailyTrafficBytes": dashboardResp.DailyTrafficBytes,
|
||||
"dailyPeekBandwidthBits": dailyPeekBandwidthBytes,
|
||||
}
|
||||
|
||||
// 服务列表
|
||||
countServersResp, err := this.RPC().ServerRPC().CountAllEnabledServersMatch(this.AdminContext(), &pb.CountAllEnabledServersMatchRequest{
|
||||
UserId: params.UserId,
|
||||
NodeClusterId: params.ClusterId,
|
||||
ServerGroupId: params.GroupId,
|
||||
Keyword: params.Keyword,
|
||||
AuditingFlag: params.AuditingFlag,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var count = countServersResp.Count
|
||||
var page = this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
serversResp, err := this.RPC().ServerRPC().ListEnabledServersMatch(this.AdminContext(), &pb.ListEnabledServersMatchRequest{
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
UserId: params.UserId,
|
||||
NodeClusterId: params.ClusterId,
|
||||
ServerGroupId: params.GroupId,
|
||||
Keyword: params.Keyword,
|
||||
AuditingFlag: params.AuditingFlag,
|
||||
TrafficOutDesc: params.TrafficOutOrder == "desc",
|
||||
TrafficOutAsc: params.TrafficOutOrder == "asc",
|
||||
IgnoreServerNames: true,
|
||||
IgnoreSSLCerts: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var serverMaps = []maps.Map{}
|
||||
for _, server := range serversResp.Servers {
|
||||
var config = &serverconfigs.ServerConfig{}
|
||||
err = json.Unmarshal(server.Config, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 端口列表
|
||||
var portMaps = []maps.Map{}
|
||||
if config.HTTP != nil && config.HTTP.IsOn {
|
||||
for _, listen := range config.HTTP.Listen {
|
||||
portMaps = append(portMaps, maps.Map{
|
||||
"protocol": listen.Protocol,
|
||||
"portRange": listen.PortRange,
|
||||
})
|
||||
}
|
||||
}
|
||||
if config.HTTPS != nil && config.HTTPS.IsOn {
|
||||
for _, listen := range config.HTTPS.Listen {
|
||||
portMaps = append(portMaps, maps.Map{
|
||||
"protocol": listen.Protocol,
|
||||
"portRange": listen.PortRange,
|
||||
})
|
||||
}
|
||||
}
|
||||
if config.TCP != nil && config.TCP.IsOn {
|
||||
for _, listen := range config.TCP.Listen {
|
||||
portMaps = append(portMaps, maps.Map{
|
||||
"protocol": listen.Protocol,
|
||||
"portRange": listen.PortRange,
|
||||
})
|
||||
}
|
||||
}
|
||||
if config.TLS != nil && config.TLS.IsOn {
|
||||
for _, listen := range config.TLS.Listen {
|
||||
portMaps = append(portMaps, maps.Map{
|
||||
"protocol": listen.Protocol,
|
||||
"portRange": listen.PortRange,
|
||||
})
|
||||
}
|
||||
}
|
||||
if config.UDP != nil && config.UDP.IsOn {
|
||||
for _, listen := range config.UDP.Listen {
|
||||
portMaps = append(portMaps, maps.Map{
|
||||
"protocol": listen.Protocol,
|
||||
"portRange": listen.PortRange,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 分组
|
||||
var groupMaps = []maps.Map{}
|
||||
if len(server.ServerGroups) > 0 {
|
||||
for _, group := range server.ServerGroups {
|
||||
groupMaps = append(groupMaps, maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 域名列表
|
||||
// 域名列表
|
||||
if server.IsAuditing || (server.AuditingResult != nil && !server.AuditingResult.IsOk) {
|
||||
server.ServerNamesJSON = server.AuditingServerNamesJSON
|
||||
|
||||
if len(config.ServerNames) == 0 {
|
||||
// 审核中的域名
|
||||
if len(server.ServerNamesJSON) > 0 {
|
||||
var serverNames = []*serverconfigs.ServerNameConfig{}
|
||||
err = json.Unmarshal(server.ServerNamesJSON, &serverNames)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
config.ServerNames = serverNames
|
||||
}
|
||||
}
|
||||
}
|
||||
var auditingIsOk = true
|
||||
if !server.IsAuditing && server.AuditingResult != nil && !server.AuditingResult.IsOk {
|
||||
auditingIsOk = false
|
||||
}
|
||||
var firstServerName = ""
|
||||
for _, serverNameConfig := range config.ServerNames {
|
||||
if len(serverNameConfig.Name) > 0 {
|
||||
firstServerName = serverNameConfig.Name
|
||||
break
|
||||
}
|
||||
if len(serverNameConfig.SubNames) > 0 {
|
||||
firstServerName = serverNameConfig.SubNames[0]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 提交审核时间
|
||||
var auditingTime = ""
|
||||
if server.AuditingAt > 0 {
|
||||
auditingTime = timeutil.FormatTime("Y-m-d", server.AuditingAt)
|
||||
}
|
||||
|
||||
// 统计数据
|
||||
var bandwidthBits int64 = 0
|
||||
if server.BandwidthBytes > 0 {
|
||||
bandwidthBits = server.BandwidthBytes * 8
|
||||
}
|
||||
|
||||
serverMaps = append(serverMaps, maps.Map{
|
||||
"id": server.Id,
|
||||
"isOn": server.IsOn,
|
||||
"name": server.Name,
|
||||
"cluster": maps.Map{
|
||||
"id": server.NodeCluster.Id,
|
||||
"name": server.NodeCluster.Name,
|
||||
},
|
||||
"ports": portMaps,
|
||||
"serverTypeName": serverconfigs.FindServerType(server.Type).GetString("name"),
|
||||
"groups": groupMaps,
|
||||
"firstServerName": firstServerName,
|
||||
"countServerNames": server.CountServerNames,
|
||||
"isAuditing": server.IsAuditing,
|
||||
"auditingIsOk": auditingIsOk,
|
||||
"auditingTime": auditingTime,
|
||||
"bandwidthBits": bandwidthBits,
|
||||
})
|
||||
}
|
||||
this.Data["servers"] = serverMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package userutils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var ErrUserNotFound = errors.New("not found user")
|
||||
|
||||
// InitUser 查找用户基本信息
|
||||
func InitUser(p *actionutils.ParentAction, userId int64) error {
|
||||
resp, err := p.RPC().UserRPC().FindEnabledUser(p.AdminContext(), &pb.FindEnabledUserRequest{UserId: userId})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.User == nil {
|
||||
return ErrUserNotFound
|
||||
}
|
||||
|
||||
// AccessKey数量
|
||||
countAccessKeysResp, err := p.RPC().UserAccessKeyRPC().CountAllEnabledUserAccessKeys(p.AdminContext(), &pb.CountAllEnabledUserAccessKeysRequest{
|
||||
AdminId: 0,
|
||||
UserId: userId,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 是否有实名认证
|
||||
hasNewIndividualIdentity, hasNewEnterpriseIdentity, identityTag, err := CheckUserIdentity(p.RPC(), p.AdminContext(), userId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Data["user"] = maps.Map{
|
||||
"id": userId,
|
||||
"fullname": resp.User.Fullname,
|
||||
"username": resp.User.Username,
|
||||
"countAccessKeys": countAccessKeysResp.Count,
|
||||
"hasNewIndividualIdentity": hasNewIndividualIdentity,
|
||||
"hasNewEnterpriseIdentity": hasNewEnterpriseIdentity,
|
||||
"identityTag": identityTag,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckUserIdentity 实名认证信息
|
||||
func CheckUserIdentity(rpcClient *rpc.RPCClient, ctx context.Context, userId int64) (hasNewIndividualIdentity bool, hasNewEnterpriseIdentity bool, identityTag string, err error) {
|
||||
var tags = []string{}
|
||||
|
||||
// 个人
|
||||
individualIdentityResp, err := rpcClient.UserIdentityRPC().FindEnabledUserIdentityWithOrgType(ctx, &pb.FindEnabledUserIdentityWithOrgTypeRequest{
|
||||
UserId: userId,
|
||||
OrgType: userconfigs.UserIdentityOrgTypeIndividual,
|
||||
})
|
||||
if err != nil {
|
||||
return false, false, "", err
|
||||
}
|
||||
var individualIdentity = individualIdentityResp.UserIdentity
|
||||
hasNewIndividualIdentity = individualIdentity != nil && individualIdentity.Status == userconfigs.UserIdentityStatusSubmitted
|
||||
|
||||
if individualIdentity != nil && individualIdentity.Status == userconfigs.UserIdentityStatusVerified {
|
||||
tags = append(tags, "个人")
|
||||
}
|
||||
|
||||
// 企业
|
||||
enterpriseIdentityResp, err := rpcClient.UserIdentityRPC().FindEnabledUserIdentityWithOrgType(ctx, &pb.FindEnabledUserIdentityWithOrgTypeRequest{
|
||||
UserId: userId,
|
||||
OrgType: userconfigs.UserIdentityOrgTypeEnterprise,
|
||||
})
|
||||
if err != nil {
|
||||
return false, false, "", err
|
||||
}
|
||||
var enterpriseIdentity = enterpriseIdentityResp.UserIdentity
|
||||
hasNewEnterpriseIdentity = enterpriseIdentity != nil && enterpriseIdentity.Status == userconfigs.UserIdentityStatusSubmitted
|
||||
|
||||
if enterpriseIdentity != nil && enterpriseIdentity.Status == userconfigs.UserIdentityStatusVerified {
|
||||
tags = append(tags, "企业")
|
||||
}
|
||||
|
||||
identityTag = strings.Join(tags, "+")
|
||||
|
||||
return
|
||||
}
|
||||
57
EdgeAdmin/internal/web/actions/default/users/verifyPopup.go
Normal file
57
EdgeAdmin/internal/web/actions/default/users/verifyPopup.go
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package users
|
||||
|
||||
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 VerifyPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *VerifyPopupAction) RunGet(params struct {
|
||||
UserId int64
|
||||
}) {
|
||||
this.Data["userId"] = params.UserId
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *VerifyPopupAction) RunPost(params struct {
|
||||
UserId int64
|
||||
Result string
|
||||
RejectReason string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.User_LogVerifyUser, params.UserId, params.Result)
|
||||
|
||||
if params.Result == "pass" {
|
||||
params.RejectReason = ""
|
||||
}
|
||||
|
||||
_, err := this.RPC().UserRPC().VerifyUser(this.AdminContext(), &pb.VerifyUserRequest{
|
||||
UserId: params.UserId,
|
||||
IsRejected: params.Result == "reject" || params.Result == "delete",
|
||||
RejectReason: params.RejectReason,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if params.Result == "delete" {
|
||||
_, err = this.RPC().UserRPC().DeleteUser(this.AdminContext(), &pb.DeleteUserRequest{UserId: params.UserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
Reference in New Issue
Block a user