1
0

Initial commit for push service

This commit is contained in:
2020-07-21 22:55:29 +02:00
commit 604cdd04b0
14 changed files with 583 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>push-service-parent</artifactId>
<groupId>de.77zzcx7</groupId>
<version>1-SNAPSHOT</version>
</parent>
<artifactId>push-service-server</artifactId>
<packaging>${packaging.type}</packaging>
<description>The server part of the push-service</description>
<name>push-service-server</name>
<properties>
<packaging.type>jar</packaging.type>
</properties>
<dependencies>
<dependency>
<groupId>nl.martijndwars</groupId>
<artifactId>web-push</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>de.77zzcx7</groupId>
<artifactId>push-service-client-lib</artifactId>
<version>${version}</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>build-war</id>
<properties>
<packaging.type>war</packaging.type>
</properties>
<build>
<finalName>${project.artifactId}##${parallelDeploymentVersion}</finalName>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

View File

@@ -0,0 +1,18 @@
package de.pushservice.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class PushServiceApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(PushServiceApplication.class);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(PushServiceApplication.class);
}
}

View File

@@ -0,0 +1,38 @@
package de.pushservice.server.controller;
import de.pushservice.client.ResponseReason;
import de.pushservice.client.dto.NotificationRequestDto;
import de.pushservice.server.decorator.MessageDecorator;
import de.pushservice.server.decorator.SubscriptionDecorator;
import nl.martijndwars.webpush.Notification;
import nl.martijndwars.webpush.PushService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PushServiceController {
private static final Logger LOGGER = LoggerFactory.getLogger(PushServiceController.class);
@PostMapping
public ResponseEntity notify(NotificationRequestDto notificationRequestDto) {
try {
final SubscriptionDecorator subscription = SubscriptionDecorator
.fromDto(notificationRequestDto.getSubscriptionDto());
final Notification notification = MessageDecorator.fromDto(notificationRequestDto.getMessageDto())
.toNotification(subscription);
final PushService extPushService = new PushService();
extPushService.send(notification);
return ResponseReason.OK.toResponseEntity();
}
catch(Exception e) {
LOGGER.error("Error while sending notification!", e);
return ResponseReason.UNKNOWN_ERROR.toResponseEntity();
}
}
}

View File

@@ -0,0 +1,36 @@
package de.pushservice.server.decorator;
import de.pushservice.client.dto.MessageDto;
import nl.martijndwars.webpush.Notification;
import nl.martijndwars.webpush.Urgency;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidKeySpecException;
public class MessageDecorator {
private MessageDto dto;
private MessageDecorator(MessageDto dto) {
this.dto = dto;
}
public static final MessageDecorator fromDto(MessageDto dto) {
return new MessageDecorator(dto);
}
public Notification toNotification(SubscriptionDecorator subscription) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
return Notification.builder()
.endpoint(subscription.getEndpoint())
.userPublicKey(subscription.getUserPublicKey())
.userAuth(subscription.getAuthAsBytes())
.payload(dto.getPayload())
.urgency(getExtUrgency())
.topic(dto.getTopic())
.build();
}
private Urgency getExtUrgency() {
return Urgency.valueOf(dto.getUrgency().name());
}
}

View File

@@ -0,0 +1,48 @@
package de.pushservice.server.decorator;
import de.pushservice.client.dto.SubscriptionDto;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
public class SubscriptionDecorator {
private SubscriptionDto dto;
private SubscriptionDecorator(SubscriptionDto dto) {
this.dto = dto;
}
public static final SubscriptionDecorator fromDto(SubscriptionDto dto) {
return new SubscriptionDecorator(dto);
}
byte[] getAuthAsBytes() {
return Base64.getDecoder().decode(dto.getAuth());
}
private byte[] getKeyAsBytes() {
return Base64.getDecoder().decode(dto.getKey());
}
PublicKey getUserPublicKey() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
KeyFactory kf = KeyFactory.getInstance("ECDH", BouncyCastleProvider.PROVIDER_NAME);
ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp256r1");
ECPoint point = ecSpec.getCurve().decodePoint(getKeyAsBytes());
ECPublicKeySpec pubSpec = new ECPublicKeySpec(point, ecSpec);
return kf.generatePublic(pubSpec);
}
String getEndpoint() {
return dto.getEndpoint();
}
}