mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-17 20:50:44 +00:00
Support api-key in query-string for backend-api;
This commit is contained in:
@ -24,6 +24,8 @@ package com.kingsrook.qqq.backend.module.api.actions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
@ -644,6 +646,20 @@ public class BaseAPIActionUtil
|
||||
request.setHeader("Authorization", "Bearer " + getOAuth2Token());
|
||||
break;
|
||||
|
||||
case API_KEY_QUERY_PARAM:
|
||||
try
|
||||
{
|
||||
String uri = request.getURI().toString();
|
||||
uri += (uri.contains("?") ? "&" : "?");
|
||||
uri += backendMetaData.getApiKeyQueryParamName() + "=" + backendMetaData.getApiKey();
|
||||
request.setURI(new URI(uri));
|
||||
}
|
||||
catch(URISyntaxException e)
|
||||
{
|
||||
throw (new QException("Error setting authorization query parameter", e));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Unexpected authorization type: " + backendMetaData.getAuthorizationType());
|
||||
}
|
||||
@ -1051,37 +1067,53 @@ public class BaseAPIActionUtil
|
||||
*******************************************************************************/
|
||||
protected void logOutboundApiCall(HttpRequestBase request, QHttpResponse response)
|
||||
{
|
||||
QTableMetaData table = QContext.getQInstance().getTable(OutboundAPILog.TABLE_NAME);
|
||||
if(table == null)
|
||||
try
|
||||
{
|
||||
return;
|
||||
}
|
||||
QTableMetaData table = QContext.getQInstance().getTable(OutboundAPILog.TABLE_NAME);
|
||||
if(table == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String requestBody = null;
|
||||
if(request instanceof HttpEntityEnclosingRequest entityRequest)
|
||||
String requestBody = null;
|
||||
if(request instanceof HttpEntityEnclosingRequest entityRequest)
|
||||
{
|
||||
try
|
||||
{
|
||||
requestBody = StringUtils.join("\n", IOUtils.readLines(entityRequest.getEntity().getContent()));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// leave it null...
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// mask api keys in query strings //
|
||||
////////////////////////////////////
|
||||
String url = request.getURI().toString();
|
||||
if(backendMetaData.getAuthorizationType().equals(AuthorizationType.API_KEY_QUERY_PARAM))
|
||||
{
|
||||
url = url.replaceFirst(backendMetaData.getApiKey(), "******");
|
||||
}
|
||||
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(table.getName());
|
||||
insertInput.setRecords(List.of(new OutboundAPILog()
|
||||
.withMethod(request.getMethod())
|
||||
.withUrl(url)
|
||||
.withTimestamp(Instant.now())
|
||||
.withRequestBody(requestBody)
|
||||
.withStatusCode(response.getStatusCode())
|
||||
.withResponseBody(response.getContent())
|
||||
.toQRecord()
|
||||
));
|
||||
new InsertAction().executeAsync(insertInput);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
requestBody = StringUtils.join("\n", IOUtils.readLines(entityRequest.getEntity().getContent()));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// leave it null...
|
||||
}
|
||||
LOG.warn("Error logging outbound api call", e);
|
||||
}
|
||||
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(table.getName());
|
||||
insertInput.setRecords(List.of(new OutboundAPILog()
|
||||
.withMethod(request.getMethod())
|
||||
.withUrl(request.getURI().toString()) // todo - does this have the query string?
|
||||
.withTimestamp(Instant.now())
|
||||
.withRequestBody(requestBody)
|
||||
.withStatusCode(response.getStatusCode())
|
||||
.withResponseBody(response.getContent())
|
||||
.toQRecord()
|
||||
));
|
||||
new InsertAction().executeAsync(insertInput);
|
||||
}
|
||||
|
||||
|
||||
|
@ -31,5 +31,5 @@ public enum AuthorizationType
|
||||
BASIC_AUTH_API_KEY,
|
||||
BASIC_AUTH_USERNAME_PASSWORD,
|
||||
OAUTH2,
|
||||
|
||||
API_KEY_QUERY_PARAM,
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ public class APIBackendMetaData extends QBackendMetaData
|
||||
private String clientSecret;
|
||||
private String username;
|
||||
private String password;
|
||||
private String apiKeyQueryParamName;
|
||||
|
||||
private AuthorizationType authorizationType;
|
||||
private String contentType; // todo enum?
|
||||
@ -460,6 +461,16 @@ public class APIBackendMetaData extends QBackendMetaData
|
||||
public void performValidation(QInstanceValidator qInstanceValidator)
|
||||
{
|
||||
qInstanceValidator.assertCondition(StringUtils.hasContent(baseUrl), "Missing baseUrl for API backend: " + getName());
|
||||
|
||||
if(AuthorizationType.API_KEY_QUERY_PARAM.equals(authorizationType))
|
||||
{
|
||||
qInstanceValidator.assertCondition(StringUtils.hasContent(apiKey), "Missing apiKey for API backend: " + getName() + " (required when using AuthorizationType=API_KEY_QUERY_PARAM))");
|
||||
qInstanceValidator.assertCondition(StringUtils.hasContent(apiKeyQueryParamName), "Missing apiKeyQueryParamName for API backend: " + getName() + " (required when using AuthorizationType=API_KEY_QUERY_PARAM))");
|
||||
}
|
||||
else
|
||||
{
|
||||
qInstanceValidator.assertCondition(!StringUtils.hasContent(apiKeyQueryParamName), "Unexpected apiKeyQueryParamName for API backend: " + getName() + " (only allowed when using AuthorizationType=API_KEY_QUERY_PARAM))");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -473,4 +484,35 @@ public class APIBackendMetaData extends QBackendMetaData
|
||||
return (false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for apiKeyQueryParamName
|
||||
*******************************************************************************/
|
||||
public String getApiKeyQueryParamName()
|
||||
{
|
||||
return (this.apiKeyQueryParamName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for apiKeyQueryParamName
|
||||
*******************************************************************************/
|
||||
public void setApiKeyQueryParamName(String apiKeyQueryParamName)
|
||||
{
|
||||
this.apiKeyQueryParamName = apiKeyQueryParamName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for apiKeyQueryParamName
|
||||
*******************************************************************************/
|
||||
public APIBackendMetaData withApiKeyQueryParamName(String apiKeyQueryParamName)
|
||||
{
|
||||
this.apiKeyQueryParamName = apiKeyQueryParamName;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.module.api.model.metadata;
|
||||
|
||||
import com.kingsrook.qqq.backend.core.instances.QInstanceValidator;
|
||||
import com.kingsrook.qqq.backend.module.api.BaseTest;
|
||||
import com.kingsrook.qqq.backend.module.api.model.AuthorizationType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@ -39,7 +40,7 @@ class APIBackendMetaDataTest extends BaseTest
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test()
|
||||
void testMissingBaseUrl()
|
||||
{
|
||||
APIBackendMetaData apiBackendMetaData = new APIBackendMetaData()
|
||||
.withName("test");
|
||||
@ -49,4 +50,45 @@ class APIBackendMetaDataTest extends BaseTest
|
||||
assertThat(qInstanceValidator.getErrors()).anyMatch(e -> e.contains("Missing baseUrl"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testAuthorizationApiKeyQueryParam()
|
||||
{
|
||||
APIBackendMetaData apiBackendMetaData = new APIBackendMetaData()
|
||||
.withAuthorizationType(AuthorizationType.API_KEY_QUERY_PARAM)
|
||||
.withBaseUrl("http://localhost:8000/")
|
||||
.withName("test");
|
||||
QInstanceValidator qInstanceValidator = new QInstanceValidator();
|
||||
apiBackendMetaData.performValidation(qInstanceValidator);
|
||||
assertEquals(2, qInstanceValidator.getErrors().size());
|
||||
assertThat(qInstanceValidator.getErrors()).anyMatch(e -> e.contains("Missing apiKey for API backend"));
|
||||
assertThat(qInstanceValidator.getErrors()).anyMatch(e -> e.contains("Missing apiKeyQueryParamName for API backend"));
|
||||
|
||||
apiBackendMetaData = new APIBackendMetaData()
|
||||
.withAuthorizationType(AuthorizationType.API_KEY_QUERY_PARAM)
|
||||
.withApiKey("ABC-123")
|
||||
.withApiKeyQueryParamName("key")
|
||||
.withBaseUrl("http://localhost:8000/")
|
||||
.withName("test");
|
||||
qInstanceValidator = new QInstanceValidator();
|
||||
apiBackendMetaData.performValidation(qInstanceValidator);
|
||||
assertEquals(0, qInstanceValidator.getErrors().size());
|
||||
|
||||
apiBackendMetaData = new APIBackendMetaData()
|
||||
.withAuthorizationType(AuthorizationType.API_KEY_HEADER)
|
||||
.withApiKey("ABC-123")
|
||||
.withApiKeyQueryParamName("key")
|
||||
.withBaseUrl("http://localhost:8000/")
|
||||
.withName("test");
|
||||
qInstanceValidator = new QInstanceValidator();
|
||||
apiBackendMetaData.performValidation(qInstanceValidator);
|
||||
assertEquals(1, qInstanceValidator.getErrors().size());
|
||||
assertThat(qInstanceValidator.getErrors()).anyMatch(e -> e.contains("Unexpected apiKeyQueryParamName for API backend"));
|
||||
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user