Skip to content

Commit 31ba855

Browse files
SoulPancakektsivkovelena-kolevskamonkey92t
authored
feat: Add ACL LOG (#2536)
* feat: Add ACL LOG Signed-off-by: monkey92t <[email protected]> --------- Signed-off-by: monkey92t <[email protected]> Co-authored-by: Anuragkillswitch <[email protected]> Co-authored-by: ktsivkov <[email protected]> Co-authored-by: Elena Kolevska <[email protected]> Co-authored-by: monkey92t <[email protected]>
1 parent fcb3506 commit 31ba855

File tree

3 files changed

+177
-0
lines changed

3 files changed

+177
-0
lines changed

command.go

+109
Original file line numberDiff line numberDiff line change
@@ -5057,3 +5057,112 @@ func parseClientInfo(txt string) (info *ClientInfo, err error) {
50575057

50585058
return info, nil
50595059
}
5060+
5061+
// -------------------------------------------
5062+
5063+
type ACLLogEntry struct {
5064+
Count int64
5065+
Reason string
5066+
Context string
5067+
Object string
5068+
Username string
5069+
AgeSeconds float64
5070+
ClientInfo *ClientInfo
5071+
EntryID int64
5072+
TimestampCreated int64
5073+
TimestampLastUpdated int64
5074+
}
5075+
5076+
type ACLLogCmd struct {
5077+
baseCmd
5078+
5079+
val []*ACLLogEntry
5080+
}
5081+
5082+
var _ Cmder = (*ACLLogCmd)(nil)
5083+
5084+
func NewACLLogCmd(ctx context.Context, args ...interface{}) *ACLLogCmd {
5085+
return &ACLLogCmd{
5086+
baseCmd: baseCmd{
5087+
ctx: ctx,
5088+
args: args,
5089+
},
5090+
}
5091+
}
5092+
5093+
func (cmd *ACLLogCmd) SetVal(val []*ACLLogEntry) {
5094+
cmd.val = val
5095+
}
5096+
5097+
func (cmd *ACLLogCmd) Val() []*ACLLogEntry {
5098+
return cmd.val
5099+
}
5100+
5101+
func (cmd *ACLLogCmd) Result() ([]*ACLLogEntry, error) {
5102+
return cmd.Val(), cmd.Err()
5103+
}
5104+
5105+
func (cmd *ACLLogCmd) String() string {
5106+
return cmdString(cmd, cmd.val)
5107+
}
5108+
5109+
func (cmd *ACLLogCmd) readReply(rd *proto.Reader) error {
5110+
n, err := rd.ReadArrayLen()
5111+
if err != nil {
5112+
return err
5113+
}
5114+
5115+
cmd.val = make([]*ACLLogEntry, n)
5116+
for i := 0; i < n; i++ {
5117+
cmd.val[i] = &ACLLogEntry{}
5118+
entry := cmd.val[i]
5119+
respLen, err := rd.ReadMapLen()
5120+
if err != nil {
5121+
return err
5122+
}
5123+
for j := 0; j < respLen; j++ {
5124+
key, err := rd.ReadString()
5125+
if err != nil {
5126+
return err
5127+
}
5128+
5129+
switch key {
5130+
case "count":
5131+
entry.Count, err = rd.ReadInt()
5132+
case "reason":
5133+
entry.Reason, err = rd.ReadString()
5134+
case "context":
5135+
entry.Context, err = rd.ReadString()
5136+
case "object":
5137+
entry.Object, err = rd.ReadString()
5138+
case "username":
5139+
entry.Username, err = rd.ReadString()
5140+
case "age-seconds":
5141+
entry.AgeSeconds, err = rd.ReadFloat()
5142+
case "client-info":
5143+
txt, err := rd.ReadString()
5144+
if err != nil {
5145+
return err
5146+
}
5147+
entry.ClientInfo, err = parseClientInfo(strings.TrimSpace(txt))
5148+
if err != nil {
5149+
return err
5150+
}
5151+
case "entry-id":
5152+
entry.EntryID, err = rd.ReadInt()
5153+
case "timestamp-created":
5154+
entry.TimestampCreated, err = rd.ReadInt()
5155+
case "timestamp-last-updated":
5156+
entry.TimestampLastUpdated, err = rd.ReadInt()
5157+
default:
5158+
return fmt.Errorf("redis: unexpected key %q in ACL LOG reply", key)
5159+
}
5160+
5161+
if err != nil {
5162+
return err
5163+
}
5164+
}
5165+
}
5166+
5167+
return nil
5168+
}

commands.go

+19
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,8 @@ type Cmdable interface {
500500
GeoHash(ctx context.Context, key string, members ...string) *StringSliceCmd
501501

502502
ACLDryRun(ctx context.Context, username string, command ...interface{}) *StringCmd
503+
ACLLog(ctx context.Context, count int64) *ACLLogCmd
504+
ACLLogReset(ctx context.Context) *StatusCmd
503505

504506
ModuleLoadex(ctx context.Context, conf *ModuleLoadexConfig) *StringCmd
505507
}
@@ -3946,3 +3948,20 @@ func (c cmdable) ModuleLoadex(ctx context.Context, conf *ModuleLoadexConfig) *St
39463948
_ = c(ctx, cmd)
39473949
return cmd
39483950
}
3951+
3952+
func (c cmdable) ACLLog(ctx context.Context, count int64) *ACLLogCmd {
3953+
args := make([]interface{}, 0, 3)
3954+
args = append(args, "acl", "log")
3955+
if count > 0 {
3956+
args = append(args, count)
3957+
}
3958+
cmd := NewACLLogCmd(ctx, args...)
3959+
_ = c(ctx, cmd)
3960+
return cmd
3961+
}
3962+
3963+
func (c cmdable) ACLLogReset(ctx context.Context) *StatusCmd {
3964+
cmd := NewStatusCmd(ctx, "acl", "log", "reset")
3965+
_ = c(ctx, cmd)
3966+
return cmd
3967+
}

commands_test.go

+49
Original file line numberDiff line numberDiff line change
@@ -1985,6 +1985,55 @@ var _ = Describe("Commands", func() {
19851985

19861986
Expect(args).To(Equal(expectedArgs))
19871987
})
1988+
1989+
It("should ACL LOG", func() {
1990+
1991+
err := client.Do(ctx, "acl", "setuser", "test", ">test", "on", "allkeys", "+get").Err()
1992+
Expect(err).NotTo(HaveOccurred())
1993+
1994+
clientAcl := redis.NewClient(redisOptions())
1995+
clientAcl.Options().Username = "test"
1996+
clientAcl.Options().Password = "test"
1997+
clientAcl.Options().DB = 0
1998+
_ = clientAcl.Set(ctx, "mystring", "foo", 0).Err()
1999+
_ = clientAcl.HSet(ctx, "myhash", "foo", "bar").Err()
2000+
_ = clientAcl.SAdd(ctx, "myset", "foo", "bar").Err()
2001+
2002+
logEntries, err := client.ACLLog(ctx, 10).Result()
2003+
Expect(err).NotTo(HaveOccurred())
2004+
Expect(len(logEntries)).To(Equal(3))
2005+
2006+
for _, entry := range logEntries {
2007+
Expect(entry.Count).To(BeNumerically("==", 1))
2008+
Expect(entry.Reason).To(Equal("command"))
2009+
Expect(entry.Context).To(Equal("toplevel"))
2010+
Expect(entry.Object).NotTo(BeEmpty())
2011+
Expect(entry.Username).To(Equal("test"))
2012+
Expect(entry.AgeSeconds).To(BeNumerically(">=", 0))
2013+
Expect(entry.ClientInfo).NotTo(BeNil())
2014+
Expect(entry.EntryID).To(BeNumerically(">=", 0))
2015+
Expect(entry.TimestampCreated).To(BeNumerically(">=", 0))
2016+
Expect(entry.TimestampLastUpdated).To(BeNumerically(">=", 0))
2017+
}
2018+
2019+
limitedLogEntries, err := client.ACLLog(ctx, 2).Result()
2020+
Expect(err).NotTo(HaveOccurred())
2021+
Expect(len(limitedLogEntries)).To(Equal(2))
2022+
2023+
})
2024+
2025+
It("should ACL LOG RESET", func() {
2026+
// Call ACL LOG RESET
2027+
resetCmd := client.ACLLogReset(ctx)
2028+
Expect(resetCmd.Err()).NotTo(HaveOccurred())
2029+
Expect(resetCmd.Val()).To(Equal("OK"))
2030+
2031+
// Verify that the log is empty after the reset
2032+
logEntries, err := client.ACLLog(ctx, 10).Result()
2033+
Expect(err).NotTo(HaveOccurred())
2034+
Expect(len(logEntries)).To(Equal(0))
2035+
})
2036+
19882037
})
19892038

19902039
Describe("hashes", func() {

0 commit comments

Comments
 (0)