Skip to content

Commit 3442aa9

Browse files
committed
save for 调整
1 parent bb77d8f commit 3442aa9

File tree

20 files changed

+289
-183
lines changed

20 files changed

+289
-183
lines changed

@doc/roadmap.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,26 @@
77
- [x] 简易单表的post,put,delete操作 (可一次传递多个表, 单表指表表之间无关联)
88
- [x] 查询权限控制(表、行、字段)
99

10-
## [ ] 下水 阶段
10+
## [x] 下水 阶段
1111
- [x] 增加 hook (钩子函数), 用于对接口的的前置、后置处理 (例如修改数据、清理缓存等操作)
1212
- [x] 增加 设置 rowKey 生成 (id生成)
1313
- [x] 新增多个表时, structures 中 update可引用其他边的字段 (例如新建角色,并使用新增的id 设置给权限列表中)
1414
- [x] 批量修改(统一设置模式+单个设置模式)、批量删除
1515
- [x] request的version设置
1616
- [x] 增加 functions , 用于对数据的处理 (字典转换、id转name等操作)
17-
18-
19-
## [ ] 摸石头 阶段
20-
- [ ] 开发、测试环境下记录get请求记录
2117
- [x] 可自定义get中查询节点的实现 (即从缓存或者其他数据源查询数据)
2218
- [x] 可自定义非开放请求的具体实现
2319
- [x] 提供 web UI 用于 _access 和 _request 的管理
2420

21+
## [ ] 摸石头 阶段
22+
- [ ] 开发、测试环境下记录get请求记录
23+
- [ ] 多实例
24+
- [ ] 错误提示
25+
2526
## [ ] xxx 阶段
2627
- [ ] get请求的复杂度计算, 超过复杂度则拒绝执行(树节点计算)
2728
- [ ] 完善 apijson 规范的兼容实现
29+
- [ ] 提供一份较好的文档
2830

2931

3032

@@ -41,7 +43,6 @@
4143
- [x] MUST
4244
- [x] REFUSE
4345
- [x] 分页返回total@
44-
4546
- [x] 可用的权限方案
4647
- [x] get只有access中定义的才能访问
4748
- [x] 非get操作则必须与request指定一致才可请求

@doc/v0.2.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# v0.2
2+
3+
> 框架使用上会与apijson(java)不完全一致, 但是与前端的json请求响应规则 (即apijson的语法规则)会尽可能兼容
4+
5+
1. 由全局配置改成apijson实例,可创建不同实例对应不同的内容
6+
2. 代码内部 传递的accessName 都为 _access 配置中的alias
7+
3. access/request配置可从配置文件中获取

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
# apijson-go [下水阶段]
1+
# apijson-go [摸石头阶段]
22
基于 go + goframe 实现的 apijson
33

44
> ~~暂仍处于前期开发探索中, 请仅使用在 个人探索项目~~
5-
6-
> 目前处于 【下水阶段】, 欢迎测试、issue、建议、pr
5+
> ~~目前处于 【下水阶段】, 欢迎测试、issue、建议、pr~~
6+
> 目前处于 【摸石头阶段】, 欢迎测试、issue、建议、pr, 请勿使用在非个人的线上项目
77
88
[RoadMap 阶段规划](./@doc/roadmap.md)
99

action/action.go

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package action
22

33
import (
44
"context"
5+
"github.com/glennliao/apijson-go/config"
56
"github.com/glennliao/apijson-go/config/db"
67
"github.com/glennliao/apijson-go/consts"
78
"github.com/glennliao/apijson-go/model"
@@ -29,6 +30,8 @@ type Action struct {
2930
NoAccessVerify bool
3031
// 关闭 request 验证开关, 默认否
3132
NoRequestVerify bool
33+
34+
Access *config.Access
3235
}
3336

3437
func New(ctx context.Context, method string, req model.Map) *Action {

action/node.go

+30-26
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ type Node struct {
3131
executor string
3232

3333
keyNode map[string]*Node
34+
35+
access *config.Access
3436
}
3537

3638
func newNode(key string, req []model.Map, structure *db.Structure, executor string) Node {
@@ -143,10 +145,12 @@ func (n *Node) roleUpdate() error {
143145

144146
func (n *Node) checkAccess(ctx context.Context, method string, accessRoles []string) error {
145147

146-
role, err := config.DefaultRoleFunc(ctx, config.RoleReq{
147-
Table: n.TableName,
148-
Method: method,
149-
NodeRole: n.Role,
148+
// todo 可配置单次的内容, 而非直接使用整个的
149+
150+
role, err := n.action.Access.DefaultRoleFunc(ctx, config.RoleReq{
151+
AccessName: n.TableName,
152+
Method: method,
153+
NodeRole: n.Role,
150154
})
151155

152156
if err != nil {
@@ -164,8 +168,8 @@ func (n *Node) checkAccess(ctx context.Context, method string, accessRoles []str
164168
}
165169

166170
for i, item := range n.req {
167-
where, err := config.AccessConditionFunc(ctx, config.AccessConditionReq{
168-
Table: n.TableName,
171+
where, err := n.action.Access.ConditionFunc(ctx, config.ConditionReq{
172+
AccessName: n.TableName,
169173
TableAccessRoleList: accessRoles,
170174
Method: method,
171175
NodeRole: n.Role,
@@ -177,11 +181,11 @@ func (n *Node) checkAccess(ctx context.Context, method string, accessRoles []str
177181
}
178182

179183
if method == http.MethodPost {
180-
for k, v := range where {
184+
for k, v := range where.Where() {
181185
n.Data[i][k] = v
182186
}
183187
} else {
184-
for k, v := range where {
188+
for k, v := range where.Where() {
185189
n.Where[i][k] = v
186190
}
187191
}
@@ -304,24 +308,24 @@ func (n *Node) do(ctx context.Context, method string, dataIndex int) (ret model.
304308
return nil, err
305309
}
306310

307-
if access.RowKeyGen != "" {
308-
for i, _ := range n.Data {
309-
310-
rowKeyVal, err = config.RowKeyGen(ctx, access.RowKeyGen, n.TableName, n.Data[i])
311-
if err != nil {
312-
return nil, err
313-
}
314-
315-
for k, v := range rowKeyVal {
316-
if k == consts.RowKey {
317-
n.Data[i][access.RowKey] = v
318-
} else {
319-
n.Data[i][k] = v
320-
}
321-
}
322-
323-
}
324-
}
311+
//if access.RowKeyGen != "" {
312+
// for i, _ := range n.Data {
313+
//
314+
// rowKeyVal, err = config.RowKeyGen(ctx, access.RowKeyGen, n.TableName, n.Data[i])
315+
// if err != nil {
316+
// return nil, err
317+
// }
318+
//
319+
// for k, v := range rowKeyVal {
320+
// if k == consts.RowKey {
321+
// n.Data[i][access.RowKey] = v
322+
// } else {
323+
// n.Data[i][k] = v
324+
// }
325+
// }
326+
//
327+
// }
328+
//}
325329

326330
var id int64
327331

apijson.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package apijson
2+
3+
import (
4+
"context"
5+
"github.com/glennliao/apijson-go/config"
6+
)
7+
8+
type Plugin interface {
9+
Install(ctx context.Context, a *ApiJson)
10+
}
11+
12+
type ApiJson struct {
13+
config *config.Config
14+
Debug bool // 是否开启debug模式, 显示每步骤
15+
ctx context.Context
16+
}
17+
18+
var DefaultApiJson = New()
19+
20+
type App struct {
21+
}
22+
23+
func New() *ApiJson {
24+
a := &ApiJson{}
25+
a.config = config.New()
26+
a.ctx = context.Background()
27+
return a
28+
}
29+
30+
// Load load for defaultApiJson, 简化使用
31+
func Load(app func(ctx context.Context, a *ApiJson)) *ApiJson {
32+
DefaultApiJson.Use(app)
33+
DefaultApiJson.Load()
34+
return DefaultApiJson
35+
}
36+
37+
func (a *ApiJson) Use(p ...func(ctx context.Context, a *ApiJson)) *ApiJson {
38+
for _, plugin := range p {
39+
plugin(a.ctx, a)
40+
}
41+
return a
42+
}
43+
44+
func (a *ApiJson) Load() {
45+
46+
}
47+
48+
func (a *ApiJson) Config() *config.Config {
49+
return a.config
50+
}

config/access.go

+61-34
Original file line numberDiff line numberDiff line change
@@ -7,55 +7,82 @@ import (
77
"github.com/samber/lo"
88
)
99

10-
type AccessConditionReq struct {
11-
Table string
10+
// 设置 _access/_request 自定义表名
11+
// todo
12+
var (
13+
TableAccess = "_access"
14+
TableRequest = "_request"
15+
)
16+
17+
type ConditionReq struct {
18+
AccessName string // _access 中的alias
1219
TableAccessRoleList []string
1320
Method string
1421
NodeReq g.Map //节点的请求数据
1522
NodeRole string // 节点的角色
1623
}
1724

18-
type RoleReq struct {
19-
Table string
20-
Method string
21-
NodeRole string // 前端传入的节点的角色, 目前未传入则为空
25+
type ConditionRet struct {
26+
condition map[string]any
2227
}
2328

24-
// AccessCondition 根据传入的ctx获取用户信息, 结合req 中的信息 返回需要添加到sql的where条件
25-
type AccessCondition func(ctx context.Context, req AccessConditionReq) (g.Map, error)
29+
func (c *ConditionRet) Add(k string, v any) { // todo any?
30+
c.condition[k] = v
31+
}
32+
33+
func (c *ConditionRet) Where() map[string]any {
34+
return c.condition
35+
}
36+
37+
type AccessCondition func(ctx context.Context, req ConditionReq) (*ConditionRet, error)
38+
39+
type RoleReq struct {
40+
AccessName string
41+
Method string
42+
NodeRole string // 前端传入的节点的角色, 目前未传入则为空
43+
}
2644

27-
// DefaultRole nodeRole 为前端显式指定的role, 需要此函数中判断该role是不是用户角色之一, 返回最终该节点的角色
2845
type DefaultRole func(ctx context.Context, req RoleReq) (string, error)
2946

30-
var (
31-
// AccessVerify 是否禁用权限验证
32-
NoAccessVerify = true
33-
// AccessConditionFunc 自定义权限限制条件
34-
AccessConditionFunc AccessCondition
35-
// DefaultRoleFunc 自定义获取节点的默认角色
36-
DefaultRoleFunc DefaultRole = func(ctx context.Context, req RoleReq) (string, error) {
37-
return consts.UNKNOWN, nil
38-
}
39-
)
47+
func defaultRole(ctx context.Context, req RoleReq) (string, error) {
48+
return consts.UNKNOWN, nil
49+
}
4050

41-
// 设置 _access/_request 自定义表名
42-
var (
43-
TableAccess = "_access"
44-
TableRequest = "_request"
45-
)
51+
func defaultCondition(ctx context.Context, req ConditionReq) (*ConditionRet, error) {
52+
return &ConditionRet{}, nil
53+
}
4654

47-
// ========================= 角色 =======================
48-
// 角色列表
49-
// access 中填写的角色应在角色列表中
55+
type Access struct {
56+
// 禁用_access权限校验, 默认为false, 需手动开启
57+
NoVerify bool
5058

51-
var (
52-
roleList = []string{consts.UNKNOWN, consts.LOGIN, consts.OWNER, consts.ADMIN}
53-
)
59+
// 用于 根据accessName+user来自定义添加sql条件, 完成数据的权限限制
60+
ConditionFunc AccessCondition
61+
62+
// nodeRole 为前端显式指定的role, 需要此函数中判断该role是不是用户角色之一, 返回最终该节点的角色
63+
DefaultRoleFunc DefaultRole
64+
65+
roleList []string
66+
}
67+
68+
func NewAccess() *Access {
69+
70+
a := &Access{}
71+
a.ConditionFunc = defaultCondition
72+
a.DefaultRoleFunc = defaultRole
73+
a.roleList = []string{consts.UNKNOWN, consts.LOGIN, consts.OWNER, consts.ADMIN}
74+
75+
return a
76+
}
5477

55-
func AddRole(name string) {
56-
if !lo.Contains(roleList, name) {
57-
roleList = append(roleList, name)
78+
// AddRole 添加应用中额外的角色
79+
func (a *Access) AddRole(roles []string) *Access {
80+
for _, role := range roles {
81+
if !lo.Contains(a.roleList, role) {
82+
a.roleList = append(a.roleList, role)
83+
}
5884
}
85+
return a
5986
}
6087

61-
func RoleList() []string { return roleList }
88+
func (a *Access) RoleList() []string { return a.roleList }

config/config.go

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
package config
22

3-
var (
4-
Debug = false
5-
)
3+
type Config struct {
4+
Access *Access
5+
MaxTreeWidth int
6+
MaxTreeDeep int
7+
rowKeyGenFuncMap map[string]RowKeyGenFuncHandler
8+
}
9+
10+
func New() *Config {
11+
a := &Config{}
12+
a.Access = NewAccess()
13+
14+
a.MaxTreeWidth = 5
15+
a.MaxTreeDeep = 5
16+
17+
a.rowKeyGenFuncMap = make(map[string]RowKeyGenFuncHandler)
18+
19+
return a
20+
}

config/node.go

-4
This file was deleted.

config/rowkeygen.go

+6-8
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,18 @@ import (
88

99
type RowKeyGenFuncHandler func(ctx context.Context, genParam g.Map, table string, data g.Map) (g.Map, error)
1010

11-
var rowKeyGenFuncMap = map[string]RowKeyGenFuncHandler{}
12-
13-
func RowKeyGen(ctx context.Context, genFuncName string, table string, data g.Map) (g.Map, error) {
14-
if f, exists := rowKeyGenFuncMap[genFuncName]; exists {
11+
func (a *Config) RowKeyGen(ctx context.Context, genFuncName string, table string, data g.Map) (g.Map, error) {
12+
if f, exists := a.rowKeyGenFuncMap[genFuncName]; exists {
1513
return f(ctx, g.Map{}, table, data)
1614
}
1715

1816
return nil, nil
1917
}
2018

21-
func RowKeyGenFunc(name string, f RowKeyGenFuncHandler) {
22-
rowKeyGenFuncMap[name] = f
19+
func (a *Config) RowKeyGenFunc(name string, f RowKeyGenFuncHandler) {
20+
a.rowKeyGenFuncMap[name] = f
2321
}
2422

25-
func RowKeyGenList() []string {
26-
return lo.Keys(rowKeyGenFuncMap)
23+
func (a *Config) RowKeyGenList() []string {
24+
return lo.Keys(a.rowKeyGenFuncMap)
2725
}

0 commit comments

Comments
 (0)