From c2a3d29881b47ffa72d6cea898ae9861eaa66b71 Mon Sep 17 00:00:00 2001 From: content-bot <55035720+content-bot@users.noreply.github.com> Date: Mon, 4 Sep 2023 16:55:25 +0300 Subject: [PATCH] [Jira] Added support for arguments jira-get-organizations (#29420) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Jira] Added support for arguments jira-get-organizations (#29217) * master * reverting crowdstrike.py * get_organization modification * added release notes * bumped version * updated docker image * Update Packs/Jira/Integrations/JiraV2/JiraV2.py Co-authored-by: Michael Yochpaz <8832013+MichaelYochpaz@users.noreply.github.com> * Update Packs/Jira/Integrations/JiraV2/JiraV2.py Co-authored-by: Michael Yochpaz <8832013+MichaelYochpaz@users.noreply.github.com> * Update Packs/Jira/Integrations/JiraV2/JiraV2.py Co-authored-by: Michael Yochpaz <8832013+MichaelYochpaz@users.noreply.github.com> * added more descriptive release note * updated docker image * Update Packs/Jira/Integrations/JiraV2/JiraV2.yml Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com> * Update Packs/Jira/ReleaseNotes/3_0_12.md Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com> * Update Packs/Jira/ReleaseNotes/3_0_12.md Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com> * comments * mixed errors * fixed issue * code improvements * improved the documentation --------- Co-authored-by: Michael Yochpaz <8832013+MichaelYochpaz@users.noreply.github.com> Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com> * Minor fixes & improvements * Pre-commit * Add a message for empty results * Improve readable output --------- Co-authored-by: Enes Ă–zdemir <49711791+ennozdd@users.noreply.github.com> Co-authored-by: Michael Yochpaz <8832013+MichaelYochpaz@users.noreply.github.com> Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com> --- Packs/Jira/Integrations/JiraV2/JiraV2.py | 61 ++++++++++++++++------- Packs/Jira/Integrations/JiraV2/JiraV2.yml | 18 ++++++- Packs/Jira/ReleaseNotes/3_0_12.md | 10 ++++ Packs/Jira/pack_metadata.json | 4 +- 4 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 Packs/Jira/ReleaseNotes/3_0_12.md diff --git a/Packs/Jira/Integrations/JiraV2/JiraV2.py b/Packs/Jira/Integrations/JiraV2/JiraV2.py index d7d65535eb92..4faf34114118 100644 --- a/Packs/Jira/Integrations/JiraV2/JiraV2.py +++ b/Packs/Jira/Integrations/JiraV2/JiraV2.py @@ -2,8 +2,6 @@ from CommonServerPython import * # noqa: F401 -from typing import Union, Optional - from requests_oauthlib import OAuth1 from dateparser import parse from datetime import timedelta @@ -48,9 +46,9 @@ def jira_req( body: str = '', link: bool = False, resp_type: str = 'text', - headers: Optional[dict] = None, - files: Optional[dict] = None, - params: Optional[dict] = None + headers: dict | None = None, + files: dict | None = None, + params: dict | None = None ): url = resource_url if link else (BASE_URL + resource_url) AUTH = get_auth() @@ -76,9 +74,15 @@ def jira_req( try: rj = result.json() if rj.get('errorMessages'): - raise DemistoException(f'Status code: {result.status_code}\nMessage: {",".join(rj["errorMessages"])}') - elif rj.get('errors'): - raise DemistoException(f'Status code: {result.status_code}\nMessage: {",".join(rj["errors"].values())}') + raise DemistoException(f'Status code: {result.status_code}\nMessages: {", ".join(rj["errorMessages"])}') + elif errors := rj.get('errors'): + error_messages = [] + if isinstance(errors, list): + for error in errors: + error_messages.append(", ".join(error.values())) + else: + error_messages.append(", ".join(errors.values())) + raise DemistoException(f'Status code: {result.status_code}\nMessages: {error_messages}') else: raise DemistoException(f'Status code: {result.status_code}\nError text: {result.text}') except ValueError as ve: @@ -130,7 +134,7 @@ def get_auth(): elif is_bearer: # Personal Access Token Authentication HEADERS.update({'Authorization': f'Bearer {access_token}'}) - return + return None return_error( 'Please provide the required Authorization information:' @@ -138,6 +142,7 @@ def get_auth(): '- OAuth 1.0 requires ConsumerKey, AccessToken and PrivateKey' '- Personal Access Tokens requires AccessToken' ) + return None def get_custom_field_names(): @@ -264,6 +269,8 @@ def expand_urls(data, depth=0): else: if isinstance(value, dict): return expand_urls(value, depth + 1) + return None + return None def search_user(query: str, max_results: str = '50', is_jirav2api: bool = False): @@ -295,7 +302,7 @@ def search_user(query: str, max_results: str = '50', is_jirav2api: bool = False) def get_account_id_from_attribute( attribute: str, max_results: str = '50', - is_jirav2api: str = 'false') -> Union[CommandResults, str]: + is_jirav2api: str = 'false') -> CommandResults | str: """ https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-user-search/#api-rest-api-3-user-search-get @@ -577,6 +584,7 @@ def get_project_id(project_key='', project_name=''): return project.get('id') return_error('Project not found') + return None def get_issue_fields(issue_creating=False, mirroring=False, **issue_args): @@ -835,11 +843,28 @@ def _update_fields(issue_id, new_data): jira_req('PUT', url, json.dumps({'fields': new_data})) -def get_organizations_command(): - url = '/rest/servicedeskapi/organization' - res = jira_req('GET', url, resp_type='json').get('values') - [org.pop('_links') for org in res] - return CommandResults(outputs=res, outputs_prefix='Jira.Organizations') +def get_organizations_command(project_key=None, start="0", limit="50", account_id=None): + if project_key: + url = f'/rest/servicedeskapi/servicedesk/{project_key}/organization' + else: + url = '/rest/servicedeskapi/organization' + body = { + 'start': arg_to_number(start), + 'limit': arg_to_number(limit), + } + + if account_id: + body['accountId'] = account_id + + if response := jira_req('GET', url, params=body, resp_type='json').get('values'): + [org.pop('_links') for org in response] + + hr = tableToMarkdown(name='Organizations', t=response, headers=['name', 'id', 'created'], + json_transform_mapping={'created': JsonTransformer(func=lambda x: x.get('friendly'))}) + + return CommandResults(outputs=response, outputs_prefix='Jira.Organizations', outputs_key_field='id', readable_output=hr) + + return CommandResults(readable_output='No results found.') def get_field_command(issue_id, field): @@ -891,6 +916,7 @@ def edit_status(issue_id, status, issue): return jira_req('POST', url, json.dumps(issue)) return_error(f'Status "{status}" not found. \nValid statuses are: {statuses} \n') + return None def list_transitions_data_for_issue(issue_id): @@ -921,6 +947,7 @@ def edit_transition(issue_id, transition_name, issue): return jira_req('POST', url, json.dumps(issue)) return_error(f'Transitions "{transition_name}" not found. \nValid transitions are: {transitions_data} \n') + return None def list_transitions_command(args): @@ -1322,7 +1349,7 @@ def update_remote_system_command(args): demisto.debug(f'Got the following delta keys {str(list(remote_args.delta.keys()))} to update Jira ' f'incident {remote_id}') # take the val from data as it's the updated value - delta = {k: remote_args.data.get(k) for k in remote_args.delta.keys()} + delta = {k: remote_args.data.get(k) for k in remote_args.delta} demisto.debug(f'sending the following data to edit the issue with: {delta}') edit_issue_command(remote_id, mirroring=True, **delta) @@ -1567,7 +1594,7 @@ def main(): return_results(get_account_id_from_attribute(**demisto.args())) elif demisto.command() == 'jira-get-organizations': - return_results(get_organizations_command()) + return_results(get_organizations_command(**snakify(demisto.args()))) elif demisto.command() == 'jira-list-transitions': return_results(list_transitions_command(demisto.args())) diff --git a/Packs/Jira/Integrations/JiraV2/JiraV2.yml b/Packs/Jira/Integrations/JiraV2/JiraV2.yml index fecb624b4b29..f0d7f3e3ca2b 100644 --- a/Packs/Jira/Integrations/JiraV2/JiraV2.yml +++ b/Packs/Jira/Integrations/JiraV2/JiraV2.yml @@ -553,7 +553,21 @@ script: name: role_name description: Adds the user to a project. name: jira-add-user-to-project - - arguments: [] + - arguments: + - description: An ID or key for a service project to list all organizations associated with. + name: projectKey + required: false + - description: Start index for the returned objects. 0 by default. + name: start + required: false + defaultValue: "0" + - description: Maximum amount of organizations to list. 50 by default. + name: limit + required: false + defaultValue: "50" + - description: Account ID of the user, which uniquely identifies the user across all Atlassian products. For example, 5b10ac8d82e05b22cc7d4ef5. + name: accountId + required: false description: Lists all the organizations. name: jira-get-organizations - arguments: @@ -585,7 +599,7 @@ script: - contextPath: Ticket.Status description: The ticket status. type: String - dockerimage: demisto/oauthlib:1.0.0.63821 + dockerimage: demisto/oauthlib:1.0.0.72372 isfetch: true ismappable: true isremotesyncin: true diff --git a/Packs/Jira/ReleaseNotes/3_0_12.md b/Packs/Jira/ReleaseNotes/3_0_12.md new file mode 100644 index 000000000000..bb8125912216 --- /dev/null +++ b/Packs/Jira/ReleaseNotes/3_0_12.md @@ -0,0 +1,10 @@ + +#### Integrations + +##### Atlassian Jira v2 + +Added support for additional arguments in the ***jira-get-organizations*** command: + * *projectKey*: An ID or key for a service project to list all organizations associated with. + * *start*: Start index for the returned objects. 0 by default. + * *limit*: Maximum amount of organizations to list. 50 by default. + * *accountId*: Account ID of the user, which uniquely identifies the user across all Atlassian products. For example, 5b10ac8d82e05b22cc7d4ef5. diff --git a/Packs/Jira/pack_metadata.json b/Packs/Jira/pack_metadata.json index 18bdac7f40eb..9eff5b50b642 100644 --- a/Packs/Jira/pack_metadata.json +++ b/Packs/Jira/pack_metadata.json @@ -2,7 +2,7 @@ "name": "Atlassian Jira", "description": "Use the Jira integration to manage issues and create Cortex XSOAR incidents from Jira projects.", "support": "xsoar", - "currentVersion": "3.0.11", + "currentVersion": "3.0.12", "author": "Cortex XSOAR", "url": "https://www.paloaltonetworks.com/cortex", "email": "", @@ -21,4 +21,4 @@ "marketplacev2", "xpanse" ] -} \ No newline at end of file +}