Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jans config api fixes #2028

Merged
merged 36 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9d444bd
bug(jans-config-api): fixed swagger format issue
pujavs Jul 22, 2022
4c253a2
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jul 25, 2022
f6eb80b
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jul 25, 2022
ac97cc6
fix(jans-config-api): fixed due to couchbase clustter change
pujavs Jul 25, 2022
cd554ae
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jul 25, 2022
f4bd7aa
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jul 26, 2022
b313aae
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jul 27, 2022
c8003fd
feat(jans-config-api): new endpoint to get UmaResource based on assoc…
pujavs Jul 27, 2022
fc5ebe0
fix(jans-config-api): swagger spec fix for client attributes
pujavs Jul 27, 2022
77d19bb
fix(jans-config-api): reverted the local test properties
pujavs Jul 27, 2022
d4f8194
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jul 27, 2022
a977d1f
test(jans-config-api): commented test case
pujavs Jul 27, 2022
15dee7f
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jul 28, 2022
b409633
feat(jans-config-api): scim config endpoint enhancment
pujavs Jul 28, 2022
1498d74
feat(jans-config-api): swagger and DTO change for new fields for scim…
pujavs Jul 29, 2022
6940645
Merge branch 'jans-config-api-fixes' of https://github.com/JanssenPro…
pujavs Jul 29, 2022
3ac7ea1
feat(jans-config-api): swagger and DTO change for new fields for scim…
pujavs Jul 29, 2022
8db181b
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jul 29, 2022
1faa93f
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Aug 1, 2022
0e40cbe
fix(jans-config-api): rectified endpoint url in swagger spec for uma …
pujavs Aug 1, 2022
e40c219
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Aug 2, 2022
ef33d5c
feat(jans-config-api): agama endpoint fixes
pujavs Aug 2, 2022
0c76af8
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Aug 3, 2022
084c853
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Aug 3, 2022
1a80d8e
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Aug 3, 2022
0477b09
fix(jans-config-api): agama endpoint enhancements
pujavs Aug 3, 2022
44415b9
fix(jans-config-api): fixed swagger spec for Uma Resource delete
pujavs Aug 3, 2022
77547bb
fix(jans-config-api): agama endpoint enhancements
pujavs Aug 3, 2022
ee4afb3
fix(jans-config-api): agama endpoint enhancements
pujavs Aug 3, 2022
f22cd3b
fix(jans-config-api): agama endpoint enhancements
pujavs Aug 3, 2022
7ac9cde
fix(jans-config-api): agama endpoint enhancements
pujavs Aug 3, 2022
3a05019
fix(jans-config-api): agama endpoint enhancements
pujavs Aug 3, 2022
153c746
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Aug 4, 2022
d740c68
feat(jans-config-api): agama patch endpoint
pujavs Aug 4, 2022
0a8e5e6
feat(jans-config-api): agama patch endpoint
pujavs Aug 4, 2022
8ed2ba8
feat(jans-config-api): agama patch endpoint
pujavs Aug 4, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,13 @@
import org.slf4j.Logger;

import com.github.fge.jsonpatch.JsonPatchException;
import com.github.fge.jsonpatch.JsonPatch;

@Path(ApiConstants.AGAMA)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class AgamaResource extends ConfigBaseResource {

@Inject
Logger log;

@Inject
AgamaFlowService agamaFlowService;

Expand All @@ -58,8 +56,8 @@ public Response getFlows(@DefaultValue("") @QueryParam(value = ApiConstants.PATT
@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:{}, includeSource:{}", escapeLog(pattern),
if (logger.isDebugEnabled()) {
logger.debug("Search Agama Flow with pattern:{}, sizeLimit:{}, includeSource:{}", escapeLog(pattern),
escapeLog(limit), escapeLog(includeSource));
}

Expand All @@ -80,12 +78,13 @@ public Response getFlows(@DefaultValue("") @QueryParam(value = ApiConstants.PATT
@Path(ApiConstants.QNAME_PATH)
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:{}, includeSource:{}", escapeLog(flowName), escapeLog(includeSource));
if (logger.isDebugEnabled()) {
logger.debug("Search Agama with flowName:{}, includeSource:{}", escapeLog(flowName),
escapeLog(includeSource));
}

String decodedFlowName = getURLDecodedValue(flowName);
log.trace(" Agama Decoded flow name decodedFlowName:{}", decodedFlowName);
logger.trace(" Agama Decoded flow name decodedFlowName:{}", decodedFlowName);
Flow flow = findFlow(decodedFlowName, true, includeSource);

return Response.ok(flow).build();
Expand All @@ -95,22 +94,19 @@ public Response getFlowByName(@PathParam(ApiConstants.QNAME) @NotNull String flo
@ProtectedApi(scopes = { ApiAccessConstants.AGAMA_WRITE_ACCESS })
public Response createFlow(@Valid Flow flow)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
log.debug(" Flow to be added flow:{}, flow.getQName():{}, flow.getSource():{} ", flow, flow.getQname(),
logger.debug(" Flow to be added flow:{}, flow.getQName():{}, flow.getSource():{} ", flow, flow.getQname(),
flow.getSource());

// check if flow with same name already exists
Flow existingFlow = findFlow(flow.getQname(), false, false);
log.debug(" existingFlow:{}", existingFlow);
logger.debug(" existingFlow:{}", existingFlow);
if (existingFlow != null) {
thorwBadRequestException("Flow identified by name '" + flow.getQname() + "' already exist!");
}

// validate flow data
updateFlowDetails(flow, null);
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, false);
Expand All @@ -123,14 +119,14 @@ public Response createFlow(@Valid Flow flow)
@ProtectedApi(scopes = { ApiAccessConstants.AGAMA_WRITE_ACCESS })
public Response createFlowFromFile(@PathParam(ApiConstants.QNAME) @NotNull String flowName, @Valid String source)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
log.debug(" Flow to be created flowName:{}, source:{}", flowName, source);
logger.debug(" Flow to be created flowName:{}, source:{}", flowName, source);

String decodedFlowName = getURLDecodedValue(flowName);
log.trace(" Agama Decoded flow name for create is:{}", decodedFlowName);
logger.trace(" Agama Decoded flow name for create is:{}", decodedFlowName);

// check if flow with same name already exists
Flow existingFlow = findFlow(decodedFlowName, false, false);
log.debug(" existing-flow:{}", existingFlow);
logger.debug(" existing-flow:{}", existingFlow);
if (existingFlow != null) {
thorwBadRequestException("Flow identified by name '" + decodedFlowName + "' already exist!");
}
Expand All @@ -139,10 +135,7 @@ public Response createFlowFromFile(@PathParam(ApiConstants.QNAME) @NotNull Strin
flow.setQname(decodedFlowName);
flow.setSource(source);
flow.setEnabled(true);
flow.setRevision(-1);
FlowMetadata flowMetadata = new FlowMetadata();
flowMetadata.setTimestamp(System.currentTimeMillis());
flow.setMetadata(flowMetadata);
updateFlowDetails(flow, null);

// validate flow data
validateAgamaFlowData(flow, true);
Expand All @@ -157,25 +150,23 @@ public Response createFlowFromFile(@PathParam(ApiConstants.QNAME) @NotNull Strin
@ProtectedApi(scopes = { ApiAccessConstants.AGAMA_WRITE_ACCESS })
public Response updateFlow(@PathParam(ApiConstants.QNAME) @NotNull String flowName, @Valid Flow flow)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
log.debug(" Flow to update flowName:{}, flow:{}, flow.getQName():{}, flow.getSource():{} ", flowName, flow,
logger.debug(" Flow to update flowName:{}, flow:{}, flow.getQName():{}, flow.getSource():{} ", flowName, flow,
flow.getQname(), flow.getSource());

String decodedFlowName = getURLDecodedValue(flowName);
log.trace(" Agama Decoded flow name for update is:{}", decodedFlowName);
logger.trace(" Agama Decoded flow name for update is:{}", decodedFlowName);

// check if flow exists
Flow existingFlow = findFlow(decodedFlowName, true, false);

// set flow data
flow.setQname(decodedFlowName);
log.trace("Flow revision check - flow.getRevision():{}, existingFlow.getRevision():{}", flow.getRevision(),
existingFlow.getRevision());
getRevision(flow, existingFlow);
log.debug("Flow revision after update - flow.getRevision():{}", flow.getRevision());
updateFlowDetails(flow, existingFlow);
logger.debug("Flow revision after update - flow.getRevision():{}", flow.getRevision());

// validate flow data
validateAgamaFlowData(flow, false);
log.debug("Updating flow after validation");
logger.debug("Updating flow after validation");
agamaFlowService.updateFlow(flow);

flow = findFlow(decodedFlowName, true, false);
Expand All @@ -188,24 +179,24 @@ public Response updateFlow(@PathParam(ApiConstants.QNAME) @NotNull String flowNa
@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);
logger.debug(" Flow to be updated flowName:{}, source:{}", flowName, source);

String decodedFlowName = getURLDecodedValue(flowName);
log.trace(" Agama flow name for update is:{}", decodedFlowName);
logger.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);
// check if flow with same name exists
Flow existingFlow = findFlow(decodedFlowName, true, false);
logger.debug(" Agama existingFlow:{}", existingFlow);

// Update source and revision
if (existingFlow != null) {
existingFlow.setSource(source);

getRevision(existingFlow, existingFlow);
updateFlowDetails(existingFlow, existingFlow);

// validate flow data
validateAgamaFlowData(existingFlow, false);
log.debug("Update flow after validation");
logger.debug("Update flow after validation");
agamaFlowService.updateFlow(existingFlow);

existingFlow = findFlow(existingFlow.getQname(), true, false);
Expand All @@ -217,26 +208,28 @@ public Response updateFlowFromFile(@PathParam(ApiConstants.QNAME) @NotNull Strin
@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)
public Response patchFlow(@PathParam(ApiConstants.QNAME) @NotNull String flowName, @NotNull JsonPatch jsonPatch)
throws JsonPatchException, IOException, NoSuchMethodException, IllegalAccessException,
InvocationTargetException {
if (logger.isDebugEnabled()) {
logger.debug("Flow details to be patched - flowName:{}, pathString:{}", escapeLog(flowName),
escapeLog(pathString));
logger.debug("Flow details to be patched - flowName:{}, jsonPatch:{}", escapeLog(flowName),
escapeLog(jsonPatch));
}

String decodedFlowName = getURLDecodedValue(flowName);
log.trace(" Flow name for update is:{}", decodedFlowName);
logger.debug(" Flow to be patched is name:{}", decodedFlowName);

// check if flow exists
Flow existingFlow = findFlow(decodedFlowName, false, true);
log.debug(" existingFlow:{}", existingFlow);
logger.debug(" Flow to be patched:{}", existingFlow);

existingFlow = Jackson.applyPatch(pathString, existingFlow);
getRevision(existingFlow, existingFlow);
existingFlow = Jackson.applyJsonPatch(jsonPatch, existingFlow);
logger.debug(" After patch flow:{}", existingFlow);
updateFlowDetails(existingFlow, existingFlow);

// validate flow data
validateAgamaFlowData(existingFlow, false);
log.debug("Updating flow after validation");
logger.debug("Updating flow after validation");
agamaFlowService.updateFlow(existingFlow);
return Response.ok(existingFlow).build();
}
Expand All @@ -245,9 +238,9 @@ public Response patchFlow(@PathParam(ApiConstants.QNAME) @NotNull String flowNam
@Path(ApiConstants.QNAME_PATH)
@ProtectedApi(scopes = { ApiAccessConstants.AGAMA_DELETE_ACCESS })
public Response deleteAttribute(@PathParam(ApiConstants.QNAME) @NotNull String flowName) {
log.debug(" Flow to delete - flowName:{}", flowName);
logger.debug(" Flow to delete - flowName:{}", flowName);
String decodedFlowName = getURLDecodedValue(flowName);
log.trace(" Agama Decoded flow name is:{}", decodedFlowName);
logger.trace(" Agama Decoded flow name is:{}", decodedFlowName);

// check if flow exists
Flow flow = findFlow(decodedFlowName, true, false);
Expand All @@ -262,31 +255,33 @@ private Flow findFlow(String flowName, boolean throwError, boolean includeSource
flow = agamaFlowService.getFlowByName(flowName);

// filter values
List<Flow> flows = Arrays.asList(flow);
getAgamaFlowDetails(flows, includeSource);
if (flows != null && !flows.isEmpty()) {
flow = flows.get(0);
if (flow != null) {
List<Flow> 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);
logger.error("No flow found with the name:{} ", flowName);
if (throwError) {
throw new NotFoundException(getNotFoundError("Flow - " + flowName + "!!!"));
throw new NotFoundException(getNotFoundError("Flow - '" + flowName + "'"));
}
}
return flow;
}

private void validateAgamaFlowData(Flow flow, boolean checkNonMandatoryFields)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
log.debug(" Validate Agama Flow data - flow:{}, checkNonMandatoryFields:{}", flow, checkNonMandatoryFields);
logger.debug(" Validate Agama Flow data - flow:{}, checkNonMandatoryFields:{}", flow, checkNonMandatoryFields);
if (flow == null) {
return;
}
log.debug("Agama Flow to be added flow:{}, flow.getQname():{}, flow.getSource():{} ", flow, flow.getQname(),
logger.debug("Agama Flow to be added flow:{}, flow.getQname():{}, flow.getSource():{} ", flow, flow.getQname(),
flow.getSource());

String validateMsg = agamaFlowService.validateFlowFields(flow, checkNonMandatoryFields);
log.debug("Agama Flow to be validation msg:{} ", validateMsg);
logger.debug("Agama Flow to be validation msg:{} ", validateMsg);
if (StringUtils.isNotBlank(validateMsg)) {
thorwBadRequestException(validateMsg);
}
Expand All @@ -296,71 +291,105 @@ private void validateAgamaFlowData(Flow flow, boolean checkNonMandatoryFields)
}

private void validateSyntax(Flow flow) {
log.debug("Validate Flow Source Syntax - flow:{}", flow);
logger.debug("Validate Flow Source Syntax - flow:{}", flow);
if (flow == null) {
return;
}
// validate syntax
try {
Transpiler.runSyntaxCheck(flow.getQname(), flow.getSource());
} catch (SyntaxException se) {
log.error("Transpiler syntax check error", se);
logger.error("Transpiler syntax check error", se);
try {
log.debug("Throwing BadRequestException 400 :{} ", Jackson.asPrettyJson(se));
thorwBadRequestException(Jackson.asJson(se));
logger.debug("Throwing BadRequestException 400 :{} ", Jackson.asPrettyJson(se));
thorwBadRequestException(se);
} catch (IOException io) {
log.error("Agama Flow Transpiler syntax error parsing error", io);
logger.error("Agama Flow Transpiler syntax error parsing error", io);
thorwBadRequestException("Transpiler syntax check error" + se);
}
} catch (TranspilerException te) {
log.error("Agama Flow transpiler exception", te);
thorwBadRequestException(te.toString());
logger.error("Agama Flow transpiler exception", te);
thorwBadRequestException(te);
}
}

private String getURLDecodedValue(String pathParam) {
log.debug(" Decode pathParam():{} ", pathParam);
logger.debug(" Decode pathParam():{} ", pathParam);
try {
return URLDecoder.decode(pathParam, UTF_8.name());
} catch (UnsupportedEncodingException uee) {
log.error("Agama Flow error while URL decoding pathParam:{}, is:{}", pathParam, uee);
logger.error("Agama Flow error while URL decoding pathParam:{}, is:{}", pathParam, uee);
}
return pathParam;
}

private Flow getRevision(Flow flow, Flow existingFlow) {
log.debug("Flow revision check - flow:{}, existingFlow:{}", flow, existingFlow);
private Flow updateFlowDetails(Flow flow, Flow existingFlow) {
logger.debug("Update Flow details - flow:{}, existingFlow:{}", flow, existingFlow);

updateRevision(flow, existingFlow);
updateMetadata(flow);
return flow;
}

private Flow updateRevision(Flow flow, Flow existingFlow) {
logger.debug("Flow revision check - flow:{}, existingFlow:{}", flow, existingFlow);

if (flow == null) {
return flow;
}

if (flow == null || existingFlow == null) {
if (existingFlow == null) {
flow.setRevision(-1);
return flow;
}

log.debug("Flow revision check - flow.getRevision():{}, existingFlow.getRevision():{}", flow.getRevision(),
existingFlow.getRevision());
logger.trace("Flow revision before update - flow.getRevision():{}, existingFlow.getRevision():{}",
flow.getRevision(), existingFlow.getRevision());

if (flow.getSource() != null && flow.getRevision() == 0) {
if (existingFlow.getRevision() == 0 || existingFlow.getRevision() == -1) {
if (flow.getSource() != null && (flow.getRevision() <= 0 || flow.getRevision() == existingFlow.getRevision())) {
if (existingFlow.getRevision() <= 0) {
flow.setRevision(1);
} else {
flow.setRevision(existingFlow.getRevision() + 1);
}
}
log.debug("Final flow revision to be updated to - flow.getRevision():{}", flow.getRevision());
logger.trace("Flow revision after update - flow.getRevision():{}", flow.getRevision());
return flow;
}

private Flow updateMetadata(Flow flow) {
logger.debug("Update Flow Metadata - flow:{}", flow);

if (flow == null) {
return flow;
}

FlowMetadata flowMetadata = flow.getMetadata();
if (flowMetadata == null) {
flowMetadata = new FlowMetadata();
}

logger.trace("Flow Metadata Timestamp before update - flowMetadata.getTimestamp():{}",
flowMetadata.getTimestamp());
flowMetadata.setTimestamp(System.currentTimeMillis());
flow.setMetadata(flowMetadata);

logger.trace("Flow Metadata Timestamp after update - flowMetadata.getTimestamp():{}",
flowMetadata.getTimestamp());
return flow;
}

private List<Flow> getAgamaFlowDetails(List<Flow> flows, boolean includeSource) {

log.debug("Flow data filter - flows:{}, includeSource:{}", flows, includeSource);
logger.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);
}
Expand Down
Loading