Fix MySQL DSN escaping for setup passwords and clarify DB user setup
This commit is contained in:
@@ -2,9 +2,12 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
mysqlDriver "github.com/go-sql-driver/mysql"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -39,8 +42,18 @@ type DatabaseConfig struct {
|
||||
}
|
||||
|
||||
func (d *DatabaseConfig) DSN() string {
|
||||
return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
|
||||
d.User, d.Password, d.Host, d.Port, d.Name)
|
||||
cfg := mysqlDriver.NewConfig()
|
||||
cfg.User = d.User
|
||||
cfg.Passwd = d.Password
|
||||
cfg.Net = "tcp"
|
||||
cfg.Addr = net.JoinHostPort(d.Host, strconv.Itoa(d.Port))
|
||||
cfg.DBName = d.Name
|
||||
cfg.ParseTime = true
|
||||
cfg.Loc = time.Local
|
||||
cfg.Params = map[string]string{
|
||||
"charset": "utf8mb4",
|
||||
}
|
||||
return cfg.FormatDSN()
|
||||
}
|
||||
|
||||
type AuthConfig struct {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -13,8 +14,9 @@ import (
|
||||
qfassets "git.mchus.pro/mchus/quoteforge"
|
||||
"git.mchus.pro/mchus/quoteforge/internal/db"
|
||||
"git.mchus.pro/mchus/quoteforge/internal/localdb"
|
||||
mysqlDriver "github.com/go-sql-driver/mysql"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/driver/mysql"
|
||||
gormmysql "gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
@@ -93,10 +95,9 @@ func (h *SetupHandler) TestConnection(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=5s",
|
||||
user, password, host, port, database)
|
||||
dsn := buildMySQLDSN(host, port, database, user, password, 5*time.Second)
|
||||
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||
db, err := gorm.Open(gormmysql.Open(dsn), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Silent),
|
||||
})
|
||||
if err != nil {
|
||||
@@ -169,10 +170,9 @@ func (h *SetupHandler) SaveConnection(c *gin.Context) {
|
||||
}
|
||||
|
||||
// Test connection first
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=5s",
|
||||
user, password, host, port, database)
|
||||
dsn := buildMySQLDSN(host, port, database, user, password, 5*time.Second)
|
||||
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||
db, err := gorm.Open(gormmysql.Open(dsn), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Silent),
|
||||
})
|
||||
if err != nil {
|
||||
@@ -254,3 +254,19 @@ func testWritePermission(db *gorm.DB) bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func buildMySQLDSN(host string, port int, database, user, password string, timeout time.Duration) string {
|
||||
cfg := mysqlDriver.NewConfig()
|
||||
cfg.User = user
|
||||
cfg.Passwd = password
|
||||
cfg.Net = "tcp"
|
||||
cfg.Addr = net.JoinHostPort(host, strconv.Itoa(port))
|
||||
cfg.DBName = database
|
||||
cfg.ParseTime = true
|
||||
cfg.Loc = time.Local
|
||||
cfg.Timeout = timeout
|
||||
cfg.Params = map[string]string{
|
||||
"charset": "utf8mb4",
|
||||
}
|
||||
return cfg.FormatDSN()
|
||||
}
|
||||
|
||||
@@ -4,12 +4,15 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.mchus.pro/mchus/quoteforge/internal/appmeta"
|
||||
mysqlDriver "github.com/go-sql-driver/mysql"
|
||||
"github.com/glebarez/sqlite"
|
||||
uuidpkg "github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
@@ -141,19 +144,23 @@ func (l *LocalDB) GetDSN() (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Add aggressive timeouts for offline-first architecture
|
||||
// timeout: connection establishment timeout (3s)
|
||||
// readTimeout: I/O read timeout (3s)
|
||||
// writeTimeout: I/O write timeout (3s)
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=3s&readTimeout=3s&writeTimeout=3s",
|
||||
settings.User,
|
||||
settings.PasswordEncrypted, // Contains decrypted password after GetSettings
|
||||
settings.Host,
|
||||
settings.Port,
|
||||
settings.Database,
|
||||
)
|
||||
cfg := mysqlDriver.NewConfig()
|
||||
cfg.User = settings.User
|
||||
cfg.Passwd = settings.PasswordEncrypted // Contains decrypted password after GetSettings
|
||||
cfg.Net = "tcp"
|
||||
cfg.Addr = net.JoinHostPort(settings.Host, strconv.Itoa(settings.Port))
|
||||
cfg.DBName = settings.Database
|
||||
cfg.ParseTime = true
|
||||
cfg.Loc = time.Local
|
||||
// Add aggressive timeouts for offline-first architecture.
|
||||
cfg.Timeout = 3 * time.Second
|
||||
cfg.ReadTimeout = 3 * time.Second
|
||||
cfg.WriteTimeout = 3 * time.Second
|
||||
cfg.Params = map[string]string{
|
||||
"charset": "utf8mb4",
|
||||
}
|
||||
|
||||
return dsn, nil
|
||||
return cfg.FormatDSN(), nil
|
||||
}
|
||||
|
||||
// DB returns the underlying gorm.DB for advanced operations
|
||||
|
||||
Reference in New Issue
Block a user