Skip to content

Commit

Permalink
all: prepare for Scala3
Browse files Browse the repository at this point in the history
 - Avoiding automatic dependency on akka http server
   makes it easier for dependant projects to use Scala 3
   and netty instead.

 - adjust tests to use mockito instead of specs2 mock wrappers.
  • Loading branch information
ahjohannessen committed Apr 14, 2023
1 parent b441756 commit 7666bef
Show file tree
Hide file tree
Showing 52 changed files with 1,564 additions and 1,446 deletions.
1 change: 0 additions & 1 deletion .bsp/sbt.json

This file was deleted.

11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,13 @@ dist
/.settings
/.target
/.cache
*.DS_Store
*.DS_Store

# Metals
.metals/*
.bloop/*
.vscode/*
**/.bloop/*
**/metals.sbt

.bsp/*
32 changes: 22 additions & 10 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import Dependencies.Library
import sbt.CrossVersion

lazy val repo: String = "https://s01.oss.sonatype.org"
lazy val scala213: String = "2.13.8"
lazy val scala213: String = "2.13.10"
lazy val scala31: String = "3.1.2" // Ready for cross build, currently not yet supported by play.
lazy val supportedScalaVersions: Seq[String] = Seq(scala213 /*, scala31*/)

Global / evictionErrorLevel := Level.Info

ThisBuild / description := "Authentication library for Play Framework applications that supports several authentication methods, including OAuth1, OAuth2, OpenID, CAS, Credentials, Basic Authentication, Two Factor Authentication or custom authentication schemes"
ThisBuild / homepage := Some(url("https://silhouette.readme.io/"))
ThisBuild / licenses := Seq("Apache License" -> url("https://github.com/honeycomb-cheesecake/play-silhouette/blob/master/LICENSE"))
Expand Down Expand Up @@ -49,7 +51,7 @@ ThisBuild / publishTo := {
}
}
ThisBuild / versionPolicyIntention := Compatibility.BinaryAndSourceCompatible
ThisBuild / scapegoatVersion := "1.4.13"
ThisBuild / scapegoatVersion := "2.1.1"

dependencyCheckAssemblyAnalyzerEnabled := Some(false)
dependencyCheckFormat := "ALL"
Expand Down Expand Up @@ -101,7 +103,9 @@ lazy val silhouette = (project in file("silhouette"))
.settings(
name := "play-silhouette",
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"),
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-mock"),
dependencyUpdatesFilter -= moduleFilter(organization = "com.typesafe.akka", name = "akka-testkit"),
dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"),
dependencyUpdatesFilter -= moduleFilter(organization = "om.auth0", name = "java-jwt"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.Play.cache,
Expand All @@ -111,28 +115,29 @@ lazy val silhouette = (project in file("silhouette"))
Library.apacheCommonLang,
Library.Play.specs2 % Test,
Library.Specs2.matcherExtra % Test,
Library.Specs2.mock % Test,
Library.mockito % Test,
Library.scalaGuice % Test,
Library.akkaTestkit % Test
),
resolvers ++= Dependencies.resolvers,
scapegoatDisabledInspections := Seq("AsInstanceOf", "BooleanParameter", "ComparingUnrelatedTypes", "FinalModifierOnCaseClass", "MethodNames")
)
.enablePlugins(PlayScala)
.disablePlugins(PlayAkkaHttpServer)

lazy val silhouetteCas = (project in file("silhouette-cas"))
.settings(
name := "play-silhouette-cas",
dependencyUpdatesFailBuild := true,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"),
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-mock"),
dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.casClient,
Library.casClientSupportSAML,
Library.Play.specs2 % Test,
Library.Specs2.matcherExtra % Test,
Library.Specs2.mock % Test,
Library.mockito % Test,
Library.scalaGuice % Test
),
scapegoatDisabledInspections := Seq("AsInstanceOf", "BooleanParameter", "ComparingUnrelatedTypes", "FinalModifierOnCaseClass", "MethodNames")
Expand All @@ -144,6 +149,7 @@ lazy val silhouetteTotp = (project in file("silhouette-totp"))
name := "play-silhouette-totp",
dependencyUpdatesFailBuild := true,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"),
dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.googleAuth,
Expand All @@ -159,6 +165,9 @@ lazy val silhouetteCryptoJca = (project in file("silhouette-crypto-jca"))
dependencyUpdatesFailBuild := true,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"),
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"),
dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"),
dependencyUpdatesFilter -= moduleFilter(organization = "commons-codec", name = "commons-codec"),

libraryDependencies ++=
Library.updates ++ Seq(
Library.commonsCodec,
Expand All @@ -174,6 +183,7 @@ lazy val silhouetteArgon2 = (project in file("silhouette-password-argon2"))
name := "play-silhouette-password-argon2",
dependencyUpdatesFailBuild := true,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"),
dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.argon2,
Expand All @@ -188,6 +198,7 @@ lazy val silhouetteBcrypt = (project in file("silhouette-password-bcrypt"))
name := "play-silhouette-password-bcrypt",
dependencyUpdatesFailBuild := true,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"),
dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.jbcrypt,
Expand All @@ -203,12 +214,12 @@ lazy val silhouettePersistence = (project in file("silhouette-persistence"))
dependencyUpdatesFailBuild := true,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"),
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"),
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-mock"),
dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.Specs2.core % Test,
Library.Specs2.matcherExtra % Test,
Library.Specs2.mock % Test,
Library.mockito % Test,
Library.scalaGuice % Test
),
scapegoatDisabledInspections := Seq("AsInstanceOf", "BooleanParameter", "ComparingUnrelatedTypes", "FinalModifierOnCaseClass", "MethodNames")
Expand All @@ -220,13 +231,14 @@ lazy val silhouetteTestkit = (project in file("silhouette-testkit"))
name := "play-silhouette-testkit",
dependencyUpdatesFailBuild := true,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"),
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-mock"),
dependencyUpdatesFilter -= moduleFilter(organization = "com.typesafe.akka", name = "akka-testkit"),
dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.Play.test,
Library.Play.specs2 % Test,
Library.Specs2.matcherExtra % Test,
Library.Specs2.mock % Test,
Library.mockito % Test,
Library.scalaGuice % Test,
Library.akkaTestkit % Test
),
Expand Down
4 changes: 2 additions & 2 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ object Dependencies {
private val version = "4.9.4" // Versions later than this will fail due to removed dependencies.
val core = "org.specs2" %% "specs2-core" % version
val matcherExtra = "org.specs2" %% "specs2-matcher-extra" % version
val mock = "org.specs2" %% "specs2-mock" % version
}

val argon2 = "de.mkammerer" % "argon2-jvm" % "2.11"
val commonsCodec = "commons-codec" % "commons-codec" % "1.15"
val jbcrypt = "de.svenkubiak" % "jBCrypt" % "0.4.3"
val jwt = "com.auth0" % "java-jwt" % "3.18.2"
val scalaGuice = "net.codingwell" %% "scala-guice" % "5.1.0"
val scalaGuice = "net.codingwell" %% "scala-guice" % "5.1.1"
val akkaTestkit = "com.typesafe.akka" %% "akka-testkit" % play.core.PlayVersion.akkaVersion
val mockito = "org.mockito" % "mockito-core" % "5.3.0"
val casClient = "org.jasig.cas.client" % "cas-client-core" % "3.6.4"
val casClientSupportSAML = "org.jasig.cas.client" % "cas-client-support-saml" % "3.6.4"
val apacheCommonLang = "org.apache.commons" % "commons-lang3" % "3.12.0"
Expand Down
20 changes: 11 additions & 9 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
addSbtPlugin(dependency = "ch.epfl.scala" % "sbt-version-policy" % "2.0.1")
Global / evictionErrorLevel := Level.Info

addSbtPlugin(dependency = "ch.epfl.scala" % "sbt-version-policy" % "2.1.0")
addSbtPlugin(dependency = "com.github.sbt" % "sbt-release" % "1.1.0")
addSbtPlugin(dependency = "com.github.sbt" % "sbt-unidoc" % "0.5.0")
addSbtPlugin(dependency = "com.jsuereth" % "sbt-pgp" % "2.0.2")
addSbtPlugin(dependency = "com.jsuereth" % "sbt-pgp" % "2.1.1")
addSbtPlugin(dependency = "com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.1.1")
addSbtPlugin(dependency = "com.timushev.sbt" % "sbt-updates" % "0.6.2")
addSbtPlugin(dependency = "com.typesafe.play" % "sbt-plugin" % "2.8.16")
addSbtPlugin(dependency = "net.vonbuchholtz" % "sbt-dependency-check" % "4.0.0")
addSbtPlugin(dependency = "org.scalariform" % "sbt-scalariform" % "1.8.2")
addSbtPlugin(dependency = "org.scoverage" % "sbt-scoverage" % "1.9.3")
addSbtPlugin(dependency = "org.scoverage" % "sbt-coveralls" % "1.3.2")
addSbtPlugin(dependency = "org.xerial.sbt" % "sbt-sonatype" % "3.9.12")
addSbtPlugin(dependency = "com.timushev.sbt" % "sbt-updates" % "0.6.4")
addSbtPlugin(dependency = "com.typesafe.play" % "sbt-plugin" % "2.8.19")
addSbtPlugin(dependency = "net.vonbuchholtz" % "sbt-dependency-check" % "5.1.0")
addSbtPlugin(dependency = "org.scalariform" % "sbt-scalariform" % "1.8.3")
addSbtPlugin(dependency = "org.scoverage" % "sbt-scoverage" % "2.0.7")
addSbtPlugin(dependency = "org.scoverage" % "sbt-coveralls" % "1.3.7")
addSbtPlugin(dependency = "org.xerial.sbt" % "sbt-sonatype" % "3.9.18")
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import io.github.honeycombcheesecake.play.silhouette.api.util.HTTPLayer
import io.github.honeycombcheesecake.play.silhouette.api.{ Logger, LoginInfo }

import org.jasig.cas.client.authentication.AttributePrincipal
import org.specs2.mock.Mockito
import org.mockito.Mockito._
import org.specs2.specification.Scope
import play.api.test.FakeRequest
import test.SocialProviderSpec
Expand All @@ -32,7 +32,7 @@ import scala.concurrent.duration._
/**
* Test case for the [[CasProvider]] class.
*/
class CasProviderSpec extends SocialProviderSpec[CasInfo] with Mockito with Logger {
class CasProviderSpec extends SocialProviderSpec[CasInfo] with Logger {

"The settings" should {
"fail with a ConfigurationException if casURL is invalid" in new Context {
Expand Down Expand Up @@ -94,9 +94,9 @@ class CasProviderSpec extends SocialProviderSpec[CasInfo] with Mockito with Logg

"The `retrieveProfile` method" should {
"return a valid profile if the CAS client validates the ticket" in new Context {
principal.getName returns userName
principal.getAttributes returns attr
client.validateServiceTicket(ticket) returns Future.successful(principal)
when(principal.getName).thenReturn(userName)
when(principal.getAttributes).thenReturn(attr)
when(client.validateServiceTicket(ticket)).thenReturn(Future.successful(principal))

implicit val req = FakeRequest(GET, "/?ticket=%s".format(ticket))

Expand Down Expand Up @@ -128,8 +128,8 @@ class CasProviderSpec extends SocialProviderSpec[CasInfo] with Mockito with Logg
redirectURL = "https://cas-redirect/")

lazy val httpLayer = {
val m = mock[HTTPLayer]
m.executionContext returns global
val m = mock(classOf[HTTPLayer])
when(m.executionContext).thenReturn(global)
m
}

Expand All @@ -143,7 +143,7 @@ class CasProviderSpec extends SocialProviderSpec[CasInfo] with Mockito with Logg

lazy val casAuthInfo = CasInfo(ticket)

lazy val principal = mock[AttributePrincipal].smart
lazy val principal = mock(classOf[AttributePrincipal], withSettings().defaultAnswer(RETURNS_SMART_NULLS))

lazy val name = "abc123"
lazy val email = "email"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,60 +19,60 @@ import io.github.honeycombcheesecake.play.silhouette.api.StorableAuthenticator
import io.github.honeycombcheesecake.play.silhouette.api.util.CacheLayer
import io.github.honeycombcheesecake.play.silhouette.test.WaitPatience
import org.specs2.concurrent.ExecutionEnv
import org.specs2.mock.Mockito
import org.specs2.mutable.Specification
import org.specs2.specification.Scope
import org.mockito.Mockito._

import scala.concurrent.Future
import scala.concurrent.duration.Duration

/**
* Test case for the [[CacheAuthenticatorRepository]] class.
*/
class CacheAuthenticatorRepositorySpec(implicit ev: ExecutionEnv) extends Specification with Mockito with WaitPatience {
class CacheAuthenticatorRepositorySpec(implicit ev: ExecutionEnv) extends Specification with WaitPatience {

"The `find` method" should {
"return value from cache" in new Context {
cacheLayer.find[StorableAuthenticator]("test-id") returns Future.successful(Some(authenticator))
when(cacheLayer.find[StorableAuthenticator]("test-id")).thenReturn(Future.successful(Some(authenticator)))

repository.find("test-id") must beSome(authenticator).awaitWithPatience
there was one(cacheLayer).find[StorableAuthenticator]("test-id")
verify(cacheLayer).find[StorableAuthenticator]("test-id")
}

"return None if value couldn't be found in cache" in new Context {
cacheLayer.find[StorableAuthenticator]("test-id") returns Future.successful(None)
when(cacheLayer.find[StorableAuthenticator]("test-id")).thenReturn(Future.successful(None))

repository.find("test-id") must beNone.awaitWithPatience
there was one(cacheLayer).find[StorableAuthenticator]("test-id")
verify(cacheLayer).find[StorableAuthenticator]("test-id")
}
}

"The `add` method" should {
"add value in cache" in new Context {
authenticator.id returns "test-id"
cacheLayer.save("test-id", authenticator, Duration.Inf) returns Future.successful(authenticator)
when(authenticator.id).thenReturn("test-id")
when(cacheLayer.save("test-id", authenticator, Duration.Inf)).thenReturn(Future.successful(authenticator))

repository.add(authenticator) must beEqualTo(authenticator).awaitWithPatience
there was one(cacheLayer).save("test-id", authenticator, Duration.Inf)
verify(cacheLayer).save("test-id", authenticator, Duration.Inf)
}
}

"The `update` method" should {
"update value in cache" in new Context {
authenticator.id returns "test-id"
cacheLayer.save("test-id", authenticator, Duration.Inf) returns Future.successful(authenticator)
when(authenticator.id).thenReturn("test-id")
when(cacheLayer.save("test-id", authenticator, Duration.Inf)).thenReturn(Future.successful(authenticator))

repository.update(authenticator) must beEqualTo(authenticator).awaitWithPatience
there was one(cacheLayer).save("test-id", authenticator, Duration.Inf)
verify(cacheLayer).save("test-id", authenticator, Duration.Inf)
}
}

"The `remove` method" should {
"remove value from cache" in new Context {
cacheLayer.remove("test-id") returns Future.successful(())
when(cacheLayer.remove("test-id")).thenReturn(Future.successful(()))

repository.remove("test-id") must beEqualTo(()).awaitWithPatience
there was one(cacheLayer).remove("test-id")
verify(cacheLayer).remove("test-id")
}
}

Expand All @@ -84,12 +84,12 @@ class CacheAuthenticatorRepositorySpec(implicit ev: ExecutionEnv) extends Specif
/**
* A storable authenticator.
*/
lazy val authenticator = mock[StorableAuthenticator]
lazy val authenticator = mock(classOf[StorableAuthenticator])

/**
* The cache layer implementation.
*/
lazy val cacheLayer = mock[CacheLayer]
lazy val cacheLayer = mock(classOf[CacheLayer])

/**
* The repository to test.
Expand Down
Loading

0 comments on commit 7666bef

Please sign in to comment.