提交 d9a100be 编写于 作者: Mr.奇淼('s avatar Mr.奇淼(

权限管理完成

上级 84beb656
......@@ -57,7 +57,7 @@ func DeleteApi(c *gin.Context) {
type AuthAndPathIn struct {
AuthorityId string `json:"authorityId"`
Apis []dbModel.Api `json:"apis"`
ApiIds []uint `json:"apiIds"`
}
// @Tags Api
......@@ -71,7 +71,7 @@ type AuthAndPathIn struct {
func SetAuthAndApi(c *gin.Context) {
var authAndPathIn AuthAndPathIn
_ = c.BindJSON(&authAndPathIn)
err := new(dbModel.ApiAuthority).SetAuthAndApi(authAndPathIn.AuthorityId, authAndPathIn.Apis)
err := new(dbModel.ApiAuthority).SetAuthAndApi(authAndPathIn.AuthorityId, authAndPathIn.ApiIds)
if err != nil {
servers.ReportFormat(c, false, fmt.Sprintf("添加失败:%v", err), gin.H{})
} else {
......@@ -136,7 +136,6 @@ func GetApiById(c *gin.Context) {
// @Param data body api.CreateApiParams true "创建api"
// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /api/updataApi [post]
func UpdataApi(c *gin.Context) {
var api dbModel.Api
_ = c.BindJSON(&api)
......@@ -146,4 +145,22 @@ func GetApiById(c *gin.Context) {
} else {
servers.ReportFormat(c, true, "修改数据成功", gin.H{})
}
}
\ No newline at end of file
}
// @Tags Api
// @Summary 获取所有的Api 不分页
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /api/getAllApis [post]
func GetAllApis(c *gin.Context){
err,apis := new(dbModel.Api).GetAllApis()
if err != nil {
servers.ReportFormat(c, false, fmt.Sprintf("获取数据失败,%v", err), gin.H{})
} else {
servers.ReportFormat(c, true, "获取数据成功", gin.H{
"apis": apis,
})
}
}
\ No newline at end of file
......@@ -82,4 +82,30 @@ func GetAuthorityList(c *gin.Context){
"pageSize": pageInfo.PageSize,
})
}
}
type GetAuthorityId struct {
AuthorityId string `json:"authorityId"`
}
// @Tags authority
// @Summary 获取本角色所有有权限的apiId
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body api.GetAuthorityId true "获取本角色所有有权限的apiId"
// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /authority/getAuthAndApi [post]
func GetAuthAndApi(c *gin.Context){
var idInfo GetAuthorityId
_ = c.BindJSON(&idInfo)
err,apis := new(dbModel.ApiAuthority).GetAuthAndApi(idInfo.AuthorityId)
if err != nil {
servers.ReportFormat(c, false, fmt.Sprintf("获取数据失败,%v", err), gin.H{})
} else {
servers.ReportFormat(c, true, "获取数据成功", gin.H{
"apis": apis,
})
}
}
\ No newline at end of file
......@@ -138,7 +138,7 @@ type IdInfo struct {
}
// @Tags menu
// @Summary 获取指定角色menu
// @Summary 删除菜单
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
......@@ -157,11 +157,11 @@ func DeleteBaseMenu(c *gin.Context) {
}
// @Tags menu
// @Summary 新增菜单
// @Summary 更新菜单
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body dbModel.BaseMenu true "新增菜单"
// @Param data body dbModel.BaseMenu true "更新菜单"
// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /menu/updataBaseMen [post]
func UpdataBaseMenu(c *gin.Context) {
......
......@@ -2,13 +2,22 @@ package middleware
import (
"errors"
"fmt"
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
uuid "github.com/satori/go.uuid"
"main/controller/servers"
"main/init/qmsql"
"time"
)
type SqlRes struct {
Path string
AuthorityId string
ApiId uint
Id uint
}
func JWTAuth() gin.HandlerFunc {
return func(c *gin.Context) {
// 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localSstorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
......@@ -31,6 +40,14 @@ func JWTAuth() gin.HandlerFunc {
c.Abort()
return
}
var sqlRes SqlRes
row:=qmsql.DEFAULTDB.Raw("SELECT apis.path,api_authorities.authority_id,api_authorities.api_id,apis.id FROM apis INNER JOIN api_authorities ON api_authorities.api_id = apis.id WHERE apis.path = ? AND api_authorities.authority_id = ?",c.Request.RequestURI,claims.AuthorityId)
err=row.Scan(&sqlRes).Error
if(fmt.Sprintf("%v",err) == "record not found"){
servers.ReportFormat(c, false, "没有Api操作权限", gin.H{})
c.Abort()
return
}
c.Set("claims", claims)
}
}
......
......@@ -12,6 +12,7 @@ type Api struct {
gorm.Model
Path string `json:"path"`
Description string `json:"description"`
Group string `json:"group"`
}
func (a *Api) CreateApi() (err error) {
......@@ -38,6 +39,12 @@ func (a *Api) GetApiById(id float64)(err error,api Api){
err = qmsql.DEFAULTDB.Where("id = ?",id).First(&api).Error
return
}
// 获取所有api信息
func (a *Api)GetAllApis()(err error,apis []Api){
err = qmsql.DEFAULTDB.Find(&apis).Error
return
}
// 分页获取数据 需要分页实现这个接口即可
func (a *Api) GetInfoList(info modelInterface.PageInfo) (err error, list interface{}, total int) {
......@@ -47,7 +54,7 @@ func (a *Api) GetInfoList(info modelInterface.PageInfo) (err error, list interfa
return
} else {
var apiList []Api
err = db.Find(&apiList).Error
err = db.Order("group").Find(&apiList).Error
return err, apiList, total
}
}
......@@ -14,13 +14,23 @@ type ApiAuthority struct {
}
//创建角色api关联关系
func (a *ApiAuthority) SetAuthAndApi(authId string, apis []Api) (err error) {
err = qmsql.DEFAULTDB.Where("authority_id = ?", authId).Delete(&ApiAuthority{}).Error
for _, v := range apis {
err = qmsql.DEFAULTDB.Create(&ApiAuthority{AuthorityId: authId, ApiId: v.ID}).Error
func (a *ApiAuthority) SetAuthAndApi(authId string, apisid []uint) (err error) {
err = qmsql.DEFAULTDB.Where("authority_id = ?", authId).Unscoped().Delete(&ApiAuthority{}).Error
for _, v := range apisid {
err = qmsql.DEFAULTDB.Create(&ApiAuthority{AuthorityId: authId, ApiId: v}).Error
if err != nil {
return err
}
}
return nil
}
// 获取角色api关联关系
func (a *ApiAuthority) GetAuthAndApi(authId string) (err error,apiIds []uint) {
var apis []ApiAuthority
err = qmsql.DEFAULTDB.Where("authority_id = ?", authId).Find(&apis).Error
for _, v := range apis {
apiIds = append(apiIds,v.ApiId)
}
return nil,apiIds
}
\ No newline at end of file
......@@ -11,9 +11,11 @@ func InitApiRouter(Router *gin.Engine) {
{
ApiRouter.POST("createApi", api.CreateApi) //创建Api
ApiRouter.POST("deleteApi", api.DeleteApi) //删除Api
ApiRouter.POST("setAuthAndPath",api.SetAuthAndApi) // 设置api和角色关系
ApiRouter.POST("setAuthAndApi",api.SetAuthAndApi) // 设置api和角色关系
ApiRouter.POST("getApiList",api.GetApiList) //获取Api列表
ApiRouter.POST("getApiById",api.GetApiById) //获取单条Api消息
ApiRouter.POST("updataApi",api.UpdataApi) //更新api
ApiRouter.POST("getAllApis",api.GetAllApis) // 获取所有api
ApiRouter.POST("getAuthAndApi",api.GetAuthAndApi) // 获取api和auth关系
}
}
......@@ -9,8 +9,8 @@ import (
func InitAuthorityRouter(Router *gin.Engine) {
AuthorityRouter := Router.Group("authority").Use(middleware.JWTAuth())
{
AuthorityRouter.POST("createAuthority", api.CreateAuthority)
AuthorityRouter.POST("deleteAuthority", api.DeleteAuthority)
AuthorityRouter.POST("getAuthorityList",api.GetAuthorityList)
AuthorityRouter.POST("createAuthority", api.CreateAuthority) //创建角色
AuthorityRouter.POST("deleteAuthority", api.DeleteAuthority) //删除角色
AuthorityRouter.POST("getAuthorityList",api.GetAuthorityList) //获取角色列表
}
}
......@@ -9,14 +9,14 @@ import (
func InitMenuRouter(Router *gin.Engine) {
MenuRouter := Router.Group("menu").Use(middleware.JWTAuth())
{
MenuRouter.POST("getMenu", api.GetMenu)
MenuRouter.POST("getMenuList", api.GetMenuList)
MenuRouter.POST("addBaseMenu", api.AddBaseMenu)
MenuRouter.POST("getBaseMenuTree", api.GetBaseMenuTree)
MenuRouter.POST("addMenuAuthority", api.AddMenuAuthority)
MenuRouter.POST("getMenuAuthority", api.GetMenuAuthority)
MenuRouter.POST("deleteBaseMenu", api.DeleteBaseMenu)
MenuRouter.POST("updataBaseMenu", api.UpdataBaseMenu)
MenuRouter.POST("getBaseMenuById", api.GetBaseMenuById)
MenuRouter.POST("getMenu", api.GetMenu) //获取菜单树
MenuRouter.POST("getMenuList", api.GetMenuList) // 分页获取基础menu列表
MenuRouter.POST("addBaseMenu", api.AddBaseMenu) // 新增菜单
MenuRouter.POST("getBaseMenuTree", api.GetBaseMenuTree) // 获取用户动态路由
MenuRouter.POST("addMenuAuthority", api.AddMenuAuthority) // 增加menu和角色关联关系
MenuRouter.POST("getMenuAuthority", api.GetMenuAuthority) // 获取指定角色menu
MenuRouter.POST("deleteBaseMenu", api.DeleteBaseMenu) // 删除菜单
MenuRouter.POST("updataBaseMenu", api.UpdataBaseMenu) // 更新菜单
MenuRouter.POST("getBaseMenuById", api.GetBaseMenuById) //根据id获取菜单
}
}
......@@ -9,8 +9,8 @@ import (
func InitUserRouter(Router *gin.Engine) {
UserRouter := Router.Group("user").Use(middleware.JWTAuth())
{
UserRouter.POST("changePassword", api.ChangePassword)
UserRouter.POST("uploadHeaderImg", api.UploadHeaderImg)
UserRouter.POST("getInfoList", api.GetInfoList)
UserRouter.POST("changePassword", api.ChangePassword) // 修改密码
UserRouter.POST("uploadHeaderImg", api.UploadHeaderImg) //上传头像
UserRouter.POST("getInfoList", api.GetInfoList) // 分页获取用户列表
}
}
......@@ -70,8 +70,6 @@ export const updataApi = (data) => {
})
}
// @Tags Api
// @Summary 更新api
// @Security ApiKeyAuth
......@@ -86,4 +84,52 @@ export const setAuthApi = (data) => {
method: 'post',
data
})
}
// @Tags Api
// @Summary 获取所有的Api 不分页
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /api/getAllApis [post]
export const getAllApis = (data) => {
return service({
url: "/api/getAllApis",
method: 'post',
data
})
}
// @Tags authority
// @Summary 获取本角色所有有权限的apiId
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body api.GetAuthorityId true "获取本角色所有有权限的apiId"
// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /authority/getAuthAndApi [post]
export const getAuthAndApi = (data) => {
return service({
url: "/api/getAuthAndApi",
method: 'post',
data
})
}
// @Tags Api
// @Summary 创建api和角色关系
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body api.AuthAndPathIn true "创建api和角色关系"
// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /api/setAuthAndApi [post]
export const setAuthAndApi = (data) => {
return service({
url: "/api/setAuthAndApi",
method: 'post',
data
})
}
\ No newline at end of file
<template>
<div>
<div class="menu-total">
<i class="el-icon-arrow-right"></i>
<i class="el-icon-arrow-right"></i>
</div>
<vue-scroll :ops="ops">
<el-menu
......@@ -31,14 +31,14 @@ export default {
data() {
return {
active: '',
isCollapse: true,
isCollapse: false,
ops: {
bar: {disable:true}
bar: { disable: true }
}
}
},
methods: {
selectMenuItem(index,indexList) {
selectMenuItem(index) {
if (index === this.$route.name) return
this.$router.push({ name: index })
}
......
......@@ -6,6 +6,7 @@
<el-table :data="tableData" border stripe>
<el-table-column label="id" min-width="60" prop="ID"></el-table-column>
<el-table-column label="api路径" min-width="150" prop="path"></el-table-column>
<el-table-column label="api分组" min-width="150" prop="group"></el-table-column>
<el-table-column label="api简介" min-width="150" prop="description"></el-table-column>
<el-table-column fixed="right" label="操作" width="200">
<template slot-scope="scope">
......@@ -29,9 +30,12 @@
<el-dialog :visible.sync="dialogFormVisible" title="新增Api">
<el-form :inline="true" :model="form" label-width="80px">
<el-form-item label="路径">
<el-input autocomplete="off" v-model="form.path"></el-input>
<el-input autocomplete="off" @blur="autoGroup" v-model="form.path"></el-input>
</el-form-item>
<el-form-item label="说明">
<el-form-item label="api分组">
<el-input autocomplete="off" v-model="form.group"></el-input>
</el-form-item>
<el-form-item label="api简介">
<el-input autocomplete="off" v-model="form.description"></el-input>
</el-form-item>
</el-form>
......@@ -60,15 +64,21 @@ export default {
dialogFormVisible: false,
form: {
path: '',
group: '',
description: ''
},
type: ''
}
},
methods: {
// 自动设置api分组
autoGroup(){
this.form.group = this.form.path.split('/')[1]
},
initForm() {
this.form = {
path: '',
group: '',
description: ''
}
},
......
......@@ -45,13 +45,14 @@
<!-- 关联menu弹窗 -->
<el-dialog :visible.sync="menuDialogFlag" title="关联菜单">
<el-tree
:data="treeData"
:default-checked-keys="treeIds"
:props="defaultProps"
v-if="menuDialogFlag"
:data="menuTreeData"
:default-checked-keys="menuTreeIds"
:props="menuDefaultProps"
default-expand-all
highlight-current
node-key="ID"
ref="tree"
ref="menuTree"
show-checkbox
></el-tree>
<div class="dialog-footer" slot="footer">
......@@ -59,6 +60,27 @@
<el-button @click="relation" type="primary">确 定</el-button>
</div>
</el-dialog>
<!-- 关联api弹窗 -->
<el-dialog :visible.sync="apiDialogFlag" title="关联api">
<el-tree
v-if="apiDialogFlag"
:data="apiTreeData"
:default-checked-keys="apiTreeIds"
:props="apiDefaultProps"
default-expand-all
highlight-current
node-key="ID"
ref="apiTree"
show-checkbox
></el-tree>
<div class="dialog-footer" slot="footer">
<el-button @click="closeDialog">取 消</el-button>
<el-button @click="authApiEnter" type="primary">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
......@@ -71,6 +93,11 @@ import {
createAuthority
} from '@/api/authority'
import { getBaseMenuTree, addMenuAuthority, getMenuAuthority } from '@/api/menu'
import {
getAllApis,
getAuthAndApi,
setAuthAndApi
} from '@/api/api'
import infoList from '@/view/superAdmin/mixins/infoList'
export default {
name: 'Authority',
......@@ -80,14 +107,22 @@ export default {
listApi: getAuthorityList,
listKey:'list',
activeUserId: 0,
treeData: [],
treeIds: [],
defaultProps: {
menuTreeData: [],
menuTreeIds: [],
menuDefaultProps: {
children: 'children',
label: 'nickName'
},
apiTreeData: [],
apiTreeIds: [],
apiDefaultProps: {
children: 'children',
label: 'description'
},
dialogFormVisible: false,
menuDialogFlag: false,
apiDialogFlag: false,
form: {
authorityId: '',
authorityName: ''
......@@ -130,8 +165,10 @@ export default {
this.initForm()
this.dialogFormVisible = false
this.menuDialogFlag = false
this.apiDialogFlag = false
},
// 确定弹窗
async enterDialog() {
const res = await createAuthority(this.form)
if (res.success) {
......@@ -161,17 +198,14 @@ export default {
arr.push(Number(item.menuId))
}
})
this.treeIds = arr
const res2 = await getBaseMenuTree()
this.treeData = res2.data.menus
this.menuTreeIds = arr
this.activeUserId = row.authorityId
this.menuDialogFlag = true
},
// 关联树 确认方法
async relation() {
const checkArr = this.$refs.tree
.getCheckedNodes()
.concat(this.$refs.tree.getHalfCheckedNodes())
const checkArr = this.$refs.menuTree
.getCheckedNodes(false,true)
const res = await addMenuAuthority({
menus: checkArr,
authorityId: this.activeUserId
......@@ -183,11 +217,56 @@ export default {
})
}
this.closeDialog()
},
// 创建api树方法
buildApiTree(apis){
const apiObj = new Object
apis&&apis.map(item=>{
if(apiObj.hasOwnProperty(item.group)){
apiObj[item.group].push(item)
}else{
Object.assign(apiObj,{[item.group]:[item]})
}
})
const apiTree = []
for(const key in apiObj){
const treeNode = {
ID:key,
description:key+"",
children:apiObj[key]
}
apiTree.push(treeNode)
}
return apiTree
},
// 关联用户api关系
async addAuthApi(row){
const res = await getAuthAndApi({authorityId:row.authorityId})
this.activeUserId = row.authorityId
this.apiTreeIds = res.data.apis||[]
this.apiDialogFlag = true
},
async authApiEnter(){
const checkArr = this.$refs.apiTree.getCheckedKeys(true)
const res = await setAuthAndApi({authorityId:this.activeUserId,apiIds:checkArr})
if (res.success) {
this.$message({
type: 'success',
message: '添加成功!'
})
}
this.closeDialog()
}
// 获取基础menu树
},
created() {
async created() {
this.getTableData()
// 获取所有菜单树
const res = await getBaseMenuTree()
this.menuTreeData = res.data.menus
// 获取api并整理成树结构
const res2 = await getAllApis()
const apis = res2.data.apis
this.apiTreeData = this.buildApiTree(apis)
}
}
</script>
......
......@@ -6,13 +6,7 @@ function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
/**
* You will need to set publicPath if you plan to deploy your site under a sub path,
* for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
* then publicPath should be set to "/bar/".
* In most cases please use '/' !!!
* Detail: https://cli.vuejs.org/config/#publicpath
*/
// 基础配置 详情看文档
publicPath: '/',
outputDir: 'dist',
assetsDir: 'static',
......@@ -26,20 +20,19 @@ module.exports = {
errors: true
},
proxy: {
// change xxx-api/login => mock/login
// 把key的路径代理到target位置
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: {
target: `http://127.0.0.1:8888`,
[process.env.VUE_APP_BASE_API]: { //需要代理的路径 例如 '/api'
target: `http://127.0.0.1:8888`, //代理到 目标路径
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
pathRewrite: { // 修改路径数据
['^' + process.env.VUE_APP_BASE_API]: '' // 举例 '^/api:""' 把路径中的/api字符串删除
}
}
},
},
configureWebpack: {
// provide the app's title in webpack's name field, so that
// it can be accessed in index.html to inject the correct title.
// @路径走src文件夹
resolve: {
alias: {
'@': resolve('src')
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册