diff --git a/server/admin/api_other.go b/server/admin/api_other.go
index 00f926a..234a220 100644
--- a/server/admin/api_other.go
+++ b/server/admin/api_other.go
@@ -2,8 +2,10 @@ package admin
import (
"encoding/json"
+ "errors"
"io/ioutil"
"net/http"
+ "regexp"
"github.com/bjdgyc/anylink/dbdata"
)
@@ -60,3 +62,42 @@ func SetOtherEdit(w http.ResponseWriter, r *http.Request) {
data := &dbdata.SettingOther{}
setOtherEdit(data, w, r)
}
+
+func SetOtherAuditLog(w http.ResponseWriter, r *http.Request) {
+ data, err := dbdata.SettingGetAuditLog()
+ if err != nil {
+ RespError(w, RespInternalErr, err)
+ return
+ }
+ RespSucess(w, data)
+}
+
+func SetOtherAuditLogEdit(w http.ResponseWriter, r *http.Request) {
+ body, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ RespError(w, RespInternalErr, err)
+ return
+ }
+ defer r.Body.Close()
+ data := &dbdata.SettingAuditLog{}
+ err = json.Unmarshal(body, data)
+ if err != nil {
+ RespError(w, RespInternalErr, err)
+ return
+ }
+ if data.LifeDay < 0 || data.LifeDay > 365 {
+ RespError(w, RespParamErr, errors.New("日志存储时长范围在 0 ~ 365"))
+ return
+ }
+ ok, _ := regexp.Match("^([0-9]|0[0-9]|1[0-9]|2[0-3]):([0][0])$", []byte(data.ClearTime))
+ if !ok {
+ RespError(w, RespParamErr, errors.New("每天清理时间填写有误"))
+ return
+ }
+ err = dbdata.SettingSet(data)
+ if err != nil {
+ RespError(w, RespInternalErr, err)
+ return
+ }
+ RespSucess(w, data)
+}
diff --git a/server/admin/server.go b/server/admin/server.go
index 02675be..d4939e0 100644
--- a/server/admin/server.go
+++ b/server/admin/server.go
@@ -41,6 +41,8 @@ func StartAdmin() {
r.HandleFunc("/set/other/edit", SetOtherEdit)
r.HandleFunc("/set/other/smtp", SetOtherSmtp)
r.HandleFunc("/set/other/smtp/edit", SetOtherSmtpEdit)
+ r.HandleFunc("/set/other/audit_log", SetOtherAuditLog)
+ r.HandleFunc("/set/other/audit_log/edit", SetOtherAuditLogEdit)
r.HandleFunc("/set/audit/list", SetAuditList)
r.HandleFunc("/set/audit/export", SetAuditExport)
diff --git a/server/cron/clear_audit.go b/server/cron/clear_audit.go
new file mode 100644
index 0000000..34f114c
--- /dev/null
+++ b/server/cron/clear_audit.go
@@ -0,0 +1,20 @@
+package cron
+
+import (
+ "github.com/bjdgyc/anylink/base"
+ "github.com/bjdgyc/anylink/dbdata"
+)
+
+// 清除访问审计日志
+func ClearAudit() {
+ lifeDay, timesUp := isClearTime()
+ if !timesUp {
+ return
+ }
+ // 当审计日志永久保存,则退出
+ if lifeDay <= 0 {
+ return
+ }
+ affected, err := dbdata.ClearAccessAudit(getTimeAgo(lifeDay))
+ base.Info("Cron ClearAudit: ", affected, err)
+}
diff --git a/server/cron/clear_statsinfo.go b/server/cron/clear_statsinfo.go
new file mode 100644
index 0000000..11ecbd3
--- /dev/null
+++ b/server/cron/clear_statsinfo.go
@@ -0,0 +1,52 @@
+package cron
+
+import (
+ "time"
+
+ "github.com/bjdgyc/anylink/base"
+ "github.com/bjdgyc/anylink/dbdata"
+)
+
+const siLifeDay = 30
+
+// 清除图表数据
+func ClearStatsInfo() {
+ _, timesUp := isClearTime()
+ if !timesUp {
+ return
+ }
+ ts := getTimeAgo(siLifeDay)
+ for _, item := range dbdata.StatsInfoIns.Actions {
+ affected, err := dbdata.StatsInfoIns.ClearStatsInfo(item, ts)
+ base.Info("Cron ClearStatsInfo "+item+": ", affected, err)
+ }
+}
+
+// 是否到了"清理时间"
+func isClearTime() (int, bool) {
+ dataLog, err := dbdata.SettingGetAuditLog()
+ if err != nil {
+ base.Error("Cron SettingGetLog: ", err)
+ return -1, false
+ }
+ currentTime := time.Now().Format("15:04")
+ // 未到"清理时间"时, 则返回
+ if dataLog.ClearTime != currentTime {
+ return -1, false
+ }
+ return dataLog.LifeDay, true
+}
+
+// 根据存储时长,获取清理日期
+func getTimeAgo(days int) string {
+ var timeS string
+ ts := time.Now().AddDate(0, 0, -days)
+ tsZero := time.Date(ts.Year(), ts.Month(), ts.Day(), 0, 0, 0, 0, time.Local)
+ timeS = tsZero.Format(dbdata.LayoutTimeFormat)
+ // UTC
+ switch base.Cfg.DbType {
+ case "sqlite3", "postgres":
+ timeS = tsZero.UTC().Format(dbdata.LayoutTimeFormat)
+ }
+ return timeS
+}
diff --git a/server/cron/start.go b/server/cron/start.go
new file mode 100644
index 0000000..2692cfe
--- /dev/null
+++ b/server/cron/start.go
@@ -0,0 +1,14 @@
+package cron
+
+import (
+ "time"
+
+ "github.com/go-co-op/gocron"
+)
+
+func Start() {
+ s := gocron.NewScheduler(time.Local)
+ s.Cron("0 * * * *").Do(ClearAudit)
+ s.Cron("0 * * * *").Do(ClearStatsInfo)
+ s.StartAsync()
+}
diff --git a/server/dbdata/audit.go b/server/dbdata/audit.go
index dc7e49b..d54f315 100644
--- a/server/dbdata/audit.go
+++ b/server/dbdata/audit.go
@@ -49,3 +49,8 @@ func GetAuditSession(search string) *xorm.Session {
}
return session
}
+
+func ClearAccessAudit(ts string) (int64, error) {
+ affected, err := xdb.Where("created_at < '" + ts + "'").Delete(&AccessAudit{})
+ return affected, err
+}
diff --git a/server/dbdata/db.go b/server/dbdata/db.go
index 771820c..64f1ecc 100644
--- a/server/dbdata/db.go
+++ b/server/dbdata/db.go
@@ -87,6 +87,13 @@ func addInitData() error {
return err
}
+ // SettingAuditLog
+ auditLog := SettingGetAuditLogDefault()
+ err = SettingSessAdd(sess, auditLog)
+ if err != nil {
+ return err
+ }
+
// SettingOther
other := &SettingOther{
LinkAddr: "vpn.xx.com",
diff --git a/server/dbdata/setting.go b/server/dbdata/setting.go
index 4770401..964cb72 100644
--- a/server/dbdata/setting.go
+++ b/server/dbdata/setting.go
@@ -3,6 +3,7 @@ package dbdata
import (
"encoding/json"
"reflect"
+
"xorm.io/xorm"
)
@@ -19,6 +20,11 @@ type SettingSmtp struct {
Encryption string `json:"encryption"`
}
+type SettingAuditLog struct {
+ LifeDay int `json:"life_day"`
+ ClearTime string `json:"clear_time"`
+}
+
type SettingOther struct {
LinkAddr string `json:"link_addr"`
Banner string `json:"banner"`
@@ -64,3 +70,30 @@ func SettingGet(data interface{}) error {
err = json.Unmarshal(s.Data, data)
return err
}
+
+func SettingGetAuditLog() (SettingAuditLog, error) {
+ data := SettingAuditLog{}
+ err := SettingGet(&data)
+ if err == nil {
+ return data, err
+ }
+ if !CheckErrNotFound(err) {
+ return data, err
+ }
+ sess := xdb.NewSession()
+ defer sess.Close()
+ auditLog := SettingGetAuditLogDefault()
+ err = SettingSessAdd(sess, auditLog)
+ if err != nil {
+ return data, err
+ }
+ return auditLog, nil
+}
+
+func SettingGetAuditLogDefault() SettingAuditLog {
+ auditLog := SettingAuditLog{
+ LifeDay: 0,
+ ClearTime: "05:00",
+ }
+ return auditLog
+}
diff --git a/server/dbdata/statsinfo.go b/server/dbdata/statsinfo.go
index 21eb583..cef60be 100644
--- a/server/dbdata/statsinfo.go
+++ b/server/dbdata/statsinfo.go
@@ -237,3 +237,17 @@ func (s *StatsInfo) getStatsWhere(sd *ScopeDetail) (where string) {
}
return
}
+
+func (s *StatsInfo) ClearStatsInfo(action string, ts string) (affected int64, err error) {
+ switch action {
+ case "online":
+ affected, err = xdb.Where("created_at < '" + ts + "'").Delete(&StatsOnline{})
+ case "network":
+ affected, err = xdb.Where("created_at < '" + ts + "'").Delete(&StatsNetwork{})
+ case "cpu":
+ affected, err = xdb.Where("created_at < '" + ts + "'").Delete(&StatsCpu{})
+ case "mem":
+ affected, err = xdb.Where("created_at < '" + ts + "'").Delete(&StatsMem{})
+ }
+ return affected, err
+}
diff --git a/server/go.mod b/server/go.mod
index d77fc96..9f361f8 100644
--- a/server/go.mod
+++ b/server/go.mod
@@ -4,6 +4,7 @@ go 1.18
require (
github.com/arl/statsviz v0.5.1
+ github.com/go-co-op/gocron v1.17.0
github.com/go-ldap/ldap v3.0.3+incompatible
github.com/go-sql-driver/mysql v1.6.0
github.com/gocarina/gocsv v0.0.0-20220712153207-8b2118da4570
@@ -23,7 +24,7 @@ require (
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
github.com/spf13/cobra v1.2.1
github.com/spf13/viper v1.8.1
- github.com/stretchr/testify v1.7.0
+ github.com/stretchr/testify v1.8.0
github.com/xhit/go-simple-mail/v2 v2.10.0
github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119
go.uber.org/atomic v1.10.0
@@ -54,6 +55,7 @@ require (
github.com/pion/transport v0.13.0 // indirect
github.com/pion/udp v0.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/spf13/afero v1.6.0 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
@@ -62,11 +64,12 @@ require (
github.com/syndtr/goleveldb v1.0.0 // indirect
github.com/tklauser/go-sysconf v0.3.7 // indirect
github.com/tklauser/numcpus v0.2.3 // indirect
+ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
- gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
xorm.io/builder v0.3.9 // indirect
)
diff --git a/server/go.sum b/server/go.sum
index 63efb0f..aa2f83a 100644
--- a/server/go.sum
+++ b/server/go.sum
@@ -123,6 +123,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-co-op/gocron v1.17.0 h1:IixLXsti+Qo0wMvmn6Kmjp2csk2ykpkcL+EmHmST18w=
+github.com/go-co-op/gocron v1.17.0/go.mod h1:IpDBSaJOVfFw7hXZuTag3SCSkqazXBBUkbQ1m1aesBs=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -460,6 +462,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
+github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -512,13 +516,16 @@ github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5J
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
@@ -696,6 +703,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -981,8 +989,9 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/server/handler/start.go b/server/handler/start.go
index 117fa28..4eeba14 100644
--- a/server/handler/start.go
+++ b/server/handler/start.go
@@ -7,6 +7,7 @@ import (
"github.com/bjdgyc/anylink/admin"
"github.com/bjdgyc/anylink/base"
+ "github.com/bjdgyc/anylink/cron"
"github.com/bjdgyc/anylink/dbdata"
"github.com/bjdgyc/anylink/sessdata"
)
@@ -14,6 +15,7 @@ import (
func Start() {
dbdata.Start()
sessdata.Start()
+ cron.Start()
switch base.Cfg.LinkMode {
case base.LinkModeTUN:
diff --git a/web/src/pages/set/Other.vue b/web/src/pages/set/Other.vue
index 8c518c7..d1ca281 100644
--- a/web/src/pages/set/Other.vue
+++ b/web/src/pages/set/Other.vue
@@ -32,6 +32,32 @@
+
+
+
+ 天
+ 范围: 0 ~ 365天 , 0 代表永久保存
+
+
+
+
+
+
+ 保存
+ 重置
+
+
+
@@ -104,6 +130,7 @@ export default {
return {
activeName: 'dataSmtp',
dataSmtp: {},
+ dataAuditLog: {},
dataOther: {},
rules: {
host: {required: true, message: '请输入服务器地址', trigger: 'blur'},
@@ -122,9 +149,12 @@ export default {
case "dataSmtp":
this.getSmtp()
break
+ case "dataAuditLog":
+ this.getAuditLog()
+ break
case "dataOther":
this.getOther()
- break
+ break
}
},
getSmtp() {
@@ -141,6 +171,20 @@ export default {
console.log(error);
});
},
+ getAuditLog() {
+ axios.get('/set/other/audit_log').then(resp => {
+ let rdata = resp.data
+ console.log(rdata)
+ if (rdata.code !== 0) {
+ this.$message.error(rdata.msg);
+ return;
+ }
+ this.dataAuditLog = rdata.data
+ }).catch(error => {
+ this.$message.error('哦,请求出错');
+ console.log(error);
+ });
+ },
getOther() {
axios.get('/set/other').then(resp => {
let rdata = resp.data
@@ -174,6 +218,17 @@ export default {
})
break;
+ case "dataAuditLog":
+ axios.post('/set/other/audit_log/edit', this.dataAuditLog).then(resp => {
+ var rdata = resp.data
+ console.log(rdata);
+ if (rdata.code === 0) {
+ this.$message.success(rdata.msg);
+ } else {
+ this.$message.error(rdata.msg);
+ }
+ })
+ break;
case "dataOther":
axios.post('/set/other/edit', this.dataOther).then(resp => {
var rdata = resp.data
@@ -201,4 +256,9 @@ export default {
width: 600px;
}
+.input_tip {
+ line-height: 1.428;
+ margin:2px 0 0 0;
+}
+