Compare commits

..

No commits in common. "main" and "v1.5.3" have entirely different histories.
main ... v1.5.3

View File

@ -12,69 +12,7 @@ import (
func init() { func init() {
jsmod.Register("db", map[string]any{ jsmod.Register("db", map[string]any{
// 入口:支持别名获取,不传则默认 "default" "get": func(ctx context.Context, name string) (*jsDB, error) {
"Get": func(ctx context.Context, name *string) (*jsDB, error) {
target := "default"
if name != nil {
target = *name
}
return getJSDB(ctx, target)
},
// 默认快捷调用 (面向 "default" 实例)
"Query": func(ctx context.Context, query string, args ...any) (*QueryResult, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Query(query, args...), nil
},
"Exec": func(ctx context.Context, query string, args ...any) (*ExecResult, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Exec(query, args...), nil
},
"Insert": func(ctx context.Context, table string, data any) (*ExecResult, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Insert(table, data), nil
},
"Update": func(ctx context.Context, table string, data any, conditions string, args ...any) (*ExecResult, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Update(table, data, conditions, args...), nil
},
"Delete": func(ctx context.Context, table string, conditions string, args ...any) (*ExecResult, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Delete(table, conditions, args...), nil
},
"Replace": func(ctx context.Context, table string, data any) (*ExecResult, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Replace(table, data), nil
},
"Begin": func(ctx context.Context) (*jsTx, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Begin()
},
})
}
func getJSDB(ctx context.Context, name string) (*jsDB, error) {
isReadOnly := false isReadOnly := false
// 安全模式下的动态判定 // 安全模式下的动态判定
@ -85,6 +23,7 @@ func getJSDB(ctx context.Context, name string) (*jsDB, error) {
if idx := strings.Index(path, "?"); idx != -1 { if idx := strings.Index(path, "?"); idx != -1 {
path = path[:idx] path = path[:idx]
} }
// 如果路径不在沙箱内VerifyPathForSafeMode 会直接返回 error阻止连接
_, err := file.VerifyPathForSafeMode(ctx, path) _, err := file.VerifyPathForSafeMode(ctx, path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -93,7 +32,7 @@ func getJSDB(ctx context.Context, name string) (*jsDB, error) {
} else { } else {
// 2. 远程数据库前缀校验 // 2. 远程数据库前缀校验
var allowedDSNs []string var allowedDSNs []string
cast.Convert(&allowedDSNs, jsmod.Get(ctx, "AllowedDSNs")) cast.Convert(&allowedDSNs, ctx.Value("AllowedDSNs"))
matched := false matched := false
for _, prefix := range allowedDSNs { for _, prefix := range allowedDSNs {
if strings.HasPrefix(name, prefix) { if strings.HasPrefix(name, prefix) {
@ -102,6 +41,7 @@ func getJSDB(ctx context.Context, name string) (*jsDB, error) {
} }
} }
if !matched { if !matched {
// 未命中白名单,降级为只读模式
isReadOnly = true isReadOnly = true
} }
} }
@ -112,6 +52,8 @@ func getJSDB(ctx context.Context, name string) (*jsDB, error) {
return nil, d.Error return nil, d.Error
} }
return &jsDB{db: d, ctx: ctx, isReadOnly: isReadOnly}, nil return &jsDB{db: d, ctx: ctx, isReadOnly: isReadOnly}, nil
},
})
} }
type jsDB struct { type jsDB struct {
@ -179,10 +121,6 @@ func (jd *jsDB) Begin() (*jsTx, error) {
return &jsTx{tx: tx, ctx: jd.ctx, isReadOnly: jd.isReadOnly}, nil return &jsTx{tx: tx, ctx: jd.ctx, isReadOnly: jd.isReadOnly}, nil
} }
// Metadata
func (jd *jsDB) InKeys(numArgs int) string { return jd.db.InKeys(numArgs) }
func (jd *jsDB) Quote(text string) string { return jd.db.Quote(text) }
// jsTx wraps *Tx for JS environment // jsTx wraps *Tx for JS environment
type jsTx struct { type jsTx struct {
tx *Tx tx *Tx
@ -244,3 +182,7 @@ func (jt *jsTx) Commit() error {
} }
func (jt *jsTx) Rollback() error { return jt.tx.Rollback() } func (jt *jsTx) Rollback() error { return jt.tx.Rollback() }
// Metadata
func (jd *jsDB) InKeys(numArgs int) string { return jd.db.InKeys(numArgs) }
func (jd *jsDB) Quote(text string) string { return jd.db.Quote(text) }