This commit is contained in:
unknown
2026-02-04 20:27:13 +08:00
commit 3b042d1dad
9410 changed files with 1488147 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build plus
package userconfigs
// 所有账户相关的事件类型
type AccountEventType = string
const (
AccountEventTypeCharge AccountEventType = "charge" // 充值
AccountEventTypeAward AccountEventType = "award" // 赠送
AccountEventTypeBuyPlan AccountEventType = "buyPlan" // 购买CDN套餐
AccountEventTypePayBill AccountEventType = "payBill" // 支付账单
AccountEventTypeRefund AccountEventType = "refund" // 退款
AccountEventTypeWithdraw AccountEventType = "withdraw" // 提现
AccountEventTypeBuyNSPlan AccountEventType = "buyNSPlan" // 购买DNS套餐
AccountEventTypeBuyTrafficPackage AccountEventType = "buyTrafficPackage" // 购买流量包
AccountEventTypeBuyAntiDDoSPackage AccountEventType = "buyAntiDDoSPackage" // 购买高防实例
AccountEventTypeRenewAntiDDoSPackage AccountEventType = "renewAntiDDoSPackage" // 续费高防实例
)
type AccountEvent struct {
Name string `json:"name"` // 名称
Code AccountEventType `json:"code"` // 代号
Description string `json:"description"` // 描述
IsPositive bool `json:"isPositive"` // 是否为正向
}
var AccountIncomeEventTypes = []AccountEventType{AccountEventTypeCharge} // 收入
var AccountExpenseEventTypes = []AccountEventType{AccountEventTypeWithdraw} // 支出
// FindAllAccountEventTypes 查找所有的事件类型
func FindAllAccountEventTypes() []*AccountEvent {
return []*AccountEvent{
{
Name: "充值",
Code: AccountEventTypeCharge,
Description: "为用户账户充值。",
IsPositive: true,
},
{
Name: "赠送",
Code: AccountEventTypeAward,
Description: "为用户账户赠送余额。",
IsPositive: true,
},
{
Name: "购买CDN套餐",
Code: AccountEventTypeBuyPlan,
Description: "购买CDN套餐支出。",
IsPositive: false,
},
{
Name: "支付账单",
Code: AccountEventTypePayBill,
Description: "支付账单支出。",
IsPositive: false,
},
{
Name: "退款",
Code: AccountEventTypeRefund,
Description: "退款到用户账户。",
IsPositive: true,
},
{
Name: "提现",
Code: AccountEventTypeWithdraw,
Description: "用户从账户提现。",
IsPositive: false,
},
{
Name: "购买DNS套餐",
Code: AccountEventTypeBuyNSPlan,
Description: "购买DNS套餐支出。",
IsPositive: false,
},
{
Name: "购买流量包",
Code: AccountEventTypeBuyTrafficPackage,
Description: "购买流量包支出",
IsPositive: false,
},
{
Name: "购买DDoS高防实例",
Code: AccountEventTypeBuyAntiDDoSPackage,
Description: "购买DDoS高防实例支出",
IsPositive: false,
},
{
Name: "续费DDoS高防实例",
Code: AccountEventTypeRenewAntiDDoSPackage,
Description: "续费DDoS高防实例支出",
IsPositive: false,
},
}
}
// FindAccountEvent 根据事件类型查找事件定义
func FindAccountEvent(eventType AccountEventType) *AccountEvent {
for _, e := range FindAllAccountEventTypes() {
if e.Code == eventType {
return e
}
}
return nil
}

View File

@@ -0,0 +1,74 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package userconfigs
import (
"strings"
)
type ADPackagePeriod = string
const (
ADPackagePeriodMonth ADPackagePeriod = "month"
ADPackagePeriodYear ADPackagePeriod = "year"
)
func IsValidADPackagePeriod(period string) bool {
return period == ADPackagePeriodMonth || period == ADPackagePeriodYear
}
func ADPackagePeriodToMonths(count int32, unit ADPackagePeriod) int32 {
if count < 0 {
return count
}
switch unit {
case ADPackagePeriodMonth:
return count
case ADPackagePeriodYear:
return count * 12
}
return 0
}
func ADPackagePeriodUnitName(unit ADPackagePeriod) string {
switch unit {
case ADPackagePeriodMonth:
return "个月"
case ADPackagePeriodYear:
return "年"
}
return ""
}
type ADPackageSizeUnit = string
const (
ADPackageSizeUnitMb ADPackageSizeUnit = "mb"
ADPackageSizeUnitGb ADPackageSizeUnit = "gb"
ADPackageSizeUnitTb ADPackageSizeUnit = "tb"
)
func IsValidADPackageSizeUnit(unit string) bool {
return unit == ADPackageSizeUnitMb || unit == ADPackageSizeUnitGb || unit == ADPackageSizeUnitTb
}
func ADPackageSizeFullUnit(unit ADPackageSizeUnit) string {
if len(unit) != 2 {
return unit
}
return strings.ToUpper(unit[:1]) + unit[1:] + "ps"
}
func ADPackageSizeBits(count int32, unit ADPackageSizeUnit) int64 {
switch unit {
case ADPackageSizeUnitMb:
return int64(count) * (1 << 20) * 8
case ADPackageSizeUnitGb:
return int64(count) * (1 << 30) * 8
case ADPackageSizeUnitTb:
return int64(count) * (1 << 40) * 8
}
return 0
}

View File

@@ -0,0 +1,129 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package userconfigs
import "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
type OrderType = string
const (
OrderTypeCharge OrderType = "charge" // 充值
OrderTypeBuyNSPlan OrderType = "buyNSPlan" // 购买DNS套餐
OrderTypeBuyTrafficPackage OrderType = "buyTrafficPackage" // 购买流量包
OrderTypeBuyAntiDDoSInstance OrderType = "buyAntiDDoSInstance" // 购买高防实例
OrderTypeRenewAntiDDoSInstance OrderType = "renewAntiDDoSInstance" // 续费高防实例
)
// OrderTypeBuyNSPlanParams 购买NS套餐参数
type OrderTypeBuyNSPlanParams struct {
PlanId int64 `json:"planId"`
DayFrom string `json:"dayFrom"`
DayTo string `json:"dayTo"`
Period string `json:"period"`
}
// OrderTypeBuyTrafficPackageParams 购买流量包参数
type OrderTypeBuyTrafficPackageParams struct {
PackageId int64 `json:"packageId"`
RegionId int64 `json:"regionId"`
PeriodId int64 `json:"periodId"`
PeriodCount int32 `json:"periodCount"` // 冗余数据,防止 Period 在生成订单时发生变更
PeriodUnit string `json:"periodUnit"`
Count int32 `json:"count"`
}
// OrderTypeBuyAntiDDoSInstanceParams 购买高防实例
type OrderTypeBuyAntiDDoSInstanceParams struct {
PackageId int64 `json:"packageId"`
PeriodId int64 `json:"periodId"`
PeriodCount int32 `json:"periodCount"` // 冗余数据,防止 Period 在生成订单时发生变更
PeriodUnit string `json:"periodUnit"`
Count int32 `json:"count"`
}
// OrderTypeRenewAntiDDoSInstanceParams 续费高防实例
type OrderTypeRenewAntiDDoSInstanceParams struct {
UserInstanceId int64 `json:"userInstanceId"` // 用户实例ID
PeriodId int64 `json:"periodId"` // 有效期ID
}
func FindAllOrderTypes() []*shared.Definition {
return []*shared.Definition{
{
Name: "充值",
Code: OrderTypeCharge,
},
{
Name: "购买DNS套餐",
Code: OrderTypeBuyNSPlan,
},
{
Name: "购买流量包",
Code: OrderTypeBuyTrafficPackage,
},
{
Name: "购买DDoS高防实例",
Code: OrderTypeBuyAntiDDoSInstance,
},
{
Name: "续费DDoS高防实例",
Code: OrderTypeRenewAntiDDoSInstance,
},
}
}
func IsValidOrderType(orderType string) bool {
for _, def := range FindAllOrderTypes() {
if def.Code == orderType {
return true
}
}
return false
}
func FindOrderTypeName(orderType OrderType) string {
for _, def := range FindAllOrderTypes() {
if def.Code == orderType {
return def.Name
}
}
return ""
}
type OrderStatus = string
const (
OrderStatusNone OrderStatus = "none"
OrderStatusCancelled OrderStatus = "cancelled"
OrderStatusFinished OrderStatus = "finished"
)
func FindOrderStatusName(orderStatus OrderStatus) string {
switch orderStatus {
case OrderStatusNone:
return "未支付"
case OrderStatusCancelled:
return "已取消"
case OrderStatusFinished:
return "已完成"
}
return ""
}
func FindAllOrderStatusList() []*shared.Definition {
return []*shared.Definition{
{
Name: "已完成",
Code: OrderStatusFinished,
},
{
Name: "未支付",
Code: OrderStatusNone,
},
{
Name: "已取消",
Code: OrderStatusCancelled,
},
}
}

View File

@@ -0,0 +1,231 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package userconfigs
import "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
// UserFeatureCode 用户功能代号
type UserFeatureCode = string
const (
UserFeatureCodePlan UserFeatureCode = "plan"
UserFeatureCodeServerTCP UserFeatureCode = "server.tcp"
UserFeatureCodeServerTCPPort UserFeatureCode = "server.tcp.port"
UserFeatureCodeServerUDP UserFeatureCode = "server.udp"
UserFeatureCodeServerUDPPort UserFeatureCode = "server.udp.port"
UserFeatureCodeServerAccessLog UserFeatureCode = "server.accessLog"
UserFeatureCodeServerViewAccessLog UserFeatureCode = "server.viewAccessLog"
UserFeatureCodeServerScript UserFeatureCode = "server.script"
UserFeatureCodeServerWAF UserFeatureCode = "server.waf"
UserFeatureCodeServerOptimization UserFeatureCode = "server.optimization"
UserFeatureCodeServerUAM UserFeatureCode = "server.uam"
UserFeatureCodeServerWebP UserFeatureCode = "server.webp"
UserFeatureCodeServerCC UserFeatureCode = "server.cc"
UserFeatureCodeServerACME UserFeatureCode = "server.acme"
UserFeatureCodeServerAuth UserFeatureCode = "server.auth"
UserFeatureCodeServerWebsocket UserFeatureCode = "server.websocket"
UserFeatureCodeServerHTTP3 UserFeatureCode = "server.http3"
UserFeatureCodeServerReferers UserFeatureCode = "server.referers"
UserFeatureCodeServerUserAgent UserFeatureCode = "server.userAgent"
UserFeatureCodeServerRequestLimit UserFeatureCode = "server.requestLimit"
UserFeatureCodeServerCompression UserFeatureCode = "server.compression"
UserFeatureCodeServerRewriteRules UserFeatureCode = "server.rewriteRules"
UserFeatureCodeServerHostRedirects UserFeatureCode = "server.hostRedirects"
UserFeatureCodeServerHTTPHeaders UserFeatureCode = "server.httpHeaders"
UserFeatureCodeServerPages UserFeatureCode = "server.pages"
)
// UserFeature 用户功能
type UserFeature struct {
Name string `json:"name"`
Code string `json:"code"`
Description string `json:"description"`
SupportPlan bool `json:"supportPlan"`
}
func (this *UserFeature) ToPB() *pb.UserFeature {
return &pb.UserFeature{
Name: this.Name,
Code: this.Code,
Description: this.Description,
SupportPlan: this.SupportPlan,
}
}
// FindAllUserFeatures 所有功能列表
func FindAllUserFeatures() []*UserFeature {
return []*UserFeature{
{
Name: "记录访问日志",
Code: UserFeatureCodeServerAccessLog,
Description: "用户可以开启服务的访问日志。",
SupportPlan: true,
},
{
Name: "查看访问日志",
Code: UserFeatureCodeServerViewAccessLog,
Description: "用户可以查看服务的访问日志。",
SupportPlan: true,
},
/**{
Name: "转发访问日志",
Code: "server.accessLog.forward",
Description: "用户可以配置访问日志转发到自定义的API。",
SupportPlan: true,
},**/
{
Name: "TCP负载均衡",
Code: UserFeatureCodeServerTCP,
Description: "用户可以添加TCP/TLS负载均衡服务。",
SupportPlan: false,
},
{
Name: "自定义TCP负载均衡端口",
Code: UserFeatureCodeServerTCPPort,
Description: "用户可以自定义TCP端口。",
SupportPlan: true,
},
{
Name: "UDP负载均衡",
Code: UserFeatureCodeServerUDP,
Description: "用户可以添加UDP负载均衡服务。",
SupportPlan: false,
},
{
Name: "自定义UDP负载均衡端口",
Code: UserFeatureCodeServerUDPPort,
Description: "用户可以自定义UDP端口。",
SupportPlan: true,
},
{
Name: "申请免费证书",
Code: UserFeatureCodeServerACME,
Description: "用户可以申请ACME免费证书。",
SupportPlan: false,
},
{
Name: "开启WAF",
Code: UserFeatureCodeServerWAF,
Description: "用户可以开启WAF功能并可以设置黑白名单等。",
SupportPlan: true,
},
{
Name: "边缘脚本",
Code: UserFeatureCodeServerScript,
Description: "用户可以在使用边缘脚本过滤请求。",
SupportPlan: true,
},
{
Name: "5秒盾",
Code: UserFeatureCodeServerUAM,
Description: "用户可以使用5秒盾全站防护功能。",
SupportPlan: true,
},
{
Name: "CC防护",
Code: UserFeatureCodeServerCC,
Description: "用户可以使用CC防护功能。",
SupportPlan: true,
},
{
Name: "WebP",
Code: UserFeatureCodeServerWebP,
Description: "用户可以开启WebP自动转换功能。",
SupportPlan: true,
},
{
Name: "页面优化",
Code: UserFeatureCodeServerOptimization,
Description: "用户可以开启页面优化功能。",
SupportPlan: true,
},
{
Name: "访问鉴权",
Code: UserFeatureCodeServerAuth,
Description: "用户可以开启访问鉴权功能。",
SupportPlan: true,
},
{
Name: "Websocket",
Code: UserFeatureCodeServerWebsocket,
Description: "用户可以开启Websocket功能。",
SupportPlan: true,
},
{
Name: "防盗链",
Code: UserFeatureCodeServerReferers,
Description: "用户可以开启防盗链功能。",
SupportPlan: true,
},
{
Name: "UA名单",
Code: UserFeatureCodeServerUserAgent,
Description: "用户可以开启UserAgent允许和禁止的名单。",
SupportPlan: true,
},
{
Name: "HTTP/3",
Code: UserFeatureCodeServerHTTP3,
Description: "用户可以开启HTTP/3功能。",
SupportPlan: true,
},
{
Name: "请求限制",
Code: UserFeatureCodeServerRequestLimit,
Description: "用户可以限制单网站并发连接数、带宽等。",
SupportPlan: true,
},
{
Name: "内容压缩",
Code: UserFeatureCodeServerCompression,
Description: "用户可以使用内容压缩功能。",
SupportPlan: true,
},
{
Name: "URL跳转",
Code: UserFeatureCodeServerHostRedirects,
Description: "用户可以使用URL跳转功能。",
SupportPlan: true,
},
{
Name: "重写规则",
Code: UserFeatureCodeServerRewriteRules,
Description: "用户可以使用重写规则功能。",
SupportPlan: true,
},
{
Name: "HTTP报头",
Code: UserFeatureCodeServerHTTPHeaders,
Description: "用户可以管理网站相关请求和响应报头。",
SupportPlan: true,
},
{
Name: "自定义页面",
Code: UserFeatureCodeServerPages,
Description: "用户可以自定义404、50x等页面。",
SupportPlan: true,
},
{
Name: "套餐",
Code: UserFeatureCodePlan,
Description: "用户可以购买和管理套餐。",
SupportPlan: false,
},
}
}
// FindUserFeature 查询单个功能
func FindUserFeature(code string) *UserFeature {
for _, feature := range FindAllUserFeatures() {
if feature.Code == code {
return feature
}
}
return nil
}
// CheckUserFeature 检查某个功能代号是否正确
func CheckUserFeature(featureCode string) bool {
return FindUserFeature(featureCode) != nil
}

View File

@@ -0,0 +1,32 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package userconfigs
// 认证状态
type UserIdentityStatus = string
const (
UserIdentityStatusNone UserIdentityStatus = "none"
UserIdentityStatusSubmitted UserIdentityStatus = "submitted"
UserIdentityStatusRejected UserIdentityStatus = "rejected"
UserIdentityStatusVerified UserIdentityStatus = "verified"
)
// 认证类型
type UserIdentityType = string
const (
UserIdentityTypeIDCard UserIdentityType = "idCard"
UserIdentityTypeEnterpriseLicense UserIdentityType = "enterpriseLicense"
)
// 组织类型
type UserIdentityOrgType = string
const (
UserIdentityOrgTypeEnterprise UserIdentityOrgType = "enterprise"
UserIdentityOrgTypeIndividual UserIdentityOrgType = "individual"
)

View File

@@ -0,0 +1,13 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package userconfigs
type UserModule = string
const (
UserModuleCDN UserModule = "cdn"
UserModuleAntiDDoS UserModule = "antiDDoS"
UserModuleNS UserModule = "ns"
)
var DefaultUserModules = []UserModule{UserModuleCDN}

View File

@@ -0,0 +1,76 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package userconfigs
const (
MobileVerificationCodeLength = 6 // sms verification code length
MobileVerificationDailyLimit = 10 // sms verification times limit per day
)
// UserNotificationType 业务类型
type UserNotificationType = string
const (
UserNotificationTypeServer UserNotificationType = "server"
UserNotificationTypeBill UserNotificationType = "bill"
UserNotificationTypeNS UserNotificationType = "ns"
)
// UserNotificationMedia 媒介类型
type UserNotificationMedia = string
const (
UserNotificationMediaEmail UserNotificationMedia = "email"
)
// UserNotificationItem 单个业务配置
type UserNotificationItem struct {
Type UserNotificationType `json:"type"`
Medias []UserNotificationMedia `json:"medias"`
}
func FindAllUserNotificationItems() []*UserNotificationItem {
return []*UserNotificationItem{
{
Type: UserNotificationTypeServer,
Medias: []UserNotificationMedia{UserNotificationMediaEmail},
},
{
Type: UserNotificationTypeBill,
Medias: []UserNotificationMedia{UserNotificationMediaEmail},
},
{
Type: UserNotificationTypeNS,
Medias: []UserNotificationMedia{UserNotificationMediaEmail},
},
}
}
// UserNotificationConfig 用户通知订阅
type UserNotificationConfig struct {
Items []*UserNotificationItem `json:"items"`
}
func NewUserNotificationConfig() *UserNotificationConfig {
return &UserNotificationConfig{}
}
func (this *UserNotificationConfig) Support(notificationType UserNotificationType, media UserNotificationMedia) bool {
var items = this.Items
if len(items) == 0 {
items = FindAllUserNotificationItems()
}
for _, notification := range items {
if notification.Type == notificationType {
for _, allowMedia := range notification.Medias {
if allowMedia == media {
return true
}
}
return false
}
}
return false
}

View File

@@ -0,0 +1,20 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package userconfigs_test
import (
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
"testing"
)
func TestUserNotificationConfig_Support(t *testing.T) {
var config = userconfigs.NewUserNotificationConfig()
t.Log(config.Support(userconfigs.UserNotificationTypeBill, userconfigs.UserNotificationMediaEmail))
config.Items = append(config.Items, &userconfigs.UserNotificationItem{
Type: userconfigs.UserNotificationTypeBill,
Medias: []string{"mobile", userconfigs.UserNotificationMediaEmail},
})
t.Log(config.Support(userconfigs.UserNotificationTypeBill, userconfigs.UserNotificationMediaEmail))
}

View File

@@ -0,0 +1,24 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package userconfigs
import "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
// UserOrderConfig 用户订单配置
type UserOrderConfig struct {
EnablePay bool `json:"enablePay"` // 启用支付
DisablePageHTML string `json:"disablePageHTML"` // 禁用支付时的页面提示
OrderLife *shared.TimeDuration `json:"orderLife"` // 过期时间
}
func DefaultUserOrderConfig() *UserOrderConfig {
return &UserOrderConfig{
EnablePay: false,
DisablePageHTML: "暂不提供在线充值功能,请联系管理员充值。",
OrderLife: &shared.TimeDuration{
Count: 1,
Unit: shared.TimeDurationUnitHour,
},
}
}

View File

@@ -0,0 +1,132 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package userconfigs
import (
"encoding/json"
"fmt"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
)
type PayMethod = string
const (
PayMethodAlipay PayMethod = "alipay"
)
type PayMethodParams interface {
Init() error
}
type AlipayPayMethodParams struct {
IsSandbox bool `json:"isSandbox"` // 是否沙箱应用
AppId string `json:"appId"` // APPID
PrivateKey string `json:"privateKey"` // 私钥
AppPublicCert string `json:"appPublicCert"` // 应用公钥证书
AlipayPublicCert string `json:"alipayPublicCert"` // 支付宝公钥证书
AlipayRootCert string `json:"alipayRootCert"` // 支付宝根证书
ProductCode string `json:"productCode"` // 产品代号
}
func (this *AlipayPayMethodParams) Init() error {
return nil
}
type PayMethodDefinition struct {
Name string `json:"name"`
Code string `json:"code"`
Description string `json:"description"`
QRCodeTitle string `json:"qrcodeTitle"` // 二维码标题
NotifyURL string `json:"notifyURL"`
}
func FindAllPresetPayMethods() []*PayMethodDefinition {
return []*PayMethodDefinition{
{
Name: "支付宝",
Code: PayMethodAlipay,
Description: "支付宝平台提供的支付能力。",
QRCodeTitle: "请使用支付宝APP扫描下方二维码完成支付",
NotifyURL: "${baseAddr}/api/pay/alipay/notify",
},
}
}
func FindPresetPayMethodWithCode(code PayMethod) *PayMethodDefinition {
for _, payMethod := range FindAllPresetPayMethods() {
if payMethod.Code == code {
return payMethod
}
}
return nil
}
func DecodePayMethodParams(payMethodCode PayMethod, paramsJSON []byte) (params PayMethodParams, err error) {
switch payMethodCode {
case PayMethodAlipay:
params = &AlipayPayMethodParams{}
}
if params == nil {
return
}
err = json.Unmarshal(paramsJSON, params)
if err != nil {
return nil, fmt.Errorf("decode params failed: %w", err)
}
err = params.Init()
return
}
type PayClientType = string
const (
PayClientTypeAll PayClientType = "all"
PayClientTypeLaptop PayClientType = "laptop"
PayClientTypeMobile PayClientType = "mobile"
)
func FindAllPayClientTypes() []*shared.Definition {
return []*shared.Definition{
{
Name: "所有终端",
Code: PayClientTypeAll,
Description: "可以在电脑浏览器和手机上完成支付。",
},
{
Name: "PC端",
Code: PayClientTypeLaptop,
Description: "需要在电脑浏览器上完成支付。",
},
{
Name: "手机端",
Code: PayClientTypeMobile,
Description: "需要在手机上完成支付。",
},
}
}
func FindPayClientType(clientType PayClientType) *shared.Definition {
var allTypes = FindAllPayClientTypes()
if len(allTypes) == 0 {
return nil
}
for _, def := range allTypes {
if def.Code == clientType {
return def
}
}
return allTypes[0]
}
func FindPayClientTypeName(clientType PayClientType) string {
for _, def := range FindAllPayClientTypes() {
if def.Code == clientType {
return def.Name
}
}
return "所有终端"
}

View File

@@ -0,0 +1,110 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build plus
package userconfigs
import (
"encoding/json"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
)
type PriceType = string
const (
PriceTypeTraffic PriceType = "traffic" // 按流量
PriceTypeBandwidth PriceType = "bandwidth" // 按带宽
PriceTypePeriod PriceType = "period" // 按周期
PriceTypePlan PriceType = "plan" // 套餐
)
func IsValidPriceType(priceType string) bool {
return priceType == PriceTypeTraffic ||
priceType == PriceTypeBandwidth ||
priceType == PriceTypePeriod ||
priceType == PriceTypePlan
}
func PriceTypeName(priceType PriceType) string {
switch priceType {
case PriceTypeTraffic:
return "按流量"
case PriceTypeBandwidth:
return "按带宽"
case PriceTypePeriod:
return "按周期"
case PriceTypePlan:
return "按套餐"
}
return ""
}
// UserPriceConfig 计费相关设置
type UserPriceConfig struct {
IsOn bool `yaml:"isOn" json:"isOn"`
EnablePlans bool `yaml:"enablePlans" json:"enablePlans"` // 是否使用套餐
ShowPlansInUserSystem bool `yaml:"showPlansInUserSystem" json:"showPlansInUserSystem"` // 是否在用户系统显示套餐
EnableTrafficPackages bool `yaml:"enableTrafficPackages" json:"enableTrafficPackages"` // 是否可以使用流量包
ShowTrafficPackages bool `yaml:"showTrafficPackages" json:"showTrafficPackages"` // 在用户界面显示流量包
MaxTrafficPackagesInOrder int32 `yaml:"maxTrafficPackagesInOrder" json:"maxTrafficPackagesInOrder"` // 单次订单能购买的流量包数量 TODO 暂时不实现
DefaultPriceType PriceType `yaml:"priceType" json:"priceType"` // 默认计费方式
DefaultPricePeriod string `yaml:"pricePeriod" json:"pricePeriod"` // 默认计费周期
UserCanChangePriceType bool `yaml:"userCanChangePriceType" json:"userCanChangePriceType"` // 用户是否可以自定义计费方式
UserCanChangePricePeriod bool `yaml:"userCanChangePricePeriod" json:"userCanChangePricePeriod"` // 用户可以自定义计费周期
DefaultTrafficPriceConfig *serverconfigs.PlanTrafficPriceConfig `yaml:"trafficPrice" json:"trafficPrice"` // 默认流量价格
DefaultBandwidthPriceConfig *serverconfigs.PlanBandwidthPriceConfig `yaml:"bandwidthPrice" json:"bandwidthPrice"` // 默认带宽价格
UnpaidBillPolicy struct { // 未支付账单策略
IsOn bool `json:"isOn"` // 是否启用
MinDailyBillDays int32 `json:"minDailyBillDays"` // 日账单:允许未支付的最大天数
MinMonthlyBillDays int32 `json:"minMonthlyBillDays"` // 月账单:允许未支付的最大天数
DisableServers bool `json:"disableServers"` // 是否停止服务运行
} `json:"unpaidBillPolicy"`
UserUI struct {
ShowPrices bool `yaml:"showPrices" json:"showPrices"` // 显示价格和价格计算器
} `yaml:"userUI" json:"userUI"` // 用户界面相关配置
}
func (this *UserPriceConfig) Clone() (*UserPriceConfig, error) {
jsonBytes, err := json.Marshal(this)
if err != nil {
return nil, err
}
var config = &UserPriceConfig{}
err = json.Unmarshal(jsonBytes, config)
return config, err
}
func DefaultUserPriceConfig() *UserPriceConfig {
return &UserPriceConfig{
DefaultPriceType: PriceTypeBandwidth,
DefaultPricePeriod: PricePeriodMonthly,
ShowPlansInUserSystem: true,
}
}
type PricePeriod = string
const (
PricePeriodDaily PricePeriod = "daily" // 日结
PricePeriodMonthly PricePeriod = "monthly" // 月结
)
func IsValidPricePeriod(period string) bool {
return period == PricePeriodDaily || period == PricePeriodMonthly
}
func PricePeriodName(period PricePeriod) string {
switch period {
case PricePeriodDaily:
return "按日"
case PricePeriodMonthly:
return "按月"
}
return ""
}

View File

@@ -0,0 +1,101 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package userconfigs
const (
EmailVerificationDefaultLife = 86400 * 2 // 2 days
EmailResetPasswordDefaultLife = 3600 // 1 hour
MobileVerificationDefaultLife = 1800 // 30 minutes
MobileResetPasswordDefaultLife = 1800 // 30 minutes
)
type UserRegisterConfig struct {
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用用户注册
ComplexPassword bool `yaml:"complexPassword" json:"complexPassword"` // 必须使用复杂密码
RequireVerification bool `yaml:"requireVerification" json:"requireVerification"` // 是否需要审核
RequireIdentity bool `yaml:"requireIdentity" json:"requireIdentity"` // 是否需要实名认证
CheckClientRegion bool `yaml:"checkClientRegion" json:"checkClientRegion"` // 在登录状态下检查客户端区域
// 电子邮箱激活设置
EmailVerification struct {
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
ShowNotice bool `yaml:"showNotice" json:"showNotice"` // 提示用户未绑定
Subject string `yaml:"subject" json:"subject"` // 标题
Body string `yaml:"body" json:"body"` // 内容
CanLogin bool `yaml:"canLogin" json:"canLogin"` // 是否可以使用激活的邮箱登录
Life int32 `yaml:"life" json:"life"` // 有效期
} `yaml:"emailVerification" json:"emailVerification"`
// 通过邮件找回密码设置
EmailResetPassword struct {
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
Subject string `yaml:"subject" json:"subject"` // 标题
Body string `yaml:"body" json:"body"` // 内容
Life int32 `yaml:"life" json:"life"` // 有效期
} `yaml:"emailResetPassword" json:"emailResetPassword"`
// 手机号码激活设置
MobileVerification struct {
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
ShowNotice bool `yaml:"showNotice" json:"showNotice"` // 提示用户未绑定
CanLogin bool `yaml:"canLogin" json:"canLogin"` // 是否可以使用激活的邮箱登录
Body string `yaml:"body" json:"body"` // 内容
Life int32 `yaml:"life" json:"life"` // 有效期
Force bool `yaml:"force" json:"force"` // 是否强制绑定
} `yaml:"mobileVerification" json:"mobileVerification"`
// CDN
CDNIsOn bool `json:"cdnIsOn"` // 是否开启CDN服务
ClusterId int64 `yaml:"clusterId" json:"clusterId"` // 用户创建服务集群
Features []string `yaml:"features" json:"features"` // 默认启用的功能
// 开通DNS服务
NSIsOn bool `json:"nsIsOn"` // 是否开启智能DNS服务
// 开通高防服务
ADIsOn bool `json:"adIsOn"` // 是否开启高防服务
}
func DefaultUserRegisterConfig() *UserRegisterConfig {
var config = &UserRegisterConfig{
IsOn: false,
ComplexPassword: true,
CDNIsOn: true,
NSIsOn: false,
Features: []string{
UserFeatureCodeServerAccessLog,
UserFeatureCodeServerViewAccessLog,
UserFeatureCodeServerWAF,
UserFeatureCodePlan,
},
RequireVerification: false,
}
// 邮箱激活相关
config.EmailVerification.CanLogin = true
config.EmailVerification.ShowNotice = true
config.EmailVerification.Subject = "【${product.name}】Email地址激活"
config.EmailVerification.Body = `<p>欢迎你使用 ${product.name} 提供的服务你需要点击以下链接激活你的Email邮箱</p>
<p><a href="${url.verify}" target="_blank">${url.verify}</a></p>
<p>如果上面内容不是链接形式,请将该地址手工粘贴到浏览器地址栏再访问。</p>
<p></p>
<p>此致</p>
<p>${product.name} 管理团队</p>
<p><a href="${url.home}" target="_blank">${url.home}</a></p>
`
// 通过邮件重置密码相关
config.EmailResetPassword.IsOn = true
config.EmailResetPassword.Subject = "【${product.name}】找回密码"
config.EmailResetPassword.Body = `<p>你正在使用 ${product.name} 提供的找回密码功能,你需要将以下的数字验证码输入到找回密码页面中:</p>
<p><strong>验证码:${code}</strong></p>
<p></p>
<p>${product.name} 管理团队</p>
<p><a href="${url.home}" target="_blank">${url.home}</a></p>
`
// 短信验证码
config.MobileVerification.Body = "你的短信验证码${code}"
return config
}

View File

@@ -0,0 +1,105 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package userconfigs
import (
"encoding/json"
"errors"
)
type EmailSenderConfig struct {
IsOn bool `yaml:"isOn" json:"isOn"`
SMTPHost string `yaml:"smtpHost" json:"smtpHost"`
SMTPPort int32 `yaml:"smtpPort" json:"smtpPort"`
Protocol string `yaml:"protocol" json:"protocol"` // tcp|tls
Username string `yaml:"username" json:"username"`
Password string `yaml:"password" json:"password"`
FromEmail string `yaml:"fromEmail" json:"fromEmail"` // 发件人Email
FromName string `yaml:"fromName" json:"fromName"` // 发件人名称
}
func NewEmailSenderConfig() *EmailSenderConfig {
return &EmailSenderConfig{
IsOn: true,
}
}
type SMSSenderType = string
const (
SMSSenderWebHook = "webHook"
SMSSenderAliyunSMS = "aliyunSMS"
SMSSenderTencentSMS = "tencentSMS"
)
type SMSSenderConfig struct {
IsOn bool `yaml:"isOn" json:"isOn"`
Type SMSSenderType `yaml:"type" json:"type"`
WebHookParams *SMSSenderWebHookParams `yaml:"webHookParams" json:"webHookParams"`
AliyunSMSParams *SMSSenderAliyunSMSParams `yaml:"aliyunSMSParams" json:"aliyunSMSParams"`
TencentSMSParams *SMSSenderTencentSMSParams `yaml:"tencentSMSParams" json:"tencentSMSParams"`
}
func NewSMSSenderConfig() *SMSSenderConfig {
return &SMSSenderConfig{
IsOn: true,
Type: SMSSenderWebHook,
WebHookParams: &SMSSenderWebHookParams{
URL: "",
Method: "GET",
},
AliyunSMSParams: &SMSSenderAliyunSMSParams{
CodeVarName: "code",
},
TencentSMSParams: &SMSSenderTencentSMSParams{},
}
}
func (this *SMSSenderConfig) ParamsJSON() ([]byte, error) {
var params any
switch this.Type {
case SMSSenderWebHook:
params = this.WebHookParams
case SMSSenderAliyunSMS:
params = this.AliyunSMSParams
case SMSSenderTencentSMS:
params = this.TencentSMSParams
default:
return nil, errors.New("not supported type '" + this.Type + "'")
}
return json.Marshal(params)
}
type SMSSenderWebHookParams struct {
URL string `yaml:"url" json:"url"` // (http|https)://...
Method string `yaml:"method" json:"method"` // GET|POST
}
type SMSSenderAliyunSMSParams struct {
Sign string `yaml:"sign" json:"sign"` // 签名名称
TemplateCode string `yaml:"templateCode" json:"templateCode"` // 模板CODE
CodeVarName string `yaml:"codeVarName" json:"codeVarName"` // 验证码变量
AccessKeyId string `yaml:"accessKeyId" json:"accessKeyId"` // AccessKeyId
AccessKeySecret string `yaml:"accessKeySecret" json:"accessKeySecret"` // AccessKeySecret
}
type SMSSenderTencentSMSParams struct {
SDKAppId string `yaml:"sdkAppId" json:"sdkAppId"` // 应用ID
Sign string `yaml:"sign" json:"sign"` // 签名名称
TemplateId string `yaml:"templateId" json:"templateId"` // 模板ID
AccessKeyId string `yaml:"accessKeyId" json:"accessKeyId"` // AccessKeyId
AccessKeySecret string `yaml:"accessKeySecret" json:"accessKeySecret"` // AccessKeySecret
}
type UserSenderConfig struct {
VerifyEmail *EmailSenderConfig `yaml:"verifyEmail" json:"verifyEmail"` // 验证邮件
NotifyEmail *EmailSenderConfig `yaml:"notifyEmail" json:"notifyEmail"` // 通知邮件
VerifySMS *SMSSenderConfig `yaml:"verifySMS" json:"verifySMS"` // 验证短信
NotifySMS *SMSSenderConfig `yaml:"notifySMS" json:"notifySMS"` // 通知短信
}
func DefaultUserSenderConfig() *UserSenderConfig {
return &UserSenderConfig{}
}

View File

@@ -0,0 +1,39 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package userconfigs
const (
MaxCacheKeysPerTask int32 = 1000
MaxCacheKeysPerDay int32 = 10000
)
type HTTPCacheTaskConfig struct {
MaxKeysPerTask int32 `yaml:"maxKeysPerTask" json:"maxKeysPerTask"`
MaxKeysPerDay int32 `yaml:"maxKeysPerDay" json:"maxKeysPerDay"`
}
func DefaultHTTPCacheTaskConfig() *HTTPCacheTaskConfig {
return &HTTPCacheTaskConfig{
MaxKeysPerTask: 0,
MaxKeysPerDay: 0,
}
}
// UserServerConfig 用户服务设置
type UserServerConfig struct {
GroupId int64 `yaml:"groupId" json:"groupId"` // 分组
RequirePlan bool `yaml:"requirePlan" json:"requirePlan"` // 必须使用套餐
EnableStat bool `yaml:"enableStat" json:"enableStat"` // 开启统计
HTTPCacheTaskPurgeConfig *HTTPCacheTaskConfig `yaml:"httpCacheTaskPurgeConfig" json:"httpCacheTaskPurgeConfig"` // 缓存任务删除配置
HTTPCacheTaskFetchConfig *HTTPCacheTaskConfig `yaml:"httpCacheTaskFetchConfig" json:"httpCacheTaskFetchConfig"` // 缓存任务预热配置
}
func DefaultUserServerConfig() *UserServerConfig {
return &UserServerConfig{
GroupId: 0,
RequirePlan: false,
EnableStat: true,
HTTPCacheTaskPurgeConfig: DefaultHTTPCacheTaskConfig(),
HTTPCacheTaskFetchConfig: DefaultHTTPCacheTaskConfig(),
}
}

View File

@@ -0,0 +1,42 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package userconfigs
import "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
type UserTicketStatus = string
const (
UserTicketStatusNone UserTicketStatus = "none"
UserTicketStatusSolved UserTicketStatus = "solved"
UserTicketStatusClosed UserTicketStatus = "closed"
)
func UserTicketStatusName(status UserTicketStatus) string {
switch status {
case UserTicketStatusNone:
return "进行中"
case UserTicketStatusSolved:
return "已解决"
case UserTicketStatusClosed:
return "已关闭"
}
return ""
}
func FindAllUserTicketStatusList() []*shared.Definition {
return []*shared.Definition{
{
Name: "进行中",
Code: UserTicketStatusNone,
},
{
Name: "已解决",
Code: UserTicketStatusSolved,
},
{
Name: "已关闭",
Code: UserTicketStatusClosed,
},
}
}

View File

@@ -0,0 +1,63 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package userconfigs
type TrafficPackagePeriod = string
const (
TrafficPackagePeriodMonth TrafficPackagePeriod = "month"
TrafficPackagePeriodYear TrafficPackagePeriod = "year"
)
func IsValidTrafficPackagePeriod(period string) bool {
return period == TrafficPackagePeriodMonth || period == TrafficPackagePeriodYear
}
func TrafficPackagePeriodToMonths(count int32, unit TrafficPackagePeriod) int32 {
if count < 0 {
return count
}
switch unit {
case TrafficPackagePeriodMonth:
return count
case TrafficPackagePeriodYear:
return count * 12
}
return 0
}
func TrafficPackagePeriodUnitName(unit TrafficPackagePeriod) string {
switch unit {
case TrafficPackagePeriodMonth:
return "个月"
case TrafficPackagePeriodYear:
return "年"
}
return ""
}
type PackageSizeUnit = string
const (
TrafficPackageSizeUnitGB PackageSizeUnit = "gb"
TrafficPackageSizeUnitTB PackageSizeUnit = "tb"
TrafficPackageSizeUnitPB PackageSizeUnit = "pb"
)
func IsValidTrafficPackageSizeUnit(unit string) bool {
return unit == TrafficPackageSizeUnitGB || unit == TrafficPackageSizeUnitTB || unit == TrafficPackageSizeUnitPB
}
func TrafficPackageSizeBytes(count int32, unit PackageSizeUnit) int64 {
switch unit {
case TrafficPackageSizeUnitGB:
return int64(count) * (1 << 30)
case TrafficPackageSizeUnitTB:
return int64(count) * (1 << 40)
case TrafficPackageSizeUnitPB:
return int64(count) * (1 << 50)
}
return 0
}