Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support username in AUTH command #778

Merged
merged 6 commits into from
Mar 18, 2023
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
6 changes: 5 additions & 1 deletion redis/src/main/scala/zio/redis/Input.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ object Input {

case object AuthInput extends Input[Auth] {
def encode(data: Auth)(implicit codec: BinaryCodec): RespCommand =
RespCommand(RespArgument.Literal("AUTH"), RespArgument.Value(data.password))
data.username match {
case Some(username) => RespCommand(RespArgument.Value(username), RespArgument.Value(data.password))
case None => RespCommand(RespArgument.Value(data.password))
}

}

case object BoolInput extends Input[Boolean] {
Expand Down
23 changes: 20 additions & 3 deletions redis/src/main/scala/zio/redis/api/Connection.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import zio.redis.Output._
import zio.redis._

trait Connection extends RedisEnvironment {
import Connection._
import Connection.{Auth => _, _}
mijicd marked this conversation as resolved.
Show resolved Hide resolved

/**
* Authenticates the current connection to the server in two cases:
Expand All @@ -37,9 +37,26 @@ trait Connection extends RedisEnvironment {
* the server starts accepting commands. Otherwise, an error is returned and the client needs to try a new password.
*/
final def auth(password: String): IO[RedisError, Unit] = {
val command = RedisCommand(Auth, StringInput, UnitOutput, codec, executor)
val command = RedisCommand(Connection.Auth, AuthInput, UnitOutput, codec, executor)

command.run(password)
command.run(Auth(None, password))
}

/**
* Authenticates the current connection to the server using username and password.
*
* @param username
* the username used to authenticate the connection
* @param password
* the password used to authenticate the connection
* @return
* if the password provided via AUTH matches the password in the configuration file, the Unit value is returned and
* the server starts accepting commands. Otherwise, an error is returned and the client needs to try a new password.
*/
final def auth(username: String, password: String): IO[RedisError, Unit] = {
val command = RedisCommand(Connection.Auth, AuthInput, UnitOutput, codec, executor)

command.run(Auth(Some(username), password))
}

/**
Expand Down
4 changes: 1 addition & 3 deletions redis/src/main/scala/zio/redis/options/Keys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ trait Keys {

type Alpha = Alpha.type

sealed case class Auth(password: String)

sealed case class By(pattern: String)
sealed case class Auth(username: Option[String], password: String)

case object Copy {
private[redis] def stringify: String = "COPY"
Expand Down
8 changes: 8 additions & 0 deletions redis/src/test/scala/zio/redis/ConnectionSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ import java.net.InetAddress
trait ConnectionSpec extends BaseSpec {
def connectionSuite: Spec[Redis, RedisError] =
suite("connection")(
suite("authenticating")(
test("auth with 'default' username") {
for {
redis <- ZIO.service[Redis]
res <- redis.auth("default", "password")
} yield assert(res)(isUnit)
}
),
suite("clientCaching")(
test("track keys") {
for {
Expand Down
13 changes: 9 additions & 4 deletions redis/src/test/scala/zio/redis/InputSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,18 @@ object InputSpec extends BaseSpec {
suite("Auth")(
test("with empty password") {
for {
result <- ZIO.attempt(AuthInput.encode(Auth("")))
} yield assert(result)(equalTo(RespCommand(Literal("AUTH"), Value(""))))
result <- ZIO.attempt(AuthInput.encode(Auth(None, "")))
} yield assert(result)(equalTo(RespCommand(Value(""))))
},
test("with non-empty password") {
for {
result <- ZIO.attempt(AuthInput.encode(Auth("pass")))
} yield assert(result)(equalTo(RespCommand(Literal("AUTH"), Value("pass"))))
result <- ZIO.attempt(AuthInput.encode(Auth(None, "pass")))
} yield assert(result)(equalTo(RespCommand(Value("pass"))))
},
test("with both username and password") {
for {
result <- ZIO.attempt(AuthInput.encode(Auth(Some("user"), "pass")))
} yield assert(result)(equalTo(RespCommand(Value("user"), Value("pass"))))
}
),
suite("Bool")(
Expand Down