diff --git a/opencatd/db/cat.go b/opencatd/db/cat.go index c533e80..99474cd 100644 --- a/opencatd/db/cat.go +++ b/opencatd/db/cat.go @@ -100,7 +100,7 @@ func deleteUser(c *gin.Context) { } func initDB() { - db, err := sql.Open("sqlite3", "test.db") + db, err := sql.Open("sqlite3", "./db/cat.db") if err != nil { log.Fatal(err) } diff --git a/opencatd/opencat.go b/opencatd/opencat.go index 6539b72..61f3084 100644 --- a/opencatd/opencat.go +++ b/opencatd/opencat.go @@ -1,172 +1,46 @@ package main import ( - "net/http" - "strconv" + "chat/opencatd/router" + _ "chat/pkg/opencatd/db" "github.com/gin-gonic/gin" - "github.com/google/uuid" ) -type User struct { - IsDelete bool `json:"IsDelete"` - ID int `json:"id"` - UpdatedAt string `json:"updatedAt"` - Name string `json:"name"` - Token string `json:"token"` - CreatedAt string `json:"createdAt"` -} - -type Key struct { - ID int `json:"id"` - Key string `json:"key"` - UpdatedAt string `json:"updatedAt"` - Name string `json:"name"` - CreatedAt string `json:"createdAt"` -} - -var users = []User{ - {false, 1, "2023-03-28T12:36:03.907590825Z", "root", "4930f144-7ffc-469b-8f2d-71a267358d87", "2023-03-28T11:52:45.593940257Z"}, -} - -var keys = []Key{ - {1, "1234567890", "2023-03-28T12:53:41.124319079Z", "key1", "2023-03-28T12:53:41.124318928Z"}, -} - func main() { - router := gin.Default() + + r := gin.Default() + group := r.Group("/1") + { + group.Use(router.AuthMiddleware()) + + // 获取当前用户信息 + group.GET("/me", router.HandleMe) + + // 获取所有Key + group.GET("/keys", router.HandleKeys) + + // 获取所有用户信息 + group.GET("/users", router.HandleUsers) + + // 添加Key + group.POST("/keys", router.HandleAddKey) + + // 删除Key + group.DELETE("/keys/:id", router.HandleDelKey) + + // 添加用户 + group.POST("/users", router.HandleAddUser) + + // 删除用户 + group.DELETE("/users/:id", router.HandleDelUser) + + // 重置用户Token + group.POST("/users/:id/reset", router.HandleResetUserToken) + } // 初始化用户 - router.POST("/1/users/init", func(c *gin.Context) { - resJSON := User{ - false, - 1, - "2023-03-28T14:13:54.969089197Z", - "root", - "3260dd53-463f-45d0-afa4-57acd04ee036", - "2023-03-28T14:13:54.969089107Z", - } + r.POST("/1/users/init", router.Handleinit) - c.JSON(http.StatusOK, resJSON) - }) - - // 获取当前用户信息 - router.GET("/1/me", func(c *gin.Context) { - resJSON := users[0] - - c.JSON(http.StatusOK, resJSON) - }) - - // 获取所有Key - router.GET("/1/keys", func(c *gin.Context) { - c.JSON(http.StatusOK, keys) - }) - - // 获取所有用户信息 - router.GET("/1/users", func(c *gin.Context) { - c.JSON(http.StatusOK, users) - }) - - // 添加Key - router.POST("/1/keys", func(c *gin.Context) { - var body Key - if err := c.BindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) - return - } - - keys = append(keys, body) - c.JSON(http.StatusCreated, body) - }) - - // 删除Key - router.DELETE("/1/keys/:id", func(c *gin.Context) { - id := c.Param("id") - var keyIdx int = -1 - - for idx, key := range keys { - if strconv.Itoa(key.ID) == id { - keyIdx = idx - break - } - } - - if keyIdx == -1 { - c.JSON(http.StatusNotFound, gin.H{"error": "Key not found"}) - return - } - - keys = append(keys[:keyIdx], keys[keyIdx+1:]...) - c.JSON(http.StatusOK, gin.H{"message": "ok"}) - }) - - // 添加用户 - router.POST("/1/users", func(c *gin.Context) { - var body User - if err := c.BindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) - return - } - - newUser := User{ - false, - len(users) + 1, - "2023-03-28T13:05:02.103135082Z", - body.Name, - GenerateToken(), - "2023-03-28T12:38:57.513105431Z", - } - - users = append(users, newUser) - c.JSON(http.StatusCreated, newUser) - }) - - // 删除用户 - router.DELETE("/1/users/:id", func(c *gin.Context) { - id := c.Param("id") - var userIdx int = -1 - - for idx, user := range users { - if strconv.Itoa(user.ID) == id { - userIdx = idx - break - } - } - - if userIdx == -1 { - c.JSON(http.StatusNotFound, gin.H{"error": "User not found"}) - return - } - - users = append(users[:userIdx], users[userIdx+1:]...) - c.JSON(http.StatusOK, gin.H{"message": "ok"}) - }) - - // 重置用户Token - router.POST("/1/users/:id/reset", func(c *gin.Context) { - id := c.Param("id") - var userIdx int = -1 - - for idx, user := range users { - if strconv.Itoa(user.ID) == id { - userIdx = idx - break - } - } - - if userIdx == -1 { - c.JSON(http.StatusNotFound, gin.H{"error": "User not found"}) - return - } - - users[userIdx].Token = GenerateToken() - c.JSON(http.StatusOK, users[userIdx]) - }) - - router.Run(":8080") -} - -func GenerateToken() string { - token := uuid.New() - return token.String() + r.Run(":80") } diff --git a/opencatd/router/router.go b/opencatd/router/router.go new file mode 100644 index 0000000..018c162 --- /dev/null +++ b/opencatd/router/router.go @@ -0,0 +1,223 @@ +package router + +import ( + "chat/pkg/opencatd/db" + "errors" + "net/http" + "time" + + "github.com/Sakurasan/to" + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "gorm.io/gorm" +) + +var ( + rootToken string +) + +type User struct { + IsDelete bool `json:"IsDelete,omitempty"` + ID int `json:"id,omitempty"` + UpdatedAt string `json:"updatedAt,omitempty"` + Name string `json:"name,omitempty"` + Token string `json:"token,omitempty"` + CreatedAt string `json:"createdAt,omitempty"` +} + +type Key struct { + ID int `json:"id,omitempty"` + Key string `json:"key,omitempty"` + UpdatedAt string `json:"updatedAt,omitempty"` + Name string `json:"name,omitempty"` + CreatedAt string `json:"createdAt,omitempty"` +} + +func AuthMiddleware() gin.HandlerFunc { + return func(c *gin.Context) { + if rootToken == "" { + u, err := db.GetUserByID(uint(1)) + if err != nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) + c.Abort() + return + } + rootToken = u.Token + } + token := c.GetHeader("Authorization") + if token == "" || token[:7] != "Bearer " || token[7:] != rootToken { + c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) + c.Abort() + return + } + // 可以在这里对 token 进行验证并检查权限 + + c.Next() + } +} + +func Handleinit(c *gin.Context) { + user, err := db.GetUserByID(1) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + u := db.User{Name: "root", Token: uuid.NewString()} + u.ID = 1 + if err := db.CreateUser(&u); err != nil { + c.JSON(http.StatusOK, gin.H{ + "error": err.Error(), + }) + return + } else { + rootToken = u.Token + resJSON := User{ + false, + int(u.ID), + u.UpdatedAt.Format(time.RFC3339), + u.Name, + u.Token, + u.CreatedAt.Format(time.RFC3339), + } + c.JSON(http.StatusOK, resJSON) + return + } + } + c.JSON(http.StatusOK, gin.H{ + "error": err.Error(), + }) + return + } + if user.ID == uint(1) { + c.JSON(http.StatusOK, gin.H{ + "error": "super user already exists, use cli to reset password", + }) + } +} + +func HandleMe(c *gin.Context) { + u, err := db.GetUserByID(1) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "error": err.Error(), + }) + } + + resJSON := User{ + false, + int(u.ID), + u.UpdatedAt.Format(time.RFC3339), + u.Name, + u.Token, + u.CreatedAt.Format(time.RFC3339), + } + c.JSON(http.StatusOK, resJSON) +} + +func HandleKeys(c *gin.Context) { + keys, err := db.GetAllKeys() + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "error": err.Error(), + }) + } + + c.JSON(http.StatusOK, keys) +} + +func HandleUsers(c *gin.Context) { + users, err := db.GetAllUsers() + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "error": err.Error(), + }) + } + + c.JSON(http.StatusOK, users) +} + +func HandleAddKey(c *gin.Context) { + var body Key + if err := c.BindJSON(&body); err != nil { + c.JSON(http.StatusOK, gin.H{"error": err.Error()}) + return + } + if err := db.AddKey(body.Key, body.Name); err != nil { + c.JSON(http.StatusOK, gin.H{"error": err.Error()}) + return + } + k, err := db.GetKeyrByName(body.Name) + if err != nil { + c.JSON(http.StatusOK, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusCreated, k) +} + +func HandleDelKey(c *gin.Context) { + id := to.Int(c.Param("id")) + if id < 1 { + c.JSON(http.StatusOK, gin.H{"error": "invalid key id"}) + return + } + if err := db.DeleteKey(uint(id)); err != nil { + c.JSON(http.StatusOK, gin.H{"error": "invalid key id"}) + return + } + c.JSON(http.StatusOK, gin.H{"message": "ok"}) +} + +func HandleAddUser(c *gin.Context) { + var body User + if err := c.BindJSON(&body); err != nil { + c.JSON(http.StatusOK, gin.H{"error": err.Error()}) + return + } + // if len(body.Name) == 0 { + // c.JSON(http.StatusOK, gin.H{"error": "invalid user name"}) + // return + // } + + if err := db.AddUser(body.Name, uuid.NewString()); err != nil { + c.JSON(http.StatusOK, gin.H{"error": err.Error()}) + return + } + u, err := db.GetUserByName(body.Name) + if err != nil { + c.JSON(http.StatusOK, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusCreated, u) +} + +func HandleDelUser(c *gin.Context) { + id := to.Int(c.Param("id")) + if id <= 1 { + c.JSON(http.StatusOK, gin.H{"error": "invalid user id"}) + return + } + if err := db.DeleteUser(uint(id)); err != nil { + c.JSON(http.StatusOK, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"message": "ok"}) +} + +func HandleResetUserToken(c *gin.Context) { + id := to.Int(c.Param("id")) + + if err := db.UpdateUser(uint(id), uuid.NewString()); err != nil { + c.JSON(http.StatusOK, gin.H{"error": err.Error()}) + return + } + u, err := db.GetUserByID(uint(id)) + if err != nil { + c.JSON(http.StatusOK, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusOK, u) +} + +func GenerateToken() string { + token := uuid.New() + return token.String() +} diff --git a/pkg/opencatd/db/db.go b/pkg/opencatd/db/db.go index 7f7e6aa..44c1688 100644 --- a/pkg/opencatd/db/db.go +++ b/pkg/opencatd/db/db.go @@ -1,6 +1,9 @@ package db import ( + "log" + "os" + "gorm.io/driver/sqlite" "gorm.io/gorm" ) @@ -8,6 +11,12 @@ import ( var db *gorm.DB func init() { + if _, err := os.Stat("db"); os.IsNotExist(err) { + errDir := os.MkdirAll("db", 0755) + if errDir != nil { + log.Fatalln("Error creating directory:", err) + } + } var err error db, err = gorm.Open(sqlite.Open("./db/cat.db"), &gorm.Config{}) if err != nil { @@ -15,7 +24,7 @@ func init() { } // 自动迁移 User 结构体 - err = db.AutoMigrate(&User{}) + err = db.AutoMigrate(&User{}, &Key{}) if err != nil { panic(err) } diff --git a/pkg/opencatd/db/keydb.go b/pkg/opencatd/db/keydb.go index e2709e0..49e028e 100644 --- a/pkg/opencatd/db/keydb.go +++ b/pkg/opencatd/db/keydb.go @@ -1,18 +1,38 @@ package db -import "gorm.io/gorm" +import "time" type Key struct { - gorm.Model - ApiKey string - UserId string + ID uint `gorm:"primarykey" json:"id,omitempty"` + Key string `gorm:"unique;not null" json:"key,omitempty"` + Name string `gorm:"unique;not null" json:"name,omitempty"` + UserId string `json:"-,omitempty"` + CreatedAt time.Time `json:"createdAt,omitempty"` + UpdatedAt time.Time `json:"updatedAt,omitempty"` +} + +func GetKeyrByName(name string) (*Key, error) { + var key Key + result := db.First(&key, "name = ?", name) + if result.Error != nil { + return nil, result.Error + } + return &key, nil +} + +func GetAllKeys() ([]Key, error) { + var keys []Key + if err := db.Find(&keys).Error; err != nil { + return nil, err + } + return keys, nil } // 添加记录 -func AddKey(apiKey string, userId string) error { +func AddKey(apikey, name string) error { key := Key{ - ApiKey: apiKey, - UserId: userId, + Key: apikey, + Name: name, } if err := db.Create(&key).Error; err != nil { return err @@ -29,9 +49,9 @@ func DeleteKey(id uint) error { } // 更新记录 -func UpdateKey(id uint, apiKey string, userId string) error { +func UpdateKey(id uint, apikey string, userId string) error { key := Key{ - ApiKey: apiKey, + Key: apikey, UserId: userId, } if err := db.Model(&Key{}).Where("id = ?", id).Updates(key).Error; err != nil { diff --git a/pkg/opencatd/db/userdb.go b/pkg/opencatd/db/userdb.go index 0757341..db7f415 100644 --- a/pkg/opencatd/db/userdb.go +++ b/pkg/opencatd/db/userdb.go @@ -1,11 +1,25 @@ package db -import "gorm.io/gorm" +import ( + "time" +) type User struct { - gorm.Model - Name string `gorm:"not null"` - Token string `gorm:"unique;not null"` + IsDelete bool `gorm:"default:false" json:"IsDelete"` + ID uint `gorm:"primarykey" json:"id,omitempty"` + Name string `gorm:"unique;not null" json:"name,omitempty"` + Token string `gorm:"unique;not null" json:"token,omitempty"` + CreatedAt time.Time `json:"createdAt,omitempty"` + UpdatedAt time.Time `json:"updatedAt,omitempty"` + // DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +func CreateUser(u *User) error { + result := db.Create(u) + if result.Error != nil { + return result.Error + } + return nil } // 添加用户 @@ -28,11 +42,38 @@ func DeleteUser(id uint) error { } // 修改用户 -func UpdateUser(id uint, name, token string) error { - user := &User{Name: name, Token: token} +func UpdateUser(id uint, token string) error { + user := &User{Token: token} result := db.Model(&User{}).Where("id = ?", id).Updates(user) if result.Error != nil { return result.Error } return nil } + +func GetUserByID(id uint) (*User, error) { + var user User + result := db.Where("id = ?", id).First(&user) + if result.Error != nil { + return nil, result.Error + } + return &user, nil +} + +func GetUserByName(name string) (*User, error) { + var user User + result := db.Where(&User{Name: name}).First(&user) + if result.Error != nil { + return nil, result.Error + } + return &user, nil +} + +func GetAllUsers() ([]*User, error) { + var users []*User + result := db.Find(&users) + if result.Error != nil { + return nil, result.Error + } + return users, nil +}