Skip to content

Commit

Permalink
KnownUser version 3.7
Browse files Browse the repository at this point in the history
  • Loading branch information
reaz committed Dec 3, 2021
1 parent 375cf52 commit 5815bff
Show file tree
Hide file tree
Showing 18 changed files with 642 additions and 283 deletions.
152 changes: 138 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ You can install this SDK in a couple of ways:
<dependency>
<groupId>com.queue-it.connector</groupId>
<artifactId>connector</artifactId>
<version>3.6.2</version>
<version>3.7.0</version>
</dependency>
```

Expand All @@ -23,17 +23,17 @@ The KnownUser validation must be done on all requests except requests for static
This example is using the *[IntegrationConfigProvider](https://github.com/queueit/KnownUser.V3.JAVA/blob/master/Documentation/IntegrationConfigProvider.java)* to download the queue configuration. The IntegrationConfigProvider.java file is an example of how the download and caching of the configuration can be done. This is just an example, but if you make your own downloader, please cache the result for 5 - 10 minutes to limit number of download requests. **You should NEVER download the configuration as part of the request handling**.

The following method is all that is needed to validate that a user has been through the queue:
```
private void doValidation(HttpServletRequest request, HttpServletResponse response) {
```java
private void doValidation(KnownUserRequestWrapper request, HttpServletResponse response) {
try {
String customerId = "Your Queue-it customer ID";
String secretKey = "Your 72 char secrete key as specified in Go Queue-it self-service platform";
String apiKey = "Your api-key as specified in Go Queue-it self-service platform";
String apiKey = "Your api-key as specified in Go Queue-it self-service platform";

String queueitToken = request.getParameter(KnownUser.QueueITTokenKey);
String pureUrl = getPureUrl(request);
// The pureUrl is used to match Triggers and as the Target url (where to return the users to)

// The pureUrl is used to match Triggers and as the Target url (where to return the users to)
// It is therefor important that the pureUrl is exactly the url of the users browsers. So if your webserver is
// e.g. behind a load balancer that modifies the host name or port, reformat the pureUrl before proceeding
CustomerIntegration integrationConfig = IntegrationConfigProvider.getCachedIntegrationConfig(customerId, apiKey);
Expand All @@ -51,6 +51,7 @@ The following method is all that is needed to validate that a user has been thro
if (validationResult.isAjaxResult) {
//In case of ajax call send the user to the queue by sending a custom queue-it header and redirecting user to queue from javascript
response.setHeader(validationResult.getAjaxQueueRedirectHeaderKey(), validationResult.getAjaxRedirectUrl());
response.setHeader("Access-Control-Expose-Headers", validationResult.getAjaxQueueRedirectHeaderKey());
} else {
//Send the user to the queue - either becuase hash was missing or becuase is was invalid
response.sendRedirect(validationResult.getRedirectUrl());
Expand All @@ -60,16 +61,16 @@ The following method is all that is needed to validate that a user has been thro
} else {
String queryString = request.getQueryString();
//Request can continue - we remove queueittoken form querystring parameter to avoid sharing of user specific token
if (queryString != null && queryString.contains(KnownUser.QueueITTokenKey) && "Queue".equals(validationResult.getActionType()) ) {
response.sendRedirect(pureUrl);
response.getOutputStream().flush();
response.getOutputStream().close();
if (queryString != null && queryString.contains(KnownUser.QueueITTokenKey) && "Queue".equals(validationResult.getActionType()) ) {
response.sendRedirect(pureUrl);
response.getOutputStream().flush();
response.getOutputStream().close();
}
}
} catch (Exception ex) {
// There was an error validating the request
// Use your own logging framework to log the error
// This was a configuration error, so we let the user continue
// This was a configuration error, so we let the user continue
}
}

Expand All @@ -90,8 +91,8 @@ Specify the configuration in code without using the Trigger/Action paradigm. In

The following is an example of how to specify the configuration in code:

```
private void doValidationByLocalEventConfig(HttpServletRequest request, HttpServletResponse response) {
```java
private void doValidationByLocalEventConfig(KnownUserRequestWrapper request, HttpServletResponse response) {
try {

String customerId = "Your Queue-it customer ID";
Expand All @@ -118,9 +119,10 @@ The following is an example of how to specify the configuration in code:
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "Fri, 01 Jan 1990 00:00:00 GMT");
//end
if (validationResult.isAjaxResult) {
if (validationResult.isAjaxResult) {
//In case of ajax call send the user to the queue by sending a custom queue-it header and redirecting user to queue from javascript
response.setHeader(validationResult.getAjaxQueueRedirectHeaderKey(), validationResult.getAjaxRedirectUrl());
response.setHeader("Access-Control-Expose-Headers", validationResult.getAjaxQueueRedirectHeaderKey());
} else {
//Send the user to the queue - either becuase hash was missing or becuase is was invalid
response.sendRedirect(validationResult.getRedirectUrl());
Expand All @@ -144,3 +146,125 @@ The following is an example of how to specify the configuration in code:
When users are redirected back from queue-it website they carry a QueueITToken with some information which is used to validate their request by SDK.
In specific cases you would like to validate, process or extract specfic parameters you can use QueueParameterHelper class in [KnownUserHelper.java](https://github.com/queueit/KnownUser.V3.JAVA/blob/master/Documentation/KnownUserHelper.java).
Calling *QueueParameterHelper.getIsTokenValid()* will validate the token and passing QueueITToken to *QueueParameterHelper.extractQueueParams* you will get a QueueUrlParams result containing all parameters found in the token.

## Request body trigger (advanced)

The connector supports triggering on request body content. An example could be a POST call with specific item ID where you want end-users to queue up for.
For this to work, you will need to enable request body triggers in your integration settings in your GO Queue-it platform account or contact Queue-it support.
Once enabled you will need to update your integration configuration so request body is available for the connector.

Request body should be provided by the code which is using this SDK. You can read the request body in your code and provide it to the SDK. This should be done using a subclass of KnownUserRequestWrapper (Please take a look at CustomKnownUserRequestWrapper as an example). The subclass should be used instead of HttpServletRequest similar to the below example. Then the request body can be read many times by using GetRequestBodyAsString() mehod.

For the Get requests the KnownUserRequestWrapper could be used directly.

```java
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
KnownUserRequestWrapper requestWrapper = new KnownUserRequestWrapper(request);
processRequest(requestWrapper, response);
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
CustomKnownUserRequestWrapper requestWrapper = new CustomKnownUserRequestWrapper(request);
processRequest(requestWrapper, response);
}
```

Here is an example of implementing CustomKnownUserRequestWrapper subclass.
This is just one example of how to read the request body, you could use your own implementation.


```java
public class CustomKnownUserRequestWrapper extends KnownUserRequestWrapper {

private final String body;

public CustomKnownUserRequestWrapper(HttpServletRequest request) throws IOException {
super(request);

int maxBytesToRead = 1024 * 50;
StringBuilder stringBuilder = new StringBuilder();
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(super.getInputStream()));
char[] charBuffer = new char[1024];
int bytesRead = -1;
while (((bytesRead = bufferedReader.read(charBuffer)) > 0) && stringBuilder.length() <= maxBytesToRead) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} catch (IOException ex) {
throw ex;
}
body = stringBuilder.toString();
}

@Override
public ServletInputStream getInputStream() throws IOException {
final byte[] myBytes = body.getBytes("UTF-8");
ServletInputStream servletInputStream = new ServletInputStream() {
private int lastIndexRetrieved = -1;
private ReadListener readListener = null;

@Override
public boolean isFinished() {
return (lastIndexRetrieved == myBytes.length - 1);
}

@Override
public boolean isReady() {
return isFinished();
}

@Override
public void setReadListener(ReadListener readListener) {
this.readListener = readListener;
if (!isFinished()) {
try {
readListener.onDataAvailable();
} catch (IOException e) {
readListener.onError(e);
}
} else {
try {
readListener.onAllDataRead();
} catch (IOException e) {
readListener.onError(e);
}
}
}

@Override
public int read() throws IOException {
int i;
if (!isFinished()) {
i = myBytes[lastIndexRetrieved + 1];
lastIndexRetrieved++;
if (isFinished() && (readListener != null)) {
try {
readListener.onAllDataRead();
} catch (IOException ex) {
readListener.onError(ex);
throw ex;
}
}
return i;
} else {
return -1;
}
}
};
return servletInputStream;
}

@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}

public String GetRequestBodyAsString() {
return this.body;
}
}
```
2 changes: 1 addition & 1 deletion SDK/.classpath
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
Expand Down
4 changes: 2 additions & 2 deletions SDK/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.queue-it.connector</groupId>
<artifactId>connector</artifactId>
<version>3.6.2</version>
<version>3.7.0</version>
<name>KnownUserV3</name>
<description>SDK for integrating your application with Queue-it</description>
<url>https://github.com/queueit/KnownUser.V3.JAVA</url>
Expand Down Expand Up @@ -122,7 +122,7 @@
</build>
</profile>
</profiles>

<build>
<plugins>
<plugin>
Expand Down
20 changes: 20 additions & 0 deletions SDK/src/main/java/com/queue_it/connector/CancelEventConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ public class CancelEventConfig {
private String cookieDomain;
private int version;
private String actionName = "unspecified";
private Boolean isCookieHttpOnly;
private Boolean isCookieSecure;

public String getEventId() {
return eventId;
Expand Down Expand Up @@ -52,12 +54,30 @@ public String getActionName() {
return actionName;
}

public Boolean getIsCookieHttpOnly() {
return this.isCookieHttpOnly;
}

public void setIsCookieHttpOnly(Boolean isCookieHttpOnly) {
this.isCookieHttpOnly = isCookieHttpOnly;
}

public Boolean getIsCookieSecure() {
return this.isCookieSecure;
}

public void setIsCookieSecure(Boolean cookieSecure) {
this.isCookieSecure = cookieSecure;
}

@Override
public String toString() {
return "EventId:" + eventId
+ "&Version:" + version
+ "&QueueDomain:" + queueDomain
+ "&CookieDomain:" + cookieDomain
+ "&IsCookieHttpOnly:" + isCookieHttpOnly
+ "&IsCookieSecure:" + isCookieSecure
+ "&ActionName:" + actionName;
}
}
Loading

0 comments on commit 5815bff

Please sign in to comment.