Skip to content

Commit

Permalink
Merge pull request #6110 from ant-media/support-apple-push-notification
Browse files Browse the repository at this point in the history
Add APN parameters to the AppSettings
  • Loading branch information
mekya committed Feb 19, 2024
2 parents 1c9e5a3 + f020526 commit e007c0f
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 56 deletions.
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,11 @@
<artifactId>firebase-admin</artifactId>
<version>9.2.0</version>
</dependency>
<dependency>
<groupId>com.eatthepath</groupId>
<artifactId>pushy</artifactId>
<version>0.15.4</version>
</dependency>
</dependencies>
<profiles>
<profile>
Expand Down
58 changes: 58 additions & 0 deletions src/main/java/io/antmedia/AppSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -2068,6 +2068,32 @@ public boolean isWriteStatsToDatastore() {
*/
@Value("${subscriberAuthenticationKey:#{ T(org.apache.commons.lang3.RandomStringUtils).randomAlphanumeric(32)}}")
private String subscriberAuthenticationKey = RandomStringUtils.randomAlphanumeric(32);


/**
* (Apple Push Notification) Apple Push Notification Server
* Default value is development enviroment(api.sandbox.push.apple.com) and production enviroment is api.push.apple.com
*/
@Value("${apnsServer:api.sandbox.push.apple.com}")
private String apnsServer = "api.sandbox.push.apple.com";

/**
* APN(Apple Push Notification) team id
*/
@Value("${apnTeamId:#{null}}")
private String apnTeamId;

/**
* APN(Apple Push Notification) private key
*/
@Value("${apnPrivateKey:#{null}}")
private String apnPrivateKey;

/**
* APN(Apple Push Notification) key Id
*/
@Value("${apnKeyId:#{null}}")
private String apnKeyId;

public void setWriteStatsToDatastore(boolean writeStatsToDatastore) {
this.writeStatsToDatastore = writeStatsToDatastore;
Expand Down Expand Up @@ -3565,4 +3591,36 @@ public void setSubscriberAuthenticationKey(String subscriberAuthenticationKey) {
this.subscriberAuthenticationKey = subscriberAuthenticationKey;
}

public String getApnsServer() {
return apnsServer;
}

public String getApnPrivateKey() {
return apnPrivateKey;
}

public String getApnKeyId() {
return apnKeyId;
}

public String getApnTeamId() {
return apnTeamId;
}

public void setApnTeamId(String apnTeamId) {
this.apnTeamId = apnTeamId;
}

public void setApnPrivateKey(String apnPrivateKey) {
this.apnPrivateKey = apnPrivateKey;
}

public void setApnKeyId(String apnKeyId) {
this.apnKeyId = apnKeyId;
}

public void setApnsServer(String apnsServer) {
this.apnsServer = apnsServer;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.util.List;

import org.json.simple.JSONObject;

import io.antmedia.rest.model.Result;

public interface IPushNotificationService {
Expand Down Expand Up @@ -33,7 +35,7 @@ public String toString() {
* @param serviceName: fcm or apn
* @return
*/
Result sendNotification(String topic, String jsonMessage, String serviceName);
Result sendNotification(String topic, JSONObject jsonMessage, String serviceName);

/**
* Send notification to both services if they are enabled
Expand All @@ -42,7 +44,7 @@ public String toString() {
* @param jsonMessage
* @return
*/
Result sendNotification(String topic, String jsonMessage) ;
Result sendNotification(String topic, JSONObject jsonMessage) ;


/**
Expand All @@ -51,7 +53,7 @@ public String toString() {
* @param jsonMessage
* @return
*/
Result sendNotification(List<String> subscriberIds, String jsonMessage);
Result sendNotification(List<String> subscriberIds, JSONObject jsonMessage);


/**
Expand All @@ -60,5 +62,5 @@ public String toString() {
* @param jsonMessage
* @return
*/
Result sendNotification(List<String> subscriberIds, String jsonMessage, String serviceName);
Result sendNotification(List<String> subscriberIds, JSONObject jsonMessage, String serviceName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import java.util.List;

import io.antmedia.datastore.db.types.PushNotificationToken;
import org.json.simple.JSONObject;

import io.antmedia.rest.model.Result;

public class PushNotificationServiceCommunity implements IPushNotificationService {
Expand All @@ -11,22 +12,22 @@ public class PushNotificationServiceCommunity implements IPushNotificationServic


@Override
public Result sendNotification(String topic, String jsonMessage, String serviceName) {
public Result sendNotification(String topic, JSONObject jsonMessage, String serviceName) {
return new Result(false, MESSAGE_TO_USE_ENTERPRISE_EDITION);
}

@Override
public Result sendNotification(String topic, String jsonMessage) {
public Result sendNotification(String topic, JSONObject jsonMessage) {
return new Result(false, MESSAGE_TO_USE_ENTERPRISE_EDITION);
}

@Override
public Result sendNotification(List<String> subscriberIds, String jsonMessage) {
public Result sendNotification(List<String> subscriberIds, JSONObject jsonMessage) {
return new Result(false, MESSAGE_TO_USE_ENTERPRISE_EDITION);
}

@Override
public Result sendNotification(List<String> subscriberIds, String jsonMessage, String serviceName) {
public Result sendNotification(List<String> subscriberIds, JSONObject jsonMessage, String serviceName) {
return new Result(false, MESSAGE_TO_USE_ENTERPRISE_EDITION);
}

Expand Down
78 changes: 50 additions & 28 deletions src/main/java/io/antmedia/rest/PushNotificationRestService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
Expand All @@ -13,6 +16,7 @@
import io.antmedia.rest.model.PushNotificationToSubscribers;
import io.antmedia.rest.model.Result;
import io.antmedia.websocket.WebSocketConstants;
import io.grpc.internal.JsonParser;
import jakarta.servlet.ServletContext;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.FormParam;
Expand All @@ -28,27 +32,26 @@
@Component
@Path("/v2/push-notification")
public class PushNotificationRestService {

@Context
protected ServletContext servletContext;

protected ApplicationContext appCtx;

private IPushNotificationService pushNotificationService;

private AppSettings appSettings;




public ApplicationContext getAppContext() {
if (servletContext != null) {
appCtx = (ApplicationContext) servletContext
.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
return appCtx;
}


public IPushNotificationService getPushNotificationService() {
if (pushNotificationService == null) {
ApplicationContext appContext = getAppContext();
Expand All @@ -58,7 +61,7 @@ public IPushNotificationService getPushNotificationService() {
}
return pushNotificationService;
}

public AppSettings getAppSettings() {
if (appSettings == null) {
ApplicationContext appContext = getAppContext();
Expand All @@ -68,8 +71,8 @@ public AppSettings getAppSettings() {
}
return appSettings;
}


@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/subscriber-auth-token")
Expand All @@ -78,43 +81,62 @@ public Result getSubscriberAuthenticationToken(@QueryParam("subscriberId") Strin
//one hour default - 3600 seconds
timeoutDurationInSeconds = 3600;
}
long expireTimeMs = System.currentTimeMillis() + (timeoutDurationInSeconds * 1000);
String jwtToken = JWTFilter.generateJwtToken(getAppSettings().getSubscriberAuthenticationKey(), expireTimeMs, WebSocketConstants.SUBSCRIBER_ID, subscriberId);

return new Result(true, jwtToken, "Token is available in dataId field");
if (StringUtils.isNotBlank(subscriberId)) {
long expireTimeMs = System.currentTimeMillis() + (timeoutDurationInSeconds * 1000);
String jwtToken = JWTFilter.generateJwtToken(getAppSettings().getSubscriberAuthenticationKey(), expireTimeMs, WebSocketConstants.SUBSCRIBER_ID, subscriberId);

return new Result(true, jwtToken, "Token is available in dataId field");
}
else {
return new Result(false, "subscriberId is blank. Please give subscriberId as query parameter");

}
}

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/subscribers")
public Result sendPushNotification(PushNotificationToSubscribers pushNotificationToSubcribers, @QueryParam("serviceName") String serviceName) {
if (StringUtils.isBlank(serviceName)) {
return getPushNotificationService().sendNotification(pushNotificationToSubcribers.getSubscribers() , pushNotificationToSubcribers.getJsonMessage());
}
else {
return getPushNotificationService().sendNotification(pushNotificationToSubcribers.getSubscribers(), pushNotificationToSubcribers.getJsonMessage(), serviceName);
JSONParser parser = new JSONParser();
try {
if (StringUtils.isBlank(serviceName))
{
return getPushNotificationService().sendNotification(pushNotificationToSubcribers.getSubscribers() , (JSONObject)parser.parse(pushNotificationToSubcribers.getJsonMessage()));
}
else
{
return getPushNotificationService().sendNotification(pushNotificationToSubcribers.getSubscribers(), (JSONObject)parser.parse(pushNotificationToSubcribers.getJsonMessage()), serviceName);
}
} catch (ParseException e) {
return new Result(false, "JSON content cannot be parsed. Make sure JSON content is in correct format");
}
}

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/topics/{topic}")
public Result sendPushNotification(@PathParam("topic") String topic, String jsonMessage, @QueryParam("serviceName") String serviceName) {
if (StringUtils.isBlank(serviceName)) {
return getPushNotificationService().sendNotification(topic, jsonMessage);
}
else {
return getPushNotificationService().sendNotification(topic, jsonMessage, serviceName);
JSONParser parser = new JSONParser();
try {
if (StringUtils.isBlank(serviceName)) {
return getPushNotificationService().sendNotification(topic, (JSONObject)parser.parse(jsonMessage));

}
else {
return getPushNotificationService().sendNotification(topic, (JSONObject)parser.parse(jsonMessage), serviceName);
}
} catch (ParseException e) {
return new Result(false, "JSON content cannot be parsed");
}
}


public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}



}
22 changes: 21 additions & 1 deletion src/test/java/io/antmedia/test/AppSettingsUnitTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,22 @@ public void testSettings() {

appSettings.setTimeTokenSecretForPublish("secretpublish");
assertEquals("secretpublish", appSettings.getTimeTokenSecretForPublish());

String apnKeyId = "apnkeyid";
appSettings.setApnKeyId(apnKeyId);
assertEquals(apnKeyId, appSettings.getApnKeyId());

String teamId = "apnTeamId";
appSettings.setApnTeamId(teamId);
assertEquals(teamId, appSettings.getApnTeamId());

String apnServer = "apnServer";
appSettings.setApnsServer(apnServer);
assertEquals(apnServer, appSettings.getApnsServer());

String privateKey = "privateKey";
appSettings.setApnPrivateKey(privateKey);
assertEquals(privateKey, appSettings.getApnPrivateKey());
}


Expand Down Expand Up @@ -497,12 +513,16 @@ public void testUnsetAppSettings(AppSettings appSettings) {
assertNull(appSettings.getTimeTokenSecretForPlay());
assertNotNull(appSettings.getSubscriberAuthenticationKey());
assertNull(appSettings.getFirebaseAccountKeyJSON());
assertNull(appSettings.getApnKeyId());
assertNull(appSettings.getApnTeamId());
assertNull(appSettings.getApnPrivateKey());
assertEquals("api.sandbox.push.apple.com", appSettings.getApnsServer());

//if we add a new field, we just need to check its default value in this test
//When a new field is added or removed please update the number of fields and make this test pass
//by also checking its default value.
assertEquals("New field is added to settings. PAY ATTENTION: Please CHECK ITS DEFAULT VALUE and fix the number of fields.",
170, numberOfFields);
174, numberOfFields);

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import java.util.Arrays;

import org.json.simple.JSONObject;
import org.junit.Test;

import io.antmedia.pushnotification.PushNotificationServiceCommunity;
Expand All @@ -17,19 +18,23 @@ public class PushNotificationCommunityTest {
public void testPushNotificaitonServiceCommunity() {
PushNotificationServiceCommunity pushNotificationServiceCommunity = new PushNotificationServiceCommunity();

Result sendNotification = pushNotificationServiceCommunity.sendNotification("title", "message", "token");
JSONObject jsObject = new JSONObject();
jsObject.put("title", "hello world");
jsObject.put("apn-topic", "io.antmedia.ios.webrtc.sample");

Result sendNotification = pushNotificationServiceCommunity.sendNotification("title", jsObject, "token");
assertFalse(sendNotification.isSuccess());
assertEquals("Push Notification Service is not available community edition. Please use enterprise edition", sendNotification.getMessage());

sendNotification = pushNotificationServiceCommunity.sendNotification("topic", "message");
sendNotification = pushNotificationServiceCommunity.sendNotification("topic", jsObject);
assertFalse(sendNotification.isSuccess());
assertEquals("Push Notification Service is not available community edition. Please use enterprise edition", sendNotification.getMessage());

sendNotification = pushNotificationServiceCommunity.sendNotification(Arrays.asList(""), "message");
sendNotification = pushNotificationServiceCommunity.sendNotification(Arrays.asList(""), jsObject);
assertFalse(sendNotification.isSuccess());
assertEquals("Push Notification Service is not available community edition. Please use enterprise edition", sendNotification.getMessage());

sendNotification = pushNotificationServiceCommunity.sendNotification(Arrays.asList(""), "message", "serviceName");
sendNotification = pushNotificationServiceCommunity.sendNotification(Arrays.asList(""), jsObject, "serviceName");
assertFalse(sendNotification.isSuccess());
assertEquals("Push Notification Service is not available community edition. Please use enterprise edition", sendNotification.getMessage());

Expand Down
Loading

0 comments on commit e007c0f

Please sign in to comment.