diff --git a/server/api/v1/system/sys_auto_code.go b/server/api/v1/system/sys_auto_code.go index 6f3fe8106d69fb463fcfc4a7ecde67a0e96917ab..2c010445e2869a1d1a1c1def5836b54c6a24839c 100644 --- a/server/api/v1/system/sys_auto_code.go +++ b/server/api/v1/system/sys_auto_code.go @@ -3,17 +3,16 @@ package system import ( "errors" "fmt" + "github.com/flipped-aurora/gin-vue-admin/server/global" + "github.com/flipped-aurora/gin-vue-admin/server/model/common/response" + "github.com/flipped-aurora/gin-vue-admin/server/model/system" + "github.com/flipped-aurora/gin-vue-admin/server/utils" "golang.org/x/text/cases" "golang.org/x/text/language" "net/url" "os" "strings" - "github.com/flipped-aurora/gin-vue-admin/server/global" - "github.com/flipped-aurora/gin-vue-admin/server/model/common/response" - "github.com/flipped-aurora/gin-vue-admin/server/model/system" - "github.com/flipped-aurora/gin-vue-admin/server/utils" - "github.com/gin-gonic/gin" "go.uber.org/zap" ) @@ -240,3 +239,18 @@ func (autoApi *AutoCodeApi) AutoPlug(c *gin.Context) { response.Ok(c) } } + +func (autoApi *AutoCodeApi) InstallPlugin(c *gin.Context) { + header, err := c.FormFile("plug") + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + err = autoCodeService.InstallPlugin(header) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } else { + response.OkWithMessage("插件安装成功,请按照说明配置使用", c) + } +} diff --git a/server/api/v1/system/sys_user.go b/server/api/v1/system/sys_user.go index 524d93252d7ec4c93866c4d2d248d9e15113ac77..1c018c0fe245a4ffbc5e30ecda81aad73c04915d 100644 --- a/server/api/v1/system/sys_user.go +++ b/server/api/v1/system/sys_user.go @@ -138,18 +138,19 @@ func (b *BaseApi) Register(c *gin.Context) { // @Summary 用户修改密码 // @Security ApiKeyAuth // @Produce application/json -// @Param data body systemReq.ChangePasswordStruct true "用户名, 原密码, 新密码" +// @Param data body systemReq.ChangePasswordReq true "用户名, 原密码, 新密码" // @Success 200 {object} response.Response{msg=string} "用户修改密码" // @Router /user/changePassword [post] func (b *BaseApi) ChangePassword(c *gin.Context) { - var user systemReq.ChangePasswordStruct - _ = c.ShouldBindJSON(&user) - if err := utils.Verify(user, utils.ChangePasswordVerify); err != nil { + var req systemReq.ChangePasswordReq + _ = c.ShouldBindJSON(&req) + if err := utils.Verify(req, utils.ChangePasswordVerify); err != nil { response.FailWithMessage(err.Error(), c) return } - u := &system.SysUser{Username: user.Username, Password: user.Password} - if _, err := userService.ChangePassword(u, user.NewPassword); err != nil { + uid := utils.GetUserID(c) + u := &system.SysUser{GVA_MODEL: global.GVA_MODEL{ID: uid}, Password: req.Password} + if _, err := userService.ChangePassword(u, req.NewPassword); err != nil { global.GVA_LOG.Error("修改失败!", zap.Error(err)) response.FailWithMessage("修改失败,原密码与当前账户不符", c) } else { @@ -201,8 +202,7 @@ func (b *BaseApi) SetUserAuthority(c *gin.Context) { return } userID := utils.GetUserID(c) - uuid := utils.GetUserUuid(c) - if err := userService.SetUserAuthority(userID, uuid, sua.AuthorityId); err != nil { + if err := userService.SetUserAuthority(userID, sua.AuthorityId); err != nil { global.GVA_LOG.Error("修改失败!", zap.Error(err)) response.FailWithMessage(err.Error(), c) } else { diff --git a/server/go.mod b/server/go.mod index 330e84f24dfd7bc4f6cfee4f30b0ee8098be3b4f..fb681f2b80b24e1e3767ced0b0be9840bc8f5f56 100644 --- a/server/go.mod +++ b/server/go.mod @@ -29,6 +29,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mitchellh/mapstructure v1.2.2 // indirect github.com/mojocn/base64Captcha v1.3.1 + github.com/otiai10/copy v1.7.0 github.com/pelletier/go-toml v1.6.0 // indirect github.com/pkg/errors v0.9.1 github.com/qiniu/api.v7/v7 v7.4.1 diff --git a/server/go.sum b/server/go.sum index 55feb1b3895b6d941d5b0ec35b8befa253f15a3a..d1c5471d6aeb40cd7a5d072345f99d19d1d727e6 100644 --- a/server/go.sum +++ b/server/go.sum @@ -424,6 +424,13 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ= github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= +github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE= +github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.3 h1:7JgpsBaN0uMkyju4tbYHu0mnM55hNKVYLsXmwr15NQI= +github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4= diff --git a/server/initialize/plugin.go b/server/initialize/plugin.go index a7dd4875b8be7e44a521a9765e0d989a28c41455..d69663e9518f6957e4d5486794f6a06667a72276 100644 --- a/server/initialize/plugin.go +++ b/server/initialize/plugin.go @@ -1,7 +1,9 @@ package initialize import ( + "fmt" "github.com/flipped-aurora/gin-vue-admin/server/global" + "github.com/flipped-aurora/gin-vue-admin/server/middleware" "github.com/flipped-aurora/gin-vue-admin/server/plugin/email" "github.com/flipped-aurora/gin-vue-admin/server/utils/plugin" "github.com/gin-gonic/gin" @@ -14,7 +16,12 @@ func PluginInit(group *gin.RouterGroup, Plugin ...plugin.Plugin) { } } -func InstallPlugin(PublicGroup *gin.RouterGroup, PrivateGroup *gin.RouterGroup) { +func InstallPlugin(Router *gin.Engine) { + PublicGroup := Router.Group("") + fmt.Println("无鉴权插件安装==》", PublicGroup) + PrivateGroup := Router.Group("") + fmt.Println("鉴权插件安装==》", PrivateGroup) + PrivateGroup.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler()) // 添加跟角色挂钩权限的插件 示例 本地示例模式于在线仓库模式注意上方的import 可以自行切换 效果相同 PluginInit(PrivateGroup, email.CreateEmailPlug( global.GVA_CONFIG.Email.To, diff --git a/server/initialize/router.go b/server/initialize/router.go index be8b5b67c8966c95b82bb6546001be3cba0ba08b..1f4f0577995f4dee1bc5d841f43c00ee8d90e500 100644 --- a/server/initialize/router.go +++ b/server/initialize/router.go @@ -29,11 +29,10 @@ func Routers() *gin.Engine { Router.StaticFS(global.GVA_CONFIG.Local.Path, http.Dir(global.GVA_CONFIG.Local.StorePath)) // 为用户头像和文件提供静态地址 // Router.Use(middleware.LoadTls()) // 如果需要使用https 请打开此中间件 然后前往 core/server.go 将启动模式 更变为 Router.RunTLS("端口","你的cre/pem文件","你的key文件") - global.GVA_LOG.Info("use middleware logger") // 跨域,如需跨域可以打开下面的注释 // Router.Use(middleware.Cors()) // 直接放行全部跨域请求 //Router.Use(middleware.CorsByRules()) // 按照配置的规则放行跨域请求 - global.GVA_LOG.Info("use middleware cors") + //global.GVA_LOG.Info("use middleware cors") Router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) global.GVA_LOG.Info("register swagger handler") // 方便统一添加路由组前缀 多服务器上线使用 @@ -75,7 +74,7 @@ func Routers() *gin.Engine { // Code generated by github.com/flipped-aurora/gin-vue-admin/server End; DO NOT EDIT. } - InstallPlugin(PublicGroup, PrivateGroup) // 安装插件 + InstallPlugin(Router) // 安装插件 global.GVA_LOG.Info("router register success") return Router diff --git a/server/model/system/request/sys_user.go b/server/model/system/request/sys_user.go index 7befdbecd668fb30debb53ee6e5ba0f1be3b3961..7aef010dfc3a88cfd55a9619355dcd937bb0f173 100644 --- a/server/model/system/request/sys_user.go +++ b/server/model/system/request/sys_user.go @@ -22,8 +22,8 @@ type Login struct { } // Modify password structure -type ChangePasswordStruct struct { - Username string `json:"username"` // 用户名 +type ChangePasswordReq struct { + ID uint `json:"-"` // 从 JWT 中提取 user id,避免越权 Password string `json:"password"` // 密码 NewPassword string `json:"newPassword"` // 新密码 } @@ -42,7 +42,7 @@ type SetUserAuthorities struct { type ChangeUserInfo struct { ID uint `gorm:"primarykey"` // 主键ID NickName string `json:"nickName" gorm:"default:系统用户;comment:用户昵称"` // 用户昵称 - Phone string `json:"phone" gorm:"comment:用户手机号"` // 用户角色ID + Phone string `json:"phone" gorm:"comment:用户手机号"` // 用户手机号 AuthorityIds []uint `json:"authorityIds" gorm:"-"` // 角色ID Email string `json:"email" gorm:"comment:用户邮箱"` // 用户邮箱 HeaderImg string `json:"headerImg" gorm:"default:https://qmplusimg.henrongyi.top/gva_header.jpg;comment:用户头像"` // 用户头像 diff --git a/server/model/system/sys_user_authority.go b/server/model/system/sys_user_authority.go index c07de5deba57a3153c4a8a3ea6d97668f2ef46de..1aa83cbd5b672af897b14405a97f0b913279b177 100644 --- a/server/model/system/sys_user_authority.go +++ b/server/model/system/sys_user_authority.go @@ -1,10 +1,11 @@ package system -type SysUseAuthority struct { +// SysUserAuthority 是 sysUser 和 sysAuthority 的连接表 +type SysUserAuthority struct { SysUserId uint `gorm:"column:sys_user_id"` SysAuthorityAuthorityId uint `gorm:"column:sys_authority_authority_id"` } -func (s *SysUseAuthority) TableName() string { +func (s *SysUserAuthority) TableName() string { return "sys_user_authority" } diff --git a/server/router/system/sys_auto_code.go b/server/router/system/sys_auto_code.go index 82c50cec3771ac665fd2dbfb49735825ab17fa48..b9ddf0a1e0e203ad5b2df909a84dbf6c0a60ec36 100644 --- a/server/router/system/sys_auto_code.go +++ b/server/router/system/sys_auto_code.go @@ -20,5 +20,6 @@ func (s *AutoCodeRouter) InitAutoCodeRouter(Router *gin.RouterGroup) { autoCodeRouter.POST("getPackage", autoCodeApi.GetPackage) // 获取package包 autoCodeRouter.POST("delPackage", autoCodeApi.DelPackage) // 删除package包 autoCodeRouter.POST("createPlug", autoCodeApi.AutoPlug) // 自动插件包模板 + autoCodeRouter.POST("installPlugin", autoCodeApi.InstallPlugin) // 自动安装插件 } } diff --git a/server/service/system/sys_authority.go b/server/service/system/sys_authority.go index 745ded3ea171da5ae3344457b239a190dd4cb10e..c5d096966759557552a0d75b1972784efd3e62ad 100644 --- a/server/service/system/sys_authority.go +++ b/server/service/system/sys_authority.go @@ -131,7 +131,7 @@ func (authorityService *AuthorityService) DeleteAuthority(auth *system.SysAuthor return } } - err = global.GVA_DB.Delete(&[]system.SysUseAuthority{}, "sys_authority_authority_id = ?", auth.AuthorityId).Error + err = global.GVA_DB.Delete(&[]system.SysUserAuthority{}, "sys_authority_authority_id = ?", auth.AuthorityId).Error err = global.GVA_DB.Delete(&[]system.SysAuthorityBtn{}, "authority_id = ?", auth.AuthorityId).Error authorityId := strconv.Itoa(int(auth.AuthorityId)) CasbinServiceApp.ClearCasbin(0, authorityId) diff --git a/server/service/system/sys_auto_code.go b/server/service/system/sys_auto_code.go index 1c89a8da42a440f7d070d0321e2067d8b17dc1af..041d12a406a46ff907b0b035ee5c557d0ed6d638 100644 --- a/server/service/system/sys_auto_code.go +++ b/server/service/system/sys_auto_code.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + cp "github.com/otiai10/copy" "go.uber.org/zap" "go/ast" "go/format" @@ -12,8 +13,10 @@ import ( "go/token" "golang.org/x/text/cases" "golang.org/x/text/language" + "io" "io/ioutil" "log" + "mime/multipart" "os" "path/filepath" "strconv" @@ -681,7 +684,7 @@ func (vi *Visitor) addStruct(genDecl *ast.GenDecl) ast.Visitor { case *ast.StructType: f := &ast.Field{ Names: []*ast.Ident{ - &ast.Ident{ + { Name: vi.StructName, Obj: &ast.Object{ Kind: ast.Var, @@ -834,3 +837,81 @@ func (autoCodeService *AutoCodeService) CreatePlug(plug system.AutoPlugReq) erro } return nil } + +func (autoCodeService *AutoCodeService) InstallPlugin(file *multipart.FileHeader) (err error) { + const GVAPLUGPATH = "./gva-plug-temp/" + defer os.RemoveAll(GVAPLUGPATH) + _, err = os.Stat(GVAPLUGPATH) + if os.IsNotExist(err) { + os.Mkdir(GVAPLUGPATH, os.ModePerm) + } + + src, err := file.Open() + if err != nil { + return err + } + defer src.Close() + + out, err := os.Create(GVAPLUGPATH + file.Filename) + if err != nil { + return err + } + defer out.Close() + + _, err = io.Copy(out, src) + + paths, err := utils.Unzip(GVAPLUGPATH+file.Filename, GVAPLUGPATH) + var webIndex = 0 + var serverIndex = 0 + for i := range paths { + paths[i] = filepath.ToSlash(paths[i]) + pathArr := strings.Split(paths[i], "/") + if pathArr[len(pathArr)-2] == "server" && pathArr[len(pathArr)-1] == "plugin" { + serverIndex = i + 1 + } + if pathArr[len(pathArr)-2] == "web" && pathArr[len(pathArr)-1] == "plugin" { + webIndex = i + 1 + } + } + if webIndex == 0 && serverIndex == 0 { + fmt.Println("非标准插件,请按照文档自动迁移使用") + return errors.New("非标准插件,请按照文档自动迁移使用") + } + + if webIndex != 0 { + webNameArr := strings.Split(filepath.ToSlash(paths[webIndex]), "/") + webName := webNameArr[len(webNameArr)-1] + var form = filepath.ToSlash(global.GVA_CONFIG.AutoCode.Root + global.GVA_CONFIG.AutoCode.Server + "/" + paths[webIndex]) + var to = filepath.ToSlash(global.GVA_CONFIG.AutoCode.Root + global.GVA_CONFIG.AutoCode.Web + "/plugin/" + webName) + _, err := os.Stat(to) + if err == nil { + fmt.Println("web 已存在同名插件,请自行手动安装") + return errors.New("web 已存在同名插件,请自行手动安装") + } + err = cp.Copy(form, to) + if err != nil { + return err + } + } + + if serverIndex != 0 { + serverNameArr := strings.Split(filepath.ToSlash(paths[serverIndex]), "/") + serverName := serverNameArr[len(serverNameArr)-1] + var form = filepath.ToSlash(global.GVA_CONFIG.AutoCode.Root + global.GVA_CONFIG.AutoCode.Server + "/" + paths[serverIndex]) + var to = filepath.ToSlash(global.GVA_CONFIG.AutoCode.Root + global.GVA_CONFIG.AutoCode.Server + "/plugin/" + serverName) + _, err := os.Stat(to) + if err == nil { + fmt.Println("server 已存在同名插件,请自行手动安装") + return errors.New("server 已存在同名插件,请自行手动安装") + } + err = cp.Copy(form, to) + if err != nil { + return err + } + } + if err != nil { + return err + } else { + return nil + } +} diff --git a/server/service/system/sys_user.go b/server/service/system/sys_user.go index cd95e74c5804eab20bb3d8e3694092f5aed54a61..7a386820ce27384945a5982cbf61235443f74df0 100644 --- a/server/service/system/sys_user.go +++ b/server/service/system/sys_user.go @@ -79,8 +79,7 @@ func (userService *UserService) Login(u *system.SysUser) (userInter *system.SysU func (userService *UserService) ChangePassword(u *system.SysUser, newPassword string) (userInter *system.SysUser, err error) { var user system.SysUser - err = global.GVA_DB.Where("username = ?", u.Username).First(&user).Error - if err != nil { + if err = global.GVA_DB.Where("id = ?", u.ID).First(&user).Error; err != nil { return nil, err } if ok := utils.BcryptCheck(u.Password, user.Password); !ok { @@ -117,12 +116,12 @@ func (userService *UserService) GetUserInfoList(info request.PageInfo) (list int //@param: uuid uuid.UUID, authorityId string //@return: err error -func (userService *UserService) SetUserAuthority(id uint, uuid uuid.UUID, authorityId uint) (err error) { - assignErr := global.GVA_DB.Where("sys_user_id = ? AND sys_authority_authority_id = ?", id, authorityId).First(&system.SysUseAuthority{}).Error +func (userService *UserService) SetUserAuthority(id uint, authorityId uint) (err error) { + assignErr := global.GVA_DB.Where("sys_user_id = ? AND sys_authority_authority_id = ?", id, authorityId).First(&system.SysUserAuthority{}).Error if errors.Is(assignErr, gorm.ErrRecordNotFound) { return errors.New("该用户无此角色") } - err = global.GVA_DB.Where("uuid = ?", uuid).First(&system.SysUser{}).Update("authority_id", authorityId).Error + err = global.GVA_DB.Where("id = ?", id).First(&system.SysUser{}).Update("authority_id", authorityId).Error return err } @@ -134,13 +133,13 @@ func (userService *UserService) SetUserAuthority(id uint, uuid uuid.UUID, author func (userService *UserService) SetUserAuthorities(id uint, authorityIds []uint) (err error) { return global.GVA_DB.Transaction(func(tx *gorm.DB) error { - TxErr := tx.Delete(&[]system.SysUseAuthority{}, "sys_user_id = ?", id).Error + TxErr := tx.Delete(&[]system.SysUserAuthority{}, "sys_user_id = ?", id).Error if TxErr != nil { return TxErr } - var useAuthority []system.SysUseAuthority + var useAuthority []system.SysUserAuthority for _, v := range authorityIds { - useAuthority = append(useAuthority, system.SysUseAuthority{ + useAuthority = append(useAuthority, system.SysUserAuthority{ SysUserId: id, SysAuthorityAuthorityId: v, }) } @@ -169,7 +168,7 @@ func (userService *UserService) DeleteUser(id int) (err error) { if err != nil { return err } - err = global.GVA_DB.Delete(&[]system.SysUseAuthority{}, "sys_user_id = ?", id).Error + err = global.GVA_DB.Delete(&[]system.SysUserAuthority{}, "sys_user_id = ?", id).Error return err } diff --git a/server/source/system/api.go b/server/source/system/api.go index feec6ca4a77d2be74392061de30248265d97dcd5..6fc46c4f47b133e9354acb6d470f52c0a5e24e57 100644 --- a/server/source/system/api.go +++ b/server/source/system/api.go @@ -111,7 +111,8 @@ func (i *initApi) InitializeData(ctx context.Context) (context.Context, error) { {ApiGroup: "代码生成器", Method: "POST", Path: "/autoCode/createTemp", Description: "自动化代码"}, {ApiGroup: "代码生成器", Method: "POST", Path: "/autoCode/preview", Description: "预览自动化代码"}, {ApiGroup: "代码生成器", Method: "GET", Path: "/autoCode/getColumn", Description: "获取所选table的所有字段"}, - {ApiGroup: "代码生成器", Method: "POST", Path: "/autoCode/createPlug", Description: "自从创建插件包"}, + {ApiGroup: "代码生成器", Method: "POST", Path: "/autoCode/createPlug", Description: "自动创建插件包"}, + {ApiGroup: "代码生成器", Method: "POST", Path: "/autoCode/installPlug", Description: "安装插件"}, {ApiGroup: "包(pkg)生成器", Method: "POST", Path: "/autoCode/createPackage", Description: "生成包(package)"}, {ApiGroup: "包(pkg)生成器", Method: "POST", Path: "/autoCode/getPackage", Description: "获取所有包(package)"}, diff --git a/server/source/system/authorities_menus.go b/server/source/system/authorities_menus.go index 7f4d8308e5f4577d1bdd0b9bf2324d44700e9957..d58cdad36667320afca8f64243b569e0083e6dbd 100644 --- a/server/source/system/authorities_menus.go +++ b/server/source/system/authorities_menus.go @@ -2,6 +2,7 @@ package system import ( "context" + sysModel "github.com/flipped-aurora/gin-vue-admin/server/model/system" "github.com/flipped-aurora/gin-vue-admin/server/service/system" "github.com/pkg/errors" @@ -73,10 +74,13 @@ func (i *initMenuAuthority) DataInserted(ctx context.Context) bool { if !ok { return false } - var count int64 - if err := db.Model(&sysModel.SysAuthority{}). - Where("authority_id = ?", "9528").Preload("SysBaseMenus").Count(&count); err != nil { - return count == 16 + auth := &sysModel.SysAuthority{} + if ret := db.Model(auth). + Where("authority_id = ?", 9528).Preload("SysBaseMenus").Find(auth); ret != nil { + if ret.Error != nil { + return false + } + return len(auth.SysBaseMenus) > 0 } return false } diff --git a/server/source/system/casbin.go b/server/source/system/casbin.go index 307379eb54013cf42017b61316c4d3f766b85112..08729411fc3ee6338b4b651958eb0fd3635831ed 100644 --- a/server/source/system/casbin.go +++ b/server/source/system/casbin.go @@ -2,6 +2,7 @@ package system import ( "context" + adapter "github.com/casbin/gorm-adapter/v3" "github.com/flipped-aurora/gin-vue-admin/server/service/system" "github.com/pkg/errors" @@ -120,6 +121,7 @@ func (i *initCasbin) InitializeData(ctx context.Context) (context.Context, error {PType: "p", V0: "888", V1: "/autoCode/getPackage", V2: "POST"}, {PType: "p", V0: "888", V1: "/autoCode/delPackage", V2: "POST"}, {PType: "p", V0: "888", V1: "/autoCode/createPlug", V2: "POST"}, + {PType: "p", V0: "888", V1: "/autoCode/installPlugin", V2: "POST"}, {PType: "p", V0: "888", V1: "/sysDictionaryDetail/findSysDictionaryDetail", V2: "GET"}, {PType: "p", V0: "888", V1: "/sysDictionaryDetail/updateSysDictionaryDetail", V2: "PUT"}, @@ -250,7 +252,7 @@ func (i *initCasbin) DataInserted(ctx context.Context) bool { if !ok { return false } - if errors.Is(db.Where(adapter.CasbinRule{PType: "p", V0: "9528", V1: "GET", V2: "/user/getUserInfo"}). + if errors.Is(db.Where(adapter.CasbinRule{PType: "p", V0: "9528", V1: "/user/getUserInfo", V2: "GET"}). First(&adapter.CasbinRule{}).Error, gorm.ErrRecordNotFound) { // 判断是否存在数据 return false } diff --git a/server/source/system/menu.go b/server/source/system/menu.go index 44d67df9f1d2ce19bb69fc18c960db2756f76ddd..f201e9be0d4bd6b7896f355b4214f7dd84bf0618 100644 --- a/server/source/system/menu.go +++ b/server/source/system/menu.go @@ -76,10 +76,11 @@ func (i *initMenu) InitializeData(ctx context.Context) (next context.Context, er {MenuLevel: 0, Hidden: false, ParentId: "14", Path: "autoCodeAdmin", Name: "autoCodeAdmin", Component: "view/systemTools/autoCodeAdmin/index.vue", Sort: 1, Meta: Meta{Title: "自动化代码管理", Icon: "magic-stick"}}, {MenuLevel: 0, Hidden: true, ParentId: "14", Path: "autoCodeEdit/:id", Name: "autoCodeEdit", Component: "view/systemTools/autoCode/index.vue", Sort: 0, Meta: Meta{Title: "自动化代码-${id}", Icon: "magic-stick"}}, {MenuLevel: 0, Hidden: false, ParentId: "14", Path: "autoPkg", Name: "autoPkg", Component: "view/systemTools/autoPkg/autoPkg.vue", Sort: 0, Meta: Meta{Title: "自动化package", Icon: "folder"}}, - {MenuLevel: 0, Hidden: false, ParentId: "28", Path: "autoPlug", Name: "autoPlug", Component: "view/systemTools/autoPlug/autoPlug.vue", Sort: 4, Meta: Meta{Title: "自动化插件模板", Icon: "folder"}}, {MenuLevel: 0, Hidden: false, ParentId: "0", Path: "plugin", Name: "plugin", Component: "view/routerHolder.vue", Sort: 6, Meta: Meta{Title: "插件系统", Icon: "cherry"}}, - {MenuLevel: 0, Hidden: false, ParentId: "28", Path: "plugin-email", Name: "plugin-email", Component: "plugin/email/view/index.vue", Sort: 1, Meta: Meta{Title: "邮件插件", Icon: "message"}}, - {MenuLevel: 0, Hidden: false, ParentId: "28", Path: "https://plugin.gin-vue-admin.com/", Name: "https://plugin.gin-vue-admin.com/", Component: "https://plugin.gin-vue-admin.com/", Sort: 0, Meta: Meta{Title: "插件市场", Icon: "shop"}}, + {MenuLevel: 0, Hidden: false, ParentId: "27", Path: "https://plugin.gin-vue-admin.com/", Name: "https://plugin.gin-vue-admin.com/", Component: "https://plugin.gin-vue-admin.com/", Sort: 0, Meta: Meta{Title: "插件市场", Icon: "shop"}}, + {MenuLevel: 0, Hidden: false, ParentId: "27", Path: "installPlugin", Name: "installPlugin", Component: "view/systemTools/installPlugin/index.vue", Sort: 1, Meta: Meta{Title: "插件安装", Icon: "box"}}, + {MenuLevel: 0, Hidden: false, ParentId: "27", Path: "autoPlug", Name: "autoPlug", Component: "view/systemTools/autoPlug/autoPlug.vue", Sort: 2, Meta: Meta{Title: "插件模板", Icon: "folder"}}, + {MenuLevel: 0, Hidden: false, ParentId: "27", Path: "plugin-email", Name: "plugin-email", Component: "plugin/email/view/index.vue", Sort: 3, Meta: Meta{Title: "邮件插件", Icon: "message"}}, } if err = db.Create(&entities).Error; err != nil { return ctx, errors.Wrap(err, SysBaseMenu{}.TableName()+"表数据初始化失败!") diff --git a/server/utils/verify.go b/server/utils/verify.go index ff420423e9aa299b29d687b8dc636178c7414e6d..b358dd9c01be1d16866b3920b3c87e8efdef0d7c 100644 --- a/server/utils/verify.go +++ b/server/utils/verify.go @@ -14,6 +14,6 @@ var ( AuthorityVerify = Rules{"AuthorityId": {NotEmpty()}, "AuthorityName": {NotEmpty()}} AuthorityIdVerify = Rules{"AuthorityId": {NotEmpty()}} OldAuthorityVerify = Rules{"OldAuthorityId": {NotEmpty()}} - ChangePasswordVerify = Rules{"Username": {NotEmpty()}, "Password": {NotEmpty()}, "NewPassword": {NotEmpty()}} + ChangePasswordVerify = Rules{"Password": {NotEmpty()}, "NewPassword": {NotEmpty()}} SetUserAuthorityVerify = Rules{"AuthorityId": {NotEmpty()}} ) diff --git a/server/utils/zip.go b/server/utils/zip.go new file mode 100644 index 0000000000000000000000000000000000000000..b84dcc3fdec53263b986aac4fe71a56cbeb4b64a --- /dev/null +++ b/server/utils/zip.go @@ -0,0 +1,48 @@ +package utils + +import ( + "archive/zip" + "io" + "os" + "path/filepath" +) + +//解压 +func Unzip(zipFile string, destDir string) ([]string, error) { + zipReader, err := zip.OpenReader(zipFile) + var paths []string + if err != nil { + return []string{}, err + } + defer zipReader.Close() + + for _, f := range zipReader.File { + fpath := filepath.Join(destDir, f.Name) + paths = append(paths, fpath) + if f.FileInfo().IsDir() { + os.MkdirAll(fpath, os.ModePerm) + } else { + if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil { + return []string{}, err + } + + inFile, err := f.Open() + if err != nil { + return []string{}, err + } + defer inFile.Close() + + outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) + if err != nil { + return []string{}, err + } + defer outFile.Close() + + _, err = io.Copy(outFile, inFile) + if err != nil { + return []string{}, err + } + } + } + return paths, nil +} diff --git a/web/src/api/autoCode.js b/web/src/api/autoCode.js index ecb9690dd2314a8e95e5dd4df00ff95926ef15a4..15559503efce80e607d0c4b925449165ba7b8ec8 100644 --- a/web/src/api/autoCode.js +++ b/web/src/api/autoCode.js @@ -124,3 +124,10 @@ export const createPlugApi = (data) => { }) } +export const installPlug = (data) => { + return service({ + url: '/autoCode/installPlug', + method: 'post', + data + }) +} diff --git a/web/src/core/config.js b/web/src/core/config.js index bf0c0275777ce7f8232dd4a4f1f2f98bd5a83aa9..750133f2d1e3d2929115cd96ca6c47f4607fce85 100644 --- a/web/src/core/config.js +++ b/web/src/core/config.js @@ -41,11 +41,6 @@ export const viteLogo = (env) => { `> 默认自动化文档地址:http://127.0.0.1:${env.VITE_SERVER_PORT}/swagger/index.html` ) ) - console.log( - chalk.green( - `> 默认自动化文档地址:http://127.0.0.1:${env.VITE_SERVER_PORT}/swagger/index.html` - ) - ) console.log( chalk.green( `> 默认前端文件运行地址:http://127.0.0.1:${env.VITE_CLI_PORT}` diff --git a/web/src/permission.js b/web/src/permission.js index 6e59a726b7b7643784529ae0628a4ac6fe40a235..b49f137b6ad52d5639376a0933e4962a465ff39f 100644 --- a/web/src/permission.js +++ b/web/src/permission.js @@ -49,12 +49,25 @@ router.beforeEach(async(to, from, next) => { asyncRouterFlag++ await getRouter(userStore) } - next({ name: userStore.userInfo.authority.defaultRouter }) + // token 可以解析但是却是不存在的用户 id 或角色 id 会导致无限调用 + if (userStore.userInfo?.authority?.defaultRouter != null) { + next({ name: userStore.userInfo.authority.defaultRouter }) + } else { + // 强制退出账号 + userStore.ClearStorage() + next({ + name: 'Login', + query: { + redirect: document.location.hash + } + }) + return + } } else { next() } } else { - // 不在白名单中并且已经登陆的时候 + // 不在白名单中并且已经登录的时候 if (token) { // 添加flag防止多次获取动态路由和栈溢出 if (!asyncRouterFlag && whiteList.indexOf(from.name) < 0) { @@ -76,7 +89,7 @@ router.beforeEach(async(to, from, next) => { } } } - // 不在白名单中并且未登陆的时候 + // 不在白名单中并且未登录的时候 if (!token) { next({ name: 'Login', diff --git a/web/src/pinia/modules/user.js b/web/src/pinia/modules/user.js index 800c3f1be54cb4ac37f493eb0f0ed57f85b5a64d..8a01f467a8772f50c5bb9f13ad01cc07f9a82589 100644 --- a/web/src/pinia/modules/user.js +++ b/web/src/pinia/modules/user.js @@ -52,7 +52,7 @@ export const useUserStore = defineStore('user', () => { const LoginIn = async(loginInfo) => { loadingInstance.value = ElLoading.service({ fullscreen: true, - text: '登陆中,请稍候...', + text: '登录中,请稍候...', }) try { const res = await login(loginInfo) @@ -85,6 +85,12 @@ export const useUserStore = defineStore('user', () => { window.location.reload() } } + /* 清理数据 */ + const ClearStorage = async() => { + token.value = '' + sessionStorage.clear() + localStorage.clear() + } /* 设置侧边栏模式*/ const changeSideMode = async(data) => { const res = await setSelfInfo({ sideMode: data }) @@ -141,6 +147,7 @@ export const useUserStore = defineStore('user', () => { setToken, baseColor, activeColor, - loadingInstance + loadingInstance, + ClearStorage } }) diff --git a/web/src/style/newLogin.scss b/web/src/style/newLogin.scss index c2c288b1cd2185832d92c40e9d416ba00edf4827..01f005ac79fce65e729e131e14b5bc825673f84f 100644 --- a/web/src/style/newLogin.scss +++ b/web/src/style/newLogin.scss @@ -6,7 +6,7 @@ width: 100%; height: 100%; position: relative; - .input-icon{ + .input-icon { padding-right: 6px; padding-top: 4px; } @@ -47,10 +47,10 @@ padding-left: 20px; } } - .vPicBox{ - display:flex; - justify-content:space-between; - width:100%; + .vPicBox { + display: flex; + justify-content: space-between; + width: 100%; } .vPic { width: 33%; @@ -83,7 +83,7 @@ } } -//小屏幕不显示右侧,将登陆框居中 +//小屏幕不显示右侧,将登录框居中 @media (max-width: 750px) { .login_panle_right { display: none; diff --git a/web/src/view/dashboard/index.vue b/web/src/view/dashboard/index.vue index f0e0ff2a3793fbc6edc0d55d6f4f16769d78ef09..1a9837fe8e75abc0ff8c1949ee02cda380612b65 100644 --- a/web/src/view/dashboard/index.vue +++ b/web/src/view/dashboard/index.vue @@ -297,7 +297,7 @@ export default { @include flex-center; } -//小屏幕不显示右侧,将登陆框居中 +//小屏幕不显示右侧,将登录框居中 @media (max-width: 750px) { .gva-card { padding: 20px 10px !important; diff --git a/web/src/view/person/person.vue b/web/src/view/person/person.vue index 335601aa0541aa85dc859fe0cb8f6dcdad702a1d..1f8a4008de5c75c920cdbb525443d52ba153100f 100644 --- a/web/src/view/person/person.vue +++ b/web/src/view/person/person.vue @@ -274,7 +274,6 @@ const savePassword = async() => { modifyPwdForm.value.validate((valid) => { if (valid) { changePassword({ - username: userStore.userInfo.userName, password: pwdModify.value.password, newPassword: pwdModify.value.newPassword, }).then((res) => { diff --git a/web/src/view/systemTools/autoPlug/autoPlug.vue b/web/src/view/systemTools/autoPlug/autoPlug.vue index 2102f6d7454bdc6c96df211f465ec8a5910a1635..677cf454a24eab03c4b495414ea5e47de15db95e 100644 --- a/web/src/view/systemTools/autoPlug/autoPlug.vue +++ b/web/src/view/systemTools/autoPlug/autoPlug.vue @@ -96,12 +96,14 @@ 创建 +