Просмотр исходного кода

feat: Add PostgreSQL support and refactor MySQL DSN handling (#284)

lejianwen месяцев назад: 7
Родитель
Сommit
60b7a18fe7
8 измененных файлов с 142 добавлено и 39 удалено
  1. 36 7
      cmd/apimain.go
  2. 11 1
      conf/config.yaml
  3. 15 14
      config/config.go
  4. 13 2
      config/gorm.go
  5. 16 7
      go.mod
  6. 4 5
      lib/orm/mysql.go
  7. 45 0
      lib/orm/postgresql.go
  8. 2 3
      lib/orm/sqlite.go

+ 36 - 7
cmd/apimain.go

@@ -1,6 +1,7 @@
1
 package main
1
 package main
2
 
2
 
3
 import (
3
 import (
4
+	"fmt"
4
 	"github.com/go-redis/redis/v8"
5
 	"github.com/go-redis/redis/v8"
5
 	"github.com/lejianwen/rustdesk-api/v2/config"
6
 	"github.com/lejianwen/rustdesk-api/v2/config"
6
 	"github.com/lejianwen/rustdesk-api/v2/global"
7
 	"github.com/lejianwen/rustdesk-api/v2/global"
@@ -140,18 +141,40 @@ func InitGlobal() {
140
 	}
141
 	}
141
 	//gorm
142
 	//gorm
142
 	if global.Config.Gorm.Type == config.TypeMysql {
143
 	if global.Config.Gorm.Type == config.TypeMysql {
143
-		dns := global.Config.Mysql.Username + ":" + global.Config.Mysql.Password + "@(" + global.Config.Mysql.Addr + ")/" + global.Config.Mysql.Dbname + "?charset=utf8mb4&parseTime=True&loc=Local"
144
+
145
+		dsn := fmt.Sprintf("%s:%s@(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
146
+			global.Config.Mysql.Username,
147
+			global.Config.Mysql.Password,
148
+			global.Config.Mysql.Addr,
149
+			global.Config.Mysql.Dbname,
150
+		)
151
+
144
 		global.DB = orm.NewMysql(&orm.MysqlConfig{
152
 		global.DB = orm.NewMysql(&orm.MysqlConfig{
145
-			Dns:          dns,
153
+			Dsn:          dsn,
146
 			MaxIdleConns: global.Config.Gorm.MaxIdleConns,
154
 			MaxIdleConns: global.Config.Gorm.MaxIdleConns,
147
 			MaxOpenConns: global.Config.Gorm.MaxOpenConns,
155
 			MaxOpenConns: global.Config.Gorm.MaxOpenConns,
148
-		})
156
+		}, global.Logger)
157
+	} else if global.Config.Gorm.Type == config.TypePostgresql {
158
+		dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s TimeZone=%s",
159
+			global.Config.Postgresql.Host,
160
+			global.Config.Postgresql.Port,
161
+			global.Config.Postgresql.User,
162
+			global.Config.Postgresql.Password,
163
+			global.Config.Postgresql.Dbname,
164
+			global.Config.Postgresql.Sslmode,
165
+			global.Config.Postgresql.TimeZone,
166
+		)
167
+		global.DB = orm.NewPostgresql(&orm.PostgresqlConfig{
168
+			Dsn:          dsn,
169
+			MaxIdleConns: global.Config.Gorm.MaxIdleConns,
170
+			MaxOpenConns: global.Config.Gorm.MaxOpenConns,
171
+		}, global.Logger)
149
 	} else {
172
 	} else {
150
 		//sqlite
173
 		//sqlite
151
 		global.DB = orm.NewSqlite(&orm.SqliteConfig{
174
 		global.DB = orm.NewSqlite(&orm.SqliteConfig{
152
 			MaxIdleConns: global.Config.Gorm.MaxIdleConns,
175
 			MaxIdleConns: global.Config.Gorm.MaxIdleConns,
153
 			MaxOpenConns: global.Config.Gorm.MaxOpenConns,
176
 			MaxOpenConns: global.Config.Gorm.MaxOpenConns,
154
-		})
177
+		}, global.Logger)
155
 	}
178
 	}
156
 
179
 
157
 	//validator
180
 	//validator
@@ -197,11 +220,17 @@ func DatabaseAutoUpdate() {
197
 		if dbName == "" {
220
 		if dbName == "" {
198
 			dbName = global.Config.Mysql.Dbname
221
 			dbName = global.Config.Mysql.Dbname
199
 			// 移除 DSN 中的数据库名称,以便初始连接时不指定数据库
222
 			// 移除 DSN 中的数据库名称,以便初始连接时不指定数据库
200
-			dsnWithoutDB := global.Config.Mysql.Username + ":" + global.Config.Mysql.Password + "@(" + global.Config.Mysql.Addr + ")/?charset=utf8mb4&parseTime=True&loc=Local"
223
+			dsnWithoutDB := fmt.Sprintf("%s:%s@(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
224
+				global.Config.Mysql.Username,
225
+				global.Config.Mysql.Password,
226
+				global.Config.Mysql.Addr,
227
+				"",
228
+			)
229
+
201
 			//新链接
230
 			//新链接
202
 			dbWithoutDB := orm.NewMysql(&orm.MysqlConfig{
231
 			dbWithoutDB := orm.NewMysql(&orm.MysqlConfig{
203
-				Dns: dsnWithoutDB,
204
-			})
232
+				Dsn: dsnWithoutDB,
233
+			}, global.Logger)
205
 			// 获取底层的 *sql.DB 对象,并确保在程序退出时关闭连接
234
 			// 获取底层的 *sql.DB 对象,并确保在程序退出时关闭连接
206
 			sqlDBWithoutDB, err := dbWithoutDB.DB()
235
 			sqlDBWithoutDB, err := dbWithoutDB.DB()
207
 			if err != nil {
236
 			if err != nil {

+ 11 - 1
conf/config.yaml

@@ -11,7 +11,7 @@ app:
11
   disable-pwd-login: false #禁用密码登录
11
   disable-pwd-login: false #禁用密码登录
12
 
12
 
13
 admin:
13
 admin:
14
-  title: "RustDesk Api Admin"
14
+  title: "RustDesk API Admin"
15
   hello-file: "./conf/admin/hello.html"  #优先使用file
15
   hello-file: "./conf/admin/hello.html"  #优先使用file
16
   hello: ""
16
   hello: ""
17
   # ID Server and Relay Server ports https://github.com/lejianwen/rustdesk-api/issues/257
17
   # ID Server and Relay Server ports https://github.com/lejianwen/rustdesk-api/issues/257
@@ -31,6 +31,16 @@ mysql:
31
   password: ""
31
   password: ""
32
   addr: ""
32
   addr: ""
33
   dbname: ""
33
   dbname: ""
34
+
35
+postgresql:
36
+  host: "127.0.0.1"
37
+  port: "5432"
38
+  user: ""
39
+  password: ""
40
+  dbname: "postgres"
41
+  sslmode: "disable" # disable, require, verify-ca, verify-full
42
+  time-zone: "Asia/Shanghai" # Time zone for PostgreSQL connection
43
+
34
 rustdesk:
44
 rustdesk:
35
   id-server: "192.168.1.66:21116"
45
   id-server: "192.168.1.66:21116"
36
   relay-server: "192.168.1.66:21117"
46
   relay-server: "192.168.1.66:21117"

+ 15 - 14
config/config.go

@@ -32,20 +32,21 @@ type Admin struct {
32
 	RelayServerPort int    `mapstructure:"relay-server-port"`
32
 	RelayServerPort int    `mapstructure:"relay-server-port"`
33
 }
33
 }
34
 type Config struct {
34
 type Config struct {
35
-	Lang     string `mapstructure:"lang"`
36
-	App      App
37
-	Admin    Admin
38
-	Gorm     Gorm
39
-	Mysql    Mysql
40
-	Gin      Gin
41
-	Logger   Logger
42
-	Redis    Redis
43
-	Cache    Cache
44
-	Oss      Oss
45
-	Jwt      Jwt
46
-	Rustdesk Rustdesk
47
-	Proxy    Proxy
48
-	Ldap     Ldap
35
+	Lang       string `mapstructure:"lang"`
36
+	App        App
37
+	Admin      Admin
38
+	Gorm       Gorm
39
+	Mysql      Mysql
40
+	Postgresql Postgresql
41
+	Gin        Gin
42
+	Logger     Logger
43
+	Redis      Redis
44
+	Cache      Cache
45
+	Oss        Oss
46
+	Jwt        Jwt
47
+	Rustdesk   Rustdesk
48
+	Proxy      Proxy
49
+	Ldap       Ldap
49
 }
50
 }
50
 
51
 
51
 func (a *Admin) Init() {
52
 func (a *Admin) Init() {

+ 13 - 2
config/gorm.go

@@ -1,8 +1,9 @@
1
 package config
1
 package config
2
 
2
 
3
 const (
3
 const (
4
-	TypeSqlite = "sqlite"
5
-	TypeMysql  = "mysql"
4
+	TypeSqlite     = "sqlite"
5
+	TypeMysql      = "mysql"
6
+	TypePostgresql = "postgresql"
6
 )
7
 )
7
 
8
 
8
 type Gorm struct {
9
 type Gorm struct {
@@ -17,3 +18,13 @@ type Mysql struct {
17
 	Password string `mapstructure:"password"`
18
 	Password string `mapstructure:"password"`
18
 	Dbname   string `mapstructure:"dbname"`
19
 	Dbname   string `mapstructure:"dbname"`
19
 }
20
 }
21
+
22
+type Postgresql struct {
23
+	Host     string `mapstructure:"host"`
24
+	Port     string `mapstructure:"port"`
25
+	User     string `mapstructure:"user"`
26
+	Password string `mapstructure:"password"`
27
+	Dbname   string `mapstructure:"dbname"`
28
+	Sslmode  string `mapstructure:"sslmode"`   // "disable", "require", "verify-ca", "verify-full"
29
+	TimeZone string `mapstructure:"time-zone"` // e.g., "Asia/Shanghai"
30
+}

+ 16 - 7
go.mod

@@ -1,19 +1,23 @@
1
 module github.com/lejianwen/rustdesk-api/v2
1
 module github.com/lejianwen/rustdesk-api/v2
2
 
2
 
3
-go 1.22
3
+go 1.23
4
+
5
+toolchain go1.23.10
4
 
6
 
5
 require (
7
 require (
6
 	github.com/BurntSushi/toml v1.3.2
8
 	github.com/BurntSushi/toml v1.3.2
7
 	github.com/antonfisher/nested-logrus-formatter v1.3.1
9
 	github.com/antonfisher/nested-logrus-formatter v1.3.1
8
-	github.com/fsnotify/fsnotify v1.5.1
10
+	github.com/coreos/go-oidc/v3 v3.12.0
9
 	github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6
11
 	github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6
10
 	github.com/gin-gonic/gin v1.9.0
12
 	github.com/gin-gonic/gin v1.9.0
13
+	github.com/go-ldap/ldap/v3 v3.4.10
11
 	github.com/go-playground/locales v0.14.1
14
 	github.com/go-playground/locales v0.14.1
12
 	github.com/go-playground/universal-translator v0.18.1
15
 	github.com/go-playground/universal-translator v0.18.1
13
 	github.com/go-playground/validator/v10 v10.26.0
16
 	github.com/go-playground/validator/v10 v10.26.0
14
 	github.com/go-redis/redis/v8 v8.11.4
17
 	github.com/go-redis/redis/v8 v8.11.4
15
 	github.com/golang-jwt/jwt/v5 v5.2.1
18
 	github.com/golang-jwt/jwt/v5 v5.2.1
16
 	github.com/google/uuid v1.6.0
19
 	github.com/google/uuid v1.6.0
20
+	github.com/mojocn/base64Captcha v1.3.6
17
 	github.com/nicksnyder/go-i18n/v2 v2.4.0
21
 	github.com/nicksnyder/go-i18n/v2 v2.4.0
18
 	github.com/sirupsen/logrus v1.8.1
22
 	github.com/sirupsen/logrus v1.8.1
19
 	github.com/spf13/cobra v1.8.1
23
 	github.com/spf13/cobra v1.8.1
@@ -24,8 +28,9 @@ require (
24
 	golang.org/x/oauth2 v0.23.0
28
 	golang.org/x/oauth2 v0.23.0
25
 	golang.org/x/text v0.22.0
29
 	golang.org/x/text v0.22.0
26
 	gorm.io/driver/mysql v1.5.7
30
 	gorm.io/driver/mysql v1.5.7
31
+	gorm.io/driver/postgres v1.6.0
27
 	gorm.io/driver/sqlite v1.5.6
32
 	gorm.io/driver/sqlite v1.5.6
28
-	gorm.io/gorm v1.25.7
33
+	gorm.io/gorm v1.25.10
29
 )
34
 )
30
 
35
 
31
 require (
36
 require (
@@ -36,13 +41,12 @@ require (
36
 	github.com/bytedance/sonic v1.8.0 // indirect
41
 	github.com/bytedance/sonic v1.8.0 // indirect
37
 	github.com/cespare/xxhash/v2 v2.1.2 // indirect
42
 	github.com/cespare/xxhash/v2 v2.1.2 // indirect
38
 	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
43
 	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
39
-	github.com/coreos/go-oidc/v3 v3.12.0 // indirect
40
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
44
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
45
+	github.com/fsnotify/fsnotify v1.5.1 // indirect
41
 	github.com/gabriel-vasile/mimetype v1.4.8 // indirect
46
 	github.com/gabriel-vasile/mimetype v1.4.8 // indirect
42
 	github.com/gin-contrib/sse v0.1.0 // indirect
47
 	github.com/gin-contrib/sse v0.1.0 // indirect
43
 	github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
48
 	github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
44
 	github.com/go-jose/go-jose/v4 v4.0.2 // indirect
49
 	github.com/go-jose/go-jose/v4 v4.0.2 // indirect
45
-	github.com/go-ldap/ldap/v3 v3.4.10 // indirect
46
 	github.com/go-openapi/jsonpointer v0.19.5 // indirect
50
 	github.com/go-openapi/jsonpointer v0.19.5 // indirect
47
 	github.com/go-openapi/jsonreference v0.19.6 // indirect
51
 	github.com/go-openapi/jsonreference v0.19.6 // indirect
48
 	github.com/go-openapi/spec v0.20.4 // indirect
52
 	github.com/go-openapi/spec v0.20.4 // indirect
@@ -52,6 +56,10 @@ require (
52
 	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
56
 	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
53
 	github.com/hashicorp/hcl v1.0.0 // indirect
57
 	github.com/hashicorp/hcl v1.0.0 // indirect
54
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
58
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
59
+	github.com/jackc/pgpassfile v1.0.0 // indirect
60
+	github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
61
+	github.com/jackc/pgx/v5 v5.6.0 // indirect
62
+	github.com/jackc/puddle/v2 v2.2.2 // indirect
55
 	github.com/jinzhu/inflection v1.0.0 // indirect
63
 	github.com/jinzhu/inflection v1.0.0 // indirect
56
 	github.com/jinzhu/now v1.1.5 // indirect
64
 	github.com/jinzhu/now v1.1.5 // indirect
57
 	github.com/josharian/intern v1.0.0 // indirect
65
 	github.com/josharian/intern v1.0.0 // indirect
@@ -65,9 +73,9 @@ require (
65
 	github.com/mitchellh/mapstructure v1.4.2 // indirect
73
 	github.com/mitchellh/mapstructure v1.4.2 // indirect
66
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
74
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
67
 	github.com/modern-go/reflect2 v1.0.2 // indirect
75
 	github.com/modern-go/reflect2 v1.0.2 // indirect
68
-	github.com/mojocn/base64Captcha v1.3.6 // indirect
69
 	github.com/pelletier/go-toml v1.9.4 // indirect
76
 	github.com/pelletier/go-toml v1.9.4 // indirect
70
 	github.com/pelletier/go-toml/v2 v2.0.6 // indirect
77
 	github.com/pelletier/go-toml/v2 v2.0.6 // indirect
78
+	github.com/rogpeppe/go-internal v1.14.1 // indirect
71
 	github.com/spf13/afero v1.6.0 // indirect
79
 	github.com/spf13/afero v1.6.0 // indirect
72
 	github.com/spf13/cast v1.4.1 // indirect
80
 	github.com/spf13/cast v1.4.1 // indirect
73
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
81
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
@@ -79,8 +87,9 @@ require (
79
 	golang.org/x/crypto v0.33.0 // indirect
87
 	golang.org/x/crypto v0.33.0 // indirect
80
 	golang.org/x/image v0.13.0 // indirect
88
 	golang.org/x/image v0.13.0 // indirect
81
 	golang.org/x/net v0.34.0 // indirect
89
 	golang.org/x/net v0.34.0 // indirect
90
+	golang.org/x/sync v0.11.0 // indirect
82
 	golang.org/x/sys v0.30.0 // indirect
91
 	golang.org/x/sys v0.30.0 // indirect
83
-	golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
92
+	golang.org/x/tools v0.26.0 // indirect
84
 	google.golang.org/protobuf v1.33.0 // indirect
93
 	google.golang.org/protobuf v1.33.0 // indirect
85
 	gopkg.in/ini.v1 v1.63.2 // indirect
94
 	gopkg.in/ini.v1 v1.63.2 // indirect
86
 	gopkg.in/yaml.v2 v2.4.0 // indirect
95
 	gopkg.in/yaml.v2 v2.4.0 // indirect

+ 4 - 5
lib/orm/mysql.go

@@ -2,7 +2,6 @@ package orm
2
 
2
 
3
 import (
3
 import (
4
 	"fmt"
4
 	"fmt"
5
-	"github.com/lejianwen/rustdesk-api/v2/global"
6
 	"gorm.io/driver/mysql"
5
 	"gorm.io/driver/mysql"
7
 	"gorm.io/gorm"
6
 	"gorm.io/gorm"
8
 	"gorm.io/gorm/logger"
7
 	"gorm.io/gorm/logger"
@@ -10,14 +9,14 @@ import (
10
 )
9
 )
11
 
10
 
12
 type MysqlConfig struct {
11
 type MysqlConfig struct {
13
-	Dns          string
12
+	Dsn          string
14
 	MaxIdleConns int
13
 	MaxIdleConns int
15
 	MaxOpenConns int
14
 	MaxOpenConns int
16
 }
15
 }
17
 
16
 
18
-func NewMysql(mysqlConf *MysqlConfig) *gorm.DB {
17
+func NewMysql(mysqlConf *MysqlConfig, logwriter logger.Writer) *gorm.DB {
19
 	db, err := gorm.Open(mysql.New(mysql.Config{
18
 	db, err := gorm.Open(mysql.New(mysql.Config{
20
-		DSN:               mysqlConf.Dns, // DSN data source name
19
+		DSN:               mysqlConf.Dsn, // DSN data source name
21
 		DefaultStringSize: 256,           // string 类型字段的默认长度
20
 		DefaultStringSize: 256,           // string 类型字段的默认长度
22
 		//DisableDatetimePrecision:  true,                    // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
21
 		//DisableDatetimePrecision:  true,                    // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
23
 		//DontSupportRenameIndex:    true,                    // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
22
 		//DontSupportRenameIndex:    true,                    // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
@@ -26,7 +25,7 @@ func NewMysql(mysqlConf *MysqlConfig) *gorm.DB {
26
 	}), &gorm.Config{
25
 	}), &gorm.Config{
27
 		DisableForeignKeyConstraintWhenMigrating: true,
26
 		DisableForeignKeyConstraintWhenMigrating: true,
28
 		Logger: logger.New(
27
 		Logger: logger.New(
29
-			global.Logger, // io writer
28
+			logwriter, // io writer
30
 			logger.Config{
29
 			logger.Config{
31
 				SlowThreshold:             time.Second, // Slow SQL threshold
30
 				SlowThreshold:             time.Second, // Slow SQL threshold
32
 				LogLevel:                  logger.Warn, // Log level
31
 				LogLevel:                  logger.Warn, // Log level

+ 45 - 0
lib/orm/postgresql.go

@@ -0,0 +1,45 @@
1
+package orm
2
+
3
+import (
4
+	"fmt"
5
+	"gorm.io/driver/postgres"
6
+	"gorm.io/gorm"
7
+	"gorm.io/gorm/logger"
8
+	"time"
9
+)
10
+
11
+type PostgresqlConfig struct {
12
+	Dsn          string
13
+	MaxIdleConns int
14
+	MaxOpenConns int
15
+}
16
+
17
+func NewPostgresql(conf *PostgresqlConfig, logwriter logger.Writer) *gorm.DB {
18
+	db, err := gorm.Open(postgres.Open(conf.Dsn), &gorm.Config{
19
+		DisableForeignKeyConstraintWhenMigrating: true,
20
+		Logger: logger.New(
21
+			logwriter, // io writer
22
+			logger.Config{
23
+				SlowThreshold: time.Second, // Slow SQL threshold
24
+				LogLevel:      logger.Warn, // Log level
25
+				//IgnoreRecordNotFoundError: true,        // Ignore ErrRecordNotFound error for logger
26
+				ParameterizedQueries: true, // Don't include params in the SQL log
27
+				Colorful:             true,
28
+			},
29
+		),
30
+	})
31
+	if err != nil {
32
+		fmt.Println(err)
33
+	}
34
+	sqlDB, err2 := db.DB()
35
+	if err2 != nil {
36
+		fmt.Println(err2)
37
+	}
38
+	// SetMaxIdleConns 设置空闲连接池中连接的最大数量
39
+	sqlDB.SetMaxIdleConns(conf.MaxIdleConns)
40
+
41
+	// SetMaxOpenConns 设置打开数据库连接的最大数量。
42
+	sqlDB.SetMaxOpenConns(conf.MaxOpenConns)
43
+
44
+	return db
45
+}

+ 2 - 3
lib/orm/sqlite.go

@@ -2,7 +2,6 @@ package orm
2
 
2
 
3
 import (
3
 import (
4
 	"fmt"
4
 	"fmt"
5
-	"github.com/lejianwen/rustdesk-api/v2/global"
6
 	"gorm.io/driver/sqlite"
5
 	"gorm.io/driver/sqlite"
7
 	"gorm.io/gorm"
6
 	"gorm.io/gorm"
8
 	"gorm.io/gorm/logger"
7
 	"gorm.io/gorm/logger"
@@ -14,11 +13,11 @@ type SqliteConfig struct {
14
 	MaxOpenConns int
13
 	MaxOpenConns int
15
 }
14
 }
16
 
15
 
17
-func NewSqlite(sqliteConf *SqliteConfig) *gorm.DB {
16
+func NewSqlite(sqliteConf *SqliteConfig, logwriter logger.Writer) *gorm.DB {
18
 	db, err := gorm.Open(sqlite.Open("./data/rustdeskapi.db"), &gorm.Config{
17
 	db, err := gorm.Open(sqlite.Open("./data/rustdeskapi.db"), &gorm.Config{
19
 		DisableForeignKeyConstraintWhenMigrating: true,
18
 		DisableForeignKeyConstraintWhenMigrating: true,
20
 		Logger: logger.New(
19
 		Logger: logger.New(
21
-			global.Logger, // io writer
20
+			logwriter, // io writer
22
 			logger.Config{
21
 			logger.Config{
23
 				SlowThreshold:             time.Second, // Slow SQL threshold
22
 				SlowThreshold:             time.Second, // Slow SQL threshold
24
 				LogLevel:                  logger.Warn, // Log level
23
 				LogLevel:                  logger.Warn, // Log level