Skip to content

Commit 6d91343

Browse files
committed
addressed comments
Signed-off-by: Lior Sventitzky <[email protected]>
1 parent 409057a commit 6d91343

File tree

6 files changed

+114
-35
lines changed

6 files changed

+114
-35
lines changed

glide-core/redis-rs/redis/src/cluster_async/mod.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -2283,13 +2283,14 @@ where
22832283
Ok(Response::Single(Value::Okay))
22842284
}
22852285
Operation::GetUsername => {
2286-
let username = core
2286+
let username = match core
22872287
.get_cluster_param(|params| params.username.clone())
2288-
.expect(MUTEX_WRITE_ERR);
2289-
Ok(Response::Single(match username {
2290-
Some(u) => Value::SimpleString(u),
2288+
.expect(MUTEX_READ_ERR)
2289+
{
2290+
Some(username) => Value::SimpleString(username),
22912291
None => Value::Nil,
2292-
}))
2292+
};
2293+
Ok(Response::Single(username))
22932294
}
22942295
},
22952296
}

glide-core/src/client/mod.rs

+16-11
Original file line numberDiff line numberDiff line change
@@ -525,23 +525,28 @@ impl Client {
525525
Some(ResponsePolicy::AllSucceeded),
526526
));
527527
let mut cmd = redis::cmd("AUTH");
528-
match self.internal_client {
529-
ClientWrapper::Cluster { ref mut client } => {
530-
if let Ok(Value::SimpleString(username)) = client.get_username().await {
531-
cmd.arg(username);
532-
}
533-
}
534-
ClientWrapper::Standalone(ref client) => {
535-
if let Some(username) = client.get_username().await {
536-
cmd.arg(username);
537-
}
538-
}
528+
if let Some(username) = self.get_username().await {
529+
cmd.arg(username);
539530
}
540531
cmd.arg(password);
541532
self.send_command(&cmd, Some(routing)).await
542533
}
543534
}
544535
}
536+
537+
async fn get_username(&mut self) -> Option<String> {
538+
match &mut self.internal_client {
539+
ClientWrapper::Cluster { client } => {
540+
if let Ok(Value::SimpleString(username)) = client.get_username().await {
541+
return Some(username);
542+
}
543+
}
544+
ClientWrapper::Standalone(client) => {
545+
return client.get_username().await;
546+
}
547+
}
548+
None
549+
}
545550
}
546551

547552
fn load_cmd(code: &[u8]) -> Cmd {

glide-core/src/client/reconnecting_connection.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,11 @@ async fn create_connection(
120120
discover_az: bool,
121121
connection_timeout: Duration,
122122
) -> Result<ReconnectingConnection, (ReconnectingConnection, RedisError)> {
123-
let client = connection_backend.connection_info.read().unwrap();
123+
let client = {
124+
let guard = connection_backend.connection_info.read().unwrap();
125+
guard.clone()
126+
};
127+
124128
let connection_options = GlideConnectionOptions {
125129
push_sender,
126130
disconnect_notifier: Some::<Box<dyn DisconnectNotifier>>(Box::new(
@@ -129,6 +133,7 @@ async fn create_connection(
129133
discover_az,
130134
connection_timeout: Some(connection_timeout),
131135
};
136+
132137
let action = || async {
133138
get_multiplexed_connection(&client, &connection_options)
134139
.await

node/tests/AuthTest.test.ts

+25-6
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ describe("Auth tests", () => {
8080
username: string,
8181
password: string,
8282
) {
83-
await client.customCommand([
83+
const result = await client.customCommand([
8484
"ACL",
8585
"SETUSER",
8686
username,
@@ -90,13 +90,15 @@ describe("Auth tests", () => {
9090
"&*",
9191
"+@all",
9292
]);
93+
expect(result).toEqual("OK");
9394
}
9495

9596
async function deleteAclUsernameAndPassword(
9697
client: BaseClient,
9798
username: string,
9899
) {
99-
return await client.customCommand(["ACL", "DELUSER", username]);
100+
const result = await client.customCommand(["ACL", "DELUSER", username]);
101+
expect(result).toEqual(1);
100102
}
101103

102104
afterEach(async () => {
@@ -227,10 +229,6 @@ describe("Auth tests", () => {
227229
async () => {
228230
await runTest(
229231
async (client: BaseClient) => {
230-
// if (client instanceof GlideClient) {
231-
// return;
232-
// }
233-
234232
// Update password without re-authentication
235233
const result =
236234
await client.updateConnectionPassword(
@@ -257,6 +255,11 @@ describe("Auth tests", () => {
257255
"normal",
258256
]);
259257

258+
// Sleep to ensure disconnection
259+
await new Promise((resolve) =>
260+
setTimeout(resolve, 1000),
261+
);
262+
260263
// Verify client auto-reconnects with new password
261264
await client.set("test_key2", "test_value2");
262265
const value2 = await client.get("test_key2");
@@ -405,8 +408,14 @@ describe("Auth tests", () => {
405408
"TYPE",
406409
"normal",
407410
]);
411+
// Sleep to ensure disconnection
412+
await new Promise((resolve) =>
413+
setTimeout(resolve, 1000),
414+
);
415+
408416
// Try updating client password without immediate re-auth and with - non immediate should succeed,
409417
// immediate auth should fail (failing to reconnect)
418+
410419
const result = await client.updateConnectionPassword(
411420
NEW_PASSWORD,
412421
false,
@@ -463,6 +472,11 @@ describe("Auth tests", () => {
463472
NEW_PASSWORD,
464473
);
465474

475+
// Sleep to ensure disconnection
476+
await new Promise((resolve) =>
477+
setTimeout(resolve, 1000),
478+
);
479+
466480
// Verify client auto-reconnects with new password
467481
await client.set("test_key2", "test_value2");
468482
const value2 = await client.get("test_key2");
@@ -557,6 +571,11 @@ describe("Auth tests", () => {
557571
NEW_PASSWORD,
558572
);
559573

574+
// Sleep to ensure disconnection
575+
await new Promise((resolve) =>
576+
setTimeout(resolve, 1000),
577+
);
578+
560579
// Try updating client password without immediate re-auth and with - non immediate should succeed,
561580
// immediate auth should fail (failing to reconnect)
562581
expect(

python/python/tests/conftest.py

+14-11
Original file line numberDiff line numberDiff line change
@@ -366,18 +366,20 @@ async def config_set_new_password(client: TGlideClient, password):
366366

367367
async def set_new_acl_username_with_password(client: TGlideClient, username, password):
368368
"""
369-
Sets a new password for the given TGlideClient server connected.
370-
This function updates the server to require a new password.
369+
Sets a new ACL user with the provided password
371370
"""
372-
if isinstance(client, GlideClient):
373-
await client.custom_command(
374-
["ACL", "SETUSER", username, "ON", f">{password}", "~*", "&*", "+@all"]
375-
)
376-
elif isinstance(client, GlideClusterClient):
377-
await client.custom_command(
378-
["ACL", "SETUSER", username, "ON", f">{password}", "~*", "&*", "+@all"],
379-
route=AllNodes(),
380-
)
371+
try:
372+
if isinstance(client, GlideClient):
373+
await client.custom_command(
374+
["ACL", "SETUSER", username, "ON", f">{password}", "~*", "&*", "+@all"]
375+
)
376+
elif isinstance(client, GlideClusterClient):
377+
await client.custom_command(
378+
["ACL", "SETUSER", username, "ON", f">{password}", "~*", "&*", "+@all"],
379+
route=AllNodes(),
380+
)
381+
except Exception as e:
382+
raise RuntimeError(f"Failed to set ACL user: {e}")
381383

382384

383385
async def delete_acl_username_and_password(client: TGlideClient, username):
@@ -386,6 +388,7 @@ async def delete_acl_username_and_password(client: TGlideClient, username):
386388
"""
387389
if isinstance(client, GlideClient):
388390
return await client.custom_command(["ACL", "DELUSER", username])
391+
389392
elif isinstance(client, GlideClusterClient):
390393
return await client.custom_command(
391394
["ACL", "DELUSER", username], route=AllNodes()

python/python/tests/test_auth.py

+47-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,46 @@ async def cleanup(self, request, management_client: TGlideClient):
4141
except RequestError:
4242
pass
4343

44+
@pytest.mark.parametrize("cluster_mode", [True, False])
45+
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
46+
async def test_update_connection_password(
47+
self, glide_client: TGlideClient, management_client: TGlideClient
48+
):
49+
"""
50+
Test replacing the connection password without immediate re-authentication.
51+
Verifies that:
52+
1. The client can update its internal password
53+
2. The client remains connected with current auth
54+
3. The client can reconnect using the new password after server password change
55+
This test is only for cluster mode, as standalone mode does not have a connection available handler
56+
"""
57+
result = await glide_client.update_connection_password(
58+
NEW_PASSWORD, immediate_auth=False
59+
)
60+
assert result == OK
61+
# Verify that the client is still authenticated
62+
assert await glide_client.set("test_key", "test_value") == OK
63+
value = await glide_client.get("test_key")
64+
assert value == b"test_value"
65+
await config_set_new_password(glide_client, NEW_PASSWORD)
66+
await kill_connections(management_client)
67+
# Add a short delay to allow the server to apply the new password
68+
# without this delay, command may or may not time out while the client reconnect
69+
# ending up with a flaky test
70+
await asyncio.sleep(2)
71+
# Verify that the client is able to reconnect with the new password,
72+
value = await glide_client.get("test_key")
73+
assert value == b"test_value"
74+
await kill_connections(management_client)
75+
await asyncio.sleep(2)
76+
# Verify that the client is able to immediateAuth with the new password after client is killed
77+
result = await glide_client.update_connection_password(
78+
NEW_PASSWORD, immediate_auth=True
79+
)
80+
assert result == OK
81+
# Verify that the client is still authenticated
82+
assert await glide_client.set("test_key", "test_value") == OK
83+
4484
@pytest.mark.parametrize("cluster_mode", [False])
4585
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
4686
async def test_update_connection_password_connection_lost_before_password_update(
@@ -54,7 +94,7 @@ async def test_update_connection_password_connection_lost_before_password_update
5494
await glide_client.set("test_key", "test_value")
5595
await config_set_new_password(glide_client, NEW_PASSWORD)
5696
await kill_connections(management_client)
57-
await asyncio.sleep(1)
97+
await asyncio.sleep(2)
5898
result = await glide_client.update_connection_password(
5999
NEW_PASSWORD, immediate_auth=False
60100
)
@@ -176,6 +216,9 @@ async def test_update_connection_password_with_acl_user(
176216
management_client, USERNAME, NEW_PASSWORD
177217
)
178218

219+
# Sleep to allow enough time for reconnecting
220+
await asyncio.sleep(2)
221+
179222
# The client should now reconnect with the new password automatically
180223
# Verify that the client is still able to perform operations
181224
value = await acl_glide_client.get("test_key")
@@ -208,6 +251,9 @@ async def test_update_connection_password_reconnection_with_immediate_auth_with_
208251
management_client, USERNAME, NEW_PASSWORD
209252
)
210253

254+
# Sleep to allow enough time for reconnecting
255+
await asyncio.sleep(2)
256+
211257
result = await acl_glide_client.update_connection_password(
212258
NEW_PASSWORD, immediate_auth=True
213259
)

0 commit comments

Comments
 (0)