├── perm-vue
├── build
│ ├── logo.png
│ ├── vue-loader.conf.js
│ ├── build.js
│ ├── check-versions.js
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ ├── utils.js
│ └── webpack.prod.conf.js
├── config
│ ├── prod.env.js
│ ├── dev.env.js
│ └── index.js
├── static
│ ├── img
│ │ └── img.jpg
│ ├── css
│ │ ├── icon.css
│ │ ├── theme-green
│ │ │ ├── fonts
│ │ │ │ ├── element-icons.ttf
│ │ │ │ └── element-icons.woff
│ │ │ └── color-green.css
│ │ ├── color-dark.css
│ │ └── main.css
│ └── vuetable.json
├── src
│ ├── assets
│ │ ├── logo.png
│ │ ├── login-bg.jpg
│ │ ├── login-bg1.jpg
│ │ ├── reset.css
│ │ └── util.js
│ ├── components
│ │ ├── common
│ │ │ ├── bus.js
│ │ │ ├── Home.vue
│ │ │ ├── Sidebar.vue
│ │ │ └── Tags.vue
│ │ └── page
│ │ │ ├── demo
│ │ │ ├── Permission.vue
│ │ │ ├── VueEditor.vue
│ │ │ ├── Markdown.vue
│ │ │ ├── BaseCharts.vue
│ │ │ ├── Upload.vue
│ │ │ ├── Tabs.vue
│ │ │ ├── DragList.vue
│ │ │ └── BaseForm.vue
│ │ │ ├── error-page
│ │ │ ├── 403.vue
│ │ │ └── 404.vue
│ │ │ ├── sys-user
│ │ │ └── department
│ │ │ │ ├── tree.utils.js
│ │ │ │ └── tree.scss
│ │ │ └── Login.vue
│ ├── App.vue
│ ├── utils
│ │ ├── utils.js
│ │ └── rest.js
│ ├── router
│ │ ├── index.js
│ │ └── sys-user-router.js
│ └── main.js
├── .babelrc
├── .postcssrc.js
├── index.html
└── package.json
├── perm-server
├── sys-common
│ ├── supports
│ │ ├── commonConst
│ │ │ └── common_const.go
│ │ ├── simple_result.go
│ │ ├── response_message.go
│ │ ├── responseHandle
│ │ │ └── response_handle.go
│ │ └── simple_response.go
│ ├── conf
│ │ ├── config.toml
│ │ ├── rbac_model.conf
│ │ ├── app.yml
│ │ ├── config.go
│ │ └── db.yml
│ ├── utils
│ │ ├── uuid.go
│ │ ├── util.go
│ │ ├── jsonUtil.go
│ │ ├── sysconf.go
│ │ ├── encrypt.go
│ │ └── aes.go
│ ├── vo
│ │ ├── common
│ │ │ └── table_vo.go
│ │ ├── casbin_define.go
│ │ ├── baseVo
│ │ │ └── base_vo.go
│ │ ├── page_vo.go
│ │ └── Pagination.go
│ ├── inits
│ │ ├── sys
│ │ │ ├── role.go
│ │ │ └── user.go
│ │ ├── init.go
│ │ └── parse
│ │ │ ├── app.go
│ │ │ └── db.go
│ ├── middleware
│ │ ├── casbins
│ │ │ ├── parse.go
│ │ │ └── casbins.go
│ │ ├── middleware.go
│ │ └── jwts
│ │ │ └── config.go
│ ├── db
│ │ └── db.go
│ ├── models
│ │ └── baseModel
│ │ │ └── baseModel.go
│ └── caches
│ │ └── redis.go
├── main
│ └── main.go
├── doc
│ └── go-bindata-usage
└── sys-sysbase
│ ├── models
│ └── user
│ │ ├── role_resource.go
│ │ ├── user_role.go
│ │ ├── role.go
│ │ ├── department.go
│ │ ├── user.go
│ │ └── resource.go
│ ├── vo
│ └── uservo
│ │ ├── role_resource_vo.go
│ │ ├── user_role_vo.go
│ │ ├── role_vo.go
│ │ ├── department_vo.go
│ │ └── resource_vo.go
│ ├── routes
│ ├── hub.go
│ └── user
│ │ ├── department_route.go
│ │ └── resource_route.go
│ └── service
│ └── userService
│ ├── role_service.go
│ └── resource_service.go
├── .gitignore
├── .vscode
└── launch.json
├── go.mod
└── README.md
/perm-vue/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alomnt/permissionManage/HEAD/perm-vue/build/logo.png
--------------------------------------------------------------------------------
/perm-vue/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | };
5 |
--------------------------------------------------------------------------------
/perm-vue/static/img/img.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alomnt/permissionManage/HEAD/perm-vue/static/img/img.jpg
--------------------------------------------------------------------------------
/perm-vue/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alomnt/permissionManage/HEAD/perm-vue/src/assets/logo.png
--------------------------------------------------------------------------------
/perm-vue/src/assets/login-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alomnt/permissionManage/HEAD/perm-vue/src/assets/login-bg.jpg
--------------------------------------------------------------------------------
/perm-vue/src/assets/login-bg1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alomnt/permissionManage/HEAD/perm-vue/src/assets/login-bg1.jpg
--------------------------------------------------------------------------------
/perm-server/sys-common/supports/commonConst/common_const.go:
--------------------------------------------------------------------------------
1 | package commonConst
2 |
3 | const (
4 | CURRENT_USER_KEY = "_user_id"
5 | )
6 |
--------------------------------------------------------------------------------
/perm-vue/src/components/common/bus.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 |
3 | // 使用 Event Bus
4 | const bus = new Vue();
5 |
6 | export default bus;
--------------------------------------------------------------------------------
/perm-vue/static/css/icon.css:
--------------------------------------------------------------------------------
1 |
2 | [class*=" el-icon-lx"], [class^=el-icon-lx] {
3 | font-family: lx-iconfont!important;
4 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | *.idea
3 | *.iml
4 | */node_modules
5 | */package-lock.json
6 | *rebel.xml*
7 | .idea/vcs.xml
8 | perm-server/pkg/mod/cache/
9 |
--------------------------------------------------------------------------------
/perm-vue/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", { "modules": false }],
4 | "stage-3"
5 | ],
6 | "plugins": ["transform-vue-jsx"]
7 | }
8 |
--------------------------------------------------------------------------------
/perm-server/sys-common/supports/simple_result.go:
--------------------------------------------------------------------------------
1 | package supports
2 |
3 | type SimResult struct {
4 | Code bool
5 | Msg string
6 | Data interface{}
7 | }
8 |
--------------------------------------------------------------------------------
/perm-vue/static/css/theme-green/fonts/element-icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alomnt/permissionManage/HEAD/perm-vue/static/css/theme-green/fonts/element-icons.ttf
--------------------------------------------------------------------------------
/perm-vue/static/css/theme-green/fonts/element-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alomnt/permissionManage/HEAD/perm-vue/static/css/theme-green/fonts/element-icons.woff
--------------------------------------------------------------------------------
/perm-server/sys-common/conf/config.toml:
--------------------------------------------------------------------------------
1 | #reids
2 | [redis]
3 | Addr = "123.57.66.84:6379"
4 | Password = "123456"
5 | RedisMaxIdle = 10
6 | RedisIdleTimeoutSec = 43200
7 | DB = 1
8 |
--------------------------------------------------------------------------------
/perm-vue/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const merge = require('webpack-merge');
3 | const prodEnv = require('./prod.env');
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | });
8 |
--------------------------------------------------------------------------------
/perm-vue/src/assets/reset.css:
--------------------------------------------------------------------------------
1 | .el-row {
2 | margin-bottom: 20px;
3 | }
4 | .demo-input-suffix {
5 | display: inline-block;
6 | width: 35%;
7 | text-align: right;
8 | }
9 | .table {
10 | width: 100%!important;
11 | font-size: 14px!important;
12 | }
--------------------------------------------------------------------------------
/perm-server/sys-common/utils/uuid.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "github.com/gofrs/uuid"
5 | "strings"
6 | )
7 |
8 | func GetUuid() string {
9 | var uuid = uuid.Must(uuid.NewV4()).String()
10 | uuid = strings.Replace(uuid, "-", "", -1)
11 | return uuid
12 | }
13 |
--------------------------------------------------------------------------------
/perm-vue/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | // to edit target browsers: use "browserslist" field in package.json
6 | "postcss-import": {},
7 | "autoprefixer": {}
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/perm-vue/src/assets/util.js:
--------------------------------------------------------------------------------
1 | export default {
2 | GetSessionStorage: function (index, data) {
3 | if (data == '没有登录') {
4 | index.$router.push({path: '/login'});
5 | } else {
6 | index.$message.error(data);
7 | }
8 | },
9 | }
10 |
--------------------------------------------------------------------------------
/perm-server/sys-common/vo/common/table_vo.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | type TableVO struct {
4 | Total int64 `json:"total"`
5 | Rows interface{} `json:"rows"`
6 | }
7 |
8 | func NewTableVO(total int64, rows interface{}) *TableVO {
9 | return &TableVO{
10 | Total: total,
11 | Rows: rows,
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/perm-vue/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/perm-server/sys-common/conf/rbac_model.conf:
--------------------------------------------------------------------------------
1 | [request_definition]
2 | r = sub, obj, act, suf
3 |
4 | [policy_definition]
5 | p = sub, obj, act, suf
6 |
7 | [role_definition]
8 | g = _, _
9 |
10 | [policy_effect]
11 | e = some(where (p.eft == allow))
12 |
13 | [matchers]
14 | m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && regexMatch(r.suf, p.suf) && regexMatch(r.act, p.act) || r.sub == "1"
--------------------------------------------------------------------------------
/perm-server/sys-common/supports/response_message.go:
--------------------------------------------------------------------------------
1 | package supports
2 |
3 | const (
4 | PARAM_IS_EMPTY string = "入参为空"
5 |
6 | QUERY_FAIL string = "查询异常"
7 |
8 | ADD_FAIL string = "添加失败"
9 | ADD_SUCCESS string = "添加成功"
10 |
11 | UPDATE_FAIL string = "更新失败"
12 | UPDATE_SUCCESS string = "更新成功"
13 |
14 | DELETE_FAIL string = "删除失败"
15 | DELETE_SUCCESS string = "删除成功"
16 | )
17 |
--------------------------------------------------------------------------------
/perm-vue/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 基础demo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/perm-server/main/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | _ "permissionManage/perm-server/sys-common/inits"
5 | conf "permissionManage/perm-server/sys-common/inits/parse"
6 | "permissionManage/perm-server/sys-sysbase/routes"
7 |
8 | "github.com/kataras/iris/v12"
9 | )
10 |
11 | func main() {
12 | app := iris.New()
13 | routes.Hub(app)
14 | app.Run(iris.Addr(":"+conf.O.Port), iris.WithConfiguration(conf.C))
15 | }
16 |
--------------------------------------------------------------------------------
/perm-server/sys-common/conf/app.yml:
--------------------------------------------------------------------------------
1 | DisablePathCorrection: false
2 | EnablePathEscape: false
3 | FireMethodNotAllowed: false
4 | DisableBodyConsumptionOnUnmarshal: false
5 | TimeFormat: Mon, 01 Jan 2006 15:04:05 GMT
6 | Charset: UTF-8
7 | #自定义配置
8 | Other:
9 | Port: 8098
10 | IgnoreURLs: [/, /perm/user/login, /perm/user/registe, /perm/login_pwd]
11 | JWTTimeout: 900 #second
12 | LogLevel: debug
13 | Secret: xxx-Secret
14 |
15 |
16 |
--------------------------------------------------------------------------------
/perm-server/sys-common/conf/config.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | import (
4 | "fmt"
5 | "github.com/pelletier/go-toml"
6 | )
7 |
8 | var (
9 | Conf = New()
10 | )
11 |
12 | /**
13 | * 返回单例实例
14 | * @method New
15 | */
16 | func New() *toml.Tree {
17 | config, err := toml.LoadFile("./perm-server/sys-common/conf/config.toml")
18 |
19 | if err != nil {
20 | fmt.Println("TomlError ", err.Error())
21 | }
22 |
23 | return config
24 | }
25 |
--------------------------------------------------------------------------------
/perm-server/sys-common/vo/casbin_define.go:
--------------------------------------------------------------------------------
1 | package vo
2 |
3 | // 前端请求的结构体
4 | type (
5 | RoleDefine struct {
6 | // 角色的标识等于casbin的sub,但角色需要加role_前缀
7 | Sub string `json:"sub"`
8 | // 对应casbin model的定义
9 | Obj string `json:"obj"`
10 | Act string `json:"act"`
11 | Suf string `json:"suf"`
12 | RoleName string `json:"roleName"`
13 | }
14 |
15 | // 用户所属角色组
16 | GroupDefine struct {
17 | Uid int64 `json:"uid"`
18 | Sub []string `json:"sub"`
19 | }
20 | )
21 |
--------------------------------------------------------------------------------
/perm-server/sys-common/supports/responseHandle/response_handle.go:
--------------------------------------------------------------------------------
1 | package responseHandle
2 |
3 | import (
4 | "github.com/kataras/iris/v12"
5 | "permissionManage/perm-server/sys-common/supports"
6 | )
7 |
8 | func Response(ctx iris.Context, res *supports.SimResult) {
9 | if res == nil {
10 | supports.Ok(ctx, "", "")
11 | return
12 | }
13 |
14 | if !res.Code {
15 | supports.Error(ctx, iris.StatusInternalServerError, res.Msg, nil)
16 | return
17 | }
18 |
19 | supports.Ok(ctx, res.Msg, res.Data)
20 | }
21 |
--------------------------------------------------------------------------------
/perm-vue/static/css/color-dark.css:
--------------------------------------------------------------------------------
1 | .header{
2 | background-color: #242f42;
3 | }
4 | .login-wrap{
5 | background: #324157;
6 | }
7 | .plugins-tips{
8 | background: #eef1f6;
9 | }
10 | .plugins-tips a{
11 | color: #20a0ff;
12 | }
13 | .el-upload--text em {
14 | color: #20a0ff;
15 | }
16 | .pure-button{
17 | background: #20a0ff;
18 | }
19 | .tags-li.active {
20 | border: 1px solid #409EFF;
21 | background-color: #409EFF;
22 | }
23 | .message-title{
24 | color: #20a0ff;
25 | }
26 | .collapse-btn:hover{
27 | background: rgb(40,52,70);
28 | }
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 |
8 | {
9 | "name": "Launch",
10 | "type": "go",
11 | "request": "launch",
12 | "mode": "auto",
13 | "program": "${fileDirname}",
14 | "env": {},
15 | "args": []
16 | }
17 | ]
18 | }
--------------------------------------------------------------------------------
/perm-server/sys-common/conf/db.yml:
--------------------------------------------------------------------------------
1 |
2 | master:
3 | dialect: mysql
4 | user: root
5 | password: 123456
6 | host: 123.57.66.84
7 | port: 3306
8 | database: cd_dev
9 | charset: utf8
10 | showSql: true
11 | logLevel: debug
12 | maxIdleConns: 10 # 连接池的空闲数大小
13 | # maxOpenConns: 10 # 最大打开连接数
14 | slave:
15 | dialect: mysql
16 | user: root
17 | password: 123456
18 | host: 127.0.0.1
19 | port: 3306
20 | database: cd_dev
21 | charset: utf8
22 | showSql: true
23 | logLevel: debug
24 | maxIdleConns: 10 # 连接池的空闲数大小
25 | # maxOpenConns: 10 # 最大打开连接数
26 |
--------------------------------------------------------------------------------
/perm-server/sys-common/utils/util.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 | "strconv"
6 | "time"
7 | )
8 |
9 | const (
10 | rolePrefix string = "role_"
11 | )
12 |
13 | //
14 | func FmtRolePrefix(sub interface{}) string {
15 | var s string
16 | switch sub.(type) {
17 | case int64:
18 | uid := sub.(int64)
19 | s = strconv.FormatInt(uid, 10)
20 | case string:
21 | s = sub.(string)
22 | }
23 | return fmt.Sprintf("%s%s", rolePrefix, s)
24 | }
25 |
26 | // timestamp to time
27 | func StampToTime(st int64) time.Time {
28 | return time.Unix(st/1000, 0)
29 | }
30 |
--------------------------------------------------------------------------------
/perm-server/sys-common/utils/jsonUtil.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "encoding/json"
5 | "github.com/kataras/golog"
6 | )
7 |
8 | //
9 | func StructToString(stru interface{}) string {
10 |
11 | jsons, err := json.Marshal(stru) //转换成JSON返回的是byte[]
12 | if err != nil {
13 | err.Error()
14 | golog.Error(err)
15 | return ""
16 | }
17 | return string(jsons)
18 | }
19 |
20 | func ByteToStruct(byt []byte, stru interface{}) interface{} {
21 | err := json.Unmarshal(byt, &stru)
22 | if err != nil {
23 | err.Error()
24 | golog.Error(err)
25 | return stru
26 | }
27 | return stru
28 | }
29 |
--------------------------------------------------------------------------------
/perm-server/sys-common/utils/sysconf.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | /*
8 | 前面是含义,后面是 go 的表示值,多种表示,逗号","分割
9 | 年 06,2006
10 | 月份 1,01,Jan,January
11 | 日 2,02,_2
12 | 时 3,03,15,PM,pm,AM,am
13 | 分 4,04
14 | 秒 5,05
15 | 周几 Mon,Monday
16 | 时区时差表示 -07,-0700,Z0700,Z07:00,-07:00,MST
17 | 时区字母缩写 MST
18 | 您看出规律了么!哦是的,你发现了,这里面没有一个是重复的,所有的值表示都唯一对应一个时间部分。
19 | 并且涵盖了很多格式组合。
20 | */
21 | const (
22 | // 时间格式化字符串
23 | SysTimeform string = "2006-01-02 15:04:05"
24 | SysTimeformShort string = "2006-01-02"
25 | //
26 |
27 | )
28 |
29 | // 中国时区
30 | var SysTimeLocation, _ = time.LoadLocation("Asia/Chongqing")
31 |
--------------------------------------------------------------------------------
/perm-vue/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/perm-server/sys-common/inits/sys/role.go:
--------------------------------------------------------------------------------
1 | package sys
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/middleware/casbins"
5 |
6 | "github.com/kataras/golog"
7 | )
8 |
9 | var (
10 | // 定义系统初始的角色
11 | Components = [][]string{
12 | {"0", "角色管理", "role_admin*", "角色管理"},
13 | {"0", "demo角色", "role_demo*", "demo角色"},
14 | }
15 | )
16 |
17 | // 创建系统默认角色
18 | func CreateSystemRole() bool {
19 | e := casbins.GetEnforcer()
20 |
21 | for _, v := range Components {
22 | p := e.GetFilteredPolicy(0, v[0])
23 | if len(p) == 0 {
24 | if ok := e.AddPolicy(v); !ok {
25 | golog.Fatalf("初始化角色[%s]权限失败。%s", v)
26 | }
27 | }
28 | }
29 | return true
30 | }
31 |
--------------------------------------------------------------------------------
/perm-vue/src/utils/utils.js:
--------------------------------------------------------------------------------
1 | export const getToken = () => {
2 | let token = '';
3 | let user = JSON.parse(window.sessionStorage.getItem('user'));
4 | if (user) {
5 | token = user.token
6 | }
7 | return token
8 | };
9 |
10 | export const fmtToken = () => {
11 | let fmttoken = 'bearer ';
12 | let user = window.sessionStorage.getItem('user');
13 | if (user) {
14 | fmttoken += getToken()
15 | }
16 | return fmttoken
17 | };
18 |
19 | export const getUserId = () => {
20 | let userId = '';
21 | let user = JSON.parse(window.sessionStorage.getItem('user'));
22 | if (user) {
23 | userId = user.id
24 | }
25 | return userId
26 | };
--------------------------------------------------------------------------------
/perm-vue/static/css/theme-green/color-green.css:
--------------------------------------------------------------------------------
1 | .header{
2 | background-color: #07c4a8;
3 | }
4 | .login-wrap{
5 | background: rgba(56, 157, 170, 0.82);;
6 | }
7 | .plugins-tips{
8 | background: #f2f2f2;
9 | }
10 | .plugins-tips a{
11 | color: #00d1b2;
12 | }
13 | .el-upload--text em {
14 | color: #00d1b2;
15 | }
16 | .pure-button{
17 | background: #00d1b2;
18 | }
19 | .pagination > .active > a, .pagination > .active > a:hover, .pagination > .active > a:focus, .pagination > .active > span, .pagination > .active > span:hover, .pagination > .active > span:focus {
20 | background-color: #00d1b2 !important;
21 | border-color: #00d1b2 !important;
22 | }
23 | .tags-li.active {
24 | border: 1px solid #00d1b2;
25 | background-color: #00d1b2;
26 | }
27 | .collapse-btn:hover{
28 | background: #00d1b2;
29 | }
--------------------------------------------------------------------------------
/perm-vue/src/components/page/demo/Permission.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 权限测试
6 |
7 |
8 |
9 |
管理员权限页面
10 |
只有用 admin 账号登录的才拥有管理员权限,才能进到这个页面,其他账号想进来都会跳到403页面,重新用管理员账号登录才有权限。
11 |
想尝试一下,请退出登录,随便输入个账号名,再进来试试看。
12 |
13 |
14 |
15 |
16 |
17 |
24 |
25 |
--------------------------------------------------------------------------------
/perm-server/sys-common/inits/init.go:
--------------------------------------------------------------------------------
1 | package inits
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/inits/parse"
5 | "permissionManage/perm-server/sys-common/inits/sys"
6 | "permissionManage/perm-server/sys-sysbase/models/user"
7 |
8 | "github.com/kataras/golog"
9 | )
10 |
11 | func init() {
12 | parse.AppOtherParse()
13 | parse.DBSettingParse()
14 |
15 | initRootUser()
16 | }
17 |
18 | func initRootUser() {
19 | // root is existed?
20 | if sys.CheckRootExit() {
21 | return
22 | }
23 |
24 | // create root user
25 | sys.CreateRoot()
26 |
27 | ok := sys.CreateSystemRole()
28 | if ok {
29 | addRoleMenu()
30 | }
31 |
32 | }
33 |
34 | func addRoleMenu() {
35 | // 添加role-menu关系
36 | rMenus := []*user.RoleResource{
37 | {RoleId: "", ResourceId: ""},
38 | }
39 | effect, err := user.CreateRelationRoleResource(rMenus...)
40 | if err != nil {
41 | golog.Fatalf("**@@@@@@@@@@@0> %d, %s", effect, err.Error())
42 | }
43 | golog.Infof("@@@@@@@@@-> %s, %s", effect, err.Error())
44 | }
45 |
--------------------------------------------------------------------------------
/perm-server/doc/go-bindata-usage:
--------------------------------------------------------------------------------
1 | ### install go-bindata
2 | go get -u github.com/go-bindata/go-bindata/...
3 |
4 | eg:
5 | ** [Please select this command !]
6 | ** Pack current directory(conf/) all configs.
7 | go-bindata -pkg parse -o inits/parse/conf-data.go conf/
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | ** [Don't exec below !]
59 | ** Pack current directory(conf/**), and to include all input sub-directories recursively configs.
60 | go-bindata -pkg parse -o inits/parse/conf-data.go conf/...
61 |
62 | ** Pack conf/app.yml
63 | go-bindata -pkg parse -o inits/parse/app-data.go conf/app.yml
64 |
65 | ** Pack conf/db.yml
66 | go-bindata -pkg parse -o inits/parse/db-data.go conf/db.yml
67 |
68 | ** Pack conf/app.yml
69 | go-bindata -pkg parse -o inits/parse/rbac_model-data.go conf/rbac_model.conf
--------------------------------------------------------------------------------
/perm-vue/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Router from 'vue-router';
3 | import sys_user_router from './sys-user-router'
4 |
5 | Vue.use(Router);
6 |
7 | export default new Router({
8 | routes: [
9 | {
10 | path: '/',
11 | redirect: '/dashboard'
12 | },
13 | {
14 | path: '/',
15 | component: resolve => require(['../components/common/Home.vue'], resolve),
16 | children: [
17 | {
18 | path: '/dashboard',
19 | component: resolve => require(['../components/page/demo/Dashboard.vue'], resolve),
20 | meta: {title: '系统首页'}
21 | },
22 | ...sys_user_router
23 | ]
24 | },
25 | {
26 | path: '/login',
27 | component: resolve => require(['../components/page/Login.vue'], resolve)
28 | },
29 | {
30 | path: '*',
31 | redirect: '/404'
32 | }
33 | ]
34 | })
35 |
--------------------------------------------------------------------------------
/perm-server/sys-common/middleware/casbins/parse.go:
--------------------------------------------------------------------------------
1 | package casbins
2 |
3 | import (
4 | "github.com/kataras/golog"
5 | )
6 |
7 | /**
8 | 用于解析权限
9 | */
10 |
11 | // 通过uid获取用户的所有资源
12 | func GetAllResourcesByUID(uid string) map[string]interface{} {
13 | allRes := make(map[string]interface{})
14 |
15 | e := GetEnforcer()
16 |
17 | myRes := e.GetPermissionsForUser(uid)
18 | golog.Infof("myRes=> %s", myRes)
19 |
20 | // 获取用户的隐形角色
21 | implicitRoles := e.GetImplicitRolesForUser(uid)
22 | for _, v := range implicitRoles{
23 | // 查询用户隐形角色的资源权限
24 | subRes := e.GetPermissionsForUser(v)
25 | golog.Infof("-------------------------------------------------")
26 | golog.Infof("subRes[%s], len(res)=> %d", v, len(subRes))
27 | golog.Infof("subRes[%s], res=> %s", v, subRes)
28 | golog.Infof("-------------------------------------------------")
29 | allRes[v] = subRes
30 | }
31 |
32 | allRes["myRes"] = myRes
33 | return allRes
34 | }
35 |
36 | // 通过uid获取用户的所有角色
37 | func GetAllRoleByUID(uid string) []string {
38 | e := GetEnforcer()
39 | roles := e.GetImplicitRolesForUser(uid)
40 | golog.Infof("roles=> %s", roles)
41 | return roles
42 | }
43 |
--------------------------------------------------------------------------------
/perm-vue/static/vuetable.json:
--------------------------------------------------------------------------------
1 | {
2 | "list": [{
3 | "date": "1997-11-11",
4 | "name": "林丽",
5 | "address": "吉林省 辽源市 龙山区"
6 | }, {
7 | "date": "1987-09-24",
8 | "name": "文敏",
9 | "address": "江西省 萍乡市 芦溪县"
10 | }, {
11 | "date": "1996-08-08",
12 | "name": "杨秀兰",
13 | "address": "黑龙江省 黑河市 五大连池市"
14 | }, {
15 | "date": "1978-06-18",
16 | "name": "魏强",
17 | "address": "广东省 韶关市 始兴县"
18 | }, {
19 | "date": "1977-07-09",
20 | "name": "石秀兰",
21 | "address": "江苏省 宿迁市 宿豫区"
22 | }, {
23 | "date": "1994-09-20",
24 | "name": "朱洋",
25 | "address": "海外 海外 -"
26 | }, {
27 | "date": "1980-01-22",
28 | "name": "傅敏",
29 | "address": "海外 海外 -"
30 | }, {
31 | "date": "1985-10-10",
32 | "name": "毛明",
33 | "address": "内蒙古自治区 包头市 九原区"
34 | }, {
35 | "date": "1975-09-08",
36 | "name": "何静",
37 | "address": "西藏自治区 阿里地区 普兰县"
38 | }, {
39 | "date": "1970-06-07",
40 | "name": "郭秀英",
41 | "address": "四川省 巴中市 恩阳区"
42 | }]
43 | }
--------------------------------------------------------------------------------
/perm-server/sys-common/vo/baseVo/base_vo.go:
--------------------------------------------------------------------------------
1 | package baseVo
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | // 基础信息
8 | type BaseVO struct {
9 | Id string `json:"id" form:"id"`
10 | CreateTime time.Time `json:"createTime" form:"createTime"`
11 | CreatorDepartmentId string `json:"creatorDepartmentId" form:"creatorDepartmentId"`
12 | CreatorDepartmentName string `json:"creatorDepartmentName" form:"creatorDepartmentName"`
13 | CreatorId string `json:"creatorId" form:"creatorId"`
14 | CreatorName string `json:"creatorName" form:"creatorName"`
15 | IsDeleted int64 `json:"isDeleted" form:"isDeleted"`
16 | UpdateTime time.Time `json:"updateTime" form:"updateTime"`
17 | UpdatorDepartmentId string `json:"updatorDepartmentId" form:"updatorDepartmentId"`
18 | UpdatorDepartmentName string `json:"updatorDepartmentName" form:"updatorDepartmentName"`
19 | UpdatorId string `json:"updatorId" form:"updatorId"`
20 | UpdatorName string `json:"updatorName" form:"updatorName"`
21 | Version int64 `json:"version" form:"version"`
22 | Token string `json:"token"`
23 | }
24 |
--------------------------------------------------------------------------------
/perm-server/sys-common/middleware/middleware.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/inits/parse"
5 | "permissionManage/perm-server/sys-common/middleware/casbins"
6 | "permissionManage/perm-server/sys-common/middleware/jwts"
7 | "strings"
8 |
9 | "github.com/kataras/iris/v12/context"
10 | )
11 |
12 | type Middleware struct {
13 | }
14 |
15 | func ServeHTTP(ctx context.Context) {
16 | path := ctx.Path()
17 | // 过滤静态资源、login接口、首页等...不需要验证
18 | if checkURL(path) || strings.Contains(path, "/static") {
19 | ctx.Next()
20 | return
21 | }
22 |
23 | // jwt token拦截
24 | if !jwts.Serve(ctx) {
25 | return
26 | }
27 |
28 | // 系统菜单不进行权限拦截
29 | if !strings.Contains(path, "/sysMenu") {
30 | // casbin权限拦截
31 | ok := casbins.CheckPermissions(ctx)
32 | if !ok {
33 | return
34 | }
35 | }
36 |
37 | // Pass to real API
38 | ctx.Next()
39 | }
40 |
41 | /**
42 | return
43 | true:则跳过不需验证,如登录接口等...
44 | false:需要进一步验证
45 | */
46 | func checkURL(reqPath string) bool {
47 | //config := iris.YAML("conf/app.yml")
48 | //ignoreURLs := config.GetOther()["ignoreURLs"].([]interface{})
49 | for _, v := range parse.O.IgnoreURLs {
50 | if reqPath == v {
51 | return true
52 | }
53 | }
54 | return false
55 | }
56 |
--------------------------------------------------------------------------------
/perm-vue/src/router/sys-user-router.js:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | path: '/departments',
4 | component: resolve => require(['../components/page/sys-user/department/departments.vue'], resolve),
5 | meta: {title: '部门管理'}
6 | },
7 | {
8 | path: '/new-user',
9 | component: resolve => require(['../components/page/sys-user/user/userList.vue'], resolve),
10 | meta: {title: '内部用户'}
11 | },
12 | {
13 | path: '/role-list',
14 | component: resolve => require(['../components/page/sys-user/role/role-list.vue'], resolve),
15 | meta: {title: '角色管理'}
16 | },
17 | {
18 | path: '/role-edit',
19 | component: resolve => require(['../components/page/sys-user/role/role-edit.vue'], resolve),
20 | meta: {title: '角色编辑'}
21 | },
22 | {
23 | path: '/permission-list',
24 | component: resolve => require(['../components/page/sys-user/permission/permission-list.vue'], resolve),
25 | meta: {title: '资源管理'}
26 | },
27 | {
28 | path: '/page-resource-list',
29 | component: resolve => require(['../components/page/sys-user/permission/page-resource-list.vue'], resolve),
30 | meta: {title: '页面元素管理'}
31 | }
32 | ]
33 |
34 |
35 |
--------------------------------------------------------------------------------
/perm-server/sys-common/vo/page_vo.go:
--------------------------------------------------------------------------------
1 | package vo
2 |
3 | // 分页参数
4 | type PageVo struct {
5 | CurrentPage int `json:"currentPage"`
6 | PageSize int `json:"pageSize"`
7 | Start int `json:"start"`
8 | Limit int `json:"limit"`
9 | Total int64 `json:"total"`
10 | }
11 |
12 | func GetPageParam(param *PageVo) (res *PageVo) {
13 | if param == nil {
14 | res.CurrentPage = 0
15 | res.PageSize = 10
16 | res.Limit = 10
17 | res.Start = 0
18 |
19 | return
20 | }
21 |
22 | var (
23 | current int
24 | size int
25 | )
26 | res = new(PageVo)
27 |
28 | if param.CurrentPage < 0 {
29 | res.CurrentPage = 0
30 | current = 0
31 | } else {
32 | res.CurrentPage = param.CurrentPage
33 | current = param.CurrentPage - 1
34 | }
35 |
36 | if param.PageSize < 0 {
37 | res.PageSize = 10
38 | size = 10
39 | } else {
40 | res.PageSize = param.PageSize
41 | size = param.PageSize
42 | }
43 | res.Start = current * size
44 | res.Limit = param.PageSize
45 | res.Total = param.Total
46 |
47 | return
48 | }
49 |
50 | type PageResult struct {
51 | CurrentPage int `json:"currentPage"`
52 | PageSize int `json:"pageSize"`
53 | Total int64 `json:"total"`
54 | Data interface{} `json:"data"`
55 | }
56 |
--------------------------------------------------------------------------------
/perm-server/sys-common/vo/Pagination.go:
--------------------------------------------------------------------------------
1 | package vo
2 |
3 | import (
4 | "errors"
5 |
6 | "github.com/kataras/iris/v12"
7 | )
8 |
9 | // bootstraptable 分页参数
10 | type Pagination struct {
11 | PageNumber int //当前看的是第几页
12 | PageSize int //每页显示多少条数据
13 |
14 | // 用于分页设置的参数
15 | Start int
16 | Limit int
17 |
18 | SortName string //用于指定的排序
19 | SortOrder string // desc或asc
20 |
21 | // 时间范围
22 | StartDate string
23 | EndDate string
24 |
25 | Uid int64 // 公用的特殊参数
26 | }
27 |
28 | func NewPagination(ctx iris.Context) (*Pagination, error) {
29 | pageNumber, err1 := ctx.URLParamInt("pageNumber")
30 | pageSize, err2 := ctx.URLParamInt("pageSize")
31 | sortName := ctx.URLParam("sortName")
32 | sortOrder := ctx.URLParam("sortOrder")
33 | if err1 != nil || err2 != nil {
34 | return nil, errors.New("请求的分页参数解析错误.")
35 | }
36 |
37 | page := Pagination{
38 | PageNumber: pageNumber,
39 | PageSize: pageSize,
40 | SortName: sortName,
41 | SortOrder: sortOrder,
42 | }
43 | page.pageSetting()
44 | return &page, nil
45 | }
46 |
47 | // 设置分页参数
48 | func (p *Pagination) pageSetting() {
49 | if p.PageNumber < 1 {
50 | p.PageNumber = 1
51 | }
52 | if p.PageSize < 1 {
53 | p.PageSize = 1
54 | }
55 |
56 | p.Start = (p.PageNumber - 1) * p.PageSize
57 | p.Limit = p.PageSize
58 | }
59 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module permissionManage
2 |
3 | go 1.14
4 |
5 | require (
6 | github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
7 | github.com/casbin/casbin v1.9.1
8 | github.com/dgrijalva/jwt-go v3.2.0+incompatible
9 | github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4 // indirect
10 | github.com/garyburd/redigo v1.6.0
11 | github.com/go-sql-driver/mysql v1.4.1
12 | github.com/go-xorm/xorm v0.7.9
13 | github.com/gofrs/uuid v3.2.0+incompatible
14 | github.com/golang/protobuf v1.3.2 // indirectgo mod download
15 | github.com/gorilla/schema v1.1.0 // indirect
16 | github.com/iris-contrib/formBinder v5.0.0+incompatible // indirect
17 | github.com/iris-contrib/middleware/cors v0.0.0-20191219204441-78279b78a367
18 | github.com/json-iterator/go v1.1.7 // indirect
19 | github.com/kataras/golog v0.0.10
20 | github.com/kataras/iris v11.1.1+incompatible
21 | github.com/kataras/iris/v12 v12.1.2
22 | github.com/kr/pretty v0.1.0 // indirect
23 | github.com/lib/pq v1.1.1
24 | github.com/mattn/go-isatty v0.0.10 // indirect
25 | github.com/pelletier/go-toml v1.7.0
26 | github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
27 | github.com/ugorji/go v1.1.7 // indirect
28 | golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae // indirect
29 | gopkg.in/yaml.v2 v2.2.8
30 | xorm.io/core v0.7.2-0.20190928055935-90aeac8d08eb
31 | )
32 |
--------------------------------------------------------------------------------
/perm-vue/src/components/page/error-page/403.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
403
4 |
啊哦~ 你没有权限访问该页面哦
5 |
6 |
7 | 返回首页
8 |
9 | 返回上一页
10 |
11 |
12 |
13 |
14 |
23 |
24 |
25 |
57 |
--------------------------------------------------------------------------------
/perm-vue/src/components/page/error-page/404.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
404
4 |
啊哦~ 你所访问的页面不存在
5 |
6 |
7 | 返回首页
8 |
9 | 返回上一页
10 |
11 |
12 |
13 |
14 |
23 |
24 |
25 |
57 |
--------------------------------------------------------------------------------
/perm-vue/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | require('./check-versions')();
3 |
4 | process.env.NODE_ENV = 'production';
5 |
6 | const ora = require('ora');
7 | const rm = require('rimraf');
8 | const path = require('path');
9 | const chalk = require('chalk');
10 | const webpack = require('webpack');
11 | const config = require('../config');
12 | const webpackConfig = require('./webpack.prod.conf');
13 |
14 | const spinner = ora('building for production...');
15 | spinner.start();
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err;
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop();
21 | if (err) throw err;
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/perm-vue/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > #### 软件架构
2 | > 目前支持单web架构,如果部署成前后端分离,可用nginx中间件代理(已添加跨域访问设置)。
3 | > * 采用了golang iris框架;
4 | > * 采用jwt做用户认证、回话控制;
5 | > * 采用Mysql+xorm做持久层;
6 | > * 采用redis做tocken缓存;
7 | > * Vue前端项目;
8 |
9 | ***
10 | #### 项目目录结构
11 | ```
12 | perm
13 | +-- perm-server 后端服务
14 | | +-- doc 说明文档目录
15 | | +-- sql sql文件目录(包含初始化sql)
16 | | +-- main 项目启动入口(包含main.go)
17 | | +-- sys_common 公共服务目录
18 | | +-- caches 缓存工具目录
19 | | +-- conf 配置文件目录
20 | | +-- db 初始化数据库连接
21 | | +-- inits 初始化系统用户,角色目录
22 | | +-- middleware 中间件目录
23 | | +-- models 公共数据库实体模型
24 | | +-- supports 系统常量目录
25 | | +-- utils 后端工具目录
26 | | +-- vo 页面所需公共数据类型目录
27 | | +-- sys_base 业务基础服务(包含:用户,菜单,角色,部门)
28 | | +-- models 数据库对应实体模型文件
29 | | +-- routes 请求路由处理目录
30 | | +-- service 业务逻辑处理目录
31 | | +-- vo 业务所需数据类型目录
32 | +-- perm-vue 前端页面
33 | | +-- build 构建静态文件目录
34 | | +-- config 前端配置文件目录
35 | | +-- src 前端资源文件
36 | | +-- components 页面目录
37 | | +-- router 前端路由目录
38 | | +-- utils 前端工具目录
39 | | +-- static 前端静态文件目录
40 |
41 | ### 服务启动
42 | 1. rizla main.go (go get -u github.com/kataras/rizla 热启动插件)
43 |
44 |
45 | > * 超级管理员登录:
46 | > > 初始账号:root
47 | > > 初始密码: 123456
48 |
49 |
50 |
--------------------------------------------------------------------------------
/perm-vue/src/components/common/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
50 |
--------------------------------------------------------------------------------
/perm-server/sys-common/inits/parse/app.go:
--------------------------------------------------------------------------------
1 | package parse
2 |
3 | import (
4 | "strconv"
5 |
6 | "github.com/kataras/golog"
7 | "github.com/kataras/iris/v12"
8 | )
9 |
10 | var (
11 | // conf strut
12 | C iris.Configuration
13 |
14 | // 解析app.yml中的Other项
15 | O Other
16 | // app.conf配置项key定义
17 | Port string = "Port"
18 | ignoreURLs string = "IgnoreURLs"
19 | jwtTimeout string = "JWTTimeout"
20 | logLevel string = "LogLevel"
21 | secret string = "Secret"
22 | )
23 |
24 | type (
25 | Other struct {
26 | Port string
27 | IgnoreURLs []string
28 | JWTTimeout int64
29 | LogLevel string
30 | Secret string
31 | }
32 | )
33 |
34 | func AppOtherParse() {
35 | golog.Info("@@@ Init app conf")
36 | c := iris.YAML("./perm-server/sys-common/conf/app.yml")
37 |
38 | //appData, err := conf.Asset("conf/app.yml")
39 | //if err != nil {
40 | // golog.Fatalf("Error. %s", err)
41 | //}
42 | //c := iris.DefaultConfiguration()
43 | golog.Println(c)
44 | //if err = yaml.Unmarshal(appData, &c); err != nil {
45 | // golog.Fatalf("Error. %s", err)
46 | //}
47 | //C = c
48 |
49 | // -------------- 解析每个Other配置项 ---------------
50 |
51 | O.Port = strconv.Itoa(c.GetOther()[Port].(int))
52 |
53 | // 解析other的key
54 | iURLs := c.GetOther()[ignoreURLs].([]interface{})
55 | for _, v := range iURLs {
56 | O.IgnoreURLs = append(O.IgnoreURLs, v.(string))
57 | }
58 |
59 | jTimeout := c.GetOther()[jwtTimeout].(int)
60 | O.JWTTimeout = int64(jTimeout)
61 |
62 | O.LogLevel = c.GetOther()[logLevel].(string)
63 |
64 | O.Secret = c.GetOther()[secret].(string)
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/perm-vue/src/components/page/sys-user/department/tree.utils.js:
--------------------------------------------------------------------------------
1 | export function getEditContent(h, data, node) {
2 | let self = this;
3 | return (
4 |
5 | self.close(data, node) }
9 | >
10 | 取消
11 |
12 | self.editMsg(data, node) }
16 | >
17 | 确认
18 |
19 |
20 | )
21 | }
22 |
23 | export function getDefaultContent(h, data, node) {
24 | let self = this
25 | return (
26 |
27 | {
28 | self.is_superuser &&
29 | (
30 | self.update(node, data) }
34 | >
35 | 编辑
36 |
37 |
38 | {
39 | data.level !== 6 &&
40 | self.append(node, data) }
44 | >
45 | 添加
46 |
47 | }
48 |
49 | {
50 | data.level !== 1 &&
51 | self.remove(node, data) }
55 | >
56 | 删除
57 |
58 | }
59 | )
60 | }
61 |
62 | )
63 | }
64 |
--------------------------------------------------------------------------------
/perm-server/sys-common/inits/parse/db.go:
--------------------------------------------------------------------------------
1 | package parse
2 |
3 | import (
4 | "github.com/kataras/golog"
5 |
6 | "gopkg.in/yaml.v2"
7 | "io/ioutil"
8 | )
9 |
10 | var (
11 | DBConfig DB
12 | )
13 |
14 | func DBSettingParse() {
15 | golog.Info("@@@ Init db conf")
16 | data, err := ioutil.ReadFile("./perm-server/sys-common/conf/db.yml")
17 | golog.Infof("%s", data)
18 | if err != nil {
19 | golog.Fatalf("@@@ %s", err)
20 | }
21 | err = yaml.Unmarshal(data, &DBConfig)
22 | if err != nil {
23 | golog.Fatalf("@@@ Unmarshal db config error!! %s", err)
24 | }
25 |
26 | //dbData, err := Asset("conf/db.yml")
27 | //if err != nil {
28 | // golog.Fatalf("Error. %s", err)
29 | //}
30 | if err = yaml.Unmarshal(data, &DBConfig); err != nil {
31 | golog.Fatalf("Error. %s", err)
32 | }
33 |
34 | golog.Info(DBConfig)
35 | }
36 |
37 | type DB struct {
38 | Master DBConfigInfo
39 | Slave DBConfigInfo
40 | }
41 |
42 | type DBConfigInfo struct {
43 | Dialect string `yaml:"dialect"`
44 | User string `yaml:"user"`
45 | Password string `yaml:"password"`
46 | Host string `yaml:"host"`
47 | Port int `yaml:"port"`
48 | Database string `yaml:"database"`
49 | Charset string `yaml:"charset"`
50 | ShowSql bool `yaml:"showSql"`
51 | LogLevel string `yaml:"logLevel"`
52 | MaxIdleConns int `yaml:"maxIdleConns"`
53 | MaxOpenConns int `yaml:"maxOpenConns"`
54 |
55 | //ParseTime bool `yaml:"parseTime"`
56 | //MaxIdleConns int `yaml:"maxIdleConns"`
57 | //MaxOpenConns int `yaml:"maxOpenConns"`
58 | //ConnMaxLifetime int64 `yaml:"connMaxLifetime: 10"`
59 | //Sslmode string `yaml:"sslmode"`
60 | }
61 |
--------------------------------------------------------------------------------
/perm-vue/src/components/page/demo/VueEditor.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 表单
6 | 编辑器
7 |
8 |
9 |
17 |
18 |
19 |
20 |
49 |
--------------------------------------------------------------------------------
/perm-vue/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | // Template version: 1.2.7
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path');
6 |
7 | module.exports = {
8 | dev: {
9 | env: require('./dev.env'),
10 | host: 'localhost',
11 | port: 8099,
12 | // Paths
13 | assetsSubDirectory: 'http://localhost:8099/static',
14 | assetsPublicPath: 'http://localhost:8099/',
15 | proxyTable: {
16 | '/perm': {
17 | // 本机
18 | target: 'http://127.0.0.1:8098',
19 | changeOrigin: true,
20 | pathRewrite: {
21 | '/perm': '/perm'
22 | }
23 | }
24 | },
25 | cssSourceMap: false,
26 | },
27 |
28 | build: {
29 | // Template for index.html
30 | index: path.resolve(__dirname, '../perm-vue-manage/index.html'),
31 |
32 | // Paths
33 | assetsRoot: path.resolve(__dirname, '../perm-vue-manage'),
34 | assetsSubDirectory: 'static',
35 | assetsPublicPath: './',
36 |
37 | /**
38 | * Source Maps
39 | */
40 |
41 | productionSourceMap: false,
42 | // https://webpack.js.org/configuration/devtool/#production
43 | devtool: '#source-map',
44 |
45 | // Gzip off by default as many popular static hosts such as
46 | // Surge or Netlify already gzip all static assets for you.
47 | // Before setting to `true`, make sure to:
48 | // npm install --save-dev compression-webpack-plugin
49 | productionGzip: false,
50 | productionGzipExtensions: ['js', 'css'],
51 |
52 | // Run the build command with an extra argument to
53 | // View the bundle analyzer report after build finishes:
54 | // `npm run build --report`
55 | // Set to `true` or `false` to always turn it on or off
56 | bundleAnalyzerReport: process.env.npm_config_report
57 | }
58 | };
59 |
--------------------------------------------------------------------------------
/perm-server/sys-common/middleware/jwts/config.go:
--------------------------------------------------------------------------------
1 | package jwts
2 |
3 | import "github.com/dgrijalva/jwt-go"
4 |
5 | const (
6 | //DefaultContextKey jwts
7 | DefaultContextKey = "iris-jwt"
8 | )
9 |
10 | // Config is a struct for specifying configuration options for the jwts middleware.
11 | type Config struct {
12 | // The function that will return the Key to validate the JWT.
13 | // It can be either a shared secret or a public key.
14 | // Default value: nil
15 | ValidationKeyGetter jwt.Keyfunc
16 | // The name of the property in the request where the user (&token) information
17 | // from the JWT will be stored.
18 | // Default value: "jwts"
19 | ContextKey string
20 | // The function that will be called when there's an error validating the token
21 | // Default value:
22 | ErrorHandler errorHandler
23 | // A boolean indicating if the credentials are required or not
24 | // Default value: false
25 | CredentialsOptional bool
26 | // A function that extracts the token from the request
27 | // Default: FromAuthHeader (i.e., from Authorization header as bearer token)
28 | Extractor TokenExtractor
29 | // Debug flag turns on debugging output
30 | // Default: false
31 | Debug bool
32 | // When set, all requests with the OPTIONS method will use authentication
33 | // if you enable this option you should register your route with iris.Options(...) also
34 | // Default: false
35 | EnableAuthOnOptions bool
36 | // When set, the middelware verifies that tokens are signed with the specific signing algorithm
37 | // If the signing method is not constant the ValidationKeyGetter callback can be used to implement additional checks
38 | // Important to avoid security issues described here: https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
39 | // Default: nil
40 | SigningMethod jwt.SigningMethod
41 | // When set, the expiration time of token will be check every time
42 | // if the token was expired, expiration error will be returned
43 | // Default: false
44 | Expiration bool
45 | }
46 |
--------------------------------------------------------------------------------
/perm-vue/src/components/page/sys-user/department/tree.scss:
--------------------------------------------------------------------------------
1 |
2 | .ly-tree-container {
3 | margin: 20px 0 20px 20px;
4 | width: 60%;
5 | padding: 20px;
6 |
7 | span {
8 | font-size: 14px;
9 | }
10 |
11 | .el-tree > .el-tree-node > .el-tree-node__content:first-child {
12 | &::before,
13 | &::after {
14 | border: none;
15 | }
16 | }
17 |
18 | .ly-visible {
19 | margin-left: 50px;
20 | visibility: hidden;
21 | }
22 |
23 | .ly-edit__text {
24 | width: 25%;
25 | height: 25px;
26 | border: 1px solid #e6e6e6;
27 | border-radius: 3px;
28 | color: #666;
29 | text-indent: 10px;
30 | }
31 |
32 | .ly-tree__loading {
33 | color: #666;
34 | font-weight: bold;
35 | }
36 |
37 | .ly-tree-node {
38 | flex: 1;
39 | display: flex;
40 | align-items: center;
41 | // justify-content: space-between;
42 | justify-content: flex-start;
43 | font-size: 14px;
44 | padding-right: 8px;
45 | }
46 |
47 | .ly-tree-node > div > span:last-child {
48 | display: inline-block;
49 | width: 110px;
50 | text-align: left;
51 | }
52 |
53 | .ly-tree-node > span:last-child {
54 | display: inline-block;
55 | width: 110px;
56 | text-align: left;
57 | }
58 |
59 | .el-tree-node .el-tree-node__content {
60 | height: 30px;
61 |
62 | &:hover .ly-visible {
63 | visibility: visible;
64 | }
65 |
66 | &::before,
67 | &::after {
68 | content: '';
69 | position: absolute;
70 | right: auto;
71 | }
72 |
73 | &::before {
74 | border-left: 1px solid #e6e6e6;
75 | bottom: 50px;
76 | height: 100%;
77 | top: 0;
78 | width: 1px;
79 | margin-left: -5px;
80 | margin-top: -15px;
81 | }
82 |
83 | &::after {
84 | border-top: 1px solid #e6e6e6;
85 | height: 20px;
86 | top: 14px;
87 | width: 10px;
88 | margin-left: -5px;
89 | }
90 | }
91 |
92 | .el-tree .el-tree-node {
93 | position: relative;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/perm-server/sys-common/inits/sys/user.go:
--------------------------------------------------------------------------------
1 | package sys
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/db"
5 | "permissionManage/perm-server/sys-common/middleware/casbins"
6 | "permissionManage/perm-server/sys-common/utils"
7 | "permissionManage/perm-server/sys-sysbase/models/user"
8 | "time"
9 |
10 | "github.com/kataras/golog"
11 | )
12 |
13 | const (
14 | userNumber = "0"
15 | userAccount = "root"
16 | userPassword = "123456"
17 | userName = "超级管理员"
18 | )
19 |
20 | // 检查超级用户是否存在
21 | func CheckRootExit() bool {
22 | e := db.MasterEngine()
23 | // root is existed?
24 | exit, err := e.Exist(&user.User{UserAccount: userAccount})
25 | if err != nil {
26 | golog.Fatalf("@@@ When check Root User is exited? happened error. %s", err.Error())
27 | }
28 | if exit {
29 | golog.Info("@@@ Root User is existed.")
30 |
31 | // 初始化rbac_model
32 | r := user.User{UserAccount: userAccount}
33 | if exit, _ := e.Get(&r); exit {
34 | casbins.SetRbacModel(r.Id)
35 | CreateSystemRole()
36 | }
37 | }
38 | return exit
39 | }
40 |
41 | func CreateRoot() {
42 | newRoot := user.User{
43 | Id: utils.GetUuid(),
44 | UserNumber: userNumber,
45 | UserAccount: userAccount,
46 | UserPassword: utils.AESEncrypt([]byte(userPassword)),
47 | UserName: userName,
48 | CreateTime: time.Now(),
49 | }
50 |
51 | e := db.MasterEngine()
52 | if _, err := e.Insert(&newRoot); err != nil {
53 | golog.Fatalf("@@@ When create Root User happened error. %s", err.Error())
54 | }
55 | rooId := newRoot.Id
56 | casbins.SetRbacModel(rooId)
57 |
58 | addAllpolicy(rooId)
59 | }
60 |
61 | func addAllpolicy(rooId string) {
62 | // add policy for root
63 | //p := casbins.GetEnforcer().AddPolicy(utils.FmtRolePrefix(newRoot.Id), "/*", "ANY", ".*")
64 | e := casbins.GetEnforcer()
65 | p := e.AddPolicy(rooId, "/*", "ANY", ".*", "", "", "", "", "", "超级用户")
66 | if !p {
67 | golog.Fatalf("初始化用户[%s]权限失败.", userName)
68 | }
69 |
70 | //
71 | for _, v := range Components {
72 | e.AddGroupingPolicy(rooId, v[0])
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/models/user/role_resource.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/db"
5 | "permissionManage/perm-server/sys-common/utils"
6 | "time"
7 | )
8 |
9 | // 角色-资源关联表
10 | type RoleResource struct {
11 | Id string `xorm:"pk varchar(32) notnull unique 'id'"`
12 | CreateTime time.Time `xorm:"'create_time'"`
13 | CreatorDepartmentId string `xorm:"varchar(50) 'creator_department_id'"`
14 | CreatorDepartmentName string `xorm:"varchar(255) 'creator_department_name'"`
15 | CreatorId string `xorm:"varchar(50) 'creator_id'"`
16 | CreatorName string `xorm:"varchar(255) 'creator_name'"`
17 | IsDeleted int64 `xorm:"INT(1) notnull 'is_deleted'"`
18 | UpdateTime time.Time `xorm:"'update_time'"`
19 | UpdatorDepartmentId string `xorm:"varchar(50) 'updator_department_id'"`
20 | UpdatorDepartmentName string `xorm:"varchar(255) 'updator_department_name'"`
21 | UpdatorId string `xorm:"varchar(50) 'updator_id'"`
22 | UpdatorName string `xorm:"varchar(255) 'updator_name'"`
23 | Version int64 `xorm:"INT(11) 'version'"`
24 |
25 | RoleId string `xorm:"varchar(50) notnull 'role_id'"`
26 | ResourceId string `xorm:"varchar(50) notnull 'resource_id'"`
27 | }
28 |
29 | func (RoleResource) TableName() string {
30 | return "cd_sys_user_role_resource"
31 | }
32 |
33 | //
34 | func CreateRelationRoleResource(roleResources ...*RoleResource) (int64, error) {
35 | e := db.MasterEngine()
36 | var roleResourceEntitys []RoleResource
37 | for _, r := range roleResources {
38 | // 生成uuid
39 | r.Id = utils.GetUuid()
40 | r.CreateTime = time.Now()
41 | r.Version = 0
42 | r.IsDeleted = 0
43 |
44 | roleResourceEntitys = append(roleResourceEntitys, *r)
45 | }
46 | return e.Insert(roleResourceEntitys)
47 | }
48 |
49 | //========================= 物理删除 ============================
50 | func RemoveRoleResource(roleId string) (effect int64, err error) {
51 | e := db.MasterEngine()
52 |
53 | rr := new(RoleResource)
54 | effect, err = e.Where("role_id = ?", roleId).Delete(rr)
55 |
56 | return
57 | }
58 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/vo/uservo/role_resource_vo.go:
--------------------------------------------------------------------------------
1 | package uservo
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/models/baseModel"
5 | "permissionManage/perm-server/sys-sysbase/models/user"
6 | "strings"
7 | "time"
8 | )
9 |
10 | // 前端需要的数据结构
11 | type RoleResourceVO struct {
12 | Id string `json:"id"`
13 | CreateTime time.Time `json:"createTime"`
14 | CreatorDepartmentId string `json:"creatorDepartmentId"`
15 | CreatorDepartmentName string `json:"creatorDepartmentName"`
16 | CreatorId string `json:"creatorId"`
17 | CreatorName string `json:"creatorName"`
18 | IsDeleted int64 `json:"isDeleted"`
19 | UpdateTime time.Time `json:"updateTime"`
20 | UpdatorDepartmentId string `json:"updatorDepartmentId"`
21 | UpdatorDepartmentName string `json:"updatorDepartmentName"`
22 | UpdatorId string `json:"updatorId"`
23 | UpdatorName string `json:"updatorName"`
24 | Version int64 `json:"version"`
25 |
26 | RoleId string `json:"roleId"`
27 | ResourceId string `json:"resourceId"`
28 | }
29 |
30 | // 请求参数
31 | type RoleResourceParamVo struct {
32 | *baseModel.CurrentUser
33 |
34 | RoleId string `json:"roleId"`
35 | ResourceIds string `json:"resourceIds"`
36 | }
37 |
38 | func RoleResourceParamVoToRoleResource(paramVO *RoleResourceParamVo) (result []*user.RoleResource) {
39 | currentUser := paramVO.CurrentUser
40 | resourceIdArry := strings.Split(paramVO.ResourceIds, ",")
41 | for _, resourceId := range resourceIdArry {
42 | tmpRes := new(user.RoleResource)
43 | tmpRes.CreatorId = currentUser.UserAccount
44 | tmpRes.CreatorName = currentUser.UserName
45 | tmpRes.CreatorDepartmentId = currentUser.DepartmentId
46 | tmpRes.CreatorDepartmentName = currentUser.DepartmentName
47 | tmpRes.UpdatorId = currentUser.UserAccount
48 | tmpRes.UpdatorName = currentUser.UserName
49 | tmpRes.UpdatorDepartmentId = currentUser.DepartmentId
50 | tmpRes.UpdatorDepartmentName = currentUser.DepartmentName
51 | tmpRes.UpdateTime = time.Now()
52 |
53 | tmpRes.RoleId = paramVO.RoleId
54 | tmpRes.ResourceId = resourceId
55 |
56 | result = append(result, tmpRes)
57 | }
58 |
59 | return
60 | }
61 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/vo/uservo/user_role_vo.go:
--------------------------------------------------------------------------------
1 | package uservo
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/models/baseModel"
5 | "permissionManage/perm-server/sys-sysbase/models/user"
6 | "time"
7 | )
8 |
9 | // 前端需要的数据结构
10 | type UserRoleVO struct {
11 | Id string `json:"id"`
12 | CreateTime time.Time `json:"createTime"`
13 | CreatorDepartmentId string `json:"creatorDepartmentId"`
14 | CreatorDepartmentName string `json:"creatorDepartmentName"`
15 | CreatorId string `json:"creatorId"`
16 | CreatorName string `json:"creatorName"`
17 | IsDeleted int64 `json:"isDeleted"`
18 | UpdateTime time.Time `json:"updateTime"`
19 | UpdatorDepartmentId string `json:"updatorDepartmentId"`
20 | UpdatorDepartmentName string `json:"updatorDepartmentName"`
21 | UpdatorId string `json:"updatorId"`
22 | UpdatorName string `json:"updatorName"`
23 | Version int64 `json:"version"`
24 |
25 | RoleId string `json:"roleId"`
26 | ResourceId string `json:"resourceId"`
27 | }
28 |
29 | // 请求参数
30 | type UserRoleParamVo struct {
31 | *baseModel.CurrentUser
32 |
33 | CheckType string `json:"checkType"`
34 | UserId string `json:"userId"`
35 | RoleIds []string `json:"roleIds"`
36 | }
37 |
38 | func UserRoleParamVoToUserRole(paramVO *UserRoleParamVo) (result []*user.UserRole) {
39 | currentUser := paramVO.CurrentUser
40 | //roleIdArry := strings.Split(paramVO.RoleIds, ",")
41 | roleIdArry := paramVO.RoleIds
42 | for _, roleId := range roleIdArry {
43 | tmpRes := new(user.UserRole)
44 | tmpRes.CreatorId = currentUser.UserAccount
45 | tmpRes.CreatorName = currentUser.UserName
46 | tmpRes.CreatorDepartmentId = currentUser.DepartmentId
47 | tmpRes.CreatorDepartmentName = currentUser.DepartmentName
48 | tmpRes.UpdatorId = currentUser.UserAccount
49 | tmpRes.UpdatorName = currentUser.UserName
50 | tmpRes.UpdatorDepartmentId = currentUser.DepartmentId
51 | tmpRes.UpdatorDepartmentName = currentUser.DepartmentName
52 | tmpRes.UpdateTime = time.Now()
53 |
54 | tmpRes.UserId = paramVO.UserId
55 | tmpRes.RoleId = roleId
56 |
57 | result = append(result, tmpRes)
58 | }
59 |
60 | return
61 | }
62 |
--------------------------------------------------------------------------------
/perm-server/sys-common/supports/simple_response.go:
--------------------------------------------------------------------------------
1 | package supports
2 |
3 | import (
4 | "github.com/kataras/iris/v12"
5 | )
6 |
7 | const (
8 | // key定义
9 | CODE string = "code"
10 | MSG string = "msg"
11 | DATA string = "data"
12 |
13 | // msg define
14 | Success = "恭喜, 成功"
15 | OptionSuccess string = "恭喜, 操作成功"
16 | OptionFailur string = "抱歉, 操作失败"
17 | ParseParamsFailur string = "解析参数失败"
18 |
19 | RegisteSuccess string = "恭喜, 注册用户成功"
20 | RegisteFailur string = "注册失败"
21 | LoginSuccess string = "恭喜, 登录成功"
22 | LogoutSuccess string = "恭喜, 退出成功"
23 | LoginFailur string = "登录失败"
24 | DeleteUsersSuccess string = "删除用户成功"
25 | DeleteUsersFailur string = "删除用户错误"
26 |
27 | DeleteRolesSuccess string = "删除角色成功"
28 | DeleteRolesFailur string = "删除角色错误"
29 |
30 | UsernameFailur string = "用户名错误"
31 | PasswordFailur string = "密码错误"
32 | TokenCreateFailur string = "生成token错误"
33 | TokenExactFailur string = "token不存在或header设置不正确"
34 | TokenExpire string = "回话已过期"
35 | TokenParseFailur string = "token解析错误"
36 | TokenParseFailurAndEmpty string = "解析错误,token为空"
37 | TokenParseFailurAndInvalid string = "解析错误,token无效"
38 | NotFound string = "您请求的url不存在"
39 | PermissionsLess string = "权限不足"
40 |
41 | RoleCreateFailur string = "创建角色失败"
42 | RoleCreateSuccess string = "创建角色成功"
43 |
44 | // value define
45 |
46 | )
47 |
48 | // 200 define
49 | func Ok_(ctx iris.Context, msg string) {
50 | Ok(ctx, msg, nil)
51 | }
52 |
53 | func Ok(ctx iris.Context, msg string, data interface{}) {
54 | ctx.StatusCode(iris.StatusOK)
55 | ctx.JSON(iris.Map{
56 | CODE: iris.StatusOK,
57 | MSG: msg,
58 | DATA: data,
59 | })
60 | }
61 |
62 | // 401 error define
63 | func Unauthorized(ctx iris.Context, msg string, data interface{}) {
64 | unauthorized := iris.StatusUnauthorized
65 |
66 | ctx.StatusCode(unauthorized)
67 | ctx.JSON(iris.Map{
68 | CODE: unauthorized,
69 | MSG: msg,
70 | DATA: data,
71 | })
72 | }
73 |
74 | // common error define
75 | func Error(ctx iris.Context, status int, msg string, data interface{}) {
76 | ctx.StatusCode(status)
77 | ctx.JSON(iris.Map{
78 | CODE: status,
79 | MSG: msg,
80 | DATA: data,
81 | })
82 | }
83 |
--------------------------------------------------------------------------------
/perm-server/sys-common/utils/encrypt.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "crypto/aes"
5 | "crypto/md5"
6 | "encoding/hex"
7 | "errors"
8 | )
9 |
10 | // Md5 returns the MD5 checksum string of the data.
11 | func Md5(b []byte) string {
12 | checksum := md5.Sum(b)
13 | return hex.EncodeToString(checksum[:])
14 | }
15 |
16 | // AESEncrypt encrypts a piece of data.
17 | // The cipherkey argument should be the AES key,
18 | // either 16, 24, or 32 bytes to select
19 | // AES-128, AES-192, or AES-256.
20 | func AESEncrypt2(cipherkey, src []byte) []byte {
21 | block, err := aes.NewCipher(cipherkey)
22 | if err != nil {
23 | panic(err)
24 | }
25 | bs := block.BlockSize()
26 | src = padData(src, bs)
27 | r := make([]byte, len(src))
28 | dst := r
29 | for len(src) > 0 {
30 | block.Encrypt(dst, src)
31 | src = src[bs:]
32 | dst = dst[bs:]
33 | }
34 | dst = make([]byte, hex.EncodedLen(len(r)))
35 | hex.Encode(dst, r)
36 | return dst
37 | }
38 |
39 | // AESDecrypt decrypts a piece of data.
40 | // The cipherkey argument should be the AES key,
41 | // either 16, 24, or 32 bytes to select
42 | // AES-128, AES-192, or AES-256.
43 | func AESDecrypt2(cipherkey, ciphertext []byte) ([]byte, error) {
44 | block, err := aes.NewCipher(cipherkey)
45 | if err != nil {
46 | return nil, err
47 | }
48 | src := make([]byte, hex.DecodedLen(len(ciphertext)))
49 | _, err = hex.Decode(src, ciphertext)
50 | if err != nil {
51 | return nil, err
52 | }
53 | bs := block.BlockSize()
54 | r := make([]byte, len(src))
55 | dst := r
56 | for len(src) > 0 {
57 | block.Decrypt(dst, src)
58 | src = src[bs:]
59 | dst = dst[bs:]
60 | }
61 | return removePad(r)
62 | }
63 |
64 | func padData(d []byte, bs int) []byte {
65 | padedSize := ((len(d) / bs) + 1) * bs
66 | pad := padedSize - len(d)
67 | for i := len(d); i < padedSize; i++ {
68 | d = append(d, byte(pad))
69 | }
70 | return d
71 | }
72 |
73 | func removePad(r []byte) ([]byte, error) {
74 | l := len(r)
75 | if l == 0 {
76 | return []byte{}, errors.New("input []byte is empty")
77 | }
78 | last := int(r[l-1])
79 | pad := r[l-last : l]
80 | isPad := true
81 | for _, v := range pad {
82 | if int(v) != last {
83 | isPad = false
84 | break
85 | }
86 | }
87 | if !isPad {
88 | return r, errors.New("remove pad error")
89 | }
90 | return r[:l-last], nil
91 | }
92 |
--------------------------------------------------------------------------------
/perm-server/sys-common/utils/aes.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "bytes"
5 | "crypto/aes"
6 | "crypto/cipher"
7 | "encoding/base64"
8 | "fmt"
9 | )
10 |
11 | /**
12 | AES加密解密
13 | 使用CBC模式+PKCS7 填充方式实现AES的加密和解密
14 | */
15 | const key = "ARRSWdczx13213EDDSWQ!!@W"
16 |
17 | // 校验密码
18 | func CheckPWD(password, enPassword string) bool {
19 | de := AESDecrypt(enPassword)
20 | if (password == de) {
21 | return true
22 | }
23 | return false
24 | }
25 |
26 | // -----------------------------------------------------------
27 | // ----------------------- 解密 ------------------------------
28 | // -----------------------------------------------------------
29 | // 先base64转码,再解密
30 | func AESDecrypt(baseStr string) string {
31 | crypted, err := base64.StdEncoding.DecodeString(baseStr)
32 | if (err != nil) {
33 | fmt.Println("base64 encoding 错误")
34 | }
35 |
36 | block, _ := aes.NewCipher([]byte(key))
37 | blockSize := block.BlockSize()
38 | blockMode := cipher.NewCBCDecrypter(block, []byte(key)[:blockSize])
39 | originPWD := make([]byte, len(crypted))
40 | blockMode.CryptBlocks(originPWD, crypted)
41 | originPWD = pkcs7_unPadding(originPWD)
42 | return string(originPWD)
43 | }
44 |
45 | // 补码
46 | func pkcs7_unPadding(origData []byte) []byte {
47 | length := len(origData)
48 | unpadding := int(origData[length-1])
49 | return origData[:length-unpadding]
50 | }
51 |
52 | // -----------------------------------------------------------
53 | // ----------------------- 加密 ------------------------------
54 | // -----------------------------------------------------------
55 | // 加密后再base64编码成string
56 | func AESEncrypt(originPWD []byte) string {
57 | //获取block块
58 | block, _ := aes.NewCipher([]byte(key))
59 | //补码
60 | originPWD = pkcs7_padding(originPWD, block.BlockSize())
61 | //加密模式,
62 | blockMode := cipher.NewCBCEncrypter(block, []byte(key)[:block.BlockSize()])
63 | //创建明文长度的数组
64 | crypted := make([]byte, len(originPWD))
65 | //加密明文
66 | blockMode.CryptBlocks(crypted, originPWD)
67 |
68 | return base64.StdEncoding.EncodeToString(crypted)
69 | }
70 |
71 | // 补码
72 | func pkcs7_padding(origData []byte, blockSize int) []byte {
73 | //计算需要补几位数
74 | padding := blockSize - len(origData)%blockSize
75 | //在切片后面追加char数量的byte(char)
76 | padtext := bytes.Repeat([]byte{byte(padding)}, padding)
77 | return append(origData, padtext...)
78 | }
79 |
--------------------------------------------------------------------------------
/perm-vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-manage-system",
3 | "version": "3.2.0",
4 | "description": "基于Vue.js 2.x系列 + element-ui 内容管理系统解决方案",
5 | "author": "lin-xin <2981207131@qq.com>",
6 | "private": true,
7 | "scripts": {
8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
9 | "build": "node build/build.js"
10 | },
11 | "dependencies": {
12 | "jquery": "^3.1.1",
13 | "axios": "^0.15.3",
14 | "babel-polyfill": "^6.23.0",
15 | "element-ui": "^2.4.5",
16 | "js-md5": "^0.7.3",
17 | "mavon-editor": "^2.5.4",
18 | "vue": "^2.5.16",
19 | "vue-cropperjs": "^2.2.0",
20 | "vue-quill-editor": "3.0.6",
21 | "vue-router": "^3.0.1",
22 | "vue-schart": "^1.0.0",
23 | "vuedraggable": "^2.16.0"
24 | },
25 | "devDependencies": {
26 | "autoprefixer": "^7.1.2",
27 | "babel-core": "^6.22.1",
28 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
29 | "babel-loader": "^7.1.1",
30 | "babel-plugin-syntax-jsx": "^6.18.0",
31 | "babel-plugin-transform-runtime": "^6.22.0",
32 | "babel-plugin-transform-vue-jsx": "^3.5.0",
33 | "babel-preset-env": "^1.3.2",
34 | "babel-preset-stage-2": "^6.22.0",
35 | "chalk": "^2.0.1",
36 | "copy-webpack-plugin": "^4.0.1",
37 | "css-loader": "^0.28.0",
38 | "extract-text-webpack-plugin": "^3.0.0",
39 | "file-loader": "^1.1.4",
40 | "friendly-errors-webpack-plugin": "^1.6.1",
41 | "html-webpack-plugin": "^2.30.1",
42 | "node-notifier": "^5.1.2",
43 | "optimize-css-assets-webpack-plugin": "^3.2.0",
44 | "ora": "^1.2.0",
45 | "portfinder": "^1.0.13",
46 | "postcss-import": "^11.0.0",
47 | "postcss-loader": "^2.0.8",
48 | "rimraf": "^2.6.0",
49 | "semver": "^5.3.0",
50 | "shelljs": "^0.7.6",
51 | "uglifyjs-webpack-plugin": "^1.1.1",
52 | "url-loader": "^0.5.8",
53 | "vue-loader": "^13.3.0",
54 | "vue-style-loader": "^3.0.1",
55 | "vue-template-compiler": "^2.5.2",
56 | "webpack": "^3.6.0",
57 | "webpack-bundle-analyzer": "^2.9.0",
58 | "webpack-dev-server": "^2.9.1",
59 | "node-sass": "^4.9.2",
60 | "sass-loader": "^7.0.3",
61 | "webpack-merge": "^4.1.0"
62 | },
63 | "engines": {
64 | "node": ">= 4.0.0",
65 | "npm": ">= 3.0.0"
66 | },
67 | "browserslist": [
68 | "> 1%",
69 | "last 5 versions",
70 | "not ie <= 8"
71 | ]
72 | }
73 |
--------------------------------------------------------------------------------
/perm-vue/src/components/page/demo/Markdown.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 表单
6 | markdown编辑器
7 |
8 |
9 |
10 |
11 | mavonEditor:基于Vue的markdown编辑器。
12 | 访问地址:
mavonEditor
13 |
14 |
15 |
提交
16 |
17 |
18 |
19 |
20 |
63 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/models/user/user_role.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/db"
5 | "permissionManage/perm-server/sys-common/utils"
6 | "time"
7 | )
8 |
9 | // 用户-角色关联表
10 | type UserRole struct {
11 | Id string `xorm:"pk varchar(32) notnull unique" json:"id" form:"id"`
12 | CreateTime time.Time `json:"create_time" form:"create_time"`
13 | CreatorDepartmentId string `xorm:"varchar(50)" json:"creator_department_id" form:"creator_department_id"`
14 | CreatorDepartmentName string `xorm:"varchar(255)" json:"creator_department_name" form:"creator_department_name"`
15 | CreatorId string `xorm:"varchar(50)"json:"creator_id" form:"creator_id"`
16 | CreatorName string `xorm:"varchar(255)"json:"creator_name" form:"creator_name"`
17 | IsDeleted int64 `xorm:"INT(1) notnull" json:"isDeleted" form:"isDeleted"`
18 | UpdateTime time.Time `json:"update_time" form:"update_time"`
19 | UpdatorDepartmentId string `xorm:"varchar(50)" json:"updator_department_id" form:"updator_department_id"`
20 | UpdatorDepartmentName string `xorm:"varchar(255)" json:"updator_department_name" form:"updator_department_name"`
21 | UpdatorId string `xorm:"varchar(50)"json:"updator_id" form:"updator_id"`
22 | UpdatorName string `xorm:"varchar(255)"json:"updator_name" form:"updator_name"`
23 | Version int64 `xorm:"INT(11)" json:"version" form:"version"`
24 |
25 | UserId string `xorm:"varchar(50) notnull" json:"user_id"`
26 | RoleId string `xorm:"varchar(50) notnull" json:"role_id"`
27 | }
28 |
29 | func (UserRole) TableName() string {
30 | return "cd_sys_user_user_role"
31 | }
32 |
33 | //========================= 新增用户角色 ============================
34 | func CreateRelationUserRole(userRoles ...*UserRole) (int64, error) {
35 | e := db.MasterEngine()
36 | var userRolEntitys []UserRole
37 | for _, ur := range userRoles {
38 | // 生成uuid
39 | ur.Id = utils.GetUuid()
40 | ur.CreateTime = time.Now()
41 | ur.Version = 0
42 | ur.IsDeleted = 0
43 |
44 | userRolEntitys = append(userRolEntitys, *ur)
45 | }
46 | return e.Insert(userRolEntitys)
47 | }
48 |
49 | //========================= 物理删除 ============================
50 | func RemoveUserRole(userId string, roleIds []string) (effect int64, err error) {
51 | e := db.MasterEngine()
52 |
53 | ur := new(UserRole)
54 | effect, err = e.Where("user_id = ?", userId).In("role_id", roleIds).Delete(ur)
55 | return
56 | }
57 |
--------------------------------------------------------------------------------
/perm-vue/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import App from './App';
3 | import router from './router';
4 | import axios from 'axios';
5 | import ElementUI from 'element-ui';
6 | import './assets/reset.css';
7 | import 'element-ui/lib/theme-chalk/index.css'; // 默认主题
8 | // import '../static/css/theme-green/index.css'; // 浅绿色主题
9 | import 'jquery';
10 | import '../static/css/icon.css';
11 | import "babel-polyfill";
12 | import md5 from 'js-md5';
13 | import Common from './assets/util';
14 | import common from './assets/common.js';
15 |
16 | import {fmtToken} from './utils/utils'
17 |
18 | Vue.use(ElementUI, {size: 'small'});
19 | Vue.prototype.$axios = axios;
20 | Vue.config.productionTip = false;
21 | Vue.prototype.$md5 = md5;
22 | Vue.prototype.Common = Common;
23 | Vue.prototype.$Common = common;
24 |
25 | axios.interceptors.request.use(request => {
26 | request.headers.Authorization = fmtToken();
27 | let type = axios.defaults.headers['urlencoded'];
28 | let requestData = [];
29 | //上传
30 | if (type > -1) {
31 | request.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
32 | let _data = '';
33 | if (request.data) {
34 | for (let key in request.data) {
35 | requestData.push(request.data[key]);
36 | _data += `${key}=${request.data[key]}`;
37 | Object.keys(request.data).pop() !== key && (_data += '&');
38 | }
39 | request.data = _data;
40 | }
41 | return request;
42 | } else {
43 | request.headers['Content-Type'] = 'application/json;charset=UTF-8';
44 | if (request.method != 'get') {
45 | }
46 | return request;
47 | }
48 | });
49 |
50 | //使用钩子函数对路由进行权限跳转
51 | router.beforeEach((to, from, next) => {
52 | const role = localStorage.getItem('ms_username');
53 | if (!role && to.path !== '/login') {
54 | next('/login');
55 | } else if (to.meta.permission) {
56 | // 如果是管理员权限则可进入,这里只是简单的模拟管理员权限而已
57 | role === 'admin' ? next() : next('/403');
58 | } else {
59 | // 简单的判断IE10及以下不进入富文本编辑器,该组件不兼容
60 | if (navigator.userAgent.indexOf('MSIE') > -1 && to.path === '/editor') {
61 | Vue.prototype.$alert('vue-quill-editor组件不兼容IE10及以下浏览器,请使用更高版本的浏览器查看', '浏览器不兼容通知', {
62 | confirmButtonText: '确定'
63 | });
64 | } else {
65 | next();
66 | }
67 | }
68 | });
69 |
70 | new Vue({
71 | router,
72 | render: h => h(App)
73 | }).$mount('#app');
--------------------------------------------------------------------------------
/perm-server/sys-common/db/db.go:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import (
4 | "fmt"
5 | "permissionManage/perm-server/sys-common/inits/parse"
6 | "permissionManage/perm-server/sys-common/utils"
7 | "sync"
8 |
9 | "github.com/kataras/golog"
10 | "xorm.io/core"
11 |
12 | _ "github.com/go-sql-driver/mysql"
13 | "github.com/go-xorm/xorm"
14 | )
15 |
16 | var (
17 | masterEngine *xorm.Engine
18 | slaveEngine *xorm.Engine
19 | lock sync.Mutex
20 | )
21 |
22 | // 主库,单例
23 | func MasterEngine() *xorm.Engine {
24 | if masterEngine != nil {
25 | return masterEngine
26 | }
27 |
28 | lock.Lock()
29 | defer lock.Unlock()
30 |
31 | if masterEngine != nil {
32 | return masterEngine
33 | }
34 |
35 | master := parse.DBConfig.Master
36 | engine, err := xorm.NewEngine(master.Dialect, GetConnURL(&master))
37 | if err != nil {
38 | golog.Fatalf("@@@ Instance Master DB error!! %s", err)
39 | return nil
40 | }
41 | settings(engine, &master)
42 | engine.SetMapper(core.GonicMapper{})
43 |
44 | masterEngine = engine
45 | return masterEngine
46 | }
47 |
48 | // 从库,单例
49 | func SlaveEngine() *xorm.Engine {
50 | if slaveEngine != nil {
51 | return slaveEngine
52 | }
53 |
54 | lock.Lock()
55 | defer lock.Unlock()
56 |
57 | if slaveEngine != nil {
58 | return slaveEngine
59 | }
60 |
61 | slave := parse.DBConfig.Slave
62 | engine, err := xorm.NewEngine(slave.Dialect, GetConnURL(&slave))
63 | if err != nil {
64 | golog.Fatalf("@@@ Instance Slave DB error!! %s", err)
65 | return nil
66 | }
67 | settings(engine, &slave)
68 |
69 | slaveEngine = engine
70 | return engine
71 | }
72 |
73 | //
74 | func settings(engine *xorm.Engine, info *parse.DBConfigInfo) {
75 | engine.ShowSQL(info.ShowSql)
76 | engine.SetTZLocation(utils.SysTimeLocation)
77 | if info.MaxIdleConns > 0 {
78 | engine.SetMaxIdleConns(info.MaxIdleConns)
79 | }
80 | if info.MaxOpenConns > 0 {
81 | engine.SetMaxOpenConns(info.MaxOpenConns)
82 | }
83 |
84 | // 性能优化的时候才考虑,加上本机的SQL缓存
85 | //cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000)
86 | //engine.SetDefaultCacher(cacher)
87 | }
88 |
89 | // 获取数据库连接的url
90 | // true:master主库
91 | func GetConnURL(info *parse.DBConfigInfo) (url string) {
92 | //db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
93 | url = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s",
94 | info.User,
95 | info.Password,
96 | info.Host,
97 | info.Port,
98 | info.Database,
99 | info.Charset)
100 | //golog.Infof("@@@ DB conn==>> %s", url)
101 | return
102 | }
103 |
--------------------------------------------------------------------------------
/perm-vue/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 | const webpack = require('webpack')
7 |
8 | function resolve (dir) {
9 | return path.join(__dirname, '..', dir)
10 | }
11 |
12 |
13 |
14 | module.exports = {
15 | context: path.resolve(__dirname, '../'),
16 | entry: {
17 | app: './src/main.js'
18 | },
19 | output: {
20 | path: config.build.assetsRoot,
21 | filename: '[name].js',
22 | publicPath: process.env.NODE_ENV === 'production'
23 | ? config.build.assetsPublicPath
24 | : config.dev.assetsPublicPath
25 | },
26 | resolve: {
27 | extensions: ['*','.js', '.vue', '.json','.scss'],
28 | alias: {
29 | 'vue$': 'vue/dist/vue.esm.js',
30 | '@': resolve('src'),
31 | 'static': path.resolve(__dirname, '../static'),
32 | }
33 | },
34 | plugins: [
35 | new webpack.ProvidePlugin({
36 | $: "jquery",
37 | jQuery: "jquery",
38 | jquery: "jquery",
39 | "window.jQuery": "jquery"
40 | })
41 | ],
42 | module: {
43 | rules: [
44 | {
45 | test: /\.vue$/,
46 | loader: 'vue-loader',
47 | options: vueLoaderConfig
48 | },
49 | {
50 | test: /\.js$/,
51 | loader: 'babel-loader',
52 | include: [resolve('src'), resolve('test')]
53 | },
54 | {
55 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
56 | loader: 'url-loader',
57 | options: {
58 | limit: 10000,
59 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
60 | }
61 | },
62 | {
63 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
64 | loader: 'url-loader',
65 | options: {
66 | limit: 10000,
67 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
68 | }
69 | },
70 | {
71 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
72 | loader: 'url-loader',
73 | options: {
74 | limit: 10000,
75 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
76 | }
77 | }
78 | ]
79 | },
80 | node: {
81 | // prevent webpack from injecting useless setImmediate polyfill because Vue
82 | // source contains it (although only uses it if it's native).
83 | setImmediate: false,
84 | // prevent webpack from injecting mocks to Node native modules
85 | // that does not make sense for the client
86 | dgram: 'empty',
87 | fs: 'empty',
88 | net: 'empty',
89 | tls: 'empty',
90 | child_process: 'empty'
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/routes/hub.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/middleware"
5 | "permissionManage/perm-server/sys-common/supports"
6 |
7 | conf "permissionManage/perm-server/sys-common/inits/parse"
8 |
9 | "github.com/iris-contrib/middleware/cors"
10 | "github.com/kataras/iris/v12"
11 | "github.com/kataras/iris/v12/context"
12 | "github.com/kataras/iris/v12/middleware/logger"
13 | rcover "github.com/kataras/iris/v12/middleware/recover"
14 | "permissionManage/perm-server/sys-sysbase/routes/user"
15 | )
16 |
17 | // 所有的路由
18 | func Hub(app *iris.Application) {
19 | preSettring(app)
20 | var main = corsSetting(app)
21 |
22 | // 用户模块路由
23 | user.UserHub(main) // 用户API模块
24 | user.ResoureHub(main) // 菜单资源
25 | user.RoleHub(main) // 角色
26 | user.DepartmentHub(main) // 部门
27 | }
28 |
29 | func corsSetting(app *iris.Application) (main iris.Party) {
30 | var (
31 | crs context.Handler
32 | )
33 |
34 | crs = cors.New(cors.Options{
35 | AllowedOrigins: []string{"*"}, //允许通过的主机名称
36 | AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
37 | AllowedHeaders: []string{"*"},
38 | Debug: true,
39 | //AllowCredentials: true,
40 | })
41 |
42 | /* 定义路由 */
43 | main = app.Party("/perm", crs).AllowMethods(iris.MethodOptions)
44 | main.Use(middleware.ServeHTTP)
45 | //main := app.Party("/")
46 | //main.Use(middleware.ServeHTTP)
47 |
48 | return main
49 | }
50 |
51 | func preSettring(app *iris.Application) {
52 | app.Logger().SetLevel(conf.O.LogLevel)
53 |
54 | customLogger := logger.New(logger.Config{
55 | //状态显示状态代码
56 | Status: true,
57 | // IP显示请求的远程地址
58 | IP: true,
59 | //方法显示http方法
60 | Method: true,
61 | // Path显示请求路径
62 | Path: true,
63 | // Query将url查询附加到Path。
64 | Query: true,
65 | //Columns:true,
66 | // 如果不为空然后它的内容来自`ctx.Values(),Get("logger_message")
67 | //将添加到日志中。
68 | MessageContextKeys: []string{"logger_message"},
69 | //如果不为空然后它的内容来自`ctx.GetHeader(“User-Agent”)
70 | MessageHeaderKeys: []string{"User-Agent"},
71 | })
72 | app.Use(
73 | rcover.New(),
74 | customLogger,
75 | //middleware.ServeHTTP
76 | )
77 |
78 | // ---------------------- 定义错误处理 ------------------------
79 | app.OnErrorCode(iris.StatusNotFound, customLogger, func(ctx iris.Context) {
80 | supports.Error(ctx, iris.StatusNotFound, supports.NotFound, nil)
81 | })
82 | //app.OnErrorCode(iris.StatusForbidden, customLogger, func(ctx iris.Context) {
83 | // ctx.JSON(utils.Error(iris.StatusForbidden, "权限不足", nil))
84 | //})
85 | //捕获所有http错误:
86 | //app.OnAnyErrorCode(customLogger, func(ctx iris.Context) {
87 | // //这应该被添加到日志中,因为`logger.Config#MessageContextKey`
88 | // ctx.Values().Set("logger_message", "a dynamic message passed to the logs")
89 | // ctx.JSON(utils.Error(500, "服务器内部错误", nil))
90 | //})
91 | }
92 |
--------------------------------------------------------------------------------
/perm-vue/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const webpack = require('webpack')
4 | const config = require('../config')
5 | const merge = require('webpack-merge')
6 | const baseWebpackConfig = require('./webpack.base.conf')
7 | const HtmlWebpackPlugin = require('html-webpack-plugin')
8 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
9 | const portfinder = require('portfinder')
10 |
11 | const HOST = process.env.HOST
12 | const PORT = process.env.PORT && Number(process.env.PORT)
13 |
14 | const devWebpackConfig = merge(baseWebpackConfig, {
15 | module: {
16 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
17 | },
18 | // cheap-module-eval-source-map is faster for development
19 | devtool: config.dev.devtool,
20 |
21 | // these devServer options should be customized in /config/index.js
22 | devServer: {
23 | clientLogLevel: 'warning',
24 | historyApiFallback: true,
25 | hot: true,
26 | compress: true,
27 | host: HOST || config.dev.host,
28 | port: PORT || config.dev.port,
29 | open: config.dev.autoOpenBrowser,
30 | overlay: config.dev.errorOverlay
31 | ? { warnings: false, errors: true }
32 | : false,
33 | publicPath: config.dev.assetsPublicPath,
34 | proxy: config.dev.proxyTable,
35 | quiet: true, // necessary for FriendlyErrorsPlugin
36 | watchOptions: {
37 | poll: config.dev.poll,
38 | }
39 | },
40 | plugins: [
41 | new webpack.DefinePlugin({
42 | 'process.env': require('../config/dev.env')
43 | }),
44 | new webpack.HotModuleReplacementPlugin(),
45 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
46 | new webpack.NoEmitOnErrorsPlugin(),
47 | // https://github.com/ampedandwired/html-webpack-plugin
48 | new HtmlWebpackPlugin({
49 | filename: 'index.html',
50 | template: 'index.html',
51 | inject: true
52 | }),
53 | ]
54 | })
55 |
56 | module.exports = new Promise((resolve, reject) => {
57 | portfinder.basePort = process.env.PORT || config.dev.port
58 | portfinder.getPort((err, port) => {
59 | if (err) {
60 | reject(err)
61 | } else {
62 | // publish the new Port, necessary for e2e tests
63 | process.env.PORT = port
64 | // add port to devServer config
65 | devWebpackConfig.devServer.port = port
66 |
67 | // Add FriendlyErrorsPlugin
68 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
69 | compilationSuccessInfo: {
70 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
71 | },
72 | onErrors: config.dev.notifyOnErrors
73 | ? utils.createNotifierCallback()
74 | : undefined
75 | }))
76 |
77 | resolve(devWebpackConfig)
78 | }
79 | })
80 | })
81 |
--------------------------------------------------------------------------------
/perm-vue/build/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const config = require('../config')
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
5 | const packageConfig = require('../package.json')
6 |
7 | exports.assetsPath = function (_path) {
8 | const assetsSubDirectory = process.env.NODE_ENV === 'production'
9 | ? config.build.assetsSubDirectory
10 | : config.dev.assetsSubDirectory
11 |
12 | return path.posix.join(assetsSubDirectory, _path)
13 | }
14 |
15 | exports.cssLoaders = function (options) {
16 | options = options || {}
17 |
18 | const cssLoader = {
19 | loader: 'css-loader',
20 | options: {
21 | sourceMap: options.sourceMap
22 | }
23 | }
24 |
25 | const postcssLoader = {
26 | loader: 'postcss-loader',
27 | options: {
28 | sourceMap: options.sourceMap
29 | }
30 | }
31 |
32 | // generate loader string to be used with extract text plugin
33 | function generateLoaders (loader, loaderOptions) {
34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
35 |
36 | if (loader) {
37 | loaders.push({
38 | loader: loader + '-loader',
39 | options: Object.assign({}, loaderOptions, {
40 | sourceMap: options.sourceMap
41 | })
42 | })
43 | }
44 |
45 | // Extract CSS when that option is specified
46 | // (which is the case during production build)
47 | if (options.extract) {
48 | return ExtractTextPlugin.extract({
49 | use: loaders,
50 | fallback: 'vue-style-loader',
51 | publicPath: 'permissionManage/perm-server/'
52 | })
53 | } else {
54 | return ['vue-style-loader'].concat(loaders)
55 | }
56 | }
57 |
58 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
59 | return {
60 | css: generateLoaders(),
61 | postcss: generateLoaders(),
62 | less: generateLoaders('less'),
63 | sass: generateLoaders('sass', { indentedSyntax: true }),
64 | scss: generateLoaders('sass'),
65 | stylus: generateLoaders('stylus'),
66 | styl: generateLoaders('stylus')
67 | }
68 | }
69 |
70 | // Generate loaders for standalone style files (outside of .vue)
71 | exports.styleLoaders = function (options) {
72 | const output = []
73 | const loaders = exports.cssLoaders(options)
74 |
75 | for (const extension in loaders) {
76 | const loader = loaders[extension]
77 | output.push({
78 | test: new RegExp('\\.' + extension + '$'),
79 | use: loader
80 | })
81 | }
82 |
83 | return output
84 | }
85 |
86 | exports.createNotifierCallback = () => {
87 | const notifier = require('node-notifier')
88 |
89 | return (severity, errors) => {
90 | if (severity !== 'error') return
91 |
92 | const error = errors[0]
93 | const filename = error.file && error.file.split('!').pop()
94 |
95 | notifier.notify({
96 | title: packageConfig.name,
97 | message: severity + ': ' + error.name,
98 | subtitle: filename || '',
99 | icon: path.join(__dirname, 'logo.png')
100 | })
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/perm-vue/static/css/main.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | html,
7 | body,
8 | #app,
9 | .wrapper {
10 | width: 100%;
11 | height: 100%;
12 | overflow: hidden;
13 | }
14 |
15 | body {
16 | font-family: 'PingFang SC', "Helvetica Neue", Helvetica, "microsoft yahei", arial, STHeiTi, sans-serif;
17 | }
18 |
19 | a {
20 | text-decoration: none
21 | }
22 |
23 |
24 | .content-box {
25 | position: absolute;
26 | left: 220px;
27 | right: 0;
28 | top: 70px;
29 | bottom: 0;
30 | padding-bottom: 30px;
31 | -webkit-transition: left .3s ease-in-out;
32 | transition: left .3s ease-in-out;
33 | background: #f0f0f0;
34 | }
35 |
36 | .content {
37 | width: auto;
38 | height: 100%;
39 | padding: 10px;
40 | overflow-y: scroll;
41 | box-sizing: border-box;
42 | }
43 |
44 | .content-collapse {
45 | left: 65px;
46 | }
47 |
48 | .container {
49 | padding: 30px;
50 | background: #fff;
51 | border: 1px solid #ddd;
52 | border-radius: 5px;
53 | }
54 |
55 | .crumbs {
56 | margin: 10px 0;
57 | }
58 |
59 | .pagination {
60 | margin: 20px 0;
61 | text-align: right;
62 | }
63 |
64 | .plugins-tips {
65 | padding: 20px 10px;
66 | margin-bottom: 20px;
67 | }
68 |
69 | .el-button+.el-tooltip {
70 | margin-left: 10px;
71 | }
72 |
73 | .el-table tr:hover {
74 | background: #f6faff;
75 | }
76 |
77 | .mgb20 {
78 | margin-bottom: 20px;
79 | }
80 |
81 | .move-enter-active,
82 | .move-leave-active {
83 | transition: opacity .5s;
84 | }
85 |
86 | .move-enter,
87 | .move-leave {
88 | opacity: 0;
89 | }
90 |
91 | /*BaseForm*/
92 |
93 | .form-box {
94 | width: 600px;
95 | }
96 |
97 | .form-box .line {
98 | text-align: center;
99 | }
100 |
101 | .el-time-panel__content::after,
102 | .el-time-panel__content::before {
103 | margin-top: -7px;
104 | }
105 |
106 | .el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default) {
107 | padding-bottom: 0;
108 | }
109 |
110 | /*Upload*/
111 |
112 | .pure-button {
113 | width: 150px;
114 | height: 40px;
115 | line-height: 40px;
116 | text-align: center;
117 | color: #fff;
118 | border-radius: 3px;
119 | }
120 |
121 | .g-core-image-corp-container .info-aside {
122 | height: 45px;
123 | }
124 |
125 | .el-upload--text {
126 | background-color: #fff;
127 | border: 1px dashed #d9d9d9;
128 | border-radius: 6px;
129 | box-sizing: border-box;
130 | width: 360px;
131 | height: 180px;
132 | text-align: center;
133 | cursor: pointer;
134 | position: relative;
135 | overflow: hidden;
136 | }
137 |
138 | .el-upload--text .el-icon-upload {
139 | font-size: 67px;
140 | color: #97a8be;
141 | margin: 40px 0 16px;
142 | line-height: 50px;
143 | }
144 |
145 | .el-upload--text {
146 | color: #97a8be;
147 | font-size: 14px;
148 | text-align: center;
149 | }
150 |
151 | .el-upload--text em {
152 | font-style: normal;
153 | }
154 |
155 | /*VueEditor*/
156 |
157 | .ql-container {
158 | min-height: 400px;
159 | }
160 |
161 | .ql-snow .ql-tooltip {
162 | transform: translateX(117.5px) translateY(10px) !important;
163 | }
164 |
165 | .editor-btn {
166 | margin-top: 20px;
167 | }
168 |
169 | /*markdown*/
170 |
171 | .v-note-wrapper .v-note-panel {
172 | min-height: 500px;
173 | }
174 |
--------------------------------------------------------------------------------
/perm-server/sys-common/models/baseModel/baseModel.go:
--------------------------------------------------------------------------------
1 | package baseModel
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/caches"
5 | "permissionManage/perm-server/sys-common/db"
6 | "permissionManage/perm-server/sys-common/utils"
7 | "time"
8 | )
9 |
10 | // table cd_sys_user_user
11 | type BaseModel struct {
12 | Id string `json:"id" form:"id"`
13 | CreateTime time.Time `json:"create_time" form:"create_time"`
14 | CreatorDepartmentId string `json:"creator_department_id" form:"creator_department_id"`
15 | CreatorDepartmentName string `json:"creator_department_name" form:"creator_department_name"`
16 | CreatorId string `json:"creator_id" form:"creator_id"`
17 | CreatorName string `json:"creator_name" form:"creator_name"`
18 | IsDeleted int64 `json:"isDeleted" form:"isDeleted"`
19 | UpdateTime time.Time `json:"update_time" form:"update_time"`
20 | UpdaterDepartmentId string `json:"updater_department_id" form:"updater_department_id"`
21 | UpdaterDepartmentName string `json:"updater_department_name" form:"updater_department_name"`
22 | UpdaterId string `json:"updater_id" form:"updater_id"`
23 | UpdaterName string `json:"updater_name" form:"updater_name"`
24 | Version int64 `json:"version" form:"version"`
25 | }
26 |
27 | type CurrentUser struct {
28 | UserId string `json:"userId"`
29 | UserAccount string `json:"userAccount"`
30 | UserName string `json:"userName"`
31 | DepartmentId string `json:"departmentId"`
32 | DepartmentName string `json:"departmentName"`
33 | Roles string `json:"roles"`
34 | Resource string `json:"resource"`
35 | }
36 |
37 | func GetCreateBaseModel(currentUser *CurrentUser) (baseModel *BaseModel) {
38 | baseModel.Id = utils.GetUuid()
39 | baseModel.CreateTime = time.Now()
40 | baseModel.CreatorId = currentUser.UserAccount
41 | baseModel.CreatorName = currentUser.UserName
42 | baseModel.CreatorDepartmentId = currentUser.DepartmentId
43 | baseModel.CreatorDepartmentName = currentUser.DepartmentName
44 | baseModel.IsDeleted = 0
45 |
46 | return baseModel
47 | }
48 |
49 | func InitCurrentUserByUserAccount(userAccount string) (res *CurrentUser, err error) {
50 | e := db.MasterEngine()
51 |
52 | sql := "SELECT " +
53 | " u.id AS userId, " +
54 | " u.user_account AS userAccount, " +
55 | " u.user_name AS userName, " +
56 | " u.department_id AS departmentId, " +
57 | " ud.dep_name AS departmentName " +
58 | " FROM cd_sys_user_user u " +
59 | " LEFT JOIN cd_sys_user_department ud ON u.department_id = ud.id " +
60 | " WHERE u.is_deleted = FALSE " +
61 | " AND u.user_account = '" + userAccount + "'"
62 | s := e.SQL(sql)
63 | queryResult, err := s.QueryString(sql)
64 | if err != nil || len(queryResult) == 0 {
65 | return
66 | }
67 |
68 | res = new(CurrentUser)
69 | res.UserId = queryResult[0]["userId"]
70 | res.UserName = queryResult[0]["userName"]
71 | res.UserAccount = queryResult[0]["userAccount"]
72 | res.DepartmentId = queryResult[0]["departmentId"]
73 | res.DepartmentName = queryResult[0]["departmentName"]
74 |
75 | return
76 | }
77 |
78 | func GetCurrentUset(userId string) *CurrentUser {
79 | curr := new(CurrentUser)
80 | currByt, err := caches.GetJsonByte("currentUser_" + userId)
81 | if err != nil {
82 | err.Error()
83 | }
84 | res := utils.ByteToStruct(currByt, curr)
85 | return res.(*CurrentUser)
86 | }
87 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/vo/uservo/role_vo.go:
--------------------------------------------------------------------------------
1 | package uservo
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/models/baseModel"
5 | "permissionManage/perm-server/sys-common/vo"
6 | "permissionManage/perm-server/sys-sysbase/models/user"
7 | )
8 |
9 | // 前端需要的数据结构
10 | type RoleVO struct {
11 | Id string `json:"id"`
12 | PType string `json:"pType"`
13 | RoleType string `json:"roleType" form:"roleType"`
14 | RoleName string `json:"roleName" form:"roleName"`
15 | RoleCode string `json:"roleCode" form:"roleCode"`
16 | Description string `json:"description" form:"description"`
17 |
18 | Token string `json:"token"`
19 | }
20 |
21 | // 请求参数
22 | type RoleParamVo struct {
23 | *baseModel.CurrentUser
24 | baseModel.BaseModel
25 | *vo.PageVo
26 | Id string `json:"id"`
27 | PType string `json:"pType"`
28 | RoleType string `json:"roleType" form:"roleType"`
29 | RoleName string `json:"roleName" form:"roleName"`
30 | RoleCode string `json:"roleCode" form:"roleCode"`
31 | Description string `json:"description" form:"description"`
32 | Token string `json:"token"`
33 |
34 | ResourceType string `json:"resourceType"`
35 | Ids string `json:"ids"` //批量删除入参
36 | UserId string `json:"userId"` //用户id
37 | }
38 |
39 | // 列表数据结构
40 | type RoleListVo struct {
41 | Id string `json:"id"`
42 | PType string `json:"pType"`
43 | RoleType string `json:"roleType" form:"roleType"`
44 | RoleName string `json:"roleName" form:"roleName"`
45 | RoleCode string `json:"roleCode" form:"roleCode"`
46 | Description string `json:"description" form:"description"`
47 | }
48 |
49 | func RoleParamVoToRole(paramVo *RoleParamVo) (result *user.Role) {
50 | currentUser := paramVo.CurrentUser
51 | if paramVo.Id != "" {
52 | result = user.FindRoleById(paramVo.Id)
53 | result.UpdatorId = currentUser.UserAccount
54 | result.UpdatorName = currentUser.UserName
55 | result.UpdatorDepartmentId = currentUser.DepartmentId
56 | result.UpdatorDepartmentName = currentUser.DepartmentName
57 | } else {
58 | result = new(user.Role)
59 | result.CreatorId = currentUser.UserAccount
60 | result.CreatorName = currentUser.UserName
61 | result.CreatorDepartmentId = currentUser.DepartmentId
62 | result.CreatorDepartmentName = currentUser.DepartmentName
63 | }
64 |
65 | result.PType = paramVo.PType
66 | result.RoleType = "p"
67 | result.RoleName = paramVo.RoleName
68 | result.RoleCode = paramVo.RoleCode
69 | result.Description = paramVo.Description
70 | return
71 | }
72 |
73 | func RoleToRoleLListVo(rl *user.Role) (rlvo *RoleListVo) {
74 | rlvo = new(RoleListVo)
75 | rlvo.Id = rl.Id
76 | rlvo.PType = rl.PType
77 | rlvo.RoleType = rl.RoleType
78 | rlvo.RoleName = rl.RoleName
79 | rlvo.RoleCode = rl.RoleCode
80 | rlvo.Description = rl.Description
81 | return
82 | }
83 |
84 | func RoleToRoleListVos(rls []*user.Role) (rlvos []*RoleListVo) {
85 | for _, r := range rls {
86 | rtVo := RoleToRoleLListVo(r)
87 | rlvos = append(rlvos, rtVo)
88 | }
89 | return
90 | }
91 |
92 | func RoleToRoleVo(param *user.Role) (result *RoleListVo) {
93 | result = new(RoleListVo)
94 | result.Id = param.Id
95 | result.PType = param.PType
96 | result.RoleType = param.RoleType
97 | result.RoleName = param.RoleName
98 | result.RoleCode = param.RoleCode
99 | result.Description = param.Description
100 | return
101 | }
102 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/models/user/role.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/db"
5 | "permissionManage/perm-server/sys-common/utils"
6 | "time"
7 | )
8 |
9 | // table cd_sys_user_role
10 | type Role struct {
11 | Id string `xorm:"pk varchar(32) notnull unique 'id'"`
12 | CreateTime time.Time `xorm:"'create_time'"`
13 | CreatorDepartmentId string `xorm:"varchar(50) 'creator_department_id'"`
14 | CreatorDepartmentName string `xorm:"varchar(255) 'creator_department_name'"`
15 | CreatorId string `xorm:"varchar(50) 'creator_id'"`
16 | CreatorName string `xorm:"varchar(255) 'creator_name'"`
17 | IsDeleted int64 `xorm:"INT(1) notnull 'is_deleted'"`
18 | UpdateTime time.Time `xorm:"'update_time'"`
19 | UpdatorDepartmentId string `xorm:"varchar(50) 'updator_department_id'"`
20 | UpdatorDepartmentName string `xorm:"varchar(255) 'updator_department_name'"`
21 | UpdatorId string `xorm:"varchar(50) 'updator_id'"`
22 | UpdatorName string `xorm:"varchar(255) 'updator_name'"`
23 | Version int64 `xorm:"INT(11) 'version'"`
24 |
25 | PType string `xorm:"varchar(100) index 'p_type'"`
26 | RoleType string `xorm:"varchar(50) 'role_type'"`
27 | RoleName string `xorm:"varchar(100) 'role_name'"`
28 | RoleCode string `xorm:"varchar(20) 'role_code'"`
29 | Description string `xorm:"varchar(255) 'description'"`
30 | }
31 |
32 | func (Role) TableName() string {
33 | return "cd_sys_user_role"
34 | }
35 |
36 | //========================= 新增 ============================
37 | func CreateRole(roles ...*Role) (int64, error) {
38 | e := db.MasterEngine()
39 | var roleEntitys []Role
40 | for _, r := range roles {
41 | // 生成uuid
42 | r.Id = utils.GetUuid()
43 | r.CreateTime = time.Now()
44 | r.Version = 0
45 | r.IsDeleted = 0
46 |
47 | roleEntitys = append(roleEntitys, *r)
48 | }
49 | return e.Insert(roleEntitys)
50 | }
51 |
52 | //========================= 更新 ============================
53 | func UpdateRole(role *Role) (int64, error) {
54 | e := db.MasterEngine()
55 | role.UpdateTime = time.Now()
56 | role.Version = role.Version + 1
57 | aff, err := e.Id(role.Id).Update(role)
58 | if err != nil {
59 | err.Error()
60 | }
61 | return aff, err
62 | }
63 |
64 | //========================= 逻辑删除 ============================
65 | func DeleteRoleByIds(ids []string) (effect int64, err error) {
66 | e := db.MasterEngine()
67 | for _, id := range ids {
68 | role := FindRoleById(id)
69 | if role != nil {
70 | role.IsDeleted = 1
71 | _, err := e.Id(id).Update(role)
72 | if err != nil {
73 | err.Error()
74 | }
75 | }
76 | }
77 | return
78 | }
79 |
80 | //========================= 物理删除 ============================
81 | func RemoveRoleByIds(ids []int64) (effect int64, err error) {
82 | e := db.MasterEngine()
83 |
84 | cr := new(Role)
85 | for _, v := range ids {
86 | i, err1 := e.Id(v).Delete(cr)
87 | effect += i
88 | err = err1
89 | }
90 | return
91 | }
92 |
93 | //========================= 查询 ============================
94 | // 根据id查询
95 | func FindRoleById(id string) (role *Role) {
96 | role = new(Role)
97 | e := db.MasterEngine()
98 | _, err := e.Id(id).Get(role)
99 | if err != nil {
100 | err.Error()
101 | return
102 | }
103 |
104 | return
105 | }
106 |
--------------------------------------------------------------------------------
/perm-server/sys-common/caches/redis.go:
--------------------------------------------------------------------------------
1 | package caches
2 |
3 | import (
4 | "encoding/json"
5 | "errors"
6 | "fmt"
7 | "github.com/garyburd/redigo/redis"
8 | "github.com/pelletier/go-toml"
9 | "permissionManage/perm-server/sys-common/conf"
10 | "time"
11 | )
12 |
13 | // NewRedisPool 返回redis连接池
14 | func NewRedisPool() *redis.Pool {
15 | configTree := conf.Conf.Get("redis").(*toml.Tree)
16 | var (
17 | redisURL = "redis://" + configTree.Get("Addr").(string)
18 | redisMaxIdle = int(configTree.Get("RedisMaxIdle").(int64)) //最大空闲连接数
19 | redisIdleTimeoutSec = int64(configTree.Get("RedisIdleTimeoutSec").(int64))
20 | redisPassword = configTree.Get("Password").(string)
21 | dB = int(configTree.Get("DB").(int64))
22 | )
23 | return &redis.Pool{
24 | MaxIdle: redisMaxIdle,
25 | //IdleTimeout: redisIdleTimeoutSec * time.Second,
26 | Dial: func() (redis.Conn, error) {
27 | redis.DialConnectTimeout(time.Duration(redisIdleTimeoutSec))
28 | redis.DialDatabase(dB)
29 | c, err := redis.DialURL(redisURL)
30 | if err != nil {
31 | return nil, fmt.Errorf("redis connection error: %s", err)
32 | }
33 | //验证redis密码
34 | if _, authErr := c.Do("AUTH", redisPassword); authErr != nil {
35 | return nil, fmt.Errorf("redis auth password error: %s", authErr)
36 | }
37 | return c, err
38 | },
39 | TestOnBorrow: func(c redis.Conn, t time.Time) error {
40 | _, err := c.Do("PING")
41 | if err != nil {
42 | return fmt.Errorf("ping redis error: %s", err)
43 | }
44 | return nil
45 | },
46 | }
47 | }
48 |
49 | func Set(k, v string) {
50 | c := NewRedisPool().Get()
51 | defer c.Close()
52 | _, err := c.Do("SET", k, v)
53 | if err != nil {
54 | fmt.Println("set error", err.Error())
55 | }
56 | }
57 | func SetKVExpire(k, v string, ex int) {
58 | c := NewRedisPool().Get()
59 | defer c.Close()
60 | _, err := c.Do("EXPIRE", k, v, ex)
61 | if err != nil {
62 | fmt.Println("set error", err.Error())
63 | }
64 | }
65 |
66 | func GetStringValue(k string) string {
67 | c := NewRedisPool().Get()
68 | defer c.Close()
69 | username, err := redis.String(c.Do("GET", k))
70 | if err != nil {
71 | fmt.Println("Get Error: ", err.Error())
72 | return ""
73 | }
74 | return username
75 | }
76 |
77 | func SetKeyExpire(k string, ex int) {
78 | c := NewRedisPool().Get()
79 | defer c.Close()
80 | _, err := c.Do("EXPIRE", k, ex)
81 | if err != nil {
82 | fmt.Println("set error", err.Error())
83 | }
84 | }
85 |
86 | func CheckKey(k string) bool {
87 | c := NewRedisPool().Get()
88 | defer c.Close()
89 | exist, err := redis.Bool(c.Do("EXISTS", k))
90 | if err != nil {
91 | fmt.Println(err)
92 | return false
93 | } else {
94 | return exist
95 | }
96 | }
97 |
98 | func DelKey(k string) error {
99 | c := NewRedisPool().Get()
100 | defer c.Close()
101 | _, err := c.Do("DEL", k)
102 | if err != nil {
103 | fmt.Println(err)
104 | return err
105 | }
106 | return nil
107 | }
108 |
109 | func SetJson(k string, data interface{}) error {
110 | c := NewRedisPool().Get()
111 | defer c.Close()
112 | value, _ := json.Marshal(data)
113 | n, _ := c.Do("SETNX", k, value)
114 | if n != int64(1) {
115 | return errors.New("set failed")
116 | }
117 | return nil
118 | }
119 |
120 | func GetJsonByte(k string) ([]byte, error) {
121 | c := NewRedisPool().Get()
122 | jsonGet, err := redis.Bytes(c.Do("GET", k))
123 | if err != nil {
124 | fmt.Println(err)
125 | return nil, err
126 | }
127 | return jsonGet, nil
128 | }
129 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/vo/uservo/department_vo.go:
--------------------------------------------------------------------------------
1 | package uservo
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/models/baseModel"
5 | "permissionManage/perm-server/sys-common/vo"
6 | "permissionManage/perm-server/sys-sysbase/models/user"
7 | )
8 |
9 | // 前端需要的数据结构
10 | type DepartmentVO struct {
11 | *user.User
12 | Token string `json:"token"`
13 | }
14 |
15 | // 请求参数
16 | type DepartmentParamVo struct {
17 | *baseModel.CurrentUser
18 | baseModel.BaseModel
19 | *vo.PageVo
20 | DepName string `json:"depName"`
21 | DepCode string `json:"depCode" form:"depCode"`
22 | DepLevel int64 `json:"depLevel" form:"depLevel"`
23 | DepOrder int64 `json:"depOrder" form:"depOrder"`
24 | ParentId string `json:"parentId" form:"parentId"`
25 | Token string `json:"token"`
26 |
27 | Ids string `json:"ids"` //批量删除入参
28 | }
29 |
30 | // 列表数据结构
31 | type DepartmentListVo struct {
32 | Id string `json:"id"`
33 | DepName string `json:"depName"`
34 | DepCode string `json:"depCode" form:"depCode"`
35 | DepLevel int64 `json:"depLevel" form:"depLevel"`
36 | DepOrder int64 `json:"depOrder" form:"depOrder"`
37 | ParentId string `json:"parentId" form:"parentId"`
38 | }
39 |
40 | // 树结构数据
41 | type DepartmentTreeVo struct {
42 | Id string `json:"id"`
43 | ParentId string `json:"parentId"`
44 | Subs []*DepartmentTreeVo `json:"subs"`
45 | Child []*DepartmentTreeVo `json:"child"`
46 | Name string `json:"name"`
47 | DepLevel int64 `json:"depLevel" form:"depLevel"`
48 | }
49 |
50 | func DepartmentToDepartmentTreeVo(resource *user.Department) (rtVo *DepartmentTreeVo) {
51 | rtVo = new(DepartmentTreeVo)
52 | rtVo.Id = resource.Id
53 | rtVo.ParentId = resource.ParentId
54 | rtVo.Name = resource.DepName
55 | rtVo.DepLevel = resource.DepLevel
56 | //golog.Infof("%s", rtVo)
57 | return
58 | }
59 |
60 | func DepartmentToDepartmentTreeVos(resources []*user.Department) (rtVos []*DepartmentTreeVo) {
61 | for _, r := range resources {
62 | rtVo := DepartmentToDepartmentTreeVo(r)
63 | rtVos = append(rtVos, rtVo)
64 | }
65 | return
66 | }
67 |
68 | func DepartmentParamVoVoToDepartment(paramVo *DepartmentParamVo) (result *user.Department) {
69 | currentUser := paramVo.CurrentUser
70 | if paramVo.Id != "" {
71 | result = user.FindDepartmentById(paramVo.Id)
72 | result.UpdatorId = currentUser.UserAccount
73 | result.UpdatorName = currentUser.UserName
74 | result.UpdatorDepartmentId = currentUser.DepartmentId
75 | result.UpdatorDepartmentName = currentUser.DepartmentName
76 | } else {
77 | result = new(user.Department)
78 | result.CreatorId = currentUser.UserAccount
79 | result.CreatorName = currentUser.UserName
80 | result.CreatorDepartmentId = currentUser.DepartmentId
81 | result.CreatorDepartmentName = currentUser.DepartmentName
82 | }
83 | result.DepName = paramVo.DepName
84 | result.DepCode = paramVo.DepCode
85 | result.DepOrder = paramVo.DepOrder
86 | result.ParentId = paramVo.ParentId
87 | result.DepLevel = paramVo.DepLevel
88 | return
89 | }
90 |
91 | func DepartmentToResourceListVo(dep *user.Department) (depvo *DepartmentListVo) {
92 | depvo = new(DepartmentListVo)
93 | depvo.Id = dep.Id
94 | depvo.DepName = dep.DepName
95 | depvo.DepCode = dep.DepCode
96 | depvo.DepOrder = dep.DepOrder
97 | depvo.ParentId = dep.ParentId
98 | depvo.DepLevel = dep.DepLevel
99 | return
100 | }
101 |
102 | func DepartmentToDepartmentListVos(deps []*user.Department) (depVos []*DepartmentListVo) {
103 | for _, dep := range deps {
104 | depVo := DepartmentToResourceListVo(dep)
105 | depVos = append(depVos, depVo)
106 | }
107 | return
108 | }
109 |
--------------------------------------------------------------------------------
/perm-vue/src/components/common/Sidebar.vue:
--------------------------------------------------------------------------------
1 |
2 |
32 |
33 |
34 |
78 |
79 |
101 |
--------------------------------------------------------------------------------
/perm-vue/src/components/page/demo/BaseCharts.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | schart图表
6 |
7 |
8 |
9 |
10 | vue-schart:vue.js封装sChart.js的图表组件。
11 | 访问地址:
vue-schart
12 |
13 |
17 |
21 |
25 |
29 |
30 |
31 |
32 |
33 |
90 |
91 |
--------------------------------------------------------------------------------
/perm-vue/src/utils/rest.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | // import Qs from 'qs'
3 | import {Message} from 'element-ui'
4 | import {fmtToken} from "./utils";
5 |
6 | /**
7 | const postData=JSON.stringify(this.formCustomer);
8 | 'Content-Type':'application/json'}
9 |
10 | const postData=Qs.stringify(this.formCustomer);//过滤成?&=格式
11 | 'Content-Type':'application/xxxx-form'}
12 | */
13 |
14 | var axiosInstance = axios.create({
15 | baseURL: 'http://localhost:8099',
16 | // config里面有这个transformRquest,这个选项会在发送参数前进行处理。
17 | // 这时候我们通过Qs.stringify转换为表单查询参数
18 | transformRequest: [function (data) {
19 | // data = Qs.stringify(data)
20 | data = JSON.stringify(data); // 转换json
21 | return data
22 | }],
23 | // 设置Content-Type
24 | headers: {
25 | 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
26 | // 'Authorization': 'bearer ' + JSON.parse(window.sessionStorage.getItem('user')).token
27 | }
28 | });
29 |
30 | // 请求拦截
31 | axiosInstance.interceptors.request.use(config => {
32 | config.headers['Authorization'] = fmtToken();
33 | // config.headers.Authorization = 'bearer ' + token
34 | return config
35 | }, err => {
36 | Message.error({message: '请求超时!', showClose: true});
37 | return Promise.resolve(err)
38 | });
39 | // response拦截
40 | axiosInstance.interceptors.response.use(data => {
41 | // if (data.status && data.status === 200 && data.data.code != 200) {
42 | // console.log(data)
43 | // Message.error({message: data.data.msg})
44 | // return
45 | // }
46 | return data
47 | }, err => {
48 | if (err.response) {
49 | var status = err.response.status;
50 | var msg = err.response.data.msg;
51 | switch (status) {
52 | case 400:
53 | Message.error({message: (msg != null && msg !== '') ? msg : '操作失败,参数不对!', showClose: true});
54 | break;
55 | case 401:
56 | Message.error({message: (msg != null && msg !== '') ? msg : '未认证或认证过期,请重新登录!', showClose: true});
57 | break;
58 | case 404:
59 | Message.error({message: '请求的资源不存在!', showClose: true});
60 | break;
61 | case 403:
62 | Message.error({message: '权限不足,请联系管理员!', showClose: true});
63 | break;
64 | case 500:
65 | Message.error({message: '服务器被吃了 ⊙﹏⊙...', showClose: true});
66 | break;
67 | case 504:
68 | Message.error({message: '网关连接超时!', showClose: true});
69 | break;
70 | default:
71 | Message.error({message: '未知错误!', showClose: true})
72 | }
73 | }
74 | return Promise.resolve(err)
75 | });
76 |
77 | // ---------- rest请求封装 -----------
78 | let base = 'http://localhost:8088'
79 | // let base = '/api'
80 | // let base = ''
81 | export const ftmURL = function url(url) {
82 | return `${base}${url}`
83 | // return base + url
84 | };
85 |
86 | export const postRequest = function (url, params) {
87 | return axiosInstance({
88 | method: 'post',
89 | url: ftmURL(url),
90 | data: params,
91 | headers: {
92 | 'Content-Type': 'application/x-www-form-urlencoded'
93 | }
94 | })
95 | };
96 |
97 | export const uploadFileRequest = function (url, params) {
98 | return axiosInstance({
99 | method: 'post',
100 | url: ftmURL(url),
101 | data: params,
102 | headers: {
103 | 'Content-Type': 'multipart/form-data'
104 | }
105 | })
106 | };
107 |
108 | export const putRequest = function (url, params) {
109 | return axiosInstance({
110 | method: 'put',
111 | url: ftmURL(url),
112 | data: params
113 | })
114 | };
115 |
116 | export const deleteRequest = function (url) {
117 | return axiosInstance({
118 | method: 'delete',
119 | url: ftmURL(url)
120 | })
121 | };
122 |
123 | export const getRequest = function (url) {
124 | return axiosInstance({
125 | method: 'get',
126 | url: ftmURL(url)
127 | })
128 | };
129 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/models/user/department.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/db"
5 | "permissionManage/perm-server/sys-common/utils"
6 | "strconv"
7 | "time"
8 | )
9 |
10 | // table cd_sys_user_department
11 | type Department struct {
12 | Id string `xorm:"pk varchar(32) notnull unique 'id'"`
13 | CreateTime time.Time `xorm:"'create_time'"`
14 | CreatorDepartmentId string `xorm:"varchar(50) 'creator_department_id'"`
15 | CreatorDepartmentName string `xorm:"varchar(255) 'creator_department_name'"`
16 | CreatorId string `xorm:"varchar(50) 'creator_id'"`
17 | CreatorName string `xorm:"varchar(255) 'creator_name'"`
18 | IsDeleted int64 `xorm:"INT(1) notnull 'is_deleted'"`
19 | UpdateTime time.Time `xorm:"'update_time'"`
20 | UpdatorDepartmentId string `xorm:"varchar(50) 'updator_department_id'"`
21 | UpdatorDepartmentName string `xorm:"varchar(255) 'updator_department_name'"`
22 | UpdatorId string `xorm:"varchar(50) 'updator_id'"`
23 | UpdatorName string `xorm:"varchar(255) 'updator_name'"`
24 | Version int64 `xorm:"INT(11) 'version'"`
25 |
26 | DepName string `xorm:"varchar(100) 'dep_name' index"`
27 | DepCode string `xorm:"varchar(50) 'dep_code'"`
28 | DepLevel int64 `xorm:"INT(11) 'dep_level'"`
29 | DepOrder int64 `xorm:"INT(11) 'dep_order'"`
30 | ParentId string `xorm:"varchar(100) 'parent_id'"`
31 | }
32 |
33 | func (Department) TableName() string {
34 | return "cd_sys_user_department"
35 | }
36 |
37 | //========================= 新增 ============================
38 | func CreateDepartment(deps ...*Department) (int64, error) {
39 | e := db.MasterEngine()
40 | var roleEntitys []Department
41 | for _, d := range deps {
42 | // 生成uuid
43 | d.Id = utils.GetUuid()
44 | d.CreateTime = time.Now()
45 | d.Version = 0
46 | d.IsDeleted = 0
47 |
48 | roleEntitys = append(roleEntitys, *d)
49 | }
50 | return e.Insert(roleEntitys)
51 | }
52 |
53 | //========================= 更新 ============================
54 | func UpdateDepartment(eParam *Department) (int64, error) {
55 | e := db.MasterEngine()
56 | eParam.UpdateTime = time.Now()
57 | eParam.Version = eParam.Version + 1
58 | aff, err := e.Id(eParam.Id).Update(eParam)
59 | if err != nil {
60 | err.Error()
61 | }
62 | return aff, err
63 | }
64 |
65 | //========================= 逻辑删除 ============================
66 | func DeleteDepartmentByIds(ids []string) (effect int64, err error) {
67 | e := db.MasterEngine()
68 | for _, id := range ids {
69 | eModel := FindDepartmentById(id)
70 | if eModel != nil {
71 | eModel.IsDeleted = 1
72 | _, err := e.Id(id).Update(eModel)
73 | if err != nil {
74 | err.Error()
75 | }
76 | }
77 | }
78 | return
79 | }
80 |
81 | //========================= 物理删除 ============================
82 | func RemoveDepartmentByIds(ids []int64) (effect int64, err error) {
83 | e := db.MasterEngine()
84 |
85 | cr := new(Department)
86 | for _, v := range ids {
87 | i, err1 := e.Id(v).Delete(cr)
88 | effect += i
89 | err = err1
90 | }
91 | return
92 | }
93 |
94 | //========================= 查询 ============================
95 | // 根据id查询
96 | func FindDepartmentById(id string) (eRes *Department) {
97 | eRes = new(Department)
98 | e := db.MasterEngine()
99 | _, err := e.Id(id).Get(eRes)
100 | if err != nil {
101 | err.Error()
102 | return
103 | }
104 |
105 | return
106 | }
107 |
108 | // ===== 根据父id查询当前级别菜单最大序号
109 | func GetDepartmentMaxOrderByParentId(parentId string) (int64, error) {
110 | e := db.MasterEngine()
111 |
112 | sql := "SELECT MAX(ud.dep_order) AS maxOrder FROM cd_sys_user_department ud WHERE ud.parent_id = '" + parentId + "'"
113 | s := e.SQL(sql)
114 | re, err := s.QueryString(sql)
115 | if err != nil || len(re) == 0 {
116 | return int64(0), err
117 | }
118 | if re[0]["maxOrder"] == "" {
119 | return int64(0), nil
120 | }
121 | maxOrder, err := strconv.ParseInt(re[0]["maxOrder"], 10, 64)
122 |
123 | return maxOrder, err
124 | }
125 |
126 | // ===== 根据父id查询当前菜单级别
127 | func GetDepartmentParentLevelByParentId(parentId string) (int64, error) {
128 | e := db.MasterEngine()
129 |
130 | sql := "SELECT MAX(ud.dep_level) AS parentLevel FROM cd_sys_user_department ud WHERE ud.id = '" + parentId + "'"
131 | s := e.SQL(sql)
132 | re, err := s.QueryString(sql)
133 | if err != nil || len(re) == 0 {
134 | return int64(0), err
135 | }
136 | level, err := strconv.ParseInt(re[0]["parentLevel"], 10, 64)
137 |
138 | return level, err
139 | }
140 |
--------------------------------------------------------------------------------
/perm-server/sys-common/middleware/casbins/casbins.go:
--------------------------------------------------------------------------------
1 | package casbins
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | "permissionManage/perm-server/sys-common/db"
7 | "permissionManage/perm-server/sys-common/inits/parse"
8 | "permissionManage/perm-server/sys-common/middleware/jwts"
9 | "permissionManage/perm-server/sys-common/supports"
10 | "permissionManage/perm-server/sys-common/supports/commonConst"
11 | "strconv"
12 | "sync"
13 |
14 | "github.com/casbin/casbin"
15 |
16 | _ "github.com/go-sql-driver/mysql"
17 | "github.com/kataras/iris/v12/context"
18 | )
19 |
20 | var (
21 | adt *Adapter // Your driver and data source.
22 | e *casbin.Enforcer
23 |
24 | adtLook sync.Mutex
25 | eLook sync.Mutex
26 |
27 | rbacModel string
28 | )
29 |
30 | // Casbin is the casbins services which contains the casbins enforcer.
31 | //type Casbin struct {
32 | // Enforcer *casbins.Enforcer
33 | //}
34 |
35 | // New returns the casbins service which receives a casbins enforcer.
36 | //
37 | // Adapt with its `Wrapper` for the entire application
38 | // or its `ServeHTTP` for specific routes or parties.
39 | //func New() *Casbin {
40 | // return &Casbin{Enforcer: e}
41 | //}
42 |
43 | func SetRbacModel(rootID string) {
44 | rbacModel = fmt.Sprintf(`
45 | [request_definition]
46 | r = sub, obj, act, suf
47 |
48 | [policy_definition]
49 | p = sub, obj, act, suf
50 |
51 | [role_definition]
52 | g = _, _
53 |
54 | [policy_effect]
55 | e = some(where (p.eft == allow))
56 |
57 | [matchers]
58 | m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && regexMatch(r.suf, p.suf) && regexMatch(r.act, p.act) || r.sub == "%s"
59 | `, rootID)
60 | }
61 |
62 | // 获取Enforcer
63 | func GetEnforcer() *casbin.Enforcer {
64 | if e != nil {
65 | e.LoadPolicy()
66 | return e
67 | }
68 | eLook.Lock()
69 | defer eLook.Unlock()
70 | if e != nil {
71 | e.LoadPolicy()
72 | return e
73 | }
74 |
75 | m := casbin.NewModel(rbacModel)
76 | //m.AddDef("r", "r", "sub, obj, act, suf")
77 | //m.AddDef("p", "p", "sub, obj, act, suf")
78 | //m.AddDef("g", "g", "_, _")
79 | //m.AddDef("e", "e", "some(where (p.eft == allow))")
80 | //m.AddDef("m", "m", `g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && regexMatch(r.suf, p.suf) && regexMatch(r.act, p.act) || r.sub == "1"`)
81 |
82 | // Or you can use an existing DB "abc" like this:
83 | // The adapter will use the table named "casbin_rule".
84 | // If it doesn't exist, the adapter will create it automatically.
85 | // a := xormadapter.NewAdapter("mysql", "mysql_username:mysql_password@tcp(127.0.0.1:3306)/abc", true)
86 | // TODO use go-bindata fill
87 | //e = casbin.NewEnforcer("conf/rbac_model.conf", singletonAdapter())
88 | e = casbin.NewEnforcer(m, singleAdapter())
89 | e.EnableLog(true)
90 | return e
91 | }
92 |
93 | func singleAdapter() *Adapter {
94 | if adt != nil {
95 | return adt
96 | }
97 | adtLook.Lock()
98 | defer adtLook.Unlock()
99 | if adt != nil {
100 | return adt
101 | }
102 |
103 | master := parse.DBConfig.Master
104 | url := db.GetConnURL(&master)
105 | // Initialize a Gorm adapter and use it in a Casbin enforcer:
106 | // The adapter will use the MySQL database named "casbins".
107 | // If it doesn't exist, the adapter will create it automatically.
108 | // a := xormadapter.NewAdapter("mysql", "root:root@tcp(127.0.0.1:3306)/?charset=utf8&parseTime=True&loc=Local") // Your driver and data source.
109 | adt = NewAdapter(master.Dialect, url, true) // Your driver and data source.
110 | return adt
111 | }
112 |
113 | // ServeHTTP is the iris compatible casbins handler which should be passed to specific routes or parties.
114 | // Usage:
115 | // [...]
116 | // app.Get("/dataset1/resource1", casbinMiddleware.ServeHTTP, myHandler)
117 | // [...]
118 | func CheckPermissions(ctx context.Context) bool {
119 | user, ok := jwts.ParseToken(ctx)
120 | if !ok {
121 | return false
122 | }
123 |
124 | //uid := strconv.Itoa(string(user.Id))
125 | uid := strconv.Itoa(int(0))
126 | fmt.Println(user)
127 | fmt.Println(uid)
128 | yes := true //GetEnforcer().Enforce(uid, ctx.Path(), ctx.Method(), ".*", "")
129 | if !yes {
130 | supports.Unauthorized(ctx, supports.PermissionsLess, nil)
131 | ctx.StopExecution()
132 | return false
133 | }
134 | ctx.Params().Set(commonConst.CURRENT_USER_KEY, user.Id)
135 | return true
136 | //ctx.Next()
137 | }
138 |
139 | // Wrapper is the router wrapper, prefer this method if you want to use casbins to your entire iris application.
140 | // Usage:
141 | // [...]
142 | // app.WrapRouter(casbinMiddleware.Wrapper())
143 | // app.Get("/dataset1/resource1", myHandler)
144 | // [...]
145 | func Wrapper() func(w http.ResponseWriter, r *http.Request, router http.HandlerFunc) {
146 | return func(w http.ResponseWriter, r *http.Request, router http.HandlerFunc) {
147 | //if !c.Check(r) {
148 | // w.WriteHeader(http.StatusForbidden)
149 | // w.Write([]byte("403 Forbidden"))
150 | // return
151 | //}
152 | router(w, r)
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/models/user/user.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/db"
5 | "permissionManage/perm-server/sys-common/utils"
6 | "strconv"
7 | "time"
8 | )
9 |
10 | // table cd_sys_user_user
11 | type User struct {
12 | Id string `xorm:"pk varchar(32) notnull unique 'id'"`
13 | CreateTime time.Time `xorm:"'create_time'"`
14 | CreatorDepartmentId string `xorm:"varchar(50) 'creator_department_id'"`
15 | CreatorDepartmentName string `xorm:"varchar(255) 'creator_department_name'"`
16 | CreatorId string `xorm:"varchar(50) 'creator_id'"`
17 | CreatorName string `xorm:"varchar(255) 'creator_name'"`
18 | IsDeleted int64 `xorm:"INT(1) notnull 'is_deleted'"`
19 | UpdateTime time.Time `xorm:"'update_time'"`
20 | UpdatorDepartmentId string `xorm:"varchar(50) 'updator_department_id'"`
21 | UpdatorDepartmentName string `xorm:"varchar(255) 'updator_department_name'"`
22 | UpdatorId string `xorm:"varchar(50) 'updator_id'"`
23 | UpdatorName string `xorm:"varchar(255) 'updator_name'"`
24 | Version int64 `xorm:"INT(11) 'version'"`
25 |
26 | UserNumber string `xorm:"varchar(50) 'user_number'"`
27 | UserAccount string `xorm:"varchar(50) 'user_account'"`
28 | UserPassword string `xorm:"varchar(50) 'user_password'"`
29 | UserName string `xorm:"varchar(50) 'user_name'"`
30 | Sex string `xorm:"varchar(50) 'sex'"`
31 | DepartmentId string `xorm:"varchar(50) 'department_id'"`
32 | Mobile string `xorm:"varchar(50) 'mobile'"`
33 | Email string `xorm:"varchar(50) 'email'"`
34 | Address string `xorm:"varchar(255) 'address'"`
35 | }
36 |
37 | type UserDepartment struct {
38 | User `xorm:"extends"`
39 | Department `xorm:"extends"`
40 | }
41 |
42 | func (User) TableName() string {
43 | return "cd_sys_user_user"
44 | }
45 |
46 | func (UserDepartment) TableName() string {
47 | return "cd_sys_user_user"
48 | }
49 |
50 | //========================= 新增 ============================
51 | func CreateUser(users ...*User) (int64, error) {
52 | e := db.MasterEngine()
53 | var userEntitys []User
54 | for _, u := range users {
55 | u.Id = utils.GetUuid()
56 | u.CreateTime = time.Now()
57 | u.IsDeleted = 0
58 | // 密码加密
59 | u.UserPassword = utils.AESEncrypt([]byte(u.UserPassword))
60 | userEntitys = append(userEntitys, *u)
61 | }
62 | return e.Insert(userEntitys)
63 | }
64 |
65 | //========================= 更新 ============================
66 | func UpdateUser(eParam *User) (int64, error) {
67 | e := db.MasterEngine()
68 | eParam.UpdateTime = time.Now()
69 | eParam.Version = eParam.Version + 1
70 | aff, err := e.Id(eParam.Id).Update(eParam)
71 | if err != nil {
72 | err.Error()
73 | }
74 | return aff, err
75 | }
76 |
77 | //========================= 逻辑删除 ============================
78 | func DeleteUserByIds(ids []string) (effect int64, err error) {
79 | e := db.MasterEngine()
80 | for _, id := range ids {
81 | user := FindUserById(id)
82 | if user != nil {
83 | user.IsDeleted = 1
84 | _, err := e.Id(id).Update(user)
85 | if err != nil {
86 | err.Error()
87 | }
88 | }
89 | }
90 | return
91 | }
92 |
93 | //========================= 物理删除 ============================
94 | func RemoveUserByIds(ids []int64) (effect int64, err error) {
95 | e := db.MasterEngine()
96 |
97 | cr := new(User)
98 | for _, v := range ids {
99 | i, err1 := e.Id(v).Delete(cr)
100 | effect += i
101 | err = err1
102 | }
103 | return
104 | }
105 |
106 | //========================= 查询 ============================
107 | //// 根据id查询
108 | //func FindUserById(userId string) *User {
109 | // user := new(User)
110 | // e := db.MasterEngine()
111 | // e.Get(&User{Id: userId})
112 | //
113 | // return user
114 | //}
115 |
116 | // 根据id查询
117 | func FindUserById(id string) (user *User) {
118 | user = new(User)
119 | e := db.MasterEngine()
120 | _, err := e.Id(id).Get(user)
121 | if err != nil {
122 | err.Error()
123 | return
124 | }
125 |
126 | return
127 | }
128 |
129 | // ===== 查询用户最大编号
130 | func GetMaxUserNumber() (int64, error) {
131 | e := db.MasterEngine()
132 |
133 | sql := "SELECT MAX(CONVERT(uu.user_number,SIGNED)) AS maxUserNumber FROM cd_sys_user_user uu"
134 | s := e.SQL(sql)
135 | re, err := s.QueryString(sql)
136 | if err != nil || len(re) == 0 {
137 | return int64(0), err
138 | }
139 | if re[0]["maxUserNumber"] == "" {
140 | return int64(0), nil
141 | }
142 | maxUserNumber, err := strconv.ParseInt(re[0]["maxUserNumber"], 10, 64)
143 |
144 | return maxUserNumber, err
145 | }
146 |
147 | func GetUserByUsername(user *User) (bool, error) {
148 | e := db.MasterEngine()
149 | return e.Get(user)
150 | }
151 |
152 | func UpdateUserById(user *User) (int64, error) {
153 | e := db.MasterEngine()
154 | return e.Id(user.Id).Update(user)
155 | }
156 |
157 | func DeleteByUsers(uids []int64) (effect int64, err error) {
158 | e := db.MasterEngine()
159 |
160 | u := new(User)
161 | for _, v := range uids {
162 | i, err1 := e.Id(v).Delete(u)
163 | effect += i
164 | err = err1
165 | }
166 | return
167 | }
168 |
--------------------------------------------------------------------------------
/perm-vue/src/components/page/demo/Upload.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 表单
6 | 图片上传
7 |
8 |
9 |
10 |
支持拖拽
11 |
15 |
20 |
21 | 将文件拖到此处,或点击上传
22 | 只能上传jpg/png文件,且不超过500kb
23 |
24 |
支持裁剪
25 |
26 | vue-cropperjs:一个封装了 cropperjs 的 Vue 组件。
27 | 访问地址:
vue-cropperjs
28 |
29 |
30 |
![]()
31 |
选择图片
32 |
33 |
34 |
35 |
36 |
37 |
38 |
42 |
43 |
44 |
45 |
46 |
47 |
99 |
100 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/models/user/resource.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "fmt"
5 | "permissionManage/perm-server/sys-common/db"
6 | "permissionManage/perm-server/sys-common/utils"
7 | "strconv"
8 | "time"
9 | )
10 |
11 | // cd_sys_user_resource
12 | type Resource struct {
13 | Id string `xorm:"pk varchar(32) notnull unique 'id'"`
14 | CreateTime time.Time `xorm:"'create_time'"`
15 | CreatorDepartmentId string `xorm:"varchar(50) 'creator_department_id'"`
16 | CreatorDepartmentName string `xorm:"varchar(255) 'creator_department_name'"`
17 | CreatorId string `xorm:"varchar(50) 'creator_id'"`
18 | CreatorName string `xorm:"varchar(255) 'creator_name'"`
19 | IsDeleted int64 `xorm:"INT(1) notnull 'is_deleted'"`
20 | UpdateTime time.Time `xorm:"'update_time'"`
21 | UpdatorDepartmentId string `xorm:"varchar(50) 'updator_department_id'"`
22 | UpdatorDepartmentName string `xorm:"varchar(255) 'updator_department_name'"`
23 | UpdatorId string `xorm:"varchar(50) 'updator_id'"`
24 | UpdatorName string `xorm:"varchar(255) 'updator_name'"`
25 | Version int64 `xorm:"INT(11) 'version'"`
26 |
27 | ResourceType string `xorm:"varchar(50) 'resource_type'"`
28 | ResourceName string `xorm:"varchar(100) 'resource_name'"`
29 | ResourceLevel int64 `xorm:"INT(11) 'resource_level'"`
30 | ResourceOrder int64 `xorm:"INT(11) 'resource_order'"`
31 | ResourceSate int64 `xorm:"tinyint(2) 'resource_sate'"`
32 | ParentId string `xorm:"varchar(50) 'parent_id'"`
33 | Url string `xorm:"varchar(100) 'url'"`
34 | Icon string `xorm:"varchar(100) 'icon'"`
35 | Description string `xorm:"varchar(255) 'description'"`
36 | }
37 |
38 | func (Resource) TableName() string {
39 | return "cd_sys_user_resource"
40 | }
41 |
42 | //========================= 新增 ============================
43 | func CreateResource(resources ...*Resource) (int64, error) {
44 | e := db.MasterEngine()
45 | var resourcesEntitys []Resource
46 | for _, r := range resources {
47 | // 生成uuid
48 | r.Id = utils.GetUuid()
49 | r.CreateTime = time.Now()
50 | r.Version = 0
51 | r.IsDeleted = 0
52 |
53 | resourcesEntitys = append(resourcesEntitys, *r)
54 | }
55 | return e.Insert(resourcesEntitys)
56 | }
57 |
58 | //========================= 更新 ============================
59 | func UpdateResource(resource *Resource) (int64, error) {
60 | e := db.MasterEngine()
61 | resource.UpdateTime = time.Now()
62 | resource.Version = resource.Version + 1
63 | aff, err := e.Id(resource.Id).Update(resource)
64 | if err != nil {
65 | err.Error()
66 | }
67 | return aff, err
68 | }
69 |
70 | //========================= 逻辑删除 ============================
71 | func DeleteResourceByIds(ids []string) (effect int64, err error) {
72 | e := db.MasterEngine()
73 | for _, id := range ids {
74 | tmpResource := FindResourceById(id)
75 | if tmpResource != nil {
76 | tmpResource.IsDeleted = 1
77 | _, err := e.Id(id).Update(tmpResource)
78 | if err != nil {
79 | err.Error()
80 | }
81 | }
82 | }
83 | return
84 | }
85 |
86 | //========================= 物理删除 ============================
87 | func RemoveResourceByIds(ids []int64) (effect int64, err error) {
88 | e := db.MasterEngine()
89 |
90 | cr := new(Resource)
91 | for _, v := range ids {
92 | i, err1 := e.Id(v).Delete(cr)
93 | effect += i
94 | err = err1
95 | }
96 | return
97 | }
98 |
99 | //========================= 查询 ============================
100 | func FindResourceById(id string) (resource *Resource) {
101 | resource = new(Resource)
102 | e := db.MasterEngine()
103 | _, err := e.Id(id).Get(resource)
104 | if err != nil {
105 | err.Error()
106 | return
107 | }
108 |
109 | return
110 | }
111 |
112 | // ===== 根据父id查询当前级别菜单最大序号
113 | func GetResourceMaxOrderByParentId(parentId string) (int64, error) {
114 | e := db.MasterEngine()
115 |
116 | sql := "SELECT MAX(ur.resource_order) AS maxOrder FROM cd_sys_user_resource ur WHERE ur.parent_id = '" + parentId + "'"
117 | s := e.SQL(sql)
118 | re, err := s.QueryString(sql)
119 | if err != nil || len(re) == 0 {
120 | return int64(0), err
121 | }
122 | if re[0]["maxOrder"] == "" {
123 | return int64(0), nil
124 | }
125 | maxOrder, err := strconv.ParseInt(re[0]["maxOrder"], 10, 64)
126 |
127 | return maxOrder, err
128 | }
129 |
130 | // ===== 根据父id查询当前菜单级别
131 | func GetResourceLevelByParentId(parentId string) (int64, error) {
132 | e := db.MasterEngine()
133 |
134 | sql := "SELECT MAX(ur.resource_level) AS parentLevel FROM cd_sys_user_resource ur WHERE ur.id = '" + parentId + "'"
135 | s := e.SQL(sql)
136 | re, err := s.QueryString(sql)
137 | if err != nil || len(re) == 0 {
138 | return int64(0), err
139 | }
140 | level, err := strconv.ParseInt(re[0]["parentLevel"], 10, 64)
141 |
142 | return level, err
143 | }
144 |
145 | // ===== 根据用户Id获取该用户所拥有的菜单
146 | func GetResourceByUserId(uId string) ([]*Resource, error) {
147 | e := db.MasterEngine()
148 | sql := fmt.Sprintf(" SELECT * FROM cd_sys_user_resource ur "+
149 | " WHERE ur.id IN ( SELECT urr.resource_id FROM cd_sys_user_role_resource urr "+
150 | " WHERE urr.role_id IN ( SELECT uur.role_id FROM cd_sys_user_user_role uur "+
151 | " WHERE uur.user_id = '%s' ) ) "+
152 | " AND ur.resource_type = 0 "+
153 | " AND ur.is_deleted = 0 "+
154 | " ORDER BY ur.resource_order ASC", uId)
155 |
156 | result := make([]*Resource, 0)
157 | err := e.SQL(sql).Find(&result)
158 |
159 | return result, err
160 | }
161 |
--------------------------------------------------------------------------------
/perm-vue/src/components/common/Tags.vue:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
98 |
99 |
100 |
172 |
--------------------------------------------------------------------------------
/perm-vue/src/components/page/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
后台管理系统
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
14 |
15 |
16 |
17 |
18 | 登录
19 |
20 |
21 |
22 |
23 |
24 |
25 |
96 |
97 |
--------------------------------------------------------------------------------
/perm-vue/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const webpack = require('webpack')
5 | const config = require('../config')
6 | const merge = require('webpack-merge')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
13 |
14 | const env = require('../config/prod.env')
15 |
16 | const webpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({
19 | sourceMap: config.build.productionSourceMap,
20 | extract: true,
21 | usePostCSS: true
22 | })
23 | },
24 | devtool: config.build.productionSourceMap ? config.build.devtool : false,
25 | output: {
26 | path: config.build.assetsRoot,
27 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
28 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
29 | },
30 | plugins: [
31 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
32 | new webpack.DefinePlugin({
33 | 'process.env': env
34 | }),
35 | new UglifyJsPlugin({
36 | uglifyOptions: {
37 | compress: {
38 | warnings: false
39 | }
40 | },
41 | sourceMap: config.build.productionSourceMap,
42 | parallel: true
43 | }),
44 | // extract css into its own file
45 | new ExtractTextPlugin({
46 | filename: utils.assetsPath('css/[name].[contenthash].css'),
47 | // Setting the following option to `false` will not extract CSS from codesplit chunks.
48 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
49 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
50 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
51 | allChunks: true,
52 | }),
53 | // Compress extracted CSS. We are using this plugin so that possible
54 | // duplicated CSS from different components can be deduped.
55 | new OptimizeCSSPlugin({
56 | cssProcessorOptions: config.build.productionSourceMap
57 | ? { safe: true, map: { inline: false } }
58 | : { safe: true }
59 | }),
60 | // generate dist index.html with correct asset hash for caching.
61 | // you can customize output by editing /index.html
62 | // see https://github.com/ampedandwired/html-webpack-plugin
63 | new HtmlWebpackPlugin({
64 | filename: config.build.index,
65 | template: 'index.html',
66 | inject: true,
67 | minify: {
68 | removeComments: true,
69 | collapseWhitespace: true,
70 | removeAttributeQuotes: true
71 | // more options:
72 | // https://github.com/kangax/html-minifier#options-quick-reference
73 | },
74 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
75 | chunksSortMode: 'dependency'
76 | }),
77 | // keep module.id stable when vender modules does not change
78 | new webpack.HashedModuleIdsPlugin(),
79 | // enable scope hoisting
80 | new webpack.optimize.ModuleConcatenationPlugin(),
81 | // split vendor js into its own file
82 | new webpack.optimize.CommonsChunkPlugin({
83 | name: 'vendor',
84 | minChunks (module) {
85 | // any required modules inside node_modules are extracted to vendor
86 | return (
87 | module.resource &&
88 | /\.js$/.test(module.resource) &&
89 | module.resource.indexOf(
90 | path.join(__dirname, '../node_modules')
91 | ) === 0
92 | )
93 | }
94 | }),
95 | // extract webpack runtime and module manifest to its own file in order to
96 | // prevent vendor hash from being updated whenever app bundle is updated
97 | new webpack.optimize.CommonsChunkPlugin({
98 | name: 'manifest',
99 | minChunks: Infinity
100 | }),
101 | // This instance extracts shared chunks from code splitted chunks and bundles them
102 | // in a separate chunk, similar to the vendor chunk
103 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
104 | new webpack.optimize.CommonsChunkPlugin({
105 | name: 'app',
106 | async: 'vendor-async',
107 | children: true,
108 | minChunks: 3
109 | }),
110 |
111 | // copy custom static assets
112 | new CopyWebpackPlugin([
113 | {
114 | from: path.resolve(__dirname, '../static'),
115 | to: config.build.assetsSubDirectory,
116 | ignore: ['.*']
117 | }
118 | ])
119 | ]
120 | })
121 |
122 | if (config.build.productionGzip) {
123 | const CompressionWebpackPlugin = require('compression-webpack-plugin')
124 |
125 | webpackConfig.plugins.push(
126 | new CompressionWebpackPlugin({
127 | asset: '[path].gz[query]',
128 | algorithm: 'gzip',
129 | test: new RegExp(
130 | '\\.(' +
131 | config.build.productionGzipExtensions.join('|') +
132 | ')$'
133 | ),
134 | threshold: 10240,
135 | minRatio: 0.8
136 | })
137 | )
138 | }
139 |
140 | if (config.build.bundleAnalyzerReport) {
141 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
142 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
143 | }
144 |
145 | module.exports = webpackConfig
146 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/vo/uservo/resource_vo.go:
--------------------------------------------------------------------------------
1 | package uservo
2 |
3 | import (
4 | "permissionManage/perm-server/sys-common/models/baseModel"
5 | "permissionManage/perm-server/sys-common/vo"
6 | "permissionManage/perm-server/sys-sysbase/models/user"
7 | "time"
8 | )
9 |
10 | // 前端需要的数据结构
11 | type ResourceVO struct {
12 | Id string `json:"id"`
13 | CreateTime time.Time `json:"createTime"`
14 | CreatorDepartmentId string `json:"creatorDepartmentId"`
15 | CreatorDepartmentName string `json:"creatorDepartmentName"`
16 | CreatorId string `json:"creatorId"`
17 | CreatorName string `json:"creatorName"`
18 | IsDeleted int64 `json:"isDeleted"`
19 | UpdateTime time.Time `json:"updateTime"`
20 | UpdatorDepartmentId string `json:"updatorDepartmentId"`
21 | UpdatorDepartmentName string `json:"updatorDepartmentName"`
22 | UpdatorId string `json:"updatorId"`
23 | UpdatorName string `json:"updatorName"`
24 | Version int64 `json:"version"`
25 |
26 | ResourceType string `json:"resourceType"`
27 | ResourceName string `json:"resourceName"`
28 | ResourceLevel int64 `json:"resourceLevel"`
29 | ResourceOrder int64 `json:"resourceOrder"`
30 | ResourceSate int64 `json:"resourceSate"`
31 | ParentId string `json:"parentId"`
32 | Url string `json:"url"`
33 | Icon string `json:"icon"`
34 | Description string `json:"description"`
35 | }
36 |
37 | // 请求参数
38 | type ResourceParamVo struct {
39 | *baseModel.CurrentUser
40 | baseModel.BaseModel
41 | *vo.PageVo
42 | Id string `json:"id"`
43 | UserId string `json:"userId"`
44 | ResourceType string `json:"resourceType"`
45 | ResourceName string `json:"resourceName"`
46 | ResourceLevel int64 `json:"resourceLevel"`
47 | ResourceOrder int64 `json:"resourceOrder"`
48 | ResourceSate int64 `json:"resourceSate"`
49 | ParentId string `json:"parentId"`
50 | Url string `json:"url"`
51 | Icon string `json:"icon"`
52 | Description string `json:"description"`
53 | Token string `json:"token"`
54 |
55 | Ids string `json:"ids"` //批量删除入参
56 | }
57 |
58 | // 树结构数据
59 | type ResourceTreeVo struct {
60 | Id string `json:"id"`
61 | ParentId string `json:"parentId"`
62 | ResourceName string `json:"title"`
63 | Url string `json:"index"`
64 | Icon string `json:"icon"`
65 | Subs []*ResourceTreeVo `json:"subs"`
66 | Children []*ResourceTreeVo `json:"children"`
67 | Label string `json:"label"`
68 | }
69 |
70 | // 列表数据结构
71 | type ResourceListVo struct {
72 | Id string `json:"id"`
73 | ResourceType string `json:"resourceType"`
74 | ResourceName string `json:"resourceName"`
75 | ResourceLevel int64 `json:"resourceLevel"`
76 | ResourceOrder int64 `json:"resourceOrder"`
77 | ResourceSate int64 `json:"resourceSate"`
78 | ParentId string `json:"parentId"`
79 | Url string `json:"url"`
80 | Icon string `json:"icon"`
81 | Description string `json:"description"`
82 | }
83 |
84 | // 用户列表,不带token
85 | func ResourceToResourceTreeVo(resource *user.Resource) (rtVo *ResourceTreeVo) {
86 | rtVo = new(ResourceTreeVo)
87 | rtVo.Id = resource.Id
88 | rtVo.ParentId = resource.ParentId
89 | rtVo.ResourceName = resource.ResourceName
90 | rtVo.Url = resource.Url
91 | rtVo.Icon = resource.Icon
92 | rtVo.Label = resource.ResourceName
93 | //golog.Infof("%s", rtVo)
94 | return
95 | }
96 |
97 | func ResourceToResourceTreeVos(resources []*user.Resource) (rtVos []*ResourceTreeVo) {
98 | for _, r := range resources {
99 | rtVo := ResourceToResourceTreeVo(r)
100 | rtVos = append(rtVos, rtVo)
101 | }
102 | return
103 | }
104 |
105 | func ResourceToResourceListVo(resource *user.Resource) (rtVo *ResourceListVo) {
106 | rtVo = new(ResourceListVo)
107 | rtVo.Id = resource.Id
108 | rtVo.ResourceType = resource.ResourceType
109 | rtVo.ResourceName = resource.ResourceName
110 | rtVo.ResourceLevel = resource.ResourceLevel
111 | rtVo.ResourceLevel = resource.ResourceLevel
112 | rtVo.ResourceOrder = resource.ResourceOrder
113 | rtVo.ResourceSate = resource.ResourceSate
114 | rtVo.ParentId = resource.ParentId
115 | rtVo.Url = resource.Url
116 | rtVo.Icon = resource.Icon
117 | rtVo.Description = resource.Description
118 | //golog.Infof("%s", rtVo)
119 | return
120 | }
121 |
122 | func ResourceToResourceListVos(resources []*user.Resource) (rtVos []*ResourceListVo) {
123 | for _, r := range resources {
124 | rtVo := ResourceToResourceListVo(r)
125 | rtVos = append(rtVos, rtVo)
126 | }
127 | return
128 | }
129 |
130 | func ResourceParamVoToResource(rp *ResourceParamVo) (result *user.Resource) {
131 | currentUser := rp.CurrentUser
132 | if rp.Id != "" {
133 | result = user.FindResourceById(rp.Id)
134 | result.UpdatorId = currentUser.UserAccount
135 | result.UpdatorName = currentUser.UserName
136 | result.UpdatorDepartmentId = currentUser.DepartmentId
137 | result.UpdatorDepartmentName = currentUser.DepartmentName
138 | } else {
139 | result = new(user.Resource)
140 | result.CreatorId = currentUser.UserAccount
141 | result.CreatorName = currentUser.UserName
142 | result.CreatorDepartmentId = currentUser.DepartmentId
143 | result.CreatorDepartmentName = currentUser.DepartmentName
144 |
145 | result.ResourceLevel = rp.ResourceLevel
146 | result.ResourceOrder = rp.ResourceOrder
147 | result.ResourceSate = rp.ResourceSate
148 | }
149 | result.ResourceType = "0"
150 | result.ResourceName = rp.ResourceName
151 | result.ParentId = rp.ParentId
152 | result.Url = rp.Url
153 | result.Icon = rp.Icon
154 | result.Description = rp.Description
155 |
156 | return
157 | }
158 |
--------------------------------------------------------------------------------
/perm-vue/src/components/page/demo/Tabs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | tab选项卡
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{scope.row.title}}
15 |
16 |
17 |
18 |
19 |
20 | 标为已读
21 |
22 |
23 |
24 |
25 | 全部标为已读
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | {{scope.row.title}}
34 |
35 |
36 |
37 |
38 |
39 | 删除
40 |
41 |
42 |
43 |
44 | 删除全部
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | {{scope.row.title}}
54 |
55 |
56 |
57 |
58 |
59 | 还原
60 |
61 |
62 |
63 |
64 | 清空回收站
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
120 |
121 |
129 |
130 |
--------------------------------------------------------------------------------
/perm-vue/src/components/page/demo/DragList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 拖拽排序
6 |
7 |
8 |
9 |
10 | Vue.Draggable:基于 Sortable.js 的 Vue 拖拽组件。
11 | 访问地址:
Vue.Draggable
12 |
13 |
14 |
15 |
todo
16 |
17 |
18 |
19 | {{item.content}}
20 |
21 |
22 |
23 |
24 |
25 |
doing
26 |
27 |
28 |
29 | {{item.content}}
30 |
31 |
32 |
33 |
34 |
35 |
done
36 |
37 |
38 |
39 | {{item.content}}
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
108 |
109 |
165 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/routes/user/department_route.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "github.com/kataras/iris/v12"
5 | "github.com/kataras/iris/v12/hero"
6 | "permissionManage/perm-server/sys-common/models/baseModel"
7 | "permissionManage/perm-server/sys-common/supports"
8 | "permissionManage/perm-server/sys-common/supports/commonConst"
9 | "permissionManage/perm-server/sys-common/supports/responseHandle"
10 | "permissionManage/perm-server/sys-sysbase/service/userService"
11 | "permissionManage/perm-server/sys-sysbase/vo/uservo"
12 | )
13 |
14 | func DepartmentHub(party iris.Party) {
15 | var menu = party.Party("/department") //菜单管理
16 |
17 | menu.Post("/addDepartment", hero.Handler(AddDepartment)) // 添加部门
18 | menu.Post("/updateDepartment", hero.Handler(UpdateDepartment)) // 更新部门
19 | menu.Post("/isDepartmentCanDelete", hero.Handler(IsDepartmentCanDelete)) // 删除部门
20 | menu.Post("/deleteDepartment", hero.Handler(DeleteDepartment)) // 删除部门
21 |
22 | menu.Post("/findDepartmentList", hero.Handler(FindDepartmentList)) // 列表
23 | menu.Post("/findDepartmentPages", hero.Handler(FindDepartmentPages)) // 分页
24 | menu.Post("/findDepartmentTreeAll", hero.Handler(FindDepartmentTreeAll)) // 获取菜单树带根
25 | }
26 |
27 | //============================= 新增 =========================================
28 | func AddDepartment(ctx iris.Context) {
29 | var (
30 | err error
31 | paramRVo = new(uservo.DepartmentParamVo)
32 | res *supports.SimResult
33 | )
34 |
35 | if err = ctx.ReadJSON(¶mRVo); err != nil {
36 | ctx.Application().Logger().Errorf("", supports.PARAM_IS_EMPTY, err.Error())
37 | supports.Error(ctx, iris.StatusBadRequest, supports.PARAM_IS_EMPTY, nil)
38 | return
39 | }
40 | paramRVo.CurrentUser = baseModel.GetCurrentUset(ctx.Params().Get(commonConst.CURRENT_USER_KEY))
41 |
42 | res = userService.CreateDepartment(paramRVo)
43 |
44 | responseHandle.Response(ctx, res)
45 | }
46 |
47 | //============================= 更新 =========================================
48 | func UpdateDepartment(ctx iris.Context) {
49 | var (
50 | err error
51 | paramRVo = new(uservo.DepartmentParamVo)
52 | res *supports.SimResult
53 | )
54 |
55 | if err = ctx.ReadJSON(¶mRVo); err != nil {
56 | ctx.Application().Logger().Errorf("", supports.PARAM_IS_EMPTY, err.Error())
57 | supports.Error(ctx, iris.StatusBadRequest, supports.PARAM_IS_EMPTY, nil)
58 | return
59 | }
60 | paramRVo.CurrentUser = baseModel.GetCurrentUset(ctx.Params().Get(commonConst.CURRENT_USER_KEY))
61 |
62 | res = userService.UpdateDepartment(paramRVo)
63 |
64 | responseHandle.Response(ctx, res)
65 | }
66 |
67 | //============================= 确认是否能删除 =========================================
68 | func IsDepartmentCanDelete(ctx iris.Context) {
69 | var (
70 | err error
71 | paramRVo = new(uservo.DepartmentParamVo)
72 | res *supports.SimResult
73 | )
74 |
75 | if err = ctx.ReadJSON(¶mRVo); err != nil || paramRVo.Id == "" {
76 | ctx.Application().Logger().Errorf("", supports.PARAM_IS_EMPTY, err.Error())
77 | supports.Error(ctx, iris.StatusBadRequest, supports.PARAM_IS_EMPTY, nil)
78 | return
79 | }
80 |
81 | res = userService.IsDepartmentCanDelete(paramRVo)
82 |
83 | responseHandle.Response(ctx, res)
84 | }
85 |
86 | //============================= 删除 =========================================
87 | func DeleteDepartment(ctx iris.Context) {
88 | var (
89 | err error
90 | paramRVo = new(uservo.DepartmentParamVo)
91 | res *supports.SimResult
92 | )
93 |
94 | if err = ctx.ReadJSON(¶mRVo); err != nil || paramRVo.Ids == "" {
95 | ctx.Application().Logger().Errorf("", supports.PARAM_IS_EMPTY, err.Error())
96 | supports.Error(ctx, iris.StatusBadRequest, supports.PARAM_IS_EMPTY, nil)
97 | return
98 | }
99 |
100 | res = userService.DeleteDepartment(paramRVo)
101 |
102 | responseHandle.Response(ctx, res)
103 | }
104 |
105 | // 获取菜单资源列表
106 | func FindDepartmentPages(ctx iris.Context) {
107 | var (
108 | err error
109 | paramRVo = new(uservo.DepartmentParamVo)
110 | )
111 |
112 | if err = ctx.ReadJSON(¶mRVo); err != nil {
113 | ctx.Application().Logger().Errorf("", supports.PARAM_IS_EMPTY, err.Error())
114 | supports.Error(ctx, iris.StatusBadRequest, supports.PARAM_IS_EMPTY, nil)
115 | return
116 | }
117 |
118 | res := userService.FindDepartmentPages(paramRVo)
119 | if res == nil {
120 | supports.Ok(ctx, "", "")
121 | return
122 | }
123 |
124 | if !res.Code {
125 | supports.Error(ctx, iris.StatusInternalServerError, res.Msg, nil)
126 | return
127 | }
128 |
129 | supports.Ok(ctx, res.Msg, res.Data)
130 | }
131 |
132 | func FindDepartmentList(ctx iris.Context) {
133 | var (
134 | err error
135 | paramRVo = new(uservo.DepartmentParamVo)
136 | )
137 |
138 | if err = ctx.ReadJSON(¶mRVo); err != nil {
139 | ctx.Application().Logger().Errorf("", supports.PARAM_IS_EMPTY, err.Error())
140 | supports.Error(ctx, iris.StatusBadRequest, supports.PARAM_IS_EMPTY, nil)
141 | return
142 | }
143 |
144 | tmpRes := userService.FindDepartmentList(paramRVo)
145 | if !tmpRes.Code {
146 | ctx.Application().Logger().Errorf("", tmpRes.Msg, err.Error())
147 | supports.Error(ctx, iris.StatusInternalServerError, tmpRes.Msg, nil)
148 | return
149 | }
150 |
151 | supports.Ok(ctx, tmpRes.Msg, tmpRes.Data)
152 |
153 | return
154 | }
155 |
156 | // 获取菜单树
157 | func FindDepartmentTreeAll(ctx iris.Context) {
158 | var (
159 | err error
160 | paramRVo = new(uservo.DepartmentParamVo)
161 | )
162 |
163 | if err = ctx.ReadJSON(¶mRVo); err != nil {
164 | ctx.Application().Logger().Errorf("", supports.PARAM_IS_EMPTY, err.Error())
165 | supports.Error(ctx, iris.StatusBadRequest, supports.PARAM_IS_EMPTY, nil)
166 | return
167 | }
168 |
169 | res := userService.FindDepartmentTreeAll(paramRVo)
170 | responseHandle.Response(ctx, res)
171 | }
172 |
--------------------------------------------------------------------------------
/perm-vue/src/components/page/demo/BaseForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 表单
6 | 基本表单
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | -
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | 表单提交
56 | 取消
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/routes/user/resource_route.go:
--------------------------------------------------------------------------------
1 | package user
2 |
3 | import (
4 | "github.com/kataras/iris/v12"
5 | "github.com/kataras/iris/v12/hero"
6 | "permissionManage/perm-server/sys-common/models/baseModel"
7 | "permissionManage/perm-server/sys-common/supports"
8 | "permissionManage/perm-server/sys-common/supports/commonConst"
9 | "permissionManage/perm-server/sys-common/supports/responseHandle"
10 | "permissionManage/perm-server/sys-sysbase/service/userService"
11 | userVO "permissionManage/perm-server/sys-sysbase/vo/uservo"
12 | )
13 |
14 | func ResoureHub(party iris.Party) {
15 | var menu = party.Party("/resoure") //菜单管理
16 |
17 | menu.Post("/addResource", hero.Handler(AddResource)) // 添加资源
18 | menu.Post("/updateResource", hero.Handler(UpdateResource)) // 更新资源
19 | menu.Post("/deleteResource", hero.Handler(DeleteResource)) // 删除资源
20 |
21 | menu.Post("/findResourceList", hero.Handler(FindResourceList)) // 给角色添加权限
22 | menu.Post("/findResourceTree", hero.Handler(FindResourceTree)) // 给角色添加权限
23 | menu.Post("/findResourceTreeAll", hero.Handler(FindResourceTreeAll)) // 获取菜单树带根
24 | menu.Post("/findResourceTreeAllWithoutRoot", hero.Handler(FindResourceTreeAllWithoutRoot)) // 获取菜单树不带带根
25 | menu.Post("/findPagesResource", hero.Handler(FindPagesResource)) // 给角色添加权限
26 | }
27 |
28 | //============================= 新增 =========================================
29 | func AddResource(ctx iris.Context) {
30 | var (
31 | err error
32 | paramRVo = new(userVO.ResourceParamVo)
33 | res *supports.SimResult
34 | )
35 |
36 | if err = ctx.ReadJSON(¶mRVo); err != nil {
37 | ctx.Application().Logger().Errorf("", supports.PARAM_IS_EMPTY, err.Error())
38 | supports.Error(ctx, iris.StatusBadRequest, supports.PARAM_IS_EMPTY, nil)
39 | return
40 | }
41 | paramRVo.CurrentUser = baseModel.GetCurrentUset(ctx.Params().Get(commonConst.CURRENT_USER_KEY))
42 |
43 | res = userService.CreateResource(paramRVo)
44 |
45 | responseHandle.Response(ctx, res)
46 | }
47 |
48 | //============================= 更新 =========================================
49 | func UpdateResource(ctx iris.Context) {
50 | var (
51 | err error
52 | paramRVo = new(userVO.ResourceParamVo)
53 | res *supports.SimResult
54 | )
55 |
56 | if err = ctx.ReadJSON(¶mRVo); err != nil {
57 | ctx.Application().Logger().Errorf("", supports.PARAM_IS_EMPTY, err.Error())
58 | supports.Error(ctx, iris.StatusBadRequest, supports.PARAM_IS_EMPTY, nil)
59 | return
60 | }
61 | paramRVo.CurrentUser = baseModel.GetCurrentUset(ctx.Params().Get(commonConst.CURRENT_USER_KEY))
62 |
63 | res = userService.UpdateResource(paramRVo)
64 |
65 | responseHandle.Response(ctx, res)
66 | }
67 |
68 | //============================= 删除 =========================================
69 | func DeleteResource(ctx iris.Context) {
70 | var (
71 | err error
72 | paramRVo = new(userVO.ResourceParamVo)
73 | res *supports.SimResult
74 | )
75 |
76 | if err = ctx.ReadJSON(¶mRVo); err != nil || paramRVo.Ids == "" {
77 | ctx.Application().Logger().Errorf("", supports.PARAM_IS_EMPTY, err.Error())
78 | supports.Error(ctx, iris.StatusBadRequest, supports.PARAM_IS_EMPTY, nil)
79 | return
80 | }
81 |
82 | res = userService.DeleteResource(paramRVo)
83 |
84 | responseHandle.Response(ctx, res)
85 | }
86 |
87 | //============================= 获取菜单资源列表 =========================================
88 | func FindResourceList(ctx iris.Context) {
89 | var (
90 | err error
91 | paramRVo = new(userVO.ResourceParamVo)
92 | res *supports.SimResult
93 | )
94 |
95 | if err = ctx.ReadJSON(¶mRVo); err != nil {
96 | ctx.Application().Logger().Errorf("用户id为空", "", err.Error())
97 | supports.Error(ctx, iris.StatusBadRequest, "用户id为空", nil)
98 | return
99 | }
100 |
101 | res = userService.FindResourceListByUser(paramRVo)
102 |
103 | responseHandle.Response(ctx, res)
104 | }
105 |
106 | //============================= 获取用户所拥有菜单 =========================================
107 | func FindResourceTree(ctx iris.Context) {
108 | var (
109 | err error
110 | paramRVo = new(userVO.ResourceParamVo)
111 | res *supports.SimResult
112 | )
113 |
114 | if err = ctx.ReadJSON(¶mRVo); err != nil {
115 | ctx.Application().Logger().Errorf("用户id为空", "", err.Error())
116 | supports.Error(ctx, iris.StatusBadRequest, "用户id为空", nil)
117 | return
118 | }
119 |
120 | res = userService.FindResourceTreeByUser(paramRVo)
121 |
122 | responseHandle.Response(ctx, res)
123 |
124 | }
125 |
126 | func FindPagesResource(ctx iris.Context) {
127 | var (
128 | err error
129 | paramRVo = new(userVO.ResourceParamVo)
130 | )
131 |
132 | if err = ctx.ReadJSON(¶mRVo); err != nil {
133 | ctx.Application().Logger().Errorf("用户id为空", "", err.Error())
134 | supports.Error(ctx, iris.StatusBadRequest, "用户id为空", nil)
135 | return
136 | }
137 |
138 | tmpRes := userService.FindPagesResource(paramRVo)
139 | if !tmpRes.Code {
140 | ctx.Application().Logger().Errorf("用户id为空", "", err.Error())
141 | return
142 | }
143 |
144 | supports.Ok(ctx, tmpRes.Msg, tmpRes.Data)
145 |
146 | return
147 | }
148 |
149 | // 获取菜单树
150 | func FindResourceTreeAll(ctx iris.Context) {
151 | var (
152 | err error
153 | paramRVo = new(userVO.ResourceParamVo)
154 | subRtVo []*userVO.ResourceTreeVo
155 | rtVo *userVO.ResourceTreeVo
156 | )
157 |
158 | if err = ctx.ReadJSON(¶mRVo); err != nil {
159 | ctx.Application().Logger().Errorf("用户id为空", "", err.Error())
160 | supports.Error(ctx, iris.StatusBadRequest, "用户id为空", nil)
161 | return
162 | }
163 |
164 | subRtVo, res := userService.FindResourceTreeAll(paramRVo)
165 | if res == nil {
166 | supports.Ok(ctx, "", "")
167 | return
168 | }
169 |
170 | if !res.Code {
171 | supports.Error(ctx, iris.StatusBadRequest, res.Msg, nil)
172 | return
173 | }
174 |
175 | rtVo = &userVO.ResourceTreeVo{
176 | Id: "0",
177 | ParentId: "-1",
178 | ResourceName: "总菜单",
179 | Subs: subRtVo,
180 | Children: subRtVo,
181 | Label: "总菜单",
182 | }
183 | supports.Ok(ctx, res.Msg, rtVo)
184 | }
185 |
186 | func FindResourceTreeAllWithoutRoot(ctx iris.Context) {
187 | var (
188 | err error
189 | paramRVo = new(userVO.ResourceParamVo)
190 | subRtVo []*userVO.ResourceTreeVo
191 | )
192 |
193 | if err = ctx.ReadJSON(¶mRVo); err != nil {
194 | ctx.Application().Logger().Errorf("用户id为空", "", err.Error())
195 | supports.Error(ctx, iris.StatusBadRequest, "用户id为空", nil)
196 | return
197 | }
198 |
199 | subRtVo, res := userService.FindResourceTreeAll(paramRVo)
200 | res = &supports.SimResult{
201 | Code: res.Code,
202 | Msg: res.Msg,
203 | Data: subRtVo,
204 | }
205 | responseHandle.Response(ctx, res)
206 | }
207 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/service/userService/role_service.go:
--------------------------------------------------------------------------------
1 | package userService
2 |
3 | import (
4 | "fmt"
5 | "permissionManage/perm-server/sys-common/db"
6 | "permissionManage/perm-server/sys-common/supports"
7 | "permissionManage/perm-server/sys-common/vo"
8 | "permissionManage/perm-server/sys-sysbase/models/user"
9 | "permissionManage/perm-server/sys-sysbase/vo/uservo"
10 | "strings"
11 | )
12 |
13 | //============================= 新增 =========================================
14 | func CreateRole(paramVo *uservo.RoleParamVo) (res *supports.SimResult) {
15 | role := uservo.RoleParamVoToRole(paramVo)
16 |
17 | _, err := user.CreateRole(role)
18 | if err != nil {
19 | res = &supports.SimResult{
20 | Code: false,
21 | Msg: supports.ADD_FAIL,
22 | }
23 | }
24 |
25 | res = &supports.SimResult{
26 | Code: true,
27 | Msg: supports.ADD_SUCCESS,
28 | }
29 |
30 | return
31 | }
32 |
33 | //============================= 更新 =========================================
34 | func UpdateRole(paramVo *uservo.RoleParamVo) (res *supports.SimResult) {
35 | eModel := uservo.RoleParamVoToRole(paramVo)
36 | _, err := user.UpdateRole(eModel)
37 | if err != nil {
38 | err.Error()
39 | res = &supports.SimResult{
40 | Code: false,
41 | Msg: supports.UPDATE_FAIL,
42 | }
43 | return
44 | }
45 |
46 | res = &supports.SimResult{
47 | Code: true,
48 | Msg: supports.UPDATE_SUCCESS,
49 | }
50 |
51 | return
52 | }
53 |
54 | //============================= 删除 =========================================
55 | func DeleteRole(paramVo *uservo.RoleParamVo) (res *supports.SimResult) {
56 | idsStr := paramVo.Ids
57 | _, err := user.DeleteRoleByIds(strings.Split(idsStr, ","))
58 | if err != nil {
59 | err.Error()
60 | res = &supports.SimResult{
61 | Code: false,
62 | Msg: supports.DELETE_FAIL,
63 | }
64 | return
65 | }
66 |
67 | res = &supports.SimResult{
68 | Code: true,
69 | Msg: supports.DELETE_SUCCESS,
70 | }
71 |
72 | return
73 | }
74 |
75 | //============================= 查询 =========================================
76 | // 根据id查询
77 | func FindRoleById(roleParam *uservo.RoleParamVo) (res *supports.SimResult) {
78 | res = &supports.SimResult{
79 | Code: true,
80 | Data: uservo.RoleToRoleVo(user.FindRoleById(roleParam.Id)),
81 | }
82 | return
83 | }
84 | func FindRoleList(roleParam *uservo.RoleParamVo) (res *supports.SimResult) {
85 | e := db.MasterEngine()
86 | result := make([]*user.Role, 0)
87 |
88 | sql := fmt.Sprintf(" SELECT * FROM cd_sys_user_role ur " +
89 | " WHERE ur.is_deleted = false")
90 |
91 | err := e.SQL(sql).Find(&result)
92 | if err != nil {
93 | res = &supports.SimResult{
94 | Code: false,
95 | Msg: "",
96 | Data: nil,
97 | }
98 | return
99 | }
100 |
101 | res = &supports.SimResult{
102 | Code: true,
103 | Data: uservo.RoleToRoleListVos(result),
104 | }
105 |
106 | return
107 | }
108 |
109 | // 分页
110 | func FindRolePages(paramVo *uservo.RoleParamVo) (res *supports.SimResult) {
111 | e := db.MasterEngine()
112 | roleListVos := make([]*uservo.RoleListVo, 0)
113 | roles := make([]*user.Role, 0)
114 |
115 | pageParam := vo.GetPageParam(paramVo.PageVo)
116 |
117 | sql := " is_deleted = false "
118 | if paramVo.RoleName != "" {
119 | sql += " and role_name like '%" + paramVo.RoleName + "%'"
120 | }
121 | s := e.Where(sql).Limit(pageParam.PageSize, pageParam.Start)
122 | count, err := s.FindAndCount(&roles)
123 | if err != nil {
124 | res = &supports.SimResult{
125 | Code: false,
126 | Msg: supports.ADD_FAIL,
127 | }
128 | }
129 |
130 | roleListVos = uservo.RoleToRoleListVos(roles)
131 |
132 | pageResult := &vo.PageResult{
133 | CurrentPage: pageParam.CurrentPage,
134 | PageSize: pageParam.PageSize,
135 | Total: count,
136 | Data: roleListVos,
137 | }
138 | res = &supports.SimResult{
139 | Code: true,
140 | Msg: "",
141 | Data: pageResult,
142 | }
143 | return
144 | }
145 |
146 | // 查询角色所拥有的菜单
147 | func GetRoleResourceByRoleIds(paramVo *uservo.RoleParamVo) (res *supports.SimResult) {
148 | e := db.MasterEngine()
149 | sql := fmt.Sprintf("SELECT" +
150 | " ur.id" +
151 | " FROM cd_sys_user_resource ur" +
152 | " LEFT JOIN cd_sys_user_role_resource urr ON ur.id = urr.resource_id" +
153 | " WHERE ur.is_deleted = 0" +
154 | " AND ur.resource_type = '" + paramVo.ResourceType + "'" +
155 | " AND urr.role_id = '" + paramVo.Id + "'")
156 | tmpRes, err := e.QueryString(sql)
157 |
158 | if err != nil {
159 | err.Error()
160 | res = &supports.SimResult{
161 | Code: false,
162 | Msg: supports.ADD_FAIL,
163 | }
164 | }
165 | resArry := make([]string, 0)
166 | for _, tmp := range tmpRes {
167 | resArry = append(resArry, tmp["id"])
168 | }
169 |
170 | res = &supports.SimResult{
171 | Code: true,
172 | Data: resArry,
173 | }
174 | return
175 | }
176 |
177 | //============================= 角色资源关联关系 =========================================
178 | func FindRoluesByUserId(userId string) (res *supports.SimResult) {
179 | e := db.MasterEngine()
180 | result := make([]*user.Role, 0)
181 | sql := "SELECT * FROM cd_sys_user_role ur WHERE ur.id IN(SELECT uur.role_id FROM cd_sys_user_user_role uur WHERE uur.user_id = '" +
182 | "" + userId + "') AND ur.is_deleted = FALSE"
183 | err := e.SQL(sql).Find(&result)
184 | if err != nil {
185 | res = &supports.SimResult{
186 | Code: false,
187 | Msg: "",
188 | Data: nil,
189 | }
190 | return
191 | }
192 |
193 | res = &supports.SimResult{
194 | Code: true,
195 | Data: uservo.RoleToRoleListVos(result),
196 | }
197 |
198 | return
199 | }
200 |
201 | // 根据用户id查询用户未分配的角色
202 | func FindUnDistributeRoluesByUserId(userId string) (res *supports.SimResult) {
203 | e := db.MasterEngine()
204 | result := make([]*user.Role, 0)
205 | sql := "SELECT * FROM cd_sys_user_role ur WHERE ur.id NOT IN(SELECT uur.role_id FROM cd_sys_user_user_role uur WHERE uur.user_id = '" +
206 | "" + userId + "') AND ur.is_deleted = FALSE"
207 | err := e.SQL(sql).Find(&result)
208 | if err != nil {
209 | res = &supports.SimResult{
210 | Code: false,
211 | Msg: "",
212 | Data: nil,
213 | }
214 | return
215 | }
216 |
217 | res = &supports.SimResult{
218 | Code: true,
219 | Data: uservo.RoleToRoleListVos(result),
220 | }
221 |
222 | return
223 | }
224 |
225 | func CreateRoleResource(paramVo *uservo.RoleResourceParamVo) (res *supports.SimResult) {
226 | roleResource := uservo.RoleResourceParamVoToRoleResource(paramVo)
227 |
228 | // 删除现有的关系
229 | user.RemoveRoleResource(paramVo.RoleId)
230 | // 添加新的关系
231 | _, err := user.CreateRelationRoleResource(roleResource...)
232 | if err != nil {
233 | res = &supports.SimResult{
234 | Code: false,
235 | Msg: supports.ADD_FAIL,
236 | }
237 | }
238 |
239 | res = &supports.SimResult{
240 | Code: true,
241 | Msg: supports.ADD_SUCCESS,
242 | }
243 |
244 | return
245 | }
246 |
--------------------------------------------------------------------------------
/perm-server/sys-sysbase/service/userService/resource_service.go:
--------------------------------------------------------------------------------
1 | package userService
2 |
3 | import (
4 | "fmt"
5 | "github.com/kataras/golog"
6 | "permissionManage/perm-server/sys-common/db"
7 | "permissionManage/perm-server/sys-common/supports"
8 | "permissionManage/perm-server/sys-common/vo"
9 | "permissionManage/perm-server/sys-sysbase/models/user"
10 | "permissionManage/perm-server/sys-sysbase/vo/uservo"
11 | "strings"
12 | )
13 |
14 | func CreateResource(resourceParam *uservo.ResourceParamVo) (res *supports.SimResult) {
15 | resource := uservo.ResourceParamVoToResource(resourceParam)
16 | maxOrder, orderErr := user.GetResourceMaxOrderByParentId(resourceParam.ParentId)
17 | if orderErr != nil {
18 | orderErr.Error()
19 | res = &supports.SimResult{
20 | Code: false,
21 | Msg: supports.ADD_FAIL,
22 | }
23 | return
24 | }
25 | resource.ResourceOrder = maxOrder + 1
26 |
27 | if resourceParam.ParentId == "0" {
28 | resource.ResourceLevel = 1
29 | } else {
30 | level, levelErr := user.GetResourceLevelByParentId(resourceParam.ParentId)
31 | if levelErr != nil {
32 | levelErr.Error()
33 | res = &supports.SimResult{
34 | Code: false,
35 | Msg: supports.ADD_FAIL,
36 | }
37 | return
38 | }
39 | resource.ResourceLevel = level + 1
40 | }
41 |
42 | _, err := user.CreateResource(resource)
43 | if err != nil {
44 | err.Error()
45 | res = &supports.SimResult{
46 | Code: false,
47 | Msg: supports.ADD_FAIL,
48 | }
49 | return
50 | }
51 |
52 | res = &supports.SimResult{
53 | Code: true,
54 | Msg: supports.ADD_SUCCESS,
55 | }
56 |
57 | return
58 | }
59 |
60 | func UpdateResource(resourceParam *uservo.ResourceParamVo) (res *supports.SimResult) {
61 | resource := uservo.ResourceParamVoToResource(resourceParam)
62 | _, err := user.UpdateResource(resource)
63 | if err != nil {
64 | err.Error()
65 | res = &supports.SimResult{
66 | Code: false,
67 | Msg: supports.UPDATE_FAIL,
68 | }
69 | return
70 | }
71 |
72 | res = &supports.SimResult{
73 | Code: true,
74 | Msg: supports.UPDATE_SUCCESS,
75 | }
76 |
77 | return
78 | }
79 |
80 | func DeleteResource(resourceParam *uservo.ResourceParamVo) (res *supports.SimResult) {
81 | idsStr := resourceParam.Ids
82 | _, err := user.DeleteResourceByIds(strings.Split(idsStr, ","))
83 | if err != nil {
84 | err.Error()
85 | res = &supports.SimResult{
86 | Code: false,
87 | Msg: supports.DELETE_FAIL,
88 | }
89 | return
90 | }
91 |
92 | res = &supports.SimResult{
93 | Code: true,
94 | Msg: supports.DELETE_SUCCESS,
95 | }
96 |
97 | return
98 | }
99 |
100 | func FindResourceListByUser(resourceParam *uservo.ResourceParamVo) (res *supports.SimResult) {
101 | var (
102 | err error
103 | resourceList []*user.Resource
104 | )
105 | result := make([]*uservo.ResourceParamVo, 0)
106 |
107 | resourceList, err = user.GetResourceByUserId(resourceParam.UserId)
108 | if err != nil {
109 | err.Error()
110 | res = &supports.SimResult{
111 | Code: false,
112 | Msg: "",
113 | Data: result,
114 | }
115 | return
116 | }
117 |
118 | res = &supports.SimResult{
119 | Code: true,
120 | Data: uservo.ResourceToResourceListVos(resourceList),
121 | }
122 |
123 | return
124 | }
125 |
126 | // 构建 菜单 tree
127 | func FindResourceTreeByUser(resourceParam *uservo.ResourceParamVo) (res *supports.SimResult) {
128 | var (
129 | err error
130 | resourceList []*user.Resource
131 | )
132 |
133 | resourceList, err = user.GetResourceByUserId(resourceParam.UserId)
134 | if err != nil {
135 | err.Error()
136 | res = &supports.SimResult{
137 | Code: false,
138 | Msg: supports.QUERY_FAIL,
139 | }
140 | return
141 | }
142 | tmpRtVO := uservo.ResourceToResourceTreeVos(resourceList)
143 | rtVO := buildResourceTree(tmpRtVO)
144 | res = &supports.SimResult{
145 | Code: true,
146 | Msg: supports.LoginSuccess,
147 | Data: rtVO,
148 | }
149 |
150 | return
151 | }
152 | func FindResourceTreeAll(resourceParam *uservo.ResourceParamVo) (rtVO []*uservo.ResourceTreeVo, res *supports.SimResult) {
153 | var (
154 | err error
155 | resourceList []*user.Resource
156 | )
157 |
158 | resourceList, err = FindResourceList(resourceParam)
159 | if err != nil {
160 | err.Error()
161 | res = &supports.SimResult{
162 | Code: false,
163 | Msg: supports.ADD_FAIL,
164 | }
165 | return
166 | }
167 | tmpRtVO := uservo.ResourceToResourceTreeVos(resourceList)
168 | rtVO = buildResourceTree(tmpRtVO)
169 |
170 | res = &supports.SimResult{
171 | Code: true,
172 | Msg: "",
173 | Data: rtVO,
174 | }
175 | return
176 | }
177 |
178 | func buildResourceTree(resourceTreeVo []*uservo.ResourceTreeVo) (rtVO []*uservo.ResourceTreeVo) {
179 | for _, rt := range resourceTreeVo {
180 | subs := getSubResourceTree(rt.Id, resourceTreeVo)
181 | if subs == nil {
182 | if rt.ParentId == "0" {
183 | rtVO = append(rtVO, rt)
184 | }
185 | continue
186 | }
187 | rt.Subs = subs
188 | rt.Children = subs
189 | buildResourceTree(subs)
190 | if rt.ParentId == "0" {
191 | rtVO = append(rtVO, rt)
192 | }
193 | }
194 | return
195 | }
196 | func getSubResourceTree(parentId string, resourceTreeVoAll []*uservo.ResourceTreeVo) (rtVO []*uservo.ResourceTreeVo) {
197 | for _, rt := range resourceTreeVoAll {
198 | if rt.ParentId == parentId {
199 | rtVO = append(rtVO, rt)
200 | }
201 | }
202 |
203 | return
204 | }
205 |
206 | func FindResourceList(resourceParam *uservo.ResourceParamVo) (rs []*user.Resource, err error) {
207 | e := db.MasterEngine()
208 | result := make([]*user.Resource, 0)
209 |
210 | sql := fmt.Sprintf(" SELECT * FROM cd_sys_user_resource ur " +
211 | " WHERE ur.is_deleted = false")
212 |
213 | err = e.SQL(sql).Find(&result)
214 |
215 | return result, err
216 | }
217 |
218 | // 分页
219 | func FindPagesResource(paramVo *uservo.ResourceParamVo) (res *supports.SimResult) {
220 | e := db.MasterEngine()
221 | resourceListVos := make([]*uservo.ResourceListVo, 0)
222 | resources := make([]*user.Resource, 0)
223 |
224 | pageParam := vo.GetPageParam(paramVo.PageVo)
225 |
226 | sql := " is_deleted = false "
227 | if paramVo.ResourceName != "" {
228 | sql += " and resource_name like '%" + paramVo.ResourceName + "%'"
229 | }
230 | if paramVo.ResourceType != "" {
231 | sql += " and resource_type = '" + paramVo.ResourceType + "'"
232 | }
233 | s := e.Where(sql).Limit(pageParam.PageSize, pageParam.Start)
234 | count, err := s.FindAndCount(&resources)
235 |
236 | resourceListVos = uservo.ResourceToResourceListVos(resources)
237 |
238 | pageResult := &vo.PageResult{
239 | CurrentPage: pageParam.CurrentPage,
240 | PageSize: pageParam.PageSize,
241 | Total: count,
242 | Data: resourceListVos,
243 | }
244 | res = &supports.SimResult{
245 | Code: true,
246 | Msg: "",
247 | Data: pageResult,
248 | }
249 | golog.Println(count, err)
250 | return
251 | }
252 |
--------------------------------------------------------------------------------