From b27bfe348f77e9afa8f6e818f9e6ac51775a260e Mon Sep 17 00:00:00 2001 From: Xirui Date: Mon, 15 Jun 2020 13:44:48 +1200 Subject: [PATCH 1/9] add function sinatures to acl cmds --- command.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/command.ts b/command.ts index 84c74277..d3cd073f 100644 --- a/command.ts +++ b/command.ts @@ -396,6 +396,18 @@ export type RedisCommands = { // Cluster // cluster // // Server + acl_cat(): Promise; + acl_deluser(): Promise; + acl_genpass(): Promise; + acl_getuser(): Promise; + acl_help(): Promise; + acl_list(): Promise; + acl_load(): Promise; + acl_log(): Promise; + acl_save(): Promise; + acl_setuser(): Promise; + acl_users(): Promise; + acl_whoami(): Promise; bgrewriteaof(): Promise; bgsave(): Promise; // client // From b1fc74b0a413c8ee3d47c50b9b49d522065905a1 Mon Sep 17 00:00:00 2001 From: Xirui Date: Tue, 16 Jun 2020 08:34:46 +1200 Subject: [PATCH 2/9] implement acl commands --- command.ts | 16 ++++++++-------- redis.ts | 28 ++++++++++++++++++++++++++++ redis_test.ts | 1 + tests/acl_cmd_test.ts | 21 +++++++++++++++++++++ 4 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 tests/acl_cmd_test.ts diff --git a/command.ts b/command.ts index d3cd073f..6e8470c4 100644 --- a/command.ts +++ b/command.ts @@ -396,16 +396,16 @@ export type RedisCommands = { // Cluster // cluster // // Server - acl_cat(): Promise; - acl_deluser(): Promise; - acl_genpass(): Promise; - acl_getuser(): Promise; - acl_help(): Promise; - acl_list(): Promise; + // acl_cat(): Promise; + // acl_deluser(): Promise; + // acl_genpass(): Promise; + acl_getuser(parameter: string): Promise; + acl_help(): Promise; + acl_list(): Promise; acl_load(): Promise; - acl_log(): Promise; + // acl_log(): Promise; acl_save(): Promise; - acl_setuser(): Promise; + // acl_setuser(): Promise; acl_users(): Promise; acl_whoami(): Promise; bgrewriteaof(): Promise; diff --git a/redis.ts b/redis.ts index 3dccd918..aaf3f7c9 100644 --- a/redis.ts +++ b/redis.ts @@ -89,6 +89,34 @@ class RedisImpl implements RedisCommands { return reply as Status | BulkNil; } + acl_getuser(username: string) { + return this.execArrayReply("ACL", "GETUSER", username); + } + + acl_help() { + return this.execArrayReply("ACL", "HELP"); + } + + acl_list() { + return this.execArrayReply("ACL", "LIST"); + } + + acl_load() { + return this.execStatusReply("ACL", "LOAD"); + } + + acl_save() { + return this.execStatusReply("ACL", "SAVE"); + } + + acl_users() { + return this.execStatusReply("ACL", "USERS"); + } + + acl_whoami() { + return this.execStatusReply("ACL", "WHOAMI"); + } + append(key: string, value: string | number) { return this.execIntegerReply("APPEND", key, value); } diff --git a/redis_test.ts b/redis_test.ts index 47af3785..dcfd4d0e 100644 --- a/redis_test.ts +++ b/redis_test.ts @@ -8,3 +8,4 @@ import "./tests/set_test.ts"; import "./tests/sorted_set_test.ts"; import "./tests/string_test.ts"; import "./tests/key_test.ts"; +import "./tests/acl_cmd_test.ts"; diff --git a/tests/acl_cmd_test.ts b/tests/acl_cmd_test.ts new file mode 100644 index 00000000..fdf7e4b4 --- /dev/null +++ b/tests/acl_cmd_test.ts @@ -0,0 +1,21 @@ +import { makeTest } from "./test_util.ts"; +import { + assertEquals, +} from "../vendor/https/deno.land/std/testing/asserts.ts"; + +const { test, client } = await makeTest("acl_cmd"); + +test("whoami", async () => { + assertEquals(await client.acl_whoami(), "default"); +}); + +test("list", async () => { + assertEquals(await client.acl_list(), ["user default on nopass ~* +@all"]); +}); + +test("getuser", async () => { + assertEquals(await client.acl_getuser("default"), + [ "flags",[ "on", "allkeys", "allcommands", "nopass" ], + "passwords", [], "commands", "+@all", "keys", [ "*" ] + ]); +}); From 5e9b86d33a12a2ba7486b9d1c75008716f6a4b26 Mon Sep 17 00:00:00 2001 From: Xirui Date: Tue, 16 Jun 2020 13:15:48 +1200 Subject: [PATCH 3/9] implement acl cat --- command.ts | 2 +- redis.ts | 8 ++++++ tests/acl_cmd_test.ts | 61 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/command.ts b/command.ts index 6e8470c4..12454293 100644 --- a/command.ts +++ b/command.ts @@ -396,7 +396,7 @@ export type RedisCommands = { // Cluster // cluster // // Server - // acl_cat(): Promise; + acl_cat(parameter?: string): Promise; // acl_deluser(): Promise; // acl_genpass(): Promise; acl_getuser(parameter: string): Promise; diff --git a/redis.ts b/redis.ts index aaf3f7c9..5813f6ae 100644 --- a/redis.ts +++ b/redis.ts @@ -89,6 +89,14 @@ class RedisImpl implements RedisCommands { return reply as Status | BulkNil; } + acl_cat(categoryname?: string) { + if (categoryname) { + return this.execArrayReply("ACL", "CAT", categoryname); + } else { + return this.execArrayReply("ACL", "CAT"); + } + } + acl_getuser(username: string) { return this.execArrayReply("ACL", "GETUSER", username); } diff --git a/tests/acl_cmd_test.ts b/tests/acl_cmd_test.ts index fdf7e4b4..c3a8f774 100644 --- a/tests/acl_cmd_test.ts +++ b/tests/acl_cmd_test.ts @@ -19,3 +19,64 @@ test("getuser", async () => { "passwords", [], "commands", "+@all", "keys", [ "*" ] ]); }); + +test("cat", async () => { + assertEquals(await client.acl_cat(), + [ + "keyspace", + "read", + "write", + "set", + "sortedset", + "list", + "hash", + "string", + "bitmap", + "hyperloglog", + "geo", + "stream", + "pubsub", + "admin", + "fast", + "slow", + "blocking", + "dangerous", + "connection", + "transaction", + "scripting" + ]); + assertEquals(await client.acl_cat("dangerous"), + [ + "lastsave", + "shutdown", + "module", + "monitor", + "role", + "client", + "replconf", + "config", + "pfselftest", + "save", + "replicaof", + "restore-asking", + "restore", + "latency", + "swapdb", + "slaveof", + "bgsave", + "debug", + "bgrewriteaof", + "sync", + "flushdb", + "keys", + "psync", + "pfdebug", + "flushall", + "cluster", + "info", + "migrate", + "acl", + "sort", + "slowlog" + ]); +}); From 6d356f59c9f65d922286658fad45cc8e2adb292a Mon Sep 17 00:00:00 2001 From: Xirui Date: Tue, 16 Jun 2020 13:25:02 +1200 Subject: [PATCH 4/9] implement acl deluser --- command.ts | 2 +- redis.ts | 4 ++++ tests/acl_cmd_test.ts | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/command.ts b/command.ts index 12454293..aa10b30f 100644 --- a/command.ts +++ b/command.ts @@ -397,7 +397,7 @@ export type RedisCommands = { // cluster // // Server acl_cat(parameter?: string): Promise; - // acl_deluser(): Promise; + acl_deluser(parameter: string): Promise; // acl_genpass(): Promise; acl_getuser(parameter: string): Promise; acl_help(): Promise; diff --git a/redis.ts b/redis.ts index 5813f6ae..6ddb6532 100644 --- a/redis.ts +++ b/redis.ts @@ -97,6 +97,10 @@ class RedisImpl implements RedisCommands { } } + acl_deluser(username: string) { + return this.execIntegerReply("ACL", "DELUSER", username); + } + acl_getuser(username: string) { return this.execArrayReply("ACL", "GETUSER", username); } diff --git a/tests/acl_cmd_test.ts b/tests/acl_cmd_test.ts index c3a8f774..d0936d78 100644 --- a/tests/acl_cmd_test.ts +++ b/tests/acl_cmd_test.ts @@ -80,3 +80,7 @@ test("cat", async () => { "slowlog" ]); }); + +test("deluser", async () => { + assertEquals(await client.acl_deluser("balhblahblah"), 0); +}); From 5bd89afb7dad47f8ec43859707fd84464be6d607 Mon Sep 17 00:00:00 2001 From: Xirui Date: Wed, 17 Jun 2020 12:52:14 +1200 Subject: [PATCH 5/9] implement rest acl commands --- command.ts | 9 +++++---- redis.ts | 28 +++++++++++++++++++++++++++- tests/acl_cmd_test.ts | 40 +++++++++++++++++++++++++++++++++++----- 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/command.ts b/command.ts index aa10b30f..27ae4de7 100644 --- a/command.ts +++ b/command.ts @@ -396,17 +396,18 @@ export type RedisCommands = { // Cluster // cluster // // Server + acl_auth(username: string, passwd: string): Promise; acl_cat(parameter?: string): Promise; acl_deluser(parameter: string): Promise; - // acl_genpass(): Promise; + acl_genpass(parameter?: number): Promise; acl_getuser(parameter: string): Promise; acl_help(): Promise; acl_list(): Promise; acl_load(): Promise; - // acl_log(): Promise; + acl_log(parameter: string | number): Promise; acl_save(): Promise; - // acl_setuser(): Promise; - acl_users(): Promise; + acl_setuser(username: string, rule: string): Promise; + acl_users(): Promise; acl_whoami(): Promise; bgrewriteaof(): Promise; bgsave(): Promise; diff --git a/redis.ts b/redis.ts index 6ddb6532..04c77802 100644 --- a/redis.ts +++ b/redis.ts @@ -89,6 +89,10 @@ class RedisImpl implements RedisCommands { return reply as Status | BulkNil; } + acl_auth(username: string, passwd: string) { + return this.execStatusReply("AUTH", username, passwd); + } + acl_cat(categoryname?: string) { if (categoryname) { return this.execArrayReply("ACL", "CAT", categoryname); @@ -101,6 +105,14 @@ class RedisImpl implements RedisCommands { return this.execIntegerReply("ACL", "DELUSER", username); } + acl_genpass(bits?: Integer) { + if (bits) { + return this.execStatusReply("ACL", "GENPASS", bits); + } else { + return this.execStatusReply("ACL", "GENPASS"); + } + } + acl_getuser(username: string) { return this.execArrayReply("ACL", "GETUSER", username); } @@ -117,12 +129,26 @@ class RedisImpl implements RedisCommands { return this.execStatusReply("ACL", "LOAD"); } + acl_log(param: string|number) { + if (param === "RESET" || param === "reset") { + return this.execStatusReply("ACL", "LOG", "RESET"); + } + // if (typeof param == "number") { + return this.execArrayReply("ACL", "LOG", param); + // } + // return this.execStatusReply("ACL", "LOAD"); + } + acl_save() { return this.execStatusReply("ACL", "SAVE"); } + acl_setuser(username: string, rule: string) { + return this.execStatusReply("ACL", "SETUSER", username, rule); + } + acl_users() { - return this.execStatusReply("ACL", "USERS"); + return this.execArrayReply("ACL", "USERS"); } acl_whoami() { diff --git a/tests/acl_cmd_test.ts b/tests/acl_cmd_test.ts index d0936d78..af4448fd 100644 --- a/tests/acl_cmd_test.ts +++ b/tests/acl_cmd_test.ts @@ -21,7 +21,7 @@ test("getuser", async () => { }); test("cat", async () => { - assertEquals(await client.acl_cat(), + assertEquals((await client.acl_cat()).sort(), [ "keyspace", "read", @@ -44,8 +44,8 @@ test("cat", async () => { "connection", "transaction", "scripting" - ]); - assertEquals(await client.acl_cat("dangerous"), + ].sort()); + assertEquals((await client.acl_cat("dangerous")).sort(), [ "lastsave", "shutdown", @@ -78,9 +78,39 @@ test("cat", async () => { "acl", "sort", "slowlog" - ]); + ].sort()); +}); + +test("users", async () => { + assertEquals(await client.acl_users(), ["default"]) +}); + +test("acl_setuser", async () => { + assertEquals(await client.acl_setuser("alan", "+get"), "OK") + assertEquals(await client.acl_deluser("alan"), 1); }); test("deluser", async () => { - assertEquals(await client.acl_deluser("balhblahblah"), 0); + assertEquals(await client.acl_deluser("alan"), 0); +}); + +test("genpass", async () => { + assertEquals((await client.acl_genpass()).length, 64); + let testlen = 32 + assertEquals((await client.acl_genpass(testlen)).length, testlen / 4); +}); + +test("aclauth", async () => { + assertEquals(await client.acl_auth("default", ""), "OK") +}); + +test("log", async () => { + let username = "balh" + try { + await client.acl_auth(username, username) + } catch (error) { + // skip invalid username-password pair error + } + assertEquals((await client.acl_log(1))[0][9], username); + assertEquals((await client.acl_log("RESET")), "OK"); }); From b55e5fe32d650a84bc9807ed429a39efcace5138 Mon Sep 17 00:00:00 2001 From: Xirui Date: Wed, 17 Jun 2020 13:41:46 +1200 Subject: [PATCH 6/9] implement module commands --- command.ts | 3 +++ redis.ts | 12 ++++++++++++ tests/acl_cmd_test.ts | 4 ++++ 3 files changed, 19 insertions(+) diff --git a/command.ts b/command.ts index 27ae4de7..d3c6915b 100644 --- a/command.ts +++ b/command.ts @@ -450,6 +450,9 @@ export type RedisCommands = { samples?: number; }, ): Promise; + module_list(): Promise; + module_load(path: string, args: string): Promise; + module_unload(name: string): Promise; monitor(): void; role(): Promise< | ["master", Integer, BulkString[][]] diff --git a/redis.ts b/redis.ts index 04c77802..3f5d63f1 100644 --- a/redis.ts +++ b/redis.ts @@ -728,6 +728,18 @@ class RedisImpl implements RedisCommands { return this.execStatusReply("MIGRATE", ...args); } + module_list() { + return this.execArrayReply("MODULE", "LIST"); + } + + module_load(path: string, args: string) { + return this.execStatusReply("MODULE", "LOAD", path, args); + } + + module_unload(name: string) { + return this.execStatusReply("MODULE", "UNLOAD", name); + } + monitor() { throw new Error("not supported yet"); } diff --git a/tests/acl_cmd_test.ts b/tests/acl_cmd_test.ts index af4448fd..fe88abd5 100644 --- a/tests/acl_cmd_test.ts +++ b/tests/acl_cmd_test.ts @@ -114,3 +114,7 @@ test("log", async () => { assertEquals((await client.acl_log(1))[0][9], username); assertEquals((await client.acl_log("RESET")), "OK"); }); + +test("module_list", async () => { + assertEquals(await client.module_list(), []); +}); From c3b4ae1b1346a34d72e042881369fd5a2dfcc6a0 Mon Sep 17 00:00:00 2001 From: Xirui Date: Wed, 17 Jun 2020 19:49:02 +1200 Subject: [PATCH 7/9] remove comment --- redis.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/redis.ts b/redis.ts index 3f5d63f1..7bb447be 100644 --- a/redis.ts +++ b/redis.ts @@ -133,10 +133,7 @@ class RedisImpl implements RedisCommands { if (param === "RESET" || param === "reset") { return this.execStatusReply("ACL", "LOG", "RESET"); } - // if (typeof param == "number") { return this.execArrayReply("ACL", "LOG", param); - // } - // return this.execStatusReply("ACL", "LOAD"); } acl_save() { From b112a7c8843a518522ac89a2e24adec7f0c22ecc Mon Sep 17 00:00:00 2001 From: Xirui Date: Mon, 22 Jun 2020 13:36:19 +1200 Subject: [PATCH 8/9] overload auth function --- command.ts | 2 +- redis.ts | 7 +++++-- tests/acl_cmd_test.ts | 8 ++++---- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/command.ts b/command.ts index d3c6915b..72a37991 100644 --- a/command.ts +++ b/command.ts @@ -11,6 +11,7 @@ export type ConditionalArray = Raw[]; export type RedisCommands = { // Connection auth(password: string): Promise; + auth(username: string, password: string): Promise; echo(message: string): Promise; ping(): Promise; ping(message: string): Promise; @@ -396,7 +397,6 @@ export type RedisCommands = { // Cluster // cluster // // Server - acl_auth(username: string, passwd: string): Promise; acl_cat(parameter?: string): Promise; acl_deluser(parameter: string): Promise; acl_genpass(parameter?: number): Promise; diff --git a/redis.ts b/redis.ts index 7bb447be..1d2891c2 100644 --- a/redis.ts +++ b/redis.ts @@ -156,8 +156,11 @@ class RedisImpl implements RedisCommands { return this.execIntegerReply("APPEND", key, value); } - auth(password: string) { - return this.execStatusReply("AUTH", password); + auth(param1: string, param2?: string) { + if (typeof param2 === "string") { + return this.execStatusReply("AUTH", param1, param2); + } + return this.execStatusReply("AUTH", param1); } bgrewriteaof() { diff --git a/tests/acl_cmd_test.ts b/tests/acl_cmd_test.ts index fe88abd5..96f7c8e1 100644 --- a/tests/acl_cmd_test.ts +++ b/tests/acl_cmd_test.ts @@ -101,17 +101,17 @@ test("genpass", async () => { }); test("aclauth", async () => { - assertEquals(await client.acl_auth("default", ""), "OK") + assertEquals(await client.auth("default", ""), "OK") }); test("log", async () => { - let username = "balh" + let randString = "balh" try { - await client.acl_auth(username, username) + await client.auth(randString, randString) } catch (error) { // skip invalid username-password pair error } - assertEquals((await client.acl_log(1))[0][9], username); + assertEquals((await client.acl_log(1))[0][9], randString); assertEquals((await client.acl_log("RESET")), "OK"); }); From 608375cd46986b21ed476d1fdc2a29327377e784 Mon Sep 17 00:00:00 2001 From: Xirui Date: Mon, 22 Jun 2020 13:40:30 +1200 Subject: [PATCH 9/9] remove acl_auth --- redis.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/redis.ts b/redis.ts index 1d2891c2..dde93477 100644 --- a/redis.ts +++ b/redis.ts @@ -89,10 +89,6 @@ class RedisImpl implements RedisCommands { return reply as Status | BulkNil; } - acl_auth(username: string, passwd: string) { - return this.execStatusReply("AUTH", username, passwd); - } - acl_cat(categoryname?: string) { if (categoryname) { return this.execArrayReply("ACL", "CAT", categoryname);