v1.0.0
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"sun-panel/global"
|
||||
"sun-panel/initialize/cUserToken"
|
||||
"sun-panel/initialize/config"
|
||||
"sun-panel/initialize/database"
|
||||
"sun-panel/initialize/lang"
|
||||
"sun-panel/initialize/other"
|
||||
"sun-panel/initialize/redis"
|
||||
"sun-panel/initialize/runlog"
|
||||
"sun-panel/initialize/systemSettingCache"
|
||||
"sun-panel/initialize/userToken"
|
||||
"sun-panel/lib/cmn"
|
||||
"sun-panel/models"
|
||||
"sun-panel/structs"
|
||||
|
||||
"log"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var DB_DRIVER = database.SQLITE
|
||||
|
||||
// var RUNCODE = "debug"
|
||||
// var ISDOCER = "" // 是否为docker模式
|
||||
|
||||
func InitApp() error {
|
||||
gin.SetMode(global.RUNCODE) // GIN 运行模式
|
||||
|
||||
// 日志
|
||||
if logger, err := runlog.InitRunlog(global.RUNCODE, "running.log"); err != nil {
|
||||
log.Panicln("日志初始化错误", err)
|
||||
panic(err)
|
||||
} else {
|
||||
global.Logger = logger
|
||||
}
|
||||
|
||||
// 命令行运行
|
||||
CommandRun()
|
||||
|
||||
// 配置初始化
|
||||
{
|
||||
if config, err := config.ConfigInit(); err != nil {
|
||||
global.Logger.Errorln("配置初始化错误", err)
|
||||
return err
|
||||
} else {
|
||||
global.Config = config
|
||||
}
|
||||
}
|
||||
|
||||
// 多语言初始化
|
||||
lang.LangInit("zh-cn") // en-us
|
||||
|
||||
DatabaseConnect()
|
||||
|
||||
// Redis 连接
|
||||
{
|
||||
// 判断是否有使用redis的驱动,没有将不连接
|
||||
cacheDrive := global.Config.GetValueString("base", "cache_drive")
|
||||
queueDrive := global.Config.GetValueString("base", "queue_drive")
|
||||
if cacheDrive == "redis" || queueDrive == "redis" {
|
||||
redisConfig := structs.IniConfigRedis{}
|
||||
global.Config.GetSection("redis", &redisConfig)
|
||||
rdb, err := redis.InitRedis(redis.Options{
|
||||
Addr: redisConfig.Address,
|
||||
Password: redisConfig.Password,
|
||||
DB: redisConfig.Db,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Panicln("Redis初始化错误", err)
|
||||
panic(err)
|
||||
// return err
|
||||
}
|
||||
global.RedisDb = rdb
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化用户token
|
||||
global.UserToken = userToken.InitUserToken()
|
||||
global.CUserToken = cUserToken.InitCUserToken()
|
||||
|
||||
// 其他的初始化
|
||||
global.VerifyCodeCachePool = other.InitVerifyCodeCachePool()
|
||||
global.SystemSetting = systemSettingCache.InItSystemSettingCache()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DatabaseConnect() {
|
||||
// 数据库连接 - 开始
|
||||
var dbClientInfo database.DbClient
|
||||
databaseDrive := global.Config.GetValueStringOrDefault("base", "database_drive")
|
||||
if databaseDrive == database.MYSQL {
|
||||
dbClientInfo = &database.MySQLConfig{
|
||||
Username: global.Config.GetValueStringOrDefault("mysql", "username"),
|
||||
Password: global.Config.GetValueStringOrDefault("mysql", "password"),
|
||||
Host: global.Config.GetValueStringOrDefault("mysql", "host"),
|
||||
Port: global.Config.GetValueStringOrDefault("mysql", "port"),
|
||||
Database: global.Config.GetValueStringOrDefault("mysql", "db_name"),
|
||||
WaitTimeout: global.Config.GetValueInt("mysql", "wait_timeout"),
|
||||
}
|
||||
} else {
|
||||
dbClientInfo = &database.SQLiteConfig{
|
||||
Filename: global.Config.GetValueStringOrDefault("sqlite", "file_path"),
|
||||
}
|
||||
}
|
||||
|
||||
if db, err := database.DbInit(dbClientInfo); err != nil {
|
||||
log.Panicln("数据库初始化错误", err)
|
||||
panic(err)
|
||||
} else {
|
||||
global.Db = db
|
||||
models.Db = global.Db
|
||||
}
|
||||
|
||||
database.CreateDatabase(databaseDrive, global.Db)
|
||||
|
||||
database.NotFoundAndCreateUser(global.Db)
|
||||
}
|
||||
|
||||
// 命令行运行
|
||||
func CommandRun() {
|
||||
var (
|
||||
cfg bool
|
||||
pwd bool
|
||||
)
|
||||
|
||||
flag.BoolVar(&cfg, "config", false, "生成配置文件")
|
||||
flag.BoolVar(&pwd, "password-reset", false, "重置第一个用户的密码")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if cfg {
|
||||
// 生成配置文件
|
||||
fmt.Println("正在生成配置文件")
|
||||
cmn.AssetsTakeFileToPath("conf.example.ini", "conf/conf.example.ini")
|
||||
cmn.AssetsTakeFileToPath("conf.example.ini", "conf/conf.ini")
|
||||
fmt.Println("配置文件已经创建 conf/conf.ini ", "请按照自己的需求修改")
|
||||
os.Exit(0) // 务必退出
|
||||
} else if pwd {
|
||||
|
||||
// 配置初始化
|
||||
config, _ := config.ConfigInit()
|
||||
global.Config = config
|
||||
|
||||
// 重置密码
|
||||
DatabaseConnect()
|
||||
userInfo := models.User{}
|
||||
if err := global.Db.First(&userInfo).Error; err != nil {
|
||||
fmt.Println("ERROR", err.Error())
|
||||
os.Exit(0) // 务必退出
|
||||
}
|
||||
|
||||
newPassword := "12345678"
|
||||
|
||||
updateInfo := models.User{
|
||||
Password: cmn.PasswordEncryption(newPassword),
|
||||
Token: "",
|
||||
}
|
||||
if err := global.Db.Select("Password", "Token").Where("id=?", userInfo.ID).Updates(&updateInfo).Error; err != nil {
|
||||
fmt.Println("ERROR", err.Error())
|
||||
os.Exit(0) // 务必退出
|
||||
}
|
||||
|
||||
fmt.Println("密码已经重置成功,以下是账号信息")
|
||||
fmt.Println("用户名 ", userInfo.Username)
|
||||
fmt.Println("密码 ", newPassword)
|
||||
os.Exit(0) // 务必退出
|
||||
} else {
|
||||
return
|
||||
}
|
||||
os.Exit(0) // 务必退出
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package cUserToken
|
||||
|
||||
import (
|
||||
"sun-panel/global"
|
||||
"sun-panel/lib/cache"
|
||||
|
||||
"time"
|
||||
)
|
||||
|
||||
func InitCUserToken() cache.Cacher[string] {
|
||||
return global.NewCache[string](72*time.Hour, 48*time.Hour, "CUserToken")
|
||||
}
|
||||
|
||||
// func InitVerifyCodeCachePool() {
|
||||
// global.VerifyCodeCachePool = cache.NewGoCache(10*time.Minute, 60*time.Second)
|
||||
// }
|
||||
@@ -0,0 +1,90 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sun-panel/global"
|
||||
"sun-panel/lib/cmn"
|
||||
"sun-panel/lib/iniConfig"
|
||||
)
|
||||
|
||||
func getDefaultConfig() map[string]map[string]string {
|
||||
return map[string]map[string]string{
|
||||
"base": {
|
||||
"http_port": "9090",
|
||||
"source_path": "./files", // 存放文件的路径
|
||||
"source_temp_path": "./files/temp", // 存放文件的缓存路径
|
||||
},
|
||||
"sqlite": {
|
||||
"file_path": "./database.db",
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func ConfigInit() (*iniConfig.IniConfig, error) {
|
||||
|
||||
// 配置文件初始化
|
||||
if config, err, errCode := Conf(getDefaultConfig()); err != nil && errCode == 0 {
|
||||
// 抛出错误
|
||||
cmn.Pln(cmn.LOG_ERROR, "配置文件创建错误:"+err.Error())
|
||||
os.Exit(1)
|
||||
return nil, err
|
||||
} else if errCode == 1 {
|
||||
// 配置文件不存在,进行创建
|
||||
if err := CreateConfExample("conf.example.ini", "conf.ini"); err != nil {
|
||||
cmn.Pln(cmn.LOG_ERROR, "配置文件创建错误:"+err.Error())
|
||||
os.Exit(1)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
global.Logger.Errorln("配置文件已经自动生成'conf/conf.ini',将再次读取配置")
|
||||
// 创建成功再次读取文件
|
||||
if configAgain, errAgain, _ := Conf(getDefaultConfig()); errAgain != nil {
|
||||
return nil, errAgain
|
||||
} else {
|
||||
global.Logger.Errorln("尝试读取配置文件'conf/conf.ini',二次读取配置文件成功")
|
||||
return configAgain, nil
|
||||
}
|
||||
} else {
|
||||
return config, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 配置初始化
|
||||
// errCode=1 说明初始化流程
|
||||
func Conf(defaultConfig map[string]map[string]string) (config *iniConfig.IniConfig, err error, errCode int) {
|
||||
CreateConfExample("conf.example.ini", "conf.example.ini")
|
||||
exists, err := cmn.PathExists("conf/conf.ini")
|
||||
if exists {
|
||||
config = iniConfig.NewIniConfig("conf/conf.ini") // 读取配置
|
||||
config.Default = defaultConfig
|
||||
} else if err != nil {
|
||||
|
||||
} else {
|
||||
// docker 运行模式,生成配置文件
|
||||
if global.ISDOCKER != "" {
|
||||
cmn.AssetsTakeFileToPath("conf.example.ini", "conf/conf.ini")
|
||||
config = iniConfig.NewIniConfig("conf/conf.ini") // 读取配置
|
||||
config.Default = defaultConfig
|
||||
} else {
|
||||
errCode = 1
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 生成示例配置文件
|
||||
func CreateConfExample(confName string, targetName string) (err error) {
|
||||
// 查看配置示例文件是否存在,不存在创建(分别为示例配置和配置文件)
|
||||
exists, err := cmn.PathExists("conf/" + targetName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !exists {
|
||||
if err = cmn.AssetsTakeFileToPath(confName, "conf/"+targetName); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"sun-panel/lib/cmn"
|
||||
"sun-panel/models"
|
||||
"time"
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
_ "gorm.io/driver/mysql"
|
||||
"gorm.io/driver/sqlite"
|
||||
_ "gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
const (
|
||||
MYSQL = "mysql"
|
||||
SQLITE = "sqlite"
|
||||
)
|
||||
|
||||
type DbClient interface {
|
||||
Connect() (db *gorm.DB, err error)
|
||||
}
|
||||
|
||||
type MySQLConfig struct {
|
||||
Username string
|
||||
Password string
|
||||
Host string
|
||||
Port string
|
||||
Database string
|
||||
WaitTimeout int
|
||||
}
|
||||
|
||||
type SQLiteConfig struct {
|
||||
Filename string
|
||||
}
|
||||
|
||||
func DbInit(dbClient DbClient) (db *gorm.DB, dbErr error) {
|
||||
db, dbErr = dbClient.Connect()
|
||||
if dbErr != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Connect mysql连接
|
||||
func (d *MySQLConfig) Connect() (db *gorm.DB, err error) {
|
||||
dsn := d.Username + ":" + d.Password + "@tcp(" + d.Host + ":" + d.Port + ")/" + d.Database + "?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||
Logger: GetLogger(),
|
||||
NamingStrategy: schema.NamingStrategy{
|
||||
// TablePrefix: "blog_",
|
||||
SingularTable: true,
|
||||
},
|
||||
DisableForeignKeyConstraintWhenMigrating: true,
|
||||
})
|
||||
sqlDb, _ := db.DB()
|
||||
sqlDb.SetMaxIdleConns(10) // SetMaxIdleConns 设置空闲连接池中连接的最大数量
|
||||
sqlDb.SetMaxOpenConns(100) // SetMaxOpenConns 设置打开数据库连接的最大数量。
|
||||
wait_timeout := d.WaitTimeout
|
||||
sqlDb.SetConnMaxLifetime(time.Duration(wait_timeout * int(time.Second))) // SetConnMaxLifetime 设置了连接可复用的最大时间。
|
||||
return
|
||||
}
|
||||
|
||||
// Connect sqllite3连接
|
||||
func (d *SQLiteConfig) Connect() (db *gorm.DB, err error) {
|
||||
filePath := d.Filename
|
||||
exists := false
|
||||
if exists, err = cmn.PathExists(path.Dir(filePath)); err != nil {
|
||||
return
|
||||
} else {
|
||||
|
||||
// 创建文件夹
|
||||
if !exists {
|
||||
if err = os.MkdirAll(path.Dir(filePath), 0666); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
db, err = gorm.Open(sqlite.Open(filePath), &gorm.Config{
|
||||
Logger: GetLogger(),
|
||||
NamingStrategy: schema.NamingStrategy{
|
||||
SingularTable: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 日志
|
||||
func GetLogger() logger.Interface {
|
||||
return logger.New(
|
||||
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer(日志输出的目标,前缀和日志包含的内容——译者注)
|
||||
logger.Config{
|
||||
SlowThreshold: time.Second, // 慢 SQL 阈值
|
||||
LogLevel: logger.Warn, // 日志级别
|
||||
IgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound(记录未找到)错误
|
||||
Colorful: true, // 彩色打印
|
||||
},
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
// 创建数据库
|
||||
func CreateDatabase(driver string, db *gorm.DB) error {
|
||||
|
||||
// mysql特殊处理
|
||||
if driver == MYSQL {
|
||||
db = db.Set("gorm:table_options", "ENGINE=InnoDB")
|
||||
}
|
||||
|
||||
// 创建数据表
|
||||
err := db.AutoMigrate(
|
||||
&models.User{},
|
||||
&models.SystemSetting{},
|
||||
&models.ItemIcon{},
|
||||
&models.UserConfig{},
|
||||
&models.File{},
|
||||
)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 初始化一个用户,一个用户都没有的时候创建一个
|
||||
func NotFoundAndCreateUser(db *gorm.DB) error {
|
||||
fUser := models.User{}
|
||||
if err := db.First(&fUser).Error; err != nil {
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
return err
|
||||
}
|
||||
username := "admin@sun.cc"
|
||||
fUser.Mail = username
|
||||
fUser.Username = username
|
||||
fUser.Name = username
|
||||
fUser.Status = 1
|
||||
fUser.Role = 1
|
||||
fUser.Password = cmn.PasswordEncryption("12345678")
|
||||
|
||||
if errCreate := db.Create(&fUser).Error; errCreate != nil {
|
||||
return errCreate
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package lang
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sun-panel/global"
|
||||
"sun-panel/lib/cmn"
|
||||
"sun-panel/lib/language"
|
||||
)
|
||||
|
||||
func LangInit(lang string) {
|
||||
filename := "lang/" + lang + ".ini"
|
||||
exists, err := cmn.PathExists(filename)
|
||||
if err != nil {
|
||||
global.Logger.Errorln("语言文件不存在", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 生成语言文件
|
||||
if !exists {
|
||||
global.Logger.Infoln("输出语言文件:", filename)
|
||||
err := cmn.AssetsTakeFileToPath("lang/zh-cn.ini", "lang/zh-cn.ini")
|
||||
if err != nil {
|
||||
global.Logger.Errorln("输出语言文件出错:", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
err = cmn.AssetsTakeFileToPath("lang/en-us.ini", "lang/en-us.ini")
|
||||
if err != nil {
|
||||
global.Logger.Errorln("输出语言文件出错:", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
exists, err = cmn.PathExists(filename)
|
||||
if err != nil || !exists {
|
||||
global.Logger.Errorln("语言文件不存在:", filename)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
global.Lang = language.NewLang(filename)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package other
|
||||
|
||||
import (
|
||||
"sun-panel/global"
|
||||
"sun-panel/lib/cache"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InitVerifyCodeCachePool() cache.Cacher[string] {
|
||||
return global.NewCache[string](10*time.Minute, 10*time.Minute, "VerifyCodeCachePool")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package rateLimitCache
|
||||
|
||||
import (
|
||||
"sun-panel/global"
|
||||
"sun-panel/lib/cache"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 速率限制分钟级别
|
||||
func InitMinute() cache.Cacher[int] {
|
||||
return global.NewCache[int](1*time.Minute, 1*time.Hour, "RateLimitCacheMinute")
|
||||
}
|
||||
|
||||
// 速率限制小时级别
|
||||
func InitHour() cache.Cacher[int] {
|
||||
return global.NewCache[int](1*time.Hour, 2*time.Hour, "RateLimitCacheHour")
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
Addr string // localhost:6379
|
||||
Password string // 没有密码,默认值
|
||||
DB int // 默认DB 0
|
||||
}
|
||||
|
||||
func InitRedis(options Options) (*redis.Client, error) {
|
||||
rdb := redis.NewClient(&redis.Options{
|
||||
Addr: options.Addr,
|
||||
Password: options.Password,
|
||||
DB: options.DB,
|
||||
})
|
||||
|
||||
// 验证连接是否成功
|
||||
ctx := context.Background()
|
||||
if _, err := rdb.Ping(ctx).Result(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rdb, nil
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package runlog
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sun-panel/global"
|
||||
"sun-panel/lib/cmn"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func InitRunlog(runmode string, filePath string) (*zap.SugaredLogger, error) {
|
||||
|
||||
runtimePath := "./runtime/runlog"
|
||||
if err := os.MkdirAll(runtimePath, 0777); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var level zap.AtomicLevel
|
||||
if runmode == "debug" {
|
||||
level = zap.NewAtomicLevelAt(zap.DebugLevel)
|
||||
} else {
|
||||
level = global.LoggerLevel
|
||||
}
|
||||
|
||||
logger := cmn.InitLogger(runtimePath+"/"+filePath, level)
|
||||
return logger, nil
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package systemSettingCache
|
||||
|
||||
import (
|
||||
"sun-panel/global"
|
||||
"sun-panel/lib/cmn/systemSetting"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InItSystemSettingCache() *systemSetting.SystemSettingCache {
|
||||
return &systemSetting.SystemSettingCache{
|
||||
Cache: global.NewCache[interface{}](5*time.Hour, -1, "systemSettingCache"),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package userToken
|
||||
|
||||
import (
|
||||
"sun-panel/global"
|
||||
"sun-panel/lib/cache"
|
||||
"sun-panel/models"
|
||||
|
||||
"time"
|
||||
)
|
||||
|
||||
func InitUserToken() cache.Cacher[models.User] {
|
||||
return global.NewCache[models.User](1*time.Minute, 1*time.Hour, "UserToken")
|
||||
}
|
||||
|
||||
// func InitVerifyCodeCachePool() {
|
||||
// global.VerifyCodeCachePool = cache.NewGoCache(10*time.Minute, 60*time.Second)
|
||||
// }
|
||||
Reference in New Issue
Block a user