From f2c19a14b0b5b869eb97afd24ac7169328f22b2f Mon Sep 17 00:00:00 2001 From: pujavs <43700552+pujavs@users.noreply.github.com> Date: Wed, 3 Aug 2022 22:15:38 +0530 Subject: [PATCH] feat(jans-config-api): enhancement to agama and uma resource endpoint (#2015) * bug(jans-config-api): fixed swagger format issue * fix(jans-config-api): fixed due to couchbase clustter change * feat(jans-config-api): new endpoint to get UmaResource based on associatedClient * fix(jans-config-api): swagger spec fix for client attributes * fix(jans-config-api): reverted the local test properties * test(jans-config-api): commented test case * feat(jans-config-api): scim config endpoint enhancment * feat(jans-config-api): swagger and DTO change for new fields for scim config endpoint * feat(jans-config-api): swagger and DTO change for new fields for scim config endpoint * fix(jans-config-api): rectified endpoint url in swagger spec for uma resource * feat(jans-config-api): agama endpoint fixes * fix(jans-config-api): agama endpoint enhancements * fix(jans-config-api): fixed swagger spec for Uma Resource delete * fix(jans-config-api): agama endpoint enhancements * fix(jans-config-api): agama endpoint enhancements * fix(jans-config-api): agama endpoint enhancements * fix(jans-config-api): agama endpoint enhancements * fix(jans-config-api): agama endpoint enhancements --- .../io/jans/configapi/util/ApiConstants.java | 2 + .../docs/jans-config-api-swagger.yaml | 146 +++++++++++---- .../profiles/local/test.properties | 4 +- .../rest/resource/auth/AgamaResource.java | 133 ++++++++++++-- .../service/auth/AgamaFlowService.java | 6 +- .../resources/feature/agama/agama.feature | 167 +++++++++++++++++- 6 files changed, 394 insertions(+), 64 deletions(-) diff --git a/jans-config-api/common/src/main/java/io/jans/configapi/util/ApiConstants.java b/jans-config-api/common/src/main/java/io/jans/configapi/util/ApiConstants.java index 47a1c776905..0d6a29892a5 100644 --- a/jans-config-api/common/src/main/java/io/jans/configapi/util/ApiConstants.java +++ b/jans-config-api/common/src/main/java/io/jans/configapi/util/ApiConstants.java @@ -79,6 +79,8 @@ private ApiConstants() {} public static final String QNAME_PATH = "{qname}"; public static final String ENABLED = "enabled"; public static final String QNAME = "qname"; + public static final String INCLUDE_SOURCE = "includeSource"; + public static final String SOURCE = "/source/"; public static final String LIMIT = "limit"; public static final String START_INDEX = "startIndex"; diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index 7a847817348..b248078b1b4 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -2053,6 +2053,7 @@ paths: description: Internal Server Error security: - oauth2: [https://jans.io/oauth/config/openid/clients.write] + /jans-config-api/api/v1/uma/resources: get: tags: @@ -2169,38 +2170,7 @@ paths: description: Internal Server Error security: - oauth2: [https://jans.io/oauth/config/uma/resources.readonly] - /jans-config-api/api/v1/uma/resources/clientId/{clientId}: - parameters: - - name: clientId - in: path - required: true - description: Client ID. - schema: - type: string - get: - tags: - - OAuth - UMA Resources - summary: Fetch uma resources by client id. - description: Fetch uma resources by client id. - operationId: get-oauth-uma-resources-by-clientid - responses: - '200': - description: OK - content: - application/json: - schema: - title: UMA Resource list. - description: List of UMA Resource. - items: - $ref: '#/components/schemas/UmaResource' - '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' - '500': - description: Internal Server Error - security: - - oauth2: [https://jans.io/oauth/config/uma/resources.readonly] + delete: tags: - OAuth - UMA Resources @@ -2218,6 +2188,7 @@ paths: description: Internal Server Error security: - oauth2: [https://jans.io/oauth/config/uma/resources.delete] + patch: tags: - OAuth - UMA Resources @@ -2249,6 +2220,42 @@ paths: description: Internal Server Error security: - oauth2: [https://jans.io/oauth/config/uma/resources.write] + + + /jans-config-api/api/v1/uma/resources/clientId/{clientId}: + parameters: + - name: clientId + in: path + required: true + description: Client ID. + schema: + type: string + get: + tags: + - OAuth - UMA Resources + summary: Fetch uma resources by client id. + description: Fetch uma resources by client id. + operationId: get-oauth-uma-resources-by-clientid + responses: + '200': + description: OK + content: + application/json: + schema: + title: UMA Resource list. + description: List of UMA Resource. + items: + $ref: '#/components/schemas/UmaResource' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + description: Internal Server Error + security: + - oauth2: [https://jans.io/oauth/config/uma/resources.readonly] + + /jans-config-api/api/v1/scopes: get: tags: @@ -2534,8 +2541,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: - oauth2: [https://jans.io/oauth/config/agama.write] - - + put: summary: Updates an agama flow based on Qname. description: Updates an agama based on Qname. @@ -2561,7 +2567,39 @@ paths: '500': $ref: '#/components/responses/InternalServerError' security: - - oauth2: [https://jans.io/oauth/config/agama.write] + - oauth2: [https://jans.io/oauth/config/agama.write] + + patch: + summary: Partially modify a Agama Flow. + description: Partially modify a Agama Flow. + operationId: patch-agama-flow + tags: + - Configuration – Agama Flow + 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/AgamaFlow' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - oauth2: [https://jans.io/oauth/config/agama.write] + delete: summary: Deletes an agama flow based on Qname. description: Deletes an agama flow based on Qname. @@ -2580,6 +2618,41 @@ paths: security: - oauth2: [https://jans.io/oauth/config/agama.delete] + /jans-config-api/api/v1/agama/source/{qname}: + parameters: + - schema: + type: string + name: qname + in: path + description: flow qname. + required: true + + put: + summary: Update agama flow from source file. + description: Update agama flow from source file. + operationId: put-agama-flow-from-source + tags: + - Configuration – Agama Flow + requestBody: + content: + text/plain: + schema: + type: string + + responses: + '201': + description: CREATED + content: + application/json: + schema: + $ref: '#/components/schemas/AgamaFlow' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - oauth2: [https://jans.io/oauth/config/agama.write] + /jans-config-api/api/v1/stat: get: summary: Provides server with basic statistic. @@ -3577,6 +3650,9 @@ components: https://jans.io/oauth/config/user.readonly: View user related information https://jans.io/oauth/config/user.write: Manage user related information https://jans.io/oauth/config/user.delete: Delete user related information + https://jans.io/oauth/config/agama.readonly: View Agama Flow related information + https://jans.io/oauth/config/agama.write: Manage Agama Flow related information + https://jans.io/oauth/config/agama.delete: Delete Agama Flow related information responses: diff --git a/jans-config-api/profiles/local/test.properties b/jans-config-api/profiles/local/test.properties index 55e4b0d691f..fea5d396a4c 100644 --- a/jans-config-api/profiles/local/test.properties +++ b/jans-config-api/profiles/local/test.properties @@ -4,6 +4,6 @@ test.scopes=https://jans.io/oauth/config/acrs.readonly https://jans.io/oauth/con # jans.server token.endpoint=https://jans.server1/jans-auth/restv1/token token.grant.type=client_credentials -test.client.id=1800.d2d3ab98-e018-4a75-bc1d-15b5ac8cb455 -test.client.secret=oGjYGFjhBr97 +test.client.id=1800.c3d63983-6883-438d-b974-38348645de42 +test.client.secret=QzZFg9RnQjSP test.issuer=https://jans.server1 \ No newline at end of file diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaResource.java index eb11ebc1124..d4ce0ee3e79 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaResource.java @@ -7,6 +7,7 @@ package io.jans.configapi.rest.resource.auth; import io.jans.agama.model.Flow; +import io.jans.agama.model.FlowMetadata; import io.jans.agama.dsl.Transpiler; import io.jans.agama.dsl.TranspilerException; import io.jans.agama.dsl.error.SyntaxException; @@ -30,12 +31,16 @@ import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static java.nio.charset.StandardCharsets.UTF_8; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; +import com.github.fge.jsonpatch.JsonPatchException; + @Path(ApiConstants.AGAMA) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @@ -50,10 +55,12 @@ public class AgamaResource extends ConfigBaseResource { @GET @ProtectedApi(scopes = { ApiAccessConstants.AGAMA_READ_ACCESS }) public Response getFlows(@DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, - @DefaultValue(DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit) { + @DefaultValue(DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, + @DefaultValue("false") @QueryParam(value = ApiConstants.INCLUDE_SOURCE) boolean includeSource) { if (log.isDebugEnabled()) { - log.debug("Search Agama Flow with pattern:{}, sizeLimit:{}, ", escapeLog(pattern), escapeLog(limit)); + log.debug("Search Agama Flow with pattern:{}, sizeLimit:{}, includeSource:{}", escapeLog(pattern), + escapeLog(limit), escapeLog(includeSource)); } List flows = null; @@ -63,20 +70,23 @@ public Response getFlows(@DefaultValue("") @QueryParam(value = ApiConstants.PATT flows = agamaFlowService.getAllAgamaFlows(limit); } + // filter values + getAgamaFlowDetails(flows, includeSource); return Response.ok(flows).build(); } @GET @ProtectedApi(scopes = { ApiAccessConstants.AGAMA_READ_ACCESS }) @Path(ApiConstants.QNAME_PATH) - public Response getFlowByName(@PathParam(ApiConstants.QNAME) @NotNull String flowName) { + public Response getFlowByName(@PathParam(ApiConstants.QNAME) @NotNull String flowName, + @DefaultValue("false") @QueryParam(value = ApiConstants.INCLUDE_SOURCE) boolean includeSource) { if (log.isDebugEnabled()) { - log.debug("Search Agama with flowName:{}, ", escapeLog(flowName)); + log.debug("Search Agama with flowName:{}, includeSource:{}", escapeLog(flowName), escapeLog(includeSource)); } String decodedFlowName = getURLDecodedValue(flowName); log.trace(" Agama Decoded flow name decodedFlowName:{}", decodedFlowName); - Flow flow = findFlow(decodedFlowName, true); + Flow flow = findFlow(decodedFlowName, true, includeSource); return Response.ok(flow).build(); } @@ -89,7 +99,7 @@ public Response createFlow(@Valid Flow flow) flow.getSource()); // check if flow with same name already exists - Flow existingFlow = findFlow(flow.getQname(), false); + Flow existingFlow = findFlow(flow.getQname(), false, false); log.debug(" existingFlow:{}", existingFlow); if (existingFlow != null) { thorwBadRequestException("Flow identified by name '" + flow.getQname() + "' already exist!"); @@ -98,9 +108,12 @@ public Response createFlow(@Valid Flow flow) // validate flow data validateAgamaFlowData(flow, true); flow.setRevision(-1); + FlowMetadata flowMetadata = new FlowMetadata(); + flowMetadata.setTimestamp(System.currentTimeMillis()); + flow.setMetadata(flowMetadata); agamaFlowService.addAgamaFlow(flow); - flow = findFlow(flow.getQname(), true); + flow = findFlow(flow.getQname(), true, false); return Response.status(Response.Status.CREATED).entity(flow).build(); } @@ -116,8 +129,8 @@ public Response createFlowFromFile(@PathParam(ApiConstants.QNAME) @NotNull Strin log.trace(" Agama Decoded flow name for create is:{}", decodedFlowName); // check if flow with same name already exists - Flow existingFlow = findFlow(decodedFlowName, false); - log.debug(" existingFlow:{}", existingFlow); + Flow existingFlow = findFlow(decodedFlowName, false, false); + log.debug(" existing-flow:{}", existingFlow); if (existingFlow != null) { thorwBadRequestException("Flow identified by name '" + decodedFlowName + "' already exist!"); } @@ -127,12 +140,15 @@ public Response createFlowFromFile(@PathParam(ApiConstants.QNAME) @NotNull Strin flow.setSource(source); flow.setEnabled(true); flow.setRevision(-1); + FlowMetadata flowMetadata = new FlowMetadata(); + flowMetadata.setTimestamp(System.currentTimeMillis()); + flow.setMetadata(flowMetadata); // validate flow data validateAgamaFlowData(flow, true); agamaFlowService.addAgamaFlow(flow); - flow = findFlow(flow.getQname(), true); + flow = findFlow(flow.getQname(), true, false); return Response.status(Response.Status.CREATED).entity(flow).build(); } @@ -148,7 +164,7 @@ public Response updateFlow(@PathParam(ApiConstants.QNAME) @NotNull String flowNa log.trace(" Agama Decoded flow name for update is:{}", decodedFlowName); // check if flow exists - Flow existingFlow = findFlow(decodedFlowName, true); + Flow existingFlow = findFlow(decodedFlowName, true, false); // set flow data flow.setQname(decodedFlowName); @@ -162,10 +178,69 @@ public Response updateFlow(@PathParam(ApiConstants.QNAME) @NotNull String flowNa log.debug("Updating flow after validation"); agamaFlowService.updateFlow(flow); - flow = findFlow(decodedFlowName, true); + flow = findFlow(decodedFlowName, true, false); return Response.status(Response.Status.OK).entity(flow).build(); } + @PUT + @Consumes(MediaType.TEXT_PLAIN) + @Path(ApiConstants.SOURCE + ApiConstants.QNAME_PATH) + @ProtectedApi(scopes = { ApiAccessConstants.AGAMA_WRITE_ACCESS }) + public Response updateFlowFromFile(@PathParam(ApiConstants.QNAME) @NotNull String flowName, @Valid String source) + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + log.debug(" Flow to be updated flowName:{}, source:{}", flowName, source); + + String decodedFlowName = getURLDecodedValue(flowName); + log.trace(" Agama flow name for update is:{}", decodedFlowName); + + // check if flow with same name already exists + Flow existingFlow = findFlow(decodedFlowName, false, false); + log.debug(" Agama existingFlow:{}", existingFlow); + + // Update source and revision + if (existingFlow != null) { + existingFlow.setSource(source); + + getRevision(existingFlow, existingFlow); + + // validate flow data + validateAgamaFlowData(existingFlow, false); + log.debug("Update flow after validation"); + agamaFlowService.updateFlow(existingFlow); + + existingFlow = findFlow(existingFlow.getQname(), true, false); + } + return Response.status(Response.Status.OK).entity(existingFlow).build(); + } + + @PATCH + @Consumes(MediaType.APPLICATION_JSON_PATCH_JSON) + @Path(ApiConstants.QNAME_PATH) + @ProtectedApi(scopes = { ApiAccessConstants.AGAMA_WRITE_ACCESS }) + public Response patchFlow(@PathParam(ApiConstants.QNAME) @NotNull String flowName, @NotNull String pathString) + throws JsonPatchException, IOException, NoSuchMethodException, IllegalAccessException, + InvocationTargetException { + if (logger.isDebugEnabled()) { + logger.debug("Flow details to be patched - flowName:{}, pathString:{}", escapeLog(flowName), + escapeLog(pathString)); + } + String decodedFlowName = getURLDecodedValue(flowName); + log.trace(" Flow name for update is:{}", decodedFlowName); + + // check if flow exists + Flow existingFlow = findFlow(decodedFlowName, false, true); + log.debug(" existingFlow:{}", existingFlow); + + existingFlow = Jackson.applyPatch(pathString, existingFlow); + getRevision(existingFlow, existingFlow); + + // validate flow data + validateAgamaFlowData(existingFlow, false); + log.debug("Updating flow after validation"); + agamaFlowService.updateFlow(existingFlow); + return Response.ok(existingFlow).build(); + } + @DELETE @Path(ApiConstants.QNAME_PATH) @ProtectedApi(scopes = { ApiAccessConstants.AGAMA_DELETE_ACCESS }) @@ -175,16 +250,23 @@ public Response deleteAttribute(@PathParam(ApiConstants.QNAME) @NotNull String f log.trace(" Agama Decoded flow name is:{}", decodedFlowName); // check if flow exists - Flow flow = findFlow(decodedFlowName, true); + Flow flow = findFlow(decodedFlowName, true, false); agamaFlowService.removeAgamaFlow(flow); return Response.noContent().build(); } - private Flow findFlow(String flowName, boolean throwError) { + private Flow findFlow(String flowName, boolean throwError, boolean includeSource) { Flow flow = null; try { flow = agamaFlowService.getFlowByName(flowName); + + // filter values + List flows = Arrays.asList(flow); + getAgamaFlowDetails(flows, includeSource); + if (flows != null && !flows.isEmpty()) { + flow = flows.get(0); + } } catch (EntryPersistenceException e) { log.error("No flow found with the name:{} ", flowName); if (throwError) { @@ -224,7 +306,7 @@ private void validateSyntax(Flow flow) { } catch (SyntaxException se) { log.error("Transpiler syntax check error", se); try { - log.debug("Throwing BadRequestException 400 :{} ", Jackson.asJson(se)); + log.debug("Throwing BadRequestException 400 :{} ", Jackson.asPrettyJson(se)); thorwBadRequestException(Jackson.asJson(se)); } catch (IOException io) { log.error("Agama Flow Transpiler syntax error parsing error", io); @@ -266,4 +348,25 @@ private Flow getRevision(Flow flow, Flow existingFlow) { log.debug("Final flow revision to be updated to - flow.getRevision():{}", flow.getRevision()); return flow; } + + private List getAgamaFlowDetails(List flows, boolean includeSource) { + + log.debug("Flow data filter - flows:{}, includeSource:{}", flows, includeSource); + if (flows == null || flows.isEmpty()) { + return flows; + } + + for (Flow flow : flows) { + + flow.setTranspiled(null); + flow.setTransHash(null); + + if (!includeSource) { + flow.setSource(null); + } + + } + return flows; + + } } diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AgamaFlowService.java b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AgamaFlowService.java index 70a98b993f1..d299806a747 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AgamaFlowService.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AgamaFlowService.java @@ -181,7 +181,7 @@ public String validateFlowFields(Flow flow, List mandatoryAttributes, Li logger.debug("Checking mandatory errorMsg:{} ", errorMsg); if (errorMsg.length() > 0) { - errorMsg.insert(0, "Required feilds missing -> ("); + errorMsg.insert(0, "Required fields missing -> ("); errorMsg.replace(errorMsg.lastIndexOf(","), errorMsg.length(), ""); errorMsg.append("). "); } @@ -255,7 +255,7 @@ public String validateNonMandatoryFields(Flow flow, List mandatoryAttrib logger.debug("Checking mandatory unwantedAttributes:{} ", unwantedAttributes); if (unwantedAttributes.length() > 0) { - unwantedAttributes.insert(0, "Value of these feilds should be null -> ("); + unwantedAttributes.insert(0, "Value of these fields should be null -> ("); unwantedAttributes.replace(unwantedAttributes.lastIndexOf(","), unwantedAttributes.length(), ""); unwantedAttributes.append(")."); } @@ -304,7 +304,7 @@ else if ("io.jans.agama.model.FlowMetadata".equalsIgnoreCase(dataType.getName()) || StringUtils.isNotBlank(flowMetadata.getAuthor()) || StringUtils.isNotBlank(flowMetadata.getDescription()) || flowMetadata.getInputs() != null || (flowMetadata.getTimeout() != null && flowMetadata.getTimeout() > 0) - || flowMetadata.getProperties() != null || flowMetadata.getTimestamp() > 0) { + || flowMetadata.getProperties() != null ) { logger.debug("FlowMetadata is not null !!!"); return true; } diff --git a/jans-config-api/server/src/test/resources/feature/agama/agama.feature b/jans-config-api/server/src/test/resources/feature/agama/agama.feature index d757960aef3..5b503944f00 100644 --- a/jans-config-api/server/src/test/resources/feature/agama/agama.feature +++ b/jans-config-api/server/src/test/resources/feature/agama/agama.feature @@ -61,10 +61,23 @@ Scenario: Create, update and delete agama flow And request read('agama.json') When method POST Then status 201 + And print response + And print response.qname + Then def flowName = response.qname + And print flowName + Then def encodedFlowName = funGetEncodedValue(flowName) + And print encodedFlowName + #Fetch agama flow by name and with source + Given url mainUrl + '/' +encodedFlowName+ '?includeSource=true' + And header Authorization = 'Bearer ' + accessToken + When method GET + Then status 200 And print response Then def result = response - And print 'Old transHash ='+response.transHash - Then set result.transHash = 'UpdatedAgamaFlowtransHash' + And print result + And print 'Old revision ='+response.revision + Then set result.revision = response.revision+1 + And print result And print response.qname Then def flowName = response.qname And print flowName @@ -78,7 +91,7 @@ Scenario: Create, update and delete agama flow Then status 200 And print response And print response.qname - And print response.transHash + And print response.revision Then def flowName = response.qname And print flowName Then def encodedFlowName = funGetEncodedValue(flowName) @@ -91,6 +104,16 @@ Scenario: Create, update and delete agama flow And print response And print response.qname Then def flowName = response.qname + And print flowName + Then def encodedFlowName = funGetEncodedValue(flowName) + And print encodedFlowName + #Fetch agama flow by name and with source + Given url mainUrl + '/' +encodedFlowName + '?includeSource=true' + And header Authorization = 'Bearer ' + accessToken + When method GET + Then status 200 + And print response + Then def flowName = response.qname And print flowName Then def encodedFlowName = funGetEncodedValue(flowName) And print encodedFlowName @@ -101,7 +124,7 @@ Scenario: Create, update and delete agama flow Then status 204 And print response - + @CreateFlowWithDataInRequestBodyUpdateDelete Scenario: Create agama flow with source data in request body #Create agama flow @@ -117,13 +140,22 @@ Scenario: Create agama flow with source data in request body When method POST Then status 201 And print response + Then def flowName = response.qname + And print flowName + Then def encodedFlowName = funGetEncodedValue(flowName) + And print encodedFlowName + #Fetch agama flow by name and with source + Given url mainUrl + '/' +encodedFlowName+ '?includeSource=true' + And header Authorization = 'Bearer ' + accessToken + When method GET + Then status 200 + And print response And print response.qname Then def flowName = response.qname And print flowName Then def result = response - And print 'Old transHash ='+response.transHash - Then set result.transHash = 'UpdatedAgamaFlowtransHash' - Then def encodedFlowName = funGetEncodedValue(flowName) + And print 'Old revision ='+response.revision + Then set result.revision = response.revision+1 And print encodedFlowName #Update agama flow Given url mainUrl + '/' +encodedFlowName @@ -133,7 +165,7 @@ Scenario: Create agama flow with source data in request body Then status 200 And print response And print response.qname - And print response.transHash + And print response.revision Then def flowName = response.qname And print flowName Then def encodedFlowName = funGetEncodedValue(flowName) @@ -155,5 +187,122 @@ Scenario: Create agama flow with source data in request body When method DELETE Then status 204 And print response + + +@CreateAndUpdateFlowWithDataInRequestBodyUpdateDelete +Scenario: Create agama flow with source data in request body + #Create agama flow + Then def flowName = 'test' + And print flowName + Then def encodedFlowName = funGetEncodedValue(flowName) + And print encodedFlowName + Given url mainUrl + '/' +encodedFlowName + And header Authorization = 'Bearer ' + accessToken + And header Content-Type = 'text/plain' + And header Accept = 'application/json' + And request read('agama-source.txt') + When method POST + Then status 201 + And print response + Then def flowName = response.qname + And print flowName + Then def encodedFlowName = funGetEncodedValue(flowName) + And print encodedFlowName + #Fetch agama flow by name and with source + Given url mainUrl + '/' +encodedFlowName+ '?includeSource=true' + And header Authorization = 'Bearer ' + accessToken + When method GET + Then status 200 + And print response + And print response.qname + Then def flowName = response.qname + And print flowName + Then def result = response + Then def encodedFlowName = funGetEncodedValue(flowName) + And print encodedFlowName + #Update agama flow + Given url mainUrl + '/source/' +encodedFlowName + And header Authorization = 'Bearer ' + accessToken + And header Content-Type = 'text/plain' + And header Accept = 'application/json' + And request read('agama-source.txt') + When method PUT + Then status 200 + And print response + And print response.qname + And print response.revision + Then def flowName = response.qname + And print flowName + Then def encodedFlowName = funGetEncodedValue(flowName) + And print encodedFlowName + #Fetch agama flow by name + Given url mainUrl + '/' +encodedFlowName + And header Authorization = 'Bearer ' + accessToken + When method GET + Then status 200 + And print response + And print response.qname + Then def flowName = response.qname + And print flowName + Then def encodedFlowName = funGetEncodedValue(flowName) + And print encodedFlowName + #Delete agama flow by name + Given url mainUrl + '/' +encodedFlowName + And header Authorization = 'Bearer ' + accessToken + When method DELETE + Then status 204 + And print response + - +@CreateAndPatchFlowAndDelete +Scenario: Create and Patch agama flow + #Create agama flow + Given url mainUrl + And header Authorization = 'Bearer ' + accessToken + And request read('agama.json') + When method POST + Then status 201 + And print response + Then def flowName = response.qname + And print flowName + Then def encodedFlowName = funGetEncodedValue(flowName) + And print encodedFlowName + #Fetch agama flow by name and with source + Given url mainUrl + '/' +encodedFlowName+ '?includeSource=true' + And header Authorization = 'Bearer ' + accessToken + When method GET + Then status 200 + And print response + Then def result = response + And print response.qname + Then def flowName = response.qname + And print flowName + Then def encodedFlowName = funGetEncodedValue(flowName) + And print encodedFlowName + #Patch agama flow + Then def revision_before = response.revision + And print 'revision = '+revision_before + Then def revision_updated = revision_before+1 + And print 'revision_updated = '+revision_updated + And print result.jansHideOnDiscovery + And def request_body = (result.revision == null ? "[ {\"op\":\"add\", \"path\": \"/revision\", \"value\":"+revision_updated+" } ]" : "[ {\"op\":\"replace\", \"path\": \"/revision\", \"value\":"+revision_updated+" } ]") + And print 'request_body ='+request_body + Given url mainUrl + '/' +encodedFlowName + And header Authorization = 'Bearer ' + accessToken + And header Content-Type = 'application/json-patch+json' + And header Accept = 'application/json' + And request request_body + Then print request + When method PATCH + Then status 200 + And print response + Then def flowName = response.qname + And print flowName + Then def encodedFlowName = funGetEncodedValue(flowName) + And print encodedFlowName + #Delete agama flow by name + Given url mainUrl + '/' +encodedFlowName + And header Authorization = 'Bearer ' + accessToken + When method DELETE + Then status 204 + And print response