Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Unreleased

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

# 0.22.2
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ redis.call("GET", "mykey")
- `db`: The database to select after connecting, defaults to `0`.
- `id` ID for the client connection, assigns name to current connection by sending `CLIENT SETNAME`.
- `username` Username to authenticate against server, defaults to `"default"`.
- `password` Password to authenticate against server.
- `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.
- `timeout`: The general timeout in seconds, default to `1.0`.
- `connect_timeout`: The connection timeout, takes precedence over the general timeout when connecting to the server.
- `read_timeout`: The read timeout, takes precedence over the general timeout when reading responses from the server.
Expand Down
33 changes: 25 additions & 8 deletions lib/redis_client/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ class Config
DEFAULT_DB = 0

module Common
attr_reader :db, :password, :id, :ssl, :ssl_params, :command_builder, :inherit_socket,
:connect_timeout, :read_timeout, :write_timeout, :driver, :connection_prelude, :protocol,
attr_reader :db, :id, :ssl, :ssl_params, :command_builder, :inherit_socket,
:connect_timeout, :read_timeout, :write_timeout, :driver, :protocol,
:middlewares_stack, :custom, :circuit_breaker

alias_method :ssl?, :ssl
Expand Down Expand Up @@ -70,7 +70,7 @@ def initialize(

reconnect_attempts = Array.new(reconnect_attempts, 0).freeze if reconnect_attempts.is_a?(Integer)
@reconnect_attempts = reconnect_attempts
@connection_prelude = build_connection_prelude
@connection_prelude = (build_connection_prelude unless @password.respond_to?(:call))

circuit_breaker = CircuitBreaker.new(**circuit_breaker) if circuit_breaker.is_a?(Hash)
if @circuit_breaker = circuit_breaker
Expand All @@ -87,6 +87,22 @@ def initialize(
@middlewares_stack = middlewares_stack
end

def connection_prelude
if @password.respond_to?(:call)
build_connection_prelude
else
@connection_prelude
end
end

def password
if @password.respond_to?(:call)
@password.call(username)
else
@password
end
end

def username
@username || DEFAULT_USERNAME
end
Expand Down Expand Up @@ -151,17 +167,18 @@ def server_url

def build_connection_prelude
prelude = []
pass = password
if protocol == 3
prelude << if @password
["HELLO", "3", "AUTH", @username || DEFAULT_USERNAME, @password]
prelude << if pass
["HELLO", "3", "AUTH", username, pass]
else
["HELLO", "3"]
end
elsif @password
elsif pass
prelude << if @username && !@username.empty?
["AUTH", @username, @password]
["AUTH", @username, pass]
else
["AUTH", @password]
["AUTH", pass]
end
end

Expand Down
18 changes: 18 additions & 0 deletions test/redis_client/config_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -218,5 +218,23 @@ def test_custom_field
config = Config.new(custom: { foo: "bar" })
assert_equal({ foo: "bar" }, config.custom)
end

def test_callable_password
called = 0
argument = nil
password_callable = lambda do |username|
called += 1
argument = username
username.upcase.reverse
end
config = Config.new(
username: "george",
password: password_callable,
)

assert_equal [%w(HELLO 3 AUTH george EGROEG)], config.connection_prelude
assert_equal 1, called
assert_equal "george", argument
end
end
end
Loading