diff --git a/OPS_设计.xmind b/OPS_设计.xmind index 6fdeab8..a14fafc 100644 Binary files a/OPS_设计.xmind and b/OPS_设计.xmind differ diff --git a/gin_ops/def_config/config_temp.yaml b/gin_ops/def_config/config_temp.yaml index c4be36c..88a9173 100644 --- a/gin_ops/def_config/config_temp.yaml +++ b/gin_ops/def_config/config_temp.yaml @@ -17,9 +17,44 @@ database: user: cookie_timeout: 604800 pass_hash_type: "md5" #密码哈希类型 text md5 - def_avatar_save_path: "/data/avatar/" #头像保存的真实位置 - def_avatar_ginrouter_path: "/avatar/" #gin 路由的路径 - def_avatar_path: "/static/avatars/def.png" + avatar_save_path: "/data/avatar/" #头像保存的真实位置 + avatar_ginrouter_path: "/avatar/" #gin 路由的路径 + avatar_path: "/static/avatars/def.png" + +file: + max_size_mb: 50 + pahts: + - "./data/avatar/" + - "./data/upload/image/" + - "./data/upload/video/" + - "./data/upload/music/" + - "./data/upload/pdf/" + - "./data/upload/other/" + + allow_image_mime: + - image/jpeg: true + - image/png: true + - image/gif: true + - image/bmp: true + + allow_video_mime: + - video/mp4: true + - video/x-msvideo: true + - video/quicktime: true + - video/x-flv: true + - video/mpeg: true + + allow_music_mime: + - audio/mpeg: true + - audio/aac: true + - audio/wav: true + - audio/flac: true + + allow_pdf_mime: + - application/pdf: true + + + warehouses: repos_per_page: 12 #每页显示多少个仓库 diff --git a/gin_ops/main.go b/gin_ops/main.go index 2f9651b..bd25dd4 100644 --- a/gin_ops/main.go +++ b/gin_ops/main.go @@ -16,22 +16,17 @@ func init() { func main() { fmt.Println("main_init!") - data_path := "./data/upload/" - avatar_path := "./data/avatar/" + config_file_path := "./data/config.yaml" config_temp_path := "./def_config/config_temp.yaml" // 直接尝试创建所有必要的目录 - err := os.MkdirAll(data_path, 0755) + err := os.MkdirAll("./data", 0755) if err != nil { fmt.Printf("创建文件夹失败: %v\n", err) - return + panic("创建文件夹失败") + } - err = os.MkdirAll(avatar_path, 0755) - if err != nil { - fmt.Printf("创建文件夹失败: %v\n", err) - return - } - //fmt.Println("文件夹创建成功或已存在") + //尝试读取配置 if !models.File_exists(config_file_path) { fmt.Println("读取配置失败") @@ -40,32 +35,33 @@ func main() { fmt.Println("复制配置模板") input, err := os.ReadFile(config_temp_path) if err != nil { - fmt.Println(err) - return + panic(err) + } err = os.WriteFile(config_file_path, input, 0644) if err != nil { - fmt.Println(err) - return + panic(err) + } fmt.Printf("需要修改此配置:%s\n", config_file_path) - return + } + //读取默认配置 data, err := os.ReadFile(config_file_path) if err != nil { - fmt.Println(err) - return + panic(err) + } if err := yaml.Unmarshal(data, &models.Configs); err != nil { - fmt.Println(err) - return + panic(err) + } if models.Configs["configed"] == false { fmt.Printf("需要将:%s 内的configed设置为true", config_file_path) - return + panic("need config") } //统一初始化 @@ -81,7 +77,7 @@ func main() { r.Static("/dist/", "./static/dist/") //静态用户上传的文件 - r.Static("/avatar/", avatar_path) + r.Static("/avatar/", models.Configs_file.Pahts[0]) //store := cookie.NewStore([]byte("secret")) // 自定义 404 页面(需要提前加载模板) @@ -93,15 +89,15 @@ func main() { routers.Router_api(r.Group("/api/")) routers.Router_file(r.Group("/file/")) - var http_port = models.Wed_configs.Host + ":" + models.Wed_configs.Port - var gin_port = "0.0.0.0" + ":" + models.Wed_configs.Port - if models.Wed_configs.Tls { - if models.Wed_configs.Cert_public_path == "" || models.Wed_configs.Cert_private_path == "" { + var http_port = models.Configs_wed.Host + ":" + models.Configs_wed.Port + var gin_port = "0.0.0.0" + ":" + models.Configs_wed.Port + if models.Configs_wed.Tls { + if models.Configs_wed.Cert_public_path == "" || models.Configs_wed.Cert_private_path == "" { fmt.Printf("需要配置证书路径") return } else { fmt.Println("https://" + http_port) - r.RunTLS(gin_port, models.Wed_configs.Cert_public_path, models.Wed_configs.Cert_private_path) + r.RunTLS(gin_port, models.Configs_wed.Cert_public_path, models.Configs_wed.Cert_private_path) } } else { fmt.Println("http://" + http_port) diff --git a/gin_ops/models/config.go b/gin_ops/models/config.go index 2f85731..4802d29 100644 --- a/gin_ops/models/config.go +++ b/gin_ops/models/config.go @@ -1,15 +1,20 @@ package models -import "github.com/mitchellh/mapstructure" +import ( + "fmt" + "os" + + "github.com/mitchellh/mapstructure" +) var Configs map[string]interface{} -var Wed_configs Wed_configs_t +var Configs_wed Configs_web_t +var Configs_user Configs_user_t +var Configs_file Configs_file_t var Database_configs map[string]interface{} -var User_configs map[string]interface{} - var Allowed_avatar_ext = map[string]bool{ ".jpg": true, ".jpeg": true, @@ -26,17 +31,35 @@ func init() { } func All_config_init() { - //读取web配置 - err := mapstructure.Decode(Configs["web"].(map[string]interface{}), &Wed_configs) + //初始化数据库 + Init_database() + + //读取web配置 + err := mapstructure.Decode(Configs["web"].(map[string]interface{}), &Configs_wed) if err != nil { panic(err) } - //初始化数据库 - Database_init() - //初始化user config - User_configs = Configs["user"].(map[string]interface{}) + err = mapstructure.Decode(Configs["user"].(map[string]interface{}), &Configs_user) + if err != nil { + panic(err) + } + + //初始化file config + err = mapstructure.Decode(Configs["file"].(map[string]interface{}), &Configs_file) + if err != nil { + panic(err) + } + //创建file的关键文件夹 + for _, value := range Configs_file.Pahts { + err := os.MkdirAll(value, 0755) + if err != nil { + fmt.Printf("创建文件夹失败: %v\n", err) + panic("创建文件夹失败") + + } + } } diff --git a/gin_ops/models/config_head.go b/gin_ops/models/config_head.go index 25065f8..abcd332 100644 --- a/gin_ops/models/config_head.go +++ b/gin_ops/models/config_head.go @@ -1,9 +1,26 @@ package models -type Wed_configs_t struct { +type Configs_web_t struct { Host string `mapstructure:"host"` Port string `mapstructure:"port"` Tls bool `mapstructure:"tls"` Cert_private_path string `mapstructure:"cert_private_path"` Cert_public_path string `mapstructure:"cert_public_path"` } + +type Configs_user_t struct { + Cookie_timeout int `mapstructure:"cookie_timeout"` + Pass_hash_type string `mapstructure:"pass_hash_type"` + Avatar_save_path string `mapstructure:"avatar_save_path"` + Avatar_ginrouter_path string `mapstructure:"avatar_ginrouter_path"` + Avatar_path string `mapstructure:"avatar_path"` +} + +type Configs_file_t struct { + Max_size_mb uint `mapstructure:"max_size_mb"` + Pahts []string `mapstructure:"pahts"` + Allow_image_mime []map[string]bool `mapstructure:"allow_image_mime"` + Allow_video_mime []map[string]bool `mapstructure:"allow_video_mime"` + Allow_music_mime []map[string]bool `mapstructure:"allow_music_mime"` + Allow_pdf_mime []map[string]bool `mapstructure:"allow_pdf_mime"` +} diff --git a/gin_ops/models/database.go b/gin_ops/models/database.go index 8abe1bf..efec5e9 100644 --- a/gin_ops/models/database.go +++ b/gin_ops/models/database.go @@ -139,7 +139,7 @@ func init() { } -func Database_init() { +func Init_database() { fmt.Println("database_init") //var database_config map[string]interface{}=Configs["database"] diff --git a/gin_ops/models/def_models.go b/gin_ops/models/def_models.go index 050a5ea..5d51bb7 100644 --- a/gin_ops/models/def_models.go +++ b/gin_ops/models/def_models.go @@ -100,7 +100,7 @@ func Md5_str(str string) string { } func Hash_user_pass(str string) string { - switch User_configs["pass_hash_type"].(string) { + switch Configs_user.Pass_hash_type { case "text": return str case "md5": diff --git a/gin_ops/routers/api_users.go b/gin_ops/routers/api_users.go index 7f85f09..67f2e61 100644 --- a/gin_ops/routers/api_users.go +++ b/gin_ops/routers/api_users.go @@ -47,7 +47,7 @@ func V1_user_api(r *gin.RouterGroup) { //创建info var user_info models.User_info - user_info.AvatarPath = models.User_configs["def_avatar_path"].(string) + user_info.AvatarPath = models.Configs_user.Avatar_path user_info.UserID = newUser.ID models.DB.Create(&user_info) // 传入指针 @@ -91,7 +91,7 @@ func V1_user_api(r *gin.RouterGroup) { //cookie时间 var cookie_time = 0 if jsonData.Is_keep_login { - cookie_time = models.User_configs["cookie_timeout"].(int) + cookie_time = models.Configs_user.Cookie_timeout } cookie := models.Rand_str_32() //生成32字节cookie @@ -99,7 +99,7 @@ func V1_user_api(r *gin.RouterGroup) { //fmt.Println(cookie) //将cookie写进数据库 new_cookie := models.Cookie{} - new_cookie.Domain = models.Wed_configs.Host + new_cookie.Domain = models.Configs_wed.Host new_cookie.Name = "user" new_cookie.Value = cookie new_cookie.UserID = user.ID @@ -108,11 +108,11 @@ func V1_user_api(r *gin.RouterGroup) { new_cookie.CreatedAt = time.Now() new_cookie.UpdatedAt = new_cookie.CreatedAt //计算cookie失效时间 - new_cookie.ExpiresAt = time.Now().Add(time.Duration(models.User_configs["cookie_timeout"].(int)) * time.Second) //计算过期时间 - new_cookie.SecureFlag = models.Wed_configs.Tls + new_cookie.ExpiresAt = time.Now().Add(time.Duration(models.Configs_user.Cookie_timeout) * time.Second) //计算过期时间 + new_cookie.SecureFlag = models.Configs_wed.Tls //发送到前端 - ctx.SetCookie("user", cookie, cookie_time, "/", models.Wed_configs.Host, models.Wed_configs.Tls, true) + ctx.SetCookie("user", cookie, cookie_time, "/", models.Configs_wed.Host, models.Configs_wed.Tls, true) ctx.Set("cookie", new_cookie) //写到数据库 models.DB.Create(&new_cookie) // 传入指针 @@ -167,7 +167,7 @@ func V1_user_api(r *gin.RouterGroup) { if err := mapstructure.Decode(cookie_any, &cookie); err == nil { models.DB.Where(&cookie).Delete(&cookie) //删除前端cookie - ctx.SetCookie("user", "", -1, "/", models.Wed_configs.Host, models.Wed_configs.Tls, true) + ctx.SetCookie("user", "", -1, "/", models.Configs_wed.Host, models.Configs_wed.Tls, true) ctx.Set("cookie", nil) Return_json(ctx, "api_ok", nil) @@ -178,7 +178,7 @@ func V1_user_api(r *gin.RouterGroup) { } } else { - ctx.SetCookie("user", "", -1, "/", models.Wed_configs.Host, models.Wed_configs.Tls, true) + ctx.SetCookie("user", "", -1, "/", models.Configs_wed.Host, models.Configs_wed.Tls, true) Return_json(ctx, "user_no_sign", nil) } @@ -211,10 +211,10 @@ func V1_user_api(r *gin.RouterGroup) { } //需要验证传入数据的合法性 例如头像url是否站内的 - if strings.HasPrefix(new_user_info.AvatarPath, models.User_configs["def_avatar_ginrouter_path"].(string)) { + if strings.HasPrefix(new_user_info.AvatarPath, models.Configs_user.Avatar_ginrouter_path) { } else { - new_user_info.AvatarPath = models.User_configs["def_avatar_path"].(string) + new_user_info.AvatarPath = models.Configs_user.Avatar_path } //fmt.Printf("%%#v: %#v\n", new_user_info) diff --git a/gin_ops/routers/routers_flie.go b/gin_ops/routers/routers_flie.go index 0c96324..18bba1d 100644 --- a/gin_ops/routers/routers_flie.go +++ b/gin_ops/routers/routers_flie.go @@ -3,13 +3,17 @@ package routers //文件路由 import ( - "fmt" - "github.com/gin-gonic/gin" ) func Router_file(r *gin.RouterGroup) { + //无需权限,可以直接下载的接口 + r.GET("/download/:id", func(ctx *gin.Context) { + + }) + + //先在中间件判断有没有登录 r.Use(func(ctx *gin.Context) { cookie_value := ctx.PostForm("cookie") //fmt.Println(cookie_value) @@ -26,15 +30,34 @@ func Router_file(r *gin.RouterGroup) { } }) - r.POST("/upload", func(ctx *gin.Context) { - file, err := ctx.FormFile("file") - if err == nil { - fmt.Println("ok") - } else { - fmt.Println("err:", err) - fmt.Println("file:", file) - } - Return_json(ctx, "api_ok", nil) + upload := r.Group("/upload") //定义上传组 + //4大媒体上传接口,严格判断文件类型,可以直接被前端引用 + upload.POST("/image", func(ctx *gin.Context) { + + }) + upload.POST("/video", func(ctx *gin.Context) { + + }) + upload.POST("/music", func(ctx *gin.Context) { + + }) + upload.POST("/pdf", func(ctx *gin.Context) { + + }) + //其他文件,只能通过用户报告的类型定义,不能直接被前端引用 + upload.POST("/other", func(ctx *gin.Context) { + }) + // r.POST("/upload", func(ctx *gin.Context) { + // file, err := ctx.FormFile("file") + // if err == nil { + // fmt.Println("ok") + // } else { + // fmt.Println("err:", err) + // fmt.Println("file:", file) + // } + // Return_json(ctx, "api_ok", nil) + // }) + } diff --git a/gin_ops/routers/uses.go b/gin_ops/routers/uses.go index 225cb09..74f11a8 100644 --- a/gin_ops/routers/uses.go +++ b/gin_ops/routers/uses.go @@ -27,10 +27,10 @@ func Use_login_from_cookie(ctx *gin.Context) { //每次调用都更新cookie的最新状态 ,用于计算在线 var cookie_up models.Cookie cookie_up.UpdatedAt = time.Now() - cookie_up.ExpiresAt = time.Now().Add(time.Duration(models.User_configs["cookie_timeout"].(int)) * time.Second) //计算过期时间 + cookie_up.ExpiresAt = time.Now().Add(time.Duration(models.Configs_user.Cookie_timeout) * time.Second) //计算过期时间 models.DB.Model(&models.Cookie{}).Where(&cookie).Updates(&cookie_up) //更新前端cookie - ctx.SetCookie("user", cookie.Value, models.User_configs["cookie_timeout"].(int), "/", models.Wed_configs.Host, models.Wed_configs.Tls, true) + ctx.SetCookie("user", cookie.Value, models.Configs_user.Cookie_timeout, "/", models.Configs_wed.Host, models.Configs_wed.Tls, true) cookie.UpdatedAt = cookie_up.UpdatedAt cookie.ExpiresAt = cookie_up.ExpiresAt ctx.Set("cookie", cookie) @@ -52,7 +52,7 @@ func Use_login_from_cookie(ctx *gin.Context) { } else { // 无数据 //创建一个默认info - user_info.AvatarPath = models.User_configs["def_avatar_path"].(string) + user_info.AvatarPath = models.Configs_user.Avatar_path user_info.UserID = cookie.UserID models.DB.Create(&user_info) // 传入指针 } @@ -63,7 +63,7 @@ func Use_login_from_cookie(ctx *gin.Context) { } else { //找不到登录权限?? 可能被封号? //删除前端cookie - ctx.SetCookie("user", "", -1, "/", models.Wed_configs.Host, models.Wed_configs.Tls, true) + ctx.SetCookie("user", "", -1, "/", models.Configs_wed.Host, models.Configs_wed.Tls, true) cookie.Value = "" cookie.ExpiresAt = time.Now() ctx.Set("cookie", cookie) @@ -75,7 +75,7 @@ func Use_login_from_cookie(ctx *gin.Context) { //删除数据库的cookie models.DB.Delete(&cookie) //删除前端cookie - ctx.SetCookie("user", "", -1, "/", models.Wed_configs.Host, models.Wed_configs.Tls, true) + ctx.SetCookie("user", "", -1, "/", models.Configs_wed.Host, models.Configs_wed.Tls, true) cookie.Value = "" cookie.ExpiresAt = time.Now() ctx.Set("cookie", cookie) @@ -84,7 +84,7 @@ func Use_login_from_cookie(ctx *gin.Context) { } else { //找不到cookie,未登录 //删除前端cookie - ctx.SetCookie("user", "", -1, "/", models.Wed_configs.Host, models.Wed_configs.Tls, true) + ctx.SetCookie("user", "", -1, "/", models.Configs_wed.Host, models.Configs_wed.Tls, true) cookie.Value = "" cookie.ExpiresAt = time.Now() ctx.Set("cookie", cookie)