diff --git a/getway/main.go b/getway/main.go index 1339880..fab2799 100644 --- a/getway/main.go +++ b/getway/main.go @@ -12,6 +12,7 @@ import ( "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt" "github.com/google/go-github/v50/github" + "github.com/joho/godotenv" "golang.org/x/oauth2" ogithub "golang.org/x/oauth2/github" "gorm.io/driver/mysql" @@ -19,15 +20,19 @@ import ( ) var db *gorm.DB -var jwtSecret = []byte(os.Getenv("JWT_SECRET")) +var jwtSecret = []byte("JWT_SECRET") func main() { + err := godotenv.Load() + if err != nil { + log.Fatal("Error loading .env file") + } initDB() router := gin.Default() router.Use(cors.New(cors.Config{ - AllowOrigins: []string{"http://localhost:8080"}, + AllowOrigins: []string{"http://localhost:8000"}, AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"}, AllowHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"}, AllowCredentials: true, @@ -40,7 +45,8 @@ func main() { } func githubLoginHandler(c *gin.Context) { - state := generateState() + state := "1234567890" + // state := generateState() // code := generateCode() // err := storeStateToDB(state, code) @@ -110,7 +116,7 @@ func githubCallbackHandler(c *gin.Context) { } c.SetCookie("token", jwtToken, 60*60*24, "/", "localhost", false, true) - c.Redirect(http.StatusFound, "http://localhost:8080/#/") + c.Redirect(http.StatusFound, "http://localhost:8080/") } func initDB() { @@ -202,3 +208,11 @@ func generateJWTToken(userID int64) (string, error) { return jwtToken, nil } + +type GithubUser struct { + ID int `json:"id"` + Login string `json:"login"` + Name string `json:"name"` + AvatarURL string `json:"avatar_url"` + Email string `json:"email"` +} diff --git a/go.mod b/go.mod index 8f98754..c78fcb5 100644 --- a/go.mod +++ b/go.mod @@ -8,10 +8,13 @@ require ( github.com/golang-jwt/jwt v3.2.2+incompatible github.com/google/go-github v17.0.0+incompatible github.com/google/go-github/v50 v50.2.0 + github.com/google/uuid v1.3.0 github.com/gorilla/websocket v1.5.0 + github.com/joho/godotenv v1.5.1 golang.org/x/oauth2 v0.6.0 gorm.io/driver/mysql v1.4.7 - gorm.io/gorm v1.23.8 + gorm.io/driver/sqlite v1.4.4 + gorm.io/gorm v1.24.0 ) require ( @@ -33,6 +36,7 @@ require ( github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-sqlite3 v1.14.15 // indirect github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect diff --git a/opencatd/db/cat.go b/opencatd/db/cat.go new file mode 100644 index 0000000..c533e80 --- /dev/null +++ b/opencatd/db/cat.go @@ -0,0 +1,132 @@ +package db + +import ( + "database/sql" + "fmt" + "log" + "net/http" + "time" + + "github.com/gin-gonic/gin" +) + +type User struct { + ID int `json:"id"` + Name string `json:"name"` + Token string `json:"token"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` + IsDelete bool `json:"isDelete"` +} + +func addUser(c *gin.Context) { + var user User + if err := c.ShouldBindJSON(&user); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + db, err := sql.Open("sqlite3", "test.db") + if err != nil { + log.Fatal(err) + } + + stmt, err := db.Prepare("INSERT INTO users(name, token, created_at, updated_at, is_delete) values(?,?,?,?,?)") + if err != nil { + log.Fatal(err) + } + + res, err := stmt.Exec(user.Name, user.Token, user.CreatedAt, user.UpdatedAt, user.IsDelete) + if err != nil { + log.Fatal(err) + } + + id, err := res.LastInsertId() + if err != nil { + log.Fatal(err) + } + + user.ID = int(id) + + c.JSON(http.StatusOK, user) +} + +func updateUser(c *gin.Context) { + id := c.Param("id") + + var user User + if err := c.ShouldBindJSON(&user); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + db, err := sql.Open("sqlite3", "test.db") + if err != nil { + log.Fatal(err) + } + + stmt, err := db.Prepare("UPDATE users SET name=?, token=?, created_at=?, updated_at=?, is_delete=? WHERE id=?") + if err != nil { + log.Fatal(err) + } + + _, err = stmt.Exec(user.Name, user.Token, user.CreatedAt, user.UpdatedAt, user.IsDelete, id) + if err != nil { + log.Fatal(err) + } + + c.JSON(http.StatusOK, user) +} + +func deleteUser(c *gin.Context) { + id := c.Param("id") + + db, err := sql.Open("sqlite3", "test.db") + if err != nil { + log.Fatal(err) + } + + stmt, err := db.Prepare("DELETE FROM users WHERE id=?") + if err != nil { + log.Fatal(err) + } + + _, err = stmt.Exec(id) + if err != nil { + log.Fatal(err) + } + + c.JSON(http.StatusOK, gin.H{"message": "ok"}) +} + +func initDB() { + db, err := sql.Open("sqlite3", "test.db") + if err != nil { + log.Fatal(err) + } + defer db.Close() + + _, err = db.Exec("CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY, name TEXT, token TEXT, created_at DATETIME, updated_at DATETIME, is_delete BOOLEAN)") + if err != nil { + log.Fatal(err) + } + + shouldBeDeleted := false + now := time.Now().Format(time.RFC3339) + stmt, err := db.Prepare("INSERT INTO users(name, token, created_at, updated_at, is_delete) values(?,?,?,?,?)") + if err != nil { + log.Fatal(err) + } + + res, err := stmt.Exec("Test User", "123456789", now, now, shouldBeDeleted) + if err != nil { + log.Fatal(err) + } + + id, err := res.LastInsertId() + if err != nil { + log.Fatal(err) + } + + fmt.Printf("New user ID: %d\n", id) +} diff --git a/opencatd/opencat.go b/opencatd/opencat.go new file mode 100644 index 0000000..6539b72 --- /dev/null +++ b/opencatd/opencat.go @@ -0,0 +1,172 @@ +package main + +import ( + "net/http" + "strconv" + + "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() + + // 初始化用户 + 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", + } + + 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() +} diff --git a/opencatd/opencatd.c b/opencatd/opencatd.c new file mode 100644 index 0000000..cbb5524 --- /dev/null +++ b/opencatd/opencatd.c @@ -0,0 +1,108 @@ +docker pull debian:bullseye + +opencat://team/join?domain=http://168.138.211.226&token=f1ad7afa-65fe-436f-bbbb-8df8a35c332e + +"/1/me" +"/1/keys" +"/1/users" + +POST "/1/users/init" + +{ + "IsDelete" : false, + "id" : 1, + "updatedAt" : "2023-03-28T14:13:54.969089197Z", + "name" : "root", + "token" : "3260dd53-463f-45d0-afa4-57acd04ee036", + "createdAt" : "2023-03-28T14:13:54.969089107Z" +} + + +GET "1/me" + +{ + "IsDelete" : false, + "id" : 1, + "updatedAt" : "2023-03-28T12:36:03.907590825Z", + "name" : "root", + "token" : "4930f144-7ffc-469b-8f2d-71a267358d87", + "createdAt" : "2023-03-28T11:52:45.593940257Z" +} + +GET "1/keys" + +[ + { + "id" : 1, + "key" : "1234567890", + "updatedAt" : "2023-03-28T12:53:41.124319079Z", + "name" : "key1", + "createdAt" : "2023-03-28T12:53:41.124318928Z" + } +] + +GET "1/users" + +[ + { + "IsDelete" : false, + "id" : 1, + "updatedAt" : "2023-03-28T12:36:03.907590825Z", + "name" : "root", + "token" : "4930f144-7ffc-469b-8f2d-71a267358d87", + "createdAt" : "2023-03-28T11:52:45.593940257Z" + } +] + +//添加key +POST "/1/keys" body {"key":"1234567890","name":"key1"} + +{ + "id" : 1, + "key" : "1234567890", + "updatedAt" : "2023-03-28T12:53:41.124319079Z", + "name" : "key1", + "createdAt" : "2023-03-28T12:53:41.124318928Z" +} + +//删除KEY +DELETE "1/keys/1" + +{"message":"ok"} + +//添加user +POST "1/users" body{"name":"user1"} +Host: 168.138.211.226 +User-Agent: OpenCat/99 CFNetwork/1404.0.5 Darwin/22.3.0 +Authorization: Bearer 4930f144-7ffc-469b-8f2d-71a267358d87 + +{ + "IsDelete" : false, + "id" : 2, + "updatedAt" : "2023-03-28T12:38:57.513105571Z", + "name" : "user1", + "token" : "f5bbee90-5f10-4501-bbe4-4989d0c41a82", + "createdAt" : "2023-03-28T12:38:57.513105431Z" +} + +//删除user3 +DELETE "1/users/3" + +{"message":"ok"} + +//重置user token +POST "/1/users/2/reset" + +{ + "IsDelete" : false, + "id" : 2, + "updatedAt" : "2023-03-28T13:05:02.103135082Z", + "name" : "user1", + "token" : "87f0af9c-ae80-4754-8de8-2d9522b24dee", + "createdAt" : "2023-03-28T12:38:57.513105431Z" +} + +http://localhost/v1/chat/completions + +./opencatd reset_root + diff --git a/pkg/opencatd/db/db.go b/pkg/opencatd/db/db.go new file mode 100644 index 0000000..0b44a64 --- /dev/null +++ b/pkg/opencatd/db/db.go @@ -0,0 +1,57 @@ +package db + +import ( + "gorm.io/driver/sqlite" + "gorm.io/gorm" +) + +type User struct { + gorm.Model + Name string `gorm:"not null"` + Token string `gorm:"unique;not null"` +} + +var db *gorm.DB + +func init() { + var err error + db, err = gorm.Open(sqlite.Open("./db/cat.db"), &gorm.Config{}) + if err != nil { + panic("failed to connect database") + } + + // 自动迁移 User 结构体 + err = db.AutoMigrate(&User{}) + if err != nil { + panic(err) + } +} + +// 添加用户 +func AddUser(name, token string) error { + user := &User{Name: name, Token: token} + result := db.Create(&user) + if result.Error != nil { + return result.Error + } + return nil +} + +// 删除用户 +func DeleteUser(id uint) error { + result := db.Delete(&User{}, id) + if result.Error != nil { + return result.Error + } + return nil +} + +// 修改用户 +func UpdateUser(id uint, name, token string) error { + user := &User{Name: name, Token: token} + result := db.Model(&User{}).Where("id = ?", id).Updates(user) + if result.Error != nil { + return result.Error + } + return nil +}