This commit is contained in:
Sun
2023-11-08 21:53:07 +08:00
commit 211c3071dc
245 changed files with 39293 additions and 0 deletions
+178
View File
@@ -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)
// }
+90
View File
@@ -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
}
+150
View File
@@ -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
}
+39
View File
@@ -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")
}
+28
View File
@@ -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
}
+26
View File
@@ -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"),
}
}
+17
View File
@@ -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)
// }