Skip to content

Commit

Permalink
- Update dependencies and Scala version (support 2.13)
Browse files Browse the repository at this point in the history
- Fix warnings/code smells
- Update CI
  • Loading branch information
cchantep committed Mar 18, 2021
1 parent 130a3bb commit 0be0bbb
Show file tree
Hide file tree
Showing 18 changed files with 212 additions and 56 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -41,3 +41,4 @@ out/
*.sublime-workspace

bin/
.bsp
8 changes: 5 additions & 3 deletions .travis.yml
Expand Up @@ -2,11 +2,13 @@ language: scala
dist: trusty # If unspecified uses Xenial images, which no longer support oraclejdk8
sudo: false

jdk: openjdk8

matrix:
include:
- jdk: oraclejdk8
- scala: 2.12.4
- scala: 2.12.13
- scala: 2.13.5

script:
- sbt test
- sbt scapegoat test

89 changes: 76 additions & 13 deletions build.sbt
@@ -1,25 +1,88 @@
import Dependencies._

inThisBuild(List(
organization := "com.stackstate",
scalaVersion := "2.12.13",
crossScalaVersions := Seq(scalaVersion.value, "2.13.5"),
version := "0.6.1",
libraryDependencies ++= {
// Silencer
val silencerVersion = "1.7.3"

Seq(
compilerPlugin(("com.github.ghik" %% "silencer-plugin" % silencerVersion).
cross(CrossVersion.full)),
("com.github.ghik" %% "silencer-lib" % silencerVersion % Provided).
cross(CrossVersion.full)
)
}
))

lazy val root = (project in file(".")).settings(
inThisBuild(List(organization := "com.stackstate", scalaVersion := "2.12.11", version := "0.6.1")),
name := "akka-http-pac4j",
libraryDependencies ++= Seq(akkaHttp, akkaStream, pac4j, scalaTestCore % Test, scalacheck % Test, akkaHttpTestKit % Test, akkaStreamTestKit % Test),
libraryDependencies ++= Seq(
akkaHttp,
akkaStream,
pac4j,
scalaTestCore % Test,
scalacheck % Test,
akkaHttpTestKit % Test,
akkaStreamTestKit % Test),
scalacOptions ++= Seq(
"-encoding", "UTF-8",
"-explaintypes",
"-unchecked",
"-deprecation",
"-encoding",
"UTF-8",
"-feature",
"-language:existentials",
"-language:higherKinds",
"-language:implicitConversions",
"-language:postfixOps",
"-unchecked",
// "-Xfatal-warnings", // TODO: Should be reenabled when implementation is complete
//"-language:higherKinds",
"-Xlint",
"-Yno-adapted-args",
"-Xfuture"
"-g:vars"
),
scalacOptions in (Compile, console) --= Seq("-Ywarn-unused-import", "-Xfatal-warnings")
scalacOptions ++= {
if (scalaBinaryVersion.value == "2.13") {
Seq(
"-Werror",
"-Wnumeric-widen",
"-Wdead-code",
"-Wvalue-discard",
"-Wunused",
"-Wmacros:after",
"-Woctal-literal",
"-Wextra-implicit")

} else {
Seq(
"-Xfatal-warnings",
"-Ywarn-numeric-widen",
"-Ywarn-dead-code",
"-Ywarn-value-discard",
"-Ywarn-infer-any",
"-Ywarn-unused",
"-Ywarn-unused-import",
"-Ywarn-macros:after")
}
},
scalacOptions in Test ~= {
_.filterNot(_ == "-Werror")
},
scalacOptions ++= {
if (scalaBinaryVersion.value == "2.13") {
Seq("-P:silencer:globalFilters=scala.jdk.CollectionConverters")
} else {
Seq.empty
}
},
scalacOptions in Test += "-P:silencer:globalFilters=discarded\\ non-Unit",
scalacOptions in (Compile, console) ~= {
_.filterNot { opt =>
opt.startsWith("-P") || opt.startsWith("-X") || opt.startsWith("-W")
}
},
scalacOptions in (Test, console) ~= {
_.filterNot { opt =>
opt.startsWith("-P") || opt.startsWith("-X") || opt.startsWith("-W")
}
}
)

publishMavenStyle := true
Expand Down
12 changes: 6 additions & 6 deletions project/Dependencies.scala
@@ -1,17 +1,17 @@
import sbt._

object Dependencies {
val scalacheckVersion = "1.14.3"
val akkaHttpVersion = "10.1.9"
val akkaStreamsVersion = "2.5.25"
val pac4jVersion = "4.4.0"
val scalaTestVersion = "3.2.2"

lazy val scalacheck = "org.scalacheck" %% "scalacheck" % scalacheckVersion
lazy val akkaHttp = "com.typesafe.akka" %% "akka-http" % akkaHttpVersion
lazy val akkaHttpTestKit = "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion
lazy val akkaStream = "com.typesafe.akka" %% "akka-stream" % akkaStreamsVersion
lazy val pac4j = "org.pac4j" % "pac4j-core" % pac4jVersion
lazy val scalaTestCore = "org.scalatest" %% "scalatest" % scalaTestVersion
lazy val akkaStreamTestKit = "com.typesafe.akka" %% "akka-stream-testkit" % akkaStreamsVersion

val scalacheckVersion = "1.14.3"
val akkaHttpVersion = "10.1.9"
val akkaStreamsVersion = "2.5.25"
val pac4jVersion = "4.0.3"
val scalaTestVersion = "3.0.5"
}
54 changes: 54 additions & 0 deletions project/Scapegoat.scala
@@ -0,0 +1,54 @@
import sbt.Keys._
import sbt._
import sbt.plugins.JvmPlugin

import com.sksamuel.scapegoat.sbt.ScapegoatSbtPlugin

object Scapegoat extends AutoPlugin {
override def trigger = allRequirements
override def requires = JvmPlugin

import ScapegoatSbtPlugin.autoImport._

override def projectSettings = Seq(
ThisBuild / scapegoatVersion := "1.4.8",
scapegoatReports := Seq("text"), // xml in 2.13 require extra dep
scapegoatDisabledInspections := Seq("FinalModifierOnCaseClass"),
pomPostProcess := {
object Processor {
def apply() = transformPomDependencies { dep =>
if ((dep \ "groupId").text == "com.sksamuel.scapegoat") {
None
} else Some(dep)
}

// ---

import scala.xml.{ Elem => XmlElem, Node => XmlNode }

private def transformPomDependencies(tx: XmlElem => Option[XmlNode]): XmlNode => XmlNode = { node: XmlNode =>
import scala.xml.{ NodeSeq, XML }
import scala.xml.transform.{ RewriteRule, RuleTransformer }

val tr = new RuleTransformer(new RewriteRule {
override def transform(node: XmlNode): NodeSeq = node match {
case e: XmlElem if e.label == "dependency" => tx(e) match {
case Some(n) => n
case _ => NodeSeq.Empty
}

case _ => node
}
})

tr.transform(node).headOption match {
case Some(transformed) => transformed
case _ => sys.error("Fails to transform the POM")
}
}
}

Processor()
}
)
}
2 changes: 1 addition & 1 deletion project/build.properties
@@ -1 +1 @@
sbt.version=1.3.8
sbt.version=1.4.9
2 changes: 2 additions & 0 deletions project/plugins.sbt
Expand Up @@ -3,3 +3,5 @@ addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.8")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.1")

addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.3")

addSbtPlugin("com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.1.0")
9 changes: 7 additions & 2 deletions src/main/scala/com/stackstate/pac4j/AkkaHttpSecurity.scala
Expand Up @@ -76,24 +76,28 @@ class AkkaHttpSecurity(config: Config, sessionStorage: SessionStorage, val sessi

import AkkaHttpSecurity._

@SuppressWarnings(Array("AsInstanceOf"))
private[pac4j] val securityLogic: AkkaHttpSecurityLogic =
Option(config.getSecurityLogic) match {
case Some(v) => v.asInstanceOf[AkkaHttpSecurityLogic]
case None => new DefaultSecurityLogic[Future[RouteResult], AkkaHttpWebContext]
}

@SuppressWarnings(Array("AsInstanceOf"))
private[pac4j] val actionAdapter: HttpActionAdapter[Future[RouteResult], AkkaHttpWebContext] =
Option(config.getHttpActionAdapter) match {
case Some(v) => v.asInstanceOf[HttpActionAdapter[Future[RouteResult], AkkaHttpWebContext]]
case None => AkkaHttpActionAdapter
}

@SuppressWarnings(Array("AsInstanceOf"))
private[pac4j] val callbackLogic: CallbackLogic[Future[RouteResult], AkkaHttpWebContext] =
Option(config.getCallbackLogic) match {
case Some(v) => v.asInstanceOf[AkkaHttpCallbackLogic]
case None => new DefaultCallbackLogic[Future[RouteResult], AkkaHttpWebContext]
}

@SuppressWarnings(Array("AsInstanceOf"))
private[pac4j] val logoutLogic: LogoutLogic[Future[RouteResult], AkkaHttpWebContext] =
Option(config.getLogoutLogic) match {
case Some(v) => v.asInstanceOf[AkkaHttpLogoutLogic]
Expand Down Expand Up @@ -126,6 +130,7 @@ class AkkaHttpSecurity(config: Config, sessionStorage: SessionStorage, val sessi
* Authenticate using the provided pac4j configuration. Delivers an AuthenticationRequest which can be used for further authorization
* this does not apply any authorization ofr filtering.
*/
@SuppressWarnings(Array("NullAssignment"))
def withAuthentication(clients: String = null /* Default null, meaning all defined clients */,
multiProfile: Boolean = true,
authorizers: String = ""): Directive1[AuthenticatedRequest] =
Expand All @@ -134,7 +139,7 @@ class AkkaHttpSecurity(config: Config, sessionStorage: SessionStorage, val sessi
// TODO This is a hack to ensure that any underlying Futures are scheduled (and handled in case of errors) from here
// TODO Fix this properly
Future.successful(()).flatMap { _ =>
securityLogic.perform(akkaWebContext, config, (context: AkkaHttpWebContext, profiles: util.Collection[UserProfile], parameters: AnyRef) => {
securityLogic.perform(akkaWebContext, config, (context: AkkaHttpWebContext, profiles: util.Collection[UserProfile], _: AnyRef) => {
val authenticatedRequest = AuthenticatedRequest(context, profiles.asScala.toList)
inner(Tuple1(authenticatedRequest))(ctx)
}, actionAdapter, clients, authorizers, "", multiProfile)
Expand Down Expand Up @@ -168,7 +173,7 @@ class AkkaHttpSecurity(config: Config, sessionStorage: SessionStorage, val sessi
localLogout: Boolean = true,
destroySession: Boolean = true,
centralLogout: Boolean = false): Route = {
withContext() { akkaWebContext => ctx =>
withContext() { akkaWebContext => _ =>
logoutLogic.perform(akkaWebContext, config, actionAdapter, defaultUrl, logoutPatternUrl, localLogout, destroySession, centralLogout)
}
}
Expand Down
13 changes: 8 additions & 5 deletions src/main/scala/com/stackstate/pac4j/AkkaHttpWebContext.scala
Expand Up @@ -67,7 +67,7 @@ case class AkkaHttpWebContext(request: HttpRequest,
name = cookie.getName,
value = cookie.getValue,
expires = None,
maxAge = if (cookie.getMaxAge < 0) None else Some(cookie.getMaxAge),
maxAge = if (cookie.getMaxAge < 0) None else Some(cookie.getMaxAge.toLong),
domain = Option(cookie.getDomain),
path = Option(cookie.getPath),
secure = cookie.isSecure,
Expand Down Expand Up @@ -97,9 +97,9 @@ case class AkkaHttpWebContext(request: HttpRequest,
changes = changes.copy(headers = header :: changes.headers.filter(_.name != name))
}

override def getRequestParameters: java.util.Map[String, Array[String]] = {
requestParameters.mapValues(Array(_)).asJava
}
@com.github.ghik.silencer.silent("mapValues")
override def getRequestParameters: java.util.Map[String, Array[String]] =
requestParameters.mapValues(Array(_)).toMap.asJava

override def getFullRequestURL: String = {
request.getUri().toString
Expand Down Expand Up @@ -171,7 +171,10 @@ case class AkkaHttpWebContext(request: HttpRequest,
addResponseCookie(cookie)
}

def addResponseCsrfCookie(): Unit = CsrfCookieAuthorizer(this, Some(sessionStorage.sessionLifetime))
def addResponseCsrfCookie(): Unit = {
CsrfCookieAuthorizer(this, Some(sessionStorage.sessionLifetime))
()
}
}

object AkkaHttpWebContext {
Expand Down
18 changes: 11 additions & 7 deletions src/main/scala/com/stackstate/pac4j/AuthenticatedRequest.scala
Expand Up @@ -6,12 +6,16 @@ import org.pac4j.core.profile.UserProfile
* Class which serves as a witness when authentication was successful. This class is private such that the user of this
* library cannot mess with it.
*/
case class AuthenticatedRequest private[pac4j] (private[pac4j] val webContext: AkkaHttpWebContext,
/*
* Profiles can be accessed such that the user can inspect data from the authentication. Should not be empty after
* authentication
*/
val profiles: List[UserProfile]) {
case class AuthenticatedRequest private[pac4j] (
private[pac4j] val webContext: AkkaHttpWebContext,
/*
* Profiles can be accessed such that the user can inspect data
* from the authentication. Should not be empty after authentication
*/
val profiles: List[UserProfile]) {

lazy val mainProfile: UserProfile = profiles.head
lazy val mainProfile: UserProfile = profiles.headOption match {
case Some(p) => p
case None => throw new IllegalStateException("Missing profile")
}
}
Expand Up @@ -16,7 +16,6 @@ import org.pac4j.core.exception.http.{
NoContentAction,
OkAction,
SeeOtherAction,
TemporaryRedirectAction,
UnauthorizedAction
}

Expand Down
Expand Up @@ -12,16 +12,25 @@ class AkkaHttpSessionStore() extends SessionStore[AkkaHttpWebContext] {
override def get(context: AkkaHttpWebContext, key: String): Optional[Object] =
context.sessionStorage.getSessionValue(context.sessionId, key).asJava

override def set(context: AkkaHttpWebContext, key: String, value: scala.AnyRef): Unit =
override def set(context: AkkaHttpWebContext, key: String, value: scala.AnyRef): Unit = {
context.sessionStorage.setSessionValue(context.sessionId, key, value)
()
}

override def destroySession(context: AkkaHttpWebContext): Boolean = context.destroySession()

override def getTrackableSession(context: AkkaHttpWebContext): Optional[AnyRef] = Optional.ofNullable(context.sessionId)

override def buildFromTrackableSession(context: AkkaHttpWebContext, trackableSession: scala.Any): Optional[SessionStore[AkkaHttpWebContext]] = {
context.trackSession(trackableSession.asInstanceOf[String])
Optional.of(this)
trackableSession match {
case session: String => {
context.trackSession(session)
Optional.of(this)
}

case _ =>
Optional.empty()
}
}

override def renewSession(context: AkkaHttpWebContext): Boolean = {
Expand Down
Expand Up @@ -2,7 +2,7 @@ package com.stackstate.pac4j.store

import com.stackstate.pac4j.store.SessionStorage._

import scala.collection.SortedSet
import scala.collection.immutable.SortedSet
import scala.concurrent.duration.FiniteDuration

object InMemorySessionStorage {
Expand All @@ -18,7 +18,7 @@ class InMemorySessionStorage(override val sessionLifetime: FiniteDuration) exten
private val sessionLifetimeMs = sessionLifetime.toMillis

private[store] var expiryQueue = SortedSet[ExpiryRecord]()(Ordering.by(v => (v.registered, v.id)))
private[store] var sessionData = Map[SessionKey, DataRecord]()
private[store] var sessionData = Map.empty[SessionKey, DataRecord]

private[store] def getTime = System.currentTimeMillis()

Expand Down

0 comments on commit 0be0bbb

Please sign in to comment.