From 166b6f64f394dea1258abf7491f4b9a9d5fa9f98 Mon Sep 17 00:00:00 2001 From: Dmitry Polyakovsky Date: Mon, 24 Feb 2025 12:00:08 -0800 Subject: [PATCH] added functions to get_client_id, name, username, info and certificate added example and tests Signed-off-by: Dmitry Polyakovsky --- Cargo.toml | 4 ++++ examples/client.rs | 30 ++++++++++++++++++++++++++++++ src/context/mod.rs | 33 ++++++++++++++++++++++++++++++++- tests/integration.rs | 13 +++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 examples/client.rs diff --git a/Cargo.toml b/Cargo.toml index 76c2cef..1ffbeaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -125,6 +125,10 @@ crate-type = ["cdylib"] name = "expire" crate-type = ["cdylib"] +[[example]] +name = "client" +crate-type = ["cdylib"] + [dependencies] bitflags = "2.8.0" libc = "0.2" diff --git a/examples/client.rs b/examples/client.rs new file mode 100644 index 0000000..97ecc09 --- /dev/null +++ b/examples/client.rs @@ -0,0 +1,30 @@ +use valkey_module::alloc::ValkeyAlloc; +use valkey_module::{valkey_module, Context, ValkeyResult, ValkeyString}; + +valkey_module! { + name: "client", + version: 1, + allocator: (ValkeyAlloc, ValkeyAlloc), + data_types: [], + commands: [ + ["client.id", get_client_id, "readonly", 1, 1, 1], + ] +} + +fn get_client_id(ctx: &Context, _args: Vec) -> ValkeyResult { + let client_id = ctx.get_client_id(); + ctx.log_notice(&format!( + "client_username: {:?}", + ctx.get_client_username().to_string() + )); + ctx.log_notice(&format!( + "client_name: {:?}", + ctx.get_client_name().to_string() + )); + ctx.log_notice(&format!( + "client_cert: {:?}", + ctx.get_client_cert().to_string() + )); + ctx.log_notice(&format!("client_info: {:?}", ctx.get_client_info())); + Ok((client_id as i64).into()) +} diff --git a/src/context/mod.rs b/src/context/mod.rs index b31cb2e..d43939c 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -14,7 +14,8 @@ use crate::redisvalue::ValkeyValueKey; use crate::{ add_info_begin_dict_field, add_info_end_dict_field, add_info_field_double, add_info_field_long_long, add_info_field_str, add_info_field_unsigned_long_long, raw, utils, - Status, + RedisModule_GetClientCertificate, RedisModule_GetClientId, RedisModule_GetClientInfoById, + RedisModule_GetClientNameById, RedisModule_GetClientUserNameById, Status, }; use crate::{add_info_section, ValkeyResult}; use crate::{ValkeyError, ValkeyString, ValkeyValue}; @@ -829,6 +830,36 @@ impl Context { .map_err(|_e| ValkeyError::Str("User does not have permissions on key")) } + pub fn get_client_id(&self) -> u64 { + unsafe { RedisModule_GetClientId.unwrap()(self.ctx) } + } + + pub fn get_client_name(&self) -> ValkeyString { + let client_id = self.get_client_id(); + let client_name = unsafe { RedisModule_GetClientNameById.unwrap()(self.ctx, client_id) }; + ValkeyString::from_redis_module_string(self.ctx, client_name) + } + + pub fn get_client_username(&self) -> ValkeyString { + let client_id = self.get_client_id(); + let client_username = + unsafe { RedisModule_GetClientUserNameById.unwrap()(self.ctx, client_id) }; + ValkeyString::from_redis_module_string(self.ctx, client_username) + } + + pub fn get_client_cert(&self) -> ValkeyString { + let client_id = self.get_client_id(); + let client_cert = unsafe { RedisModule_GetClientCertificate.unwrap()(self.ctx, client_id) }; + ValkeyString::from_redis_module_string(self.ctx, client_cert) + } + + pub fn get_client_info(&self) -> ValkeyValue { + let client_id = self.get_client_id(); + let client_info = + unsafe { RedisModule_GetClientInfoById.unwrap()(self.ctx as *mut c_void, client_id) }; + (client_info as i64).into() + } + api!( [RedisModule_AddPostNotificationJob], /// When running inside a key space notification callback, it is dangerous and highly discouraged to perform any write diff --git a/tests/integration.rs b/tests/integration.rs index fd7b5cf..9c4c502 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1014,3 +1014,16 @@ fn test_acl_categories() -> Result<()> { assert!(response_data.contains(&search_str)); Ok(()) } + +#[test] +fn test_client() -> Result<()> { + let port = 6507; + let _guards = + vec![start_valkey_server_with_module("client", port) + .with_context(|| FAILED_TO_START_SERVER)?]; + let mut con = get_valkey_connection(port).with_context(|| FAILED_TO_CONNECT_TO_SERVER)?; + redis::cmd("client.id") + .exec(&mut con) + .with_context(|| "failed execute client.id")?; + Ok(()) +}