diff --git a/apiserver/plane/utils/importers/jira.py b/apiserver/plane/utils/importers/jira.py index 3081096feb7..5e8c31f97ce 100644 --- a/apiserver/plane/utils/importers/jira.py +++ b/apiserver/plane/utils/importers/jira.py @@ -1,53 +1,89 @@ import requests +import re from requests.auth import HTTPBasicAuth from sentry_sdk import capture_exception +from urllib.parse import urlparse, urljoin -from urllib.parse import urlparse def is_allowed_hostname(hostname): - allowed_lists = ["atl-paas.net", "atlassian.com", "atlassian.net", "jira.com"] - # Extract the base domain from the hostname - parsed_uri = urlparse(f"https://{hostname}") # Add scheme for urlparse to work properly - domain = parsed_uri.netloc.split(":")[0] # Removes port number if included - base_domain = ".".join(domain.split(".")[-2:]) # Extract base domain + allowed_domains = ["atl-paas.net", "atlassian.com", "atlassian.net", "jira.com"] + parsed_uri = urlparse(f"https://{hostname}") + domain = parsed_uri.netloc.split(":")[0] # Ensures no port is included + base_domain = ".".join(domain.split(".")[-2:]) + return base_domain in allowed_domains - # Check if the base domain is in the allowed list - return base_domain in allowed_lists + +def is_valid_project_key(project_key): + if project_key: + project_key = project_key.strip().upper() + # Adjust the regular expression as needed based on your specific requirements. + if len(project_key) > 30: + return False + # Check the validity of the key as well + pattern = re.compile(r'^[A-Z0-9]{1,10}$') + return pattern.match(project_key) is not None + else: + False + +def generate_valid_project_key(project_key): + return project_key.strip().upper() + +def generate_url(hostname, path): + if not is_allowed_hostname(hostname): + raise ValueError("Invalid or unauthorized hostname") + return urljoin(f"https://{hostname}", path) def jira_project_issue_summary(email, api_token, project_key, hostname): try: - - if not is_allowed_hostname(hostname): - print("Errored Hostname") return {"error": "Invalid or unauthorized hostname"} + if not is_valid_project_key(project_key): + return {"error": "Invalid project key"} + auth = HTTPBasicAuth(email, api_token) headers = {"Accept": "application/json"} + + # make the project key upper case + project_key = generate_valid_project_key(project_key) - issue_url = f"https://{hostname}/rest/api/3/search?jql=project={project_key} AND issuetype!=Epic" + # issues + issue_url = generate_url( + hostname, + f"/rest/api/3/search?jql=project={project_key} AND issuetype!=Epic", + ) issue_response = requests.request( "GET", issue_url, headers=headers, auth=auth ).json()["total"] - module_url = f"https://{hostname}/rest/api/3/search?jql=project={project_key} AND issuetype=Epic" + # modules + module_url = generate_url( + hostname, f"/rest/api/3/search?jql=project={project_key} AND issuetype=Epic" + ) module_response = requests.request( "GET", module_url, headers=headers, auth=auth ).json()["total"] - status_url = f"https://{hostname}/rest/api/3/project/${project_key}/statuses" + # status + status_url = generate_url( + hostname, f"/rest/api/3/project/${project_key}/statuses" + ) status_response = requests.request( "GET", status_url, headers=headers, auth=auth ).json() - labels_url = f"https://{hostname}/rest/api/3/label/?jql=project={project_key}" + # labels + labels_url = generate_url( + hostname, f"/rest/api/3/label/?jql=project={project_key}" + ) labels_response = requests.request( "GET", labels_url, headers=headers, auth=auth ).json()["total"] - users_url = ( - f"https://{hostname}/rest/api/3/users/search?jql=project={project_key}" + # users + users_url = generate_url( + hostname, f"/rest/api/3/users/search?jql=project={project_key}" ) users_response = requests.request( "GET", users_url, headers=headers, auth=auth