Compare commits

...

37 Commits

Author SHA1 Message Date
刘祥超
4bd7ec9871 优化远程安装时uname读取方法 2023-01-08 20:13:09 +08:00
刘祥超
95cfad60c4 更新SQL 2023-01-08 20:12:38 +08:00
刘祥超
7f51d451f7 用户Dashboard信息中增加缓存、攻击相关信息 2023-01-08 11:50:47 +08:00
刘祥超
a4fb0fd795 更新SQL 2023-01-07 19:36:09 +08:00
刘祥超
c02928dd44 升级数据库时同时升级edgeClientAgentIPs中的countIPs字段值 2023-01-07 10:29:08 +08:00
刘祥超
e70c49d407 创建缓存任务时即使没有有效的Key,也可以在后台查看创建的任务 2023-01-05 17:09:20 +08:00
刘祥超
e1c1984fd4 华为云可以设置终端节点(endpoint) 2023-01-01 18:29:33 +08:00
刘祥超
f801d304c6 优化代码 2022-12-31 17:31:27 +08:00
刘祥超
178a38c6d9 优化证书加载速度 2022-12-31 17:21:40 +08:00
刘祥超
e356707db7 优化证书数量很多时的页面加载速度 2022-12-31 17:12:39 +08:00
刘祥超
8d3043d0fe 实现UA名单功能 2022-12-30 20:49:20 +08:00
刘祥超
1e494bd1fd 更新SQL 2022-12-29 19:15:01 +08:00
刘祥超
b726c8d589 增加CORS自适应跨域 2022-12-29 17:16:21 +08:00
刘祥超
e71e80703d 远程安装时使用uname取代/usr/bin/uname命令 2022-12-28 19:01:09 +08:00
刘祥超
c9b666e5bc 增加基础的用户邮件通知 2022-12-27 18:53:49 +08:00
刘祥超
874139ea07 调整Agent相关接口权限 2022-12-22 11:42:30 +08:00
刘祥超
05d79ad606 服务没有所属用户时,可以修改所属用户 2022-12-21 17:07:02 +08:00
刘祥超
13c78a5fec 修改/取消服务套餐同时按需变更DNS 2022-12-17 15:16:01 +08:00
刘祥超
f3e3824b7d DNS完善实现SRV和CAA记录 2022-12-15 16:17:54 +08:00
刘祥超
67473c2dcf 优化代码 2022-12-14 17:32:24 +08:00
刘祥超
3921c547be 智能DNS初步支持搜索引擎线路 2022-12-13 18:39:23 +08:00
刘祥超
3e0d2fda6a 优化代码 2022-12-12 11:12:55 +08:00
刘祥超
7ff6c0c18b 优化代码 2022-12-12 10:28:22 +08:00
刘祥超
e76464673a 实现用户通过邮件重置密码功能 2022-12-10 15:57:17 +08:00
刘祥超
1ab849d9b0 初步完成用户电子邮箱绑定(激活) 2022-12-08 20:25:46 +08:00
刘祥超
781c851571 增加测试用例 2022-12-06 14:53:38 +08:00
刘祥超
0b19d93a47 缩短访问日志自动清理时间(从每12个小时改成每6个小时) 2022-12-03 21:51:55 +08:00
刘祥超
2856f7716b 实现线路优先级 2022-12-03 20:49:53 +08:00
刘祥超
c9ba24dc96 操作系统和浏览器ID字段改为bigint 2022-12-03 20:49:46 +08:00
刘祥超
a660fb1f42 调整自动远程启动离线节点的错误级别 2022-12-02 17:34:24 +08:00
刘祥超
8586ad6478 管理员和用户状态为不可用时,删除已生成的API令牌 2022-12-02 17:33:45 +08:00
刘祥超
0fab6fecfe 获取API令牌时检查管理员和用户状态 2022-12-02 17:33:01 +08:00
刘祥超
d752bb08c7 版本号更改为0.6.0 2022-11-29 15:41:21 +08:00
刘祥超
6f845f36c9 版本号修改为0.5.10 2022-11-28 18:59:09 +08:00
刘祥超
66bc60a47c 更新SQL 2022-11-28 18:17:25 +08:00
刘祥超
1c048da1f0 节点版本号修改为0.5.9 2022-11-28 18:14:17 +08:00
刘祥超
da8aa20f83 版本号修改为0.5.9 2022-11-28 15:58:40 +08:00
89 changed files with 1831 additions and 389 deletions

View File

@@ -1,7 +1,7 @@
package teaconst
const (
Version = "0.5.8"
Version = "0.6.0"
ProductName = "Edge API"
ProcessName = "edge-api"
@@ -18,8 +18,8 @@ const (
// 其他节点版本号,用来检测是否有需要升级的节点
NodeVersion = "0.5.8"
NodeVersion = "0.6.0"
// SQLVersion SQL版本号
SQLVersion = "4"
SQLVersion = "9"
)

View File

@@ -44,11 +44,17 @@ func (this *AdminDAO) EnableAdmin(tx *dbs.Tx, id int64) (rowsAffected int64, err
}
// DisableAdmin 禁用条目
func (this *AdminDAO) DisableAdmin(tx *dbs.Tx, id int64) (rowsAffected int64, err error) {
return this.Query(tx).
Pk(id).
func (this *AdminDAO) DisableAdmin(tx *dbs.Tx, adminId int64) error {
err := this.Query(tx).
Pk(adminId).
Set("state", AdminStateDisabled).
Update()
UpdateQuickly()
if err != nil {
return err
}
// 删除AccessTokens
return SharedAPIAccessTokenDAO.DeleteAccessTokens(tx, adminId, 0)
}
// FindEnabledAdmin 查找启用中的条目
@@ -190,7 +196,19 @@ func (this *AdminDAO) UpdateAdmin(tx *dbs.Tx, adminId int64, username string, ca
}
op.IsOn = isOn
err := this.Save(tx, op)
return err
if err != nil {
return err
}
if !isOn {
// 删除AccessTokens
err = SharedAPIAccessTokenDAO.DeleteAccessTokens(tx, adminId, 0)
if err != nil {
return err
}
}
return nil
}
// CheckAdminUsername 检查用户名是否存在

View File

@@ -81,3 +81,16 @@ func (this *APIAccessTokenDAO) FindAccessToken(tx *dbs.Tx, token string) (*APIAc
}
return one.(*APIAccessToken), nil
}
// DeleteAccessTokens 删除用户的令牌
func (this *APIAccessTokenDAO) DeleteAccessTokens(tx *dbs.Tx, adminId int64, userId int64) error {
var query = this.Query(tx)
if adminId > 0 {
query.Attr("adminId", adminId)
} else if userId > 0 {
query.Attr("userId", userId)
} else {
return nil
}
return query.DeleteQuickly()
}

View File

@@ -43,9 +43,9 @@ func (this *APINode) DecodeHTTPS(tx *dbs.Tx, cacheMap *utils.CacheMap) (*serverc
}
if config.SSLPolicyRef != nil {
policyId := config.SSLPolicyRef.SSLPolicyId
var policyId = config.SSLPolicyRef.SSLPolicyId
if policyId > 0 {
sslPolicy, err := SharedSSLPolicyDAO.ComposePolicyConfig(tx, policyId, cacheMap)
sslPolicy, err := SharedSSLPolicyDAO.ComposePolicyConfig(tx, policyId, false, cacheMap)
if err != nil {
return nil, err
}
@@ -143,7 +143,7 @@ func (this *APINode) DecodeRestHTTPS(tx *dbs.Tx, cacheMap *utils.CacheMap) (*ser
if config.SSLPolicyRef != nil {
policyId := config.SSLPolicyRef.SSLPolicyId
if policyId > 0 {
sslPolicy, err := SharedSSLPolicyDAO.ComposePolicyConfig(tx, policyId, cacheMap)
sslPolicy, err := SharedSSLPolicyDAO.ComposePolicyConfig(tx, policyId, false, cacheMap)
if err != nil {
return nil, err
}

View File

@@ -0,0 +1,98 @@
package clients
import (
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
)
type ClientAgentDAO dbs.DAO
func NewClientAgentDAO() *ClientAgentDAO {
return dbs.NewDAO(&ClientAgentDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeClientAgents",
Model: new(ClientAgent),
PkName: "id",
},
}).(*ClientAgentDAO)
}
var SharedClientAgentDAO *ClientAgentDAO
func init() {
dbs.OnReady(func() {
SharedClientAgentDAO = NewClientAgentDAO()
})
}
// FindClientAgentName 根据主键查找名称
func (this *ClientAgentDAO) FindClientAgentName(tx *dbs.Tx, id int64) (string, error) {
return this.Query(tx).
Pk(id).
Result("name").
FindStringCol("")
}
// FindAgent 查找Agent
func (this *ClientAgentDAO) FindAgent(tx *dbs.Tx, agentId int64) (*ClientAgent, error) {
if agentId <= 0 {
return nil, nil
}
one, err := this.Query(tx).
Pk(agentId).
Find()
if err != nil || one == nil {
return nil, err
}
return one.(*ClientAgent), nil
}
// FindAgentIdWithCode 根据代号查找ID
func (this *ClientAgentDAO) FindAgentIdWithCode(tx *dbs.Tx, code string) (int64, error) {
return this.Query(tx).
ResultPk().
Attr("code", code).
FindInt64Col(0)
}
// FindAgentNameWithCode 根据代号查找Agent名称
func (this *ClientAgentDAO) FindAgentNameWithCode(tx *dbs.Tx, code string) (string, error) {
return this.Query(tx).
Result("name").
Attr("code", code).
FindStringCol("")
}
// UpdateAgentCountIPs 修改Agent拥有的IP数量
func (this *ClientAgentDAO) UpdateAgentCountIPs(tx *dbs.Tx, agentId int64, countIPs int64) error {
return this.Query(tx).
Pk(agentId).
Set("countIPs", countIPs).
UpdateQuickly()
}
// FindAllAgents 查找所有Agents
func (this *ClientAgentDAO) FindAllAgents(tx *dbs.Tx) (result []*ClientAgent, err error) {
_, err = this.Query(tx).
Desc("order").
AscPk().
Slice(&result).
FindAll()
return
}
// FindAllNSAgents 查找所有DNS可以使用的Agents
func (this *ClientAgentDAO) FindAllNSAgents(tx *dbs.Tx) (result []*ClientAgent, err error) {
// 注意允许NS使用所有的Agent不管有没有IP数据
_, err = this.Query(tx).
Result("id", "name", "code").
Desc("order").
AscPk().
Slice(&result).
FindAll()
return
}

View File

@@ -0,0 +1,6 @@
package clients_test
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View File

@@ -0,0 +1,105 @@
package clients
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
)
// TODO 需要定时对所有IP的PTR进行检查剔除已经变更的IP
type ClientAgentIPDAO dbs.DAO
func NewClientAgentIPDAO() *ClientAgentIPDAO {
return dbs.NewDAO(&ClientAgentIPDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeClientAgentIPs",
Model: new(ClientAgentIP),
PkName: "id",
},
}).(*ClientAgentIPDAO)
}
var SharedClientAgentIPDAO *ClientAgentIPDAO
func init() {
dbs.OnReady(func() {
SharedClientAgentIPDAO = NewClientAgentIPDAO()
})
}
// CreateIP 写入IP
func (this *ClientAgentIPDAO) CreateIP(tx *dbs.Tx, agentId int64, ip string, ptr string) error {
// 检查数据有效性
if agentId <= 0 || len(ip) == 0 {
return nil
}
// 限制ptr长度
if len(ptr) > 100 {
ptr = ptr[:100]
}
// 检查是否存在
exists, err := this.Query(tx).
Attr("agentId", agentId).
Attr("ip", ip).
Exist()
if err != nil {
return err
}
if exists {
return nil
}
var op = NewClientAgentIPOperator()
op.AgentId = agentId
op.IP = ip
op.Ptr = ptr
err = this.Save(tx, op)
if err != nil {
// 忽略duplicate错误
if models.CheckSQLDuplicateErr(err) {
return nil
}
return err
}
// 更新Agent IP数量
countIPs, err := this.CountAgentIPs(tx, agentId)
if err != nil {
return err
}
err = SharedClientAgentDAO.UpdateAgentCountIPs(tx, agentId, countIPs)
if err != nil {
return err
}
return nil
}
// ListIPsAfterId 列出某个ID之后的IP
func (this *ClientAgentIPDAO) ListIPsAfterId(tx *dbs.Tx, id int64, size int64) (result []*ClientAgentIP, err error) {
if id < 0 {
id = 0
}
_, err = this.Query(tx).
Result("id", "ip", "ptr", "agentId").
Gt("id", id).
AscPk().
Limit(size). // 限制单次读取个数
Slice(&result).
FindAll()
return
}
// CountAgentIPs 计算Agent IP数量
func (this *ClientAgentIPDAO) CountAgentIPs(tx *dbs.Tx, agentId int64) (int64, error) {
return this.Query(tx).
Attr("agentId", agentId).
Count()
}

View File

@@ -0,0 +1,16 @@
package clients_test
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models/clients"
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
"testing"
)
func TestClientAgentIPDAO_CreateIP(t *testing.T) {
var dao = clients.NewClientAgentIPDAO()
err := dao.CreateIP(nil, 1, "127.0.0.1", "")
if err != nil {
t.Fatal(err)
}
}

View File

@@ -0,0 +1,20 @@
package clients
// ClientAgentIP Agent IP
type ClientAgentIP struct {
Id uint64 `field:"id"` // ID
AgentId uint32 `field:"agentId"` // Agent ID
IP string `field:"ip"` // IP地址
Ptr string `field:"ptr"` // PTR值
}
type ClientAgentIPOperator struct {
Id any // ID
AgentId any // Agent ID
IP any // IP地址
Ptr any // PTR值
}
func NewClientAgentIPOperator() *ClientAgentIPOperator {
return &ClientAgentIPOperator{}
}

View File

@@ -0,0 +1 @@
package clients

View File

@@ -0,0 +1,24 @@
package clients
// ClientAgent Agent库
type ClientAgent struct {
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 名称
Code string `field:"code"` // 代号
Description string `field:"description"` // 介绍
Order uint32 `field:"order"` // 排序
CountIPs uint32 `field:"countIPs"` // IP数量
}
type ClientAgentOperator struct {
Id any // ID
Name any // 名称
Code any // 代号
Description any // 介绍
Order any // 排序
CountIPs any // IP数量
}
func NewClientAgentOperator() *ClientAgentOperator {
return &ClientAgentOperator{}
}

View File

@@ -0,0 +1,6 @@
package clients
// NSRouteCode NS线路代号
func (this *ClientAgent) NSRouteCode() string {
return "agent:" + this.Code
}

View File

@@ -1,6 +1,7 @@
package models
package clients
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/goman"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
"github.com/TeaOSLab/EdgeAPI/internal/utils/ttlcache"
@@ -130,7 +131,7 @@ func (this *ClientBrowserDAO) CreateBrowserIfNotExists(tx *dbs.Tx, browserName s
op.CreatedDay = timeutil.Format("Ymd")
op.State = ClientBrowserStateEnabled
browserId, err = this.SaveInt64(tx, op)
if err != nil && CheckSQLErrCode(err, 1062 /** duplicate entry **/) {
if err != nil && models.CheckSQLErrCode(err, 1062 /** duplicate entry **/) {
return nil
}

View File

@@ -1,13 +1,13 @@
package models_test
package clients_test
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/db/models/clients"
_ "github.com/go-sql-driver/mysql"
"testing"
)
func TestClientBrowserDAO_CreateBrowser(t *testing.T) {
var dao = models.NewClientBrowserDAO()
var dao = clients.NewClientBrowserDAO()
err := dao.CreateBrowserIfNotExists(nil, "Hello")
if err != nil {
t.Fatal(err)
@@ -25,7 +25,7 @@ func TestClientBrowserDAO_CreateBrowser(t *testing.T) {
}
func TestClientBrowserDAO_Clean(t *testing.T) {
var dao = models.NewClientBrowserDAO()
var dao = clients.NewClientBrowserDAO()
err := dao.Clean(nil, 30)
if err != nil {
t.Fatal(err)

View File

@@ -1,10 +1,10 @@
package models
package clients
import "github.com/iwind/TeaGo/dbs"
// ClientBrowser 终端浏览器信息
type ClientBrowser struct {
Id uint32 `field:"id"` // ID
Id uint64 `field:"id"` // ID
Name string `field:"name"` // 浏览器名称
Codes dbs.JSON `field:"codes"` // 代号
CreatedDay string `field:"createdDay"` // 创建日期YYYYMMDD

View File

@@ -0,0 +1 @@
package clients

View File

@@ -1,6 +1,7 @@
package models
package clients
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/goman"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
"github.com/TeaOSLab/EdgeAPI/internal/utils/ttlcache"
@@ -129,7 +130,7 @@ func (this *ClientSystemDAO) CreateSystemIfNotExists(tx *dbs.Tx, systemName stri
op.CreatedDay = timeutil.Format("Ymd")
op.State = ClientSystemStateEnabled
systemId, err = this.SaveInt64(tx, op)
if err != nil && CheckSQLErrCode(err, 1062 /** duplicate entry **/) {
if err != nil && models.CheckSQLErrCode(err, 1062 /** duplicate entry **/) {
return nil
}

View File

@@ -1,13 +1,13 @@
package models_test
package clients_test
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/db/models/clients"
_ "github.com/go-sql-driver/mysql"
"testing"
)
func TestClientSystemDAO_CreateSystemIfNotExists(t *testing.T) {
var dao = models.NewClientSystemDAO()
var dao = clients.NewClientSystemDAO()
{
err := dao.CreateSystemIfNotExists(nil, "Mac OS X")
if err != nil {
@@ -23,7 +23,7 @@ func TestClientSystemDAO_CreateSystemIfNotExists(t *testing.T) {
}
func TestClientSystemDAO_Clean(t *testing.T) {
var dao = models.NewClientSystemDAO()
var dao = clients.NewClientSystemDAO()
err := dao.Clean(nil, 30)
if err != nil {
t.Fatal(err)

View File

@@ -1,10 +1,10 @@
package models
package clients
import "github.com/iwind/TeaGo/dbs"
// ClientSystem 终端操作系统信息
type ClientSystem struct {
Id uint32 `field:"id"` // ID
Id uint64 `field:"id"` // ID
Name string `field:"name"` // 系统名称
Codes dbs.JSON `field:"codes"` // 代号
CreatedDay string `field:"createdDay"` // 创建日期YYYYMMDD

View File

@@ -0,0 +1 @@
package clients

View File

@@ -206,6 +206,7 @@ func (this *HTTPCacheTaskDAO) UpdateTaskStatus(tx *dbs.Tx, taskId int64, isDone
if isDone {
op.DoneAt = time.Now().Unix()
op.IsReady = true // 让后台列表能列出来
}
return this.Save(tx, op)

View File

@@ -182,19 +182,19 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
return nil, nil
}
config := &shared.HTTPHeaderPolicy{}
var config = &shared.HTTPHeaderPolicy{}
config.Id = int64(policy.Id)
config.IsOn = policy.IsOn
// SetHeaders
if IsNotNull(policy.SetHeaders) {
refs := []*shared.HTTPHeaderRef{}
var refs = []*shared.HTTPHeaderRef{}
err = json.Unmarshal(policy.SetHeaders, &refs)
if err != nil {
return nil, err
}
if len(refs) > 0 {
resultRefs := []*shared.HTTPHeaderRef{}
var resultRefs = []*shared.HTTPHeaderRef{}
for _, ref := range refs {
headerConfig, err := SharedHTTPHeaderDAO.ComposeHeaderConfig(tx, ref.HeaderId)
if err != nil {
@@ -212,7 +212,7 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
// Delete Headers
if IsNotNull(policy.DeleteHeaders) {
headers := []string{}
var headers = []string{}
err = json.Unmarshal(policy.DeleteHeaders, &headers)
if err != nil {
return nil, err
@@ -220,6 +220,16 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
config.DeleteHeaders = headers
}
// CORS
if IsNotNull(policy.Cors) {
var corsConfig = &shared.HTTPCORSHeaderConfig{}
err = json.Unmarshal(policy.Cors, corsConfig)
if err != nil {
return nil, err
}
config.CORS = corsConfig
}
// Expires
// TODO
@@ -235,6 +245,46 @@ func (this *HTTPHeaderPolicyDAO) FindHeaderPolicyIdWithHeaderId(tx *dbs.Tx, head
FindInt64Col(0)
}
// UpdateHeaderPolicyCORS 修改CORS
func (this *HTTPHeaderPolicyDAO) UpdateHeaderPolicyCORS(tx *dbs.Tx, headerPolicyId int64, corsConfig *shared.HTTPCORSHeaderConfig) error {
if headerPolicyId <= 0 {
return errors.New("invalid headerId")
}
corsJSON, err := json.Marshal(corsConfig)
if err != nil {
return err
}
err = this.Query(tx).
Pk(headerPolicyId).
Set("cors", corsJSON).
UpdateQuickly()
if err != nil {
return err
}
return this.NotifyUpdate(tx, headerPolicyId)
}
// CheckUserHeaderPolicy 检查用户权限
func (this *HTTPHeaderPolicyDAO) CheckUserHeaderPolicy(tx *dbs.Tx, userId int64, policyId int64) error {
if userId <= 0 || policyId <= 0 {
return ErrNotFound
}
webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithHeaderPolicyId(tx, policyId)
if err != nil {
return err
}
if webId <= 0 {
return ErrNotFound
}
return SharedHTTPWebDAO.CheckUserWeb(tx, userId, webId)
}
// NotifyUpdate 通知更新
func (this *HTTPHeaderPolicyDAO) NotifyUpdate(tx *dbs.Tx, policyId int64) error {
webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithHeaderPolicyId(tx, policyId)

View File

@@ -2,7 +2,7 @@ package models
import "github.com/iwind/TeaGo/dbs"
//
// HTTPHeaderPolicy Header定义
type HTTPHeaderPolicy struct {
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
@@ -16,21 +16,23 @@ type HTTPHeaderPolicy struct {
ReplaceHeaders dbs.JSON `field:"replaceHeaders"` // 替换Header内容
Expires dbs.JSON `field:"expires"` // Expires单独设置
DeleteHeaders dbs.JSON `field:"deleteHeaders"` // 删除的Headers
Cors dbs.JSON `field:"cors"` // CORS配置
}
type HTTPHeaderPolicyOperator struct {
Id interface{} // ID
IsOn interface{} // 是否启用
State interface{} // 状态
AdminId interface{} // 管理员ID
UserId interface{} // 用户ID
CreatedAt interface{} // 创建时间
AddHeaders interface{} // 添加的Header
AddTrailers interface{} // 添加的Trailers
SetHeaders interface{} // 设置Header
ReplaceHeaders interface{} // 替换Header内容
Expires interface{} // Expires单独设置
DeleteHeaders interface{} // 删除的Headers
Id any // ID
IsOn any // 是否启用
State any // 状态
AdminId any // 管理员ID
UserId any // 用户ID
CreatedAt any // 创建时间
AddHeaders any // 添加的Header
AddTrailers any // 添加的Trailers
SetHeaders any // 设置Header
ReplaceHeaders any // 替换Header内容
Expires any // Expires单独设置
DeleteHeaders any // 删除的Headers
Cors any // CORS配置
}
func NewHTTPHeaderPolicyOperator() *HTTPHeaderPolicyOperator {

View File

@@ -468,6 +468,16 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
config.Referers = referersConfig
}
// User-Agent
if IsNotNull(web.UserAgent) {
var userAgentConfig = serverconfigs.NewUserAgentConfig()
err = json.Unmarshal(web.UserAgent, userAgentConfig)
if err != nil {
return nil, err
}
config.UserAgent = userAgentConfig
}
if cacheMap != nil {
cacheMap.Put(cacheKey, config)
}
@@ -1252,6 +1262,35 @@ func (this *HTTPWebDAO) FindWebReferers(tx *dbs.Tx, webId int64) ([]byte, error)
FindJSONCol()
}
// UpdateWebUserAgent 修改User-Agent设置
func (this *HTTPWebDAO) UpdateWebUserAgent(tx *dbs.Tx, webId int64, userAgentConfig *serverconfigs.UserAgentConfig) error {
if userAgentConfig == nil {
return nil
}
configJSON, err := json.Marshal(userAgentConfig)
if err != nil {
return err
}
err = this.Query(tx).
Pk(webId).
Set("userAgent", configJSON).
UpdateQuickly()
if err != nil {
return err
}
return this.NotifyUpdate(tx, webId)
}
// FindWebUserAgent 查找服务User-Agent配置
func (this *HTTPWebDAO) FindWebUserAgent(tx *dbs.Tx, webId int64) ([]byte, error) {
return this.Query(tx).
Pk(webId).
Result("userAgent").
FindJSONCol()
}
// NotifyUpdate 通知更新
func (this *HTTPWebDAO) NotifyUpdate(tx *dbs.Tx, webId int64) error {
// server

View File

@@ -39,6 +39,7 @@ type HTTPWeb struct {
RequestScripts dbs.JSON `field:"requestScripts"` // 请求脚本
Uam dbs.JSON `field:"uam"` // UAM设置
Referers dbs.JSON `field:"referers"` // 防盗链设置
UserAgent dbs.JSON `field:"userAgent"` // UserAgent设置
}
type HTTPWebOperator struct {
@@ -77,6 +78,7 @@ type HTTPWebOperator struct {
RequestScripts any // 请求脚本
Uam any // UAM设置
Referers any // 防盗链设置
UserAgent any // UserAgent设置
}
func NewHTTPWebOperator() *HTTPWebOperator {

View File

@@ -1,6 +1,7 @@
package models
package models_test
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
"github.com/iwind/TeaGo/dbs"
@@ -11,7 +12,7 @@ func TestMessageTaskDAO_FindSendingMessageTasks(t *testing.T) {
dbs.NotifyReady()
var tx *dbs.Tx
tasks, err := NewMessageTaskDAO().FindSendingMessageTasks(tx, 100)
tasks, err := models.NewMessageTaskDAO().FindSendingMessageTasks(tx, 100)
if err != nil {
t.Fatal(err)
}
@@ -20,3 +21,12 @@ func TestMessageTaskDAO_FindSendingMessageTasks(t *testing.T) {
t.Log("task:", task.Id, "recipient:", task.RecipientId)
}
}
func TestMessageTaskDAO_CleanExpiredMessageTasks(t *testing.T) {
var dao = models.NewMessageTaskDAO()
var tx *dbs.Tx
err := dao.CleanExpiredMessageTasks(tx, 30)
if err != nil {
t.Fatal(err)
}
}

View File

@@ -12,6 +12,11 @@ type NSRecord struct {
Type string `field:"type"` // 类型
Value string `field:"value"` // 值
MxPriority uint32 `field:"mxPriority"` // MX优先级
SrvPriority uint32 `field:"srvPriority"` // SRV优先级
SrvWeight uint32 `field:"srvWeight"` // SRV权重
SrvPort uint32 `field:"srvPort"` // SRV端口
CaaFlag uint8 `field:"caaFlag"` // CAA Flag
CaaTag string `field:"caaTag"` // CAA TAG
Ttl uint32 `field:"ttl"` // TTL
Weight uint32 `field:"weight"` // 权重
RouteIds dbs.JSON `field:"routeIds"` // 线路
@@ -29,6 +34,11 @@ type NSRecordOperator struct {
Type any // 类型
Value any // 值
MxPriority any // MX优先级
SrvPriority any // SRV优先级
SrvWeight any // SRV权重
SrvPort any // SRV端口
CaaFlag any // CAA Flag
CaaTag any // CAA TAG
Ttl any // TTL
Weight any // 权重
RouteIds any // 线路

View File

@@ -16,6 +16,7 @@ type NSRoute struct {
Ranges dbs.JSON `field:"ranges"` // 范围
Order uint32 `field:"order"` // 排序
Version uint64 `field:"version"` // 版本号
Priority uint32 `field:"priority"` // 优先级,越高越优先
Code string `field:"code"` // 代号
State uint8 `field:"state"` // 状态
}
@@ -33,6 +34,7 @@ type NSRouteOperator struct {
Ranges any // 范围
Order any // 排序
Version any // 版本号
Priority any // 优先级,越高越优先
Code any // 代号
State any // 状态
}

View File

@@ -978,7 +978,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
}
for _, server := range servers {
serverConfig, err := SharedServerDAO.ComposeServerConfig(tx, server, cacheMap, true, false)
serverConfig, err := SharedServerDAO.ComposeServerConfig(tx, server, false, cacheMap, true, false)
if err != nil {
return nil, err
}

View File

@@ -23,6 +23,7 @@ type NSCluster struct {
Answer dbs.JSON `field:"answer"` // 应答设置
SoaSerial uint64 `field:"soaSerial"` // SOA序列号
Email string `field:"email"` // 管理员邮箱
DetectAgents bool `field:"detectAgents"` // 是否监测Agents
}
type NSClusterOperator struct {
@@ -45,6 +46,7 @@ type NSClusterOperator struct {
Answer any // 应答设置
SoaSerial any // SOA序列号
Email any // 管理员邮箱
DetectAgents any // 是否监测Agents
}
func NewNSClusterOperator() *NSClusterOperator {

View File

@@ -403,7 +403,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
}
config.CertRef = ref
if ref.CertId > 0 {
certConfig, err := SharedSSLCertDAO.ComposeCertConfig(tx, ref.CertId, cacheMap)
certConfig, err := SharedSSLCertDAO.ComposeCertConfig(tx, ref.CertId, false, cacheMap)
if err != nil {
return nil, err
}

View File

@@ -195,15 +195,20 @@ func (this *ServerDailyStatDAO) SumUserMonthlyPeek(tx *dbs.Tx, userId int64, reg
// SumUserDaily 获取某天流量总和
// day 格式为YYYYMMDD
func (this *ServerDailyStatDAO) SumUserDaily(tx *dbs.Tx, userId int64, regionId int64, day string) (int64, error) {
func (this *ServerDailyStatDAO) SumUserDaily(tx *dbs.Tx, userId int64, regionId int64, day string) (stat *ServerDailyStat, err error) {
var query = this.Query(tx)
if regionId > 0 {
query.Attr("regionId", regionId)
}
return query.
Attr("day", day).
one, err := query.Attr("day", day).
Attr("userId", userId).
SumInt64("bytes", 0)
Result("SUM(bytes) AS bytes", "SUM(cachedBytes) AS cachedBytes", "SUM(attackBytes) AS attackBytes", "SUM(countRequests) AS countRequests", "SUM(countCachedRequests) AS countCachedRequests", "SUM(countAttackRequests) AS countAttackRequests").
Find()
if err != nil || one == nil {
return nil, err
}
return one.(*ServerDailyStat), nil
}
// SumUserTrafficBytesBetweenDays 获取用户某个日期段内的流量总和

View File

@@ -1001,7 +1001,7 @@ func (this *ServerDAO) FindServerNodeFilters(tx *dbs.Tx, serverId int64) (isOk b
}
// ComposeServerConfigWithServerId 构造服务的Config
func (this *ServerDAO) ComposeServerConfigWithServerId(tx *dbs.Tx, serverId int64, forNode bool) (*serverconfigs.ServerConfig, error) {
func (this *ServerDAO) ComposeServerConfigWithServerId(tx *dbs.Tx, serverId int64, ignoreCertData bool, forNode bool) (*serverconfigs.ServerConfig, error) {
server, err := this.FindEnabledServer(tx, serverId)
if err != nil {
return nil, err
@@ -1009,12 +1009,12 @@ func (this *ServerDAO) ComposeServerConfigWithServerId(tx *dbs.Tx, serverId int6
if server == nil {
return nil, ErrNotFound
}
return this.ComposeServerConfig(tx, server, nil, forNode, false)
return this.ComposeServerConfig(tx, server, ignoreCertData, nil, forNode, false)
}
// ComposeServerConfig 构造服务的Config
// forNode 是否是节点请求
func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap *utils.CacheMap, forNode bool, forList bool) (*serverconfigs.ServerConfig, error) {
func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, ignoreCerts bool, cacheMap *utils.CacheMap, forNode bool, forList bool) (*serverconfigs.ServerConfig, error) {
if server == nil {
return nil, ErrNotFound
}
@@ -1110,8 +1110,8 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
}
// SSL
if httpsConfig.SSLPolicyRef != nil && httpsConfig.SSLPolicyRef.SSLPolicyId > 0 {
sslPolicyConfig, err := SharedSSLPolicyDAO.ComposePolicyConfig(tx, httpsConfig.SSLPolicyRef.SSLPolicyId, cacheMap)
if httpsConfig.SSLPolicyRef != nil && httpsConfig.SSLPolicyRef.SSLPolicyId > 0 && !ignoreCerts {
sslPolicyConfig, err := SharedSSLPolicyDAO.ComposePolicyConfig(tx, httpsConfig.SSLPolicyRef.SSLPolicyId, false, cacheMap)
if err != nil {
return nil, err
}
@@ -1142,8 +1142,8 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
}
// SSL
if tlsConfig.SSLPolicyRef != nil {
sslPolicyConfig, err := SharedSSLPolicyDAO.ComposePolicyConfig(tx, tlsConfig.SSLPolicyRef.SSLPolicyId, cacheMap)
if tlsConfig.SSLPolicyRef != nil && !ignoreCerts {
sslPolicyConfig, err := SharedSSLPolicyDAO.ComposePolicyConfig(tx, tlsConfig.SSLPolicyRef.SSLPolicyId, false, cacheMap)
if err != nil {
return nil, err
}
@@ -2494,6 +2494,14 @@ func (this *ServerDAO) UpdateServersClusterIdWithPlanId(tx *dbs.Tx, planId int64
// UpdateServerUserPlanId 设置服务所属套餐
func (this *ServerDAO) UpdateServerUserPlanId(tx *dbs.Tx, serverId int64, userPlanId int64) error {
oldClusterId, err := this.Query(tx).
Pk(serverId).
Result("clusterId").
FindInt64Col(0)
if err != nil {
return err
}
// 取消套餐
if userPlanId <= 0 {
// 所属用户
@@ -2524,7 +2532,24 @@ func (this *ServerDAO) UpdateServerUserPlanId(tx *dbs.Tx, serverId int64, userPl
if err != nil {
return err
}
return this.NotifyUpdate(tx, serverId)
err = this.NotifyUpdate(tx, serverId)
if err != nil {
return err
}
// 通知DNS更新
if oldClusterId != clusterId {
if oldClusterId > 0 {
err = this.NotifyClusterDNSUpdate(tx, oldClusterId, serverId)
if err != nil {
return err
}
}
return this.NotifyClusterDNSUpdate(tx, clusterId, serverId)
}
return nil
}
// 设置新套餐
@@ -2544,16 +2569,34 @@ func (this *ServerDAO) UpdateServerUserPlanId(tx *dbs.Tx, serverId int64, userPl
return errors.New("can not find plan with id '" + types.String(userPlan.PlanId) + "'")
}
var clusterId = int64(plan.ClusterId)
err = this.Query(tx).
Pk(serverId).
Set("userPlanId", userPlanId).
Set("lastUserPlanId", userPlanId).
Set("clusterId", plan.ClusterId).
Set("clusterId", clusterId).
UpdateQuickly()
if err != nil {
return err
}
return this.NotifyUpdate(tx, serverId)
err = this.NotifyUpdate(tx, serverId)
if err != nil {
return err
}
// 通知DNS更新
if oldClusterId != clusterId {
if oldClusterId > 0 {
err = this.NotifyClusterDNSUpdate(tx, oldClusterId, serverId)
if err != nil {
return err
}
}
return this.NotifyClusterDNSUpdate(tx, clusterId, serverId)
}
return nil
}
// FindServerLastUserPlanIdAndUserId 查找最后使用的套餐
@@ -2654,6 +2697,72 @@ func (this *ServerDAO) UpdateServerBandwidth(tx *dbs.Tx, serverId int64, fullTim
}
}
// UpdateServerUserId 修改服务所属用户
func (this *ServerDAO) UpdateServerUserId(tx *dbs.Tx, serverId int64, userId int64) error {
if serverId <= 0 {
return nil
}
serverOne, err := this.Query(tx).
Result("https", "tls").
Pk(serverId).
State(ServerStateEnabled).
Find()
if err != nil || serverOne == nil {
return err
}
var server = serverOne.(*Server)
// 修改服务
err = this.Query(tx).
Pk(serverId).
Set("userId", userId).
UpdateQuickly()
if err != nil {
return err
}
// 修改证书相关数据
var sslPolicyIds = []int64{}
var httpsConfig = server.DecodeHTTPS()
if httpsConfig != nil && httpsConfig.SSLPolicyRef != nil && httpsConfig.SSLPolicyRef.SSLPolicyId > 0 {
sslPolicyIds = append(sslPolicyIds, httpsConfig.SSLPolicyRef.SSLPolicyId)
}
var tlsConfig = server.DecodeTLS()
if tlsConfig != nil && tlsConfig.SSLPolicyRef != nil && tlsConfig.SSLPolicyRef.SSLPolicyId > 0 {
sslPolicyIds = append(sslPolicyIds, tlsConfig.SSLPolicyRef.SSLPolicyId)
}
if len(sslPolicyIds) > 0 {
for _, sslPolicyId := range sslPolicyIds {
policy, err := SharedSSLPolicyDAO.FindEnabledSSLPolicy(tx, sslPolicyId)
if err != nil {
return err
}
if policy != nil {
// 修改策略
err = SharedSSLPolicyDAO.UpdatePolicyUser(tx, sslPolicyId, userId)
if err != nil {
return err
}
var certRefs = policy.DecodeCerts()
for _, certRef := range certRefs {
if certRef.CertId > 0 {
// 修改证书
err = SharedSSLCertDAO.UpdateCertUser(tx, certRef.CertId, userId)
if err != nil {
return err
}
}
}
}
}
}
return this.NotifyUpdate(tx, serverId)
}
// NotifyUpdate 同步服务所在的集群
func (this *ServerDAO) NotifyUpdate(tx *dbs.Tx, serverId int64) error {
// 创建任务

View File

@@ -42,10 +42,38 @@ func (this *Server) DecodeHTTPPorts() (ports []int) {
return
}
// DecodeHTTPS 解析HTTPS设置
func (this *Server) DecodeHTTPS() *serverconfigs.HTTPSProtocolConfig {
if len(this.Https) == 0 {
return nil
}
var config = &serverconfigs.HTTPSProtocolConfig{}
err := json.Unmarshal(this.Https, config)
if err != nil {
remotelogs.Error("Server_DecodeHTTPS", err.Error())
}
return config
}
// DecodeTLS 解析TLS设置
func (this *Server) DecodeTLS() *serverconfigs.TLSProtocolConfig {
if len(this.Tls) == 0 {
return nil
}
var config = &serverconfigs.TLSProtocolConfig{}
err := json.Unmarshal(this.Tls, config)
if err != nil {
remotelogs.Error("Server_DecodeTLS", err.Error())
}
return config
}
// DecodeHTTPSPorts 获取HTTPS所有端口
func (this *Server) DecodeHTTPSPorts() (ports []int) {
if len(this.Https) > 0 {
config := &serverconfigs.HTTPSProtocolConfig{}
var config = &serverconfigs.HTTPSProtocolConfig{}
err := json.Unmarshal(this.Https, config)
if err != nil {
return nil

View File

@@ -200,7 +200,8 @@ func (this *SSLCertDAO) UpdateCert(tx *dbs.Tx,
}
// ComposeCertConfig 组合配置
func (this *SSLCertDAO) ComposeCertConfig(tx *dbs.Tx, certId int64, cacheMap *utils.CacheMap) (*sslconfigs.SSLCertConfig, error) {
// ignoreData 是否忽略证书数据,避免因为数据过大影响传输
func (this *SSLCertDAO) ComposeCertConfig(tx *dbs.Tx, certId int64, ignoreData bool, cacheMap *utils.CacheMap) (*sslconfigs.SSLCertConfig, error) {
if cacheMap == nil {
cacheMap = utils.NewCacheMap()
}
@@ -218,15 +219,17 @@ func (this *SSLCertDAO) ComposeCertConfig(tx *dbs.Tx, certId int64, cacheMap *ut
return nil, nil
}
config := &sslconfigs.SSLCertConfig{}
var config = &sslconfigs.SSLCertConfig{}
config.Id = int64(cert.Id)
config.IsOn = cert.IsOn
config.IsCA = cert.IsCA
config.IsACME = cert.IsACME
config.Name = cert.Name
config.Description = cert.Description
config.CertData = cert.CertData
config.KeyData = cert.KeyData
if !ignoreData {
config.CertData = cert.CertData
config.KeyData = cert.KeyData
}
config.ServerName = cert.ServerName
config.TimeBeginAt = int64(cert.TimeBeginAt)
config.TimeEndAt = int64(cert.TimeEndAt)
@@ -239,7 +242,7 @@ func (this *SSLCertDAO) ComposeCertConfig(tx *dbs.Tx, certId int64, cacheMap *ut
config.OCSPError = cert.OcspError
if IsNotNull(cert.DnsNames) {
dnsNames := []string{}
var dnsNames = []string{}
err := json.Unmarshal(cert.DnsNames, &dnsNames)
if err != nil {
return nil, err
@@ -248,7 +251,7 @@ func (this *SSLCertDAO) ComposeCertConfig(tx *dbs.Tx, certId int64, cacheMap *ut
}
if cert.CommonNames.IsNotNull() {
commonNames := []string{}
var commonNames = []string{}
err := json.Unmarshal(cert.CommonNames, &commonNames)
if err != nil {
return nil, err
@@ -399,6 +402,17 @@ func (this *SSLCertDAO) CheckUserCert(tx *dbs.Tx, certId int64, userId int64) er
return nil
}
// UpdateCertUser 修改证书所属用户
func (this *SSLCertDAO) UpdateCertUser(tx *dbs.Tx, certId int64, userId int64) error {
if certId <= 0 || userId <= 0 {
return nil
}
return this.Query(tx).
Pk(certId).
Set("userId", userId).
UpdateQuickly()
}
// ListCertsToUpdateOCSP 查找需要更新OCSP的证书
func (this *SSLCertDAO) ListCertsToUpdateOCSP(tx *dbs.Tx, maxTries int, size int64) (result []*SSLCert, err error) {
var nowTime = time.Now().Unix()

View File

@@ -77,7 +77,7 @@ func (this *SSLPolicyDAO) FindEnabledSSLPolicy(tx *dbs.Tx, id int64) (*SSLPolicy
}
// ComposePolicyConfig 组合配置
func (this *SSLPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, cacheMap *utils.CacheMap) (*sslconfigs.SSLPolicy, error) {
func (this *SSLPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, ignoreData bool, cacheMap *utils.CacheMap) (*sslconfigs.SSLPolicy, error) {
if cacheMap == nil {
cacheMap = utils.NewCacheMap()
}
@@ -95,7 +95,7 @@ func (this *SSLPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, cacheM
if policy == nil {
return nil, nil
}
config := &sslconfigs.SSLPolicy{}
var config = &sslconfigs.SSLPolicy{}
config.Id = int64(policy.Id)
config.IsOn = policy.IsOn
config.ClientAuthType = int(policy.ClientAuthType)
@@ -104,14 +104,14 @@ func (this *SSLPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, cacheM
// certs
if IsNotNull(policy.Certs) {
refs := []*sslconfigs.SSLCertRef{}
var refs = []*sslconfigs.SSLCertRef{}
err = json.Unmarshal(policy.Certs, &refs)
if err != nil {
return nil, err
}
if len(refs) > 0 {
for _, ref := range refs {
certConfig, err := SharedSSLCertDAO.ComposeCertConfig(tx, ref.CertId, cacheMap)
certConfig, err := SharedSSLCertDAO.ComposeCertConfig(tx, ref.CertId, ignoreData, cacheMap)
if err != nil {
return nil, err
}
@@ -126,14 +126,14 @@ func (this *SSLPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, cacheM
// client CA certs
if IsNotNull(policy.ClientCACerts) {
refs := []*sslconfigs.SSLCertRef{}
var refs = []*sslconfigs.SSLCertRef{}
err = json.Unmarshal(policy.ClientCACerts, &refs)
if err != nil {
return nil, err
}
if len(refs) > 0 {
for _, ref := range refs {
certConfig, err := SharedSSLCertDAO.ComposeCertConfig(tx, ref.CertId, cacheMap)
certConfig, err := SharedSSLCertDAO.ComposeCertConfig(tx, ref.CertId, ignoreData, cacheMap)
if err != nil {
return nil, err
}
@@ -159,7 +159,7 @@ func (this *SSLPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, cacheM
// hsts
if IsNotNull(policy.Hsts) {
hstsConfig := &sslconfigs.HSTSConfig{}
var hstsConfig = &sslconfigs.HSTSConfig{}
err = json.Unmarshal(policy.Hsts, hstsConfig)
if err != nil {
return nil, err
@@ -306,6 +306,18 @@ func (this *SSLPolicyDAO) CheckUserPolicy(tx *dbs.Tx, userId int64, policyId int
return nil
}
// UpdatePolicyUser 修改策略所属用户
func (this *SSLPolicyDAO) UpdatePolicyUser(tx *dbs.Tx, policyId int64, userId int64) error {
if policyId <= 0 || userId <= 0 {
return nil
}
return this.Query(tx).
Pk(policyId).
Set("userId", userId).
UpdateQuickly()
}
// NotifyUpdate 通知更新
func (this *SSLPolicyDAO) NotifyUpdate(tx *dbs.Tx, policyId int64) error {
serverIds, err := SharedServerDAO.FindAllEnabledServerIdsWithSSLPolicyIds(tx, []int64{policyId})

View File

@@ -1 +1,20 @@
package models
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
)
func (this *SSLPolicy) DecodeCerts() []*sslconfigs.SSLCertRef {
if len(this.Certs) == 0 {
return nil
}
var refs = []*sslconfigs.SSLCertRef{}
err := json.Unmarshal(this.Certs, &refs)
if err != nil {
remotelogs.Error("SSLPolicy_DecodeCerts", err.Error())
}
return refs
}

View File

@@ -14,6 +14,7 @@ import (
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/types"
"strconv"
"time"
)
@@ -172,6 +173,21 @@ func (this *SysSettingDAO) ReadAdminUIConfig(tx *dbs.Tx, cacheMap *utils.CacheMa
return &systemconfigs.AdminUIConfig{}, nil
}
// ReadProductName 读取设置的产品名称
func (this *SysSettingDAO) ReadProductName(tx *dbs.Tx) (string, error) {
productName, err := this.Query(tx).
Attr("code", systemconfigs.SettingCodeAdminUIConfig).
Result("JSON_EXTRACT(value, '$.productName')").
FindStringCol("")
if err != nil {
return "", err
}
if len(productName) > 0 {
return strconv.Unquote(productName)
}
return "", nil
}
// ReadUserUIConfig 读取用户UI配置
func (this *SysSettingDAO) ReadUserUIConfig(tx *dbs.Tx) (*systemconfigs.UserUIConfig, error) {
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeUserUIConfig)
@@ -228,3 +244,21 @@ func (this *SysSettingDAO) ReadUserServerConfig(tx *dbs.Tx) (*userconfigs.UserSe
}
return config, nil
}
// ReadUserRegisterConfig 读取用户注册配置
func (this *SysSettingDAO) ReadUserRegisterConfig(tx *dbs.Tx) (*userconfigs.UserRegisterConfig, error) {
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeUserRegisterConfig)
if err != nil {
return nil, err
}
if len(valueJSON) == 0 {
return userconfigs.DefaultUserRegisterConfig(), nil
}
var config = userconfigs.DefaultUserRegisterConfig()
err = json.Unmarshal(valueJSON, config)
if err != nil {
return nil, err
}
return config, nil
}

View File

@@ -42,3 +42,8 @@ func TestSysSettingDAO_CompareInt64Setting(t *testing.T) {
}
t.Log("result:", i)
}
func TestSysSettingDAO_ReadProductName(t *testing.T) {
var tx *dbs.Tx
t.Log(NewSysSettingDAO().ReadProductName(tx))
}

View File

@@ -74,6 +74,11 @@ func (this *UserDAO) DisableUser(tx *dbs.Tx, userId int64) error {
return err
}
err = SharedAPIAccessTokenDAO.DeleteAccessTokens(tx, 0, userId)
if err != nil {
return err
}
return this.NotifyUpdate(tx, userId)
}
@@ -137,7 +142,24 @@ func (this *UserDAO) FindEnabledUserIdWithUsername(tx *dbs.Tx, username string)
FindInt64Col(0)
}
// FindUserFullname 获取管理员名称
// FindUserId 根据多个条件查找用户ID
func (this *UserDAO) FindUserId(tx *dbs.Tx, verifiedEmail string, verifiedMobile string) (int64, error) {
var query = this.Query(tx).
State(UserStateEnabled).
ResultPk()
if len(verifiedEmail) > 0 {
query.Attr("verifiedEmail", verifiedEmail)
} else if len(verifiedMobile) > 0 {
query.Attr("verifiedMobile", verifiedMobile)
} else {
return 0, nil
}
return query.FindInt64Col(0)
}
// FindUserFullname 获取用户名称
func (this *UserDAO) FindUserFullname(tx *dbs.Tx, userId int64) (string, error) {
return this.Query(tx).
Pk(userId).
@@ -145,6 +167,14 @@ func (this *UserDAO) FindUserFullname(tx *dbs.Tx, userId int64) (string, error)
FindStringCol("")
}
// FindUserVerifiedEmail 查询用户已绑定邮箱
func (this *UserDAO) FindUserVerifiedEmail(tx *dbs.Tx, userId int64) (string, error) {
return this.Query(tx).
Pk(userId).
Result("verifiedEmail").
FindStringCol("")
}
// CreateUser 创建用户
func (this *UserDAO) CreateUser(tx *dbs.Tx, username string,
password string,
@@ -217,6 +247,14 @@ func (this *UserDAO) UpdateUser(tx *dbs.Tx, userId int64, username string, passw
return err
}
// 删除AccessTokens
if !isOn {
err = SharedAPIAccessTokenDAO.DeleteAccessTokens(tx, 0, userId)
if err != nil {
return err
}
}
return this.NotifyUpdate(tx, userId)
}
@@ -244,8 +282,20 @@ func (this *UserDAO) UpdateUserLogin(tx *dbs.Tx, userId int64, username string,
if len(password) > 0 {
op.Password = stringutil.Md5(password)
}
err := this.Save(tx, op)
return err
return this.Save(tx, op)
}
// UpdateUserPassword 修改用户密码
func (this *UserDAO) UpdateUserPassword(tx *dbs.Tx, userId int64, password string) error {
if userId <= 0 {
return errors.New("invalid userId")
}
var op = NewUserOperator()
op.Id = userId
if len(password) > 0 {
op.Password = stringutil.Md5(password)
}
return this.Save(tx, op)
}
// CountAllEnabledUsers 计算用户数量
@@ -327,7 +377,7 @@ func (this *UserDAO) ListEnabledUserIds(tx *dbs.Tx, offset, size int64) ([]int64
return result, nil
}
// CheckUserPassword 检查用户名密码
// CheckUserPassword 检查用户名+密码
func (this *UserDAO) CheckUserPassword(tx *dbs.Tx, username string, encryptedPassword string) (int64, error) {
if len(username) == 0 || len(encryptedPassword) == 0 {
return 0, nil
@@ -341,6 +391,20 @@ func (this *UserDAO) CheckUserPassword(tx *dbs.Tx, username string, encryptedPas
FindInt64Col(0)
}
// CheckUserEmailPassword 检查邮箱+密码
func (this *UserDAO) CheckUserEmailPassword(tx *dbs.Tx, verifiedEmail string, encryptedPassword string) (int64, error) {
if len(verifiedEmail) == 0 || len(encryptedPassword) == 0 {
return 0, nil
}
return this.Query(tx).
Attr("verifiedEmail", verifiedEmail).
Attr("password", encryptedPassword).
Attr("state", UserStateEnabled).
Attr("isOn", true).
ResultPk().
FindInt64Col(0)
}
// FindUserClusterId 查找用户所在集群
func (this *UserDAO) FindUserClusterId(tx *dbs.Tx, userId int64) (int64, error) {
return this.Query(tx).
@@ -573,6 +637,30 @@ func (this *UserDAO) RenewUserServersState(tx *dbs.Tx, userId int64) (bool, erro
return newServersEnabled, nil
}
// FindUserIdWithVerifiedEmail 使用验证后Email查找用户ID
func (this *UserDAO) FindUserIdWithVerifiedEmail(tx *dbs.Tx, verifiedEmail string) (int64, error) {
if len(verifiedEmail) == 0 {
}
return this.Query(tx).
ResultPk().
State(UserStateEnabled).
Attr("verifiedEmail", verifiedEmail).
FindInt64Col(0)
}
// UpdateUserVerifiedEmail 修改已激活邮箱
func (this *UserDAO) UpdateUserVerifiedEmail(tx *dbs.Tx, userId int64, verifiedEmail string) error {
if userId <= 0 {
return nil
}
return this.Query(tx).
Pk(userId).
Set("verifiedEmail", verifiedEmail).
Set("emailIsVerified", true).
UpdateQuickly()
}
// NotifyUpdate 用户变更通知
func (this *UserDAO) NotifyUpdate(tx *dbs.Tx, userId int64) error {
if userId <= 0 {

View File

@@ -0,0 +1,28 @@
package models
import (
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
)
type UserEmailNotificationDAO dbs.DAO
func NewUserEmailNotificationDAO() *UserEmailNotificationDAO {
return dbs.NewDAO(&UserEmailNotificationDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeUserEmailNotifications",
Model: new(UserEmailNotification),
PkName: "id",
},
}).(*UserEmailNotificationDAO)
}
var SharedUserEmailNotificationDAO *UserEmailNotificationDAO
func init() {
dbs.OnReady(func() {
SharedUserEmailNotificationDAO = NewUserEmailNotificationDAO()
})
}

View File

@@ -0,0 +1,6 @@
package models_test
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View File

@@ -0,0 +1,24 @@
package models
// UserEmailNotification 邮件通知队列
type UserEmailNotification struct {
Id uint64 `field:"id"` // ID
Email string `field:"email"` // 邮箱地址
Subject string `field:"subject"` // 标题
Body string `field:"body"` // 内容
CreatedAt uint64 `field:"createdAt"` // 创建时间
Day string `field:"day"` // YYYYMMDD
}
type UserEmailNotificationOperator struct {
Id any // ID
Email any // 邮箱地址
Subject any // 标题
Body any // 内容
CreatedAt any // 创建时间
Day any // YYYYMMDD
}
func NewUserEmailNotificationOperator() *UserEmailNotificationOperator {
return &UserEmailNotificationOperator{}
}

View File

@@ -0,0 +1,28 @@
package models
import (
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
)
type UserEmailVerificationDAO dbs.DAO
func NewUserEmailVerificationDAO() *UserEmailVerificationDAO {
return dbs.NewDAO(&UserEmailVerificationDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeUserEmailVerifications",
Model: new(UserEmailVerification),
PkName: "id",
},
}).(*UserEmailVerificationDAO)
}
var SharedUserEmailVerificationDAO *UserEmailVerificationDAO
func init() {
dbs.OnReady(func() {
SharedUserEmailVerificationDAO = NewUserEmailVerificationDAO()
})
}

View File

@@ -0,0 +1,6 @@
package models_test
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View File

@@ -0,0 +1,28 @@
package models
// UserEmailVerification 邮箱激活邮件队列
type UserEmailVerification struct {
Id uint64 `field:"id"` // ID
Email string `field:"email"` // 邮箱
UserId uint64 `field:"userId"` // 用户ID
Code string `field:"code"` // 激活码
CreatedAt uint64 `field:"createdAt"` // 创建时间
IsSent bool `field:"isSent"` // 是否已发送
IsVerified bool `field:"isVerified"` // 是否已激活
Day string `field:"day"` // YYYYMMDD
}
type UserEmailVerificationOperator struct {
Id any // ID
Email any // 邮箱
UserId any // 用户ID
Code any // 激活码
CreatedAt any // 创建时间
IsSent any // 是否已发送
IsVerified any // 是否已激活
Day any // YYYYMMDD
}
func NewUserEmailVerificationOperator() *UserEmailVerificationOperator {
return &UserEmailVerificationOperator{}
}

View File

@@ -10,9 +10,11 @@ type User struct {
Password string `field:"password"` // 密码
Fullname string `field:"fullname"` // 真实姓名
Mobile string `field:"mobile"` // 手机号
VerifiedMobile string `field:"verifiedMobile"` // 已验证手机号
Tel string `field:"tel"` // 联系电话
Remark string `field:"remark"` // 备注
Email string `field:"email"` // 邮箱地址
VerifiedEmail string `field:"verifiedEmail"` // 激活后的邮箱
EmailIsVerified uint8 `field:"emailIsVerified"` // 邮箱是否已验证
AvatarFileId uint64 `field:"avatarFileId"` // 头像文件ID
CreatedAt uint64 `field:"createdAt"` // 创建时间
@@ -31,6 +33,7 @@ type User struct {
PriceType string `field:"priceType"` // 计费类型traffic|bandwidth
PricePeriod string `field:"pricePeriod"` // 结算周期
ServersEnabled uint8 `field:"serversEnabled"` // 是否禁用所有服务
Notification dbs.JSON `field:"notification"` // 通知设置
}
type UserOperator struct {
@@ -40,9 +43,11 @@ type UserOperator struct {
Password any // 密码
Fullname any // 真实姓名
Mobile any // 手机号
VerifiedMobile any // 已验证手机号
Tel any // 联系电话
Remark any // 备注
Email any // 邮箱地址
VerifiedEmail any // 激活后的邮箱
EmailIsVerified any // 邮箱是否已验证
AvatarFileId any // 头像文件ID
CreatedAt any // 创建时间
@@ -61,6 +66,7 @@ type UserOperator struct {
PriceType any // 计费类型traffic|bandwidth
PricePeriod any // 结算周期
ServersEnabled any // 是否禁用所有服务
Notification any // 通知设置
}
func NewUserOperator() *UserOperator {

View File

@@ -44,7 +44,7 @@ func (this *UserNode) DecodeHTTPS(cacheMap *utils.CacheMap) (*serverconfigs.HTTP
if config.SSLPolicyRef != nil {
policyId := config.SSLPolicyRef.SSLPolicyId
if policyId > 0 {
sslPolicy, err := SharedSSLPolicyDAO.ComposePolicyConfig(nil, policyId, cacheMap)
sslPolicy, err := SharedSSLPolicyDAO.ComposePolicyConfig(nil, policyId, false, cacheMap)
if err != nil {
return nil, err
}

View File

@@ -0,0 +1,28 @@
package models
import (
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
)
type UserVerifyCodeDAO dbs.DAO
func NewUserVerifyCodeDAO() *UserVerifyCodeDAO {
return dbs.NewDAO(&UserVerifyCodeDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeUserVerifyCodes",
Model: new(UserVerifyCode),
PkName: "id",
},
}).(*UserVerifyCodeDAO)
}
var SharedUserVerifyCodeDAO *UserVerifyCodeDAO
func init() {
dbs.OnReady(func() {
SharedUserVerifyCodeDAO = NewUserVerifyCodeDAO()
})
}

View File

@@ -0,0 +1,6 @@
package models_test
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View File

@@ -0,0 +1,32 @@
package models
// UserVerifyCode 重置密码之验证码
type UserVerifyCode struct {
Id uint64 `field:"id"` // ID
Email string `field:"email"` // 邮箱地址
Mobile string `field:"mobile"` // 手机号
Code string `field:"code"` // 验证码
Type string `field:"type"` // 类型
IsSent bool `field:"isSent"` // 是否已发送
IsVerified bool `field:"isVerified"` // 是否已激活
CreatedAt uint64 `field:"createdAt"` // 创建时间
ExpiresAt uint64 `field:"expiresAt"` // 过期时间
Day string `field:"day"` // YYYYMMDD
}
type UserVerifyCodeOperator struct {
Id any // ID
Email any // 邮箱地址
Mobile any // 手机号
Code any // 验证码
Type any // 类型
IsSent any // 是否已发送
IsVerified any // 是否已激活
CreatedAt any // 创建时间
ExpiresAt any // 过期时间
Day any // YYYYMMDD
}
func NewUserVerifyCodeOperator() *UserVerifyCodeOperator {
return &UserVerifyCodeOperator{}
}

View File

@@ -0,0 +1 @@
package models

View File

@@ -72,3 +72,11 @@ func CheckSQLErrCode(err error, code uint16) bool {
return false
}
// CheckSQLDuplicateErr 检查Duplicate错误
func CheckSQLDuplicateErr(err error) bool {
if err == nil {
return false
}
return CheckSQLErrCode(err, 1062)
}

View File

@@ -206,6 +206,23 @@ func (this *EdgeDNSAPIProvider) GetRoutes(domain string) (routes []*dnstypes.Rou
}
}
// Agent
{
var routesResp = &edgeapi.FindAllNSRoutesResponse{}
err = this.doAPI("/NSRouteService/FindAllAgentNSRoutes", map[string]any{}, routesResp)
if err != nil {
// 忽略错误因为老版本的EdgeDNS没有提供这个接口
err = nil
} else {
for _, route := range routesResp.Data.NSRoutes {
routes = append(routes, &dnstypes.Route{
Name: route.Name,
Code: route.Code,
})
}
}
}
// 自定义
{
var routesResp = &edgeapi.FindAllNSRoutesResponse{}

View File

@@ -17,13 +17,16 @@ import (
"io"
"net/http"
"net/url"
"regexp"
"sort"
"strconv"
"strings"
"time"
)
const HuaweiDNSEndpoint = "https://dns.cn-north-1.myhuaweicloud.com/"
// HuaweiDNSDefaultEndpoint 默认Endpoint
// 所有Endpointshttps://developer.huaweicloud.com/endpoint?DNS
const HuaweiDNSDefaultEndpoint = "https://dns.cn-north-4.myhuaweicloud.com/"
var huaweiDNSHTTPClient = &http.Client{
Timeout: 10 * time.Second,
@@ -43,6 +46,10 @@ type HuaweiDNSProvider struct {
accessKeyId string
accessKeySecret string
endpoint string
endpointRegionReg *regexp.Regexp
endpointDomainReg *regexp.Regexp
}
// Auth 认证
@@ -55,6 +62,12 @@ func (this *HuaweiDNSProvider) Auth(params maps.Map) error {
if len(this.accessKeySecret) == 0 {
return errors.New("'accessKeySecret' should not be empty")
}
this.endpoint = params.GetString("endpoint")
// endpoint相关正则
this.endpointRegionReg = regexp.MustCompile(`^[\w-]+$`)
this.endpointDomainReg = regexp.MustCompile(`^([\w-]+\.)+[\w-]+$`)
return nil
}
@@ -1469,13 +1482,38 @@ func (this *HuaweiDNSProvider) DefaultRoute() string {
}
func (this *HuaweiDNSProvider) doAPI(method string, apiPath string, args map[string]string, bodyMap maps.Map, respPtr interface{}) error {
apiURL := HuaweiDNSEndpoint + strings.TrimLeft(apiPath, "/")
u, err := url.Parse(HuaweiDNSEndpoint)
var endpoint = HuaweiDNSDefaultEndpoint
if len(this.endpoint) > 0 {
// 是否直接为区域
if this.endpointRegionReg.MatchString(this.endpoint) {
switch this.endpoint {
case "All", "all":
endpoint = "https://dns.myhuaweicloud.com/"
default:
endpoint = "https://dns." + this.endpoint + ".myhuaweicloud.com/"
}
} else if this.endpointDomainReg.MatchString(this.endpoint) { // 是否直接为域名
endpoint = "https://" + this.endpoint + "/"
} else {
// 是否为URL
_, err := url.Parse(this.endpoint)
if err != nil {
return errors.New("invalid endpoint '" + this.endpoint + "'")
}
endpoint = this.endpoint
if !strings.HasSuffix(endpoint, "/") {
endpoint += "/"
}
}
}
var apiURL = endpoint + strings.TrimLeft(apiPath, "/")
u, err := url.Parse(endpoint)
if err != nil {
return err
}
apiHost := u.Host
argStrings := []string{}
var apiHost = u.Host
var argStrings = []string{}
if len(args) > 0 {
apiURL += "?"
for k, v := range args {
@@ -1501,28 +1539,28 @@ func (this *HuaweiDNSProvider) doAPI(method string, apiPath string, args map[str
return err
}
contentType := "application/json"
host := apiHost
datetime := time.Now().UTC().Format("20060102T150405Z")
var contentType = "application/json"
var host = apiHost
var datetime = time.Now().UTC().Format("20060102T150405Z")
if !strings.HasSuffix(apiPath, "/") {
apiPath += "/"
}
canonicalRequest := method + "\n" + apiPath + "\n" + strings.Join(argStrings, "&") + "\ncontent-type:" + contentType + "\nhost:" + host + "\nx-sdk-date:" + datetime + "\n" + "\ncontent-type;host;x-sdk-date"
var canonicalRequest = method + "\n" + apiPath + "\n" + strings.Join(argStrings, "&") + "\ncontent-type:" + contentType + "\nhost:" + host + "\nx-sdk-date:" + datetime + "\n" + "\ncontent-type;host;x-sdk-date"
h := sha256.New()
var h = sha256.New()
_, err = h.Write(bodyData)
if err != nil {
return err
}
canonicalRequest += "\n" + fmt.Sprintf("%x", h.Sum(nil))
h2 := sha256.New()
var h2 = sha256.New()
_, err = h2.Write([]byte(canonicalRequest))
if err != nil {
return err
}
source := "SDK-HMAC-SHA256\n" + datetime + "\n" + fmt.Sprintf("%x", h2.Sum(nil))
h3 := hmac.New(sha256.New, []byte(this.accessKeySecret))
var source = "SDK-HMAC-SHA256\n" + datetime + "\n" + fmt.Sprintf("%x", h2.Sum(nil))
var h3 = hmac.New(sha256.New, []byte(this.accessKeySecret))
h3.Write([]byte(source))
signString := fmt.Sprintf("%x", h3.Sum(nil))
req.Header.Set("Host", host)

View File

@@ -139,16 +139,20 @@ func testHuaweiDNSProvider() (ProviderInterface, error) {
if err != nil {
return nil, err
}
one, err := db.FindOne("SELECT * FROM edgeDNSProviders WHERE type='huaweiDNS' ORDER BY id DESC")
one, err := db.FindOne("SELECT * FROM edgeDNSProviders WHERE type='huaweiDNS' AND state=1 ORDER BY id DESC")
if err != nil {
return nil, err
}
apiParams := maps.Map{}
var apiParams = maps.Map{}
//apiParams["endpoint"] = ""
//apiParams["endpoint"] = "cn-north-1"
//apiParams["endpoint"] = "dns.cn-north-4.myhuaweicloud.com"
//apiParams["endpoint"] = "https://dns.cn-south-1.myhuaweicloud.com/"
err = json.Unmarshal([]byte(one.GetString("apiParams")), &apiParams)
if err != nil {
return nil, err
}
provider := &HuaweiDNSProvider{}
var provider = &HuaweiDNSProvider{}
err = provider.Auth(apiParams)
if err != nil {
return nil, err

View File

@@ -125,14 +125,14 @@ func (this *BaseInstaller) LookupLatestInstaller(filePrefix string) (string, err
return "", err
}
lastVersion := ""
result := ""
var lastVersion = ""
var result = ""
for _, match := range matches {
baseName := filepath.Base(match)
var baseName = filepath.Base(match)
if !pattern.MatchString(baseName) {
continue
}
m := pattern.FindStringSubmatch(baseName)
var m = pattern.FindStringSubmatch(baseName)
if len(m) < 2 {
continue
}
@@ -147,27 +147,10 @@ func (this *BaseInstaller) LookupLatestInstaller(filePrefix string) (string, err
// InstallHelper 上传安装助手
func (this *BaseInstaller) InstallHelper(targetDir string, role nodeconfigs.NodeRole) (env *Env, err error) {
var unameRetries = 3
var uname string
for i := 0; i < unameRetries; i++ {
uname, _, err = this.client.Exec("/usr/bin/uname -a")
if len(uname) == 0 {
continue
}
if err == nil {
break
}
}
if err != nil {
return env, errors.New("unable to execute 'uname -a' on this system: " + err.Error())
}
var uname = this.uname()
if len(uname) == 0 {
return nil, errors.New("unable to execute 'uname -a' on this system")
}
osName := ""
archName := ""
var osName = ""
var archName = ""
if strings.Contains(uname, "Darwin") {
osName = "darwin"
} else if strings.Contains(uname, "Linux") {
@@ -229,3 +212,18 @@ func (this *BaseInstaller) InstallHelper(targetDir string, role nodeconfigs.Node
}
return env, nil
}
func (this *BaseInstaller) uname() (uname string) {
var unameRetries = 3
for i := 0; i < unameRetries; i++ {
for _, unameExe := range []string{"uname", "/bin/uname", "/usr/bin/uname"} {
uname, _, _ = this.client.Exec(unameExe + " -a")
if len(uname) > 0 {
return
}
}
}
return "x86_64 GNU/Linux"
}

View File

@@ -4,6 +4,8 @@ package nodes
import (
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services/clients"
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services/users"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"google.golang.org/grpc"
"reflect"
@@ -197,11 +199,6 @@ func (this *APINode) registerServices(server *grpc.Server) {
pb.RegisterMessageReceiverServiceServer(server, instance)
this.rest(instance)
}
{
var instance = this.serviceInstance(&services.MessageMediaService{}).(*services.MessageMediaService)
pb.RegisterMessageMediaServiceServer(server, instance)
this.rest(instance)
}
{
var instance = this.serviceInstance(&services.MessageRecipientGroupService{}).(*services.MessageRecipientGroupService)
pb.RegisterMessageRecipientGroupServiceServer(server, instance)
@@ -343,7 +340,7 @@ func (this *APINode) registerServices(server *grpc.Server) {
this.rest(instance)
}
{
var instance = this.serviceInstance(&services.UserService{}).(*services.UserService)
var instance = this.serviceInstance(&users.UserService{}).(*users.UserService)
pb.RegisterUserServiceServer(server, instance)
this.rest(instance)
}
@@ -408,15 +405,25 @@ func (this *APINode) registerServices(server *grpc.Server) {
this.rest(instance)
}
{
var instance = this.serviceInstance(&services.FormalClientSystemService{}).(*services.FormalClientSystemService)
var instance = this.serviceInstance(&clients.FormalClientSystemService{}).(*clients.FormalClientSystemService)
pb.RegisterFormalClientSystemServiceServer(server, instance)
this.rest(instance)
}
{
var instance = this.serviceInstance(&services.FormalClientBrowserService{}).(*services.FormalClientBrowserService)
var instance = this.serviceInstance(&clients.FormalClientBrowserService{}).(*clients.FormalClientBrowserService)
pb.RegisterFormalClientBrowserServiceServer(server, instance)
this.rest(instance)
}
{
var instance = this.serviceInstance(&clients.ClientAgentIPService{}).(*clients.ClientAgentIPService)
pb.RegisterClientAgentIPServiceServer(server, instance)
this.rest(instance)
}
{
var instance = this.serviceInstance(&clients.ClientAgentService{}).(*clients.ClientAgentService)
pb.RegisterClientAgentServiceServer(server, instance)
this.rest(instance)
}
{
var instance = this.serviceInstance(&services.ServerClientSystemMonthlyStatService{}).(*services.ServerClientSystemMonthlyStatService)
pb.RegisterServerClientSystemMonthlyStatServiceServer(server, instance)

View File

@@ -0,0 +1,40 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package clients
import (
"context"
"github.com/TeaOSLab/EdgeAPI/internal/db/models/clients"
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
// ClientAgentService Agent服务
type ClientAgentService struct {
services.BaseService
}
// FindAllClientAgents 查找所有Agent
func (this *ClientAgentService) FindAllClientAgents(ctx context.Context, req *pb.FindAllClientAgentsRequest) (*pb.FindAllClientAgentsResponse, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
var tx = this.NullTx()
agents, err := clients.SharedClientAgentDAO.FindAllAgents(tx)
if err != nil {
return nil, err
}
var pbAgents = []*pb.ClientAgent{}
for _, agent := range agents {
pbAgents = append(pbAgents, &pb.ClientAgent{
Id: int64(agent.Id),
Name: agent.Name,
Code: agent.Code,
Description: agent.Description,
CountIPs: int64(agent.CountIPs),
})
}
return &pb.FindAllClientAgentsResponse{ClientAgents: pbAgents}, nil
}

View File

@@ -0,0 +1,97 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package clients
import (
"context"
"github.com/TeaOSLab/EdgeAPI/internal/db/models/clients"
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
// ClientAgentIPService Agent IP服务
type ClientAgentIPService struct {
services.BaseService
}
// CreateClientAgentIPs 创建一组IP
func (this *ClientAgentIPService) CreateClientAgentIPs(ctx context.Context, req *pb.CreateClientAgentIPsRequest) (*pb.RPCSuccess, error) {
_, _, err := this.ValidateNodeId(ctx, rpcutils.UserTypeAdmin, rpcutils.UserTypeDNS, rpcutils.UserTypeNode)
if err != nil {
return nil, err
}
if len(req.AgentIPs) == 0 {
return this.Success()
}
var tx = this.NullTx()
for _, agentIP := range req.AgentIPs {
agentId, err := clients.SharedClientAgentDAO.FindAgentIdWithCode(tx, agentIP.AgentCode)
if err != nil {
return nil, err
}
if agentId <= 0 {
continue
}
err = clients.SharedClientAgentIPDAO.CreateIP(tx, agentId, agentIP.Ip, agentIP.Ptr)
if err != nil {
return nil, err
}
}
return this.Success()
}
// ListClientAgentIPsAfterId 查询最新的IP
func (this *ClientAgentIPService) ListClientAgentIPsAfterId(ctx context.Context, req *pb.ListClientAgentIPsAfterIdRequest) (*pb.ListClientAgentIPsAfterIdResponse, error) {
_, _, err := this.ValidateNodeId(ctx, rpcutils.UserTypeAdmin, rpcutils.UserTypeDNS, rpcutils.UserTypeNode)
if err != nil {
return nil, err
}
if req.Size <= 0 {
req.Size = 10000
}
var tx = this.NullTx()
var agentMap = map[int64]*clients.ClientAgent{} // agentId => agentCode
agentIPs, err := clients.SharedClientAgentIPDAO.ListIPsAfterId(tx, req.Id, req.Size)
if err != nil {
return nil, err
}
var pbIPs = []*pb.ClientAgentIP{}
for _, agentIP := range agentIPs {
var agentId = int64(agentIP.AgentId)
agent, ok := agentMap[agentId]
if !ok {
agent, err = clients.SharedClientAgentDAO.FindAgent(tx, agentId)
if err != nil {
return nil, err
}
if agent == nil {
continue
}
agentMap[agentId] = agent
}
pbIPs = append(pbIPs, &pb.ClientAgentIP{
Id: int64(agentIP.Id),
Ip: agentIP.IP,
Ptr: agentIP.Ptr, // 导出时需要
ClientAgent: &pb.ClientAgent{
Id: agentId,
Name: "",
Code: agent.Code,
Description: "",
},
})
}
return &pb.ListClientAgentIPsAfterIdResponse{
ClientAgentIPs: pbIPs,
}, nil
}

View File

@@ -1,18 +1,19 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package services
package clients
import (
"context"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/types"
)
// FormalClientBrowserService 浏览器信息库服务
type FormalClientBrowserService struct {
BaseService
services.BaseService
}
// CreateFormalClientBrowser 创建浏览器信息

View File

@@ -1,18 +1,19 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package services
package clients
import (
"context"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/types"
)
// FormalClientSystemService 操作系统信息库服务
type FormalClientSystemService struct {
BaseService
services.BaseService
}
// CreateFormalClientSystem 创建操作系统信息

View File

@@ -425,7 +425,7 @@ func (this *AdminService) DeleteAdmin(ctx context.Context, req *pb.DeleteAdminRe
// TODO 超级管理员用户是不能删除的,或者要至少留一个超级管理员用户
_, err = models.SharedAdminDAO.DisableAdmin(tx, req.AdminId)
err = models.SharedAdminDAO.DisableAdmin(tx, req.AdminId)
if err != nil {
return nil, err
}

View File

@@ -2,8 +2,8 @@ package services
import (
"context"
"errors"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
@@ -14,49 +14,70 @@ type APIAccessTokenService struct {
// GetAPIAccessToken 获取AccessToken
func (this *APIAccessTokenService) GetAPIAccessToken(ctx context.Context, req *pb.GetAPIAccessTokenRequest) (*pb.GetAPIAccessTokenResponse, error) {
if req.Type == "user" || req.Type == "admin" { // 用户或管理员
var tx = this.NullTx()
accessKey, err := models.SharedUserAccessKeyDAO.FindAccessKeyWithUniqueId(tx, req.AccessKeyId)
if err != nil {
return nil, err
}
if accessKey == nil {
return nil, errors.New("access key not found")
}
if accessKey.Secret != req.AccessKey {
return nil, errors.New("access key not found")
}
// 检查数据
switch req.Type {
case "user":
if accessKey.UserId == 0 {
return nil, errors.New("access key not found")
}
case "admin":
if accessKey.AdminId == 0 {
return nil, errors.New("access key not found")
}
}
// 更新AccessKey访问时间
err = models.SharedUserAccessKeyDAO.UpdateAccessKeyAccessedAt(tx, int64(accessKey.Id))
if err != nil {
return nil, err
}
// 创建AccessToken
token, expiresAt, err := models.SharedAPIAccessTokenDAO.GenerateAccessToken(tx, int64(accessKey.AdminId), int64(accessKey.UserId))
if err != nil {
return nil, err
}
return &pb.GetAPIAccessTokenResponse{
Token: token,
ExpiresAt: expiresAt,
}, nil
} else {
if req.Type != "user" && req.Type != "admin" {
return nil, errors.New("unsupported type '" + req.Type + "'")
}
var tx = this.NullTx()
accessKey, err := models.SharedUserAccessKeyDAO.FindAccessKeyWithUniqueId(tx, req.AccessKeyId)
if err != nil {
return nil, err
}
if accessKey == nil {
return nil, errors.New("access key not found")
}
if accessKey.Secret != req.AccessKey {
return nil, errors.New("access key not found")
}
// 检查数据
switch req.Type {
case "user":
// TODO 将来支持子用户
if accessKey.UserId == 0 {
return nil, errors.New("access key not found")
}
// 检查用户状态
user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(accessKey.UserId), nil)
if err != nil {
return nil, err
}
if user == nil || !user.IsOn {
return nil, errors.New("the user is not available")
}
case "admin":
if accessKey.AdminId == 0 {
return nil, errors.New("access key not found")
}
// 检查管理员状态
admin, err := models.SharedAdminDAO.FindEnabledAdmin(tx, int64(accessKey.AdminId))
if err != nil {
return nil, err
}
if admin == nil || !admin.IsOn {
return nil, errors.New("the admin is not available")
}
default:
return nil, errors.New("invalid type '" + req.Type + "'")
}
// 更新AccessKey访问时间
err = models.SharedUserAccessKeyDAO.UpdateAccessKeyAccessedAt(tx, int64(accessKey.Id))
if err != nil {
return nil, err
}
// 创建AccessToken
token, expiresAt, err := models.SharedAPIAccessTokenDAO.GenerateAccessToken(tx, int64(accessKey.AdminId), int64(accessKey.UserId))
if err != nil {
return nil, err
}
return &pb.GetAPIAccessTokenResponse{
Token: token,
ExpiresAt: expiresAt,
}, nil
}

View File

@@ -4,7 +4,9 @@ import (
"context"
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
)
type HTTPHeaderPolicyService struct {
@@ -13,16 +15,22 @@ type HTTPHeaderPolicyService struct {
// FindEnabledHTTPHeaderPolicyConfig 查找策略配置
func (this *HTTPHeaderPolicyService) FindEnabledHTTPHeaderPolicyConfig(ctx context.Context, req *pb.FindEnabledHTTPHeaderPolicyConfigRequest) (*pb.FindEnabledHTTPHeaderPolicyConfigResponse, error) {
_, _, err := this.ValidateAdminAndUser(ctx, true)
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
// TODO 检查权限
// 检查权限
if userId > 0 {
err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
if err != nil {
return nil, err
}
}
config, err := models.SharedHTTPHeaderPolicyDAO.ComposeHeaderPolicyConfig(tx, req.HeaderPolicyId)
config, err := models.SharedHTTPHeaderPolicyDAO.ComposeHeaderPolicyConfig(tx, req.HttpHeaderPolicyId)
if err != nil {
return nil, err
}
@@ -32,7 +40,7 @@ func (this *HTTPHeaderPolicyService) FindEnabledHTTPHeaderPolicyConfig(ctx conte
return nil, err
}
return &pb.FindEnabledHTTPHeaderPolicyConfigResponse{HeaderPolicyJSON: configData}, nil
return &pb.FindEnabledHTTPHeaderPolicyConfigResponse{HttpHeaderPolicyJSON: configData}, nil
}
// CreateHTTPHeaderPolicy 创建策略
@@ -44,28 +52,32 @@ func (this *HTTPHeaderPolicyService) CreateHTTPHeaderPolicy(ctx context.Context,
var tx = this.NullTx()
// TODO 检查权限
headerPolicyId, err := models.SharedHTTPHeaderPolicyDAO.CreateHeaderPolicy(tx)
if err != nil {
return nil, err
}
return &pb.CreateHTTPHeaderPolicyResponse{HeaderPolicyId: headerPolicyId}, nil
return &pb.CreateHTTPHeaderPolicyResponse{HttpHeaderPolicyId: headerPolicyId}, nil
}
// UpdateHTTPHeaderPolicyAddingHeaders 修改AddHeaders
func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyAddingHeaders(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyAddingHeadersRequest) (*pb.RPCSuccess, error) {
_, _, err := this.ValidateAdminAndUser(ctx, true)
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
// TODO 检查权限
// 检查权限
if userId > 0 {
err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
if err != nil {
return nil, err
}
}
err = models.SharedHTTPHeaderPolicyDAO.UpdateAddingHeaders(tx, req.HeaderPolicyId, req.HeadersJSON)
err = models.SharedHTTPHeaderPolicyDAO.UpdateAddingHeaders(tx, req.HttpHeaderPolicyId, req.HeadersJSON)
if err != nil {
return nil, err
}
@@ -75,16 +87,22 @@ func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyAddingHeaders(ctx con
// UpdateHTTPHeaderPolicySettingHeaders 修改SetHeaders
func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicySettingHeaders(ctx context.Context, req *pb.UpdateHTTPHeaderPolicySettingHeadersRequest) (*pb.RPCSuccess, error) {
_, _, err := this.ValidateAdminAndUser(ctx, true)
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
// TODO 检查权限
// 检查权限
if userId > 0 {
err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
if err != nil {
return nil, err
}
}
err = models.SharedHTTPHeaderPolicyDAO.UpdateSettingHeaders(tx, req.HeaderPolicyId, req.HeadersJSON)
err = models.SharedHTTPHeaderPolicyDAO.UpdateSettingHeaders(tx, req.HttpHeaderPolicyId, req.HeadersJSON)
if err != nil {
return nil, err
}
@@ -94,16 +112,22 @@ func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicySettingHeaders(ctx co
// UpdateHTTPHeaderPolicyAddingTrailers 修改AddTrailers
func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyAddingTrailers(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyAddingTrailersRequest) (*pb.RPCSuccess, error) {
_, _, err := this.ValidateAdminAndUser(ctx, true)
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
// TODO 检查权限
// 检查权限
if userId > 0 {
err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
if err != nil {
return nil, err
}
}
err = models.SharedHTTPHeaderPolicyDAO.UpdateAddingTrailers(tx, req.HeaderPolicyId, req.HeadersJSON)
err = models.SharedHTTPHeaderPolicyDAO.UpdateAddingTrailers(tx, req.HttpHeaderPolicyId, req.HeadersJSON)
if err != nil {
return nil, err
}
@@ -113,16 +137,22 @@ func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyAddingTrailers(ctx co
// UpdateHTTPHeaderPolicyReplacingHeaders 修改ReplaceHeaders
func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyReplacingHeaders(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyReplacingHeadersRequest) (*pb.RPCSuccess, error) {
_, _, err := this.ValidateAdminAndUser(ctx, true)
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
// TODO 检查权限
// 检查权限
if userId > 0 {
err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
if err != nil {
return nil, err
}
}
err = models.SharedHTTPHeaderPolicyDAO.UpdateReplacingHeaders(tx, req.HeaderPolicyId, req.HeadersJSON)
err = models.SharedHTTPHeaderPolicyDAO.UpdateReplacingHeaders(tx, req.HttpHeaderPolicyId, req.HeadersJSON)
if err != nil {
return nil, err
}
@@ -132,16 +162,57 @@ func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyReplacingHeaders(ctx
// UpdateHTTPHeaderPolicyDeletingHeaders 修改删除的Headers
func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyDeletingHeaders(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyDeletingHeadersRequest) (*pb.RPCSuccess, error) {
_, _, err := this.ValidateAdminAndUser(ctx, true)
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
// TODO 检查权限
// 检查权限
if userId > 0 {
err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
if err != nil {
return nil, err
}
}
err = models.SharedHTTPHeaderPolicyDAO.UpdateDeletingHeaders(tx, req.HeaderPolicyId, req.HeaderNames)
err = models.SharedHTTPHeaderPolicyDAO.UpdateDeletingHeaders(tx, req.HttpHeaderPolicyId, req.HeaderNames)
if err != nil {
return nil, err
}
return this.Success()
}
// UpdateHTTPHeaderPolicyCORS 修改策略CORS设置
func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyCORS(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyCORSRequest) (*pb.RPCSuccess, error) {
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
// 检查权限
if userId > 0 {
err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
if err != nil {
return nil, err
}
}
var corsConfig = &shared.HTTPCORSHeaderConfig{}
err = json.Unmarshal(req.CorsJSON, corsConfig)
if err != nil {
return nil, err
}
err = corsConfig.Init()
if err != nil {
return nil, errors.New("validate CORS config failed: " + err.Error())
}
err = models.SharedHTTPHeaderPolicyDAO.UpdateHeaderPolicyCORS(tx, req.HttpHeaderPolicyId, corsConfig)
if err != nil {
return nil, err
}

View File

@@ -822,3 +822,71 @@ func (this *HTTPWebService) FindHTTPWebReferers(ctx context.Context, req *pb.Fin
ReferersJSON: configJSON,
}, nil
}
// UpdateHTTPWebUserAgent 修改UserAgent设置
func (this *HTTPWebService) UpdateHTTPWebUserAgent(ctx context.Context, req *pb.UpdateHTTPWebUserAgentRequest) (*pb.RPCSuccess, error) {
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
if userId > 0 {
err = models.SharedHTTPWebDAO.CheckUserWeb(tx, userId, req.HttpWebId)
if err != nil {
return nil, err
}
}
var config = &serverconfigs.UserAgentConfig{}
if len(req.UserAgentJSON) > 0 {
err = json.Unmarshal(req.UserAgentJSON, config)
if err != nil {
return nil, err
}
err = config.Init()
if err != nil {
return nil, errors.New("validate user-agent config failed: " + err.Error())
}
}
err = models.SharedHTTPWebDAO.UpdateWebUserAgent(tx, req.HttpWebId, config)
if err != nil {
return nil, err
}
return this.Success()
}
// FindHTTPWebUserAgent 查找UserAgent设置
func (this *HTTPWebService) FindHTTPWebUserAgent(ctx context.Context, req *pb.FindHTTPWebUserAgentRequest) (*pb.FindHTTPWebUserAgentResponse, error) {
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
if userId > 0 {
err = models.SharedHTTPWebDAO.CheckUserWeb(tx, userId, req.HttpWebId)
if err != nil {
return nil, err
}
}
config, err := models.SharedHTTPWebDAO.FindWebUserAgent(tx, req.HttpWebId)
if err != nil {
return nil, err
}
configJSON, err := json.Marshal(config)
if err != nil {
return nil, err
}
return &pb.FindHTTPWebUserAgentResponse{
UserAgentJSON: configJSON,
}, nil
}

View File

@@ -1,64 +0,0 @@
package services
import (
"context"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
// MessageMediaService 消息媒介服务
type MessageMediaService struct {
BaseService
}
// FindAllMessageMedias 获取所有支持的媒介
func (this *MessageMediaService) FindAllMessageMedias(ctx context.Context, req *pb.FindAllMessageMediasRequest) (*pb.FindAllMessageMediasResponse, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
var tx = this.NullTx()
medias, err := models.SharedMessageMediaDAO.FindAllEnabledMessageMedias(tx)
if err != nil {
return nil, err
}
pbMedias := []*pb.MessageMedia{}
for _, media := range medias {
pbMedias = append(pbMedias, &pb.MessageMedia{
Id: int64(media.Id),
Type: media.Type,
Name: media.Name,
Description: media.Description,
UserDescription: media.UserDescription,
IsOn: media.IsOn,
})
}
return &pb.FindAllMessageMediasResponse{MessageMedias: pbMedias}, nil
}
// UpdateMessageMedias 设置所有支持的媒介
func (this *MessageMediaService) UpdateMessageMedias(ctx context.Context, req *pb.UpdateMessageMediasRequest) (*pb.RPCSuccess, error) {
_, err := this.ValidateMonitorNode(ctx)
if err != nil {
return nil, err
}
mediaMaps := []maps.Map{}
for _, media := range req.MessageMedias {
mediaMaps = append(mediaMaps, maps.Map{
"name": media.Name,
"type": media.Type,
"description": media.Description,
"userDescription": media.UserDescription,
"isOn": media.IsOn,
})
}
var tx = this.NullTx()
err = models.SharedMessageMediaDAO.UpdateMessageMedias(tx, mediaMaps)
if err != nil {
return nil, err
}
return this.Success()
}

View File

@@ -6,11 +6,13 @@ import (
"errors"
"fmt"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/db/models/clients"
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
"github.com/TeaOSLab/EdgeAPI/internal/db/models/regions"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
@@ -769,7 +771,9 @@ func (this *ServerService) ListEnabledServersMatch(ctx context.Context, req *pb.
var tx = this.NullTx()
var fromUser = false
if userId > 0 {
fromUser = true
req.UserId = userId
}
@@ -816,15 +820,17 @@ func (this *ServerService) ListEnabledServersMatch(ctx context.Context, req *pb.
}
// 用户
user, err := models.SharedUserDAO.FindEnabledBasicUser(tx, int64(server.UserId))
if err != nil {
return nil, err
}
var pbUser *pb.User = nil
if user != nil {
pbUser = &pb.User{
Id: int64(user.Id),
Fullname: user.Fullname,
if !fromUser {
user, err := models.SharedUserDAO.FindEnabledBasicUser(tx, int64(server.UserId))
if err != nil {
return nil, err
}
if user != nil {
pbUser = &pb.User{
Id: int64(user.Id),
Fullname: user.Fullname,
}
}
}
@@ -840,7 +846,7 @@ func (this *ServerService) ListEnabledServersMatch(ctx context.Context, req *pb.
}
// 配置
config, err := models.SharedServerDAO.ComposeServerConfig(tx, server, nil, false, true)
config, err := models.SharedServerDAO.ComposeServerConfig(tx, server, req.IgnoreSSLCerts, nil, false, true)
if err != nil {
return nil, err
}
@@ -963,9 +969,9 @@ func (this *ServerService) FindEnabledServer(ctx context.Context, req *pb.FindEn
}
// 分组信息
pbGroups := []*pb.ServerGroup{}
var pbGroups = []*pb.ServerGroup{}
if len(server.GroupIds) > 0 {
groupIds := []int64{}
var groupIds = []int64{}
err = json.Unmarshal(server.GroupIds, &groupIds)
if err != nil {
return nil, err
@@ -1003,7 +1009,7 @@ func (this *ServerService) FindEnabledServer(ctx context.Context, req *pb.FindEn
}
// 配置
config, err := models.SharedServerDAO.ComposeServerConfig(tx, server, nil, userId > 0, false)
config, err := models.SharedServerDAO.ComposeServerConfig(tx, server, req.IgnoreSSLCerts, nil, userId > 0, false)
if err != nil {
return nil, err
}
@@ -1063,7 +1069,7 @@ func (this *ServerService) FindEnabledServerConfig(ctx context.Context, req *pb.
}
}
config, err := models.SharedServerDAO.ComposeServerConfigWithServerId(tx, req.ServerId, false)
config, err := models.SharedServerDAO.ComposeServerConfigWithServerId(tx, req.ServerId, false, false)
if err != nil {
return nil, err
}
@@ -1514,7 +1520,7 @@ func (this *ServerService) ComposeAllUserServersConfig(ctx context.Context, req
var configs = []*serverconfigs.ServerConfig{}
var cacheMap = utils.NewCacheMap()
for _, server := range servers {
config, err := models.SharedServerDAO.ComposeServerConfig(tx, server, cacheMap, true, false)
config, err := models.SharedServerDAO.ComposeServerConfig(tx, server, false, cacheMap, true, false)
if err != nil {
return nil, err
}
@@ -1714,7 +1720,7 @@ func (this *ServerService) UploadServerHTTPRequestStat(ctx context.Context, req
return err
}
if systemId == 0 {
err = models.SharedClientSystemDAO.CreateSystemIfNotExists(tx, result.Name)
err = clients.SharedClientSystemDAO.CreateSystemIfNotExists(tx, result.Name)
if err != nil {
return err
}
@@ -1745,7 +1751,7 @@ func (this *ServerService) UploadServerHTTPRequestStat(ctx context.Context, req
return err
}
if browserId == 0 {
err = models.SharedClientBrowserDAO.CreateBrowserIfNotExists(tx, result.Name)
err = clients.SharedClientBrowserDAO.CreateBrowserIfNotExists(tx, result.Name)
if err != nil {
return err
}
@@ -2221,7 +2227,7 @@ func (this *ServerService) ComposeServerConfig(ctx context.Context, req *pb.Comp
return &pb.ComposeServerConfigResponse{ServerConfigJSON: nil}, nil
}
serverConfig, err := models.SharedServerDAO.ComposeServerConfigWithServerId(tx, req.ServerId, true)
serverConfig, err := models.SharedServerDAO.ComposeServerConfigWithServerId(tx, req.ServerId, false, true)
if err != nil {
if err == models.ErrNotFound {
return &pb.ComposeServerConfigResponse{ServerConfigJSON: nil}, nil
@@ -2238,3 +2244,28 @@ func (this *ServerService) ComposeServerConfig(ctx context.Context, req *pb.Comp
}
return &pb.ComposeServerConfigResponse{ServerConfigJSON: configJSON}, nil
}
// UpdateServerUser 修改服务所属用户
func (this *ServerService) UpdateServerUser(ctx context.Context, req *pb.UpdateServerUserRequest) (*pb.RPCSuccess, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
if req.ServerId <= 0 {
return nil, errors.New("invalid serverId")
}
if req.UserId <= 0 {
return nil, errors.New("invalid userId")
}
err = this.RunTx(func(tx *dbs.Tx) error {
return models.SharedServerDAO.UpdateServerUserId(tx, req.ServerId, req.UserId)
})
if err != nil {
return nil, err
}
return this.Success()
}

View File

@@ -92,7 +92,7 @@ func (this *SSLCertService) FindEnabledSSLCertConfig(ctx context.Context, req *p
}
}
config, err := models.SharedSSLCertDAO.ComposeCertConfig(tx, req.SslCertId, nil)
config, err := models.SharedSSLCertDAO.ComposeCertConfig(tx, req.SslCertId, false, nil)
if err != nil {
return nil, err
}
@@ -179,7 +179,7 @@ func (this *SSLCertService) ListSSLCerts(ctx context.Context, req *pb.ListSSLCer
certConfigs := []*sslconfigs.SSLCertConfig{}
for _, certId := range certIds {
certConfig, err := models.SharedSSLCertDAO.ComposeCertConfig(tx, certId, nil)
certConfig, err := models.SharedSSLCertDAO.ComposeCertConfig(tx, certId, false, nil)
if err != nil {
return nil, err
}

View File

@@ -88,7 +88,7 @@ func (this *SSLPolicyService) FindEnabledSSLPolicyConfig(ctx context.Context, re
var tx = this.NullTx()
config, err := models.SharedSSLPolicyDAO.ComposePolicyConfig(tx, req.SslPolicyId, nil)
config, err := models.SharedSSLPolicyDAO.ComposePolicyConfig(tx, req.SslPolicyId, req.IgnoreData, nil)
if err != nil {
return nil, err
}

View File

@@ -1,24 +0,0 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package services
import (
"context"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
// FindUserPriceInfo 读取用户计费信息
func (this *UserService) FindUserPriceInfo(ctx context.Context, req *pb.FindUserPriceInfoRequest) (*pb.FindUserPriceInfoResponse, error) {
return nil, this.NotImplementedYet()
}
// UpdateUserPriceType 修改用户计费方式
func (this *UserService) UpdateUserPriceType(ctx context.Context, req *pb.UpdateUserPriceTypeRequest) (*pb.RPCSuccess, error) {
return nil, this.NotImplementedYet()
}
// UpdateUserPricePeriod 修改用户计费周期
func (this *UserService) UpdateUserPricePeriod(ctx context.Context, req *pb.UpdateUserPricePeriodRequest) (*pb.RPCSuccess, error) {
return nil, this.NotImplementedYet()
}

View File

@@ -1,4 +1,4 @@
package services
package users
import (
"context"
@@ -6,6 +6,7 @@ import (
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
@@ -13,15 +14,15 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/types"
timeutil "github.com/iwind/TeaGo/utils/time"
"strings"
"time"
)
// UserService 用户相关服务
type UserService struct {
BaseService
services.BaseService
}
// CreateUser 创建用户
@@ -40,59 +41,6 @@ func (this *UserService) CreateUser(ctx context.Context, req *pb.CreateUserReque
return &pb.CreateUserResponse{UserId: userId}, nil
}
// RegisterUser 注册用户
func (this *UserService) RegisterUser(ctx context.Context, req *pb.RegisterUserRequest) (*pb.RPCSuccess, error) {
userId, err := this.ValidateUserNode(ctx, false)
if err != nil {
return nil, err
}
if userId > 0 {
return nil, this.PermissionError()
}
// 注册配置
configJSON, err := models.SharedSysSettingDAO.ReadSetting(nil, systemconfigs.SettingCodeUserRegisterConfig)
if err != nil {
return nil, err
}
if len(configJSON) == 0 {
return nil, errors.New("the registration has been disabled")
}
var config = userconfigs.DefaultUserRegisterConfig()
err = json.Unmarshal(configJSON, config)
if err != nil {
return nil, err
}
if !config.IsOn {
return nil, errors.New("the registration has been disabled")
}
err = this.RunTx(func(tx *dbs.Tx) error {
// 检查用户名
exists, err := models.SharedUserDAO.ExistUser(tx, 0, req.Username)
if err != nil {
return err
}
if exists {
return errors.New("the username exists already")
}
// 创建用户
_, err = models.SharedUserDAO.CreateUser(tx, req.Username, req.Password, req.Fullname, req.Mobile, "", req.Email, "", req.Source, config.ClusterId, config.Features, req.Ip, !config.RequireVerification)
if err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return this.Success()
}
// VerifyUser 审核用户
func (this *UserService) VerifyUser(ctx context.Context, req *pb.VerifyUserRequest) (*pb.RPCSuccess, error) {
_, err := this.ValidateAdmin(ctx)
@@ -300,6 +248,7 @@ func (this *UserService) FindEnabledUser(ctx context.Context, req *pb.FindEnable
Mobile: user.Mobile,
Tel: user.Tel,
Email: user.Email,
VerifiedEmail: user.VerifiedEmail,
Remark: user.Remark,
IsOn: user.IsOn,
CreatedAt: int64(user.CreatedAt),
@@ -360,6 +309,28 @@ func (this *UserService) LoginUser(ctx context.Context, req *pb.LoginUserRequest
var tx = this.NullTx()
// 邮箱登录
if strings.Contains(req.Username, "@") {
// 是否允许
registerConfig, err := models.SharedSysSettingDAO.ReadUserRegisterConfig(tx)
if err != nil {
return nil, err
}
if registerConfig != nil && registerConfig.EmailVerification.CanLogin {
userId, err := models.SharedUserDAO.CheckUserEmailPassword(tx, req.Username, req.Password)
if err != nil {
return nil, err
}
if userId > 0 {
return &pb.LoginUserResponse{
UserId: userId,
IsOk: true,
}, nil
}
}
}
// 用户名登录
userId, err := models.SharedUserDAO.CheckUserPassword(tx, req.Username, req.Password)
if err != nil {
utils.PrintError(err)
@@ -474,10 +445,13 @@ func (this *UserService) ComposeUserDashboard(ctx context.Context, req *pb.Compo
}
// 今日总流量
dailyTrafficBytes, err := models.SharedServerDailyStatDAO.SumUserDaily(tx, req.UserId, 0, currentDay)
dailyTrafficStat, err := models.SharedServerDailyStatDAO.SumUserDaily(tx, req.UserId, 0, currentDay)
if err != nil {
return nil, err
}
if dailyTrafficStat == nil {
dailyTrafficStat = &models.ServerDailyStat{}
}
// 近 30 日流量带宽趋势
var dailyTrafficStats = []*pb.ComposeUserDashboardResponse_DailyTrafficStat{}
@@ -495,10 +469,13 @@ func (this *UserService) ComposeUserDashboard(ctx context.Context, req *pb.Compo
}
// 流量
trafficBytes, err := models.SharedServerDailyStatDAO.SumUserDaily(tx, req.UserId, 0, day)
trafficStat, err := models.SharedServerDailyStatDAO.SumUserDaily(tx, req.UserId, 0, day)
if err != nil {
return nil, err
}
if trafficStat == nil {
trafficStat = &models.ServerDailyStat{}
}
// 峰值带宽
peekBandwidthBytesStat, err := models.SharedUserBandwidthStatDAO.FindUserPeekBandwidthInDay(tx, req.UserId, day)
@@ -510,14 +487,22 @@ func (this *UserService) ComposeUserDashboard(ctx context.Context, req *pb.Compo
peekBandwidthBytes = int64(peekBandwidthBytesStat.Bytes)
}
dailyTrafficStats = append(dailyTrafficStats, &pb.ComposeUserDashboardResponse_DailyTrafficStat{Day: day, Bytes: trafficBytes})
dailyTrafficStats = append(dailyTrafficStats, &pb.ComposeUserDashboardResponse_DailyTrafficStat{
Day: day,
Bytes: int64(trafficStat.Bytes),
CachedBytes: int64(trafficStat.CachedBytes),
AttackBytes: int64(trafficStat.AttackBytes),
CountRequests: int64(trafficStat.CountRequests),
CountCachedRequests: int64(trafficStat.CountCachedRequests),
CountAttackRequests: int64(trafficStat.CountAttackRequests),
})
dailyPeekBandwidthStats = append(dailyPeekBandwidthStats, &pb.ComposeUserDashboardResponse_DailyPeekBandwidthStat{Day: day, Bytes: peekBandwidthBytes})
}
var result = &pb.ComposeUserDashboardResponse{
CountServers: countServers,
MonthlyTrafficBytes: monthlyTrafficBytes,
MonthlyPeekBandwidthBytes: monthlyPeekBandwidthBytes,
DailyTrafficBytes: dailyTrafficBytes,
DailyTrafficBytes: int64(dailyTrafficStat.Bytes),
DailyPeekBandwidthBytes: dailyPeekBandwidthBytes,
DailyTrafficStats: dailyTrafficStats,
DailyPeekBandwidthStats: dailyPeekBandwidthStats,
@@ -825,3 +810,53 @@ func (this *UserService) RenewUserServersState(ctx context.Context, req *pb.Rene
IsEnabled: isEnabled,
}, nil
}
// CheckUserEmail 检查邮箱是否被使用
func (this *UserService) CheckUserEmail(ctx context.Context, req *pb.CheckUserEmailRequest) (*pb.CheckUserEmailResponse, error) {
userId, err := this.ValidateUserNode(ctx, false)
if err != nil {
return nil, err
}
if len(req.Email) == 0 {
return nil, errors.New("'email' required")
}
var tx = this.NullTx()
emailOwnerUserId, err := models.SharedUserDAO.FindUserIdWithVerifiedEmail(tx, req.Email)
if err != nil {
return nil, err
}
if emailOwnerUserId > 0 && userId != emailOwnerUserId {
return &pb.CheckUserEmailResponse{Exists: true}, nil
}
return &pb.CheckUserEmailResponse{Exists: false}, nil
}
// FindUserVerifiedEmailWithUsername 根据用户名查询用户绑定的邮箱
func (this *UserService) FindUserVerifiedEmailWithUsername(ctx context.Context, req *pb.FindUserVerifiedEmailWithUsernameRequest) (*pb.FindUserVerifiedEmailWithUsernameResponse, error) {
_, err := this.ValidateUserNode(ctx, false)
if err != nil {
return nil, err
}
var tx = this.NullTx()
userId, err := models.SharedUserDAO.FindEnabledUserIdWithUsername(tx, req.Username)
if err != nil {
return nil, err
}
if userId <= 0 {
return &pb.FindUserVerifiedEmailWithUsernameResponse{
Email: "",
}, nil
}
email, err := models.SharedUserDAO.FindUserVerifiedEmail(tx, userId)
if err != nil {
return nil, err
}
return &pb.FindUserVerifiedEmailWithUsernameResponse{
Email: email,
}, nil
}

View File

@@ -0,0 +1,91 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package users
import (
"context"
"errors"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/dbs"
)
// FindUserPriceInfo 读取用户计费信息
func (this *UserService) FindUserPriceInfo(ctx context.Context, req *pb.FindUserPriceInfoRequest) (*pb.FindUserPriceInfoResponse, error) {
return nil, this.NotImplementedYet()
}
// UpdateUserPriceType 修改用户计费方式
func (this *UserService) UpdateUserPriceType(ctx context.Context, req *pb.UpdateUserPriceTypeRequest) (*pb.RPCSuccess, error) {
return nil, this.NotImplementedYet()
}
// UpdateUserPricePeriod 修改用户计费周期
func (this *UserService) UpdateUserPricePeriod(ctx context.Context, req *pb.UpdateUserPricePeriodRequest) (*pb.RPCSuccess, error) {
return nil, this.NotImplementedYet()
}
// RegisterUser 注册用户
func (this *UserService) RegisterUser(ctx context.Context, req *pb.RegisterUserRequest) (*pb.RegisterUserResponse, error) {
currentUserId, err := this.ValidateUserNode(ctx, true)
if err != nil {
return nil, err
}
if currentUserId > 0 {
return nil, this.PermissionError()
}
var tx = this.NullTx()
// 检查邮箱是否已被使用
if len(req.Email) > 0 {
emailUserId, err := models.SharedUserDAO.FindUserIdWithVerifiedEmail(tx, req.Email)
if err != nil {
return nil, err
}
if emailUserId > 0 {
return nil, errors.New("the email address '" + req.Email + "' is using by other user")
}
}
// 注册配置
registerConfig, err := models.SharedSysSettingDAO.ReadUserRegisterConfig(tx)
if err != nil {
return nil, err
}
if registerConfig == nil || !registerConfig.IsOn {
return nil, errors.New("the registration has been disabled")
}
var requireEmailVerification = false
var createdUserId int64
err = this.RunTx(func(tx *dbs.Tx) error {
// 检查用户名
exists, err := models.SharedUserDAO.ExistUser(tx, 0, req.Username)
if err != nil {
return err
}
if exists {
return errors.New("the username exists already")
}
// 创建用户
userId, err := models.SharedUserDAO.CreateUser(tx, req.Username, req.Password, req.Fullname, req.Mobile, "", req.Email, "", req.Source, registerConfig.ClusterId, registerConfig.Features, req.Ip, !registerConfig.RequireVerification)
if err != nil {
return err
}
createdUserId = userId
return nil
})
if err != nil {
return nil, err
}
return &pb.RegisterUserResponse{
UserId: createdUserId,
RequireEmailVerification: requireEmailVerification,
}, nil
}

File diff suppressed because one or more lines are too long

View File

@@ -49,6 +49,15 @@ var recordsTables = []*SQLRecordsTable{
TableName: "edgeFormalClientBrowsers",
UniqueFields: []string{"dataId"},
},
{
TableName: "edgeClientAgents",
UniqueFields: []string{"code"},
ExceptFields: []string{"countIPs"},
},
{
TableName: "edgeClientAgentIPs",
UniqueFields: []string{"agentId", "ip"},
},
}
type sqlItem struct {
@@ -426,7 +435,7 @@ func (this *SQLDump) applyQueue(db *dbs.DB, newResult *SQLDumpResult, showLog bo
continue
}
args = append(args, k+"=?")
args = append(args, "`"+k+"`"+"=?")
values = append(values, v)
}
values = append(values, one.GetInt("id"))

View File

@@ -124,6 +124,12 @@ func (this *SQLExecutor) checkData(db *dbs.DB) error {
return err
}
// 更新Agents
err = this.checkClientAgents(db)
if err != nil {
return err
}
// 更新版本号
err = this.updateVersion(db, ComposeSQLVersion())
if err != nil {
@@ -471,6 +477,29 @@ func (this *SQLExecutor) checkMetricItems(db *dbs.DB) error {
return nil
}
// 更新Agents表
func (this *SQLExecutor) checkClientAgents(db *dbs.DB) error {
ones, _, err := db.FindOnes("SELECT id FROM edgeClientAgents")
if err != nil {
return err
}
for _, one := range ones {
var agentId = one.GetInt64("id")
countIPs, err := db.FindCol(0, "SELECT COUNT(*) FROM edgeClientAgentIPs WHERE agentId=?", agentId)
if err != nil {
return err
}
_, err = db.Exec("UPDATE edgeClientAgents SET countIPs=? WHERE id=?", countIPs, agentId)
if err != nil {
return err
}
}
return nil
}
// 更新版本号
func (this *SQLExecutor) updateVersion(db *dbs.DB, version string) error {
stmt, err := db.Prepare("SELECT COUNT(*) FROM edgeVersions")

View File

@@ -6,7 +6,7 @@ import (
)
func TestSQLExecutor_Run(t *testing.T) {
executor := NewSQLExecutor(&dbs.DBConfig{
var executor = NewSQLExecutor(&dbs.DBConfig{
Driver: "mysql",
Prefix: "edge",
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_new?charset=utf8mb4&multiStatements=true",
@@ -19,7 +19,7 @@ func TestSQLExecutor_Run(t *testing.T) {
}
func TestSQLExecutor_checkCluster(t *testing.T) {
executor := NewSQLExecutor(&dbs.DBConfig{
var executor = NewSQLExecutor(&dbs.DBConfig{
Driver: "mysql",
Prefix: "edge",
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_new?charset=utf8mb4&multiStatements=true",
@@ -40,7 +40,7 @@ func TestSQLExecutor_checkCluster(t *testing.T) {
}
func TestSQLExecutor_checkMetricItems(t *testing.T) {
executor := NewSQLExecutor(&dbs.DBConfig{
var executor = NewSQLExecutor(&dbs.DBConfig{
Driver: "mysql",
Prefix: "edge",
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_new?charset=utf8mb4&multiStatements=true",
@@ -61,7 +61,7 @@ func TestSQLExecutor_checkMetricItems(t *testing.T) {
}
func TestSQLExecutor_checkNS(t *testing.T) {
executor := NewSQLExecutor(&dbs.DBConfig{
var executor = NewSQLExecutor(&dbs.DBConfig{
Driver: "mysql",
Prefix: "edge",
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_new?charset=utf8mb4&multiStatements=true",
@@ -80,3 +80,24 @@ func TestSQLExecutor_checkNS(t *testing.T) {
}
t.Log("ok")
}
func TestSQLExecutor_checkClientAgents(t *testing.T) {
var executor = NewSQLExecutor(&dbs.DBConfig{
Driver: "mysql",
Prefix: "edge",
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge?charset=utf8mb4&multiStatements=true",
})
db, err := dbs.NewInstanceFromConfig(executor.dbConfig)
if err != nil {
t.Fatal(err)
}
defer func() {
_ = db.Close()
}()
err = executor.checkClientAgents(db)
if err != nil {
t.Fatal(err)
}
t.Log("ok")
}

View File

@@ -48,7 +48,7 @@ func (this *DNSTaskExecutor) Start() {
}
func (this *DNSTaskExecutor) Loop() error {
if !models.SharedAPINodeDAO.CheckAPINodeIsPrimaryWithoutErr() {
if !this.IsPrimaryNode() {
return nil
}

View File

@@ -38,7 +38,7 @@ func (this *EventLooper) Start() {
}
func (this *EventLooper) Loop() error {
if !models.SharedAPINodeDAO.CheckAPINodeIsPrimaryWithoutErr() {
if !this.IsPrimaryNode() {
return nil
}

View File

@@ -92,7 +92,7 @@ func (this *HealthCheckClusterTask) Stop() {
// Loop 单个循环任务
func (this *HealthCheckClusterTask) Loop() error {
// 检查是否为主节点
if !models.SharedAPINodeDAO.CheckAPINodeIsPrimaryWithoutErr() {
if !this.IsPrimaryNode() {
return nil
}

View File

@@ -86,7 +86,7 @@ func (this *LogTask) RunMonitor() {
func (this *LogTask) LoopMonitor() error {
// 检查是否为主节点
if !models.SharedAPINodeDAO.CheckAPINodeIsPrimaryWithoutErr() {
if !this.IsPrimaryNode() {
return nil
}

View File

@@ -57,7 +57,7 @@ func (this *NodeMonitorTask) Start() {
func (this *NodeMonitorTask) Loop() error {
// 检查是否为主节点
if !models.SharedAPINodeDAO.CheckAPINodeIsPrimaryWithoutErr() {
if !this.IsPrimaryNode() {
return nil
}
@@ -111,7 +111,7 @@ func (this *NodeMonitorTask) MonitorCluster(cluster *models.NodeCluster) error {
err = nodeQueue.StartNode(nodeId)
if err != nil {
if !installers.IsGrantError(err) {
_ = models.SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleNode, nodeId, 0, 0, models.LevelError, "NODE", "start node from remote API failed: "+err.Error(), time.Now().Unix(), "", nil)
_ = models.SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleNode, nodeId, 0, 0, models.LevelInfo, "NODE", "start node from remote API failed: "+err.Error(), time.Now().Unix(), "", nil)
}
} else {
_ = models.SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleNode, nodeId, 0, 0, models.LevelSuccess, "NODE", "start node from remote API successfully", time.Now().Unix(), "", nil)

View File

@@ -40,7 +40,7 @@ func (this *NodeTaskExtractor) Start() {
func (this *NodeTaskExtractor) Loop() error {
// 检查是否为主节点
if !models.SharedAPINodeDAO.CheckAPINodeIsPrimaryWithoutErr() {
if !this.IsPrimaryNode() {
return nil
}

View File

@@ -16,7 +16,7 @@ import (
func init() {
dbs.OnReadyDone(func() {
goman.New(func() {
NewServerAccessLogCleaner(12 * time.Hour).Start()
NewServerAccessLogCleaner(6 * time.Hour).Start()
})
})
}
@@ -52,7 +52,7 @@ func (this *ServerAccessLogCleaner) Loop() error {
if len(configJSON) == 0 {
return nil
}
config := &systemconfigs.DatabaseConfig{}
var config = &systemconfigs.DatabaseConfig{}
err = json.Unmarshal(configJSON, config)
if err != nil {
return err
@@ -60,8 +60,8 @@ func (this *ServerAccessLogCleaner) Loop() error {
if config.ServerAccessLog.Clean.Days <= 0 {
return nil
}
days := config.ServerAccessLog.Clean.Days
endDay := timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days+1))
var days = config.ServerAccessLog.Clean.Days
var endDay = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days+1))
// 当前连接的数据库
db, err := dbs.Default()
@@ -113,7 +113,7 @@ func (this *ServerAccessLogCleaner) cleanDB(db *dbs.DB, endDay string) error {
if len(columnNames) != 1 {
return errors.New("invalid column names: " + strings.Join(columnNames, ", "))
}
columnName := columnNames[0]
var columnName = columnNames[0]
var reg = regexp.MustCompile(`^(?i)(edgeHTTPAccessLogs|edgeNSAccessLogs)_(\d{8})(_\d{4})?$`)
for _, one := range ones {
var tableName = one.GetString(columnName)

View File

@@ -45,7 +45,7 @@ func (this *SSLCertExpireCheckExecutor) Start() {
// Loop 单次执行
func (this *SSLCertExpireCheckExecutor) Loop() error {
// 检查是否为主节点
if !models.SharedAPINodeDAO.CheckAPINodeIsPrimaryWithoutErr() {
if !this.IsPrimaryNode() {
return nil
}

View File

@@ -53,7 +53,7 @@ func (this *SSLCertUpdateOCSPTask) Start() {
func (this *SSLCertUpdateOCSPTask) Loop() error {
// 检查是否为主节点
if !models.SharedAPINodeDAO.CheckAPINodeIsPrimaryWithoutErr() {
if !this.IsPrimaryNode() {
return nil
}

View File

@@ -2,7 +2,10 @@
package tasks
import "github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
)
type BaseTask struct {
}
@@ -10,3 +13,7 @@ type BaseTask struct {
func (this *BaseTask) logErr(taskType string, errString string) {
remotelogs.Error("TASK", "run '"+taskType+"' failed: "+errString)
}
func (this *BaseTask) IsPrimaryNode() bool {
return models.SharedAPINodeDAO.CheckAPINodeIsPrimaryWithoutErr()
}