ai-gateway/model/main.go

238 lines
5.3 KiB
Go
Raw Normal View History

2023-04-22 12:39:27 +00:00
package model
import (
"database/sql"
"fmt"
2024-01-28 11:38:58 +00:00
"github.com/songquanpeng/one-api/common"
"github.com/songquanpeng/one-api/common/config"
"github.com/songquanpeng/one-api/common/env"
2024-01-28 11:38:58 +00:00
"github.com/songquanpeng/one-api/common/helper"
"github.com/songquanpeng/one-api/common/logger"
"github.com/songquanpeng/one-api/common/random"
2023-04-22 12:39:27 +00:00
"gorm.io/driver/mysql"
2023-08-12 11:20:12 +00:00
"gorm.io/driver/postgres"
2023-04-22 12:39:27 +00:00
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"os"
2023-08-12 11:20:12 +00:00
"strings"
"time"
2023-04-22 12:39:27 +00:00
)
var DB *gorm.DB
var LOG_DB *gorm.DB
2023-04-22 12:39:27 +00:00
func CreateRootAccountIfNeed() error {
2023-04-22 12:39:27 +00:00
var user User
2024-01-14 11:21:03 +00:00
//if user.Status != util.UserStatusEnabled {
2023-04-22 12:39:27 +00:00
if err := DB.First(&user).Error; err != nil {
logger.SysLog("no user exists, creating a root user for you: username is root, password is 123456")
2023-04-22 12:39:27 +00:00
hashedPassword, err := common.Password2Hash("123456")
if err != nil {
return err
}
accessToken := random.GetUUID()
if config.InitialRootAccessToken != "" {
accessToken = config.InitialRootAccessToken
}
2023-04-22 12:39:27 +00:00
rootUser := User{
Username: "root",
Password: hashedPassword,
2024-04-05 18:03:59 +00:00
Role: RoleRootUser,
Status: UserStatusEnabled,
2023-04-22 12:39:27 +00:00
DisplayName: "Root User",
AccessToken: accessToken,
Quota: 500000000000000,
2023-04-22 12:39:27 +00:00
}
DB.Create(&rootUser)
if config.InitialRootToken != "" {
logger.SysLog("creating initial root token as requested")
token := Token{
Id: 1,
UserId: rootUser.Id,
Key: config.InitialRootToken,
2024-04-05 18:03:59 +00:00
Status: TokenStatusEnabled,
Name: "Initial Root Token",
CreatedTime: helper.GetTimestamp(),
AccessedTime: helper.GetTimestamp(),
ExpiredTime: -1,
RemainQuota: 500000000000000,
UnlimitedQuota: true,
}
DB.Create(&token)
}
2023-04-22 12:39:27 +00:00
}
return nil
}
func chooseDB(envName string) (*gorm.DB, error) {
dsn := os.Getenv(envName)
switch {
case strings.HasPrefix(dsn, "postgres://"):
// Use PostgreSQL
return openPostgreSQL(dsn)
case dsn != "":
2023-04-22 12:39:27 +00:00
// Use MySQL
return openMySQL(dsn)
default:
// Use SQLite
return openSQLite()
2023-04-22 12:39:27 +00:00
}
}
func openPostgreSQL(dsn string) (*gorm.DB, error) {
logger.SysLog("using PostgreSQL as database")
common.UsingPostgreSQL = true
return gorm.Open(postgres.New(postgres.Config{
DSN: dsn,
PreferSimpleProtocol: true, // disables implicit prepared statement usage
}), &gorm.Config{
PrepareStmt: true, // precompile SQL
})
}
func openMySQL(dsn string) (*gorm.DB, error) {
logger.SysLog("using MySQL as database")
common.UsingMySQL = true
return gorm.Open(mysql.Open(dsn), &gorm.Config{
PrepareStmt: true, // precompile SQL
})
}
func openSQLite() (*gorm.DB, error) {
logger.SysLog("SQL_DSN not set, using SQLite as database")
2023-08-12 11:20:12 +00:00
common.UsingSQLite = true
dsn := fmt.Sprintf("%s?_busy_timeout=%d", common.SQLitePath, common.SQLiteBusyTimeout)
return gorm.Open(sqlite.Open(dsn), &gorm.Config{
2023-08-12 11:20:12 +00:00
PrepareStmt: true, // precompile SQL
})
}
func InitDB() {
var err error
DB, err = chooseDB("SQL_DSN")
if err != nil {
logger.FatalLog("failed to initialize database: " + err.Error())
return
}
sqlDB := setDBConns(DB)
if !config.IsMasterNode {
return
}
if common.UsingMySQL {
_, _ = sqlDB.Exec("DROP INDEX idx_channels_key ON channels;") // TODO: delete this line when most users have upgraded
}
logger.SysLog("database migration started")
if err = migrateDB(); err != nil {
logger.FatalLog("failed to migrate database: " + err.Error())
return
}
logger.SysLog("database migrated")
}
func migrateDB() error {
var err error
if err = DB.AutoMigrate(&Channel{}); err != nil {
return err
}
if err = DB.AutoMigrate(&Token{}); err != nil {
return err
}
if err = DB.AutoMigrate(&User{}); err != nil {
return err
}
if err = DB.AutoMigrate(&Option{}); err != nil {
return err
}
if err = DB.AutoMigrate(&Redemption{}); err != nil {
return err
}
if err = DB.AutoMigrate(&Ability{}); err != nil {
return err
2023-04-22 12:39:27 +00:00
}
if err = DB.AutoMigrate(&Log{}); err != nil {
return err
}
if err = DB.AutoMigrate(&Channel{}); err != nil {
return err
}
return nil
}
func InitLogDB() {
if os.Getenv("LOG_SQL_DSN") == "" {
LOG_DB = DB
return
}
logger.SysLog("using secondary database for table logs")
var err error
LOG_DB, err = chooseDB("LOG_SQL_DSN")
if err != nil {
logger.FatalLog("failed to initialize secondary database: " + err.Error())
return
}
setDBConns(LOG_DB)
if !config.IsMasterNode {
return
}
logger.SysLog("secondary database migration started")
err = migrateLOGDB()
if err != nil {
logger.FatalLog("failed to migrate secondary database: " + err.Error())
return
}
logger.SysLog("secondary database migrated")
}
func migrateLOGDB() error {
var err error
if err = LOG_DB.AutoMigrate(&Log{}); err != nil {
return err
}
return nil
}
func setDBConns(db *gorm.DB) *sql.DB {
if config.DebugSQLEnabled {
db = db.Debug()
}
sqlDB, err := db.DB()
if err != nil {
logger.FatalLog("failed to connect database: " + err.Error())
return nil
}
sqlDB.SetMaxIdleConns(env.Int("SQL_MAX_IDLE_CONNS", 100))
sqlDB.SetMaxOpenConns(env.Int("SQL_MAX_OPEN_CONNS", 1000))
sqlDB.SetConnMaxLifetime(time.Second * time.Duration(env.Int("SQL_MAX_LIFETIME", 60)))
return sqlDB
2023-04-22 12:39:27 +00:00
}
func closeDB(db *gorm.DB) error {
sqlDB, err := db.DB()
2023-04-22 12:39:27 +00:00
if err != nil {
return err
}
err = sqlDB.Close()
return err
}
func CloseDB() error {
if LOG_DB != DB {
err := closeDB(LOG_DB)
if err != nil {
return err
}
}
return closeDB(DB)
}