-
Notifications
You must be signed in to change notification settings - Fork 33
Add issue get command for FoD and SSC #978
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
base: dev/v3.x
Are you sure you want to change the base?
Changes from 1 commit
ca7f542
6b40ff9
6ada3b4
f945c6f
4c69521
ebfd029
cd0d1c9
9353886
c81fe68
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| /* | ||
| * Copyright 2021-2026 Open Text. | ||
| * | ||
| * The only warranties for products and services of Open Text | ||
| * and its affiliates and licensors ("Open Text") are as may | ||
| * be set forth in the express warranty statements accompanying | ||
| * such products and services. Nothing herein should be construed | ||
| * as constituting an additional warranty. Open Text shall not be | ||
| * liable for technical or editorial errors or omissions contained | ||
| * herein. The information contained herein is subject to change | ||
| * without notice. | ||
| */ | ||
| package com.fortify.cli.fod.issue.cli.cmd; | ||
|
|
||
| import com.fasterxml.jackson.databind.JsonNode; | ||
| import com.fortify.cli.common.exception.FcliSimpleException; | ||
| import com.fortify.cli.common.json.producer.IObjectNodeProducer; | ||
| import com.fortify.cli.common.json.producer.ObjectNodeProducerApplyFrom; | ||
| import com.fortify.cli.common.output.cli.mixin.OutputHelperMixins; | ||
| import com.fortify.cli.common.util.DisableTest; | ||
| import com.fortify.cli.common.util.DisableTest.TestType; | ||
| import com.fortify.cli.fod._common.cli.mixin.FoDDelimiterMixin; | ||
| import com.fortify.cli.fod._common.output.cli.cmd.AbstractFoDOutputCommand; | ||
| import com.fortify.cli.fod._common.rest.FoDUrls; | ||
| import com.fortify.cli.fod._common.rest.helper.FoDInputTransformer; | ||
| import com.fortify.cli.fod.issue.cli.mixin.FoDIssueEmbedMixin; | ||
| import com.fortify.cli.fod.issue.cli.mixin.FoDIssueIncludeMixin; | ||
| import com.fortify.cli.fod.release.cli.mixin.FoDReleaseByQualifiedNameOrIdResolverMixin; | ||
|
|
||
| import kong.unirest.HttpRequest; | ||
| import kong.unirest.UnirestInstance; | ||
| import lombok.Getter; | ||
| import picocli.CommandLine.Command; | ||
| import picocli.CommandLine.Mixin; | ||
| import picocli.CommandLine.Parameters; | ||
|
|
||
| @DisableTest(TestType.CMD_DEFAULT_TABLE_OPTIONS_PRESENT) | ||
| @Command(name = OutputHelperMixins.Get.CMD_NAME) | ||
| public class FoDIssueGetCommand extends AbstractFoDOutputCommand { | ||
| @Getter @Mixin private OutputHelperMixins.Get outputHelper; | ||
| @Mixin private FoDDelimiterMixin delimiterMixin; // Is automatically injected in resolver mixins | ||
| @Mixin private FoDReleaseByQualifiedNameOrIdResolverMixin.RequiredOption releaseResolver; | ||
| @Parameters(index = "0", arity = "1", descriptionKey = "fcli.fod.issue.get.id") | ||
| private String vulnId; | ||
| @Mixin private FoDIssueEmbedMixin embedMixin; | ||
| @Mixin private FoDIssueIncludeMixin includeMixin; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, same is true here as what I wrote for SSC. Although (contrary to SSC) the FoD endpoint used by this command does support the query parameters generated
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To confirm my understanding the fix here would be to remove the [--include] option from the [get] command and hardcode includeFixed=true and includeSuppressed=true in [findIssue()] for both ssc and fod, so that any issue can be retrieved by ID regardless of its state, without requiring the user to pass extra flags. Is that what you're expecting?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct for FoD; you'd always add the request parameters to have FoD return fixed/suppressed/... issues, such that FoD will return the issue data for the requested id independent of whether it's visible, fixed, suppressed, ... For SSC, you're using an endpoint to get the issue data for a specific issue id. This endpoint will return that data independent of whether the issue is hidden/removed/suppressed; the endpoint doesn't support the request parameters generated by the |
||
|
|
||
| @Override | ||
| protected IObjectNodeProducer getObjectNodeProducer(UnirestInstance unirest) { | ||
| String releaseId = releaseResolver.getReleaseId(unirest); | ||
| JsonNode issue = getIssue(unirest, releaseId); | ||
| return simpleObjectNodeProducerBuilder(ObjectNodeProducerApplyFrom.SPEC) | ||
| .source(issue) | ||
| .build(); | ||
| } | ||
|
|
||
| private JsonNode getIssue(UnirestInstance unirest, String releaseId) { | ||
| boolean numericId = vulnId!=null && vulnId.chars().allMatch(Character::isDigit); | ||
| JsonNode issue = numericId | ||
|
jmadhur87 marked this conversation as resolved.
Outdated
|
||
| ? getIssueByFilter(unirest, releaseId, "id", vulnId) | ||
| : getIssueByFilter(unirest, releaseId, "vulnId", vulnId); | ||
| if ( issue==null ) { | ||
| issue = numericId | ||
| ? getIssueByFilter(unirest, releaseId, "vulnId", vulnId) | ||
| : getIssueByFilter(unirest, releaseId, "id", vulnId); | ||
| } | ||
| if ( issue==null ) { | ||
| throw new FcliSimpleException(String.format("No issue found for id or vulnId '%s' in the specified release", vulnId)); | ||
| } | ||
| return issue; | ||
| } | ||
|
|
||
| private JsonNode getIssueByFilter(UnirestInstance unirest, String releaseId, String fieldName, String value) { | ||
| HttpRequest<?> request = unirest.get(FoDUrls.VULNERABILITIES) | ||
| .routeParam("relId", releaseId) | ||
| .queryString("filters", fieldName+":"+value) | ||
| .queryString("limit", "1"); | ||
|
jmadhur87 marked this conversation as resolved.
Outdated
jmadhur87 marked this conversation as resolved.
Outdated
|
||
| JsonNode body = includeMixin.updateRequest(request).asObject(JsonNode.class).getBody(); | ||
| JsonNode items = FoDInputTransformer.getItems(body); | ||
| return items!=null && items.isArray() && !items.isEmpty() ? items.get(0) : null; | ||
|
jmadhur87 marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| @Override | ||
| public boolean isSingular() { | ||
| return true; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| /* | ||
| * Copyright 2021-2026 Open Text. | ||
| * | ||
| * The only warranties for products and services of Open Text | ||
| * and its affiliates and licensors ("Open Text") are as may | ||
| * be set forth in the express warranty statements accompanying | ||
| * such products and services. Nothing herein should be construed | ||
| * as constituting an additional warranty. Open Text shall not be | ||
| * liable for technical or editorial errors or omissions contained | ||
| * herein. The information contained herein is subject to change | ||
| * without notice. | ||
| */ | ||
| package com.fortify.cli.ssc.issue.cli.cmd; | ||
|
|
||
| import com.fortify.cli.common.json.producer.IObjectNodeProducer; | ||
| import com.fortify.cli.common.json.producer.ObjectNodeProducerApplyFrom; | ||
| import com.fortify.cli.common.output.cli.mixin.OutputHelperMixins; | ||
| import com.fortify.cli.ssc._common.output.cli.cmd.AbstractSSCOutputCommand; | ||
| import com.fortify.cli.ssc._common.rest.ssc.SSCUrls; | ||
| import com.fortify.cli.ssc.appversion.cli.mixin.SSCAppVersionResolverMixin; | ||
| import com.fortify.cli.ssc.issue.cli.mixin.SSCIssueBulkEmbedMixin; | ||
| import com.fortify.cli.ssc.issue.cli.mixin.SSCIssueIncludeMixin; | ||
|
|
||
| import kong.unirest.HttpRequest; | ||
| import kong.unirest.UnirestInstance; | ||
| import lombok.Getter; | ||
| import picocli.CommandLine.Command; | ||
| import picocli.CommandLine.Mixin; | ||
| import picocli.CommandLine.Parameters; | ||
|
|
||
| @Command(name = OutputHelperMixins.Get.CMD_NAME) | ||
| public class SSCIssueGetCommand extends AbstractSSCOutputCommand { | ||
| @Getter @Mixin private OutputHelperMixins.Get outputHelper; | ||
| @Mixin private SSCAppVersionResolverMixin.RequiredOption parentResolver; | ||
| @Parameters(index = "0", arity = "1", descriptionKey = "fcli.ssc.issue.get.id") | ||
| private String id; | ||
| @Mixin private SSCIssueBulkEmbedMixin bulkEmbedMixin; | ||
| @Mixin private SSCIssueIncludeMixin includeMixin; | ||
|
jmadhur87 marked this conversation as resolved.
Outdated
|
||
|
|
||
| @Override | ||
| protected IObjectNodeProducer getObjectNodeProducer(UnirestInstance unirest) { | ||
| String appVersionId = parentResolver.getAppVersionId(unirest); | ||
| return requestObjectNodeProducerBuilder(ObjectNodeProducerApplyFrom.SPEC) | ||
| .baseRequest(getBaseRequest(unirest, appVersionId)) | ||
| .build(); | ||
| } | ||
|
|
||
| private HttpRequest<?> getBaseRequest(UnirestInstance unirest, String appVersionId) { | ||
| return unirest.get(SSCUrls.PROJECT_VERSION_ISSUE(appVersionId, id)).queryString("qm", "issues"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please double-check, but I think Also, we could consider using the issueDetails endpoint instead as that doesn't require application version to be specified (thereby simplifying CLI usage), but output of that endpoint is not the same as what we return on the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Verified the SSC api reference , query parameter is available for this endpoint.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Code still shows |
||
| } | ||
|
|
||
| @Override | ||
| public boolean isSingular() { | ||
| return true; | ||
| } | ||
| } | ||

Uh oh!
There was an error while loading. Please reload this page.