Skip to content

Commit ce625aa

Browse files
committed
feat: have more input validation
1 parent b1ffdac commit ce625aa

15 files changed

Lines changed: 272 additions & 31 deletions

ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* Update dependencies to fix CVE-2026-21441 in urllib3.
1111
* Drop support for Python 3.9 and 3.10.
1212
* Dependency updates.
13+
* Have more input validation.
1314

1415
## V1.10.1
1516

sw360/attachments.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -------------------------------------------------------------------------------
2-
# Copyright (c) 2019-2023 Siemens
2+
# Copyright (c) 2019-2026 Siemens
33
# Copyright (c) 2022 BMW CarIT GmbH
44
# All Rights Reserved.
55
# Authors: thomas.graf@siemens.com, gernot.hillier@siemens.com
@@ -34,6 +34,8 @@ def get_attachment_infos_by_hash(self, hashvalue: str) -> Optional[Dict[str, Any
3434
3535
API endpoint: GET /attachments?sha1=
3636
"""
37+
if not hashvalue:
38+
raise SW360Error(message="No hash value provided!")
3739

3840
resp = self.api_get(
3941
self.url + "resource/api/attachments?sha1=" + hashvalue
@@ -47,6 +49,15 @@ def get_attachment_infos_for_resource(self, resource_type: str, resource_id: str
4749
specific get_attachment_infos_for_{release,component,project} functions.
4850
"""
4951

52+
if not resource_id:
53+
raise SW360Error(message="No resource id provided!")
54+
55+
if not resource_type:
56+
raise SW360Error(message="No resource type provided!")
57+
58+
if resource_type not in ("releases", "components", "projects"):
59+
raise SW360Error(message="Invalid resource type!")
60+
5061
resp = self.api_get(
5162
self.url + "resource/api/"
5263
+ resource_type
@@ -65,6 +76,8 @@ def get_attachment_infos_for_release(self, release_id: str) -> List[Dict[str, An
6576
6677
:param release_id: id of the release from which to list attachments
6778
"""
79+
if not release_id:
80+
raise SW360Error(message="No release id provided!")
6881

6982
resp = self.get_attachment_infos_for_resource("releases", release_id)
7083
return resp
@@ -74,6 +87,8 @@ def get_attachment_infos_for_component(self, component_id: str) -> List[Dict[str
7487
7588
:param component_id: id of the component from which to list attachments
7689
"""
90+
if not component_id:
91+
raise SW360Error(message="No component id provided!")
7792

7893
resp = self.get_attachment_infos_for_resource("components", component_id)
7994
return resp
@@ -83,6 +98,8 @@ def get_attachment_infos_for_project(self, project_id: str) -> List[Dict[str, An
8398
8499
:param project_id: id of the project from which to list attachments
85100
"""
101+
if not project_id:
102+
raise SW360Error(message="No project id provided!")
86103

87104
resp = self.get_attachment_infos_for_resource("projects", project_id)
88105
return resp
@@ -92,6 +109,9 @@ def get_attachment_by_url(self, url: str) -> Optional[Dict[str, Any]]:
92109
93110
:param url: the full url of the attachment to be requested
94111
"""
112+
if not url:
113+
raise SW360Error(message="No url provided!")
114+
95115
resp = self.api_get(url)
96116
return resp
97117

@@ -102,6 +122,8 @@ def get_attachment(self, attachment_id: str) -> Optional[Dict[str, Any]]:
102122
103123
:param attachment_id: id of the attachment
104124
"""
125+
if not attachment_id:
126+
raise SW360Error(message="No attachment id provided!")
105127

106128
resp = self.api_get(self.url + "resource/api/attachments/" + attachment_id)
107129
return resp
@@ -111,6 +133,8 @@ def download_release_attachment(self, filename: str, release_id: str, attachment
111133
112134
API endpoint: GET /attachments
113135
"""
136+
if not release_id:
137+
raise SW360Error(message="No release id provided!")
114138

115139
self.download_resource_attachment(
116140
filename, "releases", release_id, attachment_id
@@ -121,6 +145,8 @@ def download_project_attachment(self, filename: str, project_id: str, attachment
121145
122146
API endpoint: GET /attachments
123147
"""
148+
if not project_id:
149+
raise SW360Error(message="No project id provided!")
124150

125151
self.download_resource_attachment(
126152
filename, "projects", project_id, attachment_id
@@ -131,6 +157,8 @@ def download_component_attachment(self, filename: str, component_id: str, attach
131157
132158
API endpoint: GET /attachments
133159
"""
160+
if not component_id:
161+
raise SW360Error(message="No component id provided!")
134162

135163
self.download_resource_attachment(
136164
filename, "components", component_id, attachment_id
@@ -142,6 +170,8 @@ def download_resource_attachment(self, filename: str, resource_type: str, resour
142170
143171
API endpoint: GET /attachments
144172
"""
173+
if not filename:
174+
raise SW360Error(message="No filename provided!")
145175

146176
if not resource_id:
147177
raise SW360Error(message="No resource id provided!")
@@ -165,6 +195,11 @@ def download_attachment(self, filename: str, download_url: str) -> None:
165195
166196
API endpoint: GET /attachments
167197
"""
198+
if not filename:
199+
raise SW360Error(message="No filename provided!")
200+
201+
if not download_url:
202+
raise SW360Error(message="No download url provided!")
168203

169204
hdr = self.api_headers.copy()
170205
hdr["Accept"] = "application/*"
@@ -238,6 +273,8 @@ def upload_release_attachment(self, release_id: str, upload_file: str, upload_ty
238273
239274
API endpoint: POST /attachments
240275
"""
276+
if not release_id:
277+
raise SW360Error(message="No release id provided!")
241278

242279
self._upload_resource_attachment(
243280
"releases", release_id, upload_file,
@@ -259,6 +296,8 @@ def upload_component_attachment(self, component_id: str, upload_file: str, uploa
259296
260297
API endpoint: POST /attachments
261298
"""
299+
if not component_id:
300+
raise SW360Error(message="No component id provided!")
262301

263302
self._upload_resource_attachment(
264303
"components", component_id, upload_file,
@@ -280,6 +319,8 @@ def upload_project_attachment(self, project_id: str, upload_file: str, upload_ty
280319
281320
API endpoint: POST /attachments
282321
"""
322+
if not project_id:
323+
raise SW360Error(message="No project id provided!")
283324

284325
self._upload_resource_attachment(
285326
"projects", project_id, upload_file,

sw360/clearing.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -------------------------------------------------------------------------------
2-
# Copyright (c) 2019-2023 Siemens
2+
# Copyright (c) 2019-2026 Siemens
33
# Copyright (c) 2022 BMW CarIT GmbH
44
# All Rights Reserved.
55
# Authors: thomas.graf@siemens.com, gernot.hillier@siemens.com
@@ -11,6 +11,8 @@
1111

1212
from typing import Any, Dict, Optional
1313

14+
from sw360.sw360error import SW360Error
15+
1416
from .base import BaseMixin
1517

1618

@@ -26,6 +28,8 @@ def get_clearing_request(self, request_id: str) -> Optional[Dict[str, Any]]:
2628
:rtype: JSON clearing request object
2729
:raises SW360Error: if there is a negative HTTP response
2830
"""
31+
if not request_id:
32+
raise SW360Error(message="No request id provided!")
2933

3034
resp = self.api_get(self.url + "resource/api/clearingrequest/" + request_id)
3135
return resp
@@ -41,6 +45,8 @@ def get_clearing_request_for_project(self, project_id: str) -> Optional[Dict[str
4145
:rtype: JSON clearing request object
4246
:raises SW360Error: if there is a negative HTTP response
4347
"""
48+
if not project_id:
49+
raise SW360Error(message="No project id provided!")
4450

4551
resp = self.api_get(self.url + "resource/api/clearingrequest/project/" + project_id)
4652
return resp

sw360/components.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -------------------------------------------------------------------------------
2-
# Copyright (c) 2019-2025 Siemens
2+
# Copyright (c) 2019-2026 Siemens
33
# Copyright (c) 2022 BMW CarIT GmbH
44
# All Rights Reserved.
55
# Authors: thomas.graf@siemens.com, gernot.hillier@siemens.com
@@ -93,6 +93,8 @@ def get_components_by_type(
9393
:rtype: list of JSON component objects
9494
:raises SW360Error: if there is a negative HTTP response
9595
"""
96+
if not component_type:
97+
raise SW360Error(message="No component type provided!")
9698

9799
fullbase_url = self.url + "resource/api/components"
98100
params = {"type": component_type}
@@ -123,6 +125,8 @@ def get_component(self, component_id: str) -> Optional[Dict[str, Any]]:
123125
:rtype: JSON component object
124126
:raises SW360Error: if there is a negative HTTP response
125127
"""
128+
if not component_id:
129+
raise SW360Error(message="No component id provided!")
126130

127131
resp = self.api_get(self.url + "resource/api/components/" + component_id)
128132
return resp
@@ -138,6 +142,8 @@ def get_component_by_url(self, component_url: str) -> Optional[Dict[str, Any]]:
138142
:rtype: JSON component object
139143
:raises SW360Error: if there is a negative HTTP response
140144
"""
145+
if not component_url:
146+
raise SW360Error(message="No component url provided!")
141147

142148
resp = self.api_get(component_url)
143149
return resp
@@ -164,6 +170,8 @@ def get_component_by_name(
164170
:rtype: list of JSON component objects
165171
:raises SW360Error: if there is a negative HTTP response
166172
"""
173+
if not component_name:
174+
raise SW360Error(message="No component name provided!")
167175

168176
fullbase_url = self.url + "resource/api/components"
169177
params = {"name": component_name}
@@ -193,6 +201,11 @@ def get_components_by_external_id(self, ext_id_name: str, ext_id_value: str = ""
193201
:rtype: list of JSON component objects
194202
:raises SW360Error: if there is a negative HTTP response
195203
"""
204+
if not ext_id_name:
205+
raise SW360Error(message="No external id name provided!")
206+
207+
if not ext_id_value:
208+
raise SW360Error(message="No external id value provided!")
196209

197210
resp = self.api_get(
198211
self.url
@@ -284,6 +297,15 @@ def update_component_external_id(self, ext_id_name: str, ext_id_value: str,
284297
:rtype: string
285298
:raises SW360Error: if there is a negative HTTP response
286299
"""
300+
if not component_id:
301+
raise SW360Error(message="No component id provided!")
302+
303+
if not ext_id_name:
304+
raise SW360Error(message="No external id name provided!")
305+
306+
if not ext_id_value:
307+
raise SW360Error(message="No external id value provided!")
308+
287309
complete_data = self.get_component(component_id)
288310
if not complete_data:
289311
return None
@@ -329,6 +351,8 @@ def get_users_of_component(self, component_id: str) -> Optional[Dict[str, Any]]:
329351
:rtype: JSON objects
330352
:raises SW360Error: if there is a negative HTTP response
331353
"""
354+
if not component_id:
355+
raise SW360Error(message="No component id provided!")
332356

333357
resp = self.api_get(self.url + "resource/api/components/usedBy/" + component_id)
334358
return resp

sw360/license.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -------------------------------------------------------------------------------
2-
# Copyright (c) 2019-2025 Siemens
2+
# Copyright (c) 2019-2026 Siemens
33
# Copyright (c) 2022 BMW CarIT GmbH
44
# All Rights Reserved.
55
# Authors: thomas.graf@siemens.com, gernot.hillier@siemens.com
@@ -42,6 +42,14 @@ def create_new_license(
4242
:rtype: JSON SW360 result object
4343
:raises SW360Error: if there is a negative HTTP response
4444
"""
45+
if not shortName:
46+
raise SW360Error(message="No short name provided!")
47+
48+
if not fullName:
49+
raise SW360Error(message="No full name provided!")
50+
51+
if not text:
52+
raise SW360Error(message="No license text provided!")
4553

4654
url = self.url + "resource/api/licenses"
4755

@@ -94,6 +102,12 @@ def download_license_info(
94102
:type project_id: string
95103
:type filename: string
96104
"""
105+
if not project_id:
106+
raise SW360Error(message="No project id provided!")
107+
108+
if not filename:
109+
raise SW360Error(message="No filename provided!")
110+
97111
hdr = self.api_headers.copy()
98112
hdr["Accept"] = "application/*"
99113
url = (
@@ -135,6 +149,8 @@ def get_license(self, license_id: str) -> Optional[Dict[str, Any]]:
135149
:rtype: JSON license object
136150
:raises SW360Error: if there is a negative HTTP response
137151
"""
152+
if not license_id:
153+
raise SW360Error(message="No license id provided!")
138154

139155
resp = self.api_get(self.url + "resource/api/licenses/" + license_id)
140156
return resp

sw360/moderationrequests.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -------------------------------------------------------------------------------
2-
# Copyright (c) 2024-2025 Siemens
2+
# Copyright (c) 2024-2026 Siemens
33
# All Rights Reserved.
44
# Authors: thomas.graf@siemens.com
55
#
@@ -9,6 +9,8 @@
99

1010
from typing import Any, Dict, Optional
1111

12+
from sw360.sw360error import SW360Error
13+
1214
from .base import BaseMixin
1315

1416

@@ -63,6 +65,8 @@ def get_moderation_requests_by_state(self, state: str, all_details: bool = False
6365
:rtype: list of JSON moderation requests objects
6466
:raises SW360Error: if there is a negative HTTP response
6567
"""
68+
if not state:
69+
raise SW360Error(message="No state provided!")
6670

6771
fullbase_url = self.url + "resource/api/moderationrequest/byState"
6872
params = {"state": state}
@@ -92,6 +96,8 @@ def get_moderation_request(self, mr_id: str) -> Optional[Dict[str, Any]]:
9296
:rtype: JSON moderation request object
9397
:raises SW360Error: if there is a negative HTTP response
9498
"""
99+
if not mr_id:
100+
raise SW360Error(message="No moderation request id provided!")
95101

96102
resp = self.api_get(self.url + "resource/api/moderationrequest/" + mr_id)
97103
return resp

0 commit comments

Comments
 (0)