diff --git a/server/adminserver/api/account.go b/server/adminserver/api/account.go new file mode 100644 index 00000000..9270dc90 --- /dev/null +++ b/server/adminserver/api/account.go @@ -0,0 +1,2 @@ +package api + diff --git a/server/adminserver/api/guild.go b/server/adminserver/api/guild.go new file mode 100644 index 00000000..a5f5953b --- /dev/null +++ b/server/adminserver/api/guild.go @@ -0,0 +1,115 @@ +package api + +import ( + "f5" + "github.com/gin-gonic/gin" + "main/model" + "math/rand" + "net/http" + "q5" +) + +func (server *Server) listGuilds(ctx *gin.Context) { + guilds, err := model.ListGuilds() + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to list guilds"}) + return + } + ctx.JSON(http.StatusOK, guilds) +} + +func randLeaderId() string { + randomNum := generateRandomNumber(100000, 999999) + return q5.ToString(randomNum) +} + +type createGuildRequest struct { + Name string `json:"name" binding:"required"` + LeaderId string `json:"leader_id" binding:"required"` +} + +func (server *Server) createGuild(ctx *gin.Context) { + var req createGuildRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + var guild model.Guild + guild.GuildId = f5.GetApp().NewUuid() + guild.Name = req.Name + guild.LeaderId = randLeaderId() + autoId, err := model.CreateGuild(&guild) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create guild"}) + return + } + + ctx.JSON(http.StatusCreated, gin.H{"autoId": autoId, "guildId": guild.GuildId}) +} + +type getGuildReq struct { + GuildId int64 `uri:"guild_id" binding:"required,min=1"` +} + +func (server *Server) getGuild(ctx *gin.Context) { + var req getGuildReq + if err := ctx.ShouldBindUri(&req); err != nil { + ctx.JSON(http.StatusBadRequest, errorResponse(err)) + return + } + + guild, err := model.GetGuild(req.GuildId) + if err != nil { + ctx.JSON(http.StatusInternalServerError, errorResponse(err)) + return + } + + ctx.JSON(http.StatusOK, guild) +} + +type deleteGuildReq struct { + GuildId int64 `uri:"guild_id" binding:"required,min=1"` +} + +func (server *Server) deleteGuild(ctx *gin.Context) { + var req deleteGuildReq + if err := ctx.ShouldBindUri(&req); err != nil { + ctx.JSON(http.StatusBadRequest, errorResponse(err)) + return + } + + err := model.DeleteGuild(req.GuildId) + if err != nil { + ctx.JSON(http.StatusInternalServerError, errorResponse(err)) + return + } + + ctx.JSON(http.StatusOK, "OK") +} + +type updateGuildNoticeReq struct { + GuildId int64 `uri:"guild_id" binding:"required,min=1"` + Notice int64 `uri:"notice" binding:"required,min=1"` +} + +// TODO +func (server *Server) updateGuildNotice(ctx *gin.Context) { + var req deleteGuildReq + if err := ctx.ShouldBindUri(&req); err != nil { + ctx.JSON(http.StatusBadRequest, errorResponse(err)) + return + } + + err := model.DeleteGuild(req.GuildId) + if err != nil { + ctx.JSON(http.StatusInternalServerError, errorResponse(err)) + return + } + + ctx.JSON(http.StatusOK, "OK") +} + +func generateRandomNumber(min, max int) int { + return rand.Intn(max-min+1) + min +} diff --git a/server/adminserver/api/server.go b/server/adminserver/api/server.go new file mode 100644 index 00000000..3f51dda6 --- /dev/null +++ b/server/adminserver/api/server.go @@ -0,0 +1,43 @@ +package api + +import ( + "github.com/gin-gonic/gin" + "github.com/jmoiron/sqlx" +) + +// Server serves HTTP requests for our banking service. +type Server struct { + store *sqlx.DB + router *gin.Engine +} + +func NewServer(store *sqlx.DB) (*Server, error) { + server := &Server{ + store: store, + } + + server.setupRouter() + return server, nil +} + +func (server *Server) setupRouter() { + router := gin.Default() + + router.GET("/guilds", server.listGuilds) + router.GET("/guilds/:guild_id", server.getGuild) + router.POST("/guilds", server.createGuild) + router.DELETE("/guilds/:guild_id", server.deleteGuild) + + authRoutes := router.Group("/") + authRoutes.GET("/accounts", server.listAccounts) + + server.router = router +} + +func (server *Server) Start(address string) error { + return server.router.Run(address) +} + +func errorResponse(err error) gin.H { + return gin.H{"error": err.Error()} +} diff --git a/server/adminserver/api/user.go b/server/adminserver/api/user.go new file mode 100644 index 00000000..daa8e9fa --- /dev/null +++ b/server/adminserver/api/user.go @@ -0,0 +1,96 @@ +package api + +import ( + "github.com/gin-gonic/gin" + "main/model" + "net/http" + "time" +) + +type createUserRequest struct { + Username string `json:"username" binding:"required,alphanum"` + Password string `json:"password" binding:"required,min=6"` + FullName string `json:"full_name" binding:"required"` + Email string `json:"email" binding:"required,email"` +} + +type userResponse struct { + Username string `json:"username"` + FullName string `json:"full_name"` + Email string `json:"email"` + PasswordChangedAt time.Time `json:"password_changed_at"` + CreatedAt time.Time `json:"created_at"` +} + +func (server *Server) listUsers(ctx *gin.Context) { + users, err := model.ListUsers() + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to list users"}) + return + } + ctx.JSON(http.StatusOK, users) +} + +func (server *Server) createUser(ctx *gin.Context) { + var req createUserRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + ctx.JSON(http.StatusBadRequest, errorResponse(err)) + return + } + + rsp := "" + ctx.JSON(http.StatusOK, rsp) +} + +type loginUserRequest struct { + Username string `json:"username" binding:"required,alphanum"` + Password string `json:"password" binding:"required,min=6"` +} + +type loginUserResponse struct { + SessionID string `json:"session_id"` + AccessToken string `json:"access_token"` + AccessTokenExpiresAt time.Time `json:"access_token_expires_at"` + RefreshToken string `json:"refresh_token"` + RefreshTokenExpiresAt time.Time `json:"refresh_token_expires_at"` + User userResponse `json:"user"` +} + +type Account struct { + ID int64 `json:"id"` + Owner string `json:"owner"` + Balance int64 `json:"balance"` + Currency string `json:"currency"` +} + +func (server *Server) loginUser(ctx *gin.Context) { + +} + +func (server *Server) createAccount(ctx *gin.Context) { + +} + +func (server *Server) getAccount(ctx *gin.Context) { + +} + +func (server *Server) listAccounts(ctx *gin.Context) { + account1 := &Account{ + 1, + "2", + 3, + "4", + } + account2 := &Account{ + 11, + "22", + 33, + "44", + } + var accounts []*Account + accounts = append(accounts, account1) + accounts = append(accounts, account2) + + ctx.JSON(http.StatusOK, accounts) +} diff --git a/server/adminserver/app.go b/server/adminserver/app.go index 9602567c..755bbe8e 100644 --- a/server/adminserver/app.go +++ b/server/adminserver/app.go @@ -2,6 +2,7 @@ package main import ( "f5" + "main/db" "mt" ) @@ -15,6 +16,7 @@ func (this *App) GetPkgName() string { func (this *App) Init() { f5.LoadMetaTable(mt.Table) this.registerDataSources() + db.InitDB() ginMgr.init() } diff --git a/server/adminserver/db/db.go b/server/adminserver/db/db.go new file mode 100644 index 00000000..bcb5a464 --- /dev/null +++ b/server/adminserver/db/db.go @@ -0,0 +1,40 @@ +package db + +import ( + "f5" + _ "github.com/go-sql-driver/mysql" + "github.com/jmoiron/sqlx" +) + +var db *sqlx.DB + +// go get github.com/jmoiron/sqlx + +func InitDB() { + var err error + dsn := "root:keji178@tcp(login-test.kingsome.cn:3306)/frienddb_dev_1?charset=utf8mb4&parseTime=True" + db, err = sqlx.Connect("mysql", dsn) + if err != nil { + f5.GetSysLog().Info("Failed to connect to the database err:%v \n", err) + } + if err = db.Ping(); err != nil { + f5.GetSysLog().Info("Database ping failed:%v \n", err) + } + f5.GetSysLog().Info("Connected to the database\n") +} + +//func NewDB() *sqlx.DB { +// Db, err := sqlx.Open("mysql", "root:keji178@/gamedb2006_dev_1?parseTime=true") +// if err != nil { +// f5.GetSysLog().Info("cannot open mysql err:%v \n", err) +// } +// return Db +//} + +func GetDB() *sqlx.DB { + return db +} + +func Close() error { + return db.Close() +} diff --git a/server/adminserver/db/migration/000001_init_schema.down.sql b/server/adminserver/db/migration/000001_init_schema.down.sql new file mode 100644 index 00000000..e69de29b diff --git a/server/adminserver/db/migration/000001_init_schema.up.sql b/server/adminserver/db/migration/000001_init_schema.up.sql new file mode 100644 index 00000000..e69de29b diff --git a/server/adminserver/ginmgr.go b/server/adminserver/ginmgr.go index 5c031ca3..491c4268 100644 --- a/server/adminserver/ginmgr.go +++ b/server/adminserver/ginmgr.go @@ -1,10 +1,12 @@ package main import ( - "time" - "net/http" + "adminsever/api" + "adminsever/db" + "f5" "github.com/gin-gonic/gin" "golang.org/x/sync/errgroup" + "net/http" ) type GinMgr struct { @@ -12,15 +14,16 @@ type GinMgr struct { } func (this *GinMgr) init() { - server01 := &http.Server{ - Addr: ":8080", - Handler: this.router(), - ReadTimeout: 5 * time.Second, - WriteTimeout: 10 * time.Second, - } - this.group.Go(func() error { - return server01.ListenAndServe() - }) + runGinServer() + //server01 := &http.Server{ + // Addr: ":8080", + // Handler: this.router(), + // ReadTimeout: 5 * time.Second, + // WriteTimeout: 10 * time.Second, + //} + //this.group.Go(func() error { + // return server01.ListenAndServe() + //}) } func (this *GinMgr) unInit() { @@ -32,8 +35,20 @@ func (this *GinMgr) router() http.Handler { r.GET("/webapp/index.php", func(c *gin.Context) { c.JSON(200, gin.H{ "errcode": 0, - "errmsg": "", + "errmsg": "", }) }) return r } + +func runGinServer() { + store := db.GetDB() + server, err := api.NewServer(store) + if err != nil { + f5.GetSysLog().Info("cannot create server err:%v \n", err) + } + err = server.Start("localhost:8080") + if err != nil { + f5.GetSysLog().Info("cannot start server err:%v \n", err) + } +} diff --git a/server/adminserver/go.mod b/server/adminserver/go.mod index 5d6e487e..e2830f24 100644 --- a/server/adminserver/go.mod +++ b/server/adminserver/go.mod @@ -26,9 +26,10 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.15.3 // indirect - github.com/go-sql-driver/mysql v1.5.0 // indirect + github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/gomodule/redigo v1.8.3 // indirect + github.com/jmoiron/sqlx v1.3.5 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/leodido/go-urn v1.2.4 // indirect diff --git a/server/adminserver/go.sum b/server/adminserver/go.sum index 1e716bb3..c9c7f6a5 100644 --- a/server/adminserver/go.sum +++ b/server/adminserver/go.sum @@ -26,6 +26,8 @@ github.com/go-playground/validator/v10 v10.15.3 h1:S+sSpunYjNPDuXkWbK+x+bA7iXiW2 github.com/go-playground/validator/v10 v10.15.3/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= @@ -34,6 +36,8 @@ github.com/gomodule/redigo v1.8.3/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUz github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= +github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -42,8 +46,10 @@ github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZY github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= diff --git a/server/adminserver/model/guild.go b/server/adminserver/model/guild.go new file mode 100644 index 00000000..43b944d1 --- /dev/null +++ b/server/adminserver/model/guild.go @@ -0,0 +1,82 @@ +package model + +import ( + "database/sql" + "log" + "main/db" +) + +type Guild struct { + AutoId int64 `db:"idx"` + GuildId int64 `db:"guild_id"` + Name string `db:"name"` + LeaderId string `db:"leader_account_id"` + Avatar int32 `db:"avatar"` + Notice sql.NullString `db:"notice"` + JoinCond int32 `db:"join_cond"` + JoinCondValue int32 `db:"join_cond_value"` + TotalStars int32 `db:"total_stars"` + TotalKills int32 `db:"total_kills"` + ChickenDinners int32 `db:"chicken_dinners"` + MaxMembers int32 `db:"max_members"` +} + +func CreateGuild(guild *Guild) (int64, error) { + query := "INSERT INTO t_guild (guild_id, name, leader_account_id) VALUES (?, ?, ?)" + result, err := db.GetDB().Exec(query, guild.GuildId, guild.Name, guild.LeaderId) + if err != nil { + log.Printf("Error creating guild: %v", err) + return 0, err + } + autoId, err := result.LastInsertId() + if err != nil { + log.Printf("Error getting last insert ID: %v", err) + return 0, err + } + return autoId, nil +} + +func GetGuild(guildId int64) (*Guild, error) { + query := "SELECT idx, guild_id, name, leader_account_id, avatar, notice, join_cond, join_cond_value, total_stars, total_kills, chicken_dinners, max_members FROM t_guild WHERE guild_id = ?" + var guild Guild + err := db.GetDB().Get(&guild, query, guildId) + if err != nil { + if err == sql.ErrNoRows { + return nil, nil // 不存在 + } + log.Printf("Error getting guild by ID: %v", err) + return nil, err + } + return &guild, nil +} + +func UpdateGuildNotice(guild *Guild) error { + query := "UPDATE t_guild SET `notice`=? WHERE guild_id = ?" + _, err := db.GetDB().Exec(query, guild.Notice, guild.GuildId) + if err != nil { + log.Printf("Error updating guild notice: %v", err) + return err + } + return nil +} + +func DeleteGuild(guildId int64) error { + query := "UPDATE t_guild SET `is_deleted`=? WHERE guild_id = ?" + _, err := db.GetDB().Exec(query, 1, guildId) + if err != nil { + log.Printf("Error deleting guild: %v", err) + return err + } + return nil +} + +func ListGuilds() ([]Guild, error) { + query := "SELECT idx, guild_id, name, leader_account_id, avatar, notice, join_cond, join_cond_value, total_stars, total_kills, chicken_dinners, max_members FROM t_guild WHERE is_deleted=0" + var guilds []Guild + err := db.GetDB().Select(&guilds, query) + if err != nil { + log.Printf("Error listing users: %v", err) + return nil, err + } + return guilds, nil +} diff --git a/server/adminserver/model/user.go b/server/adminserver/model/user.go new file mode 100644 index 00000000..871c0b0b --- /dev/null +++ b/server/adminserver/model/user.go @@ -0,0 +1,79 @@ +package model + +import ( + "database/sql" + "log" + "main/db" +) + +// User 结构体表示用户 +type User struct { + AccountId string `db:"account_id"` + Username string `db:"name"` + Level int32 `db:"level"` +} + +// CreateUser 创建新用户 +func CreateUser(user *User) (int64, error) { + query := "INSERT INTO users (username, email) VALUES (?, ?)" + result, err := db.GetDB().Exec(query, user.Username, user.Level) + if err != nil { + log.Printf("Error creating user: %v", err) + return 0, err + } + userID, err := result.LastInsertId() + if err != nil { + log.Printf("Error getting last insert ID: %v", err) + return 0, err + } + return userID, nil +} + +// GetUserByID 根据用户ID获取用户信息 +func GetUserByID(userID int64) (*User, error) { + query := "SELECT id, username, email FROM users WHERE id = ?" + var user User + err := db.GetDB().Get(&user, query, userID) + if err != nil { + if err == sql.ErrNoRows { + return nil, nil // 用户不存在 + } + log.Printf("Error getting user by ID: %v", err) + return nil, err + } + return &user, nil +} + +// UpdateUser 更新用户信息 +func UpdateUser(user *User) error { + query := "UPDATE users SET username = ?, level = ? WHERE id = ?" + _, err := db.GetDB().Exec(query, user.Username, user.Level, user.AccountId) + if err != nil { + log.Printf("Error updating user: %v", err) + return err + } + return nil +} + +// DeleteUser 删除用户 +func DeleteUser(userID int64) error { + query := "DELETE FROM users WHERE id = ?" + _, err := db.GetDB().Exec(query, userID) + if err != nil { + log.Printf("Error deleting user: %v", err) + return err + } + return nil +} + +// ListUsers 获取所有用户列表 +func ListUsers() ([]User, error) { + query := "SELECT account_id, name, level FROM t_user" + var users []User + err := db.GetDB().Select(&users, query) + if err != nil { + log.Printf("Error listing users: %v", err) + return nil, err + } + return users, nil +}