up
This commit is contained in:
@@ -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"`
|
||||
}
|
||||
|
||||
6
go.mod
6
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
|
||||
|
||||
132
opencatd/db/cat.go
Normal file
132
opencatd/db/cat.go
Normal file
@@ -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)
|
||||
}
|
||||
172
opencatd/opencat.go
Normal file
172
opencatd/opencat.go
Normal file
@@ -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()
|
||||
}
|
||||
108
opencatd/opencatd.c
Normal file
108
opencatd/opencatd.c
Normal file
@@ -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
|
||||
|
||||
57
pkg/opencatd/db/db.go
Normal file
57
pkg/opencatd/db/db.go
Normal file
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user