mirror of https://github.com/allinssl/allinssl
后端代码同步
parent
5124663aab
commit
312f10d06d
|
|
@ -37,8 +37,9 @@ func Deploy(cfg map[string]any, logger *public.Logger) error {
|
||||||
case "aliyun-cdn":
|
case "aliyun-cdn":
|
||||||
logger.Debug("部署到阿里云CDN...")
|
logger.Debug("部署到阿里云CDN...")
|
||||||
return DeployAliCdn(cfg)
|
return DeployAliCdn(cfg)
|
||||||
// case "aliyun-oss":
|
case "aliyun-oss":
|
||||||
|
logger.Debug("部署到阿里云OSS...")
|
||||||
|
return DeployOss(cfg)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("不支持的部署: %s", providerName)
|
return fmt.Errorf("不支持的部署: %s", providerName)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ type SSHConfig struct {
|
||||||
Password string // 可选
|
Password string // 可选
|
||||||
PrivateKey string // 可选
|
PrivateKey string // 可选
|
||||||
Host string
|
Host string
|
||||||
Port string
|
Port float64
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoteFile struct {
|
type RemoteFile struct {
|
||||||
|
|
@ -24,7 +24,7 @@ type RemoteFile struct {
|
||||||
|
|
||||||
func buildAuthMethods(password, privateKey string) ([]ssh.AuthMethod, error) {
|
func buildAuthMethods(password, privateKey string) ([]ssh.AuthMethod, error) {
|
||||||
var methods []ssh.AuthMethod
|
var methods []ssh.AuthMethod
|
||||||
|
|
||||||
if privateKey != "" {
|
if privateKey != "" {
|
||||||
signer, err := ssh.ParsePrivateKey([]byte(privateKey))
|
signer, err := ssh.ParsePrivateKey([]byte(privateKey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -32,71 +32,71 @@ func buildAuthMethods(password, privateKey string) ([]ssh.AuthMethod, error) {
|
||||||
}
|
}
|
||||||
methods = append(methods, ssh.PublicKeys(signer))
|
methods = append(methods, ssh.PublicKeys(signer))
|
||||||
}
|
}
|
||||||
|
|
||||||
if password != "" {
|
if password != "" {
|
||||||
methods = append(methods, ssh.Password(password))
|
methods = append(methods, ssh.Password(password))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(methods) == 0 {
|
if len(methods) == 0 {
|
||||||
return nil, fmt.Errorf("no authentication methods provided")
|
return nil, fmt.Errorf("no authentication methods provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
return methods, nil
|
return methods, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeMultipleFilesViaSSH(config SSHConfig, files []RemoteFile, preCmd, postCmd string) error {
|
func writeMultipleFilesViaSSH(config SSHConfig, files []RemoteFile, preCmd, postCmd string) error {
|
||||||
addr := fmt.Sprintf("%s:%s", config.Host, config.Port)
|
addr := fmt.Sprintf("%s:%d", config.Host, int(config.Port))
|
||||||
|
|
||||||
authMethods, err := buildAuthMethods(config.Password, config.PrivateKey)
|
authMethods, err := buildAuthMethods(config.Password, config.PrivateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
sshConfig := &ssh.ClientConfig{
|
sshConfig := &ssh.ClientConfig{
|
||||||
User: config.User,
|
User: config.User,
|
||||||
Auth: authMethods,
|
Auth: authMethods,
|
||||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := ssh.Dial("tcp", addr, sshConfig)
|
client, err := ssh.Dial("tcp", addr, sshConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to dial: %v", err)
|
return fmt.Errorf("failed to dial: %v", err)
|
||||||
}
|
}
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
session, err := client.NewSession()
|
session, err := client.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("会话创建失败: %v", err)
|
return fmt.Errorf("会话创建失败: %v", err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
|
||||||
var script bytes.Buffer
|
var script bytes.Buffer
|
||||||
|
|
||||||
if preCmd != "" {
|
if preCmd != "" {
|
||||||
script.WriteString(preCmd + " && ")
|
script.WriteString(preCmd + " && ")
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, file := range files {
|
for i, file := range files {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
script.WriteString(" && ")
|
script.WriteString(" && ")
|
||||||
}
|
}
|
||||||
|
|
||||||
dirCmd := fmt.Sprintf("mkdir -p $(dirname %q)", file.Path)
|
dirCmd := fmt.Sprintf("mkdir -p $(dirname %q)", file.Path)
|
||||||
writeCmd := fmt.Sprintf("printf %%s '%s' > %s", file.Content, file.Path)
|
writeCmd := fmt.Sprintf("printf %%s '%s' > %s", file.Content, file.Path)
|
||||||
|
|
||||||
script.WriteString(dirCmd + " && " + writeCmd)
|
script.WriteString(dirCmd + " && " + writeCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
if postCmd != "" {
|
if postCmd != "" {
|
||||||
script.WriteString(" && " + postCmd)
|
script.WriteString(" && " + postCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := script.String()
|
cmd := script.String()
|
||||||
|
|
||||||
if err := session.Run(cmd); err != nil {
|
if err := session.Run(cmd); err != nil {
|
||||||
return fmt.Errorf("运行出错: %v", err)
|
return fmt.Errorf("运行出错: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +127,7 @@ func DeploySSH(cfg map[string]any) error {
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("参数错误:keyPath")
|
return fmt.Errorf("参数错误:keyPath")
|
||||||
}
|
}
|
||||||
certPath, ok := cfg["keyPath"].(string)
|
certPath, ok := cfg["certPath"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("参数错误:certPath")
|
return fmt.Errorf("参数错误:certPath")
|
||||||
}
|
}
|
||||||
|
|
@ -155,8 +155,8 @@ func DeploySSH(cfg map[string]any) error {
|
||||||
}
|
}
|
||||||
// 自动创建多级目录
|
// 自动创建多级目录
|
||||||
files := []RemoteFile{
|
files := []RemoteFile{
|
||||||
{Path: keyPath, Content: certPem},
|
{Path: certPath, Content: certPem},
|
||||||
{Path: certPath, Content: keyPem},
|
{Path: keyPath, Content: keyPem},
|
||||||
}
|
}
|
||||||
err = writeMultipleFilesViaSSH(providerConfig, files, beforeCmd, afterCmd)
|
err = writeMultipleFilesViaSSH(providerConfig, files, beforeCmd, afterCmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1,189 +1,189 @@
|
||||||
package report
|
package report
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ALLinSSL/backend/public"
|
"ALLinSSL/backend/public"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/jordan-wright/email"
|
"github.com/jordan-wright/email"
|
||||||
"net/smtp"
|
"net/smtp"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetSqlite() (*public.Sqlite, error) {
|
func GetSqlite() (*public.Sqlite, error) {
|
||||||
s, err := public.NewSqlite("data/data.db", "")
|
s, err := public.NewSqlite("data/data.db", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
s.Connect()
|
s.Connect()
|
||||||
s.TableName = "report"
|
s.TableName = "report"
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetList(search string, p, limit int64) ([]map[string]any, int, error) {
|
func GetList(search string, p, limit int64) ([]map[string]any, int, error) {
|
||||||
var data []map[string]any
|
var data []map[string]any
|
||||||
var count int64
|
var count int64
|
||||||
s, err := GetSqlite()
|
s, err := GetSqlite()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return data, 0, err
|
return data, 0, err
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
var limits []int64
|
var limits []int64
|
||||||
if p >= 0 && limit >= 0 {
|
if p >= 0 && limit >= 0 {
|
||||||
limits = []int64{0, limit}
|
limits = []int64{0, limit}
|
||||||
if p > 1 {
|
if p > 1 {
|
||||||
limits[0] = (p - 1) * limit
|
limits[0] = (p - 1) * limit
|
||||||
limits[1] = p * limit
|
limits[1] = p * limit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if search != "" {
|
if search != "" {
|
||||||
count, err = s.Where("name like ?", []interface{}{"%" + search + "%"}).Count()
|
count, err = s.Where("name like ?", []interface{}{"%" + search + "%"}).Count()
|
||||||
data, err = s.Where("name like ?", []interface{}{"%" + search + "%"}).Limit(limits).Order("update_time", "desc").Select()
|
data, err = s.Where("name like ?", []interface{}{"%" + search + "%"}).Limit(limits).Order("update_time", "desc").Select()
|
||||||
} else {
|
} else {
|
||||||
count, err = s.Count()
|
count, err = s.Count()
|
||||||
data, err = s.Order("update_time", "desc").Limit(limits).Select()
|
data, err = s.Order("update_time", "desc").Limit(limits).Select()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return data, 0, err
|
return data, 0, err
|
||||||
}
|
}
|
||||||
return data, int(count), nil
|
return data, int(count), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetReport(id string) (map[string]any, error) {
|
func GetReport(id string) (map[string]any, error) {
|
||||||
s, err := GetSqlite()
|
s, err := GetSqlite()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
data, err := s.Where("id=?", []interface{}{id}).Select()
|
data, err := s.Where("id=?", []interface{}{id}).Select()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return nil, fmt.Errorf("没有找到此通知配置")
|
return nil, fmt.Errorf("没有找到此通知配置")
|
||||||
}
|
}
|
||||||
return data[0], nil
|
return data[0], nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddReport(Type, config, name string) error {
|
func AddReport(Type, config, name string) error {
|
||||||
s, err := GetSqlite()
|
s, err := GetSqlite()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
now := time.Now().Format("2006-01-02 15:04:05")
|
now := time.Now().Format("2006-01-02 15:04:05")
|
||||||
_, err = s.Insert(map[string]interface{}{
|
_, err = s.Insert(map[string]interface{}{
|
||||||
"name": name,
|
"name": name,
|
||||||
"type": Type,
|
"type": Type,
|
||||||
"config": config,
|
"config": config,
|
||||||
"create_time": now,
|
"create_time": now,
|
||||||
"update_time": now,
|
"update_time": now,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdReport(id, config, name string) error {
|
func UpdReport(id, config, name string) error {
|
||||||
s, err := GetSqlite()
|
s, err := GetSqlite()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
_, err = s.Where("id=?", []interface{}{id}).Update(map[string]interface{}{
|
_, err = s.Where("id=?", []interface{}{id}).Update(map[string]interface{}{
|
||||||
"name": name,
|
"name": name,
|
||||||
"config": config,
|
"config": config,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func DelReport(id string) error {
|
func DelReport(id string) error {
|
||||||
s, err := GetSqlite()
|
s, err := GetSqlite()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
_, err = s.Where("id=?", []interface{}{id}).Delete()
|
_, err = s.Where("id=?", []interface{}{id}).Delete()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func NotifyTest(id string) error {
|
func NotifyTest(id string) error {
|
||||||
if id == "" {
|
if id == "" {
|
||||||
return fmt.Errorf("缺少参数")
|
return fmt.Errorf("缺少参数")
|
||||||
}
|
}
|
||||||
providerData, err := GetReport(id)
|
providerData, err := GetReport(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
params := map[string]any{
|
params := map[string]any{
|
||||||
"provider_id": id,
|
"provider_id": id,
|
||||||
"body": "测试消息通道",
|
"body": "测试消息通道",
|
||||||
"subject": "测试消息通道",
|
"subject": "测试消息通道",
|
||||||
}
|
}
|
||||||
switch providerData["type"] {
|
switch providerData["type"] {
|
||||||
case "mail":
|
case "mail":
|
||||||
err = NotifyMail(params)
|
err = NotifyMail(params)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func Notify(params map[string]any) error {
|
func Notify(params map[string]any) error {
|
||||||
if params == nil {
|
if params == nil {
|
||||||
return fmt.Errorf("缺少参数")
|
return fmt.Errorf("缺少参数")
|
||||||
}
|
}
|
||||||
providerName, ok := params["provider"].(string)
|
providerName, ok := params["provider"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("通知类型错误")
|
return fmt.Errorf("通知类型错误")
|
||||||
}
|
}
|
||||||
switch providerName {
|
switch providerName {
|
||||||
case "mail":
|
case "mail":
|
||||||
return NotifyMail(params)
|
return NotifyMail(params)
|
||||||
// case "btpanel-site":
|
// case "btpanel-site":
|
||||||
// return NotifyBt(params)
|
// return NotifyBt(params)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("不支持的通知类型")
|
return fmt.Errorf("不支持的通知类型")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NotifyMail(params map[string]any) error {
|
func NotifyMail(params map[string]any) error {
|
||||||
|
|
||||||
if params == nil {
|
if params == nil {
|
||||||
return fmt.Errorf("缺少参数")
|
return fmt.Errorf("缺少参数")
|
||||||
}
|
}
|
||||||
providerID := params["provider_id"].(string)
|
providerID := params["provider_id"].(string)
|
||||||
// fmt.Println(providerID)
|
// fmt.Println(providerID)
|
||||||
providerData, err := GetReport(providerID)
|
providerData, err := GetReport(providerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
configStr := providerData["config"].(string)
|
configStr := providerData["config"].(string)
|
||||||
var config map[string]string
|
var config map[string]string
|
||||||
err = json.Unmarshal([]byte(configStr), &config)
|
err = json.Unmarshal([]byte(configStr), &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("解析配置失败: %v", err)
|
return fmt.Errorf("解析配置失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
e := email.NewEmail()
|
e := email.NewEmail()
|
||||||
e.From = config["sender"]
|
e.From = config["sender"]
|
||||||
e.To = []string{config["receiver"]}
|
e.To = []string{config["receiver"]}
|
||||||
e.Subject = params["subject"].(string)
|
e.Subject = params["subject"].(string)
|
||||||
|
|
||||||
e.Text = []byte(params["body"].(string))
|
e.Text = []byte(params["body"].(string))
|
||||||
|
|
||||||
addr := fmt.Sprintf("%s:%s", config["smtpHost"], config["smtpPort"])
|
addr := fmt.Sprintf("%s:%s", config["smtpHost"], config["smtpPort"])
|
||||||
|
|
||||||
auth := smtp.PlainAuth("", config["sender"], config["password"], config["smtpHost"])
|
auth := smtp.PlainAuth("", config["sender"], config["password"], config["smtpHost"])
|
||||||
|
|
||||||
// 使用 SSL(通常是 465)
|
// 使用 SSL(通常是 465)
|
||||||
if config["smtpPort"] == "465" {
|
if config["smtpPort"] == "465" {
|
||||||
tlsConfig := &tls.Config{
|
tlsConfig := &tls.Config{
|
||||||
InsecureSkipVerify: true, // 开发阶段跳过证书验证,生产建议关闭
|
InsecureSkipVerify: true, // 开发阶段跳过证书验证,生产建议关闭
|
||||||
ServerName: config["smtpHost"],
|
ServerName: config["smtpHost"],
|
||||||
}
|
}
|
||||||
return e.SendWithTLS(addr, auth, tlsConfig)
|
return e.SendWithTLS(addr, auth, tlsConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 普通明文发送(25端口,非推荐)
|
// 普通明文发送(25端口,非推荐)
|
||||||
return e.Send(addr, auth)
|
return e.Send(addr, auth)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ func Get() (Setting, error) {
|
||||||
Timeout: public.TimeOut,
|
Timeout: public.TimeOut,
|
||||||
Secure: public.Secure,
|
Secure: public.Secure,
|
||||||
}
|
}
|
||||||
|
|
||||||
setting.Https = public.GetSettingIgnoreError("https")
|
setting.Https = public.GetSettingIgnoreError("https")
|
||||||
key, err := os.ReadFile("data/https/key.pem")
|
key, err := os.ReadFile("data/https/key.pem")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -60,7 +60,7 @@ func Get() (Setting, error) {
|
||||||
func Save(setting *Setting) error {
|
func Save(setting *Setting) error {
|
||||||
var restart bool
|
var restart bool
|
||||||
var reload bool
|
var reload bool
|
||||||
|
|
||||||
s, err := public.NewSqlite("data/data.db", "")
|
s, err := public.NewSqlite("data/data.db", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -79,7 +79,7 @@ func Save(setting *Setting) error {
|
||||||
if setting.Username != "" {
|
if setting.Username != "" {
|
||||||
data["username"] = setting.Username
|
data["username"] = setting.Username
|
||||||
}
|
}
|
||||||
|
|
||||||
salt := user[0]["salt"].(string)
|
salt := user[0]["salt"].(string)
|
||||||
passwd := setting.Password + salt
|
passwd := setting.Password + salt
|
||||||
// fmt.Println(passwd)
|
// fmt.Println(passwd)
|
||||||
|
|
@ -98,10 +98,12 @@ func Save(setting *Setting) error {
|
||||||
if setting.Timeout != 0 {
|
if setting.Timeout != 0 {
|
||||||
s.Where("key = 'timeout'", []interface{}{}).Update(map[string]interface{}{"value": setting.Timeout})
|
s.Where("key = 'timeout'", []interface{}{}).Update(map[string]interface{}{"value": setting.Timeout})
|
||||||
public.TimeOut = setting.Timeout
|
public.TimeOut = setting.Timeout
|
||||||
|
restart = true
|
||||||
}
|
}
|
||||||
if setting.Secure != "" {
|
if setting.Secure != "" {
|
||||||
s.Where("key = 'secure'", []interface{}{}).Update(map[string]interface{}{"value": setting.Secure})
|
s.Where("key = 'secure'", []interface{}{}).Update(map[string]interface{}{"value": setting.Secure})
|
||||||
public.TimeOut = setting.Timeout
|
public.TimeOut = setting.Timeout
|
||||||
|
restart = true
|
||||||
}
|
}
|
||||||
if setting.Https == "1" {
|
if setting.Https == "1" {
|
||||||
if setting.Key == "" || setting.Cert == "" {
|
if setting.Key == "" || setting.Cert == "" {
|
||||||
|
|
@ -122,7 +124,6 @@ func Save(setting *Setting) error {
|
||||||
os.WriteFile("data/https/cert.pem", []byte(setting.Cert), 0644)
|
os.WriteFile("data/https/cert.pem", []byte(setting.Cert), 0644)
|
||||||
restart = true
|
restart = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if restart {
|
if restart {
|
||||||
Restart()
|
Restart()
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -1,117 +1,117 @@
|
||||||
package workflow
|
package workflow
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ALLinSSL/backend/public"
|
"ALLinSSL/backend/public"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetSqliteObjWH 工作流执行历史记录表对象
|
// GetSqliteObjWH 工作流执行历史记录表对象
|
||||||
func GetSqliteObjWH() (*public.Sqlite, error) {
|
func GetSqliteObjWH() (*public.Sqlite, error) {
|
||||||
s, err := public.NewSqlite("data/data.db", "")
|
s, err := public.NewSqlite("data/data.db", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
s.Connect()
|
s.Connect()
|
||||||
s.TableName = "workflow_history"
|
s.TableName = "workflow_history"
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListWH 获取工作流执行历史记录列表
|
// GetListWH 获取工作流执行历史记录列表
|
||||||
func GetListWH(id string, p, limit int64) ([]map[string]any, int, error) {
|
func GetListWH(id string, p, limit int64) ([]map[string]any, int, error) {
|
||||||
var data []map[string]any
|
var data []map[string]any
|
||||||
var count int64
|
var count int64
|
||||||
s, err := GetSqliteObjWH()
|
s, err := GetSqliteObjWH()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return data, 0, err
|
return data, 0, err
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
var limits []int64
|
var limits []int64
|
||||||
if p >= 0 && limit >= 0 {
|
if p >= 0 && limit >= 0 {
|
||||||
limits = []int64{0, limit}
|
limits = []int64{0, limit}
|
||||||
if p > 1 {
|
if p > 1 {
|
||||||
limits[0] = (p - 1) * limit
|
limits[0] = (p - 1) * limit
|
||||||
limits[1] = p * limit
|
limits[1] = p * limit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if id == "" {
|
if id == "" {
|
||||||
count, err = s.Count()
|
count, err = s.Count()
|
||||||
data, err = s.Limit(limits).Order("create_time", "desc").Select()
|
data, err = s.Limit(limits).Order("create_time", "desc").Select()
|
||||||
} else {
|
} else {
|
||||||
count, err = s.Where("workflow_id=?", []interface{}{id}).Count()
|
count, err = s.Where("workflow_id=?", []interface{}{id}).Count()
|
||||||
data, err = s.Where("workflow_id=?", []interface{}{id}).Limit(limits).Order("create_time", "desc").Select()
|
data, err = s.Where("workflow_id=?", []interface{}{id}).Limit(limits).Order("create_time", "desc").Select()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return data, 0, err
|
return data, 0, err
|
||||||
}
|
}
|
||||||
return data, int(count), nil
|
return data, int(count), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加工作流执行历史记录
|
// 添加工作流执行历史记录
|
||||||
func AddWorkflowHistory(workflowID, execType string) (string, error) {
|
func AddWorkflowHistory(workflowID, execType string) (string, error) {
|
||||||
s, err := GetSqliteObjWH()
|
s, err := GetSqliteObjWH()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
now := time.Now().Format("2006-01-02 15:04:05")
|
now := time.Now().Format("2006-01-02 15:04:05")
|
||||||
ID := public.GenerateUUID()
|
ID := public.GenerateUUID()
|
||||||
_, err = s.Insert(map[string]interface{}{
|
_, err = s.Insert(map[string]interface{}{
|
||||||
"id": ID,
|
"id": ID,
|
||||||
"workflow_id": workflowID,
|
"workflow_id": workflowID,
|
||||||
"status": "running",
|
"status": "running",
|
||||||
"exec_type": execType,
|
"exec_type": execType,
|
||||||
"create_time": now,
|
"create_time": now,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
_ = UpdDb(workflowID, map[string]interface{}{"last_run_status": "running", "last_run_time": now})
|
_ = UpdDb(workflowID, map[string]interface{}{"last_run_status": "running", "last_run_time": now})
|
||||||
return ID, nil
|
return ID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 工作流执行结束
|
// 工作流执行结束
|
||||||
func UpdateWorkflowHistory(id, status string) error {
|
func UpdateWorkflowHistory(id, status string) error {
|
||||||
s, err := GetSqliteObjWH()
|
s, err := GetSqliteObjWH()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
now := time.Now().Format("2006-01-02 15:04:05")
|
now := time.Now().Format("2006-01-02 15:04:05")
|
||||||
_, err = s.Where("id=?", []interface{}{id}).Update(map[string]interface{}{
|
_, err = s.Where("id=?", []interface{}{id}).Update(map[string]interface{}{
|
||||||
"status": status,
|
"status": status,
|
||||||
"end_time": now,
|
"end_time": now,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func StopWorkflow(id string) error {
|
func StopWorkflow(id string) error {
|
||||||
s, err := GetSqliteObjWH()
|
s, err := GetSqliteObjWH()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
data, err := s.Where("id=?", []interface{}{id}).Select()
|
data, err := s.Where("id=?", []interface{}{id}).Select()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
SetWorkflowStatus(data[0]["workflow_id"].(string), id, "fail")
|
SetWorkflowStatus(data[0]["workflow_id"].(string), id, "fail")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetExecLog(id string) (string, error) {
|
func GetExecLog(id string) (string, error) {
|
||||||
log, err := os.ReadFile(filepath.Join(public.GetSettingIgnoreError("workflow_log_path"), id+".log"))
|
log, err := os.ReadFile(filepath.Join(public.GetSettingIgnoreError("workflow_log_path"), id+".log"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return string(log), nil
|
return string(log), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
os.MkdirAll("data", os.ModePerm)
|
os.MkdirAll("data", os.ModePerm)
|
||||||
|
|
||||||
dbPath := "data/data.db"
|
dbPath := "data/data.db"
|
||||||
_, _ = filepath.Abs(dbPath)
|
_, _ = filepath.Abs(dbPath)
|
||||||
// fmt.Println("数据库路径:", absPath)
|
// fmt.Println("数据库路径:", absPath)
|
||||||
|
|
@ -176,15 +176,15 @@ func init() {
|
||||||
INSERT INTO access_type (name, type) VALUES ('ssh', 'host');
|
INSERT INTO access_type (name, type) VALUES ('ssh', 'host');
|
||||||
INSERT INTO access_type (name, type) VALUES ('btpanel', 'host');
|
INSERT INTO access_type (name, type) VALUES ('btpanel', 'host');
|
||||||
INSERT INTO access_type (name, type) VALUES ('1panel', 'host');`)
|
INSERT INTO access_type (name, type) VALUES ('1panel', 'host');`)
|
||||||
|
|
||||||
uuidStr := public.GenerateUUID()
|
uuidStr := public.GenerateUUID()
|
||||||
randomStr := public.RandomString(8)
|
randomStr := public.RandomString(8)
|
||||||
|
|
||||||
port, err := public.GetFreePort()
|
port, err := public.GetFreePort()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
port = 20773
|
port = 20773
|
||||||
}
|
}
|
||||||
|
|
||||||
Isql := fmt.Sprintf(
|
Isql := fmt.Sprintf(
|
||||||
`INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('log_path', 'logs/ALLinSSL.log', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);
|
`INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('log_path', 'logs/ALLinSSL.log', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);
|
||||||
INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ( 'workflow_log_path', 'logs/workflows/', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);
|
INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ( 'workflow_log_path', 'logs/workflows/', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);
|
||||||
|
|
@ -194,7 +194,7 @@ INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES
|
||||||
INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('session_key', '%s', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);
|
INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('session_key', '%s', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);
|
||||||
INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('secure', '/%s', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);
|
INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('secure', '/%s', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);
|
||||||
INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('port', '%d', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);`, uuidStr, uuidStr, randomStr, port)
|
INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('port', '%d', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);`, uuidStr, uuidStr, randomStr, port)
|
||||||
|
|
||||||
insertDefaultData(db, "settings", Isql)
|
insertDefaultData(db, "settings", Isql)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,7 +206,7 @@ func insertDefaultData(db *sql.DB, table, insertSQL string) {
|
||||||
// fmt.Println("检查数据行数失败:", err)
|
// fmt.Println("检查数据行数失败:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果表为空,则插入默认数据
|
// 如果表为空,则插入默认数据
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
// fmt.Println("表为空,插入默认数据...")
|
// fmt.Println("表为空,插入默认数据...")
|
||||||
|
|
|
||||||
|
|
@ -1,181 +1,181 @@
|
||||||
package public
|
package public
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
const defaultCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
|
|
||||||
// GetSettingIgnoreError 获取系统配置-忽略错误
|
// GetSettingIgnoreError 获取系统配置-忽略错误
|
||||||
func GetSettingIgnoreError(key string) string {
|
func GetSettingIgnoreError(key string) string {
|
||||||
s, err := NewSqlite("data/data.db", "")
|
s, err := NewSqlite("data/data.db", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
s.Connect()
|
s.Connect()
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
s.TableName = "settings"
|
s.TableName = "settings"
|
||||||
res, err := s.Where("key=?", []interface{}{key}).Select()
|
res, err := s.Where("key=?", []interface{}{key}).Select()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if len(res) == 0 {
|
if len(res) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
setting, ok := res[0]["value"].(string)
|
setting, ok := res[0]["value"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return setting
|
return setting
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateSetting(key, val string) error {
|
func UpdateSetting(key, val string) error {
|
||||||
s, err := NewSqlite("data/data.db", "")
|
s, err := NewSqlite("data/data.db", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.Connect()
|
s.Connect()
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
s.TableName = "settings"
|
s.TableName = "settings"
|
||||||
_, err = s.Where("key=?", []interface{}{key}).Update(map[string]any{"value": val})
|
_, err = s.Where("key=?", []interface{}{key}).Update(map[string]any{"value": val})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSettingsFromType(typ string) ([]map[string]any, error) {
|
func GetSettingsFromType(typ string) ([]map[string]any, error) {
|
||||||
db := "data/data.db"
|
db := "data/data.db"
|
||||||
s, err := NewSqlite(db, "")
|
s, err := NewSqlite(db, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
s.Connect()
|
s.Connect()
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
s.TableName = "settings"
|
s.TableName = "settings"
|
||||||
res, err := s.Where("type=?", []interface{}{typ}).Select()
|
res, err := s.Where("type=?", []interface{}{typ}).Select()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFreePort 获取一个可用的随机端口
|
// GetFreePort 获取一个可用的随机端口
|
||||||
func GetFreePort() (int, error) {
|
func GetFreePort() (int, error) {
|
||||||
// 端口为 0,表示让系统自动分配一个可用端口
|
// 端口为 0,表示让系统自动分配一个可用端口
|
||||||
ln, err := net.Listen("tcp", "localhost:0")
|
ln, err := net.Listen("tcp", "localhost:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
defer ln.Close()
|
defer ln.Close()
|
||||||
|
|
||||||
addr := ln.Addr().String()
|
addr := ln.Addr().String()
|
||||||
// 提取端口号
|
// 提取端口号
|
||||||
parts := strings.Split(addr, ":")
|
parts := strings.Split(addr, ":")
|
||||||
if len(parts) < 2 {
|
if len(parts) < 2 {
|
||||||
return 0, fmt.Errorf("invalid address: %s", addr)
|
return 0, fmt.Errorf("invalid address: %s", addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
var port int
|
var port int
|
||||||
fmt.Sscanf(parts[len(parts)-1], "%d", &port)
|
fmt.Sscanf(parts[len(parts)-1], "%d", &port)
|
||||||
return port, nil
|
return port, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandomString 生成指定长度的随机字符串
|
// RandomString 生成指定长度的随机字符串
|
||||||
func RandomString(length int) string {
|
func RandomString(length int) string {
|
||||||
if str, err := RandomStringWithCharset(length, defaultCharset); err != nil {
|
if str, err := RandomStringWithCharset(length, defaultCharset); err != nil {
|
||||||
return "allinssl"
|
return "allinssl"
|
||||||
} else {
|
} else {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandomStringWithCharset 使用指定字符集生成随机字符串
|
// RandomStringWithCharset 使用指定字符集生成随机字符串
|
||||||
func RandomStringWithCharset(length int, charset string) (string, error) {
|
func RandomStringWithCharset(length int, charset string) (string, error) {
|
||||||
result := make([]byte, length)
|
result := make([]byte, length)
|
||||||
charsetLen := big.NewInt(int64(len(charset)))
|
charsetLen := big.NewInt(int64(len(charset)))
|
||||||
|
|
||||||
for i := 0; i < length; i++ {
|
for i := 0; i < length; i++ {
|
||||||
num, err := rand.Int(rand.Reader, charsetLen)
|
num, err := rand.Int(rand.Reader, charsetLen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
result[i] = charset[num.Int64()]
|
result[i] = charset[num.Int64()]
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(result), nil
|
return string(result), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateUUID 生成 UUID
|
// GenerateUUID 生成 UUID
|
||||||
func GenerateUUID() string {
|
func GenerateUUID() string {
|
||||||
// 生成一个新的 UUID
|
// 生成一个新的 UUID
|
||||||
uuidStr := strings.ReplaceAll(uuid.New().String(), "-", "")
|
uuidStr := strings.ReplaceAll(uuid.New().String(), "-", "")
|
||||||
|
|
||||||
// 返回 UUID 的字符串表示
|
// 返回 UUID 的字符串表示
|
||||||
return uuidStr
|
return uuidStr
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLocalIP() (string, error) {
|
func GetLocalIP() (string, error) {
|
||||||
interfaces, err := net.Interfaces()
|
interfaces, err := net.Interfaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, iface := range interfaces {
|
for _, iface := range interfaces {
|
||||||
if iface.Flags&net.FlagUp == 0 {
|
if iface.Flags&net.FlagUp == 0 {
|
||||||
continue // 接口未启用
|
continue // 接口未启用
|
||||||
}
|
}
|
||||||
if iface.Flags&net.FlagLoopback != 0 {
|
if iface.Flags&net.FlagLoopback != 0 {
|
||||||
continue // 忽略回环地址
|
continue // 忽略回环地址
|
||||||
}
|
}
|
||||||
|
|
||||||
addrs, err := iface.Addrs()
|
addrs, err := iface.Addrs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
var ip net.IP
|
var ip net.IP
|
||||||
switch v := addr.(type) {
|
switch v := addr.(type) {
|
||||||
case *net.IPNet:
|
case *net.IPNet:
|
||||||
ip = v.IP
|
ip = v.IP
|
||||||
case *net.IPAddr:
|
case *net.IPAddr:
|
||||||
ip = v.IP
|
ip = v.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
// 只返回 IPv4 内网地址
|
// 只返回 IPv4 内网地址
|
||||||
if ip != nil && ip.To4() != nil && !ip.IsLoopback() {
|
if ip != nil && ip.To4() != nil && !ip.IsLoopback() {
|
||||||
return ip.String(), nil
|
return ip.String(), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", fmt.Errorf("没有找到内网 IP")
|
return "", fmt.Errorf("没有找到内网 IP")
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPublicIP() (string, error) {
|
func GetPublicIP() (string, error) {
|
||||||
resp, err := http.Get("https://www.bt.cn/Api/getIpAddress")
|
resp, err := http.Get("https://www.bt.cn/Api/getIpAddress")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("请求失败: %v", err)
|
return "", fmt.Errorf("请求失败: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return "", fmt.Errorf("HTTP状态错误: %v", resp.Status)
|
return "", fmt.Errorf("HTTP状态错误: %v", resp.Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("读取响应失败: %v", err)
|
return "", fmt.Errorf("读取响应失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(body), nil
|
return string(body), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue