diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index 3e1d3316288..a1563ab5bae 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -1104,6 +1104,37 @@ paths: description: Internal Server Error security: - oauth2: [https://jans.io/oauth/config/scripts.delete] + patch: + summary: Partially update custom script. + description: Partially update custom script. + operationId: patch-config-scripts-by-inum + security: + - oauth2: [https://jans.io/oauth/config/scripts.write] + tags: + - Custom Scripts + requestBody: + content: + application/json-patch+json: + schema: + type: array + items: + $ref: '#/components/schemas/PatchRequest' + description: String representing patch-document. + example: '[ {op:replace, path: enabled, value: \"false\" } ]' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/CustomScript' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + /jans-config-api/api/v1/config/cache: get: summary: Returns cache configuration. @@ -5051,9 +5082,6 @@ components: type: array items: type: string - clientName: - description: A human-readable name of the client. - type: string idTokenTokenBindingCnf: description: 'Specifies the JWT Confirmation Method member name (e.g. tbh) that the Relying Party expects when receiving Token Bound ID Tokens. The presence of this parameter indicates that the Relying Party supports Token Binding of ID Tokens. If omitted, the default is that the Relying Party does not support Token Binding of ID Tokens.' type: string diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/CacheConfigurationResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/CacheConfigurationResource.java index d9b6ddb3381..c97018c0350 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/CacheConfigurationResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/CacheConfigurationResource.java @@ -33,8 +33,10 @@ @Produces(MediaType.APPLICATION_JSON) public class CacheConfigurationResource extends ConfigBaseResource { + private static final String ERROR_MSG = "Unable to apply patch."; + @Inject - Logger log; + Logger logger; @Inject ConfigurationService configurationService; @@ -67,12 +69,12 @@ public Response getCacheConfiguration() { @Consumes(MediaType.APPLICATION_JSON_PATCH_JSON) @ProtectedApi(scopes = { ApiAccessConstants.CACHE_WRITE_ACCESS }) public Response patchCacheConfiguration(@NotNull String requestString) { - log.debug(" CACHE details to patch - requestString = " + requestString); + logger.debug(" CACHE details to patch - requestString:{}", requestString); final CacheConfiguration modifiedCache = mergeModifiedCache(cache -> { try { return Jackson.applyPatch(requestString, cache); } catch (IOException | JsonPatchException e) { - throw new RuntimeException("Unable to apply patch.", e); + throw new RuntimeException(ERROR_MSG, e); } }); return Response.ok(modifiedCache).build(); @@ -89,7 +91,7 @@ public Response getRedisConfiguration() { @Path(ApiConstants.REDIS) @ProtectedApi(scopes = { ApiAccessConstants.CACHE_WRITE_ACCESS }) public Response updateRedisConfiguration(@NotNull RedisConfiguration redisConfiguration) { - log.debug("REDIS CACHE details to update - redisConfiguration = " + redisConfiguration); + logger.debug("REDIS CACHE details to update - redisConfiguration:{}", redisConfiguration); final CacheConfiguration modifiedCache = mergeModifiedCache(cache -> { cache.setRedisConfiguration(redisConfiguration); return cache; @@ -102,12 +104,14 @@ public Response updateRedisConfiguration(@NotNull RedisConfiguration redisConfig @Consumes(MediaType.APPLICATION_JSON_PATCH_JSON) @ProtectedApi(scopes = { ApiAccessConstants.CACHE_WRITE_ACCESS }) public Response patchRedisConfiguration(@NotNull String requestString) { - log.debug("REDIS CACHE details to patch - requestString = " + requestString); - final CacheConfiguration modifiedCache = mergeModifiedCache(cache -> { + logger.debug("REDIS CACHE details to patch - requestString:{} ", requestString); + mergeModifiedCache(cache -> { try { - return Jackson.applyPatch(requestString, cache); + cache.setRedisConfiguration( + Jackson.applyPatch(requestString, loadCacheConfiguration().getRedisConfiguration())); + return cache; } catch (IOException | JsonPatchException e) { - throw new RuntimeException("Unable to apply patch.", e); + throw new RuntimeException(ERROR_MSG, e); } }); return Response.ok(loadCacheConfiguration().getRedisConfiguration()).build(); @@ -124,7 +128,7 @@ public Response getInMemoryConfiguration() { @Path(ApiConstants.IN_MEMORY) @ProtectedApi(scopes = { ApiAccessConstants.CACHE_WRITE_ACCESS }) public Response updateInMemoryConfiguration(@NotNull InMemoryConfiguration inMemoryConfiguration) { - log.debug("IN_MEMORY CACHE details to update - inMemoryConfiguration = " + inMemoryConfiguration); + logger.debug("IN_MEMORY CACHE details to update - inMemoryConfiguration:{}", inMemoryConfiguration); final CacheConfiguration modifiedCache = mergeModifiedCache(cache -> { cache.setInMemoryConfiguration(inMemoryConfiguration); return cache; @@ -138,12 +142,13 @@ public Response updateInMemoryConfiguration(@NotNull InMemoryConfiguration inMem @Consumes(MediaType.APPLICATION_JSON_PATCH_JSON) @ProtectedApi(scopes = { ApiAccessConstants.CACHE_WRITE_ACCESS }) public Response patchInMemoryConfiguration(@NotNull String requestString) { - log.debug("IN_MEMORY CACHE details to patch - requestString = " + requestString); - final CacheConfiguration modifiedCache = mergeModifiedCache(cache -> { + logger.debug("IN_MEMORY CACHE details to patch - requestString:{}", requestString); + mergeModifiedCache(cache -> { try { - return Jackson.applyPatch(requestString, cache); + cache.setInMemoryConfiguration(Jackson.applyPatch(requestString, cache.getInMemoryConfiguration())); + return cache; } catch (IOException | JsonPatchException e) { - throw new RuntimeException("Unable to apply patch.", e); + throw new RuntimeException(ERROR_MSG, e); } }); return Response.ok(loadCacheConfiguration().getInMemoryConfiguration()).build(); @@ -161,8 +166,8 @@ public Response getNativePersistenceConfiguration() { @ProtectedApi(scopes = { ApiAccessConstants.CACHE_WRITE_ACCESS }) public Response updateNativePersistenceConfiguration( @NotNull NativePersistenceConfiguration nativePersistenceConfiguration) { - log.debug("NATIVE_PERSISTENCE CACHE details to update - nativePersistenceConfiguration = " - + nativePersistenceConfiguration); + logger.debug("NATIVE_PERSISTENCE CACHE details to update - nativePersistenceConfiguration:{}", + nativePersistenceConfiguration); final CacheConfiguration modifiedCache = mergeModifiedCache(cache -> { cache.setNativePersistenceConfiguration(nativePersistenceConfiguration); return cache; @@ -175,12 +180,14 @@ public Response updateNativePersistenceConfiguration( @Consumes(MediaType.APPLICATION_JSON_PATCH_JSON) @ProtectedApi(scopes = { ApiAccessConstants.CACHE_WRITE_ACCESS }) public Response patchNativePersistenceConfiguration(@NotNull String requestString) { - log.debug("NATIVE_PERSISTENCE CACHE details to patch - requestString = " + requestString); - final CacheConfiguration modifiedCache = mergeModifiedCache(cache -> { + logger.debug("NATIVE_PERSISTENCE CACHE details to patch - requestString:{} ", requestString); + mergeModifiedCache(cache -> { try { - return Jackson.applyPatch(requestString, cache); + cache.setNativePersistenceConfiguration( + Jackson.applyPatch(requestString, cache.getNativePersistenceConfiguration())); + return cache; } catch (IOException | JsonPatchException e) { - throw new RuntimeException("Unable to apply patch.", e); + throw new RuntimeException(ERROR_MSG, e); } }); return Response.ok(loadCacheConfiguration().getNativePersistenceConfiguration()).build(); @@ -197,7 +204,7 @@ public Response getMemcachedConfiguration() { @Path(ApiConstants.MEMCACHED) @ProtectedApi(scopes = { ApiAccessConstants.CACHE_WRITE_ACCESS }) public Response updateMemcachedConfiguration(@NotNull MemcachedConfiguration memcachedConfiguration) { - log.debug("MEMCACHED CACHE details to update - memcachedConfiguration = " + memcachedConfiguration); + logger.debug("MEMCACHED CACHE details to update - memcachedConfiguration:{} ", memcachedConfiguration); final CacheConfiguration modifiedCache = mergeModifiedCache(cache -> { cache.setMemcachedConfiguration(memcachedConfiguration); return cache; @@ -210,12 +217,13 @@ public Response updateMemcachedConfiguration(@NotNull MemcachedConfiguration mem @Consumes(MediaType.APPLICATION_JSON_PATCH_JSON) @ProtectedApi(scopes = { ApiAccessConstants.CACHE_WRITE_ACCESS }) public Response patchMemcachedConfiguration(@NotNull String requestString) { - log.debug("MEMCACHED CACHE details to patch - requestString = " + requestString); - final CacheConfiguration modifiedCache = mergeModifiedCache(cache -> { + logger.debug("MEMCACHED CACHE details to patch - requestString:{} ", requestString); + mergeModifiedCache(cache -> { try { - return Jackson.applyPatch(requestString, cache); + cache.setMemcachedConfiguration(Jackson.applyPatch(requestString, cache.getMemcachedConfiguration())); + return cache; } catch (IOException | JsonPatchException e) { - throw new RuntimeException("Unable to apply patch.", e); + throw new RuntimeException(ERROR_MSG, e); } }); return Response.ok(loadCacheConfiguration().getMemcachedConfiguration()).build(); diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/CustomScriptResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/CustomScriptResource.java index e7f1c245c1f..b21ebd91c46 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/CustomScriptResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/CustomScriptResource.java @@ -8,6 +8,7 @@ import static io.jans.as.model.util.Util.escapeLog; import io.jans.configapi.core.rest.ProtectedApi; +import io.jans.configapi.core.util.Jackson; import io.jans.configapi.util.ApiAccessConstants; import io.jans.configapi.util.ApiConstants; import io.jans.model.custom.script.CustomScriptType; @@ -16,12 +17,16 @@ import io.jans.util.StringHelper; import org.slf4j.Logger; +import com.github.fge.jsonpatch.JsonPatchException; + import javax.inject.Inject; import javax.validation.Valid; import javax.validation.constraints.NotNull; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; + +import java.io.IOException; import java.util.List; import java.util.Objects; import java.util.UUID; @@ -127,5 +132,21 @@ public Response deleteScript(@PathParam(ApiConstants.INUM) @NotNull String inum) throw new NotFoundException(getNotFoundError(CUSTOM_SCRIPT)); } } + + @PATCH + @Consumes(MediaType.APPLICATION_JSON_PATCH_JSON) + @ProtectedApi(scopes = { ApiAccessConstants.SCRIPTS_WRITE_ACCESS }) + @Path(ApiConstants.INUM_PATH) + public Response patchAtribute(@PathParam(ApiConstants.INUM) @NotNull String inum, @NotNull String pathString) + throws JsonPatchException, IOException { + log.error(" Custom Script Resource to patch - inum:{} , pathString:{}", inum, pathString); + CustomScript existingScript = customScriptService.getScriptByInum(inum); + checkResourceNotNull(existingScript, CUSTOM_SCRIPT); + existingScript = Jackson.applyPatch(pathString, existingScript); + customScriptService.update(existingScript); + existingScript = customScriptService.getScriptByInum(inum); + log.error(" Custom Script Resource after patch - inum:{} , pathString:{}", inum, pathString); + return Response.ok(existingScript).build(); + } } diff --git a/jans-config-api/server/src/main/resources/config-api-rs-protect.json b/jans-config-api/server/src/main/resources/config-api-rs-protect.json index 3877e22726d..46a1e160a67 100644 --- a/jans-config-api/server/src/main/resources/config-api-rs-protect.json +++ b/jans-config-api/server/src/main/resources/config-api-rs-protect.json @@ -315,6 +315,12 @@ "scopes":[ "https://jans.io/oauth/config/scripts.delete" ] + }, + { + "httpMethods":["PATCH"], + "scopes":[ + "https://jans.io/oauth/config/scripts.write" + ] } ] }, diff --git a/jans-config-api/server/src/test/resources/feature/config/scripts/custom/generic/custom.feature b/jans-config-api/server/src/test/resources/feature/config/scripts/custom/generic/custom.feature index a11fc98dae5..2322d5df925 100644 --- a/jans-config-api/server/src/test/resources/feature/config/scripts/custom/generic/custom.feature +++ b/jans-config-api/server/src/test/resources/feature/config/scripts/custom/generic/custom.feature @@ -44,4 +44,24 @@ Feature: Verify Custom Script configuration endpoint And assert response.length != null - \ No newline at end of file + Scenario: Patch person custom script by inum + Given url mainUrl + And header Authorization = 'Bearer ' + accessToken + When method GET + Then status 200 + And print response + And assert response.length != null + And print response[0] + And print 'Script inum = '+response[0].inum + And assert response[0].inum != null + And print 'Script Type = '+response[0].scriptType + And print 'Patching script ' + '-' +response[0].scriptType + '-' +response[0].inum + Given url mainUrl + '/'+response[0].inum + And header Authorization = 'Bearer ' + accessToken + And def request_body = "[ {\"op\":\"replace\", \"path\": \"/enabled\", \"value\":"+response[0].enabled+" } ]") + And print 'request_body ='+request_body + And request request_body + When method PATCH + Then status 200 + And print response + And assert response.length !=0 \ No newline at end of file