feat: register context-aware redis capabilities to jsmod
This commit is contained in:
parent
868bd819a6
commit
3fc84e4ca1
@ -1,5 +1,9 @@
|
||||
# CHANGELOG - redis
|
||||
|
||||
## v1.3.3 (2026-05-30)
|
||||
- **新增**: 注册到 `jsmod`。
|
||||
- **安全性**: 引入基于 Context 的细粒度权限控制。在 `SafeMode` 下,仅允许读取操作(GET/EXISTS/ZRANGE等),所有写操作(SET/DEL/EXPIRE/DO等)将被拦截并返回错误。
|
||||
|
||||
## v1.0.8 (2026-05-10)
|
||||
- **API 对齐**:
|
||||
- `NewIDMaker` 返回值从 `*IDMaker` 修改为 `*id.IDMaker`,保持全局接口统一。
|
||||
|
||||
3
go.mod
3
go.mod
@ -8,9 +8,10 @@ require (
|
||||
apigo.cc/go/crypto v1.3.1
|
||||
apigo.cc/go/encoding v1.3.1
|
||||
apigo.cc/go/id v1.3.1
|
||||
apigo.cc/go/jsmod v1.0.1
|
||||
apigo.cc/go/log v1.3.4
|
||||
apigo.cc/go/safe v1.3.1
|
||||
github.com/gomodule/redigo v1.9.3
|
||||
github.com/gomodule/redigo v2.0.0+incompatible
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
12
go.sum
12
go.sum
@ -10,6 +10,8 @@ apigo.cc/go/file v1.3.2 h1:pu4oiDyiqgj3/eykfnJf+/6+A9v/Z0b3ClP5XK+lwG4=
|
||||
apigo.cc/go/file v1.3.2/go.mod h1:vci4h0Pz94mV6dkniQkuyBYERVYeq7/LX4jJVuCg9hs=
|
||||
apigo.cc/go/id v1.3.1 h1:pkqi6VeWyQoHuIu0Zbx/RRxIAdM61Js0j6cY1M9XVCk=
|
||||
apigo.cc/go/id v1.3.1/go.mod h1:P2/vl3tyW3US+ayOFSMoPIOCulNLBngNYPhXJC/Z7J4=
|
||||
apigo.cc/go/jsmod v1.0.1 h1:vaz3cMQi75UVoALLfyV/Trs8iP/Nh28yN57IvBFpPGk=
|
||||
apigo.cc/go/jsmod v1.0.1/go.mod h1:bmyeZtOAP/j5am+YRnaiM89smysK24K7ebk0koFtsSw=
|
||||
apigo.cc/go/log v1.3.4 h1:UT8Neb9r4QjjbCFbTzw+ZeTxd+DmdmR5gNExeR4Cj+g=
|
||||
apigo.cc/go/log v1.3.4/go.mod h1:/Q/2r51xWSsrS4QN5U9jLiTw8n6qNC8kG9nuVHweY20=
|
||||
apigo.cc/go/rand v1.3.1 h1:7FvsI6PtQ5XrWER0dTiLVo0p7GIxRidT/TBKhVy93j8=
|
||||
@ -18,20 +20,14 @@ apigo.cc/go/safe v1.3.1 h1:irTCqPAC97gGsX/Lw5AzLelDt1xXLEZIAaVhLELWe9Q=
|
||||
apigo.cc/go/safe v1.3.1/go.mod h1:XdOpBhN2vkImalaykYXXmEpczqWa1y3ah6/Q72cdRqE=
|
||||
apigo.cc/go/shell v1.3.1 h1:M8oD0b2HcJuCC6frQFx11b3UTcTx3lATX8XK+YXSVm8=
|
||||
apigo.cc/go/shell v1.3.1/go.mod h1:ZMdJjpCpWdvsHKUXlelh/AxsV/nWdkH/k3lISfzMdUw=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gomodule/redigo v1.9.3 h1:dNPSXeXv6HCq2jdyWfjgmhBdqnR6PRO3m/G05nvpPC8=
|
||||
github.com/gomodule/redigo v1.9.3/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI=
|
||||
golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8=
|
||||
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
|
||||
|
||||
196
js_export.go
Normal file
196
js_export.go
Normal file
@ -0,0 +1,196 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"apigo.cc/go/jsmod"
|
||||
)
|
||||
|
||||
func init() {
|
||||
jsmod.Register("redis", map[string]any{
|
||||
"get": func(ctx context.Context, name string) (*jsRedis, error) {
|
||||
rd := GetRedis(name, nil)
|
||||
if rd.Error != nil {
|
||||
return nil, rd.Error
|
||||
}
|
||||
return &jsRedis{rd: rd, ctx: ctx}, nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
type jsRedis struct {
|
||||
rd *Redis
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
var errSafeMode = errors.New("redis write operation is restricted in safe mode")
|
||||
|
||||
func (jr *jsRedis) checkSafe() error {
|
||||
if jsmod.IsSafeMode(jr.ctx) {
|
||||
return errSafeMode
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read Operations (Always allowed)
|
||||
func (jr *jsRedis) GET(key string) *Result { return jr.rd.GET(key) }
|
||||
func (jr *jsRedis) EXISTS(key string) bool { return jr.rd.EXISTS(key) }
|
||||
func (jr *jsRedis) HGET(key, field string) *Result { return jr.rd.HGET(key, field) }
|
||||
func (jr *jsRedis) HGETALL(key string) map[string]*Result { return jr.rd.HGETALL(key) }
|
||||
func (jr *jsRedis) HEXISTS(key, field string) bool { return jr.rd.HEXISTS(key, field) }
|
||||
func (jr *jsRedis) HLEN(key string) int { return jr.rd.HLEN(key) }
|
||||
func (jr *jsRedis) HKEYS(key string) []string { return jr.rd.HKEYS(key) }
|
||||
func (jr *jsRedis) LLEN(key string) int { return jr.rd.LLEN(key) }
|
||||
func (jr *jsRedis) LRANGE(key string, start, stop int) []Result {
|
||||
return jr.rd.LRANGE(key, start, stop)
|
||||
}
|
||||
func (jr *jsRedis) SMEMBERS(key string) []Result { return jr.rd.SMEMBERS(key) }
|
||||
func (jr *jsRedis) SCARD(key string) int { return jr.rd.SCARD(key) }
|
||||
func (jr *jsRedis) SISMEMBER(key string, value any) bool {
|
||||
return jr.rd.SISMEMBER(key, value)
|
||||
}
|
||||
func (jr *jsRedis) ZRANGE(key string, start, stop int) []Result {
|
||||
return jr.rd.ZRANGE(key, start, stop)
|
||||
}
|
||||
func (jr *jsRedis) ZREVRANGE(key string, start, stop int) []Result {
|
||||
return jr.rd.ZREVRANGE(key, start, stop)
|
||||
}
|
||||
func (jr *jsRedis) ZCARD(key string) int { return jr.rd.ZCARD(key) }
|
||||
func (jr *jsRedis) ZRANK(key string, member any) int { return jr.rd.ZRANK(key, member) }
|
||||
func (jr *jsRedis) ZREVRANK(key string, member any) int {
|
||||
return jr.rd.ZREVRANK(key, member)
|
||||
}
|
||||
func (jr *jsRedis) ZSCORE(key string, member any) float64 {
|
||||
return jr.rd.ZSCORE(key, member)
|
||||
}
|
||||
|
||||
// Write Operations (Restricted in SafeMode)
|
||||
func (jr *jsRedis) SET(key string, value any) bool {
|
||||
if jr.checkSafe() != nil {
|
||||
return false
|
||||
}
|
||||
return jr.rd.SET(key, value)
|
||||
}
|
||||
func (jr *jsRedis) SETEX(key string, seconds int, value any) bool {
|
||||
if jr.checkSafe() != nil {
|
||||
return false
|
||||
}
|
||||
return jr.rd.SETEX(key, seconds, value)
|
||||
}
|
||||
func (jr *jsRedis) SETNX(key string, value any) bool {
|
||||
if jr.checkSafe() != nil {
|
||||
return false
|
||||
}
|
||||
return jr.rd.SETNX(key, value)
|
||||
}
|
||||
func (jr *jsRedis) DEL(keys ...string) int {
|
||||
if jr.checkSafe() != nil {
|
||||
return 0
|
||||
}
|
||||
return jr.rd.DEL(keys...)
|
||||
}
|
||||
func (jr *jsRedis) EXPIRE(key string, second int) bool {
|
||||
if jr.checkSafe() != nil {
|
||||
return false
|
||||
}
|
||||
return jr.rd.EXPIRE(key, second)
|
||||
}
|
||||
func (jr *jsRedis) INCR(key string) int64 {
|
||||
if jr.checkSafe() != nil {
|
||||
return 0
|
||||
}
|
||||
return jr.rd.INCR(key)
|
||||
}
|
||||
func (jr *jsRedis) INCRBY(key string, delta int64) int64 {
|
||||
if jr.checkSafe() != nil {
|
||||
return 0
|
||||
}
|
||||
return jr.rd.INCRBY(key, delta)
|
||||
}
|
||||
func (jr *jsRedis) DECR(key string, delta int64) int64 {
|
||||
if jr.checkSafe() != nil {
|
||||
return 0
|
||||
}
|
||||
return jr.rd.DECR(key, delta)
|
||||
}
|
||||
func (jr *jsRedis) HSET(key, field string, value any) bool {
|
||||
if jr.checkSafe() != nil {
|
||||
return false
|
||||
}
|
||||
return jr.rd.HSET(key, field, value)
|
||||
}
|
||||
func (jr *jsRedis) HMSET(key string, fieldAndValues ...any) bool {
|
||||
if jr.checkSafe() != nil {
|
||||
return false
|
||||
}
|
||||
return jr.rd.HMSET(key, fieldAndValues...)
|
||||
}
|
||||
func (jr *jsRedis) HDEL(key string, fields ...string) int {
|
||||
if jr.checkSafe() != nil {
|
||||
return 0
|
||||
}
|
||||
return jr.rd.HDEL(key, fields...)
|
||||
}
|
||||
func (jr *jsRedis) HINCRBY(key, field string, delta int64) int64 {
|
||||
if jr.checkSafe() != nil {
|
||||
return 0
|
||||
}
|
||||
return jr.rd.HINCRBY(key, field, delta)
|
||||
}
|
||||
func (jr *jsRedis) LPUSH(key string, values ...string) int {
|
||||
if jr.checkSafe() != nil {
|
||||
return 0
|
||||
}
|
||||
return jr.rd.LPUSH(key, values...)
|
||||
}
|
||||
func (jr *jsRedis) RPUSH(key string, values ...string) int {
|
||||
if jr.checkSafe() != nil {
|
||||
return 0
|
||||
}
|
||||
return jr.rd.RPUSH(key, values...)
|
||||
}
|
||||
func (jr *jsRedis) LPOP(key string) *Result {
|
||||
if jr.checkSafe() != nil {
|
||||
return &Result{Error: errSafeMode}
|
||||
}
|
||||
return jr.rd.LPOP(key)
|
||||
}
|
||||
func (jr *jsRedis) RPOP(key string) *Result {
|
||||
if jr.checkSafe() != nil {
|
||||
return &Result{Error: errSafeMode}
|
||||
}
|
||||
return jr.rd.RPOP(key)
|
||||
}
|
||||
func (jr *jsRedis) SADD(key string, values ...any) int {
|
||||
if jr.checkSafe() != nil {
|
||||
return 0
|
||||
}
|
||||
return jr.rd.SADD(key, values...)
|
||||
}
|
||||
func (jr *jsRedis) SREM(key string, values ...any) int {
|
||||
if jr.checkSafe() != nil {
|
||||
return 0
|
||||
}
|
||||
return jr.rd.SREM(key, values...)
|
||||
}
|
||||
func (jr *jsRedis) ZADD(key string, score float64, member any) bool {
|
||||
if jr.checkSafe() != nil {
|
||||
return false
|
||||
}
|
||||
return jr.rd.ZADD(key, score, member)
|
||||
}
|
||||
func (jr *jsRedis) ZREM(key string, members ...any) int {
|
||||
if jr.checkSafe() != nil {
|
||||
return 0
|
||||
}
|
||||
return jr.rd.ZREM(key, members...)
|
||||
}
|
||||
|
||||
// Special: DO command must be restricted entirely in SafeMode to prevent bypassing
|
||||
func (jr *jsRedis) DO(cmd string, args ...any) *Result {
|
||||
if jr.checkSafe() != nil {
|
||||
return &Result{Error: errSafeMode}
|
||||
}
|
||||
return jr.rd.Do(cmd, args...)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user