diff --git a/slack-app-backend/pom.xml b/slack-app-backend/pom.xml
index c417ef625..45082e8ab 100644
--- a/slack-app-backend/pom.xml
+++ b/slack-app-backend/pom.xml
@@ -41,13 +41,6 @@
${slf4j.version}
-
- javax.servlet
- javax.servlet-api
- ${javax.servlet-api.version}
- provided
-
-
org.eclipse.jetty
jetty-servlet
diff --git a/slack-app-backend/src/main/java/com/slack/api/app_backend/events/servlet/SlackEventsApiServlet.java b/slack-app-backend/src/main/java/com/slack/api/app_backend/events/servlet/SlackEventsApiServlet.java
deleted file mode 100644
index 948a8224a..000000000
--- a/slack-app-backend/src/main/java/com/slack/api/app_backend/events/servlet/SlackEventsApiServlet.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.slack.api.app_backend.events.servlet;
-
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.slack.api.app_backend.SlackSignature;
-import com.slack.api.app_backend.events.EventsDispatcher;
-import com.slack.api.app_backend.events.EventsDispatcherFactory;
-import com.slack.api.util.json.GsonFactory;
-import lombok.extern.slf4j.Slf4j;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.Locale;
-import java.util.stream.Collectors;
-
-@Deprecated // Please consider Bolt framework with bolt-servlet adapter instead
-@Slf4j
-public abstract class SlackEventsApiServlet extends HttpServlet {
-
- private EventsDispatcher dispatcher = EventsDispatcherFactory.getInstance();
- private SlackSignatureVerifier signatureVerifier;
-
- protected abstract void setupDispatcher(EventsDispatcher dispatcher);
-
- public void init() throws ServletException {
- super.init();
- setupDispatcher(dispatcher);
- dispatcher.start();
- signatureVerifier = new SlackSignatureVerifier(new SlackSignature.Generator(getSlackSigningSecret()));
- }
-
- public void destroy() {
- super.destroy();
- dispatcher.stop();
- }
-
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
- String requestBody = doReadRequestBodyAsString(req);
-
- // NOTE: It's also possible to do the same in a servlet filter
- if (isSignatureVerifierEnabled()) {
- boolean validSignature = this.signatureVerifier.isValid(req, requestBody);
- if (!validSignature) { // invalid signature
- if (log.isDebugEnabled()) {
- String signature = req.getHeader(SlackSignature.HeaderNames.X_SLACK_SIGNATURE);
- log.debug("An invalid X-Slack-Signature detected - {}", signature);
- }
- resp.setStatus(401);
- return;
- }
- }
-
- String contentType = req.getHeader("Content-Type");
- if (contentType != null && contentType.toLowerCase(Locale.ENGLISH).trim().startsWith("application/json")) {
- JsonObject payload = GsonFactory.createSnakeCase().fromJson(requestBody, JsonElement.class).getAsJsonObject();
- String eventType = payload.get("type").getAsString();
- if (eventType != null && eventType.equals("url_verification")) {
- String challenge = payload.get("challenge").getAsString();
- // url_verification: https://api.slack.com/events/url_verification
- resp.setStatus(200);
- resp.setHeader("Content-Type", "text/plain");
- resp.getOutputStream().write(challenge.getBytes(Charset.forName("UTF-8")));
- } else {
- dispatcher.enqueue(requestBody);
- resp.setStatus(200);
- }
- } else {
- log.warn("Unexpected request detected - Content-Type: {}", req.getHeader("Content-Type"));
- resp.setStatus(400);
- }
-
- }
-
- /**
- * Returns the signing secret supposed to be used for verifying requests from Slack.
- */
- protected String getSlackSigningSecret() {
- return System.getenv(SlackSignature.Secret.DEFAULT_ENV_NAME);
- }
-
- /**
- * If you'd like to do the same in a servlet filter, return false instead.
- */
- protected boolean isSignatureVerifierEnabled() {
- return true;
- }
-
- /**
- * Reads the request body and returns the value as a string.
- */
- protected String doReadRequestBodyAsString(HttpServletRequest req) throws IOException {
- return req.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
- }
-
-}
diff --git a/slack-app-backend/src/main/java/com/slack/api/app_backend/events/servlet/SlackSignatureVerifier.java b/slack-app-backend/src/main/java/com/slack/api/app_backend/events/servlet/SlackSignatureVerifier.java
deleted file mode 100644
index e17e37c20..000000000
--- a/slack-app-backend/src/main/java/com/slack/api/app_backend/events/servlet/SlackSignatureVerifier.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.slack.api.app_backend.events.servlet;
-
-import com.slack.api.app_backend.SlackSignature;
-import lombok.extern.slf4j.Slf4j;
-
-import javax.servlet.http.HttpServletRequest;
-
-@Deprecated // Please consider Bolt framework with bolt-servlet adapter instead
-@Slf4j
-public class SlackSignatureVerifier {
-
- private final SlackSignature.Verifier verifier;
-
- public SlackSignatureVerifier() {
- this(new SlackSignature.Generator());
- }
-
- public SlackSignatureVerifier(SlackSignature.Generator signatureGenerator) {
- this.verifier = new SlackSignature.Verifier(signatureGenerator);
- }
-
- public boolean isValid(HttpServletRequest request, String requestBody) {
- return isValid(request, requestBody, System.currentTimeMillis());
- }
-
- public boolean isValid(HttpServletRequest request, String requestBody, long nowInMillis) {
- if (request != null && request.getHeaderNames() != null) {
- String requestTimestamp = request.getHeader(SlackSignature.HeaderNames.X_SLACK_REQUEST_TIMESTAMP);
- String requestSignature = request.getHeader(SlackSignature.HeaderNames.X_SLACK_SIGNATURE);
- return verifier.isValid(requestTimestamp, requestBody, requestSignature, nowInMillis);
- } else {
- return false;
- }
- }
-
-}
diff --git a/slack-app-backend/src/main/java/com/slack/api/app_backend/events/servlet/package-info.java b/slack-app-backend/src/main/java/com/slack/api/app_backend/events/servlet/package-info.java
deleted file mode 100644
index cd35ec7ba..000000000
--- a/slack-app-backend/src/main/java/com/slack/api/app_backend/events/servlet/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * Using the classes under this package is no longer recommended.
- * Please consider going with bolt-servlet for new app development.
- */
-package com.slack.api.app_backend.events.servlet;
\ No newline at end of file
diff --git a/slack-app-backend/src/test/java/test_locally/app_backend/events/EventsApiHandlerTest.java b/slack-app-backend/src/test/java/test_locally/app_backend/events/EventsApiHandlerTest.java
deleted file mode 100644
index a37a5f6a7..000000000
--- a/slack-app-backend/src/test/java/test_locally/app_backend/events/EventsApiHandlerTest.java
+++ /dev/null
@@ -1,209 +0,0 @@
-package test_locally.app_backend.events;
-
-import com.slack.api.app_backend.events.EventsDispatcher;
-import com.slack.api.app_backend.events.handler.AppUninstalledHandler;
-import com.slack.api.app_backend.events.handler.GoodbyeHandler;
-import com.slack.api.app_backend.events.handler.MessageHandler;
-import com.slack.api.app_backend.events.payload.AppUninstalledPayload;
-import com.slack.api.app_backend.events.payload.GoodbyePayload;
-import com.slack.api.app_backend.events.payload.MessagePayload;
-import com.slack.api.app_backend.events.payload.UrlVerificationPayload;
-import com.slack.api.app_backend.events.servlet.SlackEventsApiServlet;
-import com.slack.api.util.json.GsonFactory;
-import org.eclipse.jetty.http.HttpTester;
-import org.eclipse.jetty.servlet.ServletTester;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import javax.servlet.annotation.WebServlet;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-// TODO: These tests somehow fail on TravisCI builds.
-// will come up with better ways to do the similar.
-public class EventsApiHandlerTest {
-
- @WebServlet(urlPatterns = "/")
- public static class SampleServlet extends SlackEventsApiServlet {
- @Override
- protected boolean isSignatureVerifierEnabled() {
- return false;
- }
-
- @Override
- protected void setupDispatcher(EventsDispatcher dispatcher) {
- dispatcher.register(MESSAGE);
- dispatcher.register(APP_UNINSTALLED);
- dispatcher.register(GOODBYE);
- }
- }
-
- // --------------------------------
- // message
-
- public static AtomicInteger MESSAGE_CALL_COUNTER = new AtomicInteger(0);
-
- public static MessageHandler MESSAGE = new MessageHandler() {
- @Override
- public void handle(MessagePayload payload) {
- MESSAGE_CALL_COUNTER.incrementAndGet();
- }
- };
-
- // --------------------------------
- // app_uninstalled
-
- public static AtomicInteger APP_UNINSTALLED_CALL_COUNTER = new AtomicInteger(0);
-
- public static AppUninstalledHandler APP_UNINSTALLED = new AppUninstalledHandler() {
- @Override
- public void handle(AppUninstalledPayload event) {
- APP_UNINSTALLED_CALL_COUNTER.incrementAndGet();
- }
- };
-
- // --------------------------------
- // goodbye
-
- public static AtomicInteger GOODBYE_CALL_COUNTER = new AtomicInteger(0);
-
- public static GoodbyeHandler GOODBYE = new GoodbyeHandler() {
- @Override
- public void handle(GoodbyePayload payload) {
- GOODBYE_CALL_COUNTER.incrementAndGet();
- }
- };
-
- // -------------------------------------------------------------------
-
- @Ignore
- @Test
- public void urlVerification() throws Exception {
- ServletTester tester = getServletTester();
- HttpTester.Request request = prepareRequest();
-
- UrlVerificationPayload payload = new UrlVerificationPayload();
- payload.setChallenge("cha-xxxxxx");
- payload.setToken("token-xxxx");
- request.setContent(GsonFactory.createSnakeCase().toJson(payload));
-
- HttpTester.Response response = HttpTester.parseResponse(tester.getResponses(request.generate()));
-
- assertThat(response.getContent(), is(equalTo("cha-xxxxxx")));
- assertThat(response.getStatus(), is(equalTo(200)));
- assertThat(response.get("Content-Type"), is(equalTo("text/plain")));
- }
-
- @Ignore
- @Test
- public void message() throws Exception {
- ServletTester tester = getServletTester();
- HttpTester.Request request = prepareRequest();
-
- request.setContent("{\n" +
- " \"token\": \"XXYYZZ\",\n" +
- " \"team_id\": \"TXXXXXXXX\",\n" +
- " \"api_app_id\": \"AXXXXXXXXX\",\n" +
- " \"event\": {\n" +
- " \"type\": \"message\",\n" +
- " \"channel\": \"C2147483705\",\n" +
- " \"user\": \"U2147483697\",\n" +
- " \"text\": \"Hello world\",\n" +
- " \"ts\": \"1355517523.000005\"\n" +
- "} ,\n" +
- " \"type\": \"event_callback\",\n" +
- " \"event_id\": \"EvXXXXXXXX\",\n" +
- " \"event_time\": 1234567890\n" +
- "}");
-
- HttpTester.Response response1 = HttpTester.parseResponse(tester.getResponses(request.generate()));
- HttpTester.Response response2 = HttpTester.parseResponse(tester.getResponses(request.generate()));
- HttpTester.Response response3 = HttpTester.parseResponse(tester.getResponses(request.generate()));
-
- // wait for the async execution
- Thread.sleep(200L);
-
- assertThat(response1.getStatus(), is(equalTo(200)));
- assertThat(response2.getStatus(), is(equalTo(200)));
- assertThat(response3.getStatus(), is(equalTo(200)));
- assertThat(MESSAGE_CALL_COUNTER.get(), is(3));
- }
-
- @Ignore
- @Test
- public void app_uninstalled() throws Exception {
- ServletTester tester = getServletTester();
- HttpTester.Request request = prepareRequest();
-
- request.setContent("{\n" +
- " \"token\": \"XXYYZZ\",\n" +
- " \"team_id\": \"TXXXXXXXX\",\n" +
- " \"api_app_id\": \"AXXXXXXXXX\",\n" +
- " \"event\": {\n" +
- " \"type\": \"app_uninstalled\"\n" +
- " },\n" +
- " \"type\": \"event_callback\",\n" +
- " \"event_id\": \"EvXXXXXXXX\",\n" +
- " \"event_time\": 1234567890\n" +
- "}");
-
- HttpTester.Response response = HttpTester.parseResponse(tester.getResponses(request.generate()));
-
- // wait for the async execution
- Thread.sleep(200L);
-
- assertThat(response.getStatus(), is(equalTo(200)));
- assertThat(APP_UNINSTALLED_CALL_COUNTER.get(), is(1));
- }
-
- @Ignore
- @Test
- public void goodbye() throws Exception {
- ServletTester tester = getServletTester();
- HttpTester.Request request = prepareRequest();
-
- request.setContent("{\n" +
- " \"token\": \"XXYYZZ\",\n" +
- " \"team_id\": \"TXXXXXXXX\",\n" +
- " \"api_app_id\": \"AXXXXXXXXX\",\n" +
- " \"event\": {\n" +
- " \"type\": \"goodbye\"\n" +
- " },\n" +
- " \"type\": \"event_callback\",\n" +
- " \"event_id\": \"EvXXXXXXXX\",\n" +
- " \"event_time\": 1234567890\n" +
- "}");
-
- HttpTester.Response response = HttpTester.parseResponse(tester.getResponses(request.generate()));
-
- // wait for the async execution
- Thread.sleep(200L);
-
- assertThat(response.getStatus(), is(equalTo(200)));
- assertThat(GOODBYE_CALL_COUNTER.get(), is(1));
- }
-
- // -------------------------------------------------------------------
-
- private static ServletTester getServletTester() throws Exception {
- ServletTester tester = new ServletTester();
- tester.addServlet(SampleServlet.class, "/");
- tester.start();
- return tester;
- }
-
- private static HttpTester.Request prepareRequest() {
- HttpTester.Request request = HttpTester.newRequest();
- request.setMethod("POST");
- request.setHeader("Host", "tester"); // should be "tester"
- request.setURI("/");
- request.setVersion("HTTP/1.1");
- request.setHeader("content-type", "application/json");
- request.setHeader("Connection", "close");
- return request;
- }
-
-}
diff --git a/slack-app-backend/src/test/java/test_locally/app_backend/events/servlet/EventsApiTest.java b/slack-app-backend/src/test/java/test_locally/app_backend/events/servlet/EventsApiTest.java
deleted file mode 100644
index 60fdb45a8..000000000
--- a/slack-app-backend/src/test/java/test_locally/app_backend/events/servlet/EventsApiTest.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package test_locally.app_backend.events.servlet;
-
-import com.slack.api.app_backend.events.EventsDispatcher;
-import com.slack.api.app_backend.events.handler.AppUninstalledHandler;
-import com.slack.api.app_backend.events.handler.GoodbyeHandler;
-import com.slack.api.app_backend.events.handler.MessageHandler;
-import com.slack.api.app_backend.events.payload.AppUninstalledPayload;
-import com.slack.api.app_backend.events.payload.GoodbyePayload;
-import com.slack.api.app_backend.events.payload.MessagePayload;
-import com.slack.api.app_backend.events.payload.UrlVerificationPayload;
-import com.slack.api.app_backend.events.servlet.SlackEventsApiServlet;
-import com.slack.api.util.json.GsonFactory;
-import org.eclipse.jetty.http.HttpTester;
-import org.eclipse.jetty.servlet.ServletTester;
-import org.junit.Before;
-import org.junit.Test;
-import util.ServletTestUtils;
-
-import javax.servlet.annotation.WebServlet;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotNull;
-
-public class EventsApiTest {
-
- private static final String signingSecret = "secret";
-
- public static AtomicInteger messageCalls = new AtomicInteger(0);
- public static MessageHandler message = new MessageHandler() {
- @Override
- public void handle(MessagePayload payload) {
- messageCalls.incrementAndGet();
- }
- };
-
- public static AtomicInteger appUninstallsCalls = new AtomicInteger(0);
- public static AppUninstalledHandler allUninstall = new AppUninstalledHandler() {
- @Override
- public void handle(AppUninstalledPayload event) {
- appUninstallsCalls.incrementAndGet();
- }
- };
-
- public static AtomicInteger goodbyeCalls = new AtomicInteger(0);
- public static GoodbyeHandler goodbye = new GoodbyeHandler() {
- @Override
- public void handle(GoodbyePayload payload) {
- goodbyeCalls.incrementAndGet();
- }
- };
-
- @Before
- public void setup() {
- messageCalls.set(0);
- appUninstallsCalls.set(0);
- goodbyeCalls.set(0);
- }
-
- SlackWebApp webApp = new SlackWebApp();
-
- @WebServlet(urlPatterns = "/")
- public static class SlackWebApp extends SlackEventsApiServlet {
-
- @Override
- protected String getSlackSigningSecret() {
- return signingSecret;
- }
-
- @Override
- protected void setupDispatcher(EventsDispatcher dispatcher) {
- assertNotNull(getSlackSigningSecret());
- dispatcher.register(message);
- dispatcher.register(allUninstall);
- dispatcher.register(goodbye);
- }
- }
-
- @Test
- public void destroy() {
- SlackWebApp app = new SlackWebApp();
- app.destroy();
- }
-
- @Test
- public void urlVerification() throws Exception {
- ServletTester tester = ServletTestUtils.getServletTester(webApp);
-
- UrlVerificationPayload payload = new UrlVerificationPayload();
- payload.setChallenge("cha-xxxxxx");
- payload.setToken("token-xxxx");
-
- HttpTester.Request request = ServletTestUtils.prepareRequest(signingSecret, GsonFactory.createSnakeCase().toJson(payload));
- HttpTester.Response response = HttpTester.parseResponse(tester.getResponses(request.generate()));
-
- assertThat(response.getContent(), is(equalTo("cha-xxxxxx")));
- assertThat(response.getStatus(), is(equalTo(200)));
- assertThat(response.get("Content-Type"), is(startsWith("text/plain")));
- }
-
- @Test
- public void message() throws Exception {
- ServletTester tester = ServletTestUtils.getServletTester(webApp);
- HttpTester.Request request = ServletTestUtils.prepareRequest(signingSecret, "{\n" +
- " \"token\": \"XXYYZZ\",\n" +
- " \"team_id\": \"TXXXXXXXX\",\n" +
- " \"api_app_id\": \"AXXXXXXXXX\",\n" +
- " \"event\": {\n" +
- " \"type\": \"message\",\n" +
- " \"channel\": \"C2147483705\",\n" +
- " \"user\": \"U2147483697\",\n" +
- " \"text\": \"Hello world\",\n" +
- " \"ts\": \"1355517523.000005\"\n" +
- "} ,\n" +
- " \"type\": \"event_callback\",\n" +
- " \"event_id\": \"EvXXXXXXXX\",\n" +
- " \"event_time\": 1234567890\n" +
- "}");
-
- HttpTester.Response response1 = HttpTester.parseResponse(tester.getResponses(request.generate()));
- HttpTester.Response response2 = HttpTester.parseResponse(tester.getResponses(request.generate()));
- HttpTester.Response response3 = HttpTester.parseResponse(tester.getResponses(request.generate()));
-
- // wait for the async execution
- Thread.sleep(1000L);
-
- assertThat(response1.getStatus(), is(equalTo(200)));
- assertThat(response2.getStatus(), is(equalTo(200)));
- assertThat(response3.getStatus(), is(equalTo(200)));
- assertThat(messageCalls.get(), is(3));
- }
-
- @Test
- public void app_uninstalled() throws Exception {
- ServletTester tester = ServletTestUtils.getServletTester(webApp);
- HttpTester.Request request = ServletTestUtils.prepareRequest(signingSecret, "{\n" +
- " \"token\": \"XXYYZZ\",\n" +
- " \"team_id\": \"TXXXXXXXX\",\n" +
- " \"api_app_id\": \"AXXXXXXXXX\",\n" +
- " \"event\": {\n" +
- " \"type\": \"app_uninstalled\"\n" +
- " },\n" +
- " \"type\": \"event_callback\",\n" +
- " \"event_id\": \"EvXXXXXXXX\",\n" +
- " \"event_time\": 1234567890\n" +
- "}");
-
- HttpTester.Response response = HttpTester.parseResponse(tester.getResponses(request.generate()));
-
- // wait for the async execution
- Thread.sleep(1000L);
-
- assertThat(response.getStatus(), is(equalTo(200)));
- assertThat(appUninstallsCalls.get(), is(1));
- }
-
- @Test
- public void goodbye() throws Exception {
- ServletTester tester = ServletTestUtils.getServletTester(webApp);
- HttpTester.Request request = ServletTestUtils.prepareRequest(signingSecret, "{\n" +
- " \"token\": \"XXYYZZ\",\n" +
- " \"team_id\": \"TXXXXXXXX\",\n" +
- " \"api_app_id\": \"AXXXXXXXXX\",\n" +
- " \"event\": {\n" +
- " \"type\": \"goodbye\"\n" +
- " },\n" +
- " \"type\": \"event_callback\",\n" +
- " \"event_id\": \"EvXXXXXXXX\",\n" +
- " \"event_time\": 1234567890\n" +
- "}");
-
- HttpTester.Response response = HttpTester.parseResponse(tester.getResponses(request.generate()));
-
- // wait for the async execution
- Thread.sleep(1000L);
-
- assertThat(response.getStatus(), is(equalTo(200)));
- assertThat(goodbyeCalls.get(), is(1));
- }
-
- @Test
- public void invalid() throws Exception {
- ServletTester tester = ServletTestUtils.getServletTester(webApp);
- HttpTester.Request request = ServletTestUtils.prepareRequest("invalid", "{\n" +
- " \"token\": \"XXYYZZ\",\n" +
- " \"team_id\": \"TXXXXXXXX\",\n" +
- " \"api_app_id\": \"AXXXXXXXXX\",\n" +
- " \"event\": {\n" +
- " \"type\": \"goodbye\"\n" +
- " },\n" +
- " \"type\": \"event_callback\",\n" +
- " \"event_id\": \"EvXXXXXXXX\",\n" +
- " \"event_time\": 1234567890\n" +
- "}");
-
- HttpTester.Response response = HttpTester.parseResponse(tester.getResponses(request.generate()));
-
- // wait for the async execution
- Thread.sleep(1000L);
-
- assertThat(response.getStatus(), is(equalTo(401)));
- assertThat(goodbyeCalls.get(), is(0));
- }
-}
diff --git a/slack-app-backend/src/test/java/test_locally/app_backend/events/servlet/SlackSignatureVerifierTest.java b/slack-app-backend/src/test/java/test_locally/app_backend/events/servlet/SlackSignatureVerifierTest.java
deleted file mode 100644
index a6c7b3762..000000000
--- a/slack-app-backend/src/test/java/test_locally/app_backend/events/servlet/SlackSignatureVerifierTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package test_locally.app_backend.events.servlet;
-
-import com.slack.api.app_backend.SlackSignature;
-import com.slack.api.app_backend.events.servlet.SlackSignatureVerifier;
-import org.junit.Test;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.Enumeration;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-// https://api.slack.com/docs/verifying-requests-from-slack
-public class SlackSignatureVerifierTest {
-
- @Test
- public void validServletRequest() {
- SlackSignature.Generator generator = new SlackSignature.Generator("8f742231b10e8888abcd99yyyzzz85a5");
- Long currentTimeInMilliSeconds = System.currentTimeMillis();
- String requestTimestamp = Long.toString(currentTimeInMilliSeconds / 1000);
- String requestBody = "token=xyzz0WbapA4vBCDEFasx0q6G&team_id=T1DC2JH3J&team_domain=testteamnow&channel_id=G8PSS9T3V&channel_name=foobar&user_id=U2CERLKJA&user_name=roadrunner&command=%2Fwebhook-collect&text=&response_url=https%3A%2F%2Fhooks.slack.com%2Fcommands%2FT1DC2JH3J%2F397700885554%2F96rGlfmibIGlgcZRskXaIFfN&trigger_id=398738663015.47445629121.803a0bc887a14d10d2c447fce8b6703c";
-
- String validSignature = generator.generate(requestTimestamp, requestBody);
- HttpServletRequest httpServletRequest = mock(HttpServletRequest.class);
- when(httpServletRequest.getHeaderNames()).thenReturn(mock(Enumeration.class));
- when(httpServletRequest.getHeader(SlackSignature.HeaderNames.X_SLACK_REQUEST_TIMESTAMP)).thenReturn(requestTimestamp);
- when(httpServletRequest.getHeader(SlackSignature.HeaderNames.X_SLACK_SIGNATURE)).thenReturn(validSignature);
-
- SlackSignatureVerifier verifier = new SlackSignatureVerifier(generator);
- assertThat(verifier.isValid(httpServletRequest, requestBody), is(true));
- }
-
- @Test
- public void inValidServletRequest() {
- SlackSignature.Generator generator = new SlackSignature.Generator("8f742231b10e8888abcd99yyyzzz85a5");
- String timestamp = "1531420618";
- String requestBody = "token=xyzz0WbapA4vBCDEFasx0q6G&team_id=T1DC2JH3J&team_domain=testteamnow&channel_id=G8PSS9T3V&channel_name=foobar&user_id=U2CERLKJA&user_name=roadrunner&command=%2Fwebhook-collect&text=&response_url=https%3A%2F%2Fhooks.slack.com%2Fcommands%2FT1DC2JH3J%2F397700885554%2F96rGlfmibIGlgcZRskXaIFfN&trigger_id=398738663015.47445629121.803a0bc887a14d10d2c447fce8b6703c";
- SlackSignatureVerifier verifier = new SlackSignatureVerifier(generator);
- String validSignature = "v0=a2114d57b48eac39b9ad189dd8316235a7b4a8d21a10bd27519666489c69b503";
- HttpServletRequest httpServletRequest = mock(HttpServletRequest.class);
- when(httpServletRequest.getHeaderNames()).thenReturn(mock(Enumeration.class));
- when(httpServletRequest.getHeader(SlackSignature.HeaderNames.X_SLACK_REQUEST_TIMESTAMP)).thenReturn(timestamp);
- when(httpServletRequest.getHeader(SlackSignature.HeaderNames.X_SLACK_SIGNATURE)).thenReturn(validSignature);
- assertThat(verifier.isValid(httpServletRequest, requestBody), is(false));
- }
-
-}
diff --git a/slack-app-backend/src/test/java/test_with_remote_apis/commands/SlashCommandApiBackend.java b/slack-app-backend/src/test/java/test_with_remote_apis/commands/SlashCommandApiBackend.java
deleted file mode 100644
index edeea7bd1..000000000
--- a/slack-app-backend/src/test/java/test_with_remote_apis/commands/SlashCommandApiBackend.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package test_with_remote_apis.commands;
-
-import com.slack.api.app_backend.SlackSignature;
-import com.slack.api.app_backend.events.servlet.SlackSignatureVerifier;
-import com.slack.api.app_backend.slash_commands.SlashCommandPayloadParser;
-import com.slack.api.app_backend.slash_commands.payload.SlashCommandPayload;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.servlet.ServletHandler;
-
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.stream.Collectors;
-
-public class SlashCommandApiBackend {
-
- @Slf4j
- @WebServlet
- public static class SlackEventsServlet extends HttpServlet {
-
- // Configure this env variable to run this servlet
- private final String slackSigningSecret = System.getenv("SLACK_TEST_SIGNING_SECRET");
-
- private final SlackSignature.Generator signatureGenerator = new SlackSignature.Generator(slackSigningSecret);
- private final SlackSignatureVerifier signatureVerifier = new SlackSignatureVerifier(signatureGenerator);
- private final SlashCommandPayloadParser parser = new SlashCommandPayloadParser();
-
- protected String doReadRequestBodyAsString(HttpServletRequest req) throws IOException {
- return req.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
- }
-
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
- String requestBody = doReadRequestBodyAsString(req);
- log.info("request - {}", requestBody);
- boolean validSignature = this.signatureVerifier.isValid(req, requestBody);
- if (!validSignature) { // invalid signature
- if (log.isDebugEnabled()) {
- String signature = req.getHeader(SlackSignature.HeaderNames.X_SLACK_SIGNATURE);
- log.debug("An invalid X-Slack-Signature detected - {}", signature);
- }
- resp.setStatus(401);
- return;
- }
-
- SlashCommandPayload payload = parser.parse(requestBody);
- log.info("payload - {}", payload);
-
- resp.setStatus(200);
- resp.setHeader("Content-Type", "text/plain");
- if (payload.getText() != null) {
- resp.getWriter().write(payload.getText());
- }
- }
- }
-
- // https://www.eclipse.org/jetty/documentation/current/embedding-jetty.html
-
- public static void main(String[] args) throws Exception {
- Server server = new Server(3000);
- ServletHandler handler = new ServletHandler();
- server.setHandler(handler);
- handler.addServletWithMapping(SlackEventsServlet.class, "/slack/events");
- server.start();
- server.join();
- }
-}
-
diff --git a/slack-app-backend/src/test/java/test_with_remote_apis/events_subscription/SimpleEventsApiBackend.java b/slack-app-backend/src/test/java/test_with_remote_apis/events_subscription/SimpleEventsApiBackend.java
deleted file mode 100644
index b6cafd5c5..000000000
--- a/slack-app-backend/src/test/java/test_with_remote_apis/events_subscription/SimpleEventsApiBackend.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package test_with_remote_apis.events_subscription;
-
-import com.slack.api.app_backend.events.EventsDispatcher;
-import com.slack.api.app_backend.events.handler.MessageHandler;
-import com.slack.api.app_backend.events.payload.MessagePayload;
-import com.slack.api.app_backend.events.servlet.SlackEventsApiServlet;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.servlet.ServletHandler;
-
-import javax.servlet.annotation.WebServlet;
-
-public class SimpleEventsApiBackend {
-
- @Slf4j
- @WebServlet
- public static class SlackEventsServlet extends SlackEventsApiServlet {
- @Override
- protected void setupDispatcher(EventsDispatcher dispatcher) {
- dispatcher.register(new MessageHandler() {
- @Override
- public void handle(MessagePayload payload) {
- log.info("payload: {}", payload);
- }
- });
- }
- }
-
- // https://www.eclipse.org/jetty/documentation/current/embedding-jetty.html
-
- public static void main(String[] args) throws Exception {
- Server server = new Server(3000);
- ServletHandler handler = new ServletHandler();
- server.setHandler(handler);
- handler.addServletWithMapping(SlackEventsServlet.class, "/slack/events");
- server.start();
- server.join();
- }
-}
-
diff --git a/slack-app-backend/src/test/java/test_with_remote_apis/interactive_messages/BlockKitBackend.java b/slack-app-backend/src/test/java/test_with_remote_apis/interactive_messages/BlockKitBackend.java
deleted file mode 100644
index 4bc52f47b..000000000
--- a/slack-app-backend/src/test/java/test_with_remote_apis/interactive_messages/BlockKitBackend.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package test_with_remote_apis.interactive_messages;
-
-import com.google.gson.Gson;
-import com.slack.api.app_backend.SlackSignature;
-import com.slack.api.app_backend.events.servlet.SlackSignatureVerifier;
-import com.slack.api.app_backend.interactive_components.payload.BlockActionPayload;
-import com.slack.api.app_backend.interactive_components.response.ActionResponse;
-import com.slack.api.app_backend.interactive_components.response.BlockSuggestionResponse;
-import com.slack.api.app_backend.interactive_components.response.Option;
-import com.slack.api.app_backend.slash_commands.SlashCommandPayloadParser;
-import com.slack.api.app_backend.slash_commands.payload.SlashCommandPayload;
-import com.slack.api.app_backend.util.JsonPayloadExtractor;
-import com.slack.api.app_backend.util.JsonPayloadTypeDetector;
-import com.slack.api.model.block.SectionBlock;
-import com.slack.api.model.block.composition.MarkdownTextObject;
-import com.slack.api.model.block.composition.PlainTextObject;
-import com.slack.api.model.block.element.ExternalSelectElement;
-import com.slack.api.util.json.GsonFactory;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.servlet.ServletHandler;
-
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.stream.Collectors;
-
-public class BlockKitBackend {
-
- @Slf4j
- @WebServlet
- public static class SlackEventsServlet extends HttpServlet {
-
- // Configure these two env variables to run this servlet
- private final String slackSigningSecret = System.getenv("SLACK_TEST_SIGNING_SECRET");
-
- private final SlackSignature.Generator signatureGenerator = new SlackSignature.Generator(slackSigningSecret);
- private final SlackSignatureVerifier signatureVerifier = new SlackSignatureVerifier(signatureGenerator);
-
- private final SlashCommandPayloadParser commandPayloadParser = new SlashCommandPayloadParser();
-
- private final Gson gson = GsonFactory.createSnakeCase();
- private final JsonPayloadExtractor payloadExtractor = new JsonPayloadExtractor();
- private final JsonPayloadTypeDetector payloadTypeDetector = new JsonPayloadTypeDetector();
-
- protected String doReadRequestBodyAsString(HttpServletRequest httpReq) throws IOException {
- return httpReq.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
- }
-
- protected void doPost(HttpServletRequest httpReq, HttpServletResponse httpResp) throws IOException {
- // any command to invoke
- String requestBody = doReadRequestBodyAsString(httpReq);
- log.info("requestBody - {}", requestBody);
-
- boolean validSignature = this.signatureVerifier.isValid(httpReq, requestBody);
- if (!validSignature) { // invalid signature
- if (log.isDebugEnabled()) {
- String signature = httpReq.getHeader(SlackSignature.HeaderNames.X_SLACK_SIGNATURE);
- log.debug("An invalid X-Slack-Signature detected - {}", signature);
- }
- httpResp.setStatus(401);
- return;
- }
-
- if (requestBody.startsWith("payload=")) {
- String json = payloadExtractor.extractIfExists(requestBody);
- String payloadType = payloadTypeDetector.detectType(json);
-
- if (payloadType.equals("block_actions")) {
- // extracts trigger_id for views.open
- BlockActionPayload payload = gson.fromJson(json, BlockActionPayload.class);
- log.info("block_actions - {}", payload);
- } else if (payloadType.equals("block_suggestion")) {
- log.info("block_suggestion - {}", json);
-
- httpResp.setStatus(200);
- httpResp.setHeader("Content-Type", "application/json");
-
- BlockSuggestionResponse response = BlockSuggestionResponse.builder()
- .options(Arrays.asList(
- Option.builder().text(PlainTextObject.builder().text("label1").build()).value("v1").build(),
- Option.builder().text(MarkdownTextObject.builder().text("label2").build()).value("v2").build(),
- Option.builder().text(PlainTextObject.builder().text("label3").build()).value("v3").build()
- ))
- .build();
- String responseBody = gson.toJson(response);
- log.info("response - {}", responseBody);
- httpResp.getWriter().write(responseBody);
-
- return;
-
- } else {
- log.info("Unexpected payload - {}", payloadType);
- }
- } else {
- SlashCommandPayload payload = commandPayloadParser.parse(requestBody);
- log.info("command - {}", payload);
-// Payload webhookPayload = Payload.builder()
-// .blocks(Arrays.asList(
-// SectionBlock.builder()
-// .text(PlainTextObject.builder().text("Hi").build())
-// .accessory(ExternalSelectElement.builder().actionId("external_select_id").build())
-// .build()))
-// .build();
-// WebhookResponse response = slack.send(payload.getResponseUrl(), webhookPayload);
-// log.info("response - {}", response);
- }
-
- // ack
- httpResp.setStatus(200);
- httpResp.setHeader("Content-Type", "application/json");
-
- ActionResponse response = new ActionResponse();
- response.setResponseType("ephemeral");
- response.setBlocks(Arrays.asList(SectionBlock.builder()
- .text(PlainTextObject.builder().text("Hi").build())
- .accessory(ExternalSelectElement.builder().actionId("external_select_id").build()).build()));
- String responseBody = gson.toJson(response);
- httpResp.getWriter().write(responseBody);
- }
- }
-
- // https://www.eclipse.org/jetty/documentation/current/embedding-jetty.html
-
- public static void main(String[] args) throws Exception {
- Server server = new Server(3000);
- ServletHandler handler = new ServletHandler();
- server.setHandler(handler);
- handler.addServletWithMapping(SlackEventsServlet.class, "/slack/events");
- server.start();
- server.join();
- }
-}
-
diff --git a/slack-app-backend/src/test/java/test_with_remote_apis/views/ViewsApiBackend.java b/slack-app-backend/src/test/java/test_with_remote_apis/views/ViewsApiBackend.java
deleted file mode 100644
index 92bf6d3cd..000000000
--- a/slack-app-backend/src/test/java/test_with_remote_apis/views/ViewsApiBackend.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package test_with_remote_apis.views;
-
-import com.google.gson.Gson;
-import com.slack.api.Slack;
-import com.slack.api.app_backend.SlackSignature;
-import com.slack.api.app_backend.events.servlet.SlackSignatureVerifier;
-import com.slack.api.app_backend.interactive_components.payload.BlockActionPayload;
-import com.slack.api.app_backend.slash_commands.SlashCommandPayloadParser;
-import com.slack.api.app_backend.slash_commands.payload.SlashCommandPayload;
-import com.slack.api.app_backend.util.JsonPayloadExtractor;
-import com.slack.api.app_backend.util.JsonPayloadTypeDetector;
-import com.slack.api.app_backend.views.payload.ViewClosedPayload;
-import com.slack.api.app_backend.views.payload.ViewSubmissionPayload;
-import com.slack.api.methods.SlackApiException;
-import com.slack.api.methods.response.views.ViewsOpenResponse;
-import com.slack.api.methods.response.views.ViewsUpdateResponse;
-import com.slack.api.model.block.InputBlock;
-import com.slack.api.model.block.LayoutBlock;
-import com.slack.api.model.block.SectionBlock;
-import com.slack.api.model.block.composition.PlainTextObject;
-import com.slack.api.model.block.element.ButtonElement;
-import com.slack.api.model.block.element.PlainTextInputElement;
-import com.slack.api.model.view.View;
-import com.slack.api.model.view.ViewSubmit;
-import com.slack.api.model.view.ViewTitle;
-import com.slack.api.util.json.GsonFactory;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.servlet.ServletHandler;
-
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-public class ViewsApiBackend {
-
- @Slf4j
- @WebServlet
- public static class SlackEventsServlet extends HttpServlet {
-
- // Configure these two env variables to run this servlet
- private final String slackSigningSecret = System.getenv("SLACK_TEST_SIGNING_SECRET");
- private final String token = System.getenv("SLACK_BOT_USER_TEST_OAUTH_ACCESS_TOKEN");
-
- private final SlackSignature.Generator signatureGenerator = new SlackSignature.Generator(slackSigningSecret);
- private final SlackSignatureVerifier signatureVerifier = new SlackSignatureVerifier(signatureGenerator);
-
- private final SlashCommandPayloadParser commandPayloadParser = new SlashCommandPayloadParser();
-
- private final Gson gson = GsonFactory.createSnakeCase();
- private final JsonPayloadExtractor payloadExtractor = new JsonPayloadExtractor();
- private final JsonPayloadTypeDetector payloadTypeDetector = new JsonPayloadTypeDetector();
-
- private final Slack slack = Slack.getInstance();
-
- protected String doReadRequestBodyAsString(HttpServletRequest httpReq) throws IOException {
- return httpReq.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
- }
-
- protected void doPost(HttpServletRequest httpReq, HttpServletResponse httpResp) throws IOException {
- // any command to invoke
- String requestBody = doReadRequestBodyAsString(httpReq);
- log.info("requestBody - {}", requestBody);
-
- boolean validSignature = this.signatureVerifier.isValid(httpReq, requestBody);
- if (!validSignature) { // invalid signature
- if (log.isDebugEnabled()) {
- String signature = httpReq.getHeader(SlackSignature.HeaderNames.X_SLACK_SIGNATURE);
- log.debug("An invalid X-Slack-Signature detected - {}", signature);
- }
- httpResp.setStatus(401);
- return;
- }
-
- String triggerId;
- if (requestBody.startsWith("payload=")) {
- String json = payloadExtractor.extractIfExists(requestBody);
- String payloadType = payloadTypeDetector.detectType(json);
-
- if (payloadType.equals("view_submission")) {
- // just receives view_submission requests
- ViewSubmissionPayload payload = gson.fromJson(json, ViewSubmissionPayload.class);
- log.info("view_submission - {}", payload);
- httpResp.setStatus(200);
- return;
-
- } else if (payloadType.equals("view_closed")) {
- // just receives view_closed requests when notifyOnClose is true
- ViewClosedPayload payload = gson.fromJson(json, ViewClosedPayload.class);
- log.info("view_closed - {}", payload);
- httpResp.setStatus(200);
- return;
-
- } else if (payloadType.equals("block_actions")) {
- // extracts trigger_id for views.open
- BlockActionPayload payload = gson.fromJson(json, BlockActionPayload.class);
- if (payload.getView() != null) {
- try {
- View newView = View.builder()
- .type("modal")
- .callbackId("callback_id2")
- .title(ViewTitle.builder().type("plain_text").text("Title2").build())
- .submit(ViewSubmit.builder().type("plain_text").text("Submit2").build())
- .blocks(Arrays.asList(InputBlock.builder()
- .blockId("text_input")
- .label(PlainTextObject.builder().text("text").build())
- .element(PlainTextInputElement.builder().actionId("single").multiline(true).build())
- .build()))
- .build();
- ViewsUpdateResponse apiResponse = slack.methods(token).viewsUpdate(req -> req
- .viewId(payload.getView().getId())
- .view(newView));
- log.info("views.update - {}", apiResponse);
- } catch (SlackApiException e) {
- log.error(e.getResponseBody(), e);
- }
- return;
- } else {
- triggerId = payload.getTriggerId();
- }
- } else {
- log.info("Unexpected payload - {}", payloadType);
- return;
- }
- } else {
- // extracts trigger_id for views.open
- SlashCommandPayload payload = commandPayloadParser.parse(requestBody);
- triggerId = payload.getTriggerId();
- }
-
- List blocks = new ArrayList<>();
- blocks.add(InputBlock.builder()
- .blockId("text_input")
- .label(PlainTextObject.builder().text("text").build())
- .element(PlainTextInputElement.builder().actionId("single").multiline(true).build())
- .build());
- blocks.add(SectionBlock.builder()
- .text(PlainTextObject.builder().text("button").build())
- .accessory(ButtonElement.builder().text(PlainTextObject.builder().text("submit").build()).actionId("click").value("1").build())
- .build());
-
- View view = View.builder()
- .type("modal")
- .callbackId("callback_id")
- .title(ViewTitle.builder().type("plain_text").text("Title").build())
- .submit(ViewSubmit.builder().type("plain_text").text("Submit").build())
- .notifyOnClose(true)
- .blocks(blocks).build();
- log.info(triggerId);
- log.info("view: {}", view);
- try {
- ViewsOpenResponse apiResponse = slack.methods(token).viewsOpen(req -> req
- .view(view)
- .triggerId(triggerId));
- log.info("views.open - {}", apiResponse);
-
- if (!apiResponse.isOk()) {
- httpResp.setStatus(500);
- httpResp.getWriter().write(apiResponse.getError());
- return;
- }
- } catch (SlackApiException e) {
- httpResp.setStatus(500);
- httpResp.getWriter().write(e.getMessage());
- return;
- }
-
- // ack
- httpResp.setStatus(200);
- }
- }
-
- // https://www.eclipse.org/jetty/documentation/current/embedding-jetty.html
-
- public static void main(String[] args) throws Exception {
- Server server = new Server(3000);
- ServletHandler handler = new ServletHandler();
- server.setHandler(handler);
- handler.addServletWithMapping(SlackEventsServlet.class, "/slack/events");
- server.start();
- server.join();
- }
-}
-