package model import ( "backend/store" "backend/util" "fmt" "strings" "github.com/gin-gonic/gin" ) type Admin struct { ID int `json:"id" db:"id"` Username string `json:"username" db:"username"` Password string `json:"password" db:"password"` RealName string `json:"real_name" db:"real_name"` Nickname string `json:"nickname" db:"nickname"` Phone string `json:"phone" db:"phone"` Email string `json:"email" db:"email"` Token string `json:"token" db:"token"` Group string `json:"group" db:"group"` Status int `json:"status" db:"status"` Expires int `json:"expires" db:"expires"` Role int `json:"role" db:"role"` LastLoginTime int `json:"lastLoginTime" db:"lastLoginTime"` LastLoginIP string `json:"lastLoginIp" db:"lastLoginIp"` CreateTime int `json:"createTime" db:"createTime"` UpdateTime int `json:"updateTime" db:"updateTime"` Remark string `json:"remark" db:"remark"` } type AdminLog struct { ID int `json:"id" db:"id"` Admin string `json:"admin" db:"admin"` Action string `json:"action" db:"action"` Params string `json:"params" db:"params"` IP string `json:"ip" db:"ip"` CreateTime int `json:"createTime" db:"createTime"` } func (a *Admin) List() (*Result, error) { var admins []Admin db := util.MPool.GetGameDB() defer db.Close() if db == nil { return nil, fmt.Errorf("failed to get database connection") } err := db.Select(&admins, "SELECT `id`,`username`,`real_name`,`nickname`,`phone`,`email`,`group`,`status`,`role`,`lastLoginTime`,`lastLoginIp`,`createTime`,`updateTime`,`remark` FROM admin ORDER BY id DESC") if err != nil { return nil, fmt.Errorf("failed to scan rows: %v", err) } var total int db.Get(&total, "SELECT COUNT(*) FROM admin") return &Result{ Data: admins, Total: total, }, nil } func (a *Admin) Add() (*Result, error) { // 这里可以添加逻辑来保存管理员信息到数据库 // 假设我们将管理员信息插入到数据库中 db := util.MPool.GetGameDB() // 假设使用默认的AppConfig和ServerId为0 defer db.Close() if db == nil { return nil, fmt.Errorf("failed to get database connection") } defer db.Close() a.CreateTime = int(util.Now()) a.UpdateTime = a.CreateTime if a.Status == 0 { a.Status = 1 // 默认启用 } a.Password, _ = util.Encrypt(a.Password) _, err := db.NamedExec("INSERT INTO admin (`username`, `password`, `real_name`, `nickname`, `phone`, `email`, `token`, `group`, `status`, `role`, `createTime`, `updateTime`, `expires`, `remark`) VALUES (:username, :password, :real_name, :nickname, :phone, :email, :token, :group, :status, :role, :createTime, :updateTime, :expires, :remark)", a) if err != nil { return nil, fmt.Errorf("failed to add admin: %v", err) } var total int db.Get(&total, "SELECT COUNT(*) FROM admin") return &Result{ Data: a, Total: total, }, nil } func (a *Admin) Login() (*Admin, error) { // 这里可以添加逻辑来验证用户名和密码 // 假设我们从数据库中查询到管理员信息并返回 db := util.MPool.GetGameDB() // 假设使用默认的AppConfig和ServerId为0 defer db.Close() if db == nil { return nil, fmt.Errorf("failed to get database connection") } var admin Admin err := db.Get(&admin, "SELECT * FROM admin WHERE username = ?", a.Username) admin.Password, _ = util.Decrypt(admin.Password) // 假设有一个解密函数Login if err != nil { return nil, fmt.Errorf("账号不存在") } if admin.Password != a.Password { return nil, fmt.Errorf("密码错误") } if (admin.Expires > 0 && admin.Expires < int(util.Now())) || admin.Token == "" || admin.Expires == 0 { admin.CreateToken() // 如果令牌过期,重新生成令牌 } return &Admin{ ID: admin.ID, Username: admin.Username, Token: admin.Token, }, nil } func (a *Admin) LoginByCode(phone, code string) (*Admin, error) { db := util.MPool.GetGameDB() // 假设使用默认的AppConfig和ServerId为0 defer db.Close() if db == nil { return nil, fmt.Errorf("failed to get database connection") } var admin Admin err := db.Get(&admin, "SELECT * FROM admin WHERE phone = ?", phone) if (admin.Expires > 0 && admin.Expires < int(util.Now())) || admin.Token == "" || admin.Expires == 0 { admin.CreateToken() // 如果令牌过期,重新生成令牌 } if err != nil { return nil, fmt.Errorf("账号不存在") } if code == "" { return nil, fmt.Errorf("验证码不能为空") } storedCode, exists := store.GetCode(phone) if !exists || storedCode != code { return nil, fmt.Errorf("验证码错误") } return &Admin{ ID: admin.ID, Username: admin.Username, Token: admin.Token, }, nil } func (a *Admin) CreateToken() error { // 这里可以添加逻辑来生成令牌 // 假设我们生成一个新的令牌并更新到数据库中 a.Token = util.GenerateToken() // 假设有一个生成令牌的函数 db := util.MPool.GetGameDB() // 假设使用默认的AppConfig和ServerId为0 defer db.Close() if db == nil { return fmt.Errorf("failed to get database connection") } a.Expires = int(util.Now()) + 604800 store.AddToken(a.Token, int64(a.Expires), a.Username, util.GetRole(a.Role)) // 添加到TokenList _, err := db.NamedExec("UPDATE admin SET token = :token, expires = :expires WHERE id = :id", a) if err != nil { return fmt.Errorf("failed to update token: %v", err) } return nil } func (a *Admin) GetAdmin(username string) error { db := util.MPool.GetGameDB() // 假设使用默认的AppConfig和ServerId为0 defer db.Close() if db == nil { return fmt.Errorf("failed to get database connection") } return db.Get(a, "SELECT `username`, `role`, `password`, `token`, `group`, `remark` FROM admin WHERE username = ?", username) } func InitToken() { // 初始化TokenList,可以从数据库中加载现有的令牌 db := util.MPool.GetGameDB() // 假设使用默认的AppConfig和ServerId为0 defer db.Close() if db == nil { return } var tokens []struct { Token string `db:"token"` Expires int64 `db:"expires"` UserName string `db:"username"` Role int `db:"role"` // 假设有一个角色字段 } err := db.Select(&tokens, "SELECT username, token, expires, role FROM admin WHERE token IS NOT NULL") if err != nil { return // 处理错误 } for _, t := range tokens { store.AddToken(t.Token, t.Expires, t.UserName, util.GetRole(t.Role)) } } func (a *Admin) Edit() error { db := util.MPool.GetGameDB() defer db.Close() if db == nil { return fmt.Errorf("failed to get database connection") } a.UpdateTime = int(util.Now()) if a.Password != "" { a.Password, _ = util.Encrypt(a.Password) _, err := db.NamedExec("UPDATE admin SET `real_name`=:real_name, `nickname`=:nickname, `phone`=:phone, `email`=:email, `group`=:group, `role`=:role, `status`=:status, `remark`=:remark, `password`=:password, `updateTime`=:updateTime WHERE id=:id", a) return err } _, err := db.NamedExec("UPDATE admin SET `real_name`=:real_name, `nickname`=:nickname, `phone`=:phone, `email`=:email, `group`=:group, `role`=:role, `status`=:status, `remark`=:remark, `updateTime`=:updateTime WHERE id=:id", a) return err } func (a *Admin) Delete() error { db := util.MPool.GetGameDB() defer db.Close() if db == nil { return fmt.Errorf("failed to get database connection") } _, err := db.Exec("DELETE FROM admin WHERE id = ?", a.ID) return err } func SendPhoneCode(phone string) error { // 这里可以添加逻辑来发送验证码到手机 // 假设我们使用一个外部服务发送验证码 Code, err := util.GeneratedCode(phone) // 假设有一个发送短信的函数 store.AddCode(phone, Code) // 将验证码存储到CodeList if err != nil { return fmt.Errorf("failed to send code: %v", err) } return nil } // CheckUserPermission 基于 admin_permission 表进行动态 DB 鉴权。 // 鉴权优先级:super 全放行 → 路径无受控权限点放行 → // 用户直接权限(显式允许/拒绝)→ 用户组→角色→权限链路 → 默认拒绝。 func CheckUserPermission(username, path, method string) bool { db := util.MPool.GetGameDB() if db == nil { return false } defer db.Close() // 查询用户 ID 和角色 var adminInfo struct { ID int `db:"id"` Role int `db:"role"` } if err := db.Get(&adminInfo, "SELECT id, role FROM admin WHERE username = ?", username); err != nil { return false } // super 超级管理员跳过所有权限检查 if util.GetRole(adminInfo.Role) == util.RoleSuper { return true } // 用户通过用户组继承到 R_SUPER 角色时放行 var superRoleCount int if err := db.Get(&superRoleCount, `SELECT COUNT(*) FROM admin_user_group_rel ugr INNER JOIN admin_group_role_rel grr ON grr.group_id = ugr.group_id INNER JOIN admin_role r ON r.id = grr.role_id WHERE ugr.admin_id = ? AND r.role_code = 'R_SUPER' AND r.status = 1`, adminInfo.ID, ); err == nil && superRoleCount > 0 { return true } // 查找匹配路径的受控权限点(http_method 为空视为不限方法) var permIDs []int if err := db.Select(&permIDs, "SELECT id FROM admin_permission WHERE api_path = ? AND status = 1 AND (http_method = '' OR http_method = ?)", path, method, ); err != nil || len(permIDs) == 0 { // 路径未被任何权限点管控 → 放行 return true } // 检查用户直接权限(优先级最高) for _, pid := range permIDs { var grantType int err := db.Get(&grantType, "SELECT grant_type FROM admin_user_permission_rel WHERE admin_id = ? AND permission_id = ?", adminInfo.ID, pid, ) if err == nil { if grantType == 2 { return false // 显式拒绝 } if grantType == 1 { return true // 显式允许 } } } // 检查 用户 → 用户组 → 角色 → 权限 链路 placeholders := make([]string, len(permIDs)) pidArgs := make([]interface{}, 1+len(permIDs)) pidArgs[0] = adminInfo.ID for i, pid := range permIDs { placeholders[i] = "?" pidArgs[i+1] = pid } var count int q := fmt.Sprintf( `SELECT COUNT(*) FROM admin_role_permission_rel rpr INNER JOIN admin_group_role_rel grr ON grr.role_id = rpr.role_id INNER JOIN admin_user_group_rel ugr ON ugr.group_id = grr.group_id WHERE ugr.admin_id = ? AND rpr.permission_id IN (%s)`, strings.Join(placeholders, ","), ) if err := db.Get(&count, q, pidArgs...); err == nil && count > 0 { return true } return false } func GetAdminRole(c *gin.Context) (string, error) { username := c.GetString("admin") Admin := &Admin{} err := Admin.GetAdmin(username) if err != nil { return "", err } return util.GetRole(Admin.Role), nil }