Skip to content

Commit

Permalink
[Jira] Added support for arguments jira-get-organizations (#29420)
Browse files Browse the repository at this point in the history
* [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>
  • Loading branch information
4 people authored and moishce committed Sep 14, 2023
1 parent 1623fe5 commit c2a3d29
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 21 deletions.
61 changes: 44 additions & 17 deletions Packs/Jira/Integrations/JiraV2/JiraV2.py
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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:
Expand Down Expand Up @@ -130,14 +134,15 @@ 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:'
'- Basic Authentication requires user name and password or API token'
'- OAuth 1.0 requires ConsumerKey, AccessToken and PrivateKey'
'- Personal Access Tokens requires AccessToken'
)
return None


def get_custom_field_names():
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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()))
Expand Down
18 changes: 16 additions & 2 deletions Packs/Jira/Integrations/JiraV2/JiraV2.yml
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions 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.
4 changes: 2 additions & 2 deletions Packs/Jira/pack_metadata.json
Expand Up @@ -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": "",
Expand All @@ -21,4 +21,4 @@
"marketplacev2",
"xpanse"
]
}
}

0 comments on commit c2a3d29

Please sign in to comment.