diff --git a/backend/defConfig/errorCodes.json b/backend/defConfig/errorCodes.json index 70d7317..8aa501e 100644 --- a/backend/defConfig/errorCodes.json +++ b/backend/defConfig/errorCodes.json @@ -1,5 +1,8 @@ { "apiOK":0, - "apiErr":-1 + "apiErr":-1, + "postErr":-2, + "jsonErr":-3, + "userNameDup":-4 } \ No newline at end of file diff --git a/backend/fresh.sh b/backend/fresh.sh new file mode 100644 index 0000000..80d8c1c --- /dev/null +++ b/backend/fresh.sh @@ -0,0 +1,4 @@ +export PATH=$PATH:$(go env GOPATH)/bin + +fresh + diff --git a/backend/main.go b/backend/main.go index 14fb54b..eca47a8 100644 --- a/backend/main.go +++ b/backend/main.go @@ -66,6 +66,7 @@ func main() { //统一初始化 models.ConfigAllInit() + routers.ApiInit() //启动gin服务 r := gin.Default() @@ -74,7 +75,7 @@ func main() { fs := http.FileServer(http.Dir("./dist")) // 中间件处理路由 r.Use(func(c *gin.Context) { - if strings.HasPrefix(c.Request.URL.Path, "/api/") { + if strings.HasPrefix(c.Request.URL.Path, "/api") { c.Next() // 继续处理API请求 return } @@ -85,7 +86,7 @@ func main() { }) // API路由 - routers.ApiRoot(r.Group("/api/")) + routers.ApiRoot(r.Group("/api")) var http_port = models.ConfigsWed.Host + ":" + models.ConfigsWed.Port var gin_port = "0.0.0.0" + ":" + models.ConfigsWed.Port diff --git a/backend/models/def.go b/backend/models/def.go new file mode 100644 index 0000000..15db41e --- /dev/null +++ b/backend/models/def.go @@ -0,0 +1,51 @@ +package models + +import ( + "crypto/md5" + "crypto/rand" + "encoding/hex" + "time" +) + +// 获取当前时间字符串 +// 参数格式可选,默认"2006-01-02 15:04:05" +func GetCurrentTimeString(format ...string) string { + // 默认格式 + layout := "2006_01_02-15_04_05.999999999" + + // 如果传入了格式参数则使用自定义格式 + if len(format) > 0 { + layout = format[0] + } + + return time.Now().Format(layout) +} + +func RandStr32() string { + // 生成 32 字节 (256 位) 随机数据 + b := make([]byte, 32) + if _, err := rand.Read(b); err != nil { + panic(err) + } + + // 转换为 16 进制字符串 (长度 64) + cookie := hex.EncodeToString(b) + return cookie +} + +func Md5Str(str string) string { + hashBytes2 := md5.Sum([]byte(str)) + hashString2 := hex.EncodeToString(hashBytes2[:]) // 注意数组转切片的[:] + return hashString2 +} + +func HashUserPass(str string) string { + switch ConfigsUser.PassHashType { + case "text": + return str + case "md5": + return Md5Str(str) + } + + return GetCurrentTimeString() + RandStr32() //如果转换失败返回当前时间,避免撞库 +} diff --git a/backend/models/sql.go b/backend/models/sql.go index 779cdd5..cd90a90 100644 --- a/backend/models/sql.go +++ b/backend/models/sql.go @@ -29,9 +29,25 @@ type TabUser_ struct { Name string `gorm:"size:100;uniqueIndex"` // 唯一约束索引 Email string `gorm:"size:255;index"` // 字符串长度限制100 索引 Pass string `gorm:"size:128"` // 建议存储哈希后的密码 + Type string `gorm:"size:64;default:user"` // Date time.Time `gorm:"type:datetime;default:CURRENT_TIMESTAMP"` // 默认当前时间 } +type TabUserGroups_ struct { + ID uint `gorm:"primaryKey;autoIncrement"` // 自增主键 + Name string `gorm:"size:100;uniqueIndex"` // 唯一约束索引 + Email string `gorm:"size:255;index"` // 字符串长度限制100 索引 + Type string `gorm:"size:64;default:usergroup"` // + Date time.Time `gorm:"type:datetime;default:CURRENT_TIMESTAMP"` // 默认当前时间 +} + +type TabUserGroupBinds_ struct { + ID uint `gorm:"primaryKey;autoIncrement"` // 自增主键 + UserID uint `gorm:"index"` + GroupID uint `gorm:"index"` + Date time.Time `gorm:"type:datetime;default:CURRENT_TIMESTAMP"` // 默认当前时间 +} + type TabUserInfo_ struct { ID uint `gorm:"primaryKey;autoIncrement"` UserID uint `gorm:"not null;uniqueIndex"` @@ -89,6 +105,10 @@ func DatabaseInit() error { // 自动创建表结构 DB.AutoMigrate(&TabUser_{}) + DB.AutoMigrate(&TabUserGroups_{}) + + DB.AutoMigrate(&TabUserGroupBinds_{}) + DB.AutoMigrate(&TabUserInfo_{}) DB.AutoMigrate(&TabCookie_{}) diff --git a/backend/routers/api.go b/backend/routers/api.go index 5b34fa1..a50a6ef 100644 --- a/backend/routers/api.go +++ b/backend/routers/api.go @@ -6,6 +6,7 @@ import ( "os" "github.com/gin-gonic/gin" + "github.com/mitchellh/mapstructure" ) var ErrorCode map[string]interface{} @@ -27,6 +28,29 @@ func init() { func ApiRoot(r *gin.RouterGroup) { + r.Use(func(ctx *gin.Context) { + //转换传进来的数据 + var jsonData map[string]interface{} + if err := ctx.ShouldBindJSON(&jsonData); err == nil { + //分离数据 + + if jsonData["cookie"] != "" && jsonData["cookie"] != nil { + ctx.Set("cookie_value", jsonData["cookie"]) + } + + if jsonData["data"] != nil { + //fmt.Println(jsonData["data"]) + var data_t map[string]interface{} + if err = mapstructure.Decode(jsonData["data"], &data_t); err == nil { + ctx.Set("data", &data_t) + } + } + + } + }) + + ApiUser(r.Group("/users")) + r.GET("/", func(ctx *gin.Context) { ReturnJson(ctx, "apiOK", nil) }) diff --git a/backend/routers/apiUsers.go b/backend/routers/apiUsers.go new file mode 100644 index 0000000..bd856bd --- /dev/null +++ b/backend/routers/apiUsers.go @@ -0,0 +1,117 @@ +package routers + +import ( + "fmt" + "ops/models" + "time" + + "github.com/gin-gonic/gin" + "github.com/mitchellh/mapstructure" +) + +func ApiInit() { + //用户模块初始化init + fmt.Println("users init") + + //创建admin用户 + var user models.TabUser_ + user.Name = "admin" + + if models.DB.Where(&user).First(&user).Error == nil { + + } else { + fmt.Println("用户不存在") + user.Pass = models.HashUserPass("adminpassword") + models.DB.Create(&user) // 传入指针 + } + + //创建admin group + var usergroup models.TabUserGroups_ + usergroup.Name = "admins" + if models.DB.Where(&usergroup).First(&usergroup).Error == nil { + + } else { + fmt.Println("用户组不存在") + models.DB.Create(&usergroup) // 传入指针 + } + + //创建用户与用户组绑定 + var usergroupbind models.TabUserGroupBinds_ + usergroupbind.UserID = user.ID + usergroupbind.GroupID = usergroup.ID + + if models.DB.Where(&usergroupbind).First(&usergroupbind).Error == nil { + + } else { + models.DB.Create(&usergroupbind) // 传入指针 + } + +} + +type From_user_add struct { + Useremail string `json:"useremail"` + Username string `json:"username"` + Userpass string `json:"userpass"` +} + +func ApiUser(r *gin.RouterGroup) { + + r.GET("/test", func(ctx *gin.Context) { + ReturnJson(ctx, "apiOK", nil) + }) + r.POST("/test", func(ctx *gin.Context) { + ReturnJson(ctx, "apiOK", nil) + }) + r.POST("/register", func(ctx *gin.Context) { + //转换传进来的数据 + var jsonData From_user_add + data, isHaveData := ctx.Get("data") + + if isHaveData { + if err := mapstructure.Decode(data, &jsonData); err == nil { + //转换字段 + newUser := models.TabUser_{ + Name: jsonData.Username, + Email: jsonData.Useremail, + Pass: jsonData.Userpass, // 实际应替换为哈希值 + Date: time.Now(), + // Date 字段无需赋值,数据库会自动填充默认值 + } + if newUser.Name != "" && newUser.Pass != "" && newUser.Email != "" { + //对用户的密码进行哈希替换 + newUser.Pass = models.HashUserPass(newUser.Pass) + //用户名是唯一的,先读取是否有这个用户名 + var user models.TabUser_ + user.Name = newUser.Name + + if models.DB.Where(&user).First(&user).Error == nil { + //fmt.Println("找到用户:", user.ID) + ReturnJson(ctx, "userNameDup", nil) + } else { + //fmt.Println("用户不存在") + models.DB.Create(&newUser) // 传入指针 + + //创建info + var user_info models.TabUserInfo_ + user_info.AvatarPath = models.ConfigsUser.AvatarPath + user_info.UserID = newUser.ID + models.DB.Create(&user_info) // 传入指针 + + ReturnJson(ctx, "apiOK", nil) + } + + } else { + ReturnJson(ctx, "jsonErr", nil) + } + + } else { + ReturnJson(ctx, "jsonErr", nil) + + } + } else { + ReturnJson(ctx, "postErr", nil) + + } + + }) +} diff --git a/backend/routers/return.go b/backend/routers/return.go index ebe856d..672dcbb 100644 --- a/backend/routers/return.go +++ b/backend/routers/return.go @@ -19,4 +19,6 @@ func ReturnJson(ctx *gin.Context, errMsg string, data map[string]interface{}) { ctx.JSON(200, &returnData) + ctx.Abort() + } diff --git a/backend/routers/routers.go b/backend/routers/routers.go deleted file mode 100644 index b636e57..0000000 --- a/backend/routers/routers.go +++ /dev/null @@ -1,7 +0,0 @@ -package routers - -import "github.com/gin-gonic/gin" - -func Root(r *gin.RouterGroup) { - -} diff --git a/frontent/ops_vue_js/src/my_network_func.js b/frontent/ops_vue_js/src/my_network_func.js index 0d2178d..d8bc5a7 100644 --- a/frontent/ops_vue_js/src/my_network_func.js +++ b/frontent/ops_vue_js/src/my_network_func.js @@ -1,9 +1,25 @@ import axios from "axios"; import { myfuncs } from "./myfunc"; +var head_path = "/api"; export const my_network_func = { - post_json(path, json, callback) { - var head_path = "/api/v1"; + getJson(path, callback) { + //get 方法一般不需要权限,不插入cookie + var re_data = {}; + axios + .get(head_path + path) + .then((r) => { + re_data["statusCode"] = r.status; + re_data["data"] = r.data; + callback(re_data); + }) + .catch((error) => { + re_data["statusCode"] = -1; + re_data["error"] = error; + callback(re_data); + }); + }, + postJson(path, json, callback) { //把cookie插入json var data = {}; data["data"] = json; diff --git a/frontent/ops_vue_js/src/views/HomeView.vue b/frontent/ops_vue_js/src/views/HomeView.vue index 46ccd4d..7fa211d 100644 --- a/frontent/ops_vue_js/src/views/HomeView.vue +++ b/frontent/ops_vue_js/src/views/HomeView.vue @@ -1,9 +1,20 @@ diff --git a/frontent/ops_vue_js/src/views/registerView.vue b/frontent/ops_vue_js/src/views/registerView.vue index 1e04df7..2f39155 100644 --- a/frontent/ops_vue_js/src/views/registerView.vue +++ b/frontent/ops_vue_js/src/views/registerView.vue @@ -1,71 +1,82 @@