Skip to content

Commit f4201d4

Browse files
Merge pull request #197 from RADAR-base/release-1.1.0
Release 1.1.0
2 parents cfc1470 + 34305bc commit f4201d4

File tree

13 files changed

+410
-41
lines changed

13 files changed

+410
-41
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,8 @@
3535
/kubernetes
3636

3737
# logs
38-
/logs
38+
/logs
39+
40+
# vscode
41+
/.vscode
42+
bin/

Dockerfile

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM openjdk:11.0.1-jdk-slim AS builder
1+
FROM openjdk:11-jdk-slim AS builder
22

33
RUN mkdir /code
44
WORKDIR /code
@@ -11,10 +11,11 @@ RUN ./gradlew --version
1111

1212
COPY ./build.gradle ./settings.gradle /code/
1313
COPY ./src /code/src
14+
COPY ./shadow-radar-auth /code/shadow-radar-auth
1415

1516
RUN ./gradlew unpack
1617

17-
FROM openjdk:11.0.1-jre-slim
18+
FROM openjdk:11-jre-slim
1819

1920
LABEL maintainer="Yatharth Ranjan <yatharth.ranjan@kcl.ac.uk>"
2021

@@ -26,6 +27,11 @@ ENV SPRING_PROFILES_ACTIVE prod
2627
VOLUME /tmp
2728
ARG DEPENDENCY=/code/build/dependency
2829

30+
RUN apt-get update && apt-get install -y \
31+
curl \
32+
wget \
33+
&& rm -rf /var/lib/apt/lists/*
34+
2935
COPY --from=builder ${DEPENDENCY}/BOOT-INF/lib /app/lib
3036
COPY --from=builder ${DEPENDENCY}/META-INF /app/META-INF
3137
COPY --from=builder ${DEPENDENCY}/BOOT-INF/classes /app

README.md

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,21 @@ There is also support for legacy XMPP protocol for FCM.
2929

3030
This will start the database at `localhost:9001`
3131

32-
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`.
32+
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.
3333

34-
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. On mac or linux, run the below -
34+
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.
35+
36+
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" />`
37+
38+
6. There are 2 ways to communicate with the Firebase Cloud Messaging- XMPP and Admin SDK. At least one of these needs to be configured. To configure these, please look at the [FCM section](#fcm).
39+
40+
7. To run the build on mac or linux, run the below -
3541
```bash
3642
./gradlew bootRun
3743
```
3844
You can also run in an IDE (like IntelliJ Idea) by giving the `/src/main/java/org/radarbase/appserver/AppserverApplication.java` as the main class.
3945

40-
5. The App-server is now connected to the FCM XMPP server and is able to send and receive messages. On your mobile application, try sending an upstream message using the FCM sdk for your platform. Notification scheduling parses payloads from upstream messages containing the action SCHEDULE. The format of the data payload of upstream message should contain at least-
46+
8. The App-server is now connected to the FCM XMPP server and is able to send and receive messages. On your mobile application, try sending an upstream message using the FCM sdk for your platform. Notification scheduling parses payloads from upstream messages containing the action SCHEDULE. The format of the data payload of upstream message should contain at least-
4147
```json
4248
{
4349
"data":
@@ -54,11 +60,11 @@ There is also support for legacy XMPP protocol for FCM.
5460
}
5561
```
5662

57-
6. Voila!, you will now receive a notification at the schedule time (specified by `time` in the payload) on your device.
63+
9. Voila!, you will now receive a notification at the schedule time (specified by `time` in the payload) on your device.
5864

59-
7. You can also achieve the same using more reliable and flexible REST API using the schedule endpoint. Please refer to REST API section below for more info.
65+
10. You can also achieve the same using more reliable and flexible REST API using the schedule endpoint. Please refer to REST API section below for more info.
6066

61-
8. API documentation is available via Swagger UI when you launch the app server. Please refer to the Documentation section below.
67+
11. API documentation is available via Swagger UI when you launch the app server. Please refer to the Documentation section below.
6268

6369
## REST API
6470

@@ -107,6 +113,8 @@ The same result as stated in [Getting Started](#getting-started) can be achieved
107113
There are other features provided via the REST endpoints. These can be explored using swagger-ui. Please refer to [Documentation](#documentation) section.
108114

109115
## FCM
116+
117+
### XMPP
110118
The FCM related code is provided in the `org.radarbase.fcm` package. This can be explored in java-docs as mention in the [Documentation](#documentation) section.
111119
To use Firebase Cloud Messaging(FCM), you will need to configure the following properties -
112120

@@ -116,7 +124,11 @@ To use Firebase Cloud Messaging(FCM), you will need to configure the following p
116124
| fcmserver.serverkey | Server Key from FCM. Can be found in the FCM project settings | NA | Yes |
117125
| fcmserver.fcmsender | The Sender to use for sending messages. There is a choice of using XMPP or FCM Admin SDK. | `org.radarbase.fcm.downstream.XmppFcmSender` | No |
118126

119-
**Note:** Only sending messages via XMPP protocol supports Delivery Receipts on FCM.
127+
**Note:** Only sending messages via XMPP protocol supports Delivery Receipts on FCM.
128+
129+
### AdminSDK
130+
To configure AdminSDK, follow the official Firebase [documentation](https://firebase.google.com/docs/admin/setup#initialize-sdk) till you setup the enviroment variable. In the properties file, you would need to change `fcmserver.fcmsender` to `org.radarbase.fcm.downstream.AdminSdkFcmSender` and set `fcmserver.xmpp.upstream.enable` to `false`.
131+
120132

121133
## Docker/ Docker Compose
122134
The AppServer is also available as a docker container. It's [Dockerfile](/Dockerfile) is provided with the project. It can be run as follows -
@@ -132,7 +144,7 @@ The same can be achieved by running as a docker-compose service. Just specify th
132144
```yml
133145
services:
134146
appserver:
135-
image: radarbase/radar-appserver:0.0.1
147+
image: radarbase/radar-appserver:1.1.0
136148
restart: always
137149
ports:
138150
- 8080:8080
@@ -344,7 +356,7 @@ To enable security of specific provider, please read the sections below.
344356
### Management Portal
345357
To enable security via the [RADAR Management Portal](https://github.com/RADAR-base/ManagementPortal), set the following property -
346358
```ini
347-
managementportal.security.enabled=true
359+
security.radar.managementportal.url=true
348360
```
349361
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.
350362
All the classes are located in [/src/main/java/org/radarbase/appserver/auth/managementportal](/src/main/java/org/radarbase/appserver/auth/managementportal).
@@ -468,20 +480,4 @@ This will run checkstyle, PMD, spot bugs, unit tests and integration tests.
468480
- Uses [lombok.data](https://projectlombok.org/) in most places to reduce boiler plate code and make it more readable.
469481
- Has support for Auditing of database entities.
470482
- Uses and extends the Spring XMPP integration library for implementing the XMPP protocol.
471-
- Extends `XmppConnectionFactoryBean` with support for Reconnection and connection draining implementation using a Back-off strategy.
472-
473-
### TODO
474-
475-
- Add better documentation.
476-
- Add validation of notification requests using the protocol and enrolment date of the user.
477-
- Add endpoint to filter notifications based on different params.
478-
- ~~Update lastOpened metric for user when a request is received.~~
479-
- ~~Add batch scheduling of notifications.~~
480-
- Add Management Portal service for getting any missing info not present in a request.
481-
- Add support for sending messages via Firebase Admin SDK.
482-
- ~~Make the Xmpp Connection more robust by adding reconnection logic.~~
483-
- Break out the org.radarbase.fcm package into its own module to be used as a library.
484-
- ~~Add docker builds.~~
485-
- Add a Angular UI to view, update and schedule/send notifications to subjects.
486-
- Investigate the feasibility of adding as an integration to the Management Portal for various tasks. (For instance, a new token can be sent via push notification using a button on MP to the device if the token has expired).
487-
- ~~Add security to the application using MP OAuth client resource.~~
483+
- Extends `XmppConnectionFactoryBean` with support for Reconnection and connection draining implementation using a Back-off strategy.

build.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ plugins {
1515
id "com.github.spotbugs" version "4.5.0"
1616
id 'jacoco'
1717
id "com.github.lkishalmi.gatling" version "3.3.4"
18+
id 'com.github.johnrengelman.shadow' version '6.1.0'
1819
}
1920

2021
apply plugin: 'java'
@@ -24,7 +25,7 @@ apply plugin: 'io.spring.dependency-management'
2425
apply plugin: 'scala'
2526

2627
group = 'org.radarbase'
27-
version = '1.0.0'
28+
version = '1.1.0'
2829
sourceCompatibility = 1.11
2930

3031
repositories {
@@ -115,6 +116,8 @@ dependencies {
115116
exclude group: 'javax.servlet', module: 'servlet-api'
116117
}
117118

119+
implementation project(path: ':shadow-radar-auth', configuration: 'shadow')
120+
118121
codacy 'com.github.codacy:codacy-coverage-reporter:-SNAPSHOT'
119122

120123
testCompile group: 'io.gatling.highcharts', name: 'gatling-charts-highcharts', version: '3.3.1'

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
rootProject.name = 'appserver'
2+
include 'shadow-radar-auth'

shadow-radar-auth/build.gradle

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
plugins {
2+
id 'com.github.johnrengelman.shadow'
3+
}
4+
apply plugin: 'java-library'
5+
6+
repositories {
7+
mavenCentral()
8+
jcenter()
9+
}
10+
11+
dependencies {
12+
implementation "com.fasterxml.jackson.core:jackson-databind:2.11.4"
13+
implementation "com.fasterxml.jackson.core:jackson-annotations:2.11.4"
14+
implementation "commons-codec:commons-codec:1.15"
15+
}
16+
17+
shadowJar {
18+
relocate 'org.apache.commons.codec', 'shadow.org.apache.commons.codec'
19+
relocate 'com.fasterxml.jackson', 'shadow.com.fasterxml.jackson'
20+
}

src/main/java/org/radarbase/appserver/config/AuthConfig.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package org.radarbase.appserver.config;
22

3+
import lombok.extern.slf4j.Slf4j;
4+
import org.radarcns.auth.config.TokenValidatorConfig;
5+
import org.radarcns.auth.config.TokenVerifierPublicKeyConfig;
6+
import org.radarcns.auth.exception.ConfigurationException;
37
import org.radarcns.auth.token.RadarToken;
48
import org.springframework.beans.factory.annotation.Autowired;
59
import org.springframework.beans.factory.annotation.Value;
@@ -17,6 +21,7 @@
1721
@Configuration
1822
@ConditionalOnProperty(name = "security.radar.managementportal.enabled", havingValue = "true")
1923
@EnableAspectJAutoProxy
24+
@Slf4j
2025
public class AuthConfig {
2126

2227
@Value("${security.radar.managementportal.url}")
@@ -30,10 +35,25 @@ public ManagementPortalAuthProperties getAuthProperties() {
3035
return new ManagementPortalAuthProperties(baseUrl, resourceName);
3136
}
3237

38+
/**
39+
* First tries to load config from radar_is.yml config file. If any issues, then uses the default
40+
* MP oauth token key endpoint.
41+
*
42+
* @param managementPortalAuthProperties
43+
* @return
44+
*/
3345
@Bean
3446
AuthValidator<RadarToken> getAuthValidator(
3547
@Autowired ManagementPortalAuthProperties managementPortalAuthProperties) {
36-
return new ManagementPortalAuthValidator(managementPortalAuthProperties);
48+
try {
49+
TokenValidatorConfig validatorConfig = TokenVerifierPublicKeyConfig.readFromFileOrClasspath();
50+
return new ManagementPortalAuthValidator(managementPortalAuthProperties, validatorConfig);
51+
} catch (ConfigurationException exc) {
52+
log.warn(
53+
"Could not loading config from RADAR_IS file. Now using default public key "
54+
+ "endpoint...");
55+
return new ManagementPortalAuthValidator(managementPortalAuthProperties);
56+
}
3757
}
3858

3959
@Bean

src/main/java/org/radarbase/appserver/controller/FcmNotificationController.java

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,67 @@ public ResponseEntity<FcmNotifications> getNotificationsUsingProjectId(
138138
public ResponseEntity<FcmNotificationDto> addSingleNotification(
139139
@PathVariable String projectId,
140140
@PathVariable String subjectId,
141+
@RequestParam(required = false, defaultValue = "true") boolean schedule,
141142
@Valid @RequestBody FcmNotificationDto notification)
142143
throws URISyntaxException {
143144
FcmNotificationDto notificationDto =
144-
this.notificationService.addNotification(notification, subjectId, projectId);
145+
this.notificationService.addNotification(notification, subjectId, projectId, schedule);
145146
return ResponseEntity.created(
146147
new URI("/" + PathsUtil.MESSAGING_NOTIFICATION_PATH + "/" + notificationDto.getId()))
147148
.body(notificationDto);
148149
}
149150

151+
@Authorized(
152+
permission = AuthPermissions.UPDATE,
153+
entity = AuthEntities.SUBJECT,
154+
permissionOn = PermissionOn.SUBJECT)
155+
@PostMapping(
156+
"/"
157+
+ PathsUtil.PROJECT_PATH
158+
+ "/"
159+
+ PathsUtil.PROJECT_ID_CONSTANT
160+
+ "/"
161+
+ PathsUtil.USER_PATH
162+
+ "/"
163+
+ PathsUtil.SUBJECT_ID_CONSTANT
164+
+ "/"
165+
+ PathsUtil.MESSAGING_NOTIFICATION_PATH
166+
+ "/schedule")
167+
public ResponseEntity<FcmNotifications> scheduleUserNotifications(
168+
@PathVariable String projectId,
169+
@PathVariable String subjectId)
170+
throws URISyntaxException {
171+
return ResponseEntity.ok(
172+
this.notificationService.scheduleAllUserNotifications(subjectId, projectId));
173+
}
174+
175+
@Authorized(
176+
permission = AuthPermissions.UPDATE,
177+
entity = AuthEntities.SUBJECT,
178+
permissionOn = PermissionOn.SUBJECT)
179+
@PostMapping(
180+
"/"
181+
+ PathsUtil.PROJECT_PATH
182+
+ "/"
183+
+ PathsUtil.PROJECT_ID_CONSTANT
184+
+ "/"
185+
+ PathsUtil.USER_PATH
186+
+ "/"
187+
+ PathsUtil.SUBJECT_ID_CONSTANT
188+
+ "/"
189+
+ PathsUtil.MESSAGING_NOTIFICATION_PATH
190+
+ "/"
191+
+ PathsUtil.NOTIFICATION_ID_CONSTANT
192+
+ "/schedule")
193+
public ResponseEntity<FcmNotificationDto> scheduleUserNotification(
194+
@PathVariable String projectId,
195+
@PathVariable String subjectId,
196+
@PathVariable long notificationId)
197+
throws URISyntaxException {
198+
return ResponseEntity.ok(
199+
this.notificationService.scheduleNotification(subjectId, projectId, notificationId));
200+
}
201+
150202
@Authorized(
151203
permission = AuthPermissions.UPDATE,
152204
entity = AuthEntities.SUBJECT,
@@ -166,9 +218,10 @@ public ResponseEntity<FcmNotificationDto> addSingleNotification(
166218
public ResponseEntity<FcmNotifications> addBatchNotifications(
167219
@PathVariable String projectId,
168220
@PathVariable String subjectId,
221+
@RequestParam(required = false, defaultValue = "true") boolean schedule,
169222
@Valid @RequestBody FcmNotifications notifications) {
170223
return ResponseEntity.ok(
171-
this.notificationService.addNotifications(notifications, subjectId, projectId));
224+
this.notificationService.addNotifications(notifications, subjectId, projectId, schedule));
172225
}
173226

174227
@Authorized(

0 commit comments

Comments
 (0)