From 62358c15728a8f56bb11ffac572b6d90f8a08ed9 Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Mon, 9 Jun 2025 09:24:59 -0700 Subject: [PATCH 1/3] Added license metadata endpoint --- socketdev/__init__.py | 2 + socketdev/licensemetadata/__init__.py | 67 +++++++++++++++++++++++++++ socketdev/version.py | 2 +- 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 socketdev/licensemetadata/__init__.py diff --git a/socketdev/__init__.py b/socketdev/__init__.py index beddeea..dbe491b 100644 --- a/socketdev/__init__.py +++ b/socketdev/__init__.py @@ -17,6 +17,7 @@ from socketdev.utils import Utils, IntegrationType, INTEGRATION_TYPES from socketdev.version import __version__ from socketdev.labels import Labels +from socketdev.licensemetadata import LicenseMetadata from socketdev.log import log @@ -59,6 +60,7 @@ def __init__(self, token: str, timeout: int = 1200): self.triage = Triage(self.api) self.utils = Utils() self.labels = Labels(self.api) + self.licensemetadata = LicenseMetadata(self.api) @staticmethod def set_timeout(timeout: int): diff --git a/socketdev/licensemetadata/__init__.py b/socketdev/licensemetadata/__init__.py new file mode 100644 index 0000000..670eb3f --- /dev/null +++ b/socketdev/licensemetadata/__init__.py @@ -0,0 +1,67 @@ +import json +import logging + + +log = logging.getLogger("socketdev") + + +class LicenseMetadata: + def __init__(self, api): + self.api = api + + def post(self, licenses: list) -> dict: + path = f"license-metadata" + payload = json.dumps(licenses) + response = self.api.do_request(path=path, method="POST", payload=payload) + + if response.status_code == 200: + result = response.json() + return result + + error_message = response.json().get("error", {}).get("message", "Unknown error") + log.error(f"Failed to create license metadata: {response.status_code}, message: {error_message}") + return {} + + def get(self, org_slug: str, label_id: str) -> dict: + path = f"orgs/{org_slug}/repos/labels/{label_id}" + response = self.api.do_request(path=path) + if response.status_code == 200: + result = response.json() + return result + + error_message = response.json().get("error", {}).get("message", "Unknown error") + log.error(f"Failed to get repository label: {response.status_code}, message: {error_message}") + return {} + + def delete(self, org_slug: str, label_id: str) -> dict: + path = f"orgs/{org_slug}/repos/labels/{label_id}" + response = self.api.do_request(path=path, method="DELETE") + if response.status_code == 200: + return response.json() + + error_message = response.json().get("error", {}).get("message", "Unknown error") + log.error(f"Error deleting repository label: {response.status_code}, message: {error_message}") + return {} + + + def associate(self, org_slug: str, label_id: int, repo_id: str) -> dict: + path = f"orgs/{org_slug}/repos/labels/{label_id}/associate" + payload = json.dumps({"repository_id": repo_id}) + response = self.api.do_request(path=path, method="POST", payload=payload) + if response.status_code == 200: + return response.json() + + error_message = response.json().get("error", {}).get("message", "Unknown error") + log.error(f"Error associating repository label: {response.status_code}, message: {error_message}") + return {} + + def disassociate(self, org_slug: str, label_id: int, repo_id: str) -> dict: + path = f"orgs/{org_slug}/repos/labels/{label_id}/disassociate" + payload = json.dumps({"repository_id": repo_id}) + response = self.api.do_request(path=path, method="POST", payload=payload) + if response.status_code == 200: + return response.json() + + error_message = response.json().get("error", {}).get("message", "Unknown error") + log.error(f"Error associating repository label: {response.status_code}, message: {error_message}") + return {} diff --git a/socketdev/version.py b/socketdev/version.py index 9aa3f90..4eabd0b 100644 --- a/socketdev/version.py +++ b/socketdev/version.py @@ -1 +1 @@ -__version__ = "2.1.0" +__version__ = "2.1.2" From f27ae63a5cff76cd9b34e146f6a232f1825e30cb Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Mon, 9 Jun 2025 15:12:22 -0700 Subject: [PATCH 2/3] Fixed debug output --- socketdev/core/dedupe.py | 3 +- socketdev/export/__init__.py | 4 +-- socketdev/labels/__init__.py | 4 +-- socketdev/licensemetadata/__init__.py | 50 +++------------------------ socketdev/npm/__init__.py | 4 +-- socketdev/openapi/__init__.py | 2 +- socketdev/org/__init__.py | 2 +- socketdev/purl/__init__.py | 2 +- socketdev/quota/__init__.py | 2 +- socketdev/report/__init__.py | 10 +++--- socketdev/repos/__init__.py | 2 +- socketdev/repositories/__init__.py | 2 +- socketdev/sbom/__init__.py | 4 +-- socketdev/settings/__init__.py | 2 +- 14 files changed, 27 insertions(+), 66 deletions(-) diff --git a/socketdev/core/dedupe.py b/socketdev/core/dedupe.py index 0dc3bfc..1c285cf 100644 --- a/socketdev/core/dedupe.py +++ b/socketdev/core/dedupe.py @@ -1,5 +1,6 @@ from collections import defaultdict from typing import Dict, List, Any +from socketdev.log import log class Dedupe: @@ -100,5 +101,5 @@ def consolidate_by_order(packages: List[Dict[str, Any]]) -> dict[int, list[dict[ pkg["batchIndex"] = batch_index grouped[pkg["batchIndex"]].append(pkg) except Exception as error: - print(error) + log.error(error) return grouped \ No newline at end of file diff --git a/socketdev/export/__init__.py b/socketdev/export/__init__.py index 19c04e1..8f27117 100644 --- a/socketdev/export/__init__.py +++ b/socketdev/export/__init__.py @@ -47,7 +47,7 @@ def cdx_bom( # TODO: Add typed response when types are defined log.error(f"Error exporting CDX BOM: {response.status_code}") - print(response.text) + log.error(response.text) return {} def spdx_bom( @@ -71,5 +71,5 @@ def spdx_bom( # TODO: Add typed response when types are defined log.error(f"Error exporting SPDX BOM: {response.status_code}") - print(response.text) + log.error(response.text) return {} diff --git a/socketdev/labels/__init__.py b/socketdev/labels/__init__.py index 74aa69b..2f0c2d1 100644 --- a/socketdev/labels/__init__.py +++ b/socketdev/labels/__init__.py @@ -73,7 +73,7 @@ def post(self, org_slug: str, label_name: str) -> dict: return result error_message = response.json().get("error", {}).get("message", "Unknown error") - print(f"Failed to create repository label: {response.status_code}, message: {error_message}") + log.error(f"Failed to create repository label: {response.status_code}, message: {error_message}") return {} def get(self, org_slug: str, label_id: str) -> dict: @@ -84,7 +84,7 @@ def get(self, org_slug: str, label_id: str) -> dict: return result error_message = response.json().get("error", {}).get("message", "Unknown error") - print(f"Failed to get repository label: {response.status_code}, message: {error_message}") + log.error(f"Failed to get repository label: {response.status_code}, message: {error_message}") return {} def delete(self, org_slug: str, label_id: str) -> dict: diff --git a/socketdev/licensemetadata/__init__.py b/socketdev/licensemetadata/__init__.py index 670eb3f..898d091 100644 --- a/socketdev/licensemetadata/__init__.py +++ b/socketdev/licensemetadata/__init__.py @@ -1,6 +1,6 @@ import json import logging - +import urllib.parse log = logging.getLogger("socketdev") @@ -9,8 +9,11 @@ class LicenseMetadata: def __init__(self, api): self.api = api - def post(self, licenses: list) -> dict: + def post(self, licenses: list, params: dict = None) -> dict: path = f"license-metadata" + if params: + query_args = urllib.parse.urlencode(params) + path += f"?{query_args}" payload = json.dumps(licenses) response = self.api.do_request(path=path, method="POST", payload=payload) @@ -22,46 +25,3 @@ def post(self, licenses: list) -> dict: log.error(f"Failed to create license metadata: {response.status_code}, message: {error_message}") return {} - def get(self, org_slug: str, label_id: str) -> dict: - path = f"orgs/{org_slug}/repos/labels/{label_id}" - response = self.api.do_request(path=path) - if response.status_code == 200: - result = response.json() - return result - - error_message = response.json().get("error", {}).get("message", "Unknown error") - log.error(f"Failed to get repository label: {response.status_code}, message: {error_message}") - return {} - - def delete(self, org_slug: str, label_id: str) -> dict: - path = f"orgs/{org_slug}/repos/labels/{label_id}" - response = self.api.do_request(path=path, method="DELETE") - if response.status_code == 200: - return response.json() - - error_message = response.json().get("error", {}).get("message", "Unknown error") - log.error(f"Error deleting repository label: {response.status_code}, message: {error_message}") - return {} - - - def associate(self, org_slug: str, label_id: int, repo_id: str) -> dict: - path = f"orgs/{org_slug}/repos/labels/{label_id}/associate" - payload = json.dumps({"repository_id": repo_id}) - response = self.api.do_request(path=path, method="POST", payload=payload) - if response.status_code == 200: - return response.json() - - error_message = response.json().get("error", {}).get("message", "Unknown error") - log.error(f"Error associating repository label: {response.status_code}, message: {error_message}") - return {} - - def disassociate(self, org_slug: str, label_id: int, repo_id: str) -> dict: - path = f"orgs/{org_slug}/repos/labels/{label_id}/disassociate" - payload = json.dumps({"repository_id": repo_id}) - response = self.api.do_request(path=path, method="POST", payload=payload) - if response.status_code == 200: - return response.json() - - error_message = response.json().get("error", {}).get("message", "Unknown error") - log.error(f"Error associating repository label: {response.status_code}, message: {error_message}") - return {} diff --git a/socketdev/npm/__init__.py b/socketdev/npm/__init__.py index 55abd90..d26dc86 100644 --- a/socketdev/npm/__init__.py +++ b/socketdev/npm/__init__.py @@ -15,7 +15,7 @@ def issues(self, package: str, version: str) -> list: if response.status_code == 200: return response.json() log.error(f"Error getting npm issues: {response.status_code}") - print(response.text) + log.error(response.text) return [] def score(self, package: str, version: str) -> list: @@ -24,5 +24,5 @@ def score(self, package: str, version: str) -> list: if response.status_code == 200: return response.json() log.error(f"Error getting npm score: {response.status_code}") - print(response.text) + log.error(response.text) return [] diff --git a/socketdev/openapi/__init__.py b/socketdev/openapi/__init__.py index 96f7fa9..70854ba 100644 --- a/socketdev/openapi/__init__.py +++ b/socketdev/openapi/__init__.py @@ -15,5 +15,5 @@ def get(self) -> dict: if response.status_code == 200: return response.json() log.error(f"Error getting OpenAPI spec: {response.status_code}") - print(response.text) + log.error(response.text) return {} diff --git a/socketdev/org/__init__.py b/socketdev/org/__init__.py index d59aa0a..20a02dc 100644 --- a/socketdev/org/__init__.py +++ b/socketdev/org/__init__.py @@ -30,5 +30,5 @@ def get(self, use_types: bool = False) -> OrganizationsResponse: return OrganizationsResponse(result) return result log.error(f"Error getting organizations: {response.status_code}") - print(response.text) + log.error(response.text) return {"organizations": {}} diff --git a/socketdev/purl/__init__.py b/socketdev/purl/__init__.py index 0d7a570..659a562 100644 --- a/socketdev/purl/__init__.py +++ b/socketdev/purl/__init__.py @@ -37,5 +37,5 @@ def post(self, license: str = "false", components: list = None, **kwargs) -> lis return purl_deduped log.error(f"Error posting {components} to the Purl API: {response.status_code}") - print(response.text) + log.error(response.text) return [] diff --git a/socketdev/quota/__init__.py b/socketdev/quota/__init__.py index bd3269f..2fc797a 100644 --- a/socketdev/quota/__init__.py +++ b/socketdev/quota/__init__.py @@ -15,5 +15,5 @@ def get(self) -> dict: if response.status_code == 200: return response.json() log.error(f"Error getting quota: {response.status_code}") - print(response.text) + log.error(response.text) return {} diff --git a/socketdev/report/__init__.py b/socketdev/report/__init__.py index f92a621..c5cc67a 100644 --- a/socketdev/report/__init__.py +++ b/socketdev/report/__init__.py @@ -27,7 +27,7 @@ def list(self, from_time: int = None) -> dict: if response.status_code == 200: return response.json() log.error(f"Error listing reports: {response.status_code}") - print(response.text) + log.error(response.text) return {} def delete(self, report_id: str) -> bool: @@ -36,7 +36,7 @@ def delete(self, report_id: str) -> bool: if response.status_code == 200: return True log.error(f"Error deleting report: {response.status_code}") - print(response.text) + log.error(response.text) return False def view(self, report_id) -> dict: @@ -45,7 +45,7 @@ def view(self, report_id) -> dict: if response.status_code == 200: return response.json() log.error(f"Error viewing report: {response.status_code}") - print(response.text) + log.error(response.text) return {} def supported(self) -> dict: @@ -54,7 +54,7 @@ def supported(self) -> dict: if response.status_code == 200: return response.json() log.error(f"Error getting supported reports: {response.status_code}") - print(response.text) + log.error(response.text) return {} def create(self, files: list) -> dict: @@ -68,5 +68,5 @@ def create(self, files: list) -> dict: if response.status_code == 200: return response.json() log.error(f"Error creating report: {response.status_code}") - print(response.text) + log.error(response.text) return {} diff --git a/socketdev/repos/__init__.py b/socketdev/repos/__init__.py index 18fb71c..c4851c8 100644 --- a/socketdev/repos/__init__.py +++ b/socketdev/repos/__init__.py @@ -108,7 +108,7 @@ def repo(self, org_slug: str, repo_name: str, use_types: bool = False) -> Union[ return result error_message = response.json().get("error", {}).get("message", "Unknown error") - print(f"Failed to get repository: {response.status_code}, message: {error_message}") + log.error(f"Failed to get repository: {response.status_code}, message: {error_message}") if use_types: return GetRepoResponse.from_dict( {"success": False, "status": response.status_code, "message": error_message} diff --git a/socketdev/repositories/__init__.py b/socketdev/repositories/__init__.py index 4390313..19aaa5f 100644 --- a/socketdev/repositories/__init__.py +++ b/socketdev/repositories/__init__.py @@ -27,5 +27,5 @@ def list(self, use_types: bool = False) -> Union[dict, list[Repo]]: return result log.error(f"Error listing repositories: {response.status_code}") - print(response.text) + log.error(response.text) return [] diff --git a/socketdev/sbom/__init__.py b/socketdev/sbom/__init__.py index 67aa15e..42cf34e 100644 --- a/socketdev/sbom/__init__.py +++ b/socketdev/sbom/__init__.py @@ -32,7 +32,7 @@ def view(self, report_id: str) -> dict[str, dict]: sbom_dict[val["id"]] = val else: log.error(f"Error viewing SBOM: {response.status_code}") - print(response.text) + log.error(response.text) sbom_dict = {} return sbom_dict @@ -48,7 +48,7 @@ def create_packages_dict(self, sbom: dict[str, dict]) -> dict[str, Package]: item = sbom[package_id] package = Package(**item) if package.id in packages: - print(f"Duplicate package_id: {package_id}") + log.error(f"Duplicate package_id: {package_id}") else: packages[package.id] = package for top_id in package.topLevelAncestors: diff --git a/socketdev/settings/__init__.py b/socketdev/settings/__init__.py index 416454c..a9cbe8e 100644 --- a/socketdev/settings/__init__.py +++ b/socketdev/settings/__init__.py @@ -91,7 +91,7 @@ def get( return rules error_message = response.json().get("error", {}).get("message", "Unknown error") - print(f"Failed to get security policy: {response.status_code}, message: {error_message}") + log.error(f"Failed to get security policy: {response.status_code}, message: {error_message}") if use_types: return OrgSecurityPolicyResponse.from_dict( {"securityPolicyRules": {}, "success": False, "status": response.status_code, "message": error_message} From 9ad87c5334e33024be615ab0e28ef51b6cd039ac Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Mon, 9 Jun 2025 15:13:07 -0700 Subject: [PATCH 3/3] Version bump --- socketdev/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/socketdev/version.py b/socketdev/version.py index 4eabd0b..e835b9d 100644 --- a/socketdev/version.py +++ b/socketdev/version.py @@ -1 +1 @@ -__version__ = "2.1.2" +__version__ = "2.1.3"