add rule and deparment user_id
This commit is contained in:
parent
c5eade1523
commit
bcd8545930
33 changed files with 574 additions and 39 deletions
55
.vscode/launch.json
vendored
Normal file
55
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
{
|
||||||
|
// 使用 IntelliSense 了解相关属性。
|
||||||
|
// 悬停以查看现有属性的描述。
|
||||||
|
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Execute Designated process",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"program": "${workspaceFolder}/main.go",
|
||||||
|
"cwd": "/Users/juzhongsun/Works/yao-project",
|
||||||
|
"args": [
|
||||||
|
"run",
|
||||||
|
"yao.app.menu",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Launch Yao Project",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"program": "${workspaceFolder}/main.go",
|
||||||
|
"cwd": "/Users/juzhongsun/Works/yao-project",
|
||||||
|
"args": [
|
||||||
|
"start"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Launch Fabric Project",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"program": "${workspaceFolder}/main.go",
|
||||||
|
"cwd": "/Users/juzhongsun/Works/yao-fabric",
|
||||||
|
"args": [
|
||||||
|
"start"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Launch Fabric Process",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"program": "${workspaceFolder}/main.go",
|
||||||
|
"cwd": "/Users/juzhongsun/Works/yao-fabric",
|
||||||
|
"args": [
|
||||||
|
"run",
|
||||||
|
"models.crm.person.Get",
|
||||||
|
"::{\"withs\": {\"company\": { \"query\": { \"select\": [\"name\"] }}}, \"wheres\": [{\"rel\": \"company\", \"column\":\"name\", \"value\": \"绍兴市金桥纺织有限公司\"}]}"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
32
Makefile
32
Makefile
|
|
@ -283,7 +283,7 @@ release: clean
|
||||||
# ** XGEN will be renamed to DUI in the feature. and move to the new repository. **
|
# ** XGEN will be renamed to DUI in the feature. and move to the new repository. **
|
||||||
# ** new repository: https://github.com/YaoApp/dui.git **
|
# ** new repository: https://github.com/YaoApp/dui.git **
|
||||||
export NODE_ENV=production
|
export NODE_ENV=production
|
||||||
git clone https://github.com/YaoApp/xgen.git .tmp/xgen/v1.0
|
git clone https://github.com/sjzsdu/xgen.git .tmp/xgen/v1.0
|
||||||
# cd .tmp/xgen/v1.0 && git checkout 5002c3fded585aaa69a4366135b415ea3234964e
|
# cd .tmp/xgen/v1.0 && git checkout 5002c3fded585aaa69a4366135b415ea3234964e
|
||||||
echo "BASE=__yao_admin_root" > .tmp/xgen/v1.0/packages/xgen/.env
|
echo "BASE=__yao_admin_root" > .tmp/xgen/v1.0/packages/xgen/.env
|
||||||
cd .tmp/xgen/v1.0 && pnpm install --no-frozen-lockfile && pnpm run build
|
cd .tmp/xgen/v1.0 && pnpm install --no-frozen-lockfile && pnpm run build
|
||||||
|
|
@ -347,7 +347,7 @@ linux-release: clean
|
||||||
# ** XGEN will be renamed to DUI in the feature. and move to the new repository. **
|
# ** XGEN will be renamed to DUI in the feature. and move to the new repository. **
|
||||||
# ** new repository: https://github.com/YaoApp/dui.git **
|
# ** new repository: https://github.com/YaoApp/dui.git **
|
||||||
export NODE_ENV=production
|
export NODE_ENV=production
|
||||||
git clone https://github.com/YaoApp/xgen.git .tmp/xgen/v1.0
|
git clone https://github.com/sjzsdu/xgen.git .tmp/xgen/v1.0
|
||||||
rm -f .tmp/xgen/v1.0/pnpm-lock.yaml
|
rm -f .tmp/xgen/v1.0/pnpm-lock.yaml
|
||||||
echo "BASE=__yao_admin_root" > .tmp/xgen/v1.0/packages/xgen/.env
|
echo "BASE=__yao_admin_root" > .tmp/xgen/v1.0/packages/xgen/.env
|
||||||
cd .tmp/xgen/v1.0 && pnpm install --no-frozen-lockfile && pnpm run build
|
cd .tmp/xgen/v1.0 && pnpm install --no-frozen-lockfile && pnpm run build
|
||||||
|
|
@ -387,6 +387,34 @@ linux-release: clean
|
||||||
CGO_ENABLED=1 CGO_LDFLAGS="-static" go build -v -o dist/release/yao
|
CGO_ENABLED=1 CGO_LDFLAGS="-static" go build -v -o dist/release/yao
|
||||||
chmod +x dist/release/yao
|
chmod +x dist/release/yao
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: ubutu-release
|
||||||
|
ubutu-release: clean
|
||||||
|
mkdir -p dist/release
|
||||||
|
mkdir .tmp
|
||||||
|
# Checkout init
|
||||||
|
git clone https://github.com/YaoApp/yao-init.git .tmp/yao-init
|
||||||
|
rm -rf .tmp/yao-init/.git
|
||||||
|
rm -rf .tmp/yao-init/.gitignore
|
||||||
|
rm -rf .tmp/yao-init/LICENSE
|
||||||
|
rm -rf .tmp/yao-init/README.md
|
||||||
|
|
||||||
|
# Packing
|
||||||
|
mkdir -p .tmp/data/xgen
|
||||||
|
cp -r ./ui .tmp/data/ui
|
||||||
|
cp -r ./yao .tmp/data/yao
|
||||||
|
cp -r xgenDist .tmp/data/xgen/v1.0
|
||||||
|
cp -r .tmp/yao-init .tmp/data/init
|
||||||
|
go-bindata -fs -pkg data -o data/bindata.go -prefix ".tmp/data/" .tmp/data/...
|
||||||
|
rm -rf .tmp/data
|
||||||
|
rm -rf .tmp/xgen
|
||||||
|
|
||||||
|
# Making artifacts
|
||||||
|
mkdir -p dist
|
||||||
|
CGO_ENABLED=1 CGO_LDFLAGS="-static" go build -v -o dist/release/yao
|
||||||
|
chmod +x dist/release/yao
|
||||||
|
|
||||||
|
|
||||||
# make clean
|
# make clean
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"github.com/yaoapp/yao/pipe"
|
"github.com/yaoapp/yao/pipe"
|
||||||
"github.com/yaoapp/yao/plugin"
|
"github.com/yaoapp/yao/plugin"
|
||||||
"github.com/yaoapp/yao/query"
|
"github.com/yaoapp/yao/query"
|
||||||
|
"github.com/yaoapp/yao/rules"
|
||||||
"github.com/yaoapp/yao/runtime"
|
"github.com/yaoapp/yao/runtime"
|
||||||
"github.com/yaoapp/yao/schedule"
|
"github.com/yaoapp/yao/schedule"
|
||||||
"github.com/yaoapp/yao/script"
|
"github.com/yaoapp/yao/script"
|
||||||
|
|
@ -153,6 +154,12 @@ func Load(cfg config.Config, options LoadOption) (err error) {
|
||||||
printErr(cfg.Mode, "Plugin", err)
|
printErr(cfg.Mode, "Plugin", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load Rules
|
||||||
|
err = rules.Load(cfg)
|
||||||
|
if err != nil {
|
||||||
|
printErr(cfg.Mode, "Rules", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Load WASM Application (experimental)
|
// Load WASM Application (experimental)
|
||||||
|
|
||||||
// Load build-in widgets (table / form / chart / ...)
|
// Load build-in widgets (table / form / chart / ...)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package helper
|
package helper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
|
@ -191,59 +192,80 @@ func NewArrayTreeOption(option map[string]interface{}) ArrayTreeOption {
|
||||||
// ArrayTree []map[string]interface{} 转树形结构
|
// ArrayTree []map[string]interface{} 转树形结构
|
||||||
func ArrayTree(records []map[string]interface{}, setting map[string]interface{}) []map[string]interface{} {
|
func ArrayTree(records []map[string]interface{}, setting map[string]interface{}) []map[string]interface{} {
|
||||||
opt := NewArrayTreeOption(setting)
|
opt := NewArrayTreeOption(setting)
|
||||||
return opt.Tree(records)
|
res, err := opt.Tree(records)
|
||||||
|
if err == nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tree Array 转换为 Tree
|
func (opt ArrayTreeOption) Tree(records []map[string]interface{}) ([]map[string]interface{}, error) {
|
||||||
func (opt ArrayTreeOption) Tree(records []map[string]interface{}) []map[string]interface{} {
|
|
||||||
|
|
||||||
mapping := map[string]map[string]interface{}{}
|
mapping := map[string]map[string]interface{}{}
|
||||||
for i := range records {
|
recordOrder := []string{}
|
||||||
if key, has := records[i][opt.Key]; has {
|
|
||||||
|
for _, record := range records {
|
||||||
|
key, hasKey := record[opt.Key]
|
||||||
|
if !hasKey {
|
||||||
|
return nil, errors.New("missing key field")
|
||||||
|
}
|
||||||
|
|
||||||
primary := fmt.Sprintf("%v", key)
|
primary := fmt.Sprintf("%v", key)
|
||||||
mapping[primary] = map[string]interface{}{}
|
mapping[primary] = make(map[string]interface{})
|
||||||
mapping[primary][opt.Children] = []map[string]interface{}{}
|
mapping[primary][opt.Children] = []map[string]interface{}{}
|
||||||
for k, v := range records[i] {
|
|
||||||
|
for k, v := range record {
|
||||||
mapping[primary][k] = v
|
mapping[primary][k] = v
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
recordOrder = append(recordOrder, primary)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 向上归集
|
// 向上归集
|
||||||
for key, record := range mapping {
|
for _, key := range recordOrder {
|
||||||
|
record := mapping[key]
|
||||||
|
|
||||||
parent := fmt.Sprintf("%v", record[opt.Parent])
|
parent := fmt.Sprintf("%v", record[opt.Parent])
|
||||||
empty := fmt.Sprintf("%v", opt.Empty)
|
empty := fmt.Sprintf("%v", opt.Empty)
|
||||||
if parent == empty { // 第一级
|
if parent == empty { // 第一级
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
pKey := fmt.Sprintf("%v", parent)
|
pKey := fmt.Sprintf("%v", parent)
|
||||||
if _, has := mapping[pKey]; !has {
|
parentRecord, hasParent := mapping[pKey]
|
||||||
|
if !hasParent {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
children, ok := mapping[pKey][opt.Children].([]map[string]interface{})
|
|
||||||
|
children, ok := parentRecord[opt.Children].([]map[string]interface{})
|
||||||
if !ok {
|
if !ok {
|
||||||
children = []map[string]interface{}{}
|
children = []map[string]interface{}{}
|
||||||
}
|
}
|
||||||
children = append(children, mapping[key])
|
|
||||||
mapping[pKey][opt.Children] = children
|
children = append(children, record)
|
||||||
|
parentRecord[opt.Children] = children
|
||||||
|
mapping[pKey] = parentRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
res := []map[string]interface{}{}
|
res := []map[string]interface{}{}
|
||||||
for i := range records {
|
for _, key := range recordOrder {
|
||||||
if key, has := records[i][opt.Key]; has {
|
record := mapping[key]
|
||||||
record := mapping[fmt.Sprintf("%v", key)]
|
|
||||||
if pValue, has := record[opt.Parent]; has {
|
// recordKey := fmt.Sprintf("%v", record[opt.Key])
|
||||||
parent := fmt.Sprintf("%v", pValue)
|
recordValue, hasParent := record[opt.Parent]
|
||||||
|
|
||||||
|
if hasParent {
|
||||||
|
parent := fmt.Sprintf("%v", recordValue)
|
||||||
empty := fmt.Sprintf("%v", opt.Empty)
|
empty := fmt.Sprintf("%v", opt.Empty)
|
||||||
if parent == empty { // 父类为空
|
|
||||||
|
if parent == empty || len(mapping[parent]) == 0 {
|
||||||
res = append(res, record)
|
res = append(res, record)
|
||||||
} else if _, has := mapping[parent]; !has { // 或者父类为定义的
|
}
|
||||||
|
} else {
|
||||||
res = append(res, record)
|
res = append(res, record)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
return res, nil
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArrayMapSet []map[string]interface{} 设定数值
|
// ArrayMapSet []map[string]interface{} 设定数值
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ func JwtMake(id int, data map[string]interface{}, option map[string]interface{},
|
||||||
|
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
sid := ""
|
sid := ""
|
||||||
timeout := int64(3600)
|
timeout := int64(36000)
|
||||||
uid := fmt.Sprintf("%d", id)
|
uid := fmt.Sprintf("%d", id)
|
||||||
subject := "User Token"
|
subject := "User Token"
|
||||||
audience := "Yao Process utils.jwt.Make"
|
audience := "Yao Process utils.jwt.Make"
|
||||||
|
|
|
||||||
11
helper/str.go
Normal file
11
helper/str.go
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
package helper
|
||||||
|
|
||||||
|
// 检查字符串数组中是否包含某个字符
|
||||||
|
func ContainsString(arr []string, char string) bool {
|
||||||
|
for _, str := range arr {
|
||||||
|
if str == char {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
35
rules/api.go
Normal file
35
rules/api.go
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
package rules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/yaoapp/gou/session"
|
||||||
|
"github.com/yaoapp/kun/any"
|
||||||
|
"github.com/yaoapp/yao/helper"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Guard table widget guard
|
||||||
|
func Guard(c *gin.Context, rule string) {
|
||||||
|
sid, exists := c.Get("__sid")
|
||||||
|
if !exists {
|
||||||
|
abort(c, 400, "session id is not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user, err := session.Global().ID(sid.(string)).Get("user")
|
||||||
|
if err != nil {
|
||||||
|
abort(c, 400, "user is not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ruleIds := any.Of(user).MapStr().Get("rule_ids")
|
||||||
|
ruleIds = any.Of(ruleIds).CStrings()
|
||||||
|
if !helper.ContainsString(ruleIds.([]string), rule) && !helper.ContainsString(ruleIds.([]string), "*") {
|
||||||
|
abort(c, 400, fmt.Sprintf("no permission for this action: %s", rule))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func abort(c *gin.Context, code int, message string) {
|
||||||
|
c.JSON(code, gin.H{"code": code, "message": message})
|
||||||
|
c.Abort()
|
||||||
|
}
|
||||||
125
rules/load.go
Normal file
125
rules/load.go
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
package rules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/yaoapp/gou/application"
|
||||||
|
"github.com/yaoapp/yao/config"
|
||||||
|
"github.com/yaoapp/yao/share"
|
||||||
|
)
|
||||||
|
|
||||||
|
var RuleDSLS map[string]*DSL = map[string]*DSL{}
|
||||||
|
|
||||||
|
func Load(cfg config.Config) error {
|
||||||
|
messages := []string{}
|
||||||
|
exts := []string{"*.rul.yao", "*.rul.json", "*.rul.jsonc"}
|
||||||
|
err := application.App.Walk("rules", func(root, file string, isdir bool) error {
|
||||||
|
if isdir {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := LoadFile(root, file); err != nil {
|
||||||
|
messages = append(messages, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}, exts...)
|
||||||
|
|
||||||
|
exportProcess()
|
||||||
|
|
||||||
|
if len(messages) > 0 {
|
||||||
|
return fmt.Errorf(strings.Join(messages, ";\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadFile(root string, file string) error {
|
||||||
|
|
||||||
|
id := share.ID(root, file)
|
||||||
|
data, err := application.App.Read(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = load(data, id, file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadSource load table dsl by source
|
||||||
|
func load(source []byte, id string, file string) (*DSL, error) {
|
||||||
|
dsl := &DSL{
|
||||||
|
Rule: &Rule{
|
||||||
|
ID: id,
|
||||||
|
Children: []Rule{},
|
||||||
|
},
|
||||||
|
file: file,
|
||||||
|
source: source,
|
||||||
|
}
|
||||||
|
err := dsl.parse()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("[%s] %s", id, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
RuleDSLS[id] = dsl
|
||||||
|
return dsl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse method to parse and generate keys
|
||||||
|
func (dsl *DSL) parse() error {
|
||||||
|
err := application.Parse(dsl.file, dsl.source, dsl)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
generateKeys(dsl.Rule, "")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateKeys recursively generates keys for rules
|
||||||
|
func generateKeys(rule *Rule, parentKey string) {
|
||||||
|
if parentKey == "" {
|
||||||
|
rule.Key = rule.ID
|
||||||
|
} else {
|
||||||
|
rule.Key = fmt.Sprintf("%s_%s", parentKey, rule.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range rule.Children {
|
||||||
|
generateKeys(&rule.Children[i], rule.Key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMainKeys returns a slice of main keys in RuleDSLS
|
||||||
|
func GetMainKeys() []string {
|
||||||
|
keys := []string{}
|
||||||
|
for key := range RuleDSLS {
|
||||||
|
keys = append(keys, key)
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllKeys 返回Rule结构及其子结构中的所有Key字段
|
||||||
|
func GetAllKeys() []string {
|
||||||
|
var keys []string
|
||||||
|
var collectKeys func(r Rule)
|
||||||
|
|
||||||
|
// 定义递归函数来收集Key
|
||||||
|
collectKeys = func(r Rule) {
|
||||||
|
if r.Key != "" {
|
||||||
|
keys = append(keys, r.Key)
|
||||||
|
}
|
||||||
|
for _, child := range r.Children {
|
||||||
|
collectKeys(child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历RuleDSLS,收集所有Key
|
||||||
|
for _, dsl := range RuleDSLS {
|
||||||
|
if dsl.Rule != nil {
|
||||||
|
collectKeys(*dsl.Rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
32
rules/process.go
Normal file
32
rules/process.go
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
package rules
|
||||||
|
|
||||||
|
import (
|
||||||
|
gouProcess "github.com/yaoapp/gou/process"
|
||||||
|
)
|
||||||
|
|
||||||
|
func exportProcess() {
|
||||||
|
gouProcess.Register("yao.rule.menus", processMenu)
|
||||||
|
gouProcess.Register("yao.rule.ruleKeys", processRuleKeys)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processMenu(process *gouProcess.Process) interface{} {
|
||||||
|
argsLen := process.NumOfArgs()
|
||||||
|
menuOnly := false
|
||||||
|
dsls := GetMainKeys()
|
||||||
|
menuKeys := []string{"*"}
|
||||||
|
if argsLen == 1 {
|
||||||
|
dsls = process.ArgsStrings(0)
|
||||||
|
} else if argsLen == 2 {
|
||||||
|
dsls = process.ArgsStrings(0)
|
||||||
|
menuOnly = process.ArgsBool(1)
|
||||||
|
} else if argsLen == 3 {
|
||||||
|
dsls = process.ArgsStrings(0)
|
||||||
|
menuOnly = process.ArgsBool(1)
|
||||||
|
menuKeys = process.ArgsStrings(2)
|
||||||
|
}
|
||||||
|
return GetDSLsMaps(dsls, menuOnly, menuKeys)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processRuleKeys(process *gouProcess.Process) interface{} {
|
||||||
|
return GetAllKeys()
|
||||||
|
}
|
||||||
63
rules/rule.go
Normal file
63
rules/rule.go
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
package rules
|
||||||
|
|
||||||
|
import "github.com/yaoapp/yao/helper"
|
||||||
|
|
||||||
|
// rulesToMaps converts a slice of Rule to a slice of maps
|
||||||
|
func rulesToMaps(rules []Rule, onlyMenu bool, keys []string) []map[string]interface{} {
|
||||||
|
maps := []map[string]interface{}{}
|
||||||
|
for _, rule := range rules {
|
||||||
|
if onlyMenu && rule.Path == "" && len(rule.Children) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !helper.ContainsString(keys, rule.Key) && !helper.ContainsString(keys, "*") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
maps = append(maps, rule.ToMap(onlyMenu, keys))
|
||||||
|
}
|
||||||
|
return maps
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToMap converts a Rule to a map
|
||||||
|
func (rule *Rule) ToMap(onlyMenu bool, keys []string) map[string]interface{} {
|
||||||
|
return map[string]interface{}{
|
||||||
|
"id": rule.ID,
|
||||||
|
"name": rule.Name,
|
||||||
|
"title": rule.Name,
|
||||||
|
"icon": rule.Icon,
|
||||||
|
"path": rule.Path,
|
||||||
|
"visible_menu": rule.Visible_menu,
|
||||||
|
"children": rulesToMaps(rule.Children, onlyMenu, keys),
|
||||||
|
"rule": rule.Key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dsl *DSL) HasChildren(onlyMenu bool, keys []string) bool {
|
||||||
|
ruls := []Rule{}
|
||||||
|
for _, rule := range dsl.Children {
|
||||||
|
if onlyMenu && rule.Path == "" && len(rule.Children) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !helper.ContainsString(keys, rule.Key) && !helper.ContainsString(keys, "*") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ruls = append(ruls, rule)
|
||||||
|
}
|
||||||
|
return len(ruls) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDSLsMaps returns the maps of DSLs corresponding to the given IDs
|
||||||
|
func GetDSLsMaps(ids []string, onlyMenu bool, keys []string) []map[string]interface{} {
|
||||||
|
if keys == nil {
|
||||||
|
keys = []string{"*"}
|
||||||
|
}
|
||||||
|
maps := []map[string]interface{}{}
|
||||||
|
for _, id := range ids {
|
||||||
|
if dsl, ok := RuleDSLS[id]; ok {
|
||||||
|
rule := dsl.ToMap(onlyMenu, keys)
|
||||||
|
if dsl.HasChildren(onlyMenu, keys) {
|
||||||
|
maps = append(maps, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maps
|
||||||
|
}
|
||||||
17
rules/type.go
Normal file
17
rules/type.go
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
package rules
|
||||||
|
|
||||||
|
type Rule struct {
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
Key string `json:"-"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Icon string `json:"icon,omitempty"`
|
||||||
|
Path string `json:"path,omitempty"`
|
||||||
|
Visible_menu int `json:"visible_menu,omitempty"`
|
||||||
|
Children []Rule `json:"children,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DSL struct {
|
||||||
|
*Rule
|
||||||
|
file string `json:"-"`
|
||||||
|
source []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
@ -74,6 +74,7 @@ func guardBearerJWT(c *gin.Context) {
|
||||||
|
|
||||||
claims := helper.JwtValidate(tokenString)
|
claims := helper.JwtValidate(tokenString)
|
||||||
c.Set("__sid", claims.SID)
|
c.Set("__sid", claims.SID)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// JWT Bearer JWT
|
// JWT Bearer JWT
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/yaoapp/gou/api"
|
"github.com/yaoapp/gou/api"
|
||||||
|
"github.com/yaoapp/yao/rules"
|
||||||
"github.com/yaoapp/yao/share"
|
"github.com/yaoapp/yao/share"
|
||||||
"github.com/yaoapp/yao/widgets/action"
|
"github.com/yaoapp/yao/widgets/action"
|
||||||
)
|
)
|
||||||
|
|
@ -37,6 +38,7 @@ func Guard(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rules.Guard(c, chart.Rule)
|
||||||
}
|
}
|
||||||
|
|
||||||
func abort(c *gin.Context, code int, message string) {
|
func abort(c *gin.Context, code int, message string) {
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,10 @@ func LoadFile(root string, file string) error {
|
||||||
// LoadData load via data
|
// LoadData load via data
|
||||||
func (dsl *DSL) parse(id string, root string) error {
|
func (dsl *DSL) parse(id string, root string) error {
|
||||||
|
|
||||||
|
if dsl.Rule == "" {
|
||||||
|
dsl.Rule = strings.ReplaceAll(id, ".", "_")
|
||||||
|
}
|
||||||
|
|
||||||
if dsl.Action == nil {
|
if dsl.Action == nil {
|
||||||
dsl.Action = &ActionDSL{}
|
dsl.Action = &ActionDSL{}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
type DSL struct {
|
type DSL struct {
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
|
Rule string `json:"rule,omitempty"`
|
||||||
Action *ActionDSL `json:"action"`
|
Action *ActionDSL `json:"action"`
|
||||||
Layout *LayoutDSL `json:"layout"`
|
Layout *LayoutDSL `json:"layout"`
|
||||||
Fields *FieldsDSL `json:"fields"`
|
Fields *FieldsDSL `json:"fields"`
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ var hanlders = map[string]ComputeHanlder{
|
||||||
"Trim": Trim,
|
"Trim": Trim,
|
||||||
"Hide": Hide,
|
"Hide": Hide,
|
||||||
"Concat": Concat,
|
"Concat": Concat,
|
||||||
|
"ValueOr": ValueOr,
|
||||||
"Download": Download,
|
"Download": Download,
|
||||||
"Upload": Upload,
|
"Upload": Upload,
|
||||||
"QueryString": Trim,
|
"QueryString": Trim,
|
||||||
|
|
@ -52,6 +53,18 @@ func Concat(args ...interface{}) (interface{}, error) {
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValueOr
|
||||||
|
func ValueOr(args ...interface{}) (interface{}, error) {
|
||||||
|
res := ""
|
||||||
|
for _, arg := range args {
|
||||||
|
if arg != nil {
|
||||||
|
res = fmt.Sprintf("%v", arg)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get value
|
// Get value
|
||||||
func Get(args ...interface{}) (interface{}, error) {
|
func Get(args ...interface{}) (interface{}, error) {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/yaoapp/gou/api"
|
"github.com/yaoapp/gou/api"
|
||||||
|
"github.com/yaoapp/yao/rules"
|
||||||
"github.com/yaoapp/yao/share"
|
"github.com/yaoapp/yao/share"
|
||||||
"github.com/yaoapp/yao/widgets/action"
|
"github.com/yaoapp/yao/widgets/action"
|
||||||
)
|
)
|
||||||
|
|
@ -37,6 +38,7 @@ func Guard(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rules.Guard(c, dashboard.Rule)
|
||||||
}
|
}
|
||||||
|
|
||||||
func abort(c *gin.Context, code int, message string) {
|
func abort(c *gin.Context, code int, message string) {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
type DSL struct {
|
type DSL struct {
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
|
Rule string `json:"Rule,omitempty"`
|
||||||
Action *ActionDSL `json:"action"`
|
Action *ActionDSL `json:"action"`
|
||||||
Layout *LayoutDSL `json:"layout"`
|
Layout *LayoutDSL `json:"layout"`
|
||||||
Fields *FieldsDSL `json:"fields"`
|
Fields *FieldsDSL `json:"fields"`
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ import (
|
||||||
// Filters the filters DSL
|
// Filters the filters DSL
|
||||||
type Filters map[string]FilterDSL
|
type Filters map[string]FilterDSL
|
||||||
|
|
||||||
|
// Batch the batch DSL
|
||||||
|
type Batches map[string]FilterDSL
|
||||||
|
|
||||||
// Columns the columns DSL
|
// Columns the columns DSL
|
||||||
type Columns map[string]ColumnDSL
|
type Columns map[string]ColumnDSL
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,23 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/yaoapp/gou/api"
|
"github.com/yaoapp/gou/api"
|
||||||
|
"github.com/yaoapp/yao/helper"
|
||||||
|
"github.com/yaoapp/yao/rules"
|
||||||
"github.com/yaoapp/yao/share"
|
"github.com/yaoapp/yao/share"
|
||||||
"github.com/yaoapp/yao/widgets/action"
|
"github.com/yaoapp/yao/widgets/action"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var editAPIS = []string{
|
||||||
|
"/api/__yao/form/:id/upload/:xpath/:method",
|
||||||
|
"/api/__yao/form/:id/save",
|
||||||
|
"/api/__yao/form/:id/create",
|
||||||
|
"/api/__yao/form/:id/insert",
|
||||||
|
}
|
||||||
|
|
||||||
|
var deleteAPIS = []string{
|
||||||
|
"/api/__yao/form/:id/delete/:primary",
|
||||||
|
}
|
||||||
|
|
||||||
// Guard form widget guard
|
// Guard form widget guard
|
||||||
func Guard(c *gin.Context) {
|
func Guard(c *gin.Context) {
|
||||||
|
|
||||||
|
|
@ -37,6 +50,15 @@ func Guard(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rules.Guard(c, form.Rule)
|
||||||
|
if helper.ContainsString(editAPIS, c.FullPath()) {
|
||||||
|
ruleKey := fmt.Sprintf("%s_edit", form.Rule)
|
||||||
|
rules.Guard(c, ruleKey)
|
||||||
|
}
|
||||||
|
if helper.ContainsString(deleteAPIS, c.FullPath()) {
|
||||||
|
ruleKey := fmt.Sprintf("%s_del", form.Rule)
|
||||||
|
rules.Guard(c, ruleKey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func abort(c *gin.Context, code int, message string) {
|
func abort(c *gin.Context, code int, message string) {
|
||||||
|
|
|
||||||
|
|
@ -180,6 +180,10 @@ func load(source []byte, id string, file string) (*DSL, error) {
|
||||||
// LoadData load via data
|
// LoadData load via data
|
||||||
func (dsl *DSL) parse(id string) error {
|
func (dsl *DSL) parse(id string) error {
|
||||||
|
|
||||||
|
if dsl.Rule == "" {
|
||||||
|
dsl.Rule = strings.ReplaceAll(id, ".", "_")
|
||||||
|
}
|
||||||
|
|
||||||
if dsl.Action == nil {
|
if dsl.Action == nil {
|
||||||
dsl.Action = &ActionDSL{}
|
dsl.Action = &ActionDSL{}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
type DSL struct {
|
type DSL struct {
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
|
Rule string `json:"rule,omitempty"`
|
||||||
Action *ActionDSL `json:"action"`
|
Action *ActionDSL `json:"action"`
|
||||||
Layout *LayoutDSL `json:"layout"`
|
Layout *LayoutDSL `json:"layout"`
|
||||||
Fields *FieldsDSL `json:"fields"`
|
Fields *FieldsDSL `json:"fields"`
|
||||||
|
|
@ -94,6 +95,7 @@ type SectionDSL struct {
|
||||||
Icon interface{} `json:"icon,omitempty"`
|
Icon interface{} `json:"icon,omitempty"`
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
Weight interface{} `json:"weight,omitempty"`
|
Weight interface{} `json:"weight,omitempty"`
|
||||||
|
Rule string `json:"rule,omitempty"`
|
||||||
Columns []Column `json:"columns,omitempty"`
|
Columns []Column `json:"columns,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/yaoapp/gou/api"
|
"github.com/yaoapp/gou/api"
|
||||||
|
"github.com/yaoapp/yao/rules"
|
||||||
"github.com/yaoapp/yao/share"
|
"github.com/yaoapp/yao/share"
|
||||||
"github.com/yaoapp/yao/widgets/action"
|
"github.com/yaoapp/yao/widgets/action"
|
||||||
)
|
)
|
||||||
|
|
@ -37,6 +38,7 @@ func Guard(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rules.Guard(c, list.Rule)
|
||||||
}
|
}
|
||||||
|
|
||||||
func abort(c *gin.Context, code int, message string) {
|
func abort(c *gin.Context, code int, message string) {
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,9 @@ func LoadID(id string, root string) error {
|
||||||
// LoadData load via data
|
// LoadData load via data
|
||||||
func (dsl *DSL) parse(id string, root string) error {
|
func (dsl *DSL) parse(id string, root string) error {
|
||||||
|
|
||||||
|
if dsl.Rule == "" {
|
||||||
|
dsl.Rule = strings.ReplaceAll(id, ".", "_")
|
||||||
|
}
|
||||||
if dsl.Action == nil {
|
if dsl.Action == nil {
|
||||||
dsl.Action = &ActionDSL{}
|
dsl.Action = &ActionDSL{}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
type DSL struct {
|
type DSL struct {
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
Root string `json:"-"`
|
Root string `json:"-"`
|
||||||
|
Rule string `json:"rule,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Action *ActionDSL `json:"action"`
|
Action *ActionDSL `json:"action"`
|
||||||
Layout *LayoutDSL `json:"layout"`
|
Layout *LayoutDSL `json:"layout"`
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@ func auth(field string, value string, password string, sid string) maps.Map {
|
||||||
Wheres: []model.QueryWhere{
|
Wheres: []model.QueryWhere{
|
||||||
{Column: column, Value: value},
|
{Column: column, Value: value},
|
||||||
{Column: "status", Value: "enabled"},
|
{Column: "status", Value: "enabled"},
|
||||||
|
{Column: "type", Value: "admin"},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -91,6 +92,9 @@ func auth(field string, value string, password string, sid string) maps.Map {
|
||||||
}
|
}
|
||||||
|
|
||||||
row := rows[0]
|
row := rows[0]
|
||||||
|
row["rule_ids"] = []string{"*"}
|
||||||
|
row["role_ids"] = []int{0}
|
||||||
|
row["department_ids"] = []int{0}
|
||||||
passwordHash := row.Get("password").(string)
|
passwordHash := row.Get("password").(string)
|
||||||
row.Del("password")
|
row.Del("password")
|
||||||
|
|
||||||
|
|
@ -99,7 +103,7 @@ func auth(field string, value string, password string, sid string) maps.Map {
|
||||||
exception.New("Login password error (%v)", 403, value).Throw()
|
exception.New("Login password error (%v)", 403, value).Throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
expiresAt := time.Now().Unix() + 3600*8
|
expiresAt := time.Now().Unix() + 36000
|
||||||
|
|
||||||
// token := MakeToken(row, expiresAt)
|
// token := MakeToken(row, expiresAt)
|
||||||
id := any.Of(row.Get("id")).CInt()
|
id := any.Of(row.Get("id")).CInt()
|
||||||
|
|
@ -128,12 +132,19 @@ func auth(field string, value string, password string, sid string) maps.Map {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get user menus
|
// Get user menus
|
||||||
menus := process.New("yao.app.menu").WithSID(sid).Run()
|
// menus := process.New("yao.app.menu").WithSID(sid).Run()
|
||||||
|
// 读取菜单
|
||||||
|
setting := process.New("yao.rule.menus", []string{"sys"}, true).WithSID(sid).Run()
|
||||||
|
items := process.New("yao.rule.menus", []string{"pro", "crm"}, true).WithSID(sid).Run()
|
||||||
|
|
||||||
return maps.Map{
|
return maps.Map{
|
||||||
"expires_at": token.ExpiresAt,
|
"expires_at": token.ExpiresAt,
|
||||||
"token": token.Token,
|
"token": token.Token,
|
||||||
"user": row,
|
"user": row,
|
||||||
"menus": menus,
|
"menus": maps.Map{
|
||||||
|
"setting": setting,
|
||||||
|
"items": items,
|
||||||
|
},
|
||||||
"studio": studio,
|
"studio": studio,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package mapping
|
||||||
|
|
||||||
// Mapping common
|
// Mapping common
|
||||||
type Mapping struct {
|
type Mapping struct {
|
||||||
|
Batches map[string]string
|
||||||
Filters map[string]string
|
Filters map[string]string
|
||||||
Columns map[string]string
|
Columns map[string]string
|
||||||
Actions map[string]string
|
Actions map[string]string
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,28 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/yaoapp/gou/api"
|
"github.com/yaoapp/gou/api"
|
||||||
|
"github.com/yaoapp/yao/helper"
|
||||||
|
"github.com/yaoapp/yao/rules"
|
||||||
"github.com/yaoapp/yao/share"
|
"github.com/yaoapp/yao/share"
|
||||||
"github.com/yaoapp/yao/widgets/action"
|
"github.com/yaoapp/yao/widgets/action"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var editAPIS = []string{
|
||||||
|
"/api/__yao/table/:id/upload/:xpath/:method",
|
||||||
|
"/api/__yao/table/:id/save",
|
||||||
|
"/api/__yao/table/:id/create",
|
||||||
|
"/api/__yao/table/:id/insert",
|
||||||
|
"/api/__yao/table/:id/update/:primary",
|
||||||
|
"/api/__yao/table/:id/update/in",
|
||||||
|
"/api/__yao/table/:id/update/where",
|
||||||
|
}
|
||||||
|
|
||||||
|
var deleteAPIS = []string{
|
||||||
|
"/api/__yao/table/:id/delete/:primary",
|
||||||
|
"/api/__yao/table/:id/delete/in",
|
||||||
|
"/api/__yao/table/:id/delete/where",
|
||||||
|
}
|
||||||
|
|
||||||
// Guard table widget guard
|
// Guard table widget guard
|
||||||
func Guard(c *gin.Context) {
|
func Guard(c *gin.Context) {
|
||||||
|
|
||||||
|
|
@ -37,6 +55,15 @@ func Guard(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rules.Guard(c, tab.Rule)
|
||||||
|
if helper.ContainsString(editAPIS, c.FullPath()) {
|
||||||
|
ruleKey := fmt.Sprintf("%s_edit", tab.Rule)
|
||||||
|
rules.Guard(c, ruleKey)
|
||||||
|
}
|
||||||
|
if helper.ContainsString(deleteAPIS, c.FullPath()) {
|
||||||
|
ruleKey := fmt.Sprintf("%s_del", tab.Rule)
|
||||||
|
rules.Guard(c, ruleKey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func abort(c *gin.Context, code int, message string) {
|
func abort(c *gin.Context, code int, message string) {
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ func (layout *LayoutDSL) Xgen(data map[string]interface{}, excludes map[string]b
|
||||||
if clone.Header.Preset.Batch != nil && clone.Header.Preset.Batch.Columns != nil {
|
if clone.Header.Preset.Batch != nil && clone.Header.Preset.Batch.Columns != nil {
|
||||||
columns := []component.InstanceDSL{}
|
columns := []component.InstanceDSL{}
|
||||||
for _, column := range clone.Header.Preset.Batch.Columns {
|
for _, column := range clone.Header.Preset.Batch.Columns {
|
||||||
id, has := mapping.Filters[column.Name]
|
id, has := mapping.Batches[column.Name]
|
||||||
if !has {
|
if !has {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,10 @@ func (dsl *DSL) mapping() error {
|
||||||
dsl.Mapping.Filters = map[string]string{}
|
dsl.Mapping.Filters = map[string]string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dsl.Mapping.Batches == nil {
|
||||||
|
dsl.Mapping.Batches = map[string]string{}
|
||||||
|
}
|
||||||
|
|
||||||
if dsl.Mapping.Columns == nil {
|
if dsl.Mapping.Columns == nil {
|
||||||
dsl.Mapping.Columns = map[string]string{}
|
dsl.Mapping.Columns = map[string]string{}
|
||||||
}
|
}
|
||||||
|
|
@ -84,6 +88,27 @@ func (dsl *DSL) mapping() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dsl.Fields.Batch != nil && dsl.Layout.Header.Preset.Batch != nil && dsl.Layout.Header.Preset.Batch.Columns != nil {
|
||||||
|
for _, inst := range dsl.Layout.Header.Preset.Batch.Columns {
|
||||||
|
|
||||||
|
if batch, has := dsl.Fields.Batch[inst.Name]; has {
|
||||||
|
|
||||||
|
// Mapping ID
|
||||||
|
dsl.Mapping.Batches[batch.ID] = inst.Name
|
||||||
|
dsl.Mapping.Batches[inst.Name] = batch.ID
|
||||||
|
|
||||||
|
// Mapping Compute
|
||||||
|
if batch.Edit != nil && batch.Edit.Compute != nil {
|
||||||
|
bind := batch.FilterBind()
|
||||||
|
if _, has := dsl.Computes.Filter[bind]; !has {
|
||||||
|
dsl.Computes.Filter[bind] = []compute.Unit{}
|
||||||
|
}
|
||||||
|
dsl.Computes.Filter[bind] = append(dsl.Computes.Filter[bind], compute.Unit{Name: inst.Name, Kind: compute.Filter})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if dsl.Fields.Table != nil && dsl.Layout.Table != nil && dsl.Layout.Table.Columns != nil {
|
if dsl.Fields.Table != nil && dsl.Layout.Table != nil && dsl.Layout.Table.Columns != nil {
|
||||||
for _, inst := range dsl.Layout.Table.Columns {
|
for _, inst := range dsl.Layout.Table.Columns {
|
||||||
if field, has := dsl.Fields.Table[inst.Name]; has {
|
if field, has := dsl.Fields.Table[inst.Name]; has {
|
||||||
|
|
|
||||||
|
|
@ -260,8 +260,11 @@ func processDeleteIn(process *gouProcess.Process) interface{} {
|
||||||
func processExport(process *gouProcess.Process) interface{} {
|
func processExport(process *gouProcess.Process) interface{} {
|
||||||
process.ValidateArgNums(1)
|
process.ValidateArgNums(1)
|
||||||
tab := MustGet(process) // 0
|
tab := MustGet(process) // 0
|
||||||
|
|
||||||
params := process.ArgsQueryParams(1, types.QueryParam{})
|
params := process.ArgsQueryParams(1, types.QueryParam{})
|
||||||
pagesize := process.ArgsInt(2, 50)
|
page := process.ArgsInt(2, 1)
|
||||||
|
pagesize := process.ArgsInt(3, 50)
|
||||||
|
|
||||||
log.Trace("[table] export %s %v %d", tab.ID, params, pagesize)
|
log.Trace("[table] export %s %v %d", tab.ID, params, pagesize)
|
||||||
|
|
||||||
// Filename
|
// Filename
|
||||||
|
|
@ -276,7 +279,7 @@ func processExport(process *gouProcess.Process) interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query
|
// Query
|
||||||
page := 1
|
|
||||||
for page > 0 {
|
for page > 0 {
|
||||||
process.Args = []interface{}{tab.ID, params, page, pagesize}
|
process.Args = []interface{}{tab.ID, params, page, pagesize}
|
||||||
data, err := tab.Action.Search.Exec(process)
|
data, err := tab.Action.Search.Exec(process)
|
||||||
|
|
|
||||||
|
|
@ -209,6 +209,10 @@ func load(source []byte, id string, file string) (*DSL, error) {
|
||||||
// parse parse table dsl source
|
// parse parse table dsl source
|
||||||
func (dsl *DSL) parse(id string) error {
|
func (dsl *DSL) parse(id string) error {
|
||||||
|
|
||||||
|
if dsl.Rule == "" {
|
||||||
|
dsl.Rule = strings.ReplaceAll(id, ".", "_")
|
||||||
|
}
|
||||||
|
|
||||||
if dsl.Action == nil {
|
if dsl.Action == nil {
|
||||||
dsl.Action = &ActionDSL{}
|
dsl.Action = &ActionDSL{}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ type DSL struct {
|
||||||
// Root string `json:"-"`
|
// Root string `json:"-"`
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
|
Rule string `json:"rule,omitempty"`
|
||||||
Action *ActionDSL `json:"action"`
|
Action *ActionDSL `json:"action"`
|
||||||
Layout *LayoutDSL `json:"layout"`
|
Layout *LayoutDSL `json:"layout"`
|
||||||
Fields *FieldsDSL `json:"fields"`
|
Fields *FieldsDSL `json:"fields"`
|
||||||
|
|
@ -99,6 +100,12 @@ type HeaderLayoutDSL struct {
|
||||||
type PresetHeaderDSL struct {
|
type PresetHeaderDSL struct {
|
||||||
Batch *BatchPresetDSL `json:"batch,omitempty"`
|
Batch *BatchPresetDSL `json:"batch,omitempty"`
|
||||||
Import *ImportPresetDSL `json:"import,omitempty"`
|
Import *ImportPresetDSL `json:"import,omitempty"`
|
||||||
|
Column *ColumnDSL `json:"column,omitempty"`
|
||||||
|
Filter *ColumnDSL `json:"filter,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ColumnDSL struct {
|
||||||
|
Musts []string `json:"musts,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchPresetDSL layout.header.preset.batch
|
// BatchPresetDSL layout.header.preset.batch
|
||||||
|
|
@ -137,6 +144,7 @@ type OperationTableDSL struct {
|
||||||
// FieldsDSL the table fields DSL
|
// FieldsDSL the table fields DSL
|
||||||
type FieldsDSL struct {
|
type FieldsDSL struct {
|
||||||
Filter field.Filters `json:"filter,omitempty"`
|
Filter field.Filters `json:"filter,omitempty"`
|
||||||
|
Batch field.Batches `json:"batch,omitempty"`
|
||||||
Table field.Columns `json:"table,omitempty"`
|
Table field.Columns `json:"table,omitempty"`
|
||||||
filterMap map[string]field.FilterDSL
|
filterMap map[string]field.FilterDSL
|
||||||
tableMap map[string]field.ColumnDSL
|
tableMap map[string]field.ColumnDSL
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue