Skip to content

Commit

Permalink
Merge pull request #11 from RADAR-base/release-0.2.4
Browse files Browse the repository at this point in the history
Release 0.2.4
  • Loading branch information
blootsvoets authored Aug 27, 2020
2 parents 958076f + 3eb7f56 commit c14e767
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 80 deletions.
13 changes: 7 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
os: linux
dist: xenial
language: java
jdk:
- oraclejdk11
sudo: false
- openjdk11

cache:
directories:
Expand All @@ -14,20 +15,20 @@ cache:

deploy:
- provider: releases
api_key: ${GH_TOKEN}
token: ${GH_TOKEN}
file_glob: true
file:
- "*/build/libs/*.jar"
skip_cleanup: true
cleanup: false
on:
tags: true
- provider: script
script: ./gradlew publish
skip_cleanup: true
cleanup: false
on:
branch: dev
- provider: script
script: ./gradlew bintrayUpload
skip_cleanup: true
cleanup: false
on:
tags: true
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ repositories {
}
dependencies {
api("org.radarbase:radar-jersey:0.2.3")
api("org.radarbase:radar-jersey:0.2.4")
}
```

Expand Down
36 changes: 22 additions & 14 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.61'
id 'com.jfrog.bintray' version '1.8.4' apply false
id 'org.jetbrains.kotlin.jvm' version "1.4.0"
id 'com.jfrog.bintray' version '1.8.5' apply false
}

description = 'Library for Jersey authorization, exception handling and configuration with the RADAR platform'
group = 'org.radarbase'
version = '0.2.3'
version = '0.2.4'

ext {
githubRepoName = 'RADAR-base/radar-jersey'
Expand All @@ -17,14 +17,17 @@ ext {
managementPortalVersion = "0.5.8"
jakartaWsRsVersion = "2.1.6"
jakartaAnnotationVersion = "1.3.5"
jerseyVersion = "2.30.1"
jerseyVersion = "2.31"
grizzlyVersion = "2.4.4"
jacksonVersion = "2.10.3"
jacksonModuleVersion = "2.10.3"
okhttpVersion = "4.5.0"
jacksonVersion = "2.11.2"
jacksonModuleVersion = "2.11.2"
okhttpVersion = "4.8.1"
slf4jVersion = "1.7.30"
javaxXmlBind = "2.2.11"
javaxXmlBindVersion = "2.3.1"
javaxJaxbCoreVersion = "2.3.0.1"
javaxJaxbRuntimeVersion = "2.3.3"
javaxActivation = "1.1.1"
junitVersion = "5.6.2"
}

repositories {
Expand All @@ -49,6 +52,7 @@ dependencies {
// exception template rendering
implementation 'com.github.spullara.mustache.java:compiler:0.9.6'

implementation "org.jetbrains.kotlin:kotlin-reflect"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "org.slf4j:slf4j-api:$slf4jVersion"

Expand All @@ -60,23 +64,27 @@ dependencies {
runtimeOnly("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jacksonModuleVersion")
runtimeOnly("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:$jacksonModuleVersion")

runtimeOnly "javax.xml.bind:jaxb-api:$javaxXmlBind"
runtimeOnly "com.sun.xml.bind:jaxb-core:$javaxXmlBind"
runtimeOnly "com.sun.xml.bind:jaxb-impl:$javaxXmlBind"
runtimeOnly "javax.xml.bind:jaxb-api:$javaxXmlBindVersion"
runtimeOnly "org.glassfish.jaxb:jaxb-core:$javaxJaxbCoreVersion"
runtimeOnly "org.glassfish.jaxb:jaxb-runtime:$javaxJaxbRuntimeVersion"
runtimeOnly "javax.activation:activation:$javaxActivation"

testRuntimeOnly("org.glassfish.grizzly:grizzly-http-server:$grizzlyVersion")
testRuntimeOnly("org.glassfish.jersey.containers:jersey-container-grizzly2-servlet:$jerseyVersion")

testImplementation("org.junit.jupiter:junit-jupiter:5.5.2")
testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion")
testImplementation 'org.hamcrest:hamcrest-all:1.3'
testImplementation("com.squareup.okhttp3:okhttp:$okhttpVersion")

testRuntimeOnly("ch.qos.logback:logback-classic:1.2.3")
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions.jvmTarget = "11"
kotlinOptions {
jvmTarget = "11"
apiVersion = "1.4"
languageVersion = "1.4"
}
}

test {
Expand All @@ -89,7 +97,7 @@ test {
}

wrapper {
gradleVersion = "6.0.1"
gradleVersion = "6.6"
}

apply from: "gradle/publishing.gradle"
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
2 changes: 2 additions & 0 deletions gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar


# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
Expand Down Expand Up @@ -129,6 +130,7 @@ fi
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`

JAVACMD=`cygpath --unix "$JAVACMD"`

# We build the pattern for arguments to be converted via cygpath
Expand Down
25 changes: 7 additions & 18 deletions gradlew.bat
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"

Expand All @@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Expand All @@ -51,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
Expand All @@ -61,28 +64,14 @@ echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windows variants

if not "%OS%" == "Windows_NT" goto win9xME_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar


@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*

:end
@rem End local scope for the variables with windows NT shell
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/org/radarbase/jersey/GrizzlyServer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class GrizzlyServer(
private val server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resources)
.also { it.serverConfiguration.isJmxEnabled = enableJmx }

private val shutdownHook = Thread(Runnable {
private val shutdownHook = Thread({
logger.info("Stopping HTTP server...")
server.shutdown()
}, "shutdownHook")
Expand Down
79 changes: 69 additions & 10 deletions src/main/kotlin/org/radarbase/jersey/auth/Auth.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,18 @@ import org.radarbase.jersey.exception.HttpBadRequestException
import org.radarbase.jersey.exception.HttpForbiddenException
import org.radarcns.auth.authorization.Permission
import org.radarcns.auth.token.RadarToken
import org.slf4j.LoggerFactory

interface Auth {
/** ID of the OAuth client. */
// TODO: parse client ID from RADAR token. Pending MP 0.5.7.
val clientId: String?
get() = getClaim("client_id").let { if (it.isTextual) it.asText() else null }
/** Default project to apply operations to. */
val defaultProject: String?

val token: RadarToken

/** ID of the OAuth client. */
val clientId: String?
get() = token.clientId

/** User ID, if set in the authentication. This may be null if a client credentials grant type is used. */
val userId: String?
get() = token.subject?.takeUnless { it.isEmpty() }
Expand All @@ -35,14 +36,17 @@ interface Auth {
* @throws HttpBadRequestException if a parameter is null
* @throws HttpForbiddenException if the current authentication does not authorize for the permission.
*/
fun checkPermissionOnSubject(permission: Permission, projectId: String?, userId: String?) {
fun checkPermissionOnSubject(permission: Permission, projectId: String?, userId: String?, location: String? = null) {
if (!token.hasPermissionOnSubject(permission,
projectId ?: throw HttpBadRequestException("project_id_missing", "Missing project ID in request"),
userId ?: throw HttpBadRequestException("user_id_missing", "Missing user ID in request")
)) {
throw HttpForbiddenException("permission_mismatch", "No permission to create measurement for " +
logPermission(false, permission, location, projectId, userId)
throw HttpForbiddenException("permission_mismatch", "No permission '$permission' " +
"project $projectId with user $userId")
}

logPermission(true, permission, location, projectId, userId)
}

/**
Expand All @@ -51,13 +55,15 @@ interface Auth {
* @throws HttpBadRequestException if a parameter is null
* @throws HttpForbiddenException if the current authentication does not authorize for the permission.
*/
fun checkPermissionOnProject(permission: Permission, projectId: String?) {
fun checkPermissionOnProject(permission: Permission, projectId: String?, location: String? = null) {
if (!token.hasPermissionOnProject(permission,
projectId ?: throw HttpBadRequestException("project_id_missing", "Missing project ID in request")
)) {
throw HttpForbiddenException("permission_mismatch", "No permission to create measurement for " +
logPermission(false, permission, location, projectId)
throw HttpForbiddenException("permission_mismatch", "No permission '$permission' for " +
"project $projectId")
}
logPermission(true, permission, location, projectId)
}

/**
Expand All @@ -66,14 +72,16 @@ interface Auth {
* @throws HttpBadRequestException if a parameter is null
* @throws HttpForbiddenException if the current authentication does not authorize for the permission.
*/
fun checkPermissionOnSource(permission: Permission, projectId: String?, userId: String?, sourceId: String?) {
fun checkPermissionOnSource(permission: Permission, projectId: String?, userId: String?, sourceId: String?, location: String? = null) {
if (!token.hasPermissionOnSource(permission,
projectId ?: throw HttpBadRequestException("project_id_missing", "Missing project ID in request"),
userId ?: throw HttpBadRequestException("user_id_missing", "Missing user ID in request"),
sourceId ?: throw HttpBadRequestException("source_id_missing", "Missing source ID in request"))) {
throw HttpForbiddenException("permission_mismatch", "No permission to create measurement for " +
logPermission(false, permission, location, projectId, userId, sourceId)
throw HttpForbiddenException("permission_mismatch", "No permission '$permission' for " +
"project $projectId with user $userId and source $sourceId")
}
logPermission(true, permission, location, projectId, userId, sourceId)
}

/**
Expand All @@ -85,4 +93,55 @@ interface Auth {
* Whether the current authentication is for a user with a role in given project.
*/
fun hasRole(projectId: String, role: String): Boolean

fun logPermission(isAuthorized: Boolean, permission: Permission, location: String? = null, projectId: String? = null, userId: String? = null, sourceId: String? = null) {
if (!logger.isInfoEnabled) {
return
}

logger.info(StringBuilder(150).apply {
append("[AUTHORIZATION] ")
append(location ?: findCallerMethod())
if (token.isClientCredentials) {
append(" - Client '")
append(clientId)
} else {
append(" - User '")
append(this@Auth.userId)
}
append("' - ")

sequenceOf(
"project" to projectId,
"subject" to userId,
"source" to sourceId)
.mapNotNull { (key, value) ->
value?.let { "$key=$it" }
}
.joinTo(this, separator = ", ")
append(" - ")
append(if (isAuthorized) "GRANTED " else "DENIED ")
append(permission.scopeName())
}.toString())
}

companion object {
private val stackWalker = StackWalker
.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)

private fun findCallerMethod(): String = stackWalker.walk { stream -> stream
.skip(2) // this method and logPermission
.filter { stackElement ->
val declaringClass = stackElement.declaringClass
!declaringClass.isInstance(Auth::class.java)
&& !declaringClass.isAnonymousClass
&& !declaringClass.isLocalClass
}
.findFirst()
.map { "${it.declaringClass.simpleName}.${it.methodName}" }
.orElse("unknown method")
}

private val logger = LoggerFactory.getLogger(Auth::class.java)
}
}
Loading

0 comments on commit c14e767

Please sign in to comment.