Skip to content

Commit

Permalink
Merge pull request #447 from RADAR-base/release-2.4.1
Browse files Browse the repository at this point in the history
Release 2.4.1
  • Loading branch information
mpgxvii authored Oct 23, 2023
2 parents ae21553 + 0919a8e commit c8c0439
Show file tree
Hide file tree
Showing 24 changed files with 273 additions and 217 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ jobs:
- name: Check
run: GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/src/integrationTest/resources/google-credentials.json ./gradlew check

- name: Upload build artifacts
if: always()
uses: actions/upload-artifact@v3
with:
path: build/reports
if-no-files-found: ignore
retention-days: 5

# Check that the docker image builds correctly
docker:
# The type of runner that the job will run on
Expand Down
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ The app server provides REST endpoints to interact with the entities and data. F

3.2. To use as an embedded in-memory database instance (Not recommended for production deployments), set the `spring.datasource.url=jdbc:hsqldb:mem:/appserver` in `application-<profile>.properties`. Also, change the properties in `src/main/resources/application.properties` to dev or prod according to your requirements.

4. Build the project using gradle wrapper and run using spring boot. Note: This project uses JAVA 11, please download and install it before building.
4. Build the project using gradle wrapper and run using spring boot. Note: This project uses JAVA 17, please download and install it before building.

5. The build will need to create a logs directory. The default path is `/usr/local/var/lib/radar/appserver/logs`. Either create the directory there using `sudo mkdir -p /usr/local/var/lib/radar/appserver/logs` followed by `sudo chown $USER /usr/local/var/lib/radar/appserver/logs` or change logs file directory in `src/main/resources/logback-spring.xml` to local log directory like `<property name="LOGS" value="logs" />`

6. The appserver uses the Admin SDK to communicate with the Firebase Cloud Messaging. To
configure this, please look at the [FCM section](#fcm).

7. To run the build on mac or linux, run the below -
7. To run the build, run the command below -
```bash
./gradlew bootRun
```
Expand Down Expand Up @@ -141,13 +141,12 @@ The same result as stated in [Getting Started](#getting-started) can be achieved
## FCM

### AdminSDK
To configure AdminSDK, follow the official Firebase [documentation](https://firebase.google.
com/docs/admin/setup#initialize-sdk) till you setup the environment variable (`GOOGLE_APPLICATION_CREDENTIALS`). In the properties
To configure AdminSDK, follow the official Firebase [documentation](https://firebase.google.com/docs/admin/setup#initialize-sdk) till you setup the environment variable (`GOOGLE_APPLICATION_CREDENTIALS`). In the properties
file, you would need to set `fcmserver.fcmsender` to `org.radarbase.fcm.downstream.AdminSdkFcmSender`.


## Docker/ Docker Compose
The AppServer is also available as a docker container. It's [Dockerfile](/Dockerfile) is provided with the project. It can be run as follows -
The AppServer is also available as a docker container. Its [Dockerfile](/Dockerfile) is provided with the project. It can be run as follows -

```shell
docker run -v /logs/:/var/log/radar/appserver/ \
Expand All @@ -167,7 +166,7 @@ The same can be achieved by running as a docker-compose service. Just specify th
ports:
- 8080:8080
volumes:
- ./radar_is.yml:/resources/radar_is.yml
- ./radar-is.yml:/resources/radar-is.yml
- ./logs/:/var/log/radar/appserver/
- ./etc/google-credentials.json:/etc/google-credentials.json
environment:
Expand All @@ -176,7 +175,7 @@ The same can be achieved by running as a docker-compose service. Just specify th
RADAR_ADMIN_USER: "radar"
RADAR_ADMIN_PASSWORD: "radar"
SPRING_APPLICATION_JSON: '{"spring":{"boot":{"admin":{"client":{"url":"http://spring-boot-admin:1111","username":"radar","password":"appserver"}}}}}'
RADAR_IS_CONFIG_LOCATION: "/resources/radar_is.yml"
RADAR_IS_CONFIG_LOCATION: "/resources/radar-is.yml"
SPRING_BOOT_ADMIN_CLIENT_INSTANCE_NAME: radar-appserver
```

Expand Down Expand Up @@ -378,7 +377,7 @@ security.radar.managementportal.url=<your management portal base url>
This will instantiate all the classes needed for security using the management portal. Per endpoint level auth is controlled using Pre and Post annotations for each permission.
All the classes are located in [/src/main/java/org/radarbase/appserver/auth/managementportal](/src/main/java/org/radarbase/appserver/auth/managementportal).
You can provide the Management Portal specific config in [radar_is.yml](radar_is.yml) file providing the public key endpoint and the resource name. The path to this file should be specified in the env variable `RADAR_IS_CONFIG_LOCATION`.
You can provide the Management Portal specific config in [radar-is.yml](radar-is.yml) file providing the public key endpoint and the resource name. The path to this file should be specified in the env variable `RADAR_IS_CONFIG_LOCATION`.
### Management Portal Clients
If security is enabled, please also make sure that the correct resources and scope are set in the OAuth Client configurations in Management Portal.
Expand Down
15 changes: 7 additions & 8 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ apply plugin: 'io.spring.dependency-management'
apply plugin: 'scala'

group = 'org.radarbase'
version = '2.4.0'
version = '2.4.1'

java {
toolchain {
Expand Down Expand Up @@ -69,7 +69,6 @@ dependencies {
// Open API spec
implementation(group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: springDocVersion)


//runtimeOnly('org.springframework.boot:spring-boot-devtools')
runtimeOnly('org.hsqldb:hsqldb')
runtimeOnly('org.liquibase:liquibase-core:4.20.0')
Expand Down Expand Up @@ -112,7 +111,7 @@ javafx {
}

checkstyle {
configDirectory = file("config/checkstyle")
configDirectory.set(file("config/checkstyle"))
toolVersion = "10.8.0"
showViolations = false
ignoreFailures = true
Expand All @@ -134,14 +133,14 @@ test {
}
}

task unpack(type: Copy) {
duplicatesStrategy = 'include'
tasks.register('unpack', Copy) {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
dependsOn bootJar
from(zipTree(tasks.bootJar.outputs.files.singleFile))
into("build/dependency")
}

task loadTest(type: JavaExec) {
tasks.register('loadTest', JavaExec) {
dependsOn testClasses
description = "Load Test With Gatling"
group = "Load Test"
Expand All @@ -158,13 +157,13 @@ task loadTest(type: JavaExec) {
]
}

task integrationTest(type: Test) {
tasks.register('integrationTest', Test) {
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
useJUnitPlatform() {
excludeEngines 'junit-vintage'
}
environment "RADAR_IS_CONFIG_LOCATION", "src/integrationTest/resources/radar_is.yml"
environment "RADAR_IS_CONFIG_LOCATION", "src/integrationTest/resources/radar-is.yml"

shouldRunAfter test
}
Expand Down
3 changes: 3 additions & 0 deletions radar-is.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
resourceName: res_AppServer
publicKeyEndpoints:
- http://localhost:8081/managementportal/oauth/token_key
3 changes: 0 additions & 3 deletions radar_is.yml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
public class MPOAuthHelper implements OAuthHelper {
private static final ObjectMapper mapper = new ObjectMapper();
private static final String ACCESS_TOKEN;
private static final String MP_URL = "http://localhost:8081";
private static final String MP_URL = "http://localhost:8081/managementportal/";
private static final String MP_CLIENT = "ManagementPortalapp";
private static final String REST_CLIENT = "pRMT";
private static final String USER = "sub-1";
Expand Down
15 changes: 8 additions & 7 deletions src/integrationTest/resources/docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ services:
POSTGRES_DB: radar
POSTGRES_PASSWORD: radar
ports:
- 5432:5432
- "5432:5432"

appserver:
build: ../../../..
Expand All @@ -29,12 +29,12 @@ services:
- default
- admin
ports:
- 8080:8080
- "8080:8080"
depends_on:
- postgres
- spring-boot-admin
volumes:
- ../radar_is.yml:/resources/radar_is.yml
- ../radar-is.yml:/resources/radar-is.yml
- ../../../../logs/:/var/log/radar/appserver/
environment:
JDK_JAVA_OPTIONS: -Xmx4G -Djava.security.egd=file:/dev/./urandom
Expand All @@ -43,7 +43,7 @@ services:
RADAR_ADMIN_USER: "radar"
RADAR_ADMIN_PASSWORD: "radar"
SPRING_APPLICATION_JSON: '{"spring":{"boot":{"admin":{"client":{"url":"http://spring-boot-admin:1111","username":"radar","password":"appserver"}}}}}'
RADAR_IS_CONFIG_LOCATION: "/resources/radar_is.yml"
RADAR_IS_CONFIG_LOCATION: "/resources/radar-is.yml"
SPRING_BOOT_ADMIN_CLIENT_INSTANCE_NAME: radar-appserver

spring-boot-admin:
Expand All @@ -53,7 +53,7 @@ services:
- admin
- default
ports:
- 8888:1111
- "8888:1111"
environment:
SPRING_BOOT_ADMIN_USER_NAME: radar
SPRING_BOOT_ADMIN_USER_PASSWORD: appserver
Expand All @@ -71,10 +71,11 @@ services:
SPRING_PROFILES_ACTIVE: dev
SERVER_PORT: 8081
MANAGEMENTPORTAL_FRONTEND_CLIENT_SECRET: ""
MANAGEMENTPORTAL_COMMON_BASE_URL: http://localhost:8081/
MANAGEMENTPORTAL_COMMON_MANAGEMENT_PORTAL_BASE_URL: http://localhost:8081/
MANAGEMENTPORTAL_COMMON_BASE_URL: http://localhost:8081/managementportal
MANAGEMENTPORTAL_COMMON_MANAGEMENT_PORTAL_BASE_URL: http://localhost:8081/managementportal
MANAGEMENTPORTAL_OAUTH_CLIENTS_FILE: /mp-includes/config/oauth_client_details.csv
MANAGEMENTPORTAL_CATALOGUE_SERVER_ENABLE_AUTO_IMPORT: 'false'
SERVER_SERVLET_CONTEXT_PATH: /managementportal
JAVA_OPTS: -Xmx256m # maximum heap size for the JVM running ManagementPortal, increase this as necessary
volumes:
- ./etc/:/mp-includes/
3 changes: 3 additions & 0 deletions src/integrationTest/resources/radar-is.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
resourceName: res_AppServer
publicKeyEndpoints:
- http://localhost:8081/managementportal/oauth/token_key
3 changes: 0 additions & 3 deletions src/integrationTest/resources/radar_is.yml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public ManagementPortalAuthProperties getAuthProperties() {
}

/**
* First tries to load config from radar_is.yml config file. If any issues, then uses the default
* First tries to load config from radar-is.yml config file. If any issues, then uses the default
* MP oauth token key endpoint.
*
* @param managementPortalAuthProperties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public class UserMetrics extends AuditModel implements Serializable {
@Column(name = "last_delivered")
private Instant lastDelivered;

@ToString.Exclude @NonNull @OneToOne private User user;
@ToString.Exclude @NonNull @OneToOne(mappedBy = "usermetrics") private User user;

public UserMetrics(Instant lastOpened, Instant lastDelivered) {
this.lastOpened = lastOpened;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.radarbase.appserver.entity.DataMessageStateEvent;
import org.radarbase.appserver.entity.NotificationStateEvent;
import org.radarbase.appserver.event.state.dto.DataMessageStateEventDto;
import org.radarbase.appserver.event.state.dto.NotificationStateEventDto;
import org.radarbase.appserver.service.DataMessageStateEventService;
Expand Down Expand Up @@ -65,9 +67,8 @@ public MessageStateEventListener(ObjectMapper objectMapper,
public void onNotificationStateChange(NotificationStateEventDto event) {
String info = convertMapToString(event.getAdditionalInfo());
log.debug("ID: {}, STATE: {}", event.getNotification().getId(), event.getState());
org.radarbase.appserver.entity.NotificationStateEvent eventEntity =
new org.radarbase.appserver.entity.NotificationStateEvent(
event.getNotification(), event.getState(), event.getTime(), info);
NotificationStateEvent eventEntity = new NotificationStateEvent(
event.getNotification(), event.getState(), event.getTime(), info);
notificationStateEventService.addNotificationStateEvent(eventEntity);
}

Expand All @@ -77,22 +78,21 @@ public void onNotificationStateChange(NotificationStateEventDto event) {
public void onDataMessageStateChange(DataMessageStateEventDto event) {
String info = convertMapToString(event.getAdditionalInfo());
log.debug("ID: {}, STATE: {}", event.getDataMessage().getId(), event.getState());
org.radarbase.appserver.entity.DataMessageStateEvent eventEntity =
new org.radarbase.appserver.entity.DataMessageStateEvent(
event.getDataMessage(), event.getState(), event.getTime(), info);
DataMessageStateEvent eventEntity = new DataMessageStateEvent(
event.getDataMessage(), event.getState(), event.getTime(), info);
dataMessageStateEventService.addDataMessageStateEvent(eventEntity);
}

public String convertMapToString(Map<String, String> additionalInfoMap) {
String info = null;
if (additionalInfoMap != null) {
try {
info = objectMapper.writeValueAsString(additionalInfoMap);
} catch (JsonProcessingException exc) {
log.warn("error processing event's additional info: {}", additionalInfoMap);
}
if (additionalInfoMap == null) {
return null;
}
try {
return objectMapper.writeValueAsString(additionalInfoMap);
} catch (JsonProcessingException exc) {
log.warn("error processing event's additional info: {}", additionalInfoMap);
return null;
}
return info;
}
// we can add more event listeners by annotating with @EventListener
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.radarbase.appserver.event.state.dto.NotificationStateEventDto;
import org.radarbase.appserver.entity.TaskStateEvent;
import org.radarbase.appserver.event.state.dto.TaskStateEventDto;
import org.radarbase.appserver.service.TaskStateEventService;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
Expand All @@ -50,7 +49,6 @@ public TaskStateEventListener(ObjectMapper objectMapper,
this.taskStateEventService = taskStateEventService;
}


/**
* Handle an application event.
*
Expand All @@ -62,22 +60,21 @@ public TaskStateEventListener(ObjectMapper objectMapper,
public void onTaskStateChange(TaskStateEventDto event) {
String info = convertMapToString(event.getAdditionalInfo());
log.debug("ID: {}, STATE: {}", event.getTask().getId(), event.getState());
org.radarbase.appserver.entity.TaskStateEvent eventEntity =
new org.radarbase.appserver.entity.TaskStateEvent(
TaskStateEvent eventEntity = new TaskStateEvent(
event.getTask(), event.getState(), event.getTime(), info);
taskStateEventService.addTaskStateEvent(eventEntity);
}

public String convertMapToString(Map<String, String> additionalInfoMap) {
String info = null;
if (additionalInfoMap != null) {
try {
info = objectMapper.writeValueAsString(additionalInfoMap);
} catch (JsonProcessingException exc) {
log.warn("error processing event's additional info: {}", additionalInfoMap);
}
if (additionalInfoMap == null) {
return null;
}
try {
return objectMapper.writeValueAsString(additionalInfoMap);
} catch (JsonProcessingException exc) {
log.warn("error processing event's additional info: {}", additionalInfoMap);
return null;
}
return info;
}
// we can add more event listeners by annotating with @EventListener
}
19 changes: 7 additions & 12 deletions src/main/java/org/radarbase/appserver/service/GithubClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class GithubClient {
private final transient String authorizationHeader;

private transient final Duration httpTimeout;
private transient final Executor executor;
private transient final HttpClient client;

@Value("${security.github.client.maxContentLength:1000000}")
private transient int maxContentLength;
Expand All @@ -69,14 +69,15 @@ public GithubClient(
@Value("${security.github.client.token:}") String githubToken) {
this.authorizationHeader = githubToken != null ? "Bearer " + githubToken.trim() : "";
this.httpTimeout = Duration.ofSeconds(httpTimeout);
this.executor = new ThreadPoolExecutor(0,
8,
30,
TimeUnit.SECONDS,
new SynchronousQueue<>());
this.client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_1_1)
.followRedirects(HttpClient.Redirect.NORMAL)
.connectTimeout(this.httpTimeout)
.build();
}

public String getGithubContent(String url) throws IOException, InterruptedException {
log.debug("Fetching Github URL {}", url);
URI uri = URI.create(url);
HttpResponse<InputStream> response = makeRequest(uri);

Expand All @@ -96,12 +97,6 @@ public String getGithubContent(String url) throws IOException, InterruptedExcept
}

private HttpResponse<InputStream> makeRequest(URI uri) throws InterruptedException {
HttpClient client = HttpClient.newBuilder()
.executor(executor)
.version(HttpClient.Version.HTTP_1_1)
.followRedirects(HttpClient.Redirect.NORMAL)
.connectTimeout(this.httpTimeout)
.build();
try {
return client.send(getRequest(uri), HttpResponse.BodyHandlers.ofInputStream());
} catch (IOException ex) {
Expand Down
Loading

0 comments on commit c8c0439

Please sign in to comment.