diff --git a/README.md b/README.md
index fd7caee..dbdbee5 100644
--- a/README.md
+++ b/README.md
@@ -29,3 +29,19 @@ $ mvn jetty:run
Navigate to:
http://localhost:8080/
+
+API demos
+=========
+
+The home page links to a set of demos exercising the Castle SDK directly:
+
+* **Lists & list items API** (`/lists-demo`) — creates a list, adds an item,
+ queries the items, lists all lists and deletes the list.
+* **Events API** (`/events-demo`) — fetches the event schema and queries events.
+* **Privacy data request** (`/privacy-demo?userId=...`) — requests the data
+ Castle holds for a user.
+* **Received webhooks** (`/webhooks`) — `POST` a Castle webhook with a valid
+ `X-Castle-Signature` header to have it verified against the raw request body
+ and listed on the page.
+
+These demos require `castle-java` 2.2.0.
diff --git a/pom.xml b/pom.xml
index 617bc1a..7f64fc2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
Error: " + e.getMessage() + ""); + } + + out.println(""); + } +} diff --git a/src/main/java/io/castle/example/ListsDemoServlet.java b/src/main/java/io/castle/example/ListsDemoServlet.java new file mode 100644 index 0000000..d5b7c73 --- /dev/null +++ b/src/main/java/io/castle/example/ListsDemoServlet.java @@ -0,0 +1,70 @@ +package io.castle.example; + +import com.google.common.collect.ImmutableMap; +import io.castle.client.Castle; +import io.castle.client.api.CastleApi; +import io.castle.client.model.CastleResponse; + +import javax.servlet.ServletException; +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.io.PrintWriter; + +/** + * Demonstrates the Lists and List items API end to end: + * create a list, add an item, query the items, list all lists and delete the list. + */ +@WebServlet("/lists-demo") +public class ListsDemoServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + resp.setContentType("text/html; charset=utf-8"); + PrintWriter out = resp.getWriter(); + out.println("
Error: " + e.getMessage() + ""); + } + + out.println(""); + } + + static void render(PrintWriter out, String label, CastleResponse response) { + out.println("
" + response.json() + ""); + } +} diff --git a/src/main/java/io/castle/example/PrivacyDemoServlet.java b/src/main/java/io/castle/example/PrivacyDemoServlet.java new file mode 100644 index 0000000..3d9cbcc --- /dev/null +++ b/src/main/java/io/castle/example/PrivacyDemoServlet.java @@ -0,0 +1,47 @@ +package io.castle.example; + +import com.google.common.collect.ImmutableMap; +import io.castle.client.Castle; +import io.castle.client.api.CastleApi; +import io.castle.client.model.CastleResponse; + +import javax.servlet.ServletException; +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.io.PrintWriter; + +/** + * Demonstrates the privacy data-request API. + */ +@WebServlet("/privacy-demo") +public class PrivacyDemoServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + resp.setContentType("text/html; charset=utf-8"); + PrintWriter out = resp.getWriter(); + out.println("
Error: " + e.getMessage() + ""); + } + + out.println(""); + } +} diff --git a/src/main/java/io/castle/example/WebhookServlet.java b/src/main/java/io/castle/example/WebhookServlet.java new file mode 100644 index 0000000..c8de831 --- /dev/null +++ b/src/main/java/io/castle/example/WebhookServlet.java @@ -0,0 +1,70 @@ +package io.castle.example; + +import io.castle.client.Castle; + +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Receives Castle webhooks and verifies the {@code X-Castle-Signature} header + * against the raw request body before trusting the payload. + */ +@WebServlet("/webhooks") +public class WebhookServlet extends HttpServlet { + + private static final List
POST a Castle webhook to /webhooks with a valid "
+ + "X-Castle-Signature header to see it verified and listed here.
No verified webhooks received yet.
"); + } + for (String payload : RECEIVED) { + out.println("" + payload + ""); + } + out.println(""); + } + + private byte[] readBody(HttpServletRequest req) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + ServletInputStream in = req.getInputStream(); + byte[] chunk = new byte[4096]; + int read; + while ((read = in.read(chunk)) != -1) { + buffer.write(chunk, 0, read); + } + return buffer.toByteArray(); + } +} diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp index 6e7f89f..fb91522 100644 --- a/src/main/webapp/index.jsp +++ b/src/main/webapp/index.jsp @@ -31,6 +31,15 @@ +