Initial commit (code only without large binaries)
This commit is contained in:
280
EdgeUser/internal/web/actions/actionutils/parent_action.go
Normal file
280
EdgeUser/internal/web/actions/actionutils/parent_action.go
Normal file
@@ -0,0 +1,280 @@
|
||||
package actionutils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/nodes/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/oplogs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/rpc"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/login/loginutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type ParentAction struct {
|
||||
actions.ActionObject
|
||||
|
||||
rpcClient *rpc.RPCClient
|
||||
}
|
||||
|
||||
// Parent 可以调用自身的一个简便方法
|
||||
func (this *ParentAction) Parent() *ParentAction {
|
||||
return this
|
||||
}
|
||||
|
||||
func (this *ParentAction) ErrorPage(err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !rpc.IsConnError(err) {
|
||||
remotelogs.Error("ERROR_PAGE", this.Request.URL.String()+": "+err.Error())
|
||||
}
|
||||
|
||||
// 日志
|
||||
this.CreateLog(oplogs.LevelError, codes.UserCommon_LogSystemError, err.Error())
|
||||
|
||||
if this.Request.Method == http.MethodGet {
|
||||
FailPage(this, err)
|
||||
} else {
|
||||
Fail(this, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ParentAction) ErrorText(err string) {
|
||||
this.ErrorPage(errors.New(err))
|
||||
}
|
||||
|
||||
func (this *ParentAction) NotFound(name string, itemId int64) {
|
||||
this.ErrorPage(errors.New(name + " id: '" + strconv.FormatInt(itemId, 10) + "' is not found"))
|
||||
}
|
||||
|
||||
func (this *ParentAction) ForbidPage() {
|
||||
this.ResponseWriter.WriteHeader(http.StatusForbidden)
|
||||
}
|
||||
|
||||
func (this *ParentAction) NewPage(total int64, size ...int64) *Page {
|
||||
if len(size) > 0 {
|
||||
return NewActionPage(this, total, size[0])
|
||||
}
|
||||
return NewActionPage(this, total, 10)
|
||||
}
|
||||
|
||||
func (this *ParentAction) Nav(mainMenu string, tab string, firstMenu string) {
|
||||
this.Data["mainMenu"] = mainMenu
|
||||
this.Data["mainTab"] = tab
|
||||
this.Data["firstMenuItem"] = firstMenu
|
||||
}
|
||||
|
||||
func (this *ParentAction) FirstMenu(menuItem string) {
|
||||
this.Data["firstMenuItem"] = menuItem
|
||||
}
|
||||
|
||||
func (this *ParentAction) SecondMenu(menuItem string) {
|
||||
this.Data["secondMenuItem"] = menuItem
|
||||
}
|
||||
|
||||
func (this *ParentAction) TinyMenu(menuItem string) {
|
||||
this.Data["tinyMenuItem"] = menuItem
|
||||
}
|
||||
|
||||
func (this *ParentAction) UserId() int64 {
|
||||
return this.Context.GetInt64("userId")
|
||||
}
|
||||
|
||||
func (this *ParentAction) CreateLog(level string, messageCode langs.MessageCode, args ...any) {
|
||||
var description = messageCode.For(this.LangCode())
|
||||
var desc = fmt.Sprintf(description, args...)
|
||||
if level == oplogs.LevelInfo {
|
||||
if this.Code != 200 {
|
||||
level = oplogs.LevelWarn
|
||||
if len(this.Message) > 0 {
|
||||
desc += " 失败:" + this.Message
|
||||
}
|
||||
}
|
||||
}
|
||||
err := dao.SharedLogDAO.CreateUserLog(this.UserContext(), level, this.Request.URL.Path, desc, loginutils.RemoteIP(&this.ActionObject))
|
||||
if err != nil {
|
||||
utils.PrintError(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ParentAction) CreateLogInfo(messageCode langs.MessageCode, args ...any) {
|
||||
this.CreateLog(oplogs.LevelInfo, messageCode, args...)
|
||||
}
|
||||
|
||||
func (this *ParentAction) LangCode() langs.LangCode {
|
||||
var langCode = this.Data.GetString("teaLang")
|
||||
if len(langCode) == 0 {
|
||||
langCode = langs.DefaultManager().DefaultLang()
|
||||
}
|
||||
return langCode
|
||||
}
|
||||
|
||||
// RPC 获取RPC
|
||||
func (this *ParentAction) RPC() *rpc.RPCClient {
|
||||
if this.rpcClient != nil {
|
||||
return this.rpcClient
|
||||
}
|
||||
|
||||
// 所有集群
|
||||
rpcClient, err := rpc.SharedRPC()
|
||||
if err != nil {
|
||||
logs.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
this.rpcClient = rpcClient
|
||||
|
||||
return rpcClient
|
||||
}
|
||||
|
||||
// UserContext 获取Context
|
||||
// 每个请求的context都必须是一个新的实例
|
||||
func (this *ParentAction) UserContext() context.Context {
|
||||
if this.rpcClient == nil {
|
||||
rpcClient, err := rpc.SharedRPC()
|
||||
if err != nil {
|
||||
logs.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
this.rpcClient = rpcClient
|
||||
}
|
||||
return this.rpcClient.Context(this.UserId())
|
||||
}
|
||||
|
||||
// 一个不包含用户ID的上下文
|
||||
func (this *ParentAction) NullUserContext() context.Context {
|
||||
if this.rpcClient == nil {
|
||||
rpcClient, err := rpc.SharedRPC()
|
||||
if err != nil {
|
||||
logs.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
this.rpcClient = rpcClient
|
||||
}
|
||||
return this.rpcClient.Context(0)
|
||||
}
|
||||
|
||||
// ValidateFeature 校验Feature
|
||||
func (this *ParentAction) ValidateFeature(featureCode string, serverId int64) bool {
|
||||
b, err := this.validateFeature(featureCode, serverId)
|
||||
if err != nil {
|
||||
remotelogs.Error("FEATURE", "validate feature: "+err.Error())
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (this *ParentAction) validateFeature(featureCode string, serverId int64) (bool, error) {
|
||||
// 检查审核和认证
|
||||
if configloaders.RequireVerification() && !this.Context.GetBool("isVerified") {
|
||||
return false, nil
|
||||
}
|
||||
if configloaders.RequireIdentity() && !this.Context.GetBool("isIdentified") {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
var featureDef = userconfigs.FindUserFeature(featureCode)
|
||||
if featureDef == nil {
|
||||
return false, errors.New("invalid feature code '" + featureCode + "'")
|
||||
}
|
||||
|
||||
// 检查网站绑定的套餐
|
||||
if serverId > 0 && featureDef.SupportPlan {
|
||||
userPlanResp, err := this.RPC().ServerRPC().FindServerUserPlan(this.UserContext(), &pb.FindServerUserPlanRequest{ServerId: serverId})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if userPlanResp.UserPlan != nil && userPlanResp.UserPlan.IsOn && userPlanResp.UserPlan.Plan != nil /** 不需要判断套餐是否启用(即不需要判断是否为UserPlan.Plan.isOn),以便于兼容套餐被删除的情况 **/ {
|
||||
var plan = userPlanResp.UserPlan.Plan
|
||||
if plan.HasFullFeatures {
|
||||
return true, nil
|
||||
}
|
||||
var supportedFeatureCodes []string
|
||||
if len(plan.FeaturesJSON) > 0 {
|
||||
err = json.Unmarshal(plan.FeaturesJSON, &supportedFeatureCodes)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return lists.ContainsString(supportedFeatureCodes, featureCode), nil
|
||||
}
|
||||
}
|
||||
|
||||
// 用户功能
|
||||
userFeatureResp, err := this.RPC().UserRPC().FindUserFeatures(this.UserContext(), &pb.FindUserFeaturesRequest{UserId: this.UserId()})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
var userFeatureCodes = []string{}
|
||||
for _, feature := range userFeatureResp.Features {
|
||||
userFeatureCodes = append(userFeatureCodes, feature.Code)
|
||||
}
|
||||
|
||||
return lists.ContainsString(userFeatureCodes, featureCode), nil
|
||||
}
|
||||
|
||||
func (this *ParentAction) CheckUserStatus() bool {
|
||||
// 审核和认证
|
||||
if configloaders.RequireVerification() && !this.Context.GetBool("isVerified") {
|
||||
this.RedirectURL("/")
|
||||
return false
|
||||
}
|
||||
if configloaders.RequireIdentity() && !this.Context.GetBool("isIdentified") {
|
||||
this.RedirectURL("/")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (this *ParentAction) FindServerIdWithWebId(webId int64) (serverId int64, err error) {
|
||||
serverIdResp, err := this.RPC().HTTPWebRPC().FindServerIdWithHTTPWebId(this.UserContext(), &pb.FindServerIdWithHTTPWebIdRequest{
|
||||
HttpWebId: webId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
serverId = serverIdResp.ServerId
|
||||
return
|
||||
}
|
||||
|
||||
func (this *ParentAction) CheckHTTPSRedirecting() {
|
||||
if this.Request.TLS == nil {
|
||||
httpsPort, _ := serverutils.ReadServerHTTPS()
|
||||
if httpsPort > 0 {
|
||||
currentHost, _, hostErr := net.SplitHostPort(this.Request.Host)
|
||||
if hostErr != nil {
|
||||
currentHost = this.Request.Host
|
||||
}
|
||||
|
||||
var newHost = configutils.QuoteIP(currentHost)
|
||||
if httpsPort != 443 /** default https port **/ {
|
||||
newHost += ":" + types.String(httpsPort)
|
||||
}
|
||||
|
||||
// 如果没有前端反向代理,则跳转
|
||||
if len(this.Request.Header.Get("X-Forwarded-For")) == 0 && len(this.Request.Header.Get("X-Real-Ip")) == 0 {
|
||||
this.RedirectURL("https://" + newHost + this.Request.RequestURI)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user