mirror of
https://github.com/go-admin-team/go-admin.git
synced 2026-09-24 19:17:43 +00:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ecb1e6e4c | ||
|
|
9c299805c1 | ||
|
|
2a900c9876 | ||
|
|
0008b943a3 | ||
|
|
50c74b1f96 | ||
|
|
ae1eef6d4f | ||
|
|
d01cdc040f | ||
|
|
92b9af17b7 | ||
|
|
898e1b023a |
@@ -3,9 +3,9 @@ package apis
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||
"github.com/go-admin-team/go-admin-core/v2/jwtauth/user"
|
||||
_ "github.com/go-admin-team/go-admin-core/v2/response"
|
||||
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service"
|
||||
@@ -145,4 +145,4 @@ func (e SysApi) DeleteSysApi(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
e.OK(req.GetId(), "删除成功")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package apis
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||
"github.com/go-admin-team/go-admin-core/v2/jwtauth/user"
|
||||
_ "github.com/go-admin-team/go-admin-core/v2/response"
|
||||
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||
"go-admin/app/admin/models"
|
||||
|
||||
"go-admin/app/admin/service"
|
||||
@@ -216,5 +216,5 @@ func (e SysDictData) GetAll(c *gin.Context) {
|
||||
l = append(l, d)
|
||||
}
|
||||
|
||||
e.OK(l,"查询成功")
|
||||
e.OK(l, "查询成功")
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||
"github.com/go-admin-team/go-admin-core/v2/jwtauth/user"
|
||||
_ "github.com/go-admin-team/go-admin-core/v2/response"
|
||||
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||
"go-admin/app/admin/models"
|
||||
|
||||
"go-admin/app/admin/service"
|
||||
@@ -31,7 +31,7 @@ type SysDictType struct {
|
||||
// @Security Bearer
|
||||
func (e SysDictType) GetPage(c *gin.Context) {
|
||||
s := service.SysDictType{}
|
||||
req :=dto.SysDictTypeGetPageReq{}
|
||||
req := dto.SysDictTypeGetPageReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.Form).
|
||||
@@ -62,7 +62,7 @@ func (e SysDictType) GetPage(c *gin.Context) {
|
||||
// @Security Bearer
|
||||
func (e SysDictType) Get(c *gin.Context) {
|
||||
s := service.SysDictType{}
|
||||
req :=dto.SysDictTypeGetReq{}
|
||||
req := dto.SysDictTypeGetReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, nil).
|
||||
@@ -82,7 +82,7 @@ func (e SysDictType) Get(c *gin.Context) {
|
||||
e.OK(object, "查询成功")
|
||||
}
|
||||
|
||||
//Insert 字典类型创建
|
||||
// Insert 字典类型创建
|
||||
// @Summary 添加字典类型
|
||||
// @Description 获取JSON
|
||||
// @Tags 字典类型
|
||||
@@ -94,7 +94,7 @@ func (e SysDictType) Get(c *gin.Context) {
|
||||
// @Security Bearer
|
||||
func (e SysDictType) Insert(c *gin.Context) {
|
||||
s := service.SysDictType{}
|
||||
req :=dto.SysDictTypeInsertReq{}
|
||||
req := dto.SysDictTypeInsertReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.JSON).
|
||||
@@ -109,7 +109,7 @@ func (e SysDictType) Insert(c *gin.Context) {
|
||||
err = s.Insert(&req)
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err,fmt.Sprintf(" 创建字典类型失败,详情:%s", err.Error()))
|
||||
e.Error(500, err, fmt.Sprintf(" 创建字典类型失败,详情:%s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK(req.GetId(), "创建成功")
|
||||
@@ -127,7 +127,7 @@ func (e SysDictType) Insert(c *gin.Context) {
|
||||
// @Security Bearer
|
||||
func (e SysDictType) Update(c *gin.Context) {
|
||||
s := service.SysDictType{}
|
||||
req :=dto.SysDictTypeUpdateReq{}
|
||||
req := dto.SysDictTypeUpdateReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.JSON, nil).
|
||||
@@ -157,7 +157,7 @@ func (e SysDictType) Update(c *gin.Context) {
|
||||
// @Security Bearer
|
||||
func (e SysDictType) Delete(c *gin.Context) {
|
||||
s := service.SysDictType{}
|
||||
req :=dto.SysDictTypeDeleteReq{}
|
||||
req := dto.SysDictTypeDeleteReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.JSON, nil).
|
||||
@@ -189,7 +189,7 @@ func (e SysDictType) Delete(c *gin.Context) {
|
||||
// @Security Bearer
|
||||
func (e SysDictType) GetAll(c *gin.Context) {
|
||||
s := service.SysDictType{}
|
||||
req :=dto.SysDictTypeGetPageReq{}
|
||||
req := dto.SysDictTypeGetPageReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.Form).
|
||||
@@ -207,4 +207,4 @@ func (e SysDictType) GetAll(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
e.OK(list, "查询成功")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ type SysLoginLog struct {
|
||||
// @Security Bearer
|
||||
func (e SysLoginLog) GetPage(c *gin.Context) {
|
||||
s := service.SysLoginLog{}
|
||||
req :=dto.SysLoginLogGetPageReq{}
|
||||
req := dto.SysLoginLogGetPageReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.Form).
|
||||
@@ -60,7 +60,7 @@ func (e SysLoginLog) GetPage(c *gin.Context) {
|
||||
// @Security Bearer
|
||||
func (e SysLoginLog) Get(c *gin.Context) {
|
||||
s := service.SysLoginLog{}
|
||||
req :=dto.SysLoginLogGetReq{}
|
||||
req := dto.SysLoginLogGetReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
@@ -90,7 +90,7 @@ func (e SysLoginLog) Get(c *gin.Context) {
|
||||
// @Security Bearer
|
||||
func (e SysLoginLog) Delete(c *gin.Context) {
|
||||
s := service.SysLoginLog{}
|
||||
req :=dto.SysLoginLogDeleteReq{}
|
||||
req := dto.SysLoginLogDeleteReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.JSON, nil).
|
||||
@@ -107,4 +107,4 @@ func (e SysLoginLog) Delete(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
e.OK(req.GetId(), "删除成功")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ func (e SysOperaLog) GetPage(c *gin.Context) {
|
||||
// @Security Bearer
|
||||
func (e SysOperaLog) Get(c *gin.Context) {
|
||||
s := new(service.SysOperaLog)
|
||||
req :=dto.SysOperaLogGetReq{}
|
||||
req := dto.SysOperaLogGetReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, nil).
|
||||
@@ -96,7 +96,7 @@ func (e SysOperaLog) Get(c *gin.Context) {
|
||||
// @Security Bearer
|
||||
func (e SysOperaLog) Delete(c *gin.Context) {
|
||||
s := new(service.SysOperaLog)
|
||||
req :=dto.SysOperaLogDeleteReq{}
|
||||
req := dto.SysOperaLogDeleteReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.JSON).
|
||||
@@ -111,7 +111,7 @@ func (e SysOperaLog) Delete(c *gin.Context) {
|
||||
err = s.Remove(&req)
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500,err, fmt.Sprintf("删除失败!错误详情:%s", err.Error()))
|
||||
e.Error(500, err, fmt.Sprintf("删除失败!错误详情:%s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK(req.GetId(), "删除成功")
|
||||
|
||||
@@ -2,12 +2,12 @@ package apis
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||
"github.com/go-admin-team/go-admin-core/v2/jwtauth/user"
|
||||
_ "github.com/go-admin-team/go-admin-core/v2/response"
|
||||
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service"
|
||||
@@ -31,7 +31,7 @@ type SysPost struct {
|
||||
// @Security Bearer
|
||||
func (e SysPost) GetPage(c *gin.Context) {
|
||||
s := service.SysPost{}
|
||||
req :=dto.SysPostPageReq{}
|
||||
req := dto.SysPostPageReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.Form).
|
||||
@@ -65,7 +65,7 @@ func (e SysPost) GetPage(c *gin.Context) {
|
||||
// @Security Bearer
|
||||
func (e SysPost) Get(c *gin.Context) {
|
||||
s := service.SysPost{}
|
||||
req :=dto.SysPostGetReq{}
|
||||
req := dto.SysPostGetReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, nil).
|
||||
@@ -99,7 +99,7 @@ func (e SysPost) Get(c *gin.Context) {
|
||||
// @Security Bearer
|
||||
func (e SysPost) Insert(c *gin.Context) {
|
||||
s := service.SysPost{}
|
||||
req :=dto.SysPostInsertReq{}
|
||||
req := dto.SysPostInsertReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.JSON).
|
||||
@@ -131,7 +131,7 @@ func (e SysPost) Insert(c *gin.Context) {
|
||||
// @Security Bearer
|
||||
func (e SysPost) Update(c *gin.Context) {
|
||||
s := service.SysPost{}
|
||||
req :=dto.SysPostUpdateReq{}
|
||||
req := dto.SysPostUpdateReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.JSON, nil).
|
||||
@@ -163,7 +163,7 @@ func (e SysPost) Update(c *gin.Context) {
|
||||
// @Security Bearer
|
||||
func (e SysPost) Delete(c *gin.Context) {
|
||||
s := service.SysPost{}
|
||||
req :=dto.SysPostDeleteReq{}
|
||||
req := dto.SysPostDeleteReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.JSON).
|
||||
@@ -181,4 +181,4 @@ func (e SysPost) Delete(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
e.OK(req.GetId(), "删除成功")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,4 +29,4 @@ func registerSysDeptRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
|
||||
r1.GET("/deptTree", api.Get2Tree)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,4 +21,4 @@ func registerSysLoginLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMi
|
||||
r.GET("/:id", api.Get)
|
||||
r.DELETE("", api.Delete)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,4 +30,4 @@ func registerSysMenuRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
|
||||
//r1.GET("/menuids", api.GetMenuIDS)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,4 +20,4 @@ func registerSysOperaLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMi
|
||||
r.GET("/:id", api.Get)
|
||||
r.DELETE("", api.Delete)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,4 +22,4 @@ func registerSyPostRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddlew
|
||||
r.PUT("/:id", api.Update)
|
||||
r.DELETE("", api.Delete)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,4 +36,4 @@ func registerSysUserRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
|
||||
{
|
||||
v1auth.GET("/getinfo", api.GetInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,15 +7,15 @@ import (
|
||||
|
||||
// SysDeptGetPageReq 列表或者搜索使用结构体
|
||||
type SysDeptGetPageReq struct {
|
||||
DeptId int `form:"deptId" search:"type:exact;column:dept_id;table:sys_dept" comment:"id"` //id
|
||||
ParentId int `form:"parentId" search:"type:exact;column:parent_id;table:sys_dept" comment:"上级部门"` //上级部门
|
||||
DeptPath string `form:"deptPath" search:"type:exact;column:dept_path;table:sys_dept" comment:""` //路径
|
||||
DeptName string `form:"deptName" search:"type:exact;column:dept_name;table:sys_dept" comment:"部门名称"` //部门名称
|
||||
Sort int `form:"sort" search:"type:exact;column:sort;table:sys_dept" comment:"排序"` //排序
|
||||
Leader string `form:"leader" search:"type:exact;column:leader;table:sys_dept" comment:"负责人"` //负责人
|
||||
Phone string `form:"phone" search:"type:exact;column:phone;table:sys_dept" comment:"手机"` //手机
|
||||
Email string `form:"email" search:"type:exact;column:email;table:sys_dept" comment:"邮箱"` //邮箱
|
||||
Status string `form:"status" search:"type:exact;column:status;table:sys_dept" comment:"状态"` //状态
|
||||
DeptId int `form:"deptId" search:"type:exact;column:dept_id;table:sys_dept" comment:"id"` //id
|
||||
ParentId int `form:"parentId" search:"type:exact;column:parent_id;table:sys_dept" comment:"上级部门"` //上级部门
|
||||
DeptPath string `form:"deptPath" search:"type:exact;column:dept_path;table:sys_dept" comment:""` //路径
|
||||
DeptName string `form:"deptName" search:"type:exact;column:dept_name;table:sys_dept" comment:"部门名称"` //部门名称
|
||||
Sort int `form:"sort" search:"type:exact;column:sort;table:sys_dept" comment:"排序"` //排序
|
||||
Leader string `form:"leader" search:"type:exact;column:leader;table:sys_dept" comment:"负责人"` //负责人
|
||||
Phone string `form:"phone" search:"type:exact;column:phone;table:sys_dept" comment:"手机"` //手机
|
||||
Email string `form:"email" search:"type:exact;column:email;table:sys_dept" comment:"邮箱"` //邮箱
|
||||
Status string `form:"status" search:"type:exact;column:status;table:sys_dept" comment:"状态"` //状态
|
||||
}
|
||||
|
||||
func (m *SysDeptGetPageReq) GetNeedSearch() interface{} {
|
||||
|
||||
@@ -54,4 +54,4 @@ type SysLoginLogDeleteReq struct {
|
||||
|
||||
func (s *SysLoginLogDeleteReq) GetId() interface{} {
|
||||
return s.Ids
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,4 +107,4 @@ type SysRoleMenu struct {
|
||||
// return nil, err
|
||||
// }
|
||||
// return r, nil
|
||||
//}
|
||||
//}
|
||||
|
||||
@@ -8,6 +8,12 @@ import (
|
||||
"go-admin/app/other/models/tools"
|
||||
)
|
||||
|
||||
// emptyTableNameMsg is what the generator's endpoints answer with when the
|
||||
// request named no table. Declared once because the tests assert on it: spelled
|
||||
// out again at each site, a reworded message would leave them asserting on a
|
||||
// string the server no longer sends, and still passing.
|
||||
const emptyTableNameMsg = "table name cannot be empty!"
|
||||
|
||||
// GetDBColumnList 分页列表数据
|
||||
// @Summary 分页列表数据 / page list data
|
||||
// @Description 数据库表列分页列表 / database table column page list
|
||||
@@ -41,7 +47,7 @@ func (e Gen) GetDBColumnList(c *gin.Context) {
|
||||
}
|
||||
|
||||
data.TableName = c.Request.FormValue("tableName")
|
||||
pkg.Assert(data.TableName != "", "table name cannot be empty!", 500)
|
||||
pkg.Assert(data.TableName != "", emptyTableNameMsg, 500)
|
||||
result, count, err := data.GetPage(db, pageSize, pageIndex)
|
||||
if err != nil {
|
||||
log.Errorf("GetPage error, %s", err.Error())
|
||||
|
||||
@@ -16,17 +16,21 @@ import (
|
||||
"go-admin/common/middleware"
|
||||
)
|
||||
|
||||
const emptyTableNameMsg = "table name cannot be empty!"
|
||||
|
||||
// bodyOf covers both the success and the CustomError shape: both carry msg.
|
||||
type bodyOf struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
// newColumnListEngine wires the handler the way the router does, including the
|
||||
// newEngine wires one generator handler the way the router does, including the
|
||||
// middleware that turns pkg.Assert's panic into a response.
|
||||
func newColumnListEngine(t *testing.T) *gin.Engine {
|
||||
//
|
||||
// The generator's queries target MySQL's information_schema and cannot run on
|
||||
// the sqlite connection behind them; the driver setting only has to select that
|
||||
// branch, since no statement here is expected to succeed. That makes this
|
||||
// serviceable for any handler in this package whose behaviour is decided before
|
||||
// the query goes out -- which is what these tests are about.
|
||||
func newEngine(t *testing.T, method, path string, h gin.HandlerFunc) *gin.Engine {
|
||||
t.Helper()
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
@@ -35,26 +39,33 @@ func newColumnListEngine(t *testing.T) *gin.Engine {
|
||||
t.Fatalf("open sqlite: %v", err)
|
||||
}
|
||||
|
||||
// The query targets MySQL's information_schema; the driver setting only has
|
||||
// to select that branch, the statement itself is never expected to succeed.
|
||||
previous := config.DatabaseConfig.Driver
|
||||
config.DatabaseConfig.Driver = "mysql"
|
||||
t.Cleanup(func() { config.DatabaseConfig.Driver = previous })
|
||||
|
||||
r := gin.New()
|
||||
r.Use(middleware.CustomError)
|
||||
r.GET("/db/columns/page", func(c *gin.Context) {
|
||||
r.Handle(method, path, func(c *gin.Context) {
|
||||
c.Set("db", db)
|
||||
c.Set(pkg.LoggerKey, logger.NewHelper(logger.DefaultLogger))
|
||||
Gen{}.GetDBColumnList(c)
|
||||
h(c)
|
||||
})
|
||||
return r
|
||||
}
|
||||
|
||||
func columnListMsg(t *testing.T, r *gin.Engine, query string) bodyOf {
|
||||
func newColumnListEngine(t *testing.T) *gin.Engine {
|
||||
t.Helper()
|
||||
return newEngine(t, http.MethodGet, "/db/columns/page", Gen{}.GetDBColumnList)
|
||||
}
|
||||
|
||||
// serveJSON runs one request through the engine and decodes the envelope every
|
||||
// handler here answers with. A body that will not decode fails the test rather
|
||||
// than being reported as a mismatched message, which reads as the handler
|
||||
// having answered something unexpected instead of not having answered at all.
|
||||
func serveJSON(t *testing.T, r *gin.Engine, req *http.Request) bodyOf {
|
||||
t.Helper()
|
||||
w := httptest.NewRecorder()
|
||||
r.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/db/columns/page"+query, nil))
|
||||
r.ServeHTTP(w, req)
|
||||
|
||||
var body bodyOf
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &body); err != nil {
|
||||
@@ -63,6 +74,11 @@ func columnListMsg(t *testing.T, r *gin.Engine, query string) bodyOf {
|
||||
return body
|
||||
}
|
||||
|
||||
func columnListMsg(t *testing.T, r *gin.Engine, query string) bodyOf {
|
||||
t.Helper()
|
||||
return serveJSON(t, r, httptest.NewRequest(http.MethodGet, "/db/columns/page"+query, nil))
|
||||
}
|
||||
|
||||
func TestGetDBColumnList_AcceptsATableName(t *testing.T) {
|
||||
body := columnListMsg(t, newColumnListEngine(t), "?tableName=sys_user")
|
||||
if body.Msg == emptyTableNameMsg {
|
||||
|
||||
@@ -83,7 +83,7 @@ func (e Gen) Preview(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
tab, _ := table.Get(db,false)
|
||||
tab, _ := table.Get(db, false)
|
||||
var b1 bytes.Buffer
|
||||
err = t1.Execute(&b1, tab)
|
||||
var b2 bytes.Buffer
|
||||
@@ -129,7 +129,7 @@ func (e Gen) GenCode(c *gin.Context) {
|
||||
}
|
||||
|
||||
table.TableId = id
|
||||
tab, _ := table.Get(db,false)
|
||||
tab, _ := table.Get(db, false)
|
||||
|
||||
e.NOActionsGen(c, tab)
|
||||
|
||||
@@ -155,7 +155,7 @@ func (e Gen) GenApiToFile(c *gin.Context) {
|
||||
}
|
||||
|
||||
table.TableId = id
|
||||
tab, _ := table.Get(db,false)
|
||||
tab, _ := table.Get(db, false)
|
||||
e.genApiToFile(c, tab)
|
||||
|
||||
e.OK("", "Code generated successfully!")
|
||||
@@ -302,7 +302,7 @@ func (e Gen) GenMenuAndApi(c *gin.Context) {
|
||||
}
|
||||
|
||||
table.TableId = id
|
||||
tab, _ := table.Get(e.Orm,true)
|
||||
tab, _ := table.Get(e.Orm, true)
|
||||
tab.MLTBName = strings.Replace(tab.TBName, "_", "-", -1)
|
||||
|
||||
Mmenu := dto.SysMenuInsertReq{}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
_ "github.com/go-admin-team/go-admin-core/v2/response"
|
||||
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||
"github.com/go-admin-team/go-admin-core/v2/sdk/pkg"
|
||||
_ "github.com/go-admin-team/go-admin-core/v2/response"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"go-admin/app/other/models/tools"
|
||||
@@ -79,7 +80,7 @@ func (e SysTable) Get(c *gin.Context) {
|
||||
|
||||
var data tools.SysTables
|
||||
data.TableId, _ = pkg.StringToInt(c.Param("tableId"))
|
||||
result, err := data.Get(db,true)
|
||||
result, err := data.Get(db, true)
|
||||
if err != nil {
|
||||
log.Errorf("Get error, %s", err.Error())
|
||||
e.Error(500, err, "")
|
||||
@@ -106,7 +107,7 @@ func (e SysTable) GetSysTablesInfo(c *gin.Context) {
|
||||
if c.Request.FormValue("tableName") != "" {
|
||||
data.TBName = c.Request.FormValue("tableName")
|
||||
}
|
||||
result, err := data.Get(db,true)
|
||||
result, err := data.Get(db, true)
|
||||
if err != nil {
|
||||
log.Errorf("Get error, %s", err.Error())
|
||||
e.Error(500, err, "抱歉未找到相关信息")
|
||||
@@ -148,7 +149,8 @@ func (e SysTable) GetSysTablesTree(c *gin.Context) {
|
||||
// @Tags 工具 / 生成工具
|
||||
// @Accept application/json
|
||||
// @Product application/json
|
||||
// @Param tables query string false "tableName / 数据表名称"
|
||||
// @Param tables query string false "tableName / 数据表名称,逗号分隔"
|
||||
// @Param data body object false "tables / 同上,query 未带时从 JSON body 读"
|
||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
||||
// @Router /api/v1/sys/tables/info [post]
|
||||
@@ -163,7 +165,13 @@ func (e SysTable) Insert(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
tablesList := strings.Split(c.Request.FormValue("tables"), ",")
|
||||
tablesList, err := tablesToImport(c)
|
||||
if err != nil {
|
||||
log.Errorf("read the table list, %s", err.Error())
|
||||
e.Error(500, err, "")
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < len(tablesList); i++ {
|
||||
|
||||
data, err := genTableInit(db, tablesList, i, c)
|
||||
@@ -184,6 +192,45 @@ func (e SysTable) Insert(c *gin.Context) {
|
||||
|
||||
}
|
||||
|
||||
// tablesToImport reads the comma-separated table list carried by an import
|
||||
// request, from the query string or from a JSON body.
|
||||
//
|
||||
// The list has only ever travelled in the query string, which is the single
|
||||
// place FormValue looks once the request declares itself as JSON. A front end
|
||||
// that puts it in the body instead therefore left this empty, and the import
|
||||
// went on to ask information_schema for a table named "" -- go-admin-ui v3.2.0
|
||||
// shipped exactly that, and every import failed with the message below.
|
||||
// Reading the body when the query has nothing keeps either front end working.
|
||||
func tablesToImport(c *gin.Context) ([]string, error) {
|
||||
raw := c.Request.FormValue("tables")
|
||||
if raw == "" {
|
||||
var body struct {
|
||||
Tables string `json:"tables"`
|
||||
}
|
||||
// A body that is absent, or shaped some other way, is not itself worth
|
||||
// reporting: the list is missing either way, and the message below says
|
||||
// so in the terms the caller asked in.
|
||||
if err := c.ShouldBindJSON(&body); err == nil {
|
||||
raw = body.Tables
|
||||
}
|
||||
}
|
||||
|
||||
parts := strings.Split(raw, ",")
|
||||
names := make([]string, 0, len(parts))
|
||||
for _, name := range parts {
|
||||
// Splitting "" yields one empty name rather than nothing at all, so
|
||||
// without this an empty list reads as a request to import one table
|
||||
// whose name happens to be blank.
|
||||
if name = strings.TrimSpace(name); name != "" {
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
if len(names) == 0 {
|
||||
return nil, errors.New(emptyTableNameMsg)
|
||||
}
|
||||
return names, nil
|
||||
}
|
||||
|
||||
func genTableInit(tx *gorm.DB, tablesList []string, i int, c *gin.Context) (tools.SysTables, error) {
|
||||
var data tools.SysTables
|
||||
var dbTable tools.DBTables
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// newImportRequest builds the request an import arrives in. Where the table
|
||||
// list sits -- query or body -- is exactly what these tests are about, and it
|
||||
// is net/http's form parsing that decides what a handler can reach, so these go
|
||||
// through a real *http.Request rather than a hand-built one.
|
||||
func newImportRequest(target, contentType, body string) *http.Request {
|
||||
req := httptest.NewRequest(http.MethodPost, target, strings.NewReader(body))
|
||||
if contentType != "" {
|
||||
req.Header.Set("Content-Type", contentType)
|
||||
}
|
||||
return req
|
||||
}
|
||||
|
||||
func TestTablesToImport(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
target string
|
||||
contentType string
|
||||
body string
|
||||
want []string
|
||||
wantErr bool
|
||||
}{{
|
||||
name: "from the query, as every front end before v3.2.0 sent it",
|
||||
target: "/sys/tables/info?tables=sys_user,sys_post",
|
||||
want: []string{"sys_user", "sys_post"},
|
||||
}, {
|
||||
name: "from a JSON body, as go-admin-ui v3.2.0 sends it",
|
||||
target: "/sys/tables/info",
|
||||
contentType: "application/json",
|
||||
body: `{"tables":"sys_user,sys_post"}`,
|
||||
want: []string{"sys_user", "sys_post"},
|
||||
}, {
|
||||
name: "the query wins when a request carries both",
|
||||
target: "/sys/tables/info?tables=sys_user",
|
||||
contentType: "application/json",
|
||||
body: `{"tables":"sys_post"}`,
|
||||
want: []string{"sys_user"},
|
||||
}, {
|
||||
name: "blank entries are dropped rather than imported as a nameless table",
|
||||
target: "/sys/tables/info?tables=sys_user,,%20,sys_post",
|
||||
want: []string{"sys_user", "sys_post"},
|
||||
}, {
|
||||
name: "a body carrying an empty list is an error",
|
||||
target: "/sys/tables/info",
|
||||
contentType: "application/json",
|
||||
body: `{"tables":""}`,
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "a body that is not JSON at all is an error, not a panic",
|
||||
target: "/sys/tables/info",
|
||||
contentType: "application/json",
|
||||
body: "sys_user",
|
||||
wantErr: true,
|
||||
}}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
c, _ := gin.CreateTestContext(httptest.NewRecorder())
|
||||
c.Request = newImportRequest(tc.target, tc.contentType, tc.body)
|
||||
|
||||
got, err := tablesToImport(c)
|
||||
|
||||
if tc.wantErr {
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error, got %q", got)
|
||||
}
|
||||
if err.Error() != emptyTableNameMsg {
|
||||
t.Fatalf("message should be the one the front end shows, got %q", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if strings.Join(got, ",") != strings.Join(tc.want, ",") {
|
||||
t.Fatalf("got %q, want %q", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// insertMsg runs one import through the wired handler. It asserts nothing about
|
||||
// the import succeeding -- it cannot, over sqlite -- only about how far the
|
||||
// request got, which the empty-list message is what distinguishes.
|
||||
func insertMsg(t *testing.T, target, contentType, body string) bodyOf {
|
||||
t.Helper()
|
||||
return serveJSON(t,
|
||||
newEngine(t, http.MethodPost, "/sys/tables/info", SysTable{}.Insert),
|
||||
newImportRequest(target, contentType, body))
|
||||
}
|
||||
|
||||
func TestInsert_ReadsTheTableListFromEitherPlace(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
target string
|
||||
contentType string
|
||||
body string
|
||||
}{
|
||||
{"query", "/sys/tables/info?tables=sys_user", "", ""},
|
||||
{"JSON body", "/sys/tables/info", "application/json", `{"tables":"sys_user"}`},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if got := insertMsg(t, tc.target, tc.contentType, tc.body); got.Msg == emptyTableNameMsg {
|
||||
t.Fatalf("request carried a table name and was still rejected as empty: %+v", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsert_RejectsAMissingTableList(t *testing.T) {
|
||||
if got := insertMsg(t, "/sys/tables/info", "", ""); got.Msg != emptyTableNameMsg {
|
||||
t.Fatalf("missing table list should be rejected, got %+v", got)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -5,4 +5,4 @@ import "go-admin/app/demo/router"
|
||||
func init() {
|
||||
//注册路由 fixme 其他应用的路由,在本目录新建文件放在init方法
|
||||
AppRouters = append(AppRouters, router.InitRouter)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ func init() {
|
||||
rootCmd.AddCommand(app.StartCmd)
|
||||
}
|
||||
|
||||
//Execute : apply commands
|
||||
// Execute : apply commands
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
os.Exit(-1)
|
||||
|
||||
@@ -13,4 +13,4 @@ type SysApi struct {
|
||||
|
||||
func (SysApi) TableName() string {
|
||||
return "sys_api"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
package models
|
||||
|
||||
type SysMenu struct {
|
||||
MenuId int `json:"menuId" gorm:"primaryKey;autoIncrement"`
|
||||
MenuName string `json:"menuName" gorm:"size:128;"`
|
||||
Title string `json:"title" gorm:"size:128;"`
|
||||
Icon string `json:"icon" gorm:"size:128;"`
|
||||
Path string `json:"path" gorm:"size:128;"`
|
||||
Paths string `json:"paths" gorm:"size:128;"`
|
||||
MenuType string `json:"menuType" gorm:"size:1;"`
|
||||
Action string `json:"action" gorm:"size:16;"`
|
||||
Permission string `json:"permission" gorm:"size:255;"`
|
||||
ParentId int `json:"parentId" gorm:"size:11;"`
|
||||
NoCache bool `json:"noCache" gorm:"size:8;"`
|
||||
Breadcrumb string `json:"breadcrumb" gorm:"size:255;"`
|
||||
Component string `json:"component" gorm:"size:255;"`
|
||||
Sort int `json:"sort" gorm:"size:4;"`
|
||||
Visible string `json:"visible" gorm:"size:1;"`
|
||||
IsFrame string `json:"isFrame" gorm:"size:1;DEFAULT:0;"`
|
||||
SysApi []SysApi `json:"sysApi" gorm:"many2many:sys_menu_api_rule"`
|
||||
MenuId int `json:"menuId" gorm:"primaryKey;autoIncrement"`
|
||||
MenuName string `json:"menuName" gorm:"size:128;"`
|
||||
Title string `json:"title" gorm:"size:128;"`
|
||||
Icon string `json:"icon" gorm:"size:128;"`
|
||||
Path string `json:"path" gorm:"size:128;"`
|
||||
Paths string `json:"paths" gorm:"size:128;"`
|
||||
MenuType string `json:"menuType" gorm:"size:1;"`
|
||||
Action string `json:"action" gorm:"size:16;"`
|
||||
Permission string `json:"permission" gorm:"size:255;"`
|
||||
ParentId int `json:"parentId" gorm:"size:11;"`
|
||||
NoCache bool `json:"noCache" gorm:"size:8;"`
|
||||
Breadcrumb string `json:"breadcrumb" gorm:"size:255;"`
|
||||
Component string `json:"component" gorm:"size:255;"`
|
||||
Sort int `json:"sort" gorm:"size:4;"`
|
||||
Visible string `json:"visible" gorm:"size:1;"`
|
||||
IsFrame string `json:"isFrame" gorm:"size:1;DEFAULT:0;"`
|
||||
SysApi []SysApi `json:"sysApi" gorm:"many2many:sys_menu_api_rule"`
|
||||
ControlBy
|
||||
ModelTime
|
||||
}
|
||||
|
||||
func (SysMenu) TableName() string {
|
||||
return "sys_menu"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,4 +13,4 @@ type SysPost struct {
|
||||
|
||||
func (SysPost) TableName() string {
|
||||
return "sys_post"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,4 +17,4 @@ type SysRole struct {
|
||||
|
||||
func (SysRole) TableName() string {
|
||||
return "sys_role"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ func (e *QiNiuKODO) getToken() (string, error) {
|
||||
return putPolicy.UploadToken(mac), nil
|
||||
}
|
||||
|
||||
//Setup 装载
|
||||
//endpoint sss
|
||||
// Setup 装载
|
||||
// endpoint sss
|
||||
func (e *QiNiuKODO) Setup(endpoint, accessKeyID, accessKeySecret, BucketName string, options ...ClientOption) error {
|
||||
|
||||
mac := qbox.NewMac(accessKeyID, accessKeySecret)
|
||||
|
||||
@@ -10,8 +10,8 @@ type ALiYunOSS struct {
|
||||
BucketName string
|
||||
}
|
||||
|
||||
//Setup 装载
|
||||
//endpoint sss
|
||||
// Setup 装载
|
||||
// endpoint sss
|
||||
func (e *ALiYunOSS) Setup(endpoint, accessKeyID, accessKeySecret, BucketName string, options ...ClientOption) error {
|
||||
client, err := oss.New(endpoint, accessKeyID, accessKeySecret)
|
||||
if err != nil {
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
// NoCache is a middleware function that appends headers
|
||||
// to prevent the client from caching the HTTP response.
|
||||
func NoCache(c *gin.Context) {
|
||||
c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value")
|
||||
c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate")
|
||||
c.Header("Expires", "Thu, 01 Jan 1970 00:00:00 GMT")
|
||||
c.Header("Last-Modified", time.Now().UTC().Format(http.TimeFormat))
|
||||
c.Next()
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func TestNoCache(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
|
||||
NoCache(c)
|
||||
|
||||
if got := w.Header().Get("Cache-Control"); got != "no-cache, no-store, max-age=0, must-revalidate" {
|
||||
t.Errorf("Cache-Control = %q", got)
|
||||
}
|
||||
if got := w.Header().Get("Expires"); got != "Thu, 01 Jan 1970 00:00:00 GMT" {
|
||||
t.Errorf("Expires = %q", got)
|
||||
}
|
||||
if got := w.Header().Get("Last-Modified"); got == "" {
|
||||
t.Error("Last-Modified should not be empty")
|
||||
} else if _, err := time.Parse(http.TimeFormat, got); err != nil {
|
||||
t.Errorf("Last-Modified = %q is not a valid HTTP time: %v", got, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptions(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
t.Run("OPTIONS request", func(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = httptest.NewRequest(http.MethodOptions, "/", nil)
|
||||
|
||||
Options(c)
|
||||
|
||||
if got := w.Header().Get("Access-Control-Allow-Origin"); got != "*" {
|
||||
t.Errorf("Access-Control-Allow-Origin = %q", got)
|
||||
}
|
||||
if got := w.Header().Get("Access-Control-Allow-Methods"); got != "GET,POST,PUT,PATCH,DELETE,OPTIONS" {
|
||||
t.Errorf("Access-Control-Allow-Methods = %q", got)
|
||||
}
|
||||
if got := w.Header().Get("Access-Control-Allow-Headers"); got != "authorization, origin, content-type, accept" {
|
||||
t.Errorf("Access-Control-Allow-Headers = %q", got)
|
||||
}
|
||||
if got := w.Header().Get("Allow"); got != "HEAD,GET,POST,PUT,PATCH,DELETE,OPTIONS" {
|
||||
t.Errorf("Allow = %q", got)
|
||||
}
|
||||
if got := w.Header().Get("Content-Type"); got != "application/json" {
|
||||
t.Errorf("Content-Type = %q", got)
|
||||
}
|
||||
if !c.IsAborted() {
|
||||
t.Error("expected the request to be aborted")
|
||||
}
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("status code = %d, want %d", w.Code, http.StatusOK)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("non-OPTIONS request", func(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
|
||||
Options(c)
|
||||
|
||||
if got := w.Header().Get("Access-Control-Allow-Origin"); got != "" {
|
||||
t.Errorf("Access-Control-Allow-Origin = %q, want empty", got)
|
||||
}
|
||||
if c.IsAborted() {
|
||||
t.Error("expected the request not to be aborted")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestSecure(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
t.Run("without TLS", func(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
|
||||
Secure(c)
|
||||
|
||||
if got := w.Header().Get("Access-Control-Allow-Origin"); got != "*" {
|
||||
t.Errorf("Access-Control-Allow-Origin = %q", got)
|
||||
}
|
||||
if got := w.Header().Get("X-Content-Type-Options"); got != "nosniff" {
|
||||
t.Errorf("X-Content-Type-Options = %q", got)
|
||||
}
|
||||
if got := w.Header().Get("X-XSS-Protection"); got != "1; mode=block" {
|
||||
t.Errorf("X-XSS-Protection = %q", got)
|
||||
}
|
||||
if got := w.Header().Get("Strict-Transport-Security"); got != "" {
|
||||
t.Errorf("Strict-Transport-Security = %q, want empty without TLS", got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("with TLS", func(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
c.Request.TLS = &tls.ConnectionState{}
|
||||
|
||||
Secure(c)
|
||||
|
||||
if got := w.Header().Get("Strict-Transport-Security"); got != "max-age=31536000" {
|
||||
t.Errorf("Strict-Transport-Security = %q", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -38,6 +38,6 @@ var CasbinExclude = []UrlInfo{
|
||||
{Url: "/", Method: "GET"},
|
||||
{Url: "/api/v1/server-monitor", Method: "GET"},
|
||||
{Url: "/api/v1/public/uploadFile", Method: "POST"},
|
||||
{Url: "/api/v1/user/pwd/set", Method: "PUT"},
|
||||
{Url: "/api/v1/user/pwd/set", Method: "PUT"},
|
||||
{Url: "/api/v1/sys-user", Method: "PUT"},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user