-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #70 from amanjpro/feature/add-secure-env-variables
Add EnvVar to represent Environment variables
- Loading branch information
Showing
12 changed files
with
227 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package me.amanj.greenish.models | ||
|
||
import io.circe.syntax.EncoderOps | ||
import io.circe.{Encoder, Decoder, HCursor, Json} | ||
|
||
sealed trait EnvVar { | ||
type T <: AnyRef | ||
def name: String | ||
def value: T | ||
def tupled: (String, String) | ||
} | ||
object EnvVar { | ||
private[this] val pattern = """secure\((.*)\)""".r | ||
def apply(key: String, value: String): EnvVar = { | ||
value match { | ||
case pattern(v) => SecureEnvVar(key, v.toSeq) | ||
case _ => PlainEnvVar(key, value) | ||
} | ||
} | ||
|
||
implicit val envVarDecoer: Decoder[EnvVar] = new Decoder[EnvVar] { | ||
final def apply(obj: HCursor): Decoder.Result[EnvVar] = { | ||
obj.downField("type").as[String].flatMap { | ||
case "secure" => obj.as[SecureEnvVar] | ||
case "plain" => obj.as[PlainEnvVar] | ||
} | ||
} | ||
} | ||
|
||
implicit val envVarEncoder: Encoder[EnvVar] = Encoder.instance { | ||
case sec: SecureEnvVar => sec.asJson | ||
case plain: PlainEnvVar => plain.asJson | ||
} | ||
} | ||
|
||
private[models] case class SecureEnvVar(name: String, value: Seq[Char]) extends EnvVar { | ||
type T = Seq[Char] | ||
def tupled: (String, String) = (name, value.mkString("")) | ||
} | ||
|
||
private[models] object SecureEnvVar { | ||
val HIDDEN_PASSWORD = "****" | ||
implicit val secureEnvVarEncoder: Encoder[SecureEnvVar] = | ||
new Encoder[SecureEnvVar] { | ||
final def apply(v: SecureEnvVar): Json = Json.obj( | ||
("type", Json.fromString("secure")), | ||
("name", Json.fromString(v.name)), | ||
("value", Json.fromString(HIDDEN_PASSWORD)), | ||
) | ||
} | ||
|
||
implicit val secureEnvVarDecoder: Decoder[SecureEnvVar] = new Decoder[SecureEnvVar] { | ||
final def apply(c: HCursor): Decoder.Result[SecureEnvVar] = | ||
c.downField("type").as[String].flatMap { | ||
case "secure" => | ||
for { | ||
name <- c.downField("name").as[String] | ||
value <- c.downField("value").as[String].map(_.toSeq) | ||
} yield SecureEnvVar(name, value) | ||
} | ||
} | ||
} | ||
|
||
private[models] case class PlainEnvVar(name: String, value: String) extends EnvVar { | ||
type T = String | ||
def tupled: (String, String) = (name, value) | ||
} | ||
private[models] object PlainEnvVar { | ||
implicit val plainEnvVarEncoder: Encoder[PlainEnvVar] = | ||
new Encoder[PlainEnvVar] { | ||
final def apply(v: PlainEnvVar): Json = Json.obj( | ||
("type", Json.fromString("plain")), | ||
("name", Json.fromString(v.name)), | ||
("value", Json.fromString(v.value)), | ||
) | ||
} | ||
|
||
implicit val secureEnvVarDecoder: Decoder[PlainEnvVar] = new Decoder[PlainEnvVar] { | ||
final def apply(c: HCursor): Decoder.Result[PlainEnvVar] = | ||
c.downField("type").as[String].flatMap { | ||
case "plain" => | ||
for { | ||
name <- c.downField("name").as[String] | ||
value <- c.downField("value").as[String] | ||
} yield PlainEnvVar(name, value) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package me.amanj.greenish.models | ||
|
||
import org.scalatest.matchers.should.Matchers | ||
import org.scalatest.wordspec.AnyWordSpecLike | ||
|
||
class EnvVarSpec() extends Matchers with AnyWordSpecLike { | ||
"EnvVar.apply" must { | ||
"create PlainEnvVar when secure flag is not provided" in { | ||
val (name, value) = ("username", "Homa") | ||
val expected = PlainEnvVar(name, value) | ||
val actual = EnvVar(name, value) | ||
actual shouldBe expected | ||
} | ||
|
||
"create SecureEnvVar when secure flag is provided" in { | ||
val (name, value) = ("username", "secure(Homa)") | ||
val expected = SecureEnvVar(name, "Homa".toSeq) | ||
val actual = EnvVar(name, value) | ||
actual shouldBe expected | ||
} | ||
|
||
"create SecureEnvVar when secure flag is provided but value is empty" in { | ||
val (name, value) = ("username", "secure()") | ||
val expected = SecureEnvVar(name, "".toSeq) | ||
val actual = EnvVar(name, value) | ||
actual shouldBe expected | ||
} | ||
} | ||
|
||
"EnvVar.tupled" must { | ||
"work for secure variables" in { | ||
val (name, value) = ("username", "secure(Homa)") | ||
val origin = EnvVar(name, value) | ||
val expected = (name, "Homa") | ||
val actual = origin.tupled | ||
actual shouldBe expected | ||
} | ||
|
||
"work for plain variables" in { | ||
val (name, value) = ("username", "Homa") | ||
val origin = EnvVar(name, value) | ||
val expected = (name, value) | ||
val actual = origin.tupled | ||
actual shouldBe expected | ||
} | ||
} | ||
} | ||
|
Oops, something went wrong.