This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch 3_0_X
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/3_0_X by this push:
new 60ab1885a6 [SYNCOPE-1880] accept Prefer header with return-no-content
value with SCIM Patch to return 204 (No Content) (#1077)
60ab1885a6 is described below
commit 60ab1885a642e4357e48a9872d71f32f38247724
Author: Samuel Garofalo <[email protected]>
AuthorDate: Tue May 13 12:29:09 2025 +0200
[SYNCOPE-1880] accept Prefer header with return-no-content value with SCIM
Patch to return 204 (No Content) (#1077)
---
.../scimv2/cxf/service/AbstractSCIMService.java | 35 +++++++++++++++++++++-
.../scimv2/cxf/service/SCIMGroupServiceImpl.java | 20 +++++++++----
.../ext/scimv2/cxf/service/SCIMServiceImpl.java | 5 ++++
.../scimv2/cxf/service/SCIMUserServiceImpl.java | 20 +++++++++----
.../org/apache/syncope/fit/core/SCIMITCase.java | 28 +++++++++++++++--
5 files changed, 93 insertions(+), 15 deletions(-)
diff --git
a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
index 61b8f7cbfa..da3038c1b6 100644
---
a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
+++
b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
@@ -32,6 +32,8 @@ import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.to.AnyTO;
import org.apache.syncope.common.lib.to.GroupTO;
import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.rest.api.Preference;
+import org.apache.syncope.common.rest.api.RESTHeaders;
import org.apache.syncope.core.logic.AbstractAnyLogic;
import org.apache.syncope.core.logic.GroupLogic;
import org.apache.syncope.core.logic.SCIMDataBinder;
@@ -124,12 +126,33 @@ abstract class AbstractSCIMService<R extends
SCIMResource> {
build();
}
- protected Response updateResponse(final String key, final SCIMResource
resource) {
+ protected Response updateResponse(final String key, final SCIMResource
resource, final boolean patch) {
+ if (patch) {
+ Response.ResponseBuilder builder;
+ switch (getPreference()) {
+ case RETURN_NO_CONTENT:
+ builder = Response.noContent();
+ break;
+
+ case RETURN_CONTENT:
+ case NONE:
+ default:
+ builder =
Response.ok(uriInfo.getAbsolutePathBuilder().path(key).build()).entity(getResource(key));
+ break;
+ }
+ if (getPreference() == Preference.RETURN_CONTENT ||
getPreference() == Preference.RETURN_NO_CONTENT) {
+ builder.header(RESTHeaders.PREFERENCE_APPLIED,
getPreference().toString());
+ }
+
+ return builder.build();
+ }
return Response.ok(uriInfo.getAbsolutePathBuilder().path(key).build()).
entity(resource).
build();
}
+ protected abstract SCIMResource getResource(String key);
+
protected ResponseBuilder checkETag(final Resource resource, final String
key) {
OffsetDateTime lastChange = anyDAO(resource).findLastChange(key);
if (lastChange == null) {
@@ -223,4 +246,14 @@ abstract class AbstractSCIMService<R extends SCIMResource>
{
return response;
}
+
+ /**
+ * Reads {@code Prefer} header from request and parses into a {@code
Preference} instance.
+ *
+ * @return a {@code Preference} instance matching the passed {@code
Prefer} header,
+ * or {@code Preference.NONE} if missing.
+ */
+ protected Preference getPreference() {
+ return
Preference.fromString(messageContext.getHttpServletRequest().getHeader(RESTHeaders.PREFER));
+ }
}
diff --git
a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMGroupServiceImpl.java
b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMGroupServiceImpl.java
index d6818b8786..04e1777742 100644
---
a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMGroupServiceImpl.java
+++
b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMGroupServiceImpl.java
@@ -53,6 +53,7 @@ import org.apache.syncope.ext.scimv2.api.data.ListResponse;
import org.apache.syncope.ext.scimv2.api.data.Member;
import org.apache.syncope.ext.scimv2.api.data.SCIMGroup;
import org.apache.syncope.ext.scimv2.api.data.SCIMPatchOp;
+import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
import org.apache.syncope.ext.scimv2.api.data.SCIMSearchRequest;
import org.apache.syncope.ext.scimv2.api.service.SCIMGroupService;
import org.apache.syncope.ext.scimv2.api.type.ErrorType;
@@ -166,11 +167,8 @@ public class SCIMGroupServiceImpl extends
AbstractSCIMService<SCIMGroup> impleme
return updateResponse(
id,
- binder.toSCIMGroup(
- groupLogic.read(id),
-
uriInfo.getAbsolutePathBuilder().path(id).build().toASCIIString(),
- List.of(),
- List.of()));
+ null,
+ true);
}
@Override
@@ -212,7 +210,17 @@ public class SCIMGroupServiceImpl extends
AbstractSCIMService<SCIMGroup> impleme
result.getEntity(),
uriInfo.getAbsolutePathBuilder().path(result.getEntity().getKey()).build().toASCIIString(),
List.of(),
- List.of()));
+ List.of()),
+ false);
+ }
+
+ @Override
+ protected SCIMResource getResource(final String key) {
+ return binder.toSCIMGroup(
+ groupLogic.read(key),
+
uriInfo.getAbsolutePathBuilder().path(key).build().toASCIIString(),
+ List.of(),
+ List.of());
}
@Override
diff --git
a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMServiceImpl.java
b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMServiceImpl.java
index 693c09cfc1..2d124aaae5 100644
---
a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMServiceImpl.java
+++
b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMServiceImpl.java
@@ -73,4 +73,9 @@ public class SCIMServiceImpl extends
AbstractSCIMService<SCIMResource> implement
public Response schema(final String schema) {
return Response.ok(scimLogic.schema(schema)).build();
}
+
+ @Override
+ protected SCIMResource getResource(final String key) {
+ return null;
+ }
}
diff --git
a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMUserServiceImpl.java
b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMUserServiceImpl.java
index 69d51b4164..e5e9ec9d38 100644
---
a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMUserServiceImpl.java
+++
b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMUserServiceImpl.java
@@ -40,6 +40,7 @@ import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.ext.scimv2.api.BadRequestException;
import org.apache.syncope.ext.scimv2.api.data.ListResponse;
import org.apache.syncope.ext.scimv2.api.data.SCIMPatchOp;
+import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
import org.apache.syncope.ext.scimv2.api.data.SCIMSearchRequest;
import org.apache.syncope.ext.scimv2.api.data.SCIMUser;
import org.apache.syncope.ext.scimv2.api.service.SCIMUserService;
@@ -102,11 +103,8 @@ public class SCIMUserServiceImpl extends
AbstractSCIMService<SCIMUser> implement
return updateResponse(
id,
- binder.toSCIMUser(
- userLogic.read(id),
-
uriInfo.getAbsolutePathBuilder().path(id).build().toASCIIString(),
- List.of(),
- List.of()));
+ null,
+ true);
}
@Override
@@ -144,7 +142,17 @@ public class SCIMUserServiceImpl extends
AbstractSCIMService<SCIMUser> implement
result.getEntity(),
uriInfo.getAbsolutePathBuilder().path(result.getEntity().getKey()).build().toASCIIString(),
List.of(),
- List.of()));
+ List.of()),
+ false);
+ }
+
+ @Override
+ protected SCIMResource getResource(final String key) {
+ return binder.toSCIMUser(
+ userLogic.read(key),
+
uriInfo.getAbsolutePathBuilder().path(key).build().toASCIIString(),
+ List.of(),
+ List.of());
}
@Override
diff --git
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
index 192ce565cf..0beb6162b1 100644
---
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
+++
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
@@ -61,6 +61,8 @@ import org.apache.syncope.common.lib.to.GroupTO;
import org.apache.syncope.common.lib.to.ProvisioningResult;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.PatchOperation;
+import org.apache.syncope.common.rest.api.Preference;
+import org.apache.syncope.common.rest.api.RESTHeaders;
import org.apache.syncope.ext.scimv2.api.SCIMConstants;
import org.apache.syncope.ext.scimv2.api.data.Group;
import org.apache.syncope.ext.scimv2.api.data.ListResponse;
@@ -694,8 +696,11 @@ public class SCIMITCase extends AbstractITCase {
+ "\"value\":\"Password123!\""
+ "}]"
+ "}";
- response =
webClient().path("Users").path(user.getId()).invoke(HttpMethod.PATCH, body);
- assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ response = webClient().path("Users").path(user.getId())
+ .header(RESTHeaders.PREFER, Preference.RETURN_NO_CONTENT)
+ .invoke(HttpMethod.PATCH, body);
+ assertEquals(Response.Status.NO_CONTENT.getStatusCode(),
response.getStatus());
+ assertFalse(response.hasEntity());
}
@Test
@@ -862,6 +867,25 @@ public class SCIMITCase extends AbstractITCase {
group = response.readEntity(SCIMGroup.class);
assertTrue(group.getMembers().isEmpty());
+
+ // 4. add member
+ body =
+ "{"
+ +
"\"schemas\":[\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"],"
+ + "\"Operations\":["
+ + "{"
+ + "\"op\":\"Add\","
+ + "\"path\":\"members\","
+ + "\"value\":[{"
+ + "\"value\":\"b3cbc78d-32e6-4bd4-92e0-bbe07566a2ee\"}]"
+ + "}"
+ + "]"
+ + "}";
+ response = webClient().path("Groups").path(group.getId())
+ .header(RESTHeaders.PREFER, Preference.RETURN_NO_CONTENT)
+ .invoke(HttpMethod.PATCH, body);
+ assertEquals(Response.Status.NO_CONTENT.getStatusCode(),
response.getStatus());
+ assertFalse(response.hasEntity());
}
@Test