From 9f1f39af13924950e96feb1dd8bb7f37a507e173 Mon Sep 17 00:00:00 2001 From: JKAUSHALYA Date: Wed, 15 Nov 2023 23:42:30 +0530 Subject: [PATCH] Add bulk get support. Fix: https://github.com/wso2/product-is/issues/17825 --- .../charon3/core/encoder/JSONEncoder.java | 21 ++++---- .../core/protocol/BulkRequestProcessor.java | 50 +++++++++++++++++++ .../charon3/core/schema/SCIMConstants.java | 3 ++ 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/encoder/JSONEncoder.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/encoder/JSONEncoder.java index f06a9455c..338712a1f 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/encoder/JSONEncoder.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/encoder/JSONEncoder.java @@ -587,30 +587,29 @@ private void encodeResponseContent(BulkResponseContent responseContent, ArrayList operationResponseList) throws JSONException { - JSONObject operationObject = new JSONObject(); + int statusCode = responseContent.getScimResponse().getResponseStatus(); JSONObject status = new JSONObject(); - int statusCode = responseContent.getScimResponse().getResponseStatus(); status.put(SCIMConstants.OperationalConstants.CODE, statusCode); - + JSONObject operationObject = new JSONObject(); operationObject.put(SCIMConstants.CommonSchemaConstants.LOCATION, responseContent.getLocation()); operationObject.put(SCIMConstants.OperationalConstants.METHOD, responseContent.getMethod()); operationObject.put(SCIMConstants.OperationalConstants.BULK_ID, responseContent.getBulkID()); operationObject.put(SCIMConstants.OperationalConstants.STATUS, status); - //When indicating a response with an HTTP status other than a 200-series response, + // When indicating a response with an HTTP status other than a 200-series response, // the response body MUST be included. - if (statusCode != 200 && statusCode != 201 && statusCode != 204) { + // + // Addition: 2023/11/15 + // We are now supporting bulk get as well. Hence, even with 200 responses, we can get a body. Hence, null + // checking the scim response and if not null adding the response as well. + // Keeping the old status code check for backward compatibility. + if ((statusCode != 200 && statusCode != 201 && statusCode != 204) + || responseContent.getScimResponse() != null) { operationObject.put(SCIMConstants.OperationalConstants.RESPONSE, responseContent.getScimResponse().getResponseMessage()); } - operationResponseList.add(operationObject); - } } - - - - diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/BulkRequestProcessor.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/BulkRequestProcessor.java index f2d1b9984..22ca389a5 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/BulkRequestProcessor.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/BulkRequestProcessor.java @@ -290,10 +290,60 @@ private BulkResponseContent getBulkResponseContent(BulkRequestContent bulkReques errorsCheck(response); break; } + + case SCIMConstants.OperationalConstants.GET: { + String resourceId = extractIDFromPath(bulkRequestContent.getPath()); + String attributes = getAttributesFromData(bulkRequestContent.getData()); + String excludeAttributes = getExcludedAttributesFromData(bulkRequestContent.getData()); + + if (bulkRequestContent.getPath().contains(SCIMConstants.ROLE_V2_ENDPOINT)) { + resourceId = extractIDFromV2Path(bulkRequestContent.getPath()); + response = resourceManager.getRole(resourceId, roleV2Manager, attributes, excludeAttributes); + } else if (bulkRequestContent.getPath().contains(SCIMConstants.ROLE_ENDPOINT)) { + response = resourceManager.getRole(resourceId, roleManager, attributes, excludeAttributes); + } else { + response = resourceManager.get(resourceId, userManager, attributes, excludeAttributes); + } + + bulkResponseContent = createBulkResponseContent(response, SCIMConstants.OperationalConstants.GET, + bulkRequestContent); + errorsCheck(response); + break; + } } return bulkResponseContent; } + private String getExcludedAttributesFromData(String data) throws BadRequestException { + + String excludedAttributes = null; + try { + JSONObject dataJson = new JSONObject(data); + if (dataJson.has(SCIMConstants.CommonSchemaConstants.EXCLUDE_ATTRIBUTES)) { + excludedAttributes = dataJson.getString(SCIMConstants.CommonSchemaConstants.EXCLUDE_ATTRIBUTES); + } + } catch (JSONException e) { + throw new BadRequestException("Error while parsing the data field of the bulk request content", + ResponseCodeConstants.INVALID_SYNTAX); + } + return excludedAttributes; + } + + private String getAttributesFromData(String data) throws BadRequestException { + + String attributes = null; + try { + JSONObject dataJson = new JSONObject(data); + if (dataJson.has(SCIMConstants.CommonSchemaConstants.ATTRIBUTES)) { + attributes = dataJson.getString(SCIMConstants.CommonSchemaConstants.ATTRIBUTES); + } + } catch (JSONException e) { + throw new BadRequestException("Error while parsing the data field of the bulk request content", + ResponseCodeConstants.INVALID_SYNTAX); + } + return attributes; + } + private String extractIDFromPath(String path) throws BadRequestException { String [] parts = path.split("[/]"); diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java index 5028d3b78..2d119daa1 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java @@ -126,6 +126,8 @@ public static class CommonSchemaConstants { public static final String VERSION_DESC = "The version of the resource being returned."; public static final String SYSTEM_ROLE_DESC = "Whether the returned role is a read only system role."; + public static final String ATTRIBUTES = "attributes"; + public static final String EXCLUDE_ATTRIBUTES = "excludedAttributes"; } /** @@ -830,6 +832,7 @@ public static class OperationalConstants { public static final String DELETE = "DELETE"; public static final String PUT = "PUT"; public static final String PATCH = "PATCH"; + public static final String GET = "GET"; public static final String COLON = ":"; public static final String URL_SEPARATOR = "/";