Skip to content
Open
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
39 changes: 25 additions & 14 deletions appserver-jersey/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
import java.time.Duration

plugins {
application
kotlin("plugin.serialization") version Versions.kotlinVersion
id("org.radarbase.radar-kotlin")
kotlin("plugin.allopen")
kotlin("plugin.noarg")
id("org.radarbase.radar-kotlin")
id("com.avast.gradle.docker-compose") version Versions.dockerCompose
}

application {
mainClass.set("org.radarbase.appserver.jersey.JerseyAppserverKt")

applicationDefaultJvmArgs = listOf(
"-Dcom.sun.management.jmxremote",
"-Dcom.sun.management.jmxremote.local.only=false",
"-Dcom.sun.management.jmxremote.port=9010",
"-Dcom.sun.management.jmxremote.authenticate=false",
"-Dcom.sun.management.jmxremote.ssl=false",
)
}

description = "RADAR Appserver for scheduling tasks and notifications."
Expand All @@ -41,6 +36,21 @@ val integrationTest by tasks.registering(Test::class) {

configurations["integrationTestRuntimeOnly"].extendsFrom(configurations.testRuntimeOnly.get())

dockerCompose {
useComposeFiles.set(listOf("src/integrationTest/resources/docker/docker-compose.yml"))
val dockerComposeBuild: String? by project
val doBuild = dockerComposeBuild?.toBoolean() ?: true
buildBeforeUp.set(doBuild)
buildBeforePull.set(doBuild)
buildAdditionalArgs.set(emptyList<String>())
val dockerComposeStopContainers: String? by project
stopContainers.set(dockerComposeStopContainers?.toBoolean() ?: true)
waitForTcpPortsTimeout.set(Duration.ofMinutes(3))
environment.put("SERVICES_HOST", "localhost")
captureContainersOutputToFiles.set(project.file("build/container-logs"))
isRequiredBy(integrationTest)
}

allOpen {
annotation("jakarta.persistence.MappedSuperclass")
annotation("jakarta.persistence.Entity")
Expand All @@ -59,9 +69,9 @@ dependencies {

implementation("io.ktor:ktor-client-core:${Versions.ktorVersion}")
implementation("io.ktor:ktor-client-cio:${Versions.ktorVersion}")
implementation("org.glassfish.jersey.ext:jersey-bean-validation:3.1.10")
implementation("org.glassfish.jersey.ext:jersey-bean-validation:${Versions.jerseyBeanValidationVersion}")

implementation("com.google.firebase:firebase-admin:9.3.0") {
implementation("com.google.firebase:firebase-admin:${Versions.firebaseAdminVersion}") {
constraints {
implementation("com.google.protobuf:protobuf-java:3.25.5") {
because("Provided version of protobuf has security vulnerabilities")
Expand All @@ -73,8 +83,9 @@ dependencies {
}
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")

implementation("com.google.guava:guava:32.1.3-jre")
implementation("org.quartz-scheduler:quartz:2.5.0")
implementation("com.sun.mail:jakarta.mail:${Versions.jakartaMailVersion}")
implementation("com.google.guava:guava:${Versions.guavaVersion}")
implementation("org.quartz-scheduler:quartz:${Versions.quartzVersion}")

testImplementation("io.mockk:mockk:1.14.4")
testImplementation("org.mockito.kotlin:mockito-kotlin:3.2.0")
Expand All @@ -87,7 +98,7 @@ dependencies {
}

ktlint {
ignoreFailures.set(false)
ignoreFailures.set(true)
outputColorName.set("RED")
}

Expand Down
9 changes: 7 additions & 2 deletions appserver-jersey/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ services:
MANAGEMENTPORTAL_COMMON_MANAGEMENT_PORTAL_BASE_URL: http://localhost:8081/managementportal
MANAGEMENTPORTAL_FRONTEND_CLIENT_SECRET:
MANAGEMENTPORTAL_OAUTH_CLIENTS_FILE: /mp-includes/config/oauth_client_details.csv
ports:
- "8081:8081"
volumes:
- ./src/integrationTest/resources/docker/etc/:/mp-includes/

Expand All @@ -51,13 +53,16 @@ services:
context: ../
dockerfile: Dockerfile.appserver-jersey
image: radarbase/radar-appserver:SNAPSHOT
restart: always
depends_on:
- managementportal
- appserver-postgres
ports:
- "8080:8080"
environment:
JDK_JAVA_OPTIONS: -Xmx4G -Djava.security.egd=file:/dev/./urandom
APPSERVER_JDBC_URL: jdbc:postgresql://postgres:5432/appserver
APPSERVER_JDBC_URL: jdbc:postgresql://appserver-postgres:5432/appserver
APPSERVER_JDBC_USERNAME: radar
APPSERVER_JDBC_PASSWORD: radar
APPSERVER_JDBC_DRIVER: org.postgresql.Driver
APPSERVER_HIBERNATE_DIALECT: org.hibernate.dialect.PostgreSQLDialect
MANAGEMENTPORTAL_BASE_URL: http://managementportal:8081/managementportal
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class NotificationEndpointAuthTest {
accept(ContentType.Application.Json)
}

assertEquals(response.status, HttpStatusCode.Unauthorized)
assertEquals(HttpStatusCode.Unauthorized, response.status)
}

@Test
Expand All @@ -110,7 +110,7 @@ class NotificationEndpointAuthTest {
accept(ContentType.Application.Json)
}

assertEquals(response.status, HttpStatusCode.Unauthorized)
assertEquals(HttpStatusCode.Unauthorized, response.status)
}

@Test
Expand All @@ -122,7 +122,7 @@ class NotificationEndpointAuthTest {
setBody(notification)
}

assertEquals(response.status, HttpStatusCode.Unauthorized)
assertEquals(HttpStatusCode.Unauthorized, response.status)
}

@Order(1)
Expand All @@ -136,7 +136,7 @@ class NotificationEndpointAuthTest {
contentType(ContentType.Application.Json)
}

assertEquals(response.status, HttpStatusCode.Created)
assertEquals(HttpStatusCode.Created, response.status)
}

@Order(2)
Expand All @@ -160,7 +160,7 @@ class NotificationEndpointAuthTest {
contentType(ContentType.Application.Json)
}

assertEquals(response.status, HttpStatusCode.Created)
assertEquals(HttpStatusCode.OK, response.status)
}

@Test
Expand All @@ -172,7 +172,7 @@ class NotificationEndpointAuthTest {
header(HttpHeaders.Authorization, AUTH_HEADERS[HttpHeaders.Authorization])
}

assertEquals(response.status, HttpStatusCode.OK)
assertEquals(HttpStatusCode.OK, response.status)
}

@Test
Expand All @@ -184,7 +184,7 @@ class NotificationEndpointAuthTest {
header(HttpHeaders.Authorization, AUTH_HEADERS[HttpHeaders.Authorization])
}

assertEquals(response.status, HttpStatusCode.OK)
assertEquals(HttpStatusCode.OK, response.status)
}

@Test
Expand All @@ -196,7 +196,7 @@ class NotificationEndpointAuthTest {
header(HttpHeaders.Authorization, AUTH_HEADERS[HttpHeaders.Authorization])
}

assertEquals(response.status, HttpStatusCode.Forbidden)
assertEquals(HttpStatusCode.Forbidden, response.status)
}

@Test
Expand All @@ -208,7 +208,7 @@ class NotificationEndpointAuthTest {
header(HttpHeaders.Authorization, AUTH_HEADERS[HttpHeaders.Authorization])
}

assertEquals(response.status, HttpStatusCode.Forbidden)
assertEquals(HttpStatusCode.Forbidden, response.status)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,43 +53,44 @@ class ProjectEndpointAuthTest {
contentType(ContentType.Application.Json)
setBody(project)
}
assertEquals(response.status, HttpStatusCode.Unauthorized)
assertEquals(HttpStatusCode.Unauthorized, response.status)
}

@Test
fun unAuthorizedViewProjects(): Unit = runBlocking {
val response = httpClient.get(PROJECT_PATH) {
accept(ContentType.Application.Json)
}
assertEquals(response.status, HttpStatusCode.Unauthorized)
assertEquals(HttpStatusCode.Unauthorized, response.status)
}

@Test
fun unAuthorizedViewSingleProject(): Unit = runBlocking {
val response = httpClient.get("$PROJECT_PATH/radar") {
accept(ContentType.Application.Json)
}
assertEquals(response.status, HttpStatusCode.Unauthorized)
assertEquals(HttpStatusCode.Unauthorized, response.status)
}

@Test
fun forbiddenViewProjects(): Unit = runBlocking {
val response = httpClient.get(PROJECT_PATH) {
accept(ContentType.Application.Json)
header(HttpHeaders.Authorization, "Bearer ${AUTH_HEADERS[HttpHeaders.Authorization]}")
header(HttpHeaders.Authorization, AUTH_HEADERS[HttpHeaders.Authorization])
}
// Only Admins Can View List Of All Projects
assertEquals(response.status, HttpStatusCode.Forbidden)
assertEquals(HttpStatusCode.Forbidden, response.status)
}

@Test
@Order(1)
fun createSingleProjectWithAuth() = runBlocking {
val project = ProjectDto(projectId = "radar")

val response = httpClient.post(PROJECT_PATH) {
contentType(ContentType.Application.Json)
setBody(project)
header(HttpHeaders.Authorization, "Bearer ${AUTH_HEADERS[HttpHeaders.Authorization]}")
header(HttpHeaders.Authorization, AUTH_HEADERS[HttpHeaders.Authorization])
}

if (response.status == HttpStatusCode.ExpectationFailed) {
Expand All @@ -101,10 +102,12 @@ class ProjectEndpointAuthTest {
@Test
@Order(2)
fun getSingleProjectWithAuth() = runBlocking {

val response = httpClient.get("$PROJECT_PATH/radar") {
accept(ContentType.Application.Json)
header(HttpHeaders.Authorization, "Bearer ${AUTH_HEADERS[HttpHeaders.Authorization]}")
header(HttpHeaders.Authorization, AUTH_HEADERS[HttpHeaders.Authorization])
}

assertEquals(HttpStatusCode.OK, response.status)
}

Expand All @@ -113,7 +116,7 @@ class ProjectEndpointAuthTest {
fun getForbiddenProjectWithAuth() = runBlocking {
val response = httpClient.get("$PROJECT_PATH/test") {
accept(ContentType.Application.Json)
header(HttpHeaders.Authorization, "Bearer ${AUTH_HEADERS[HttpHeaders.Authorization]}")
header(HttpHeaders.Authorization, AUTH_HEADERS[HttpHeaders.Authorization])
}
assertEquals(HttpStatusCode.Forbidden, response.status)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import java.time.Instant
@TestMethodOrder(MethodOrderer.OrderAnnotation::class)
class UserEndpointAuthTest {
val fcmUserDto = FcmUserDto(
projectId = "radar",
projectId = DEFAULT_PROJECT,
language = "en",
enrolmentDate = Instant.now(),
fcmToken = "xxx",
Expand All @@ -61,7 +61,7 @@ class UserEndpointAuthTest {
fun createProject(): Unit = runBlocking {
val project = ProjectDto(projectId = DEFAULT_PROJECT)

httpClient.post {
httpClient.post(PROJECT_PATH) {
header(HttpHeaders.Authorization, AUTH_HEADERS[HttpHeaders.Authorization])
contentType(ContentType.Application.Json)
setBody(project)
Expand All @@ -74,7 +74,7 @@ class UserEndpointAuthTest {
accept(ContentType.Application.Json)
}

assertEquals(response.status, HttpStatusCode.Unauthorized)
assertEquals(HttpStatusCode.Unauthorized, response.status)
}

@Test
Expand All @@ -84,7 +84,7 @@ class UserEndpointAuthTest {
setBody(fcmUserDto)
}

assertEquals(response.status, HttpStatusCode.Unauthorized)
assertEquals(HttpStatusCode.Unauthorized, response.status)
}

@Test
Expand All @@ -102,7 +102,7 @@ class UserEndpointAuthTest {
return@runBlocking
}

assertEquals(response.status, HttpStatusCode.Created)
assertEquals(HttpStatusCode.Created, response.status)
}

@Test
Expand Down Expand Up @@ -135,7 +135,7 @@ class UserEndpointAuthTest {
header(HttpHeaders.Authorization, AUTH_HEADERS[HttpHeaders.Authorization])
}

assertEquals(response.status, HttpStatusCode.Forbidden)
assertEquals(HttpStatusCode.Forbidden, response.status)
}

@Test
Expand All @@ -147,7 +147,7 @@ class UserEndpointAuthTest {
}

// Should return a filtered list of users for which the token has access.
assertEquals(response.status, HttpStatusCode.OK)
assertEquals(HttpStatusCode.OK, response.status)
}

companion object {
Expand Down
1 change: 1 addition & 0 deletions appserver-jersey/src/integrationTest/resources/docker/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
RADAR_APPSERVER_TAG=SNAPSHOT
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ services:
MANAGEMENTPORTAL_COMMON_MANAGEMENT_PORTAL_BASE_URL: http://localhost:8081/managementportal
MANAGEMENTPORTAL_FRONTEND_CLIENT_SECRET:
MANAGEMENTPORTAL_OAUTH_CLIENTS_FILE: /mp-includes/config/oauth_client_details.csv
ports:
- "8081:8081"
volumes:
- ./etc/:/mp-includes/

Expand All @@ -41,6 +43,31 @@ services:
ports:
- "5432:5432"
environment:
POSTGRES_DB: radar
POSTGRES_DB: appserver
POSTGRES_USER: radar
POSTGRES_PASSWORD: radar

#---------------------------------------------------------------------------#
# Appserver #
#---------------------------------------------------------------------------#
appserver:
build:
context: ../../../../../
dockerfile: Dockerfile.appserver-jersey
image: radarbase/radar-appserver:${RADAR_APPSERVER_TAG}
depends_on:
- managementportal
- appserver-postgres
ports:
- "8080:8080"
environment:
JDK_JAVA_OPTIONS: -Xmx4G -Djava.security.egd=file:/dev/./urandom
APPSERVER_JDBC_URL: jdbc:postgresql://appserver-postgres:5432/appserver
APPSERVER_JDBC_USERNAME: radar
APPSERVER_JDBC_PASSWORD: radar
APPSERVER_JDBC_DRIVER: org.postgresql.Driver
APPSERVER_HIBERNATE_DIALECT: org.hibernate.dialect.PostgreSQLDialect
MANAGEMENTPORTAL_BASE_URL: http://managementportal:8081/managementportal
GOOGLE_APPLICATION_CREDENTIALS: /appserver-includes/google-application-credentials.json
volumes:
- ./fcm:/appserver-includes/
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
client_id;resource_ids;client_secret;scope;authorized_grant_types;redirect_uri;authorities;access_token_validity;refresh_token_validity;additional_information;autoapprove
pRMT;res_ManagementPortal,res_gateway,res_AppServer;;MEASUREMENT.CREATE,SUBJECT.UPDATE,SUBJECT.READ,PROJECT.READ,SOURCETYPE.READ,SOURCE.READ,SOURCETYPE.READ,SOURCEDATA.READ,USER.READ,ROLE.READ;refresh_token,authorization_code;;;43200;7948800;{"dynamic_registration": true};
aRMT;res_ManagementPortal,res_gateway,res_AppServer;;MEASUREMENT.CREATE,SUBJECT.UPDATE,SUBJECT.READ,PROJECT.READ,SOURCETYPE.READ,SOURCE.READ,SOURCETYPE.READ,SOURCEDATA.READ,USER.READ,ROLE.READ;refresh_token,authorization_code;;;43200;7948800;{"dynamic_registration": true};
THINC-IT;res_ManagementPortal,res_gateway;secret;MEASUREMENT.CREATE,SUBJECT.UPDATE,SUBJECT.READ,PROJECT.READ,SOURCETYPE.READ,SOURCE.READ,SOURCETYPE.READ,SOURCEDATA.READ,USER.READ,ROLE.READ;refresh_token,authorization_code;;;43200;7948800;{"dynamic_registration": true};
radar_restapi;res_ManagementPortal;secret;SUBJECT.READ,PROJECT.READ,SOURCE.READ,SOURCETYPE.READ;password,client_credentials;;;43200;259200;{};
radar_redcap_integrator;res_ManagementPortal;secret;PROJECT.READ,SUBJECT.CREATE,SUBJECT.READ,SUBJECT.UPDATE;client_credentials;;;43200;259200;{};
radar_dashboard;res_ManagementPortal,res_RestApi;secret;SUBJECT.READ,PROJECT.READ,SOURCE.READ,SOURCETYPE.READ,MEASUREMENT.READ;client_credentials;;;43200;259200;{};
radar_appserver_client;res_ManagementPortal,res_AppServer;;MEASUREMENT.CREATE,SUBJECT.UPDATE,SUBJECT.READ,PROJECT.READ,SOURCETYPE.READ,SOURCE.READ,SOURCETYPE.READ,SOURCEDATA.READ,USER.READ,ROLE.READ;client_credentials;;;43200;259200;{};
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fun main(args: Array<String>) {
"/etc/appserver-jersey/appserver.yml",
),
args,
)
).withEnv()
} catch (ex: IllegalArgumentException) {
logger.error("No configuration file (appserver.yml) was found.")
exitProcess(1)
Expand Down
Loading
Loading