Skip to content

Commit a5b5f88

Browse files
committed
Allow password to be a callable.
Fix: redis/redis-rb#1299 Makes it easy to implement short lived password authentication strategies.
1 parent 9273f58 commit a5b5f88

File tree

4 files changed

+45
-9
lines changed

4 files changed

+45
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Unreleased
22

3+
- Allow `password` to be a callable. Makes it easy to implement short lived password authentication strategies.
34
- Fix a thread safety issue in `hiredis-client` when using the `pubsub` client concurrently.
45

56
# 0.22.2

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ redis.call("GET", "mykey")
7878
- `db`: The database to select after connecting, defaults to `0`.
7979
- `id` ID for the client connection, assigns name to current connection by sending `CLIENT SETNAME`.
8080
- `username` Username to authenticate against server, defaults to `"default"`.
81-
- `password` Password to authenticate against server.
81+
- `password` Password to authenticate against server. Can either be a String or a callable that recieve `username` as argument and return a passowrd as a String.
8282
- `timeout`: The general timeout in seconds, default to `1.0`.
8383
- `connect_timeout`: The connection timeout, takes precedence over the general timeout when connecting to the server.
8484
- `read_timeout`: The read timeout, takes precedence over the general timeout when reading responses from the server.

lib/redis_client/config.rb

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ class Config
1212
DEFAULT_DB = 0
1313

1414
module Common
15-
attr_reader :db, :password, :id, :ssl, :ssl_params, :command_builder, :inherit_socket,
16-
:connect_timeout, :read_timeout, :write_timeout, :driver, :connection_prelude, :protocol,
15+
attr_reader :db, :id, :ssl, :ssl_params, :command_builder, :inherit_socket,
16+
:connect_timeout, :read_timeout, :write_timeout, :driver, :protocol,
1717
:middlewares_stack, :custom, :circuit_breaker
1818

1919
alias_method :ssl?, :ssl
@@ -70,7 +70,7 @@ def initialize(
7070

7171
reconnect_attempts = Array.new(reconnect_attempts, 0).freeze if reconnect_attempts.is_a?(Integer)
7272
@reconnect_attempts = reconnect_attempts
73-
@connection_prelude = build_connection_prelude
73+
@connection_prelude = (build_connection_prelude unless @password&.respond_to?(:call))
7474

7575
circuit_breaker = CircuitBreaker.new(**circuit_breaker) if circuit_breaker.is_a?(Hash)
7676
if @circuit_breaker = circuit_breaker
@@ -87,6 +87,22 @@ def initialize(
8787
@middlewares_stack = middlewares_stack
8888
end
8989

90+
def connection_prelude
91+
if @password&.respond_to?(:call)
92+
build_connection_prelude
93+
else
94+
@connection_prelude
95+
end
96+
end
97+
98+
def password
99+
if @password&.respond_to?(:call)
100+
@password.call(username)
101+
else
102+
@password
103+
end
104+
end
105+
90106
def username
91107
@username || DEFAULT_USERNAME
92108
end
@@ -151,17 +167,18 @@ def server_url
151167

152168
def build_connection_prelude
153169
prelude = []
170+
pass = password
154171
if protocol == 3
155-
prelude << if @password
156-
["HELLO", "3", "AUTH", @username || DEFAULT_USERNAME, @password]
172+
prelude << if pass
173+
["HELLO", "3", "AUTH", username, pass]
157174
else
158175
["HELLO", "3"]
159176
end
160-
elsif @password
177+
elsif pass
161178
prelude << if @username && !@username.empty?
162-
["AUTH", @username, @password]
179+
["AUTH", @username, pass]
163180
else
164-
["AUTH", @password]
181+
["AUTH", pass]
165182
end
166183
end
167184

test/redis_client/config_test.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,5 +218,23 @@ def test_custom_field
218218
config = Config.new(custom: { foo: "bar" })
219219
assert_equal({ foo: "bar" }, config.custom)
220220
end
221+
222+
def test_callable_password
223+
called = 0
224+
argument = nil
225+
password_callable = ->(username) do
226+
called += 1
227+
argument = username
228+
username.upcase.reverse
229+
end
230+
config = Config.new(
231+
username: "george",
232+
password: password_callable,
233+
)
234+
235+
assert_equal [%w(HELLO 3 AUTH george EGROEG)], config.connection_prelude
236+
assert_equal 1, called
237+
assert_equal "george", argument
238+
end
221239
end
222240
end

0 commit comments

Comments
 (0)