Add files via upload

This commit is contained in:
zhangch-dev
2025-05-06 18:51:53 +08:00
committed by GitHub
parent 0ccc0620f3
commit e7b5ac85e1
52 changed files with 7266 additions and 0 deletions

135
backend/app/api/access.go Normal file
View File

@@ -0,0 +1,135 @@
package api
import (
"ALLinSSL/backend/internal/access"
"ALLinSSL/backend/public"
"github.com/gin-gonic/gin"
"strings"
)
func GetAccessList(c *gin.Context) {
var form struct {
Search string `form:"search"`
Page int64 `form:"p"`
Limit int64 `form:"limit"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
accessList, count, err := access.GetList(form.Search, form.Page, form.Limit)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessData(c, accessList, count)
return
}
func GetAllAccess(c *gin.Context) {
var form struct {
Type string `form:"type"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
accessList, err := access.GetAll(form.Type)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessData(c, accessList, 0)
return
}
func AddAccess(c *gin.Context) {
var form struct {
Name string `form:"name"`
Type string `form:"type"`
Config string `form:"config"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
form.Name = strings.TrimSpace(form.Name)
if form.Name == "" {
public.FailMsg(c, "名称不能为空")
return
}
if form.Type == "" {
public.FailMsg(c, "类型不能为空")
return
}
if form.Config == "" {
public.FailMsg(c, "配置不能为空")
return
}
err = access.AddAccess(form.Config, form.Name, form.Type)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "添加成功")
return
}
func UpdateAccess(c *gin.Context) {
var form struct {
ID string `form:"id"`
Name string `form:"name"`
Config string `form:"config"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
form.Name = strings.TrimSpace(form.Name)
if form.Name == "" {
public.FailMsg(c, "名称不能为空")
return
}
if form.Config == "" {
public.FailMsg(c, "配置不能为空")
return
}
err = access.UpdateAccess(form.ID, form.Config, form.Name)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "修改成功")
return
}
func DelAccess(c *gin.Context) {
var form struct {
ID string `form:"id"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
form.ID = strings.TrimSpace(form.ID)
if form.ID == "" {
public.FailMsg(c, "ID不能为空")
return
}
err = access.DelAccess(form.ID)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "删除成功")
return
}

129
backend/app/api/cert.go Normal file
View File

@@ -0,0 +1,129 @@
package api
import (
"ALLinSSL/backend/internal/cert"
"ALLinSSL/backend/public"
"archive/zip"
"bytes"
"github.com/gin-gonic/gin"
"strings"
)
func GetCertList(c *gin.Context) {
var form struct {
Search string `form:"search"`
Page int64 `form:"p"`
Limit int64 `form:"limit"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
certList, count, err := cert.GetList(form.Search, form.Page, form.Limit)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessData(c, certList, count)
return
}
func UploadCert(c *gin.Context) {
var form struct {
Key string `form:"key"`
Cert string `form:"cert"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
form.Key = strings.TrimSpace(form.Key)
form.Cert = strings.TrimSpace(form.Cert)
if form.Key == "" {
public.FailMsg(c, "名称不能为空")
return
}
if form.Cert == "" {
public.FailMsg(c, "类型不能为空")
return
}
err = cert.UploadCert(form.Key, form.Cert)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "添加成功")
return
}
func DelCert(c *gin.Context) {
var form struct {
ID string `form:"id"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
if form.ID == "" {
public.FailMsg(c, "ID不能为空")
return
}
err = cert.DelCert(form.ID)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "删除成功")
return
}
func DownloadCert(c *gin.Context) {
ID := c.Query("id")
if ID == "" {
public.FailMsg(c, "ID不能为空")
return
}
certData, err := cert.GetCert(ID)
if err != nil {
public.FailMsg(c, err.Error())
return
}
// 构建 zip 包(内存中)
buf := new(bytes.Buffer)
zipWriter := zip.NewWriter(buf)
for filename, content := range certData {
if filename == "cert" || filename == "key" {
writer, err := zipWriter.Create(filename + ".pem")
if err != nil {
public.FailMsg(c, err.Error())
return
}
_, err = writer.Write([]byte(content))
if err != nil {
public.FailMsg(c, err.Error())
return
}
}
}
// 关闭 zipWriter
if err := zipWriter.Close(); err != nil {
public.FailMsg(c, err.Error())
return
}
// 设置响应头
zipName := strings.ReplaceAll(certData["domains"], ".", "_")
zipName = strings.ReplaceAll(zipName, ",", "-")
c.Header("Content-Type", "application/zip")
c.Header("Content-Disposition", "attachment; filename="+zipName+".zip")
c.Data(200, "application/zip", buf.Bytes())
return
}

162
backend/app/api/login.go Normal file
View File

@@ -0,0 +1,162 @@
package api
import (
"ALLinSSL/backend/public"
"crypto/md5"
"encoding/hex"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"strings"
"time"
)
func Sign(c *gin.Context) {
var form struct {
Username string `form:"username" binding:"required"`
Password string `form:"password" binding:"required"`
Code string `form:"code"`
}
err := c.Bind(&form)
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
// return
}
form.Username = strings.TrimSpace(form.Username)
form.Code = strings.TrimSpace(form.Code)
// 从数据库拿用户
s, err := public.NewSqlite("data/data.db", "")
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
s.Connect()
defer s.Close()
s.TableName = "users"
res, err := s.Where("username=?", []interface{}{form.Username}).Select()
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
session := sessions.Default(c)
now := time.Now()
loginErrCount := session.Get("__loginErrCount")
loginErrEnd := session.Get("__loginErrEnd")
ErrCount := 0
ErrEnd := now
// 获取登录错误次数
if __loginErrCount, ok := loginErrCount.(int); ok {
ErrCount = __loginErrCount
}
// 获取登录错误时间
if __loginErrEnd, ok := loginErrEnd.(time.Time); ok {
ErrEnd = __loginErrEnd
}
// fmt.Println(ErrCount, ErrEnd)
// 判断登录错误次数
switch {
case ErrCount >= 5:
// 登录错误次数超过5次15分钟内禁止登录
if now.Sub(ErrEnd) < 15*time.Minute {
// c.JSON(http.StatusBadRequest, public.ResERR("登录次数过多请15分钟后再试"))
public.FailMsg(c, "登录次数过多请15分钟后再试")
return
}
session.Delete("__loginErrEnd")
case ErrCount > 0:
if form.Code == "" {
// c.JSON(http.StatusBadRequest, public.ResERR("验证码错误1"))
public.FailMsg(c, "验证码错误1")
return
} else {
// 这里添加验证码的逻辑
verifyCode := session.Get("_verifyCode")
if _verifyCode, ok := verifyCode.(string); ok {
if !strings.EqualFold(form.Code, _verifyCode) {
// c.JSON(http.StatusBadRequest, public.ResERR("验证码错误2"))
public.FailMsg(c, "验证码错误2")
return
}
} else {
// c.JSON(http.StatusBadRequest, public.ResERR("验证码错误3"))
public.FailMsg(c, "验证码错误3")
return
}
}
}
// 判断用户是否存在
if len(res) == 0 {
session.Set("__loginErrCount", ErrCount+1)
session.Set("__loginErrEnd", now)
_ = session.Save()
// c.JSON(http.StatusBadRequest, public.ResERR("用户不存在"))
// 设置cookie
c.SetCookie("must_code", "1", 0, "/", "", false, true)
public.FailMsg(c, "用户不存在")
return
}
// 判断密码是否正确
// qSalt := "_bt_all_in_ssl"
// password := md5.Sum([]byte(form.Password + qSalt))
// passwordMd5 := hex.EncodeToString(password[:])
// fmt.Println(passwordMd5)
salt, ok := res[0]["salt"].(string)
if !ok {
salt = "_bt_all_in_ssl"
}
passwd := form.Password + salt
// fmt.Println(passwd)
keyMd5 := md5.Sum([]byte(passwd))
passwdMd5 := hex.EncodeToString(keyMd5[:])
// fmt.Println(passwdMd5)
if res[0]["password"] != passwdMd5 {
session.Set("__loginErrCount", ErrCount+1)
session.Set("__loginErrEnd", now)
_ = session.Save()
// c.JSON(http.StatusBadRequest, public.ResERR("密码错误"))
// 设置cookie
c.SetCookie("must_code", "1", 0, "/", "", false, false)
public.FailMsg(c, "密码错误")
return
}
// session := sessions.Default(c)
session.Set("__loginErrCount", 0)
session.Delete("__loginErrEnd")
session.Set("login", true)
session.Set("__login_key", public.GetSettingIgnoreError("login_key"))
_ = session.Save()
// c.JSON(http.StatusOK, public.ResOK(0, nil, "登录成功"))
// 设置cookie
c.SetCookie("must_code", "1", -1, "/", "", false, true)
public.SuccessMsg(c, "登录成功")
return
}
func GetCode(c *gin.Context) {
_, bs64, code, _ := public.GenerateCode()
session := sessions.Default(c)
session.Set("_verifyCode", code)
_ = session.Save()
public.SuccessData(c, bs64, 0)
return
}
func SignOut(c *gin.Context) {
session := sessions.Default(c)
session.Delete("login")
_ = session.Save()
// c.JSON(http.StatusOK, public.ResOK(0, nil, "登出成功"))
public.SuccessMsg(c, "登出成功")
return
}

View File

@@ -0,0 +1,20 @@
package api
import (
"ALLinSSL/backend/internal/overview"
"ALLinSSL/backend/public"
"github.com/gin-gonic/gin"
)
func GetOverview(c *gin.Context) {
// Get the overview data from the database
overviewData, err := overview.GetOverviewData()
if err != nil {
public.FailMsg(c, err.Error())
return
}
// Return the overview data as JSON
public.SuccessData(c, overviewData, 0)
}

102
backend/app/api/report.go Normal file
View File

@@ -0,0 +1,102 @@
package api
import (
"ALLinSSL/backend/internal/report"
"ALLinSSL/backend/public"
"github.com/gin-gonic/gin"
)
func GetReportList(c *gin.Context) {
var form struct {
Search string `form:"search"`
Page int64 `form:"p"`
Limit int64 `form:"limit"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
certList, count, err := report.GetList(form.Search, form.Page, form.Limit)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessData(c, certList, count)
return
}
func AddReport(c *gin.Context) {
var form struct {
Name string `form:"name"`
Type string `form:"type"`
Config string `form:"config"`
}
err := c.Bind(&form)
if err != nil {
// fmt.Println(err)
public.FailMsg(c, err.Error())
return
}
err = report.AddReport(form.Type, form.Config, form.Name)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "添加成功")
return
}
func UpdReport(c *gin.Context) {
var form struct {
Id string `form:"id"`
Name string `form:"name"`
Config string `form:"config"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
err = report.UpdReport(form.Id, form.Config, form.Name)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "修改成功")
return
}
func DelReport(c *gin.Context) {
var form struct {
Id string `form:"id"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
err = report.DelReport(form.Id)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "删除成功")
}
func NotifyTest(c *gin.Context) {
var form struct {
Id string `form:"id"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
err = report.NotifyTest(form.Id)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "发送成功")
}

View File

@@ -0,0 +1,40 @@
package api
import (
"ALLinSSL/backend/internal/setting"
"ALLinSSL/backend/public"
"github.com/gin-gonic/gin"
)
func GetSetting(c *gin.Context) {
data, err := setting.Get()
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessData(c, data, 0)
}
func SaveSetting(c *gin.Context) {
var data setting.Setting
if err := c.Bind(&data); err != nil {
public.FailMsg(c, "参数错误")
return
}
if err := setting.Save(&data); err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "保存成功")
}
func Shutdown(c *gin.Context) {
setting.Shutdown()
public.SuccessMsg(c, "关闭成功")
}
func Restart(c *gin.Context) {
setting.Restart()
public.SuccessMsg(c, "正在重启...")
}

View File

@@ -0,0 +1,131 @@
package api
import (
"ALLinSSL/backend/internal/siteMonitor"
"ALLinSSL/backend/public"
"github.com/gin-gonic/gin"
"strings"
)
func GetMonitorList(c *gin.Context) {
var form struct {
Search string `form:"search"`
Page int64 `form:"p"`
Limit int64 `form:"limit"`
}
err := c.Bind(&form)
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
data, count, err := siteMonitor.GetList(form.Search, form.Page, form.Limit)
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
// c.JSON(http.StatusOK, public.ResOK(len(data), data, ""))
public.SuccessData(c, data, count)
return
}
func AddMonitor(c *gin.Context) {
var form struct {
Name string `form:"name"`
Domain string `form:"domain"`
Cycle int `form:"cycle"`
ReportType string `form:"report_type"`
}
err := c.Bind(&form)
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
form.Name = strings.TrimSpace(form.Name)
form.Domain = strings.TrimSpace(form.Domain)
err = siteMonitor.AddMonitor(form.Name, form.Domain, form.ReportType, form.Cycle)
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
// c.JSON(http.StatusOK, public.ResOK(0, nil, "添加成功"))
public.SuccessMsg(c, "添加成功")
return
}
func UpdMonitor(c *gin.Context) {
var form struct {
ID string `form:"id"`
Name string `form:"name"`
Domain string `form:"domain"`
Cycle int `form:"cycle"`
ReportType string `form:"report_type"`
}
err := c.Bind(&form)
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
form.ID = strings.TrimSpace(form.ID)
form.Name = strings.TrimSpace(form.Name)
form.Domain = strings.TrimSpace(form.Domain)
form.ReportType = strings.TrimSpace(form.ReportType)
err = siteMonitor.UpdMonitor(form.ID, form.Name, form.Domain, form.ReportType, form.Cycle)
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
// c.JSON(http.StatusOK, public.ResOK(0, nil, "修改成功"))
public.SuccessMsg(c, "修改成功")
return
}
func DelMonitor(c *gin.Context) {
var form struct {
ID string `form:"id"`
}
err := c.Bind(&form)
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
err = siteMonitor.DelMonitor(form.ID)
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
// c.JSON(http.StatusOK, public.ResOK(0, nil, "删除成功"))
public.SuccessMsg(c, "删除成功")
return
}
func SetMonitor(c *gin.Context) {
var form struct {
ID string `form:"id"`
Active int `form:"active"`
}
err := c.Bind(&form)
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
err = siteMonitor.SetMonitor(form.ID, form.Active)
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
// c.JSON(http.StatusOK, public.ResOK(0, nil, "操作成功"))
public.SuccessMsg(c, "操作成功")
return
}

236
backend/app/api/workflow.go Normal file
View File

@@ -0,0 +1,236 @@
package api
import (
"ALLinSSL/backend/internal/workflow"
"ALLinSSL/backend/public"
"github.com/gin-gonic/gin"
"strings"
)
func GetWorkflowList(c *gin.Context) {
var form struct {
Search string `form:"search"`
Page int64 `form:"p"`
Limit int64 `form:"limit"`
}
err := c.Bind(&form)
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
data, count, err := workflow.GetList(form.Search, form.Page, form.Limit)
if err != nil {
// c.JSON(http.StatusBadRequest, public.ResERR(err.Error()))
public.FailMsg(c, err.Error())
return
}
// c.JSON(http.StatusOK, public.ResOK(len(data), data, ""))
public.SuccessData(c, data, count)
return
}
func AddWorkflow(c *gin.Context) {
var form struct {
Name string `form:"name"`
Content string `form:"content"`
ExecType string `form:"exec_type"`
Active string `form:"active"`
ExecTime string `form:"exec_time"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
form.Name = strings.TrimSpace(form.Name)
form.ExecType = strings.TrimSpace(form.ExecType)
err = workflow.AddWorkflow(form.Name, form.Content, form.ExecType, form.Active, form.ExecTime)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "添加成功")
return
}
func DelWorkflow(c *gin.Context) {
var form struct {
ID string `form:"id"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
form.ID = strings.TrimSpace(form.ID)
err = workflow.DelWorkflow(form.ID)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "删除成功")
return
}
func UpdWorkflow(c *gin.Context) {
var form struct {
ID string `form:"id"`
Name string `form:"name"`
Content string `form:"content"`
ExecType string `form:"exec_type"`
Active string `form:"active"`
ExecTime string `form:"exec_time"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
form.ID = strings.TrimSpace(form.ID)
form.Name = strings.TrimSpace(form.Name)
form.ExecType = strings.TrimSpace(form.ExecType)
err = workflow.UpdWorkflow(form.ID, form.Name, form.Content, form.ExecType, form.Active, form.ExecTime)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "修改成功")
return
}
func UpdExecType(c *gin.Context) {
var form struct {
ID string `form:"id"`
ExecType string `form:"exec_type"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
form.ID = strings.TrimSpace(form.ID)
form.ExecType = strings.TrimSpace(form.ExecType)
err = workflow.UpdExecType(form.ID, form.ExecType)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "修改成功")
return
}
func UpdActive(c *gin.Context) {
var form struct {
ID string `form:"id"`
Active string `form:"active"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
form.ID = strings.TrimSpace(form.ID)
form.Active = strings.TrimSpace(form.Active)
if form.ID == "" {
public.FailMsg(c, "ID不能为空")
return
}
err = workflow.UpdActive(form.ID, form.Active)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "修改成功")
return
}
func ExecuteWorkflow(c *gin.Context) {
var form struct {
ID string `form:"id"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
form.ID = strings.TrimSpace(form.ID)
err = workflow.ExecuteWorkflow(form.ID)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "执行成功")
return
}
func StopWorkflow(c *gin.Context) {
var form struct {
ID string `form:"id"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
form.ID = strings.TrimSpace(form.ID)
err = workflow.StopWorkflow(form.ID)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "停止成功")
return
}
func GetWorkflowHistory(c *gin.Context) {
var form struct {
ID string `form:"id"`
Page int64 `form:"p"`
Limit int64 `form:"limit"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
form.ID = strings.TrimSpace(form.ID)
data, count, err := workflow.GetListWH(form.ID, form.Page, form.Limit)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessData(c, data, count)
return
}
func GetExecLog(c *gin.Context) {
var form struct {
ID string `form:"id"`
}
err := c.Bind(&form)
if err != nil {
public.FailMsg(c, err.Error())
return
}
form.ID = strings.TrimSpace(form.ID)
data, err := workflow.GetExecLog(form.ID)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessData(c, data, 0)
return
}